12

Is it bad to tie events to ids that aren't on the page in certain circumstances (based on PHP)? Will it cause code errors and slowness, or will jQuery automatically ignore them?

Should I instead put something like the following on every element that might not be there?

if ( $('#element') ){
    $('#element').click(function(event) {}
}

My page setup is a certain edit box is not loaded under certain conditions to keep functions from being tried.. I set it up with a conditional php include because it's based on circumstances in the database that I don't really want to pass through to the front-end.

Right now all the js for the on page is in a single file with a number of functions.

Damon
  • 10,493
  • 16
  • 86
  • 144

2 Answers2

17

When jQuery selector doesn't return any elements, no events are being bound. So you're making no harm by not writing if statement.

This means that internally jQuery binds event handler to all matched elements. When there are none, no handler will get bound to any element. This means: you don't have to check element existence in your code.

Future reference

Whenever you're doing

if ( $('#element') ){
    $('#element').click(function(event) { /* blah blah */ });
}

you should rather save selector results

var result = $('#element');

// check number of elements (zero equals false, anything else equals true)
if (result.length) {
    result.click(function(event) {
        // blah blah
    });
}

result.length is same as result.size().

Binding event handlers to non existing elements

If your interface will generate new elements and you'd like them to have eevent handlers attached when they get added to DOM, then you should use delegate() function. There's also live() function but use the first one whenever possible, because it is a better alternative. There are numerous resources on the net why this is true. This Stackoverflow answer for instance.

Note: As of jQuery 1.7, .delegate() has been superseded by the .on() method. For earlier versions, however, it remains the most effective means to use event delegation.

See jQuery documentation.

Community
  • 1
  • 1
Robert Koritnik
  • 103,639
  • 52
  • 277
  • 404
  • So essentially I don't have to worry about which elements are present or not? – Damon Sep 21 '11 at 15:10
  • @Damon: **Exactly**! Don't worry at all. Just write your code as long as you don't make it dependant on certain non-existing elements. Example: Some element that is displayed on page is disabled and should get enabled when an element that is *not displayed* gets clicked. When UI process works that way than it's fine, but when such situation is not valid, you have to check your element existence... – Robert Koritnik Sep 21 '11 at 15:22
  • 1
    Note that for more recent versions of jQuery, the `.on()` method with a selector filter is preferred to `.delegate()`. – David G Feb 02 '15 at 17:59
  • @DavidG: Updating my old answer. – Robert Koritnik Feb 02 '15 at 18:08
  • @RobertKoritnik Resurrecting this... would it generally be a bad practice (performance wise) to have jQuery code operating on elements that would only sometimes be present? Though no events are bound to nonexistent elements, I imagine there's still some time spent looking for the elements. – Chris Ullyott Jun 21 '16 at 22:26
  • @Chris: What do you mean by *sometimes be present*? In DOM or visually? The case they're being added/removed to/from DOM and if that's not too frequent (in terms of computer speed) and there aren't huge amounts of those then you can easily attach event handlers to elements directly. Delegated event handling is basically a bit *slower* than direct one. It uses browser's event propagation (always happens) but it additionally has to check sub-element selector if it matches delegated event definition. So also consider how frequently your event is being handled when element is present. – Robert Koritnik Jun 29 '16 at 05:54
  • @RobertKoritnik thanks; I meant present in the DOM. As a performance consideration, I imagine it'd be best practice to avoid calling `$('.item')` and/or others if these elements will only rarely be present in the DOM. If needing to call many potentially nonexistent items, I bet it would be better to avoid even executing that code unless some previous condition were met. That way you don't have jQuery traversing the DOM on every pageload looking for objects it will almost always never find. – Chris Ullyott Jun 30 '16 at 16:35
  • @Chris That's why I said that you can only attach events when you create those elements (if they're created dynamically on the client). If they're (sometimes) created on the server, then you will have to call it on the client regardless. But you could contain these elements within a container with a specific ID. This would speed things up considerably when you'd call `$('.item', '#itemContainer')`. If container won't be present, no traversing will be done whatsoever but if it was only a subtree of the whole DOM will be traversed making things faster as well. – Robert Koritnik Jul 01 '16 at 14:15
3

$("selector") will always return a jquery object that has the list of elements that have matched your selector.

if($("#nonexistantelement")) { /* this always happens*/ }

Whatever is inside your if will always be true, because Objects are truthy. If you really wanted do that then you'd want to say something like:

if($("#nonexistantelement").length > 0) { /* this only happens if you have something */ }

That will tell you if you have actually matched to your elements. But there is no harm in just calling .click(function) on an empty jquery set. Because all jquery does is iterate over the elements matched by the selector and apply that listener. If there are no elements in the set, then it doesn't get applied, and as essentially a noop.

Now if you want to bind callbacks to elements that dont exist yet, then look into .live() and delegate()

J. Holmes
  • 18,466
  • 5
  • 47
  • 52