4

I am using AnythingSlider jQuery plugin which dynamically reads the hash in the URL and selects an item on a page via jQuery. The problem is the end user can break the plugin if they get to http://mydomain.com/#!demos/slider.

Is there a way to test if a selector is valid instead of letting jQuery crashing (built in function or regex)? See this jsFiddle example that tries to do $('#!demos/slider') and it crashes: http://jsfiddle.net/PvY2b/

$('#!demos/slider') <= Uncaught Error: Syntax error, unrecognized expression: #!demo/slider
PhearOfRayne
  • 4,990
  • 3
  • 31
  • 44
TruMan1
  • 33,665
  • 59
  • 184
  • 335
  • Can't you just catch the error yourself and display an appropriate error message to the user? – Matt Burland Dec 20 '12 at 19:46
  • I did a try/catch but seems like a lazy hack. Is there a built in function in jQuery or sizzle to test before letting it crash? Maybe RegEx? – TruMan1 Dec 20 '12 at 19:47
  • 2
    First time I've seen a try/catch referred to as a "lazy hack" – Forty-Two Dec 20 '12 at 19:49
  • @TruMan1: Why's it a lazy hack? Seems this is exactly what `exceptions` are for. Why re-invent the wheel? jQuery is already testing it for you and the way it lets you know there's a problem is by throwing an exception. – Matt Burland Dec 20 '12 at 19:51
  • You should take an if-statement over a try/catch any day.. or it is a lazy hack. – TruMan1 Dec 20 '12 at 19:53
  • @TruMan1: That is a awfully sweeping generalization to make. There are cases where an if statement is the better choice, for example it's often better to check for the existence of a file before trying to open it, but I don't think this is one of those. jQuery should fail fast and you shouldn't reinvent the wheel by checking what jQuery is already going to check itself. – Matt Burland Dec 20 '12 at 20:33
  • The latest version of AnythingSlider will now ignore the hash bang completely if you set the `hashTags` option to `false`. Sorry about that! – Mottie Dec 23 '12 at 04:50

3 Answers3

5

ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".").

From: Basic HTML data types

Therefore something like this might work:

if (/^[A-Za-z][A-Za-z0-9\-_:\.]*$/.test(selector)) {
    // $('#' + selector)...
}

Or simply escape it:

selector = selector.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1');
jayarjo
  • 16,124
  • 24
  • 94
  • 138
1

It may be easier just to wrap this block into try-catch, like here:

try { 
  $('#!demo/pages') 
} catch(e) { 
  alert('Your selector is invalid'); 
}

It's not a lazy hack: it's quite a common approach when dealing with some external components that you cannot control directly.

raina77ow
  • 103,633
  • 15
  • 192
  • 229
0

As found in a previous answer: How do I extend jQuery's selector engine to warn me when a selector is not found?

You have to extend over jQuery init:

var oldInit = $.fn.init; // cache it

$.fn.init = function(selector, context, rootjQuery) {

    var result = new oldInit(selector, context, rootjQuery);

    if (result.length === 0)
        console.info("jQuery call has no elements!", arguments);
    return result;
};

It will still throw errors for incorrectly syntaxed selectors, but lets say you have a correct one $('#test'), if no #test exists, it will at least warn you. Good for development, to help with typos etc

I've done this with .on() and other things, it's very powerful.

Community
  • 1
  • 1
Mark Pieszak - Trilon.io
  • 61,391
  • 14
  • 82
  • 96