Determine if a string is a valid jQuery selector?

2020-06-03 06:58发布

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?

5条回答
放我归山
2楼-- · 2020-06-03 07:27

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

查看更多
叛逆
3楼-- · 2020-06-03 07:28

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) { .... }
查看更多
兄弟一词,经得起流年.
4楼-- · 2020-06-03 07:33

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
查看更多
祖国的老花朵
5楼-- · 2020-06-03 07: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.

查看更多
戒情不戒烟
6楼-- · 2020-06-03 07:38

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(){...}
}
查看更多
登录 后发表回答