¿Cómo puedo verificar si existe un elemento en el DOM visible?


423

¿Cómo se prueba la existencia de un elemento sin el uso del getElementByIdmétodo?

He configurado una demostración en vivo como referencia. También imprimiré el código aquí también:

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

Básicamente, el código anterior demuestra que un elemento se almacena en una variable y luego se elimina del DOM. Aunque el elemento se ha eliminado del DOM, la variable conserva el elemento como estaba cuando se declaró por primera vez. En otras palabras, no es una referencia en vivo al elemento en sí, sino más bien una réplica. Como resultado, verificar la existencia del valor de la variable (el elemento) proporcionará un resultado inesperado.

La isNullfunción es mi intento de verificar la existencia de elementos a partir de una variable, y funciona, pero me gustaría saber si hay una manera más fácil de lograr el mismo resultado.

PD: También me interesa saber por qué las variables de JavaScript se comportan así si alguien conoce algunos buenos artículos relacionados con el tema.


18
En realidad, es una referencia en vivo del elemento en sí, simplemente ya no está en un documento. Esa funcionalidad es necesaria porque en realidad puede extraer un elemento del DOM y luego volver a colocarlo más tarde con todos los controladores de eventos / etc. todavía conectados. ¿Por qué las variables JS actúan así? Porque sería increíblemente molesto si no lo hicieran. JS solo elimina variables cuando ya no tienes NINGUNA referencia a ellas. El lenguaje no tiene forma de saber qué referencias considera importantes y cuáles cree que no valen nada.
Mark Kahn el

@cwolves Interesante. Me he encontrado con esto muchas veces antes y nunca pensé mucho en eso. De hecho, en mi proyecto actual, estoy guardando elementos en una matriz antes de hacer cualquier cambio en ellos, en caso de que quiera revertir los cambios.
Justin Bull

1
La recolección de basura se ejecuta de vez en cuando y elimina todo lo que cree que puede. Parece bastante pésimo en la mayoría de los navegadores, pero está mejorando a medida que los desarrolladores se dan cuenta de que algunos navegadores funcionan durante días o semanas entre reinicios, por lo que una buena recolección de basura es vital para el rendimiento del navegador. Los desarrolladores web pueden ayudar eliminando propiedades (y, por lo tanto, referencias a cosas en la memoria) que ya no son necesarias.
RobG

2
@JustinBull tenga cuidado al almacenar copias de los elementos para revertir. Al almacenar un elemento DOM en una matriz, se almacena una referencia al elemento DOM, no una copia, por lo que los cambios realizados en el elemento DOM se reflejarán al hacer referencia al elemento de la matriz. Este es el caso con todos los objetos en javascript (variables de tipo 'objeto').
Anthony DiSanti

Respuestas:


545

Parece que algunas personas están aterrizando aquí, y simplemente quieren saber si un elemento existe (un poco diferente a la pregunta original).

Eso es tan simple como usar cualquiera de los métodos de selección del navegador y verificar que tenga un valor verdadero (generalmente).

Por ejemplo, si mi elemento tuviera un idde "find-me", simplemente podría usar ...

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

Esto se especifica para devolver una referencia al elemento o null. Si debe tener un valor booleano, simplemente arroje un !!antes de la llamada al método.

Además, puede usar algunos de los muchos otros métodos que existen para encontrar elementos, como (todos viviendo fuera document):

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

Algunos de estos métodos devuelven a NodeList, así que asegúrese de verificar su lengthpropiedad, porque a NodeListes un objeto y, por lo tanto, es verdadero .


Para determinar realmente si un elemento existe como parte del DOM visible (como la pregunta que se hizo originalmente), Csuwldcat proporciona una mejor solución que la suya (como solía contener esta respuesta). Es decir, usar elcontains() método en elementos DOM.

Podrías usarlo así ...

document.body.contains(someReferenceToADomElement);

1
¡Exactamente lo que estaba buscando! Así que obviamente jajaja, ¿por qué no pensé en eso? Además, ¿conoce algún buen artículo que explique por qué las variables actúan así?
Justin Bull el

3
Aún más corto:var elementInDom = function( el ) { while ( el = el.parentNode ) if ( el === document ) return true; return false; }
bennedich

2
@ButtleButkus Lea la pregunta real. Esa solución que usó no tiene sentido ya getElementById() que devolverá una referencia a un elemento DOM o null, por lo tanto, usar typeof(especialmente en el RHS) es incorrecto (si no se definiera, la condición LHS arrojaría un ReferenceError).
alex

2
¿Hay alguna razón para usar esto sobre lo que se publicó a continuación: document.body.contains()que parece tener muy buena compatibilidad con el navegador?
aplastar

1
@Jonz eliminó la parte anterior de la respuesta, no se olvide de ir a votar csuwldcat
alex

310

Utilizar getElementById() si está disponible.

Además, aquí hay una manera fácil de hacerlo con jQuery:

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

Y si no puede usar bibliotecas de terceros, simplemente manténgase en JavaScript base:

var element =  document.getElementById('elementId');
if (typeof(element) != 'undefined' && element != null)
{
  // Exists.
}

2
Para el proyecto en el que estoy trabajando, no puedo usar una biblioteca. Good-ol 'fashion raw code only. Soy consciente de ese método jQuery, pero no funciona en elementos no incluidos en el contenedor jQuery. Por ejemplo, $('#elementId')[0].lengthno produciría el mismo resultado.
Justin Bull

8
¿Hay alguna buena razón para una declaración if tan complicada en el segundo ejemplo de código? ¿Por qué no simplemente if (element) {}? Cuando el elemento no está definido o es nulo, esta expresión es falsa. Si el elemento es un elemento DOM, la expresión es verdadera.
kayahr

2
@kayahr Es demasiado complicado. getElementById()se especifica que devuelva nullsi no encuentra el elemento, por lo que solo se necesita verificar un valor devuelto verdadero .
alex

55
Creo que eso es solo sentido común.
Kon

8
getElementByIdNunca debería volver undefined. En cualquier caso, el element != nullcheque recogería esto.

191

Usando Node.contains DOM API , puede verificar la presencia de cualquier elemento en la página (actualmente en el DOM) con bastante facilidad:

document.body.contains(YOUR_ELEMENT_HERE);

NOTA DE NAVEGADOR CRUZADO : el documentobjeto en Internet Explorer no tiene un contains()método: para garantizar la compatibilidad entre navegadores, utilícelo document.body.contains().


44
Esta parece ser la respuesta definitiva a este problema ... y su apoyo, si se cree en MDN, es bastante bueno.
aplastar

2
Esta es la mejor respuesta. Tenga en cuenta que solo verificar document.contains()debería ser suficiente.
alex

@csuwldcat Funcionó para mí, al menos en Chrome con document.contains(document.documentElement). documenttiene Nodeen su cadena de prototipos, por lo que puedo decir ( document-> HTMLDocument-> Document-> Node)
alex

44
De hecho, esta es la mejor respuesta: es un estándar web, está muy bien soportado (sorprendentemente, no aparece en Firefox hasta la versión 9, supongo que era una función no estándar inventada en IE que no era estandarizado hasta más tarde) - debe ser el más rápido porque usa una sola llamada a una API nativa
Jon z

2
@LeeSaxon La sintaxis es document.body.contains([selector]), es decirdocument.body.contains(document.getElementById('div')
iglesiasedd

67

Simplemente hago:

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

Funciona para mí y todavía no tuve problemas ...


1
Sin embargo, esto no tiene nada que ver con la pregunta original. El OP quiere saber si una referencia a un elemento DOM es parte del DOM visible o no.
alex

16
Aunque me ayudó. Estaba buscando la simple prueba de la existencia del elemento; Esto funcionó. Gracias.
Khaverim

1
Esta respuesta funciona bien, pero solo cuando el elemento tiene un id. La mejor solución que responde a la pregunta ¿Cómo verificar si el elemento existe en el DOM visible? con cualquier elemento, incluso los elementos sin ids son para hacer document.body.contains(element).
Edward

@Edward Esto es algo completamente diferente acontains()
alex

Lo entiendo. Estaba sugiriendo en mi comentario que otras respuestas son mejores y más adecuadas para la pregunta.
Edward

11

Simplemente puede verificar si la propiedad parentNode es nula.

Es decir,

if(!myElement.parentNode)
{
    // The node is NOT in the DOM
}
else
{
    // The element is in the DOM
}

Sé que esta es una vieja pregunta, pero esta respuesta es exactamente el tipo de solución elegante y simple a la pregunta que estaba buscando.
poby

11
@poby: Puede parecer elegante, pero en realidad no está haciendo lo que se solicitó. Solo verifica si el elemento tiene un elemento padre. Esto no implica que el elemento esté en el DOM visible porque quizás el elemento padre no esté conectado a él.
kayahr

Uno tendría que pasar por todos los padres de los padres para averiguar si el último es un documento. El otro problema es que todavía podría estar fuera del rango visible o estar cubierto o no ser visible debido a muchas otras razones.
Arek Bal

Un elemento también podría tener un ParentNode solo en virtud de haberse agregado a un fragmento de documento.

11

De la red de desarrolladores de Mozilla :

Esta función verifica si un elemento está en el cuerpo de la página. Como contiene () es inclusivo y determinar si el cuerpo contiene no es la intención de isInPage, este caso devuelve explícitamente falso.

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

nodo es el nodo que queremos verificar en el <cuerpo>.


+1, ¿funciona esto también para nodos de texto (arbitrarios) (o nodos de comentarios)?
Nikos M.

@NikosM. Debería funcionar en cualquier etiqueta html pero no lo probé.
Ekramul Hoque

44
¿No debería falseser true?
Marc-André Lafortune

Si el nodeIS es document.body, seguramente el método debería volver true? Es decir,return (node === document.body) || document.body.contains(node);
daiscog

7

La solución más fácil es verificar la propiedad baseURI , que se establece solo cuando el elemento se inserta en el DOM, y se vuelve a una cadena vacía cuando se elimina.

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>


55
Ni siquiera sabía que había una propiedad baseURI en los nodos DOM. Lo que me gusta de este enfoque es que usa una propiedad del elemento en sí, lo que presumiblemente significa que funcionaría incluso si el elemento está en un documento diferente (por ejemplo, un iframe). Lo que no me gusta es que no parece funcionar fuera de Webkit.
DoctorDestructo

Cuidado ya que esto arrojará el siguiente error si el elemento no está en el documento: Cannot read property 'baseURI' of null. Ejemplo:console.log(document.querySelector('aside').baseURI)
Ian Davis

Este método no se puede usar ya que siempre imprime la misma cadena a partir de ahora.
Kagami Sascha Rosylight

4

Solución jQuery:

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

Esto funcionó para mí usando jQuery y no requirió $('#elementId')[0]ser utilizado.


¿Por qué hay $('#elementId')[0]que evitar algo?
alex

Hace mucho que respondí esto, así que, usando $ ('# elementId') [0] Creo que siempre estás indicando que el valor estará en el índice 0. De esta manera, siempre está buscando el primer elemento que ocurre. ¿Qué hay? Había varias casillas de verificación con el mismo nombre, como un botón de radio. Esa vez la longitud será útil.
Code Buster

3

La solución de csuwldcat parece ser la mejor del grupo, pero se necesita una ligera modificación para que funcione correctamente con un elemento que está en un documento diferente al que se está ejecutando el código JavaScript, como un iframe:

YOUR_ELEMENT.ownerDocument.body.contains(YOUR_ELEMENT);

Tenga en cuenta el uso de la ownerDocumentpropiedad del elemento , en lugar de simplemente viejodocument (que puede o no hacer referencia al documento del propietario del elemento).

torazaburo publicó un método aún más simple que también funciona con elementos no locales, pero desafortunadamente, utiliza la baseURIpropiedad, que no está implementada de manera uniforme en todos los navegadores en este momento (solo pude hacer que funcione en los basados en WebKit ). No pude encontrar ninguna otra propiedad de elemento o nodo que pudiera usarse de manera similar, por lo que creo que por el momento la solución anterior es tan buena como parece.


3

En lugar de iterar padres, solo puede obtener el rectángulo delimitador que es todo ceros cuando el elemento se separa del DOM:

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

Si desea manejar el caso de borde de un elemento de ancho y altura cero en la parte superior cero y cero izquierda, puede verificar dos veces iterando los padres hasta que 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;
}


3

Una forma simple de verificar si existe un elemento puede hacerse a través del código de una línea de jQuery.

Aquí está el código a continuación:

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


2

Este código funciona para mí y no tuve ningún problema con él.


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

1

También puede usar jQuery.contains, que comprueba si un elemento es descendiente de otro elemento. Pasé documentcomo elemento principal para buscar porque cualquier elemento que exista en la página DOM es descendiente de document.

jQuery.contains( document, YOUR_ELEMENT)

1

Compruebe si el elemento es hijo de <html>via Node::contains():

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

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

He cubierto esto y más en is-dom-detached .


1

Una solución simple con jQuery:

$('body').find(yourElement)[0] != null

2
... o$(document).find(yourElement).length !== 0
Grinn

1
Esto explota eso null == undefined. El valor real devuelto sería undefined. Compararlo nulles un poco extraño.
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;
}

En todo lo que? ¿Todos los casos?
Peter Mortensen

1
  • Si un elemento está en el DOM, sus padres también deben estar en
  • Y el último abuelo debería ser el document

Entonces, para verificar que simplemente recorramos los elementos parentNode árbol hasta llegar al último abuelo

Utilizar este:

/**
 * @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;
};

2
Esta podría ser la mejor respuesta, ya que no causa ninguna nueva representación en el DOM.
Steven Vachon

Una explicación estaría en orden (responda editando su respuesta , no aquí en los comentarios).
Peter Mortensen

0

Me gustó este enfoque:

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

if (elem)
    do this
else
    do that

también

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

if (elem)
    do this
else
    do that

1
¿Por qué no solo !!si quieres un booleano?
alex

Entonces, si el elemento no tiene una identificación, ¿se considera que no está en el DOM? Yo diría que esto está mal.
Steven Vachon

0

Utilizar querySelectorAllcon forEach,

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

como lo contrario de:

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

0

Intenta lo siguiente. Es la solución más confiable:

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

Por ejemplo,

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'


0

¡Todos los elementos existentes tienen conjunto parentElement, excepto el elemento HTML!

function elExists (e) { 
    return (e.nodeName === 'HTML' || e.parentElement !== null);
};

¿Es siempre "HTML" ? ¿Podría ser "html" ?
Peter Mortensen

x.tagName o x.nodeName siempre en mayúscula sin importar cómo lo escriba en su código
Jonás

0

Esta condición de pollito todos los 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");

}


0

Prefiero usar la node.isConnectedpropiedad ( Visita MDN ).

Nota: Esto volverá verdadero si el elemento también se agrega a ShadowRoot, lo que podría no ser el comportamiento deseado por todos.

Ejemplo:

const element = document.createElement('div');
console.log(element.isConnected); // Returns false
document.body.append(element);
console.log(element.isConnected); // Returns true
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.