2011-06-08 17 views
8

¿jQuery tiene un método para determinar si un argumento pasado a la función es un selector?¿Determina si una cadena es un selector jQuery válido?

Estoy haciendo una plantilla para algunos plugins jQuery y necesito poder verificar si el argumento pasado es un selector jQuery. Quiero permitir otros tipos de datos y realizar diferentes métodos según el tipo de datos que se pasa. La detección de tipos de datos es fácil, pero los selectores son solo una cadena y se pueden construir de muchas formas diferentes.

Mi objetivo es crear complementos que sean indulgentes con lo que pasa por los argumentos y tome decisiones informadas sobre qué hacer con él. Tome los complementos jQuery UI, por ejemplo, en algunos complementos, digamos que pasamos una función de devolución de llamada en el argumento marcador de posición que es para un número de velocidad, todavía toma la devolución de llamada y la ejecuta y usa la velocidad predeterminada. Ese es el tipo de funcionalidad que estoy buscando y los selectores son un caso bastante único.

¿Ha escrito jQuery una Regex para esto? No pude encontrar uno en el código.

Si no, supongo que tendré que escribir una enorme Regex para esto?

+0

¿por qué no pasar objetos reales de jQuery? '$ ('selector')' debería ser lo suficientemente fácil para verificar ... –

+0

@jcinacio: gracias, pero en realidad también estoy buscando eso. Mi objetivo es crear argumentos que sean bastante gratuitos con lo que se pasa. – UpHelix

+0

'$ ('selector')' no encaja para este propósito, ya que arroja un error si no es válido. –

Respuesta

4

Un montón de cuerdas pueden técnicamente ser un selector como $('blah') podría seleccionar los elementos de encargo! No hay una buena forma de conocer el intento de qué hacer con el argumento pasado a su función, por lo que es mejor tener una estructura bien definida como ha comentado Gaby.

Selector:

yourFunction({ selector: 'div' }); 

O

yourFunction({ value: 'testing' }); 

tomará una ruta diferente en el código.

Sin esta técnica, lo mejor que puede hacer es simplemente intentar que jQuery encuentre elementos basados ​​en el selector, verifique con .length, si se encuentran elementos, suponga que la persona que llama quiere un selector jQuery. Otra opción podría ser simplemente documentar que se debe pasar un objeto jQuery, es decir:

yourFunction({ value: jQuery('div') }); 

Entonces, por una ruta diferente que puede hacer

if (value instanceof of jQuery) { .... } 
+0

"intenta que jQuery encuentre elementos basados ​​en el selector, compruebe con .length, si se encuentran elementos, suponga que la persona que llama intentó un selector jQuery" ---- eso es bastante bueno. – UpHelix

+0

@UpHelix no solicitó verificar si un selector concuerda con algo o qué rol tiene lo que selecciona, pero si es válido de acuerdo con las reglas de jQuery para una sintaxis de selector. –

+2

@UpHelix "intentan que jQuery encuentre elementos basados ​​en el selector, compruebe con .length, si se encuentran elementos, suponga que la persona que llama intentó un selector jQuery" - mala idea, hay cadenas que cuando se usan como selectores de jquery emitirán una excepción , simplemente intente algo con "(" – Rui

4

No puede haber una expresión regular para esto, ya que los selectores son extensibles y cualquiera puede agregar cualquier número de selectores personales (con símbolos personalizados definidos etc ...)

Tal vez usted debe tratar de pasar sus argumentos como un solo objeto con parámetros nombrados.

{ selector:'...', 
    otherargument:'somevalue', 
    afunction: function(){...} 
} 
4

El código jQuery para determinar el selector es válido es de alrededor de 108 líneas de largo, así que no esperes para determinar si se trata de un selector válida o no en una declaración de expresiones regulares.

Su mejor opción es, probablemente, mirar lo que jQuery determina como un selector válido, y realizar una función que esencialmente verifica de la misma manera, pero devuelve si es válida o no.

https://github.com/jquery/jquery/blob/master/src/core.js#L80-188

0

esto no responde a su pregunta, pero creo que puede ser útil. No verifica si un argumento es un selector jQuery, sin embargo, prueba si el selector existe en el documento.

$.fn.inDom = function() { return $(document).find(this).length; }; 

Por cierto: no utilizo $(selector).length directamente, ya que regresará 1 si el argumento pasado es un HTMLNode.

Para obtener mejores efectos de interpretación:

$('foo').length // 0 
$('.foo').length // 0 
$('#foo').length // 0 
$('<foo>').length // 1 
$(document).find('foo').length // 0 
$(document).find('.foo').length // 0 
$(document).find('#foo').length // 0 
$(document).find('<foo>').length // 0 
+0

Útil de verdad :) Me gustaría agregar que arrojará un error si la cadena de entrada no es un selector. Y para ganar el concurso de nitpicking, realmente devolvería un booleano adecuado en lugar de la longitud. De esta manera: 'function selectorExists (selector) {try {return $ (document) .find (selector) .length! == 0; } catch (e) {return false; }} '... y no te encanta el formato de comentario de una sola línea;) – hashchange

26

Para ir directamente al grano:

  1. No, jQuery tiene ningún método para comprobar si un selector es válido.
  2. jQuery tiene muchos Regex 'para esto, es por eso que no puede encontrar uno en el código.
  3. No necesita escribir una gran Regex para esto, la respuesta es más simple como se muestra a continuación.

Entiendo su problema porque lo experimenté, hay casos en los que no tiene control del selector para dar a la función jQuery.

El problema no se describe lo suficiente es que si un selector no es válido jQuery arroja un error (es importante porque aquí está la respuesta).

Ejemplo utilizando jQuery v1.9.1:

$('##somewhere'); 

Se registra en la consola de la línea siguiente:

throw new Error("Syntax error, unrecognized expression: " + msg); 

que fuente es en la fila 4421 del archivo jquery.js no minified (y versión sin comprimir).

Así, en lugar de buscar un método interno de jQuery (que seguramente podría simplificar las cosas, pero no está disponible), sólo puede escuchar el error lanzado para establecer si el selector es válido:

function isValidSelector(selector) { 
    if (typeof(selector) !== 'string') { 
     return false; 
    } 
    try { 
     var $element = $(selector); 
    } catch(error) { 
     return false; 
    } 
    return true; 
} 

Usted también puede hacer que sea un plugin de jQuery:

jQuery.extend({ 
    isValidSelector: function(selector) { 
     if (typeof(selector) !== 'string') { 
      return false; 
     } 
     try { 
      var $element = $(selector); 
     } catch(error) { 
      return false; 
     } 
     return true; 
    } 
}); 

para ser utilizado de esta manera:

alert($.isValidSelector('#what?!?')); 

Saludos cordiales.

EDIT: añadido validación de tipo: el selector debe ser una cadena. De todos modos es una solución parcial, no devuelve falso para los selectores definidos como objetos de cadena var selector = new String('#@wrong-selector#!');, que no son de tipo primitivo.

+2

Exactamente lo que necesitaba. ¡Mil votaciones! – Ziggy

+0

¡Gracias por la explicación directa! –

+0

Lamentablemente, la prueba no es a prueba de balas. Puede pasar una cadena HTML sin procesar a jQuery, y la convertirá en un nodo y no arrojará una excepción. Entonces 'isValidSelector ("

")' devuelve verdadero, aunque no es un selector válido. – hashchange

Cuestiones relacionadas