KjetilNordin KjetilNordin - 3 months ago 86
jQuery Question

Why is my JQuery selector returning a n.fn.init[0], and what is it?

I have a set of dynamically generated checkboxes, where each of them has a

data-id
attribute corresponding to a database integer id. When i populate my html-form with an object to edit, there is a list of integers representing which checkboxes should be checked. The checkboxes are wrapped in a
div
with class
checkbox-wrapper
.

So html looks like this:

<div class="checkbox-wrapper">
<input type="checkbox" id="checkbox1" data-id="1">
<label for="checkbox1">Checkbox 1</label>
</div>
<div class="checkbox-wrapper">
<input type="checkbox" id="checkbox2" data-id="2">
<label for="checkbox2">Checkbox 2</label>
</div>
<div class="checkbox-wrapper">
<input type="checkbox" id="checkbox3" data-id="99">
<label for="checkbox3">Checkbox 99</label>
</div>


Note that the id runs on auto increment index numbers, while data-id might have a different id value. I want to select them by data-id.

Now, using JQuery, I know I can select the relevant checkboxes like this:

$(".checkbox-wrapper>input[data-id='99']");
$(".checkbox-wrapper>input[data-id='1']");


This works in my console, in chrome, and it returns the relevant DOM-element. Likewise, this below, sets the checkboxes to checked:

$(".checkbox-wrapper>input[data-id='99']").prop("checked", "checked");
$(".checkbox-wrapper>input[data-id='1']").prop("checked", "checked");


However, if I iterate through a list of integers in my javascript code (not directly in the console), and log the returned elements, based on the id values, I get some weird results:

var ids = [1,2]
$.each(ids, function(index, myID){
console.log($(".checkbox-wrapper>input[data-id='"+myID+"']"));
$(".checkbox-wrapper>input[data-id='"+myID+"']").prop("checked", "checked");
});


First of all, no checkboxes are checked. Second, my console prints strange results:

n.fn.init[0]
context: document
length: 0
prevObject: n.fn.init[1]
selector: ".checkbox-wrapper>input[data-id='1']"
__proto__: n[0]

n.fn.init[0]
context: document
length: 0
prevObject: n.fn.init[1]
selector: ".checkbox-wrapper>input[data-id='2']"
__proto__: n[0]


The printed selector Strings seems perfect. The exact same selectors returns the DOM-elements, when written directly into the chrome console. Then they return objects like this:

[<input type=​"checkbox" id=​"checkbox1" data-id=​"1">​]


What is the n.fn.init[0], and why it is returned? Why are my two seemingly identical JQuery functions returning different things?

Answer

Another approach(Inside of $function to asure that the each is executed on document ready):

var ids = [1,2];
$(function(){
  $('.checkbox-wrapper>input[type="checkbox"]').each(function(i,item){
    if(ids.indexOf($(item).data('id')) > -1){
       $(item).prop("checked", "checked");
    }
  });
});

Working fiddle: https://jsfiddle.net/robertrozas/w5uda72v/

What is the n.fn.init[0], and why it is returned? Why are my two seemingly identical JQuery functions returning different things?

Answer: It seems that your elements are not in the DOM yet, when you are trying to find them. As @Rory McCrossan pointed out, the length:0 means that it doesn't find any element based on your search criteria.

About n.fn.init[0], lets look at the core of the Jquery Library:

var jQuery = function( selector, context ) {
   return new jQuery.fn.init( selector, context );
};

Looks familiar, right?, now in a minified version of jquery, this should looks like:

var n = function( selector, context ) {
   return new n.fn.init( selector, context );
};

So when you use a selector you are creating an instance of the jquery function; when found an element based on the selector criteria it returns the matched elements; when the criteria does not match anything it returns the prototype object of the function.