If you are caching elements with javascript, which is more efficient?
HTML
<div id="parent">
<div id="child"></div>
</div>
Javascript:
var parent = $('#parent');
var child = $('#child');
or
var parent = $('#parent');
var child = $(parent).find('#child');
Is one better than the other? Or better practise? I'm writing a lot of code like this, and I am currently using find() to get specific elements of parents that are already cached.
Thanks
As #PSL says, as ids, the first is better, but with classes, the second would be faster because then you don't have to search the whole document for .child you just have to search within the #parent
Also, you can go:
var child = parent.find('#child');
instead of
var child = $(parent).find('#child');
Related
i was wondering if there's a jquery (or some other library) function that allows me to insert a node (div) between two other nodes (divs) based on its attribute.
For example:
Lets say i have this html code:
<div value=111/>
<div value=222/>
<div value=444/>
i want to insert <div value=333/> between the 222 and 444 accordingly.
Thanks to all helpers.
Yes you can do this.
obtain desired div using querySelector
use after method to add new element after the one obtained in the previous step
const div = document.createElement('div');
div.textContent = 'three';
const target = document.querySelector('div[value=two]');
target.after(div);
<div value="one">one</div>
<div value="two">two</div>
<div value="three">four</div>
To dynamically the find correct spot, you can use find method like this.
find the first element with value bigger than the one you provide
use before method to place the new element before the one from the previous step
const myValue = 333;
const div = document.createElement('div');
div.textContent = myValue;
const target = [...document.querySelectorAll('div')]
.find(v => Number(v.getAttribute('value')) > myValue );
target.before(div);
<div value="111">111</div>
<div value="222">222</div>
<div value="444">444</div>
use after();
here is working example in codepen
https://codepen.io/anon/pen/BVjbqZ
Both jQuery offers a variety of methods for this: insertBefore, insertAfter, before, and after.
The DOM provides insertBefore and insertAdjacentHTML.
For instance, using jQuery's before:
$("div[value=444]").before("<div value=333></div>");
Or using the DOM's insertBefore:
var div = document.createElement("div");
div.setAttribute("value", "333");
var target = document.querySelector("div[value=444]");
target.parentNode.insertBefore(div, target);
Or using the DOM's insertAdjacentHTML:
document.querySelector("div[value=444]").insertAdjacentHTML(
"beforebegin",
"<div value=333></div>"
);
Side note: div is not a void element, <div /> isn't a self-closing tag, it's a start tag with a / in it that's ignored.
Side note 2: value is not a valid attribute for div elements.
I know how to append an element inside another element, but how do I specify which class I want to append it to?
For example:
<div class="main" id="11">
<div class="somethingelse>
<div class="moreThings">
/*How to append to this class?*/
</div>
<div class="extraThings">
</div>
</div>
</div>
What I have is something like this:
var x = document.createElement("IMG");
x.setAttribute("src", "../truck.png");
document.getElementById(order_id).appendChild(x);
document.getElementById("btn_transport_"+order_id).style.display = "none";
There could be hundreds of classes with same name which is why I need to define them by id.
At the moment I am appending the img under everything other divs, but I would like to append it inside "morethings". How would I do that?
You could do something like this:
document.getElementById(order_id).getElementsByClassName("moreThings")[0].appendChild(x);
Make sure getElementsByClassName("moreThings") returns at least one element.
You can find out more about getElementsByClassName(...) from HERE. The gist of it is:
Returns an array-like object of all child elements which have all of the given class names
You could use document.querySelector. It allows CSS-like selectors. In your case it could look like
const myElementToAppendTo = document.querySelector('#myID .morethings');
myElementToAppendTo.appendChild(x);
I have an object that was retrieved from this expression:
const element = document.querySelector("...my selector...");
I need to get all child elements that have certain attributes, The only way I know to get all children is by:
const children = Array.from(element.childNodes);
but now each child in children is not an element, rather a node, hence, I cannot use getAttribute('') on them;
How do I "cast" a Node to an Element?, Or is there a better way to do this?
How do I "cast" a Node to an Element?
You can't.
Elements are a subset of Nodes.
If it isn't an Element already, then you can't turn it into one.
Consider:
<div>Hello, <strong>World</strong></div>
You have two child nodes. The text node "Hello, " and the strong element node.
It doesn't make sense to treat "Hello, " as an element.
Consider using children instead of childNodes. It fetches only element children.
I need to get all child elements that have certain attributes
In that case, you're probably better off just using a selector which gets you that in the first place. You'll need a child combinator and an attribute selector in addition to your existing selector. Then you'll need to use All to get more than one result.:
document.querySelectorAll("...my selector... > [someAttribute]"
You said you want to select all children with a specific attribute. So select them with querySelectorAll using an attribute selector.
var elems = document.querySelectorAll("#theParentSelector > [theChildsAttribute]")
console.log(elems.length)
Array.from(elems).forEach( function (el) {
console.log(el.getAttribute("theChildsAttribute"))
});
<div id="theParentSelector">
<div theChildsAttribute="1">Foo 1</div>
<div>Bar</div>
<div theChildsAttribute="2">Foo 2</div>
<div theChildsAttribute="3">Foo 3</div>
</div>
You'd use children to gain access to all HTML based nodes:
document.querySelector("...my selector...").children
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');
I am writing a GreaseMonkey script that goes through a page with various elements and each element has text and a button. It uses document.getElementsByClassName to find the parent elements, and it has a for loop to do something to each parent element. In this loop, I need to select a child node with a specific class and find its text value (innerHTML). I can't figure out how to select the child with a specific class of this element.
You'll want to grab the currently iterated element and use querySelector()
For example:
var elements = document.getElementsByClassName('class');
for (var i = 0, len = elements.length; i < len; i++) {
var child = elements[i].querySelector('.class_of_desired_element');
//do stuff with child
}
Note the dot before the class name in querySelector as it works similar to jQuery.
Try querySelectorAll(), which you can use to find elements within the current element.
var parent = document.getElementsByClassName('parentClass'),
parent[0].querySelectorAll('.childClass');
Depending on exactly what you are looking to do, you could also skip selecting the parent, if you don't explicitly need a reference to it.
document.querySelectorAll('.parentClass .childClass');
https://developer.mozilla.org/en-US/docs/Web/API/Element.querySelectorAll
You can use
var yourelement = document.getElementsByClass("");
var i = yourelement.nextSibling;
var e = i.nextSibling;
and keep getting the nextSibling of the element till you get it.
However, like #teddy said in the comments, I would suggest you use jQuery. It has a MUCH easier way to do it:
var value = $('.parentClass .childClass').html();