2012-07-22 7 views
5

Supongamos que tengo el siguiente requisito: Agregue el elemento e al elemento con id "x" si dicho elemento existe, de lo contrario agregue e al cuerpo.¿Existe una forma elegante de seleccionar un elemento en JQuery si no existe otro?

En DOM nivel 0, puedo escribir:

var parent = document.getElementById("x") || document.body; 
parent.appendChild(e); 

En jQuery, la siguiente no no trabajo:

var parent = $("#x") || $("body"); 
parent.append(e); 

porque si no hay ningún elemento con existe Identificación x, la primera disyunción devuelve el objeto jquery vacío, con es verdad, no falso, por lo que el append no hace nada. Yo puedo , sin embargo, escribo:

var parent = $("#x")[0] || $("body")[0]; 
parent.appendChild(e); 

pero esta solución es algo torpe, porque la indexación del objeto jQuery me lleva de nuevo a HTMLElements, por lo que debe utilizar en lugar de appendChildappend. Mientras esto funciona, me pregunto si esta mezcla de niveles es apropiada o indicativa de un mal diseño.

¿Hay alguna forma de usar first()? Tal vez podría crear un objeto jQuery que era esencialmente una matriz cuyo primer elemento era el div con id x, y el segundo era el cuerpo. Sé que puedo hacer esto con el formulario de constructor jQuery que toma una matriz de elementos, pero luego vuelvo a una mezcla de niveles. También sé cómo verificar la existencia de un elemento con id x ($("#x").length), pero no veo cómo esto llevará a una forma elegante de expresar "el elemento con id x si existe, sino el cuerpo".

¿Existe tal formulación?

Respuesta

2

En lugar de utilizar jQuery para seleccionar el elemento, se podría utilizar para envolver el nativa DOM llama:

$(document.getElementById("foo") || document.body) 

no es exactamente elegante (o en realidad ni siquiera usando jQuery), ni una técnica de aplicación universal, pero que va a terminar con algo que se puede anexar a (e incurrir en una invocación jQuery relativamente barato simplemente la una vez).

Usted no será capaz de utilizar first() - por ejemplo, $("#foo, body").first(); - debido a que el orden en el que se devuelve elementos seleccionados se basa en el fin de DOM, no selector fin (gracias, @muistooshort)

+0

Ooh, esto es bonito, aunque, a menos que jQuery funcione aquí con una magia realmente seria, tiene la desventaja de rendimiento de seleccionar * todos * los elementos antes de devolver el primero en lugar de cortocircuitar. Aún así, si nos importa ese nivel de rendimiento, realmente no deberíamos usar jQuery en primer lugar. – Matchu

+3

No, esto no funcionará desde ["El orden de los elementos DOM en el objeto jQuery devuelto puede no ser idéntico, ya que estarán en orden de documento."] (Http://api.jquery.com/multiple- selector /), por ejemplo: http://jsfiddle.net/ambiguous/edYY6/. Esto le dará '' cada vez. –

+0

Estoy de acuerdo en que esto es muy bueno. Estamos de acuerdo con el uno de cada uno (o debería ser), porque el primero tiene una identificación, que debe ser única en la página, y el segundo es ** el ** elemento del cuerpo. Solo debería haber uno de estos en HTML. –

3

Honestamente, yo realmente no creo que esto es muy detallado:

var parent = $('#x'); 
if(parent.length == 0) parent = $('body'); 

Y su intención es también bastante clara. Incluso podría envolverlo en una función si este modismo aparece mucho.

Además, aquí es una forma ternaria que sólo dispara cada consulta una vez (aunque es una solución de compromiso sobre la legibilidad):

var parent = (x = $('#header')).length ? x : $('body'); 
+2

También podría use '$ (" # x "). length? $ ("# x"): $ ("cuerpo") '. –

+0

Gracias por la respuesta rápida. Me siento un poco mal por pedir un proyecto de una sola línea (¡demasiado común en SO, lo sé!), Pero me sorprendió que, dado que DOM Level 0 tuviera una formulación concisa, jquery probablemente debería hacerlo. :) –

+0

@RayToal: agregué un trazador de líneas de un solo rendimiento, aunque es claramente menos legible.Todavía votaría convirtiéndolo en una línea al incluir la versión de dos líneas en una función, especialmente si aparece mucho ... pero si solo se usa una vez, entonces meh. – Matchu

Cuestiones relacionadas