Accessing the 2nd member of a class in jQuery? - javascript

I have a stack of divs that belong to a specific class, say tabs. and the semantic structure looks something like this:
<div class = "tabs" >_______</div>
<div class = "tabs" >_______</div>
<div class = "tabs" >_____</div>
It's easy to access the first and the last element of the div like
$('.tabs:first') or
$('.tabs:last')
but getting to the 2nd (and assuming there are multiple other divs inside then the all divs other than first or last) seems to yield a syntax error to me such as :
$('.tabs:second') or $('.tabs:third') do not work expectedly.
Can anyone pinpoint what is wrong here?

Try using the eq() selector, notice the index is zero-based:
$(".tabs:eq(1)");

There are two ways to do this, either using the .eq() method or the :eq() selector.
The .eq() method:
The way the jQuery documentation recommend you do this is by making use of the .eq() method.
// eq() is zero-based, so this would get the second element
$('.tabs').eq(1)
A handy feature is that .eq() also can take a negative number, which causes the function to start from the end instead.
// This would take the second element from the end
$('.tabs').eq(-2);
The :eq() selector
jQuery also provide an :eq() selector, that basically work the same way the .eq() method does. So you could do this as well:
$('.tabs:eq(1)')
Notice that even though this work, it is preferred to use the .eq() method instead of the selector. The method has better performance in modern browsers and the :eq() selector does not support negative numbers, so it is somewhat more limited.

Take a look at the jQuery :first selector documentation:
http://api.jquery.com/first-selector/
You'll notice that this is a jQuery extension and not part of the CSS specification.
Also that :first is equivalent to :eq(0), that means if you want to get the second element, you can do it with :eq(1).
If you don't need a filter in the CSS selector, you can simply get the element with the .eq method like this:
$('.tabs').eq(0) // get the first element
$('.tabs').eq(1) // get the second element
$('.tabs').eq(2) // get the third element
$('.tabs').eq(-2) // get the second to last element
$('.tabs').eq(-1) // get the last element

Related

How to get the second match with QuerySelector?

The following statement gives me the first element with the class titanic
element = document.querySelector('.titanic');
How would I retrieve the second element with the same class?
Use document.querySelectorAll
document.querySelectorAll('.titanic')[1]
You don't necessarily need querySelectorAll for picking second element and the question is to use querySelector API. You can utilizing the power of CSS in the selector.
For example you can do:
document.querySelector('.titanic:nth-child(2)')
to pick second element. NOTE: the count starts at 1, not 0.
Refer to this quick CodePen to play around this approach:
https://codepen.io/adamchenwei/pen/RwZvQvW?editors=1111
NOTE: It is not accurate to use n-th-child against classes among child elements that have different class names. Plz do not do that. I would suggest to find alternative method (which I am not aware at this time)
ref: nth-child doesn't respond to class
a use case example WILL NOT WORK with n-th:child: https://codepen.io/adamchenwei/pen/MWQMObL

Selecting previous anchor tag and adding a class to it with jQuery

Basically I've got two anchor tags separated by a div.
<a class="foo"></a>
<div class="count">0</a>
<a class="bar"></a>
and I'm doing something like this:
var addClass = $(this).parent().children('a:first-child').addClass('new');
It will then add it to the first anchor tag like so:
<a class="foo new"></a>
I know using the nth:child selector is pretty expensive, so I was wondering if there was an easier way to select that previous anchor node, (while ignoring the second one).
You could do this
$(this).parent().children('a:eq(0)').addClass('new');
Learn more about :eq()
Alternatively, if there are no elements between the <a> and the <div>, you could do
$(this).prev('a');
Learn more about .prev()
I'd probably combine prevAll with first (or eq(0), since first just calls eq(0) — but I find first more readable):
$(this).prevAll("a").first().addClass("new");
// or
$(this).prevAll("a").eq(0).addClass("new");
prevAll returns all of the element's preceding siblings, in order starting with the closest sibling, and of course first / eq(0) reduces the set to the first element.
You might be tempted to use the :first selector with prevAll to avoid building up an unnecessary list of siblings, but to my surprise it works better to use first after-the-fact.
How about:
$(this).siblings('a').eq(0).addClass(0);
Actually, if your structure is as simple as in your example, you can just do a simple:
$(this).prev().addClass(0);
jQuery's traversal methods give you lots of ways to get to any given destination.

"All but not" jQuery selector

I can select (using jQuery) all the divs in a HTML markup as follows:
$('div')
But I want to exclude a particular div (say having id="myid") from the above selection.
How can I do this using Jquery functions?
Simple:
$('div').not('#myid');
Using .not() will remove elements matched by the selector given to it from the set returned by $('div').
You can also use the :not() selector:
$('div:not(#myid)');
Both selectors do the same thing, however :not() is faster, presumably because jQuery's selector engine Sizzle can optimise it into a native .querySelectorAll() call.
var els = toArray(document.getElementsByTagName("div"));
els.splice(els.indexOf(document.getElementById("someId"), 1);
You could just do it the old fashioned way. No need for jQuery with something so simple.
Pro tips:
A set of dom elements is just an array, so use your favourite toArray method on a NodeList.
Adding elements to a set is just
set.push.apply(set, arrOfElements);
Removing an element from a set is
set.splice(set.indexOf(el), 1)
You can't easily remove multiple elements at once :(
$("div:not(#myid)")
[doc]
or
$("div").not("#myid")
[doc]
are main ways to select all but one id
You can see demo here
var elements = $('div').not('#myid');
This will include all the divs except the one with id 'myid'
$('div:not(#myid)');
this is what you need i think.
That should do it:
$('div:not("#myid")')
You use the .not property of the jQuery library:
$('div').not('#myDiv').css('background-color', '#000000');
See it in action here. The div #myDiv will be white.

Using jQuery to delete all elements with a given id

I have a form with several spans with id="myid". I'd like to be able to remove all elements with this id from the DOM, and I think jQuery is the best way to do it. I figured out how to use the $.remove() method to remove one instance of this id, by simply doing:
$('#myid').remove()
but of course that only removes the first instance of myid. How do I iterate over ALL instances of myid and remove them all? I thought the jQuery $.each() method might be the way, but I can't figure out the syntax to iterate over all instances of myid and remove them all.
If there's a clean way to do this with regular JS (not using jQuery) I'm open to that too. Maybe the problem is that id's are supposed to be unique (i.e. you're not supposed to have multiple elements with id="myid")?
.remove() should remove all of them. I think the problem is that you're using an ID. There's only supposed to be one HTML element with a particular ID on the page, so jQuery is optimizing and not searching for them all. Use a class instead.
All your elements should have a unique IDs, so there should not be more than one element with #myid
An "id" is a unique identifier. Each time this attribute is used in a document it must have a different value. If you are using this attribute as a hook for style sheets it may be more appropriate to use classes (which group elements) than id (which are used to identify exactly one element).
Neverthless, try this:
$("span[id=myid]").remove();
id of DOM element shout be unique. Use class instead (<span class='myclass'>).
To remove all span with this class:
$('.myclass').remove()
if you want to remove all elements with matching ID parts, for example:
<span id='myID_123'>
<span id='myID_456'>
<span id='myID_789'>
try this:
$("span[id*=myID]").remove();
don't forget the '*' - this will remove them all at once - cheers
Working Demo
The cleanest way to do it is by using html5 selectors api, specifically querySelectorAll().
var contentToRemove = document.querySelectorAll("#myid");
$(contentToRemove).remove();
The querySelectorAll() function returns an array of dom elements matching a specific id. Once you have assigned the returned array to a var, then you can pass it as an argument to jquery remove().
You should be using a class for multiple elements as an id is meant to be only a single element. To answer your question on the .each() syntax though, this is what it would look like:
$('#myID').each(function() {
$(this).remove();
});
Official jQuery documentation here.
As already said, only one element can have a specific ID. Use classes instead. Here is jQuery-free version to remove the nodes:
var form = document.getElementById('your-form-id');
var spans = form.getElementsByTagName('span');
for(var i = spans.length; i--;) {
var span = spans[i];
if(span.className.match(/\btheclass\b/)) {
span.parentNode.removeChild(span);
}
}
getElementsByTagName is the most cross-browser-compatible method that can be used here. getElementsByClassName would be much better, but is not supported by Internet Explorer <= IE 8.
Working Demo

Chaining selectors in jQuery

I'm a guy used to mootools' way of chaining selectors, and I can't seem to find anywhere how to do the same in jQuery.
Suppose I have a select element in the selectObj variable. What I need is to get the last option in that select.
In mootools I would have done something like:
var option = $(selectObj).getElement('nth-child(last)')
Can I do something similar, or what is the way of getting that last option in jQuery?
PS. I know about the parent > child selector, but I can't really use it because I don't know what selector has been used to get the select. I only have the resulting element.
$(selectObj).find(':last')
You can use find to perform another query within the current query.
In general, you can check out the Selectors and Traversal pages on jQuery docs when you're trying to figure out how to select something.
var option = $(selectObj).children(":last");
will return the last child of any element
You can also use .last() for this purpose.
jQuery has the :last Selector
$("tr:last").stuff()
Will do stuff to the last row in a table.

Categories