Como posso verificar se existe um elemento no DOM visível?

421

Como você testa um elemento quanto à existência sem o uso do getElementByIdmétodo?

Eu configurei uma demonstração ao vivo para referência. Também vou imprimir o código aqui:

<!DOCTYPE html>
<html>
<head>
    <script>
    var getRandomID = function (size) {
            var str = "",
                i = 0,
                chars = "0123456789abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ";
            while (i < size) {
                str += chars.substr(Math.floor(Math.random() * 62), 1);
                i++;
            }
            return str;
        },
        isNull = function (element) {
            var randomID = getRandomID(12),
                savedID = (element.id)? element.id : null;
            element.id = randomID;
            var foundElm = document.getElementById(randomID);
            element.removeAttribute('id');
            if (savedID !== null) {
                element.id = savedID;
            }
            return (foundElm) ? false : true;
        };
    window.onload = function () {
        var image = document.getElementById("demo");
        console.log('undefined', (typeof image === 'undefined') ? true : false); // false
        console.log('null', (image === null) ? true : false); // false
        console.log('find-by-id', isNull(image)); // false
        image.parentNode.removeChild(image);
        console.log('undefined', (typeof image === 'undefined') ? true : false); // false ~ should be true?
        console.log('null', (image === null) ? true : false); // false ~ should be true?
        console.log('find-by-id', isNull(image)); // true ~ correct but there must be a better way than this?
    };
    </script>
</head>
<body>
    <div id="demo"></div>
</body>
</html>

Basicamente, o código acima demonstra um elemento sendo armazenado em uma variável e depois removido do DOM. Mesmo que o elemento tenha sido removido do DOM, a variável mantém o elemento como estava quando foi declarado pela primeira vez. Em outras palavras, não é uma referência ao vivo ao elemento em si, mas uma réplica. Como resultado, verificar a existência do valor da variável (o elemento) fornecerá um resultado inesperado.

A isNullfunção é minha tentativa de verificar a existência de elementos a partir de uma variável e funciona, mas eu gostaria de saber se existe uma maneira mais fácil de obter o mesmo resultado.

PS: Também estou interessado em saber por que as variáveis ​​JavaScript se comportam assim, se alguém souber de alguns bons artigos relacionados ao assunto.

Justin Bull
fonte
18
Na verdade, é uma referência ao vivo para o próprio elemento, apenas não está mais em um documento. Essa funcionalidade é necessária porque você pode realmente extrair um elemento do DOM e depois colocá-lo novamente mais tarde com todos os manipuladores de eventos / etc ainda anexados a ele. Por que as variáveis ​​JS agem assim? Porque seria incrivelmente irritante se não o fizessem. O JS exclui apenas variáveis ​​quando você não tiver mais nenhuma referência a elas. A linguagem não tem como saber quais referências você considera importantes e quais considera inúteis.
Mark Kahn
@cwolves Interessante. Eu já encontrei isso muitas vezes antes e nunca pensei muito nisso. De fato, no meu projeto atual, estou salvando elementos em uma matriz antes de fazer alterações neles, apenas no caso de querer reverter as alterações.
Justin Touro
1
A coleta de lixo é executada de tempos em tempos e exclui tudo o que acha que pode. Parece bastante ruim na maioria dos navegadores, mas está melhorando à medida que os desenvolvedores percebem que alguns navegadores funcionam por dias ou semanas entre as reinicializações, portanto, uma boa coleta de lixo é vital para o desempenho do navegador. Os desenvolvedores da Web podem ajudar excluindo propriedades (e, portanto, referências a itens na memória) que não são mais necessárias.
RobG
2
@JustinBull tenha cuidado ao armazenar cópias dos elementos a serem revertidos. Ao armazenar um elemento DOM em uma matriz, uma referência ao elemento DOM é armazenada, não uma cópia; portanto, as alterações feitas no elemento DOM serão refletidas ao fazer referência ao elemento da matriz. Este é o caso de todos os objetos em javascript (variáveis ​​do tipo 'objeto').
Anthony DiSanti

Respostas:

545

Parece que algumas pessoas estão chegando aqui e simplesmente querem saber se existe um elemento (um pouco diferente da pergunta original).

Isso é tão simples quanto usar qualquer método de seleção do navegador e verificar se há um valor verdadeiro (geralmente).

Por exemplo, se meu elemento tiver um idde "find-me", eu poderia simplesmente usar ...

var elementExists = document.getElementById("find-me");

Isso é especificado para retornar uma referência ao elemento ou null. Se você deve ter um valor booleano, basta lançar a !!antes da chamada do método.

Além disso, você pode usar alguns dos muitos outros métodos existentes para encontrar elementos, como (todos vivendo document):

  • querySelector()/querySelectorAll()
  • getElementsByClassName()
  • getElementsByName()

Alguns desses métodos retornam a NodeList, portanto, verifique sua lengthpropriedade, pois a NodeListé um objeto e, portanto, é verdade .


Para determinar realmente se um elemento existe como parte do DOM visível (como a pergunta originalmente feita), o Csuwldcat fornece uma solução melhor do que a sua própria (como essa resposta costumava conter). Ou seja, para usar ocontains() método nos elementos DOM.

Você poderia usá-lo assim ...

document.body.contains(someReferenceToADomElement);
alex
fonte
1
Exatamente o que eu estava procurando! Então, obviamente, lol, por que eu não pensei nisso. Além disso, você conhece algum bom artigo que explique por que as variáveis ​​agem assim?
Justin Touro
3
Ainda mais curto:var elementInDom = function( el ) { while ( el = el.parentNode ) if ( el === document ) return true; return false; }
bennedich 26/02/12
2
@ButtleButkus Leia a pergunta real. Que a solução que você usou não faz sentido como getElementById() irá retornar uma referência a um elemento DOM ou null, portanto, usando typeof(especialmente no RHS) é errado (se não foram definidos, a condição LHS jogaria um ReferenceError).
10283 alex
2
Existe alguma razão para usar isso sobre o que foi postado abaixo: document.body.contains()qual parece ter um suporte muito bom ao navegador?
esmaga
1
@Jonz Removido o velho parte resposta, não se esqueça de ir e votar até csuwldcat
alex
310

Use getElementById()se estiver disponível.

Além disso, aqui está uma maneira fácil de fazer isso com o jQuery:

if ($('#elementId').length > 0) {
  // Exists.
}

E se você não pode usar bibliotecas de terceiros, use o JavaScript básico:

var element =  document.getElementById('elementId');
if (typeof(element) != 'undefined' && element != null)
{
  // Exists.
}
Kon
fonte
2
Para o projeto em que estou trabalhando, não consigo usar uma biblioteca. Apenas bom código de moda. Estou ciente desse método jQuery, mas ele não funciona em elementos não empacotados no contêiner jQuery. Por exemplo, $('#elementId')[0].lengthnão produziria o mesmo resultado.
Justin Touro
8
Existe alguma boa razão para uma declaração if tão complicada no segundo exemplo de código? Por que não simplesmente if (element) {}? Quando o elemento é indefinido ou nulo, essa expressão é falsa. Se elemento é um elemento DOM, a expressão é verdadeira.
Kayahr
2
@kayahr É muito complicado. getElementById()é especificado para retornar nullse não encontrar o elemento, portanto, basta verificar um valor retornado de verdade .
6283 alex
5
Eu acho que isso é apenas senso comum.
23413 Kon Kon
8
getElementByIdnunca deve retornar undefined. De qualquer forma, o element != nullcheque pegaria isso.
191

Usando a API do Node.contains DOM , você pode verificar a presença de qualquer elemento na página (atualmente no DOM) facilmente:

document.body.contains(YOUR_ELEMENT_HERE);

NOTA : O documentobjeto no Internet Explorer não possui um contains()método - para garantir a compatibilidade entre navegadores, use-o document.body.contains().

csuwldcat
fonte
4
Esta parece ser a resposta definitiva para esse problema ... e seu apoio, se se acredita que MDN é muito bom.
esmaga
2
Esta é a melhor resposta. Observe que apenas a verificação document.contains()deve ser suficiente.
alex
@csuwldcat Funcionou para mim, pelo menos no Chrome com document.contains(document.documentElement). documenttem Nodena sua cadeia de protótipos, tanto quanto eu posso dizer ( document-> HTMLDocument-> Document-> Node)
alex
4
Esta é realmente a melhor resposta: - é um padrão da web - é muito bem suportado (surpreendentemente, ele não aparece no Firefox até a versão 9, acho que porque era uma função não padronizada inventada no IE que não era padronizado até mais tarde) - deve ser o mais rápido porque usa uma única chamada para uma API nativa
Jon z
2
@LeeSaxon A sintaxe é document.body.contains([selector]), ou seja,document.body.contains(document.getElementById('div')
iglesiasd
67

Eu simplesmente faço:

if(document.getElementById("myElementId")){
    alert("Element exists");
} else {
    alert("Element does not exist");
}

Funciona para mim e ainda não tinha problemas ...

Anomalia
fonte
1
Isso não tem nada a ver com a pergunta original. O OP deseja saber se uma referência a um elemento DOM faz parte do DOM visível ou não.
13283 alex
16
Me ajudou embora. Eu estava procurando pelo teste simples da existência de elementos; isso funcionou. Obrigado.
Khaverim 13/03/2013
1
Essa resposta funciona bem, mas somente quando o elemento possui um id. A melhor solução que responde à pergunta Como verificar se existe elemento no DOM visível? com qualquer elemento, mesmo elementos sem ids devem fazer document.body.contains(element).
Edward
@ Edward Isso é algo completamente diferente decontains()
alex
Entendi. Eu estava apenas sugerindo no meu comentário que outras respostas são melhores e mais adequadas para a pergunta.
Edward
11

Você pode apenas verificar se a propriedade parentNode é nula.

Isso é,

if(!myElement.parentNode)
{
    // The node is NOT in the DOM
}
else
{
    // The element is in the DOM
}
mikechambers
fonte
Sei que essa é uma pergunta antiga, mas essa resposta é exatamente o tipo de solução simples e elegante para a pergunta que eu estava procurando.
Poby
11
@ poby: Pode parecer elegante, mas não está realmente fazendo o que foi solicitado. Ele verifica apenas se o elemento possui um elemento pai. Isso não implica que o elemento esteja no DOM visível, porque talvez o elemento pai não esteja conectado a ele.
kayahr
Um teria que passar por todos os pais dos pais para descobrir se o último é um documento. O outro problema é que ele ainda pode estar fora do alcance visível ou estar coberto ou não estar visível por vários outros motivos.
Arek Bal
Um elemento também pode ter um parentNode apenas em virtude de ter sido anexado a um fragmento de documento.
11

Na Rede de Desenvolvedores Mozilla :

Esta função verifica se um elemento está no corpo da página. Como contains () é inclusivo e determina se o corpo se contém não é a intenção de isInPage, esse caso retorna explicitamente false.

function isInPage(node) {
  return (node === document.body) ? false : document.body.contains(node);
}

node é o nó que queremos verificar no <body>.

Ekramul Hoque
fonte
+1, isso funciona para nós de texto (arbitrários) (ou nós de comentários) também?
Nikos M.
@NikosM. Ele deve funcionar em qualquer tag html, mas não testei.
Ekramul Hoque 29/09
4
Não deveria falseser true?
Marc-André Lafortune
Se o nodeé document.body, certamente o método deve retornar true? return (node === document.body) || document.body.contains(node);
daiscog 25/10
7

A solução mais fácil é verificar a propriedade baseURI , que é configurada apenas quando o elemento é inserido no DOM e reverte para uma sequência vazia quando é removida.

var div = document.querySelector('div');

// "div" is in the DOM, so should print a string
console.log(div.baseURI);

// Remove "div" from the DOM
document.body.removeChild(div);

// Should print an empty string
console.log(div.baseURI);
<div></div>

Peter Mortensen
fonte
5
Eu nem sabia que havia propriedade baseURI nos nós DOM. O que eu gosto nessa abordagem é que ela usa uma propriedade do próprio elemento, o que presumivelmente significa que funcionaria mesmo se o elemento estivesse em um documento diferente (por exemplo, um iframe). O que eu não gosto é que parece não funcionar fora do Webkit.
DoctorDestructo
Cuidado, pois isso irá lançar o seguinte erro se o elemento não está no documento: Cannot read property 'baseURI' of null. Exemplo:console.log(document.querySelector('aside').baseURI)
Ian Davis
Este método não pode ser usado, pois sempre imprime a mesma string a partir de agora.
Kagami Sascha Rosylight
4

solução jQuery:

if ($('#elementId').length) {
    // element exists, do something...
}

Isso funcionou para mim usando o jQuery e não precisava $('#elementId')[0]ser usado.

Code Buster
fonte
Por que $('#elementId')[0]algo deve ser evitado?
alex
Faz muito tempo que respondi isso, então, usando $ ('# elementId') [0] Acredito que você esteja sempre indicando que o valor estará no 0º índice. Dessa forma, você sempre verifica o primeiro elemento ocorrendo. Existem várias caixas de seleção com o mesmo nome, como um botão de opção. Nesse momento, o comprimento será útil.
Code Buster
3

A solução do csuwldcat parece ser a melhor do grupo, mas uma pequena modificação é necessária para fazê-lo funcionar corretamente com um elemento que está em um documento diferente do que o código JavaScript está executando, como um iframe:

YOUR_ELEMENT.ownerDocument.body.contains(YOUR_ELEMENT);

Observe o uso da ownerDocumentpropriedade do elemento , em vez de simplesmente antigo document(que pode ou não se referir ao documento do proprietário do elemento).

O torazaburo postou um método ainda mais simples que também funciona com elementos não locais, mas, infelizmente, ele usa a baseURIpropriedade, que não é implementada uniformemente nos navegadores no momento (eu só consegui fazê-lo funcionar nos baseados no WebKit ). Como não encontrei nenhum outro elemento ou nó que pudesse ser usado de maneira semelhante, acho que, por enquanto, a solução acima é a melhor possível.

DoctorDestructo
fonte
3

Em vez de iterar os pais, você pode obter o retângulo delimitador, que é todos os zeros quando o elemento é desanexado do DOM:

function isInDOM(element) {
    if (!element)
        return false;
    var rect = element.getBoundingClientRect();
    return (rect.top || rect.left || rect.height || rect.width)?true:false;
}

Se você deseja manipular a caixa de aresta de um elemento de largura e altura zero na parte superior e esquerda zero, verifique novamente iterando os pais até document.body:

function isInDOM(element) {
    if (!element)
        return false;
    var rect = element.getBoundingClientRect();
    if (element.top || element.left || element.height || element.width)
        return true;
    while(element) {
        if (element == document.body)
            return true;
        element = element.parentNode;
    }
    return false;
}
Erez Pilosof
fonte
Isso faz com que uma re-disposição: gist.github.com/paulirish/5d52fb081b3570c81e3a#box-metrics
Steven Vachon
3

Uma maneira simples de verificar se existe um elemento pode ser feita através do código de uma linha do jQuery.

Aqui está o código abaixo:

if ($('#elementId').length > 0) {
    // Do stuff here if the element exists
} else {
    // Do stuff here if the element does not exist
}
Ravi Agrawal
fonte
2

Outra opção é element.closest :

element.closest('body') === null
Brian M. Hunt
fonte
2

Esse código funciona para mim e não tive problemas com ele.


    if(document.getElementById("mySPAN")) {
        // If the element exists, execute this code
        alert("Element exists");
    }
    else {
        // If the element does not exist execute this code
        alert("Element does not exists");
    }
Mohammad Ayoub Khan
fonte
1

Você também pode usar jQuery.contains, que verifica se um elemento é descendente de outro elemento. Passei documentcomo o elemento pai para pesquisar porque qualquer elemento existente no DOM da página é descendente de document.

jQuery.contains( document, YOUR_ELEMENT)
nitinkhuranas
fonte
1

Verifique se o elemento é filho de <html>via Node::contains():

const div = document.createElement('div');
document.documentElement.contains(div); //-> false

document.body.appendChild(div);
document.documentElement.contains(div); //-> true

Eu cobri isso e muito mais em é-dom-destacado .

Steven Vachon
fonte
1

Uma solução simples com jQuery:

$('body').find(yourElement)[0] != null
mateusmaso
fonte
2
... ou$(document).find(yourElement).length !== 0
Grinn
1
Isso explora isso null == undefined. O valor real retornado seria undefined. Compará-lo nullé um pouco estranho.
24413 alex
1
// This will work prefectly in all :D
function basedInDocument(el) {

    // This function is used for checking if this element in the real DOM
    while (el.parentElement != null) {
        if (el.parentElement == document.body) {
            return true;
        }
        el = el.parentElement; // For checking the parent of.
    } // If the loop breaks, it will return false, meaning
      // the element is not in the real DOM.

    return false;
}
qandil afa
fonte
Em tudo o que? Todos os casos?
Peter Mortensen
1
  • Se um elemento está no DOM, seus pais também devem estar no
  • E o último avô deve ser o document

Então, para verificar se apenas fazemos um loop na parentNodeárvore do elemento até chegarmos ao último avô

Usa isto:

/**
 * @param {HTMLElement} element - The element to check
 * @param {boolean}     inBody  - Checks if the element is in the body
 * @return {boolean}
 */
var isInDOM = function(element, inBody) {
    var _ = element, last;

    while (_) {
        last = _;
        if (inBody && last === document.body) { break;}
        _ = _.parentNode;
    }

    return inBody ? last === document.body : last === document;
};
silassare
fonte
2
Essa pode ser a melhor resposta, pois não causa nova renderização no DOM.
Steven Vachon
Uma explicação estaria em ordem (responda editando sua resposta , não aqui nos comentários).
Peter Mortensen
0

Gostei dessa abordagem:

var elem = document.getElementById('elementID');

if (elem)
    do this
else
    do that

Além disso

var elem = ((document.getElementById('elemID')) ? true:false);

if (elem)
    do this
else
    do that
Hugh
fonte
1
Por que não apenas !!se você quer um booleano?
alex
Então, se o elemento não tiver um ID, ele será considerado como não estando no DOM? Eu diria que isso está errado.
Steven Vachon
0

Use querySelectorAllcom forEach,

document.querySelectorAll('.my-element').forEach((element) => {
  element.classList.add('new-class');
});

como o oposto de:

const myElement = document.querySelector('.my-element');
if (myElement) {
  element.classList.add('new-class');
}
Rafal Enden
fonte
0

Tente o seguinte. É a solução mais confiável:

window.getComputedStyle(x).display == ""

Por exemplo,

var x = document.createElement("html")
var y = document.createElement("body")
var z = document.createElement("div")
x.appendChild(y);
y.appendChild(z);

z.style.display = "block";

console.log(z.closest("html") == null); // 'false'
console.log(z.style.display); // 'block'
console.log(window.getComputedStyle(z).display == ""); // 'true'
dexiang
fonte
1
Isso provavelmente provoca uma re-disposição: gist.github.com/paulirish/5d52fb081b3570c81e3a#getcomputedstyle
Steven Vachon
0

Todos os elementos existentes têm parentElement definido, exceto o elemento HTML!

function elExists (e) { 
    return (e.nodeName === 'HTML' || e.parentElement !== null);
};
Jonah
fonte
É sempre "HTML" ? Poderia ser "html" ?
Peter Mortensen
x.tagName ou x.nodeName sempre em maiúsculas, não importa como você escreve no seu código
Jonah
0

esta condição pintainho todos os casos.

function del() {
//chick if dom has this element 
//if not true condition means null or undifind or false .

if (!document.querySelector("#ul_list ")===true){

// msg to user
    alert("click btn load ");

// if console chick for you and show null clear console.
    console.clear();

// the function will stop.
    return false;
}

// if its true function will log delet .
console.log("delet");

}

Omar bakhsh
fonte
0

Prefiro usar a node.isConnectedpropriedade ( Visite MDN ).

Nota: Isso retornará true se o elemento também for anexado a um ShadowRoot, o que pode não ser o que todos desejam.

Exemplo:

const element = document.createElement('div');
console.log(element.isConnected); // Returns false
document.body.append(element);
console.log(element.isConnected); // Returns true
Robbendebiene
fonte