15

Does jQuery have a method to determine if an argument passed to function is a selector?

I am making a template for some jQuery plugins and I need to be able to check if the argument passed in is a jQuery selector. I want to allow for other data types and perform different methods based on what data type is passed. Detecting data types is easy, but selectors are just a string and can be constructed is many different ways.

My goal is to create plugins that are forgiving with what you pass in for the arguments and makes educated decisions about what to do with it. Take the jQuery UI plugins for example, in some plugins, lets say we pass a callback function in the argument place holder that is for a number for a speed, it still takes the callback and runs it and uses the default for speed. That's the kind of functionality I'm going for and selectors are a pretty unique case.

Has jQuery written a Regex for this? I couldn't find one in the code.

If not, I guess I'll just have to write a huge Regex for this?

3
  • why not pass actual jQuery objects? $('selector') should be easy enough to check for... Commented Jun 8, 2011 at 18:18
  • @jcinacio: thanks, but I am actually checking for that too. My goal is to create arguments that are pretty free with what you pass in. Commented Jun 8, 2011 at 18:25
  • $('selector') does not fit for the purpose, since it throws an error if it is not valid. Commented Jun 2, 2013 at 20:29

5 Answers 5

36

To go straight to the point:

  1. No, jQuery has no method to check if a selector is valid.
  2. jQuery has lots of Regex' for this, that's why you cannot find one in the code.
  3. You do not have to write a huge Regex for this, the answer is more simple as shown below.

I understand your problem because I experienced it, there are cases in which you're not in control of the selector to give to the jQuery function.

The problem not outlined enough is that if a selector is not valid jQuery throws an error (it is important because here is the answer).

Example using jQuery v1.9.1:

$('##somewhere'); 

It logs into the console the following line:

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

which source is at row 4421 of the jQuery.js file (non-minified and uncompressed version).

So, instead of looking for an inner method of jQuery (which could surely simplify things but is not available), you can just listen the error thrown to establish if the selector is valid:

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

You can also make it a jQuery plugin:

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

to be used this way:

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

Best regards.

EDIT: added type validation: the selector must be a string. Anyhow it is a partial solution, it does not return false for selectors defined as string objects var selector = new String('#@wrong-selector#!');, which are not a primitive type.

Sign up to request clarification or add additional context in comments.

4 Comments

Unfortunately, the test is not bullet-proof. You can pass a raw HTML string to jQuery, and it will turn it into a node and not throw an exception. So isValidSelector( "<p />" ) returns true, even though it is not a valid selector.
While I'm at it, the function fails to check if the input is a string - pass it a node or jQuery object, and isValidSelector( $( ".foo" ) ) returns true.
@hashchange you are right, but I assumed the task is not to check if the given selector matches something in the document (which jQuery already does through the .length property), but only checking if the selector is formally acceptable.
@hashchange thanks to your obvservation, I improved the function by checking the type of the selector.
5

Lots of strings can technically be a selector like $('blah') could select custom elements! There isn't any good way of knowing the intent of what to do with the argument passed to your function, so it's best to have a well defined structure like Gaby has commented.

Selector:

yourFunction({ selector: 'div' }); 

Or

yourFunction({ value: 'testing' }); 

Will take a different route in your code.

Without this technique the best you can do is just attempt for jQuery to find elements based on the selector, check with .length, if elements are found then assume the caller intended a jQuery selector. Another option could be just to document that a jQuery object must be passed i.e.:

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

Then for a different route you can do

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

3 Comments

"attempt for jQuery to find elements based on the selector, check with .length, if elements are found then assume the caller intended a jQuery selector" ---- that's pretty good.
@UpHelix did not asked to check if a selector matches something or what role has what it selects, but if it is valid according to the jQuery rules for a selector syntax.
@UpHelix "attempt for jQuery to find elements based on the selector, check with .length, if elements are found then assume the caller intended a jQuery selector" - bad idea, there are strings that when used as jquery selectors will throw an exception, just try something with "("
4

There can not be a regex for this, since the selectors are extensible and anyone could add any number of personal selectors (with custom defined symbols etc) ...

Perhaps you should try passing your arguments as a single object with named parameters.

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

Comments

4

The jQuery code for determining the selector is valid is about 108 lines long, so don't expect to determine if it's a valid selector or not in one RegEx statement.

Your best bet is probably to look at what jQuery determines to be a valid selector, and make a function that essentially checks the same way, but returns whether it's valid or not.

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

Comments

0

This does not answer your question, but i think it can be helpful. It checks not if an argument is a jQuery selector, however it tests whether the selector exists in the document.

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

BTW: I dont use $(selector).length directly, since it will return 1 if the passed argument is an HTMLNode.

For better interpretation purposes:

$('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 

1 Comment

Helpful indeed :) I'd just like to add that it will throw an error if the input string is not a selector. And for winning the nitpicking contest, I'd actually return a proper boolean instead of the length. Like this: function selectorExists( selector ) { try { return $( document ).find( selector ).length !== 0; } catch ( e ) { return false; } } ... and don't you just love the single-line comment formatting ;)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.