In Javascript, arrays should have methods pop and shift.
However, JQuery objects seem to be missing these methods:
$('div').shift(); // Error, shift is undefined
$('div').pop(); // Error, pop is undefined
$('div').splice(); // Splice is OK actually
I wonder why these functions are missing - after all, the jquery object is just an array.
What's the easiest way of performing pop and shift functions on jquery objects?
They're missing because a jQuery object isn't an Array.
(function( $ ) {
$.fn.pop = function() {
var top = this.get(-1);
this.splice(this.length-1,1);
return top;
};
$.fn.shift = function() {
var bottom = this.get(0);
this.splice(0,1);
return bottom;
};
})( jQuery );
EDIT: .slice() doesn't modify the original object. Fixed to use .splice() instead.
Your safest bet would be to just use:
[].pop.call($('div'))
[].shift.call($('div'))
If you want to use the exact syntax in your example you can augment jQuery.fn:
jQuery.fn.pop = [].pop;
jQuery.fn.shift = [].shift;
The latter works well for the mutator methods. It'll work for the accessor and iteration methods too, but be advised that many of those returns a pure array that you'd have to rewrap. Be aware that jQuery has is own version of some of these (e.g. .map, .slice, .filter, etc.) that you probably don't want to overwrite.
This seemed to work for me:
var divArray = $('div').toArray();
var elem = $( divArray.shift() );
.toArray() return the DOM elements as a JavaScript Array, which can be used as intended. Then all you need to do is convert it back into a jQuery object.
I realize this answer has already been selected, but here's another alternative that isn't too hard to remember, in case you don't want to worry about having to install plugins all the time.
$('div > :first').detach(); // shift
$('div > :last').detach(); // pop
By the way, I realize there are performance issues with using :last selector as part of your primary selector so you may want to consider doing something like this for pop:
$('div').children(':last').detach();
var $firstDiv = $( $('div').splice(0, 1) );
Another way using jQuery 1.9.1+:
$('div').first().remove();
$('div').last().remove();
Related
Hi I was just wondering if building an array in javascript was possible using a function like so. I have a variable that is getting the margins of a series of elements using $(ele).css('margin');. This returns a string of 0px 0px 0px 0px where I only want the left property to check whether it's been animated -= left.
I can do a similar function but I know there must be a better way. Here's my example:
var marginsLeft = new array();
$(ele).each(function(i){
var r = $(i).css('margin').split(" ");
marginsLeft[i]=r[3];
});
I'm not entirely sure how to simplify this, but I'm sure it's possible :) thanks in advance.
You can use $.map:
var marginsLeft = $(ele).map(function() {
return parseInt($(this).css('margin-left'), 10);
}).get();
Update: as pointed out by #undefined, if you want a regular array you should also call .get on the result. Otherwise, you'll have a jQuery wrapped array. It is array-like, so it can be used as an array in many contexts, but not in others (in particular, it may not have the native Array methods).
Also, to convert the result to a number you can use parseInt (which will ignore the letters and use only the digits), remembering to explicitate the base (10).
Have a look at the docs for .each(): The first parameter of the callback function is the index, the array element (DOM node) can be accessed either as the second parameter or the this value. So, use
var marginsLeft = []; // literal shortcut for "new Array()"
$(ele).each(function(i, el){
marginsLeft[i] = $(el).css('margin-left');
});
You also might have a look at the .map() method, but that returns a jQuery wrapper object instead of an array.
you could use css('margin-left') instead
I've been working on my own personal JavaScript library for a while now, and it works fine. But I've been wondering about the jQuery return object.
Lets say you have a few divs in your DOM and you select them with $("div") jquery actually returns the selected nodes (as an object/array?) in the console log and you can mouse-over them to see where they are in the documents.
My object actually returns the entire object itself, so if you call kj("div") (Where kj is my object name) it shows up like this in the console log:
> kj
> elements: Array[10]
> length : 10
> more stuff
My question is, how can I make it return something like jQuery?
Thanks in advance.
I think what you are looking for is that in jQuery the Array of elements is the primary object, the methods and other information is connected to that array as properties.
function $$(tagname){
var x = document.getElementsByTagName( tagname );
x.moreStuff = true;
return x;
}
var d = $$('div');
because typeof Array === 'object' you can arbitrarily attach methods and properties to an array.
JQuery hooks up it's own references to an object whick in turn reference to things in the dom. Those references are a little more complex than just the "contents of the html" as there are events attached. JQuery also has very efficient "Selectors" that iterate over the dom and build those references.
I have to say I agree with the Scrum Meister. JQuery's an accepted standard across even Microsoft development these days (WOOHOO!). Why not use it?
Open you console on this page and do console.log($('#custom-header')) and you will get the result. I think that, jquery will return an object with following methods and property which we use on them like hide() and show(). I think it is better to use jquery then to create another library.
>>> console.log($('#custom-header'))
[div#custom-header]
0
div#custom-header
context
Document what-is-the-jquery-returned-object-exactly
jquery
"1.4.4"
length
1
selector
"#custom-header"
init
function()
TextAreaResizer
function()
_toggle
function()
add
function()
addClass
function()
addSpinner
function()
addSpinnerAfter
function()
after
function()
ajaxComplete
function()
ajaxError
function()
ajaxSend
function()
ajaxStart
function()
ajaxStop
function()
.......
.......
.......
I know this has been asked and answered a couple times already, but I'm still confused about how to reference the current object when iterating over a jQuery array. For example, the following code gives me the error TypeError: genH3Array[i].next is not a function. What is the right way to reference the current array object?
var genH3Array = $('#Generation_II').parent();
genH3Array.push($('#Generation_III').parent());;
genH3Array.push($('#Generation_IV').parent())
$.each(genH3Array, function(i, value)
{
if(genH3Array[i].next().attr("align") == "center")
{ genH3Array[i].next().next().next().insertBefore(heading.next())
}
genH3Array[i].next().next().insertBefore(heading.next())
genH3Array[i].next().insertBefore(heading.next())
})
EDIT: Thanks for all your help, everyone. I know this was probably a cinch for most of you, but it was a major headache for me. The corrected code is below:
var genH3Array = $('#Generation_II,#Generation_III,#Generation_IV').parent();
$.each(genH3Array, function(i, value)
{
console.log($(this).next());
if($(this).next().attr("align") == "center")
{
$(this).next().next().next().insertBefore(pokemonHeader.next())
}
$(this).next().next().insertBefore(pokemonHeader.next())
$(this).next().insertBefore(pokemonHeader.next())
$(this).insertBefore(pokemonHeader.next())
})
This part:
var genH3Array = $('#Generation_II').parent();
genH3Array.push($('#Generation_III').parent());
genH3Array.push($('#Generation_IV').parent());
...isn't really the way to use .push() against a jQuery object. When you .push() a value in, it should be a DOM element. Not a jQuery object.
You could simplify that entire bit like this:
var genH3Array = $('#Generation_II,#Generation_III,#Generation_IV').parent();
Now you'll have the .parent() of all three in the object.
Not entirely sure what the each is supposed to do, but it seems like you're trying to take the next three elements of each one, and insert them after some heading element.
$.each(genH3Array, function(i, value) {
if($(this).next().attr("align") == "center") {
heading.after( $(this).nextUntil('sometarget:last') );
}
heading.after( $(this).nextUntil('sometarget') );
});
I really don't know if this is what you want. It's a little hard to tell.
Both value and this point to the current item in the iteration, but that isn't your problem. Your problem is that the item returned by [] on a jQuery object isn't a jQuery object. You could do this:
$(genH3Array[i]).next()
Adding to what #patrick dw said: once you get the right selector, you can use the following syntax:
var getH3Array = ('#Generation_II,#Generation_III,#Generation_IV').parent().each(function() {
$(this); // this references the dom element matched, so:
if($(this).next().attr("align") == "center") {
// do something here
}
});
I think what you want is
var array = $("#c1, #c2, #c3").parent();
$.each(array, function(){
console.log($(this).next());
});
In $.each callback, the this variable point to the current element. If you are iterating through a jquery array like what you have, it will be iterating through the dom elements not jQuery objects, so you need to get the jQuery objects corresponding to them by using $(this).
jQuery.each
I'm trying to pass "this" from a clicked span to a jQuery function that can then execute jQuery on that clicked element's first child. Can't seem to get it right...
<p onclick="toggleSection($(this));"><span class="redClass"></span></p>
Javascript:
function toggleSection(element) {
element.toggleClass("redClass");
}
How do I reference the :first-child of element?
If you want to apply a selector to the context provided by an existing jQuery set, try the find() function:
element.find(">:first-child").toggleClass("redClass");
Jørn Schou-Rode noted that you probably only want to find the first direct descendant of the context element, hence the child selector (>). He also points out that you could just as well use the children() function, which is very similar to find() but only searches one level deep in the hierarchy (which is all you need...):
element.children(":first").toggleClass("redClass");
Use the children function with the :first selector to get the single first child of element:
element.children(":first").toggleClass("redClass");
I've added jsperf test to see the speed difference for different approaches to get the first child (total 1000+ children)
given, notif = $('#foo')
jQuery ways:
$(":first-child", notif) - 4,304 ops/sec - fastest
notif.children(":first") - 653 ops/sec - 85% slower
notif.children()[0] - 1,416 ops/sec - 67% slower
Native ways:
JavaScript native' ele.firstChild - 4,934,323 ops/sec (all the above approaches are 100% slower compared to firstChild)
Native DOM ele from jQery: notif[0].firstChild - 4,913,658 ops/sec
So, first 3 jQuery approaches are not recommended, at least for first-child (I doubt that would be the case with many other too). If you have a jQuery object and need to get the first-child, then get the native DOM element from the jQuery object, using array reference [0] (recommended) or .get(0) and use the ele.firstChild. This gives the same identical results as regular JavaScript usage.
all tests are done in Chrome Canary build v15.0.854.0
element.children().first();
Find all children and get first of them.
you can use DOM
$(this).children().first()
// is equivalent to
$(this.firstChild)
Have you tried
$(":first-child", element).toggleClass("redClass");
I think you want to set your element as a context for your search. There might be a better way to do this which some other jQuery guru will hop in here and throw out at you :)
I've just written a plugin which uses .firstElementChild if possible, and falls back to iterating over each individual node if necessary:
(function ($) {
var useElementChild = ('firstElementChild' in document.createElement('div'));
$.fn.firstChild = function () {
return this.map(function() {
if (useElementChild) {
return this.firstElementChild;
} else {
var node = this.firstChild;
while (node) {
if (node.type === 1) {
break;
}
node = node.nextSibling;
}
return node;
}
});
};
})(jQuery);
It's not as fast as a pure DOM solution, but in jsperf tests under Chrome 24 it was a couple of orders of magnitude faster than any other jQuery selector-based method.
please use it like this
first thing give a class name to tag p like "myp"
then on use the following code
$(document).ready(function() {
$(".myp").click(function() {
$(this).children(":first").toggleClass("classname"); // this will access the span.
})
})
This can be done with a simple magic like this:
$(":first-child", element).toggleClass("redClass");
Reference: http://www.snoopcode.com/jquery/jquery-first-child-selector
i am using
$('.txt').first().css('display', 'none');
If you want immediate first child you need
$(element).first();
If you want particular first element in the dom from your element then use below
var spanElement = $(elementId).find(".redClass :first");
$(spanElement).addClass("yourClassHere");
try out : http://jsfiddle.net/vgGbc/2/
Consider this:
var i=$('<img src="/path/to/imgI.png"/>');
var j=$('<img src="/path/to/imgJ.png"/>');
$([i,j]).css('cursor','hand');
The cursor is not changed however and I don't know why..
When I do it separately, it works.
Thanks.
The array is of two jQuery objects when what you require is the DOM elements within those jQuery objects. This will work:
var i=$('<img src="/path/to/imgI.png"/>')[0]; // <= Notice [0]
var j=$('<img src="/path/to/imgJ.png"/>')[0];
$([i,j]).css('cursor','pointer');
Alternatively, (using add())
var i=$('<img src="/path/to/imgI.png"/>');
var j=$('<img src="/path/to/imgJ.png"/>');
$(i).add(j).css('cursor','pointer');
EDIT: Also, use cursor:pointer; instead of cursor:hand;
Are you sure your problems isn't browser specific? That particular css property is tricky, it requires the property be set two different ways to work in IE and Firefox.
I'd recommend using a class in the img tag to specify the hand property. Then you can specify both rules and get what you are looking for.
Would make more sense to put selectors in the array:
var i = $('<img src="/path/to/imgI.png"/>').attr('id','i');
var j = $('<img src="/path/to/imgJ.png"/>').attr('id','j');
$( ['#i', '#j'] ).css('cursor','hand');
The correct cursor property is "pointer" not "hand", which is an IE only extension no longer required for anything but IE 5.5 and lower - i.e. very rarely.
You can use jQuery method to turn the jQuery object into a true array and then merge them.
var i=$('<img src="/path/to/imgI.png"/>');
var j=$('<img src="/path/to/imgJ.png"/>');
i = $.makeArray(i);
j = $.makeArray(j);
$( $.merge(i,j) ).css('cursor','pointer');
Btw that also works when you need to add multiple jQuery selection together,
i = $.makeArray( $('div') );
j = $.makeArray( $('a') );
$( $.merge(i,j) ); //this jQuery object holds all divs and a's
You could of course also do that like this:
$('div').add('a');