jQuery `.is («: visible »)` ne fonctionne pas dans Chrome

207
if ($("#makespan").is(":visible") == true) { 
    var make = $("#make").val(); 
}
else {
    var make = $("#othermake").val(); 
}

Make:<span id=makespan><select id=make></select><span id=othermakebutton class=txtbutton>Other?</span></span><span id=othermakespan style="display: none;"><input type=text name=othermake id=othermake>&nbsp;-&nbsp;<span id=othermakecancel class=txtbutton>Cancel</span></span>

Le code ci-dessus fonctionne sans problème dans Firefox, mais ne semble pas fonctionner dans Chrome. Dans Chrome, il s'affiche .is(":visible") = falsemême lorsqu'il l'est true.

J'utilise la version jQuery suivante: jquery-1.4.3.min.js

Lien jsFiddle: http://jsfiddle.net/WJU2r/4/

Saad Bashir
la source
1
de préférence dans un lien jsfiddle? et éventuellement le vérifier avec jquery.latest.
xaxxon
le makaspan peut être affiché: aucun, ou visibilité: caché?
Artur Keyan
et peut-être mettre à jour temporairement la dernière version de jQuery, juste pour exclure un bogue jQuery?
Strelok
1
Voir aussi: bugs.jquery.com/ticket/13132 Il semble que cela sera corrigé dans la version 1.12 / 2.2! -
Glen Little
1
il n'est pas nécessaire d'ajouter "== true" dans l'instruction if: if ($ ("# makespan"). is (": visible")) est suffisant
marcdahan

Réponses:

273

Il semble que le :visiblesélecteur de jQuery ne fonctionne pas pour certains éléments en ligne dans Chrome. La solution consiste à ajouter un style d'affichage, comme "block"ou"inline-block" pour le faire fonctionner.

Notez également que jQuery a une définition quelque peu différente de ce qui est visible que de nombreux développeurs:

Les éléments sont considérés comme visibles s'ils consomment de l'espace dans le document.
Les éléments visibles ont une largeur ou une hauteur supérieure à zéro.

En d'autres termes, un élément doit avoir une largeur et une hauteur non nulles pour consommer de l'espace et être visible.

Les éléments avec visibility: hiddenou opacity: 0sont considérés comme visibles, car ils consomment toujours de l'espace dans la mise en page.

D'un autre côté, même si son visibilityest défini sur hiddenou l'opacité est nulle, c'est toujours :visibleà jQuery car il consomme de l'espace, ce qui peut être déroutant lorsque le CSS dit explicitement que sa visibilité est masquée.

Les éléments qui ne figurent pas dans un document sont considérés comme masqués; jQuery n'a aucun moyen de savoir s'ils seront visibles lorsqu'ils seront ajoutés à un document car cela dépend des styles applicables.

Tous les éléments d'option sont considérés comme masqués, quel que soit leur état sélectionné.

Lors des animations qui masquent un élément, l'élément est considéré comme visible jusqu'à la fin de l'animation. Lors des animations pour montrer un élément, l'élément est considéré comme visible au début de l'animation.

Le moyen le plus simple de le regarder est que si vous pouvez voir l'élément à l'écran, même si vous ne pouvez pas voir son contenu, il est transparent, etc., il est visible, c'est-à-dire qu'il prend de la place.

J'ai un peu nettoyé votre balisage et ajouté un style d'affichage ( c'est-à-dire en définissant l'affichage des éléments sur "bloquer", etc. ), et cela fonctionne pour moi:

VIOLON

Référence officielle de l'API pour :visible


Depuis jQuery 3, la définition de :visiblea légèrement changé

jQuery 3 modifie légèrement la signification de :visible(et donc de :hidden).
À partir de cette version, les éléments seront pris en compte :visibles'ils ont des boîtes de mise en page, y compris celles de largeur et / ou de hauteur zéro. Par exemple, les bréléments et les éléments en ligne sans contenu seront sélectionnés par le :visiblesélecteur.

adeneo
la source
J'ai également essayé de coller les composants individuels dans jsFiddle et cela a bien fonctionné. Je vais essayer de répliquer l'erreur dans jsFiddle puis poster le lien. Probablement quelque chose d'autre dans le code est à l'origine de cette erreur
Saad Bashir
J'ai reproduit le problème sur le lien suivant: jsfiddle.net/WJU2r/3
Saad Bashir
3
Merci beaucoup qui a fonctionné! Je ne sais pas pourquoi mais en définissant #makespan {display: block; } l'a fait fonctionner.
Saad Bashir
Le commentaire de l'affiche originale contient la solution réelle, IE, qui rend l'affichage de vos étendues: bloc. Idiot que les travées soient invisibles par défaut en chrome, mais peu importe.
Jeff Davis
Cela suffit si vous ajoutez un & nbsp; à l'élément, car si un élément n'a pas de contenu, il est invisible dans Chrome
Briganti
67

Je ne sais pas pourquoi votre code ne fonctionne pas sur Chrome, mais je vous suggère d'utiliser certaines solutions:

$el.is(':visible') === $el.is(':not(:hidden)');

ou

$el.is(':visible') === !$el.is(':hidden');  

Si vous êtes certain que jQuery vous donne de mauvais résultats dans Chrome, vous pouvez simplement vous fier à la vérification des règles CSS:

if($el.css('display') !== 'none') {
    // i'm visible
}

De plus, vous voudrez peut-être utiliser la dernière jQuery, car il pourrait y avoir des bogues d'une ancienne version corrigés.

gion_13
la source
2
J'ai reproduit le problème sur le lien suivant: jsfiddle.net/WJU2r/3
Saad Bashir
Cette question détaille la différence entre :hiddenet :not(:visible). stackoverflow.com/questions/17425543/…
Mark Schultheiss
la fonction est (': visible') ou .is (': caché') ou est (': pas (: caché)') est très mauvaise pour les performances
Diogo Cid
9

Il y a un cas étrange où si l'élément est défini sur display: inline jQuery, la vérification de la visibilité échoue.

Exemple:

CSS

#myspan {display: inline;}

jQuery

$('#myspan').show(); // Our element is `inline` instead of `block`
$('#myspan').is(":visible"); // This is false

Pour le corriger, vous pouvez masquer l'élément dans jQuery et que show/hideou toggle()devrait fonctionner correctement.

$('#myspan').hide()
$('#otherElement').on('click', function() {
    $('#myspan').toggle();
});
Alex Rashkov
la source
J'ai ce problème avec PhantomJS mais sur Chrome 47.0.2526 cela semble fonctionner. voir: jsfiddle.net/k4b925gn/2
ekkis
8

Je suppose que cela a quelque chose à voir avec une bizarrerie dans notre HTML parce que d'autres endroits sur la même page fonctionnent très bien.

La seule façon dont j'ai pu résoudre ce problème était de faire:

if($('#element_id').css('display') == 'none')
{
   // Take element is hidden action
}
else
{
   // Take element is visible action
}
Chris Dutrow
la source
7

Si vous lisez les documents jquery, il y a de nombreuses raisons pour que quelque chose ne soit pas considéré comme visible / caché:

Ils ont une valeur d'affichage CSS nulle.

Ce sont des éléments de formulaire de type = "caché".

Leur largeur et leur hauteur sont explicitement définies sur 0.

Un élément ancêtre est masqué, donc l'élément n'est pas affiché sur la page.

http://api.jquery.com/visible-selector/

Voici un petit exemple jsfiddle avec un élément visible et un élément caché:

http://jsfiddle.net/tNjLb/

xaxxon
la source
J'ai reproduit le problème sur le lien suivant: jsfiddle.net/WJU2r/3
Saad Bashir
7

Internet Explorer, Chrome, Firefox ...

Fonction Cross Browser "isVisible ()"

//check if exist and is visible
function isVisible(id) {
    var element = $('#' + id);
    if (element.length > 0 && element.css('visibility') !== 'hidden' && element.css('display') !== 'none') {
        return true;
    } else {
        return false;
    }
}

Exemple complet:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script src="http://code.jquery.com/jquery-1.10.2.js"></script>
        <script type="text/javascript">
            //check if exist and is visible
            function isVisible(id) {
                var element = $('#' + id);
                if (element.length > 0 && element.css('visibility') !== 'hidden' && element.css('display') !== 'none') {
                    return true;
                } else {
                    return false;
                }
            }

            function check(id) {
                if (isVisible(id)) {
                    alert('visible: true');
                } else {
                    alert('visible: false');
                }
                return false;
            }
        </script>

        <style type="text/css">
            #fullname{
                display: none;
            }
            #vote{
                visibility: hidden;
            }
        </style>
        <title>Full example: isVisible function</title>
    </head>
    <body>
        <div id="hello-world">
            Hello World!
        </div>
        <div id="fullname">
            Fernando Mosquera Catarecha
        </div>
        <div id="vote">
            rate it!
        </div>
        <a href="#" onclick="check('hello-world');">Check isVisible('hello-world')</a><br /><br />
        <a href="#" onclick="check('fullname');">Check isVisible('fullname')</a><br /><br />
        <a href="#" onclick="check('vote');">Check isVisible('vote')</a>
    </body>
</html>

Cordialement,

Fernando

Fernando
la source
3

Généralement, je vis cette situation lorsque le parent de mon objet est caché. par exemple lorsque le html est comme ceci:

    <div class="div-parent" style="display:none">
        <div class="div-child" style="display:block">
        </div>
    </div>

si vous demandez si l'enfant est visible comme:

    $(".div-child").is(":visible");

il renverra false car son parent n'est pas visible, de sorte que div ne sera pas visible également.

cenk ebret
la source
voir ma solution plus bas ... dans votre enfant, définissez l'affichage sur 'hériter', qui copiera l'état de son élément parent, donc si c'est caché, elemtn.is (": caché") fonctionnera
Patrick
3

Une solution multi-navigateur / version pour déterminer si un élément est visible, consiste à ajouter / supprimer une classe CSS à l'élément lors de l'affichage / masquage. L'état par défaut (visible) de l'élément pourrait être par exemple comme ceci:

<span id="span1" class="visible">Span text</span>

Ensuite, sur masquer, supprimez la classe:

$("#span1").removeClass("visible").hide();

À l'affiche, ajoutez-le à nouveau:

$("#span1").addClass("visible").show();

Ensuite, pour déterminer si l'élément est visible, utilisez ceci:

if ($("#span1").hasClass("visible")) { // do something }

Cela résout également les implications en termes de performances, qui peuvent survenir lors d'une utilisation intensive du sélecteur ": visible", pointées dans la documentation de jQuery:

L'utilisation intensive de ce sélecteur peut avoir des implications sur les performances, car il peut forcer le navigateur à restituer la page avant de pouvoir déterminer la visibilité. Le suivi de la visibilité des éléments via d'autres méthodes, en utilisant une classe par exemple, peut fournir de meilleures performances.

Documentation officielle de l'API jQuery pour le sélecteur ": visible"

Alex
la source
1

J'ai ajouté le style suivant sur le parent et .is (": visible") a fonctionné.

affichage: bloc en ligne;

Horatiu
la source
0

Si un élément est enfant d'un élément masqué, (": visible") renvoie true, ce qui est incorrect.

Je viens de corriger cela en ajoutant "display: inherit" à l'élément enfant. Cela le corrigera pour moi:

<div class="parent">
   <div class="child">
   </div>
<div>

et le CSS:

.parent{
   display: hidden;
}
.child{
   display: inherit;
}

Désormais, l'élément peut être activé et désactivé efficacement en modifiant la visibilité du parent, et $ (element) .is (": visible") rendra la visibilité de l'élément parent

patrick
la source
0

C'est le morceau de code de jquery.js qui s'exécute lorsque is (": visible") est appelé:

if (jQuery.expr && jQuery.expr.filters){

    jQuery.expr.filters.hidden = function( elem ) {
        return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
    };

    jQuery.expr.filters.visible = function( elem ) {
        return !jQuery.expr.filters.hidden( elem );
    };
}

Comme vous pouvez le voir, il utilise plus que la propriété d'affichage CSS. Cela dépend également de la largeur et de la hauteur du contenu de l'élément. Par conséquent, assurez-vous que l'élément a une certaine largeur et hauteur. Et pour ce faire, vous devrez peut-être définir la propriété d'affichage sur "inline-block"ou "block"

hkulur
la source
0

J'ai besoin d'utiliser la visibilité: caché au moment de l' affichage: aucun car la visibilité prend des événements, tandis que l' affichage ne le fait pas.

Moi aussi .attr('visibility') === "visible"

mitjajez
la source