jQuery throws an error that element.find() is not a function - javascript

I have written a small JS to iterate through a set of matched elements and perform some task on each of them.
Here is the code:
var eachProduct = $(".item");
eachProduct.each(function(index, element){
var eachProductContent = element.find(".product-meta").clone();
});
When I console log element it outputs properly and the exact objects. Why should jquery throw this error?

because element is a dom element not a jQuery object
var eachProductContent = $(element).find(".product-meta").clone();
Inside the each() handler you will get the dom element reference as the second parameter, not a jQuery object reference. So if you want to access any jQuery methods on the element then you need to get the elements jQuery wrapper object.

You are calling .find() on a plain JS object, But that function belongs to Jquery object
var eachProductContent = $(element).find(".product-meta").clone();
You can convert it to a jquery object by wrapping it inside $(). And in order to avoid this kind of discrepancies you can simply use $(this) reference instead of using other.

Use $(this) for current Element
var eachProductContent = $(this).find(".product-meta").clone();

you should change "element" to "this":
var eachProduct = $(".item");
eachProduct.each(function(index, element){
var eachProductContent = $(this).find(".product-meta").clone();
});

Related

Correct jQuery Syntax for accessing text of array in one line

I am trying to access the text of the first "th" element of the first element of "rows" with jQuery and would like to do so in one line
var currentStation = $(rows[0]).find("th")[0].text();
What would be the correct syntax to do so?
I am able to get the "th" element, but as soon as I try to access the text I get error messages.
I already tried numerous variations of different brackets combinations, but each one threw me errors.
The issue is that your [0] on find("th") takes the HTML element out of the jQuery object. The easiest way to do this is to either use innerText instead of text:
var currentStation = $(rows[0]).find("th")[0].innerText;
Or don't use [0], rather first:
var currentStation = $(rows[0]).find("th:first").text();
(Or another first):
var currentStation = $(rows[0]).find("th").first().text();
text() is a method on jQuery objects.
You are extracting the DOM element object from the jQuery object and then trying to call text() on the DOM element object.
Use the :first selector instead (note this is a jQuery selector and not a CSS selector)
const $firstRow = $(rows[0]);
const $firstTh = $firstRow.find("th:first");
var currentStation = $firstTh.text();

Simple Example : Setting attributes by iterating

$(function(){
var els = [];
var m = $("#container");
m.attr({"style" : "width:50%;"});
$(".grid").each(function(e){
els.push(this);
});
var n = els[3];
n.attr({"style" : "width:50%;"}) //error
});
Hello, I am fairly new to DOM manipulating. I am wondering why the JQuery above returns [Object][Object] for var m, but returns [Object][HTMLDivElement] for var n.
Because of this behavior I cannot use statements such as n.attr(args).
TypeError: n.attr is not a function
Ultimately, I would like to store each .grid element in an array, and iterate over them, setting attributes as I go.
To be more exact, I have a 6x3 grid of div elements, and each time the page loads, they are given a random animation-duration because they are animated to fade in and out of view.
Why can I not use n.attr()?
That's because this inside the .each() loop is the actual DOM element, not the jQuery object. If you want the items in your array to be jQuery objects you need to wrap them in one yourself:
els.push($(this));
Alternatively, you can just wrap the DOM element at the time you are accessing it:
var n = $(els[3]);
From jQuery .each():
More importantly, the callback is fired in the context of the current
DOM element, so the keyword this refers to the element.
and
To access a jQuery object instead of the regular DOM element, use
$( this )
A DOM element is not a jQuery object. n is an array of DOM elements, not jQuery objects which have a DOM element as a property. You can achieve the same result using DOM methods without jQuery
onload = function() {
var m = document.getElementById("container");
m.style.width = "50%";
var els = document.querySelectorAll(".grid");
var n = els[3];
n.style.width = "50%";
}

Value is undefined when element is obtained with jQuery

Below is the code where I obtain my input element with jQuery:
var txt = $(tableRow).find('input:text');
if (txt.value == null) {
//TO DO code
}
and here's how I do it with pure JavaScript
var txt = document.getElementById('txtAge');
if (txt.value == null) {
//TO DO code
}
With the first way the value of the txt is undefined. But with the second way the value is what's inside the input element. Now more interesting is, on the bottom-right pane of the Mozilla Firebug if I scroll down to the "value" of the txt I can see it there, both ways.
I know I can simply say $(txt).val(), but I also want to understand why I can't access the value of an element if it's been selected by jQuery. Isn't jQuery just a library of JavaScript functions?
.value is not part of the jquery api. You should use .val() instead:
var txt = $(tableRow).find('input:text');
if (txt.val() == "") {
//TO DO code
}
A dom object and a jquery dom object are not exactly the same. In fact, you can open the Developer tools (in webkit) or Firebug (Firefox) to check what are they in the inside. Jquery holds more information (actually, it contains an instance of the dom that it's representing). So, if you wanted to use .value, you need to call the "generic" dom object from the jquery object, and then use .value.
jQuery selects DOM elements using various native and non-native techniques and places them all in it’s own array-like instance that also wraps them in their own API. jQuery doesn’t "extend" native DOM properties or methods, so you will need to target the DOM node to do that.
Think of it like this:
var node = document.getElementById('txtAge'); // the DOM node
var txt = $('#txtAge'); // the same node wrapped in a jQuery object/API
Since jQuery object holds an array-like collection of DOM nodes, so you can access the first element by doing:
txt[0] // same as node
But it’s generally recommended that you use the .get() method:
txt.get(0)
Another more jQuery-way to do what you want is to iterate through a jQuery collection using .each():
$(tableRow).find('input:text').each(function() {
// "this" in the each callback is the DOM node
if ( this.value == null ) {
// Do something
}
});
.find() will return an arry-like object. If you're sure that there's one, and one only, element matching your query, you could do
var txt = $(tableRow).find('input:text')[0].value;
That's not very jQuery-like, so to speak, more like a mismatch of both jQuery and DOM methods, but it'll get what you want. Also, since you show, as a DOM example, var txt = document.getElementById('txtAge');, this could be rewritten in jQuery as
var txt = $('#txtAge')[0];
var x = $(tableRow).find('input:text');
It's an jquery object .
`x.value`
There is no property value in jquery object . So it returns undefined.
x.val() is a method you can use for get the value of an element.

jQuery syntax not setting object property

My jQuery question I beleive is pretty simple, which is driving me insane that I can't get it.
I have an object with a property "content", I want to be able to take that object, manipulate the property "content" with jQuery and then overwrite the value with the new value jQuery creates.
Example:
o.content = "<div><span>hello</span></div>";
$('div', o.content).addClass('test');
At this point I want o.content to be equal to <div class='test'><span>hello</span></div>
I can not for the life of me figure out the syntax. Any help is really appreciated.
This will give you a string <div class="test"><span>hello</span></div> if this is what you want:
$(o.content).addClass('test').wrap('<div>').parent().html();
Parse the html in o.content, add the class, append the parsed html to a new <div>, and get the html of the new div:
o.content = "<div><span>hello</span></div>";
var el = $(o.content).addClass('test');
o.content = $("<div>").append(el).html();
Edit: This assumes you want o.content to still contain a string, rather than a jQuery object. In that case, it's simpler:
o.content = $(o.content).addClass('test');
from the docs of the jquery function, context must be
A DOM Element, Document, or jQuery to use as context
Your context (o.content) is a string. Also, the jQuery function is not able to select the entire context, it can only select elements in that context.
Try this instead:
// make o.content a jquery element, not a string
o.content = $("<div><span>hello</span></div>");
// select on something inside the context (inside the div), not the div itself
$('span', o.content).addClass('test');
http://jsfiddle.net/JfW4Q/
I don't think you can lookup an element from a string like that.. I would rather do it like below,
var content = "<span>hello</span>";
content = $('<div/>', {class: 'test'}).html(content)
DEMO: http://jsfiddle.net/k4e5z/
You want the following
o.content = "<div><span>hello</span></div>";
// Create a jQuery object you can call addClass on
var docFragment = $(o.content);
docFragment.addClass('test');
// Since there's no outerHTML in jQuery, append it to another node
var wrapper = $('div');
docFragment.appendTo(wrapper);
// The HTML of the wrapper is the outerHTML of docFragment
console.log(wrapper.html()); // outputs <div class='test'><span>hello</span></div>
Why not do it all in one line:
var o = {};
o.content = $( "<div></div>" ) // create element
.addClass('test') // add class
.html( '<span>hello</span>' ); // append content
Fiddle: http://jsfiddle.net/kboucher/eQmar/
o.content = $("<div><span>hello</span></div>");
o.content.addClass('test');
o.content is a jQuery object in this example, as opposed to just a string. Here's a demo on jsfiddle: http://jsfiddle.net/cvbsm/1/

Retrieving an element by array index in jQuery vs the each() function

I was writing a "pluginable" function when I noticed the following behavior (tested in FF 3.5.9 with Firebug 1.5.3).
$.fn.computerMove = function () {
var board = $(this);
var emptySquares = board.find('div.clickable');
var randPosition = Math.floor(Math.random() * emptySquares.length);
emptySquares.each(function (index) {
if (index === randPosition) {
// logs a jQuery object
console.log($(this));
}
});
target = emptySquares[randPosition];
// logs a non-jQuery object
console.log(target);
// throws error: attr() not a function for target
board.placeMark({'position' : target.attr('id')});
}
I noticed the problem when the script threw an error at target.attr('id') (attr not a function). When I checked the log, I noticed that the output (in Firebug) for target was:
<div style="width: 97px; height: 97px;" class="square clickable" id="8"></div>
If I output $(target), or $(this) from the each() function, I get a nice jQuery object:
[ div#8.square ]
Now here comes my question: why does this happen, considering that find() seems to return an array of jQuery objects? Why do I have to do $() to target all over again?
[div#0.square, div#1.square, div#2.square, div#3.square, div#4.square, div#5.square, div#6.square, div#7.square, div#8.square]
Just a curiosity :).
.find() returns not an array of jQuery objects, but one jQuery object containing an array of DOM elements (a jQuery object, at it's core, is a wrapper around a DOM element array).
When you're iterating through, each element you're on is a DOM element. So, it needs to be wrapped in $(this) to become jQuery object and have access to those methods.
Also as a side note: The id attribute can't begin with a number, since it's invalid HTML you may or may not experience strange behavior, especially cross-browser (this rule applies for any invalid HTML).
No, the find method doesn't return an array of jQuery objects. You are creating a jQuery object for each element here:
console.log($(this));
If you log the value without creating a jQuery object from it:
console.log(this);
you will see that it's an element, not a jQuery object.
When you access the jQuery object as an array, you get an element. If you want a jQuery object you have to create one from the element.

Categories

Resources