I need to find the next element that is not a sibling - javascript

Let's say I have following HTML:
<span>
<span id="x1" class="x">X1</span>
</span>
<span>
<span>
<span id="x2" class="x">X2</span>
</span>
</span>
And $(this) is the <span id="x1" ...>.
What is the best way to find next element matching .x with jQuery?
The structure of the actual document is unpredictable, so the HTML provided is only an example.
I can't use nextAll as it only finds siblings.
If I do $('.x'), it finds all, but I'll have to iterate/compare.
Is there a better solution?
See also: http://jsfiddle.net/JZ9VW/1/.

Given that you seem to be unwilling to make assumptions about the structure of the markup, a class-based selector is best. If elements aren't being added/removed then you can select them once and keep them around as an optimization.
var exes = $('.x');
var x1 = $('#x1');
var nextEx = exes.eq(exes.index(x1) + 1);
http://jsfiddle.net/mattball/QKawu
With a truly unpredictable HTML structure, asking for "the next element" only makes sense in the context of "the collection of elements with the specified class name," which is exactly what the above code reflects.

Find the parent, then get the parent's next sibling, then find the class.
.parent().next().find('.x')

Related

How to recursively select all children under an element Javascript

I need a function that recursively selects all child elements but wont select elements (and those elements children) if they have the "foo" attribute.
<section>
<div>
<span foo>
<input>
</span>
</div>
<p>
<img>
</p>
</section>
//should return [section, div, p, img]
I need raw Javascript please
edit:
I tried something like this:
$tag.querySelectorAll(":not([foo])")
but querySelectorAll(":not([foo])") will still return the children of the unselected element.
You can use element.querySelectorAll() with the :not modifier here, together with the [attr] selector:
var nonFooElements = parentElement.querySelectorAll("*:not([foo])");
Be aware that this sort of call will be moderately expensive because the selector doesn't begin with an id or a classname, so don't do huge amounts of it.
I adapted this answer from this one: https://stackoverflow.com/a/21975970/5009210

JQuery how to find the closest element that is neither a parent nor a child of the current element?

Say I have HTML that looks like this:
<div>
<div>
<div class="calendar start">
</div>
</div>
<div>
<div class="calendar end">
</div>
</div>
</div>
We can assume that the start and end will always be on the same "level" of a branch from each other, and will at some point share a common parent.
Without knowledge of the exact HTML structure, how would I find calendar end from calendar start? What if they are nested further down?
Edit: For clarification. I want to start at start's parent. Search all child elements for end. Then move to the next parent, and search all child elements...etc till I find end. I am wondering if this is possible with built in JQuery functions, without writing my own DOM traversal logic.
You can do it like below, But it is a costlier process.
var parentWhichHasCalEnd =
$($(".calendar.start").parents()
.get().find(itm => $(itm).find(".calendar.end").length));
var calEnd = $(".calendar.end", parentWhichHasCalEnd);
DEMO
Explanation: We are selecting the .start element first, then we are retrieving its parent elements. After that we are converting that jquery object collection to an array of elements by using .get(). So that we could use .find(), an array function over it. Now inside of the callBack of find we are checking for .end over each parent element of .start, if a parent has .end then we would return that parent. Thats all.
You could get more understanding, if you read .get(), .find(), and arrow functions.
You can use jQuery#next() method from .start parent element
var startSelector = $('body > div > div:nth-child(3) > .start')
var endSelector = secondStart.parent().next().find('.end');
I think this method is faster rather than jQuery#children() method, but you can benchmark it if you want to
btw you may check my answer based on this JSBin
i don't know if i got this right but have you tried children function in jquery
$( ".calender" ).children( ".end" )
and for the parent you can use parent() function so you can first check the parent then the children or vicversa
edit:
if you dont know the exact structure the better way is to find the common parent and then search it's children :
$( ".calender.start").closest('.common-parent').children('.calender.end');
closest function give the nearest parent
Try:
$('.start').parent().parent().find('.end');

JavaScript equivalent to JQuery .next()

Is there a JavaScript method similar to jQuery .next()? I want to find the next element that has the class of "error" relative to the element. I've tried using .nextSibling as a loop but couldn't figure it out. Didn't know if there was an easier way to go about it without jQuery.
For instance, if I have this code:
<div id="section">
<div id="test">test</div>
<span class="info">Information</span>
<span class="error">Error!</span>
</div>
I'm trying to get the next .error class closest to #test, if I have a #section2 and a #test2 I would want to get the .error class closest to #test2 and so on.
The nextElementSibling property returns the element immediately following the specified element, in the same tree level.
Example: Get the HTML content of the next sibling of a list item:
var x = document.getElementById("item1").nextElementSibling
The nextElementSibling property might help.
Best bet would be to search through the jQuery code and see what they did.
http://code.jquery.com/jquery-2.0.3.js
At a glance, I do see some calls to "nextSibling" and "previousSibling."
Also see here:
How to get next element using JavaScript-only?
Hope this helps!
This is the pure javascript for you:
HTML
<div id="nodes">
<div class="error">This is error Node</div>
<div class="nextElement">This is next Element</div>
</div>
Javscript:
var nodes = Array.prototype.slice.call( document.getElementById('nodes').children ),
errorNode = document.getElementsByClassName('error')[0];
var indexOfError = nodes.indexOf(errorNode);
var nextElement = nodes[indexOfError + 1];
alert(nextElement.innerText);
Here is demo
Sounds like you may be looking for document.getElementsByClassName()... if the elements with class=error are not direct siblings in the DOM, then there's not a good way to find them otherwise. It's elementary, but you can just search through the array returned by document.getElementsByClassName('error') until you find your starting element, and then you know the next item in the array will be the next element in the DOM.
See also MDN reference. Won't work in old IE, but works for all modern browsers.

jQuery creating and modifying elements

I'm using an HTML snippet to insert some text into the element, then display it somewhere:
var elemTemp = $('<span /><strong class="value unit" />').find('span').text('hi!').end();
elemTemp.appendTo('#someDiv');
I want to insert "hi" inside the span but could not get it working. The find() method doesn't seem to find the span.
find looks down the DOM tree, but your span is not a descendant, so find won't find it. Use siblings instead:
var elemTemp = $('<span /><strong class="value unit" />').siblings('span').text('hi!').end();
Here's a working example. Note that this produces HTML along the lines of:
<span>hi!</span>
<strong class="value unit"></strong>
I'm not sure if you were aiming for that, or if you wanted the strong to be a child of the span.
Why not do this as simply and quickly as possible?
$('#someDiv').append('<span>hi!</span>'); // or whatever HTML you want in there
You have to specify which span-tag you want to insert "hi" into. The easiest way is to set a class on the span-tag.
HTML:
<span class="hello"></span>
jQuery:
$('span.hello').html('hi');

How can I get img src and text from distant elements using JQuery?

Could you please lend a hand as I am having some trouble getting the text of a heading and the source of an image element in order to create a list of the item clicked. But I will explain better with some code:
Firstly I have a div element that goes like this:
<div class="main_page_entry">
<div class="main_item_desc">
<img class="main_item_pic" src="blah.jpg" />
<h6>Item Title</h6>
<span class="icon"> <img src="icon.png" /></span><br />
<span class="address">Some address</span>
<p class="item_desc">More blahs and links for description </p>
</div>
<div class="item_controls">
...
<a href="#" class="add_to_list">
<img src="add_icon.gif" />Add to List
</a>
...
</div>
</div>
It consists with a big div containing two smaller. What I want to do is the following: When I click on 'Add to List' link, I would like to get just the text inside and the main_item_pic source in order to create a list item with those two.
So here is my written code so far:
$('a.add_to_list').live('click', function() {
var name = $(this).closest('h6').text();
var source = $(this).closest('.main_item_pic').src;
$('<li class="hide list_entry"><span class="entry_title">'+
name+'</span><button class="remove_entry"></button>'+
'<img class="list_entry" src="'+source+'" /></li>')
.appendTo('#favs_list ul')
.show('slow');
});
Obviously this doesn't work! I've tried different solutions that I read around here like:
var name = $(this).closest('h6').html();
var source = $(this).closest('.main_item_pic').attr('src');
but oh well...no luck so far. Any ideas? Thanks in advance!
Try going back to the top and coming down again along the right DOM branch:
var src = $(this).closest('.main_page_entry') // Back to the top
.find('.main_item_desc .main_item_pic') // And down again.
.attr('src');
The closest method goes up the DOM tree through your ancestors:
Get the first ancestor element that matches the selector, beginning at the current element and progressing up through the DOM tree.
So it won't cross over to any of the sibling branches. Then, once you're at the appropriate ancestor, you use find to come back down, find is just like $() but uses the specified element rather than document as the root:
Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element.
The closest method only finds the closest ancestor that matches the selector you pass it. Because the h6 and img you are looking for are not ancestors of the element you are calling it on, it won't find them. What you need is to find the closest element that contains both the element you are searching from and the elements you are trying to find, and use it as an intermediate step in the search:
var name = $(this).closest('.main_page_entry').find('h6').text();
var source = $(this).closest('.main_page_entry').find('.main_item_pic').attr('src');
First off, if this content isn't added dynamically or in a live manner (in other words, if the content is loaded with the original HTML load) then you do not have to use the .live() function.
Also, why are you using .closest()? Couldn't you just do:
<img class="main_item_pic" ref='pic1' src="blah.jpg" />
<a ref='pic1' href="#" class="add_to_list">
<img src="add_icon.gif" />Add to List
</a>
$('a.add_to_list').click(function(){
var ref = $(this).attr('ref');
var src = $("img[ref='" + ref + "']").attr('src');
var name = $('h6 a').text();
});
The method closest() looks for ancestors. Your h6 and img are not ancestors of your link.
Also, I guess you don't want $('h6').html() but $('h6 a').html()

Categories