jQuery `.is (“: visible ”)` não funciona no 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>

O código acima funciona sem problemas no Firefox, mas parece não funcionar no Chrome. No Chrome, é exibido .is(":visible") = falsemesmo quando está true.

Estou usando a seguinte versão do jQuery: jquery-1.4.3.min.js

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

Saad Bashir
fonte
1
de preferência em um link jsfiddle? e, possivelmente, verifique-o com jquery.latest.
Xaxxon
o makaspan pode ser exibido: nenhum ou visibilidade: oculto?
Artur Keyan
e talvez atualize temporariamente para a versão mais recente do jQuery, apenas para descartar um bug do jQuery?
Strelok
1
Veja também: bugs.jquery.com/ticket/13132 Parece que será corrigido na versão 1.12 / 2.2! -
Glen Little
1
Não é necessário adicionar "== true" no caso da escrita declaração: if ($ ( "# makespan") é ( ": visível").) é enougth
marcdahan

Respostas:

273

Parece que o :visibleseletor do jQuery não funciona para alguns elementos embutidos no Chrome. A solução é adicionar um estilo de exibição, como "block"ou "inline-block"fazê-lo funcionar.

Observe também que o jQuery tem uma definição um pouco diferente do que é visível do que muitos desenvolvedores:

Os elementos são considerados visíveis se consumirem espaço no documento.
Os elementos visíveis têm uma largura ou altura maior que zero.

Em outras palavras, um elemento deve ter largura e altura diferentes de zero para consumir espaço e ser visível.

Elementos com visibility: hiddenou opacity: 0são considerados visíveis, pois ainda consomem espaço no layout.

Por outro lado, mesmo que visibilityesteja definido como hiddenou a opacidade seja zero, ainda é o :visiblejQuery, pois consome espaço, o que pode ser confuso quando o CSS diz explicitamente que sua visibilidade está oculta.

Elementos que não estão em um documento são considerados ocultos; O jQuery não tem como saber se eles serão visíveis quando anexados a um documento, pois depende dos estilos aplicáveis.

Todos os elementos de opção são considerados ocultos, independentemente do estado selecionado.

Durante as animações que ocultam um elemento, o elemento é considerado visível até o final da animação. Durante as animações para mostrar um elemento, o elemento é considerado visível no início da animação.

A maneira mais fácil de ver isso é que, se você pode ver o elemento na tela, mesmo que não possa ver seu conteúdo, é transparente, etc., é visível, ou seja, ocupa espaço.

Limpei um pouco a sua marcação e adicionei um estilo de exibição ( ou seja, definir os elementos para "bloquear" etc ), e isso funciona para mim:

FIDDLE

Referência oficial da API para :visible


No jQuery 3, a definição de :visiblemudou ligeiramente

O jQuery 3 modifica levemente o significado de :visible(e, portanto, de :hidden).
A partir desta versão, os elementos serão considerados :visiblese tiverem caixas de layout, incluindo as de largura e / ou altura zero. Por exemplo, brelementos e elementos embutidos sem conteúdo serão selecionados pelo :visibleseletor.

adeneo
fonte
Também tentei colar os componentes individuais no jsFiddle e funcionou bem. Vou tentar replicar o erro no jsFiddle e depois postar o link. Provavelmente alguma coisa no código está causando esse erro
Saad Bashir
Eu repliquei o problema no seguinte link: jsfiddle.net/WJU2r/3
Saad Bashir
3
Muito obrigado que funcionou! Não sei por que, mas definir #makespan {display: block; } fez funcionar.
Saad Bashir
O comentário do pôster original contém a solução real, IE, exibindo seus intervalos de tempo: block. Bobo que vãos são invisíveis por padrão no chrome, mas, tanto faz.
Jeff Davis
É suficiente se você adicionar um & nbsp; ao elemento, porque se um elemento não tem conteúdo, então é invisível no Chrome
Briganti
67

Não sei por que seu código não funciona no chrome, mas sugiro que você use algumas soluções alternativas:

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

ou

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

Se você tem certeza de que o jQuery fornece alguns resultados ruins no chrome, basta confiar na verificação da regra css:

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

Além disso, convém usar o jQuery mais recente, pois ele pode ter erros da versão anterior corrigidos.

gion_13
fonte
2
Eu replicado o problema no seguinte link: jsfiddle.net/WJU2r/3
Saad Bashir
Esta pergunta detalha qual é a diferença entre :hiddene :not(:visible). stackoverflow.com/questions/17425543/…
Mark Schultheiss
a função é (': visible') ou .is (': hidden') ou is (': not (: hidden)') é muito ruim para o desempenho
Diogo Cid
9

Há um caso estranho em que, se o elemento estiver definido como display: inlinejQuery, a verificação de visibilidade falhará.

Exemplo:

CSS

#myspan {display: inline;}

jQuery

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

Para corrigi-lo, você pode ocultar o elemento no jQuery e que show/hideou toggle()deve funcionar bem.

$('#myspan').hide()
$('#otherElement').on('click', function() {
    $('#myspan').toggle();
});
Alex Rashkov
fonte
Estou tendo esse problema com o PhantomJS, mas no Chrome 47.0.2526 isso parece funcionar. Veja: jsfiddle.net/k4b925gn/2
ekkis
8

Suponho que tenha algo a ver com uma peculiaridade em nosso HTML, porque outros lugares na mesma página funcionam muito bem.

A única maneira de resolver esse problema foi:

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

Se você ler os documentos do jquery, existem várias razões para que algo não seja considerado visível / oculto:

Eles têm um valor de exibição CSS nenhum.

Eles são elementos de formulário com o tipo = "oculto".

Sua largura e altura são explicitamente definidas como 0.

Um elemento ancestral está oculto, portanto, o elemento não é mostrado na página.

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

Aqui está um pequeno exemplo do jsfiddle com um elemento visível e um elemento oculto:

http://jsfiddle.net/tNjLb/

xaxxon
fonte
Eu replicado o problema no seguinte link: jsfiddle.net/WJU2r/3
Saad Bashir
7

Internet Explorer, Chrome, Firefox ...

Função 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;
    }
}

Exemplo completo:

<!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>

Saudações,

Fernando

Fernando
fonte
3

Geralmente eu vivo essa situação quando o pai do meu objeto está oculto. por exemplo, quando o html é assim:

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

se você perguntar se child é visível como:

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

ele retornará false porque seu pai não é visível, de modo que div também não será visível.

cenk ebret
fonte
veja minha solução mais baixa ... na exibição do conjunto filho como 'herdar', que copiará o estado do item pai, por isso, se estiver oculto elemtn.is (": hidden") funcionará
patrick
3

Uma solução entre navegadores / versões para determinar se um elemento está visível é adicionar / remover uma classe css ao elemento em show / hide. O estado padrão (visível) do elemento pode ser, por exemplo, assim:

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

Em seguida, ocultar, remova a classe:

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

No programa, adicione-o novamente:

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

Em seguida, para determinar se o elemento está visível, use o seguinte:

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

Isso também resolve as implicações de desempenho, que podem ocorrer no uso intenso do seletor ": visible", apontado na documentação do jQuery:

O uso intenso desse seletor pode ter implicações no desempenho, pois pode forçar o navegador a renderizar novamente a página antes de determinar a visibilidade. O rastreamento da visibilidade dos elementos por outros métodos, usando uma classe, por exemplo, pode fornecer um melhor desempenho.

Documentação oficial da API jQuery para o seletor ": visible"

Alex
fonte
1

Eu adicionei o próximo estilo no pai e .is (": visible") funcionou.

display: bloco embutido;

Horatiu
fonte
0

Se um item é filho de um item oculto, (": visible") retornará true, o que está incorreto.

Eu apenas corrigi isso adicionando "display: herdar" ao item filho. Isso irá corrigi-lo para mim:

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

e o CSS:

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

Agora o item pode ser ativado e desativado efetivamente alterando a visibilidade do pai, e $ (elemento) .is (": visible") retornará a visibilidade do item pai

patrick
fonte
0

Este é o trecho de código do jquery.js que é executado quando is (": visible") é chamado:

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 );
    };
}

Como você pode ver, ele usa mais do que apenas a propriedade de exibição CSS. Também depende da largura e altura do conteúdo do elemento. Portanto, verifique se o elemento possui alguma largura e altura. E para fazer isso, pode ser necessário definir a propriedade display como "inline-block"ou "block"

hkulur
fonte
0

Eu preciso usar a visibilidade: instinto oculto da exibição: nenhum porque a visibilidade recebe eventos, enquanto a exibição não.

Então eu faço .attr('visibility') === "visible"

mitjajez
fonte