tags:

views:

82

answers:

5

After studying the docs for a while, I came up with my first jQuery script. It's a simple Form Focus script. Just want to make sure I've got this right.

I couldn't find anything that spoke of "conditional statements" with jQuery, so I assume you just use standard JavaScript if / else if statments.

To test if the #id exists, the jQuery docs explained I should use .length.

$(document).ready( function() {
    if ($('#one').length) {
     $('#one').focus();
    }
    else if ($('#two').length ) {
     $('#two').focus();
    }
    else {
     return false; // is this even necessary?
    }
});

EDIT:

It is possible that #one and #two will exist on the same page, so I want to target #one first.

+1  A: 

Your script is accurate, although there's no need, as you anticipated, to return anything in your else clause (or even to have one)

David Hedlund
+1  A: 

Depending on how your interface is displayed... for example, will elements one and two exist at the same time, if not, you can do:

$(document).ready( function() {
  $('#one').focus();
  $('#two').focus();
}

If they will exist together on the same page, then this is fine:

$(document).ready( function() {
  if ($('#one').length) {
    $('#one').focus();
  }
  else {
    $('#two').focus();
  }
}

If no elements were returned, the .focus() won't actually fail or anything, so you're free to just do it in 1 line without the conditional.

Also, the return false bit isn't necessary.

Langdon
Yes, `#one` and `#two` will exist at the same time.
Jeff
+3  A: 

you don't need to test length. if the wrapped set is empty the focus function is called for nothing. if only #one or #two will exist, then the following works fine:

$(function() {  // shorthand for $(document).ready()
       $('#one, #two').focus();
});
Scott Evernden
Great solution Scott. I was thinking there was a better way to do this. Obviously if they both exist this would cause a problem.
Doug Neiner
Isn't $(document).ready(function() {}) the preferred jQuery way of doing it since $(function()) just calleds the document ready handler? It's certainly more communicative of the intent of the script.
Hooray Im Helping
@Hooray Im Helping - I think once you are used to the $(function(){...}); syntax for setting up code for the ready handler it helps clear the clutter.
scunliffe
Your code is almost the same as @duckyflip but you need to add `.filter(:first)` since jeff wants `#one` selected if `#one` and `#two` exist together: `$('#one, #two').filter(':first').focus();`
Doug Neiner
A: 

What you did is functionally correct. As you advance with jQuery though, you will not want to do multiple lookups. This would be a better way of writing it:

$(document).ready( function() {
    var $one = $("#one"), $two = $("#two");
    if ( $one.length ) $one.focus();
    else if ( $two.length ) $two.focus();
});

Every time you use $("#id") it performs a lookup. If you can cache it in a variable the first time like var $one = $("#one") you can save times on lookups later. The $ sign in my variable names is completely arbitrary, but it helps you remember which variables have jQuery wrapped objects.

Doug Neiner
jQuery uses selector cache internally, though
David Hedlund
@d: Does that mean setting up the `vars` is not important in this case? I was actually just setting up my script this way, but I'd like to hear more about "the selector cache".
Jeff
I'll let @d answer, but it might be a good idea anyway. If you don't then you will be more likely to do $("#one .some_child") later than just using $one.find('.some_child'). I am interested to hear more about the internal cache as well.
Doug Neiner
I just chatted with Codey Lindey on the jQuery core team. There is no internal selector cache in jQuery. Each time you use the `jQuery()` or `$()` functions, a new jQuery object is created and a new lookup is performed. By caching the jQuery object in a variable, you can really speed up your code.
Doug Neiner
Thanks dcneiner!
Jeff
+1  A: 

Your logic is generally correct, although when using jQuery you can really cut the amount of cheks & detections you'd need with standard Javascript

  • Calling a method or property on the jQuery object will not return an error even if the object (e.g $("#one") ) was not found

  • You can fetch multiple DOM Elements at once (e.g $("#one,#two") ) and you can also call a method on all of these objects at once `

  • There's no need to return anything at the end of your $(document).load(function(){...})

So having all these points in ming you can update your script like so:

$(document).ready(function() {
  $('#one,#two').focus();
});

EDIT:

Since you indicated you want to select #one first, in the case when both #one and #two exist on the same page, all you have to do is put the #one reference at the end of the list and it will be the one that always gets selected if it exists.

$('#two,#one').focus();
duckyflip
Is this valid even if `#one` and `#two` will exist at the same time?
Jeff
Jeff, check my amendments
duckyflip
Jeff, this is not true as of the most recent versions of jQuery. Selectors are always returned in document order, so whichever is last in the DOM will be selected.
Doug Neiner
@duckyflip: When I first wrote the script, I noticed that. I decided to use `if` / `else if` because I thought, "jQuery is going to first focus on `#one` if it exists, then it will see that `#two` exists and focus on that, and so on...
Jeff
Just add a little bit to your selector: `$('#one, #two').filter(':first').focus();` and it will work.
Doug Neiner
Both the $('#one, #two').filter(':first') and the $('#two, #one') approaches are dependent on properties of the DOM at hand. if #one is the last element in the DOM, the :first solution will fail, if #one is first in the DOM, the '#two, #one' solution will fail
David Hedlund
@d: Could you post a solution?
Jeff