javascript - ejemplos - getelementsbytagname
JavaScript isDOM-¿Cómo verifica si un objeto JavaScript es un objeto DOM? (30)
¿Qué tal el _.isElement
Lo-Dash ?
$ npm install lodash.iselement
Y en el código:
var isElement = require("lodash.iselement");
isElement(document.body);
Estoy tratando de conseguir:
document.createElement(''div'') //=> true
{tagName: ''foobar something''} //=> false
En mis propios scripts, solía usar esto ya que nunca necesité tagName
como propiedad:
if (!object.tagName) throw ...;
Entonces, para el segundo objeto, se me ocurrió lo siguiente como una solución rápida, que en su mayoría funciona. ;)
El problema es que depende de los navegadores que aplican las propiedades de solo lectura, que no todos lo hacen.
function isDOM(obj) {
var tag = obj.tagName;
try {
obj.tagName = ''''; // Read-only for DOM, should throw exception
obj.tagName = tag; // Restore for normal objects
return false;
} catch (e) {
return true;
}
}
¿Hay un buen sustituto?
Al utilizar la detección de raíz que se encuentra here , podemos determinar si, por ejemplo, la alerta es un miembro de la raíz del objeto, que es probable que sea una ventana:
function isInAnyDOM(o) {
return (o !== null) && !!(o.ownerDocument && (o.ownerDocument.defaultView || o.ownerDocument.parentWindow).alert); // true|false
}
Para determinar si el objeto es la ventana actual es aún más simple:
function isInCurrentDOM(o) {
return (o !== null) && !!o.ownerDocument && (window === (o.ownerDocument.defaultView || o.ownerDocument.parentWindow)); // true|false
}
Esto parece ser menos costoso que la solución try / catch en el hilo de apertura.
Don p
Aquí hay un truco usando jQuery
var obj = {};
var element = document.getElementById(''myId''); // or simply $("#myId")
$(obj).html() == undefined // true
$(element).html() == undefined // false
así que poniéndolo en una función:
function isElement(obj){
return (typeOf obj === ''object'' && !($(obj).html() == undefined));
}
Cada DOMElement.constructor devuelve la función HTML ... Elemento () o [Objeto HTML ... Elemento], así que ...
function isDOM(getElem){
if(getElem===null||typeof getElem==="undefined") return false;
var c = getElem.constructor.toString();
var html = c.search("HTML")!==-1;
var element = c.search("Element")!==-1;
return html&&element;
}
Creo que la creación de prototipos no es una solución muy buena, pero tal vez sea la más rápida: defina este bloque de código;
Element.prototype.isDomElement = true;
HTMLElement.prototype.isDomElement = true;
que compruebe sus objetos es propiedad delDominio:
if(a.isDomElement){}
Espero que esto ayude.
Creo que lo que tienes que hacer es hacer un control minucioso de algunas propiedades que siempre estarán en un elemento dom, pero su combinación probablemente no estará en otro objeto, como por ejemplo:
var isDom = function (inp) {
return inp && inp.tagName && inp.nodeName && inp.ownerDocument && inp.removeAttribute;
};
El siguiente código súper simple compatible con IE8 funciona perfectamente.
La respuesta aceptada no detecta todos los tipos de elementos HTML. Por ejemplo, los elementos SVG no son compatibles. En contraste, esta respuesta funciona tanto para HTML como para SVG.
Véalo en acción aquí: https://jsfiddle.net/eLuhbu6r/
function isElement(element) {
return element instanceof Element || element instanceof HTMLDocument;
}
En Firefox, puedes usar la instanceof Node
. Ese Node
está definido en DOM1 .
Pero eso no es tan fácil en IE.
- "instanceof ActiveXObject" solo puede indicar que es un objeto nativo.
- "typeof document.body.appendChild == ''object''" dice que puede ser un objeto DOM, pero también puede ser otra cosa que tenga la misma función.
Solo puede asegurarse de que sea un elemento DOM usando la función DOM y capturar si hay alguna excepción. Sin embargo, puede tener efectos secundarios (por ejemplo, cambio de estado interno / rendimiento / pérdida de memoria)
Esto es de la hermosa biblioteca de JavaScript MooTools :
if (obj.nodeName){
switch (obj.nodeType){
case 1: return ''element'';
case 3: return (//S/).test(obj.nodeValue) ? ''textnode'' : ''whitespace'';
}
}
Esto es lo que descubrí:
var isHTMLElement = (function () {
if ("HTMLElement" in window) {
// Voilà. Quick and easy. And reliable.
return function (el) {return el instanceof HTMLElement;};
} else if ((document.createElement("a")).constructor) {
// We can access an element''s constructor. So, this is not IE7
var ElementConstructors = {}, nodeName;
return function (el) {
return el && typeof el.nodeName === "string" &&
(el instanceof ((nodeName = el.nodeName.toLowerCase()) in ElementConstructors
? ElementConstructors[nodeName]
: (ElementConstructors[nodeName] = (document.createElement(nodeName)).constructor)))
}
} else {
// Not that reliable, but we don''t seem to have another choice. Probably IE7
return function (el) {
return typeof el === "object" && el.nodeType === 1 && typeof el.nodeName === "string";
}
}
})();
Para mejorar el rendimiento, creé una función de invocación automática que prueba las capacidades del navegador solo una vez y asigna la función apropiada en consecuencia.
La primera prueba debería funcionar en la mayoría de los navegadores modernos y ya se discutió aquí. Solo comprueba si el elemento es una instancia de HTMLElement
. Muy sencillo.
El segundo es el más interesante. Esta es su funcionalidad principal:
return el instanceof (document.createElement(el.nodeName)).constructor
Comprueba si el es una instancia del constructor que pretende ser. Para hacer eso, necesitamos acceso al contructor de un elemento. Es por eso que estamos probando esto en la declaración if. IE7, por ejemplo, falla esto, porque (document.createElement("a")).constructor
undefined
está undefined
en IE7.
El problema con este enfoque es que document.createElement
realmente no es la función más rápida y podría ralentizar fácilmente su aplicación si está probando muchos elementos con ella. Para resolver esto, decidí cachear los constructores. El objeto ElementConstructors
tiene nodeNames como claves con sus constructores correspondientes como valores. Si un constructor ya está en caché, lo usa desde el caché; de lo contrario, crea el Elemento, almacena en caché su constructor para un acceso futuro y luego lo prueba.
La tercera prueba es la caída desagradable. nodeType
si el es un object
, tiene una propiedad nodeType
establecida en 1
y una cadena como nodeName
. Por supuesto, esto no es muy confiable, pero la gran mayoría de los usuarios ni siquiera deberían retroceder hasta el momento.
Este es el enfoque más confiable que se me ocurrió, a la vez que mantengo el rendimiento lo más alto posible.
Esto funcionará para casi cualquier navegador. (No hay distinción entre elementos y nodos aquí)
function dom_element_check(element){
if (typeof element.nodeType !== ''undefined''){
return true;
}
return false;
}
Esto podría ser útil: isDOM
//-----------------------------------
// Determines if the @obj parameter is a DOM element
function isDOM (obj) {
// DOM, Level2
if ("HTMLElement" in window) {
return (obj && obj instanceof HTMLElement);
}
// Older browsers
return !!(obj && typeof obj === "object" && obj.nodeType === 1 && obj.nodeName);
}
En el código anterior, usamos el operador de doble negación para obtener el valor booleano del objeto pasado como argumento, de esta manera nos aseguramos de que cada expresión evaluada en la declaración condicional sea booleana, aprovechando la Evaluación de cortocircuito , por lo tanto la función devuelve true
o false
Esto puede ser de interés:
function isElement(obj) {
try {
//Using W3 DOM2 (works for FF, Opera and Chrome)
return obj instanceof HTMLElement;
}
catch(e){
//Browsers not supporting W3 DOM2 don''t have HTMLElement and
//an exception is thrown and we end up here. Testing some
//properties that all elements have (works on IE7)
return (typeof obj==="object") &&
(obj.nodeType===1) && (typeof obj.style === "object") &&
(typeof obj.ownerDocument ==="object");
}
}
Es parte del DOM, Nivel2 .
Actualización 2 : Así lo implementé en mi propia biblioteca: (el código anterior no funcionó en Chrome, porque Node y HTMLElement son funciones en lugar del objeto esperado. Este código se prueba en FF3, IE7, Chrome 1 y Opera 9).
//Returns true if it is a DOM node
function isNode(o){
return (
typeof Node === "object" ? o instanceof Node :
o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string"
);
}
//Returns true if it is a DOM element
function isElement(o){
return (
typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2
o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName==="string"
);
}
La forma más fácil y cruzada de navegador para detectar si un elemento es parte de HTML DOM es la siguiente:
function inHTMLDom(myelement){
if(myelement.ownerDocument.documentElement.tagName.toLowerCase()=="html"){
return true;
}else{
return false;
}
}
inHTMLDom(<your element>); // <your element>:element you are interested in checking.
probado en IE6, IE7, IE8, IE9, IE10, FF, Chrome, Safari, Opera.
No hay necesidad de hacks, solo puedes preguntar si un elemento es una instancia del Element :
const isElement = el => el instanceof Element
No para insistir en esto ni nada, excepto en los navegadores compatibles con ES5, por qué no simplemente:
function isDOM(e) {
return (/HTML(?:.*)Element/).test(Object.prototype.toString.call(e).slice(8, -1));
}
No funcionará en TextNodes y no estoy seguro acerca de Shadow DOM o DocumentFragments, etc., pero funcionará en casi todos los elementos de etiquetas HTML.
Para los que usan Angular:
angular.isElement
https://docs.angularjs.org/api/ng/function/angular.isElement
Podrías intentar agregarlo a un nodo DOM real ...
function isDom(obj)
{
var elm = document.createElement(''div'');
try
{
elm.appendChild(obj);
}
catch (e)
{
return false;
}
return true;
}
Puede ver si el objeto o nodo en cuestión devuelve un tipo de cadena.
typeof (array).innerHTML === "string" => false
typeof (object).innerHTML === "string" => false
typeof (number).innerHTML === "string" => false
typeof (text).innerHTML === "string" => false
//any DOM element will test as true
typeof (HTML object).innerHTML === "string" => true
typeof (document.createElement(''anything'')).innerHTML === "string" => true
Quizás esta es una alternativa? Probado en Opera 11, FireFox 6, Internet Explorer 8, Safari 5 y Google Chrome 16.
function isDOMNode(v) {
if ( v===null ) return false;
if ( typeof v!==''object'' ) return false;
if ( !(''nodeName'' in v) ) return false;
var nn = v.nodeName;
try {
// DOM node property nodeName is readonly.
// Most browsers throws an error...
v.nodeName = ''is readonly?'';
} catch (e) {
// ... indicating v is a DOM node ...
return true;
}
// ...but others silently ignore the attempt to set the nodeName.
if ( v.nodeName===nn ) return true;
// Property nodeName set (and reset) - v is not a DOM node.
v.nodeName = nn;
return false;
}
La función no será engañada, por ejemplo, por esto.
isDOMNode( {''nodeName'':''fake''} ); // returns false
Sugiero una forma sencilla de probar si una variable es un elemento DOM
function isDomEntity(entity) {
if( typeof entity === ''object'' && entity.nodeType != undefined){
return true;
}
else{
return false;
}
}
Tengo una forma especial de hacer esto que aún no se ha mencionado en las respuestas.
Mi solución se basa en cuatro pruebas. Si el objeto pasa los cuatro, entonces es un elemento:
El objeto no es nulo.
El objeto tiene un método llamado "appendChild".
El método "appendChild" se heredó de la clase Node y no es solo un método impostor (una propiedad creada por el usuario con un nombre idéntico).
El objeto es de Nodo Tipo 1 (Elemento). Los objetos que heredan métodos de la clase Nodo son siempre Nodos, pero no necesariamente Elementos.
P: ¿Cómo verifico si una propiedad determinada se hereda y no es solo un impostor?
R: Una prueba simple para ver si un método realmente se heredó de Node es verificar primero que la propiedad tiene un tipo de "objeto" o "función". A continuación, convierta la propiedad en una cadena y verifique si el resultado contiene el texto "[Código nativo]". Si el resultado se ve algo como esto:
function appendChild(){
[Native Code]
}
Entonces el método ha sido heredado del objeto Nodo. Ver https://davidwalsh.name/detect-native-function
Y finalmente, al reunir todas las pruebas, la solución es:
function ObjectIsElement(obj) {
var IsElem = true;
if (obj == null) {
IsElem = false;
} else if (typeof(obj.appendChild) != "object" && typeof(obj.appendChild) != "function") {
//IE8 and below returns "object" when getting the type of a function, IE9+ returns "function"
IsElem = false;
} else if ((obj.appendChild + '''').replace(/[/r/n/t/b/f/v/xC2/xA0/x00-/x1F/x7F-/x9F ]/ig, '''').search(//{/[NativeCode]}$/i) == -1) {
IsElem = false;
} else if (obj.nodeType != 1) {
IsElem = false;
}
return IsElem;
}
Todas las soluciones arriba y abajo (incluida mi solución) tienen la posibilidad de ser incorrectas, especialmente en IE. Es muy posible (re) definir algunos objetos / métodos / propiedades para imitar un nodo DOM que hace que la prueba no sea válida.
Por lo general, utilizo las pruebas tipo pato: pruebo específicamente las cosas que uso. Por ejemplo, si quiero clonar un nodo, lo pruebo así:
if(typeof node == "object" && "nodeType" in node &&
node.nodeType === 1 && node.cloneNode){
// most probably this is a DOM node, we can clone it safely
clonedNode = node.cloneNode(false);
}
Básicamente es un pequeño control de cordura + la prueba directa de un método (o una propiedad) que planeo usar.
Por cierto, la prueba anterior es una buena prueba para los nodos DOM en todos los navegadores. Pero si quiere estar seguro, siempre verifique la presencia de métodos y propiedades y verifique sus tipos.
EDITAR: IE usa objetos ActiveX para representar nodos, por lo que sus propiedades no se comportan como un verdadero objeto de JavaScript, por ejemplo:
console.log(typeof node.cloneNode); // object
console.log(node.cloneNode instanceof Function); // false
mientras que debe devolver "función" y true
respectivamente. La única forma de probar los métodos es ver si están definidos.
Un método de derecho absoluto, comprobar destino es un código primario de elemento html real :
(function (scope) {
if (!scope.window) {//May not run in window scope
return;
}
var HTMLElement = window.HTMLElement || window.Element|| function() {};
var tempDiv = document.createElement("div");
var isChildOf = function(target, parent) {
if (!target) {
return false;
}
if (parent == null) {
parent = document.body;
}
if (target === parent) {
return true;
}
var newParent = target.parentNode || target.parentElement;
if (!newParent) {
return false;
}
return isChildOf(newParent, parent);
}
/**
* The dom helper
*/
var Dom = {
/**
* Detect if target element is child element of parent
* @param {} target The target html node
* @param {} parent The the parent to check
* @returns {}
*/
IsChildOf: function (target, parent) {
return isChildOf(target, parent);
},
/**
* Detect target is html element
* @param {} target The target to check
* @returns {} True if target is html node
*/
IsHtmlElement: function (target) {
if (!X.Dom.IsHtmlNode(target)) {
return false;
}
return target.nodeType === 1;
},
/**
* Detect target is html node
* @param {} target The target to check
* @returns {} True if target is html node
*/
IsHtmlNode:function(target) {
if (target instanceof HTMLElement) {
return true;
}
if (target != null) {
if (isChildOf(target, document.documentElement)) {
return true;
}
try {
tempDiv.appendChild(target.cloneNode(false));
if (tempDiv.childNodes.length > 0) {
tempDiv.innerHTML = "";
return true;
}
} catch (e) {
}
}
return false;
}
};
X.Dom = Dom;
})(this);
diferenciar un objeto js en bruto de un HTMLElement
function isDOM (x){
return /HTML/.test( {}.toString.call(x) );
}
utilizar:
isDOM( {a:1} ) // false
isDOM( document.body ) // true
// O
Object.defineProperty(Object.prototype, "is",
{
value: function (x) {
return {}.toString.call(this).indexOf(x) >= 0;
}
});
utilizar:
o={}; o.is("HTML") // false o=document.body; o.is("HTML") // true
hilo viejo, pero aquí hay una posibilidad actualizada para los usuarios de ie8 y ff3.5 :
function isHTMLElement(o) {
return (o.constructor.toString().search(//object HTML.+Element/) > -1);
}
(element instanceof $ && element.get(0) instanceof Element) || element instanceof Element
Esto comprobará si es un elemento DOM jQuery o JavaScript
var IsPlainObject = function ( obj ) { return obj instanceof Object && ! ( obj instanceof Function || obj.toString( ) !== ''[object Object]'' || obj.constructor.name !== ''Object'' ); },
IsDOMObject = function ( obj ) { return obj instanceof EventTarget; },
IsDOMElement = function ( obj ) { return obj instanceof Node; },
IsListObject = function ( obj ) { return obj instanceof Array || obj instanceof NodeList; },
// De hecho, es más probable que use estos en línea, pero a veces es bueno tener estos accesos directos para el código de configuración
var isElement = function(e){
try{
// if e is an element attached to the DOM, we trace its lineage and use native functions to confirm its pedigree
var a = [e], t, s, l = 0, h = document.getElementsByTagName(''HEAD'')[0], ht = document.getElementsByTagName(''HTML'')[0];
while(l!=document.body&&l!=h&&l.parentNode) l = a[a.push(l.parentNode)-1];
t = a[a.length-1];
s = document.createElement(''SCRIPT''); // safe to place anywhere and it won''t show up
while(a.length>1){ // assume the top node is an element for now...
var p = a.pop(),n = a[a.length-1];
p.insertBefore(s,n);
}
if(s.parentNode)s.parentNode.removeChild(s);
if(t!=document.body&&t!=h&&t!=ht)
// the top node is not attached to the document, so we don''t have to worry about it resetting any dynamic media
// test the top node
document.createElement(''DIV'').appendChild(t).parentNode.removeChild(t);
return e;
}
catch(e){}
return null;
}
Probé esto en Firefox, Safari, Chrome, Opera e IE9. No pude encontrar una manera de hackearlo.
En teoría, prueba todos los antepasados del elemento propuesto, así como el propio elemento, insertando una etiqueta de script delante de él.
Si su primer antepasado se remonta a un elemento conocido, como <html>
, <head>
o <body>
, y no ha arrojado un error en el camino, tenemos un elemento.
Si el primer antepasado no está adjunto al documento, creamos un elemento e intentamos colocar el elemento propuesto dentro de él (y luego lo eliminamos del nuevo elemento).
Por lo tanto, se remonta a un elemento conocido, se conecta exitosamente a un elemento conocido o falla.
Devuelve el elemento o nulo si no es un elemento.