Muchas veces es imprescindible saber si un elemento es o no visible. Con jQuery averiguarlo es bastante fácil, símplemente hay que preguntar si el filtro “visible” está presente (también se puede mirar ‘hidden‘). Sin embargo hay que tener en cuenta un par de cosas, porque puede ser que jQuery no nos esté diciendo lo que queremos saber en realidad.
El problema viene cuando preguntamos por el div X y el padre está oculto, entonces jQuery nos dirá que X no está oculto, pero realmente el usuario no lo estará viendo en la pantalla, por lo que sí estará oculto.
Como siempre, lo mejor son los ejemplos.
Ejemplo 1:
Empecemos por el principio. Si yo tengo el siguiente código HTML:
<div id="DivBlock">Element</div>
Al ejecutar el siguiente código, tendremos dos alerts, el primero diciendo “Visible!” y el segundo “Not Hidden”.
if ($('#DivBlock').is (':visible')) alert ("Visible!");
if (!$('#DivBlock').is (':hidden')) alert ("Not Hidden");
Como veis, hasta aquí todo funciona a la perfección, y podeis ver que preguntar si un objeto está visible o oculto en jquery no tiene demasiada dificultad.
Ejemplo 2:
Ahora bien, veamos que ocurre si el padre está oculto:
<div style="display: none;">
<div id="DivBlock">Element</div>
</div>
Ahora si ejecutamos el siguiente código, en todos los navegadores menos Safari volverán a saltar los alerts, y sin embargo el elemento está oculto!!.
if ($('#DivBlock').is (':visible')) alert ("Visible!");
if (!$('#DivBlock').is (':hidden')) alert ("Not Hidden");
Oh my god! ¡¡jQuery lo está haciendo mal!!
Afortunadamente, la solución a este problema es muy sencilla. Para preguntar si el elemento X es realmente visible, hay que preguntar ¿son X y todos sus padres visibles?, o lo que es lo mismo ¿es X visible y ningún padre de X ha sido ocultado? que en jQuery viene a expresarse de la siguiente manera:
if ($('#DivBlock').is (':visible') && $('#DivBlock').parents (':hidden').length == 0)
alert ("Visible!");
Finalmente, como solución alternativa, se puede crear un selector para preguntarle directamente:
jQuery.extend(
jQuery.expr[ ":" ],
{ reallyvisible : "(jQuery(a).is(':visible') && jQuery(a).parents(':hidden').length == 0)" }
);
Con lo que el código javascript del ejemplo anterior quedaría:
if ($('#DivBlock').is (':reallyvisible')) alert ("Visible!");
Para más información:
English
03/06/2009 at 1:02 pm Permalink
Great job! Your :reallyvisible selector should definitely be in the core!
05/08/2009 at 12:16 pm Permalink
Thanks very much. Help me a lot this evening.
21/08/2009 at 7:27 am Permalink
Awesome man… Very very helpful…
09/09/2009 at 1:01 am Permalink
Thanks for the article – well explained and eay to follow. However, the syntax for your extension to the jQuery selector engine does not work – try this instead:
jQuery.extend(jQuery.expr[":"],{reallyvisible: function(a) { return (jQuery(a).is(‘:visible’) && jQuery(a).parents(‘:hidden’).length == 0) }});
10/11/2009 at 2:11 pm Permalink
if (!$(‘#DivBlock’).is (‘:hidden’)) alert (“Not Hidden”);
not work with IE8.