I have list:
<ul class='mates'>
<li class='m' id='1'>Jakub</li>
<li class='f' id='2'>Vinnie</li>
<li class='m' id='3'>David</li>
</ul>
How can I select 'li' tags "ONE BY ONE" to be checked if their content (between 'li' tags) is equal to 'xyz'.
element = document.getElementsByClassName('.mates').firstChield.innerHTML;
do {
if(){
//do something
}
}while (element = element.nextSibling);
but I'm not getting even far enough to select firstChild. This error is showing in console: "Cannot read property 'innerHTML' of undefined". This needs to be done in plain JavaScript. Any ideas?
<ul class='mates'>
<li class='m' id='1'>Jakub</li>
<li class='f' id='2'>Vinnie</li>
<li class='m' id='3'>David</li>
</ul>
<script>
var mates = document.getElementsByClassName('mates')[0];
for (var i=0; i< mates.childNodes.length; i++){
if(mates.children[i].innerHTML == 'Vinnie') alert("Got you! ID "+mates.children[i].id)
}
</script>
Drop the dot in the parameter. Like this:
element = document.getElementsByClassName('mates').firstChild.innerHTML;
The dot is not a part of the name of the class.
EDIT also notice that the question originally had a typo in firstChild.
Your element variable is not an element (its value is probably undefined). It should work if you use it like this:
var element = document.getElementsByClassName('mates')[0].firstChild;
do {
if(element.innerHTML == 'foo'){
//do something
}
} while (element = element.nextSibling);
The code above fixes:
The class name as pointed out by #Renan
The typo in .firstChild
Also note that getElementsByClassName returns a list of elements, so you have to grab the first one in the list (index 0) to reach your <ul>.
Finally, keep in mind that you'll be looping over all children of the <ul>, including empty text nodes (see a demonstration at http://jsfiddle.net/58ZZF/). This can be avoided if you use firstElementChild and nextElementSibling, but I'm not sure if there are cross browsers issues with those properties (MDN only says it's Firefox 3.5+).
Few mistakes
Class name to getElementsByClassName should not have .
Spelling mistake in firstChild
getElementsByClassName returns an array, not a dom reference
When using nextSibling it could return text nodes also, you need to check the nodeType to make sure the element is a element node(nodeTye = 1), also you can check the tagName == 'LI'
Try
var element = document.getElementsByClassName('mates')[0].firstChild;
do {
if(element.nodeType == 1){
console.log(element.textContent)
}
}while (element = element.nextSibling);
Demo: Fiddle
Related
I have a pure Javascript script with an onclick event that checks the value of the next sibling before deciding what to do. This will cause an error if the element clicked is the last element in its container (because of accessing nextSibling). I need to first check that the element clicked is not the last element in the container, but can't seem to find out how.
Note: I don't think this is a duplicate. There are quite a few questions about checking if an element is the last child, but all accepted answers—all answers in general—use JQuery.
You can use the .nextSibling property on the element and see if it comes back as empty (undefined, etc).
You can use the node.lastChild Property
The Node.lastChild read-only property returns the last child of the node. > If its parent is an element, then the child is generally an element node, > a text node, or a comment node. It returns null if there are no child elements..
var tr = document.getElementById("row1");
var corner_td = tr.lastChild;
The error you get should be some kind of can't set property on undefined.
You have just to check whether the next element exists:
if (typeof element.nextSibling === "undefined")
return;
For some reason none of the answers worked for me, I always ended up seeing a #text node instead of undefined or null, so I ended up comparing my element with the last child of the parent of the element:
element === element.parentNode.children[element.parentNode.children.length-1]
or if you want it as a function
function isLastChild(el) {
return (el === el.parentNode.children[el.parentNode.children.length-1])
}
//Useage
if(isLastChild(el)) {
//Element is the last child of its parent.
}
Might be longer than other answers but surly won't fail you.
Accessing an element's nextSibling element you'll get null if the element has no next sibling, so you can just check before going on with your code, like this:
if (myElement.nextSibling) {
// the element has a next sibling
// go on...
} else {
// the element is the last child
}
Use the .lastChild property of the node.
Example:
Here, we are removing last 4 child nodes in the list.
function clearAll() {
var sidemenu = document.getElementById('side_menu');
console.log("sidemenu.childNodes.length = " + sidemenu.childNodes.length);
while (sidemenu.childNodes.length > 2) {
console.log(sidemenu.childNodes);
sidemenu.removeChild(sidemenu.lastChild);
console.log("removed");
console.log("sidemenu.childNodes.length = " + sidemenu.childNodes.length);
}
console.log("What we have left now:");
console.log(sidemenu.childNodes);
}
clearAll();
<ul id="side_menu">
<li>List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
<li>List Item 4</li>
<li>List Item 5</li>
</ul>
Learn more: Node.lastChild - Web API Interfaces | MDN
This is one way to check:
document.querySelector(":last-child");
Here's one more:
var isLastChild = (element === element.parentNode.lastChild);
If you're trying to make this compatible with older browsers, just use childNodes:
// Last element in the body
document.getElementsByTagName('body')[0].childNodes[document.getElementsByTagName('body')[0].childNodes.length-1]
so for your particular problem, use the event object in your onclick:
element.onclick = function(event) {
var parent = event.target.parentNode;
if(event.target === parent.childNodes[parent.childNodes.length-1])
// Code here
}
How about var isLastChild = element === element.parentNode.lastChild?
Ask if there is a next element or not to know if it is the last or not:
if (typeof element.nextElementSibling == null) {
//is last
return;
} else {
//is not last
}
you must use nextElementSibling, no nextSibling or typeof ...
function isLastElement(element) {
return element.nextElementSibling === null;
}
<body>
<div id="li-container">
<ul>
<li class="hot">item1</li>
<li id="secLi" class="cool">item2</li>
<li class="cool">item3</li>
<li class="cool">item4</li>
</ul>
</div>
<script language="javascript" type="text/javascript">
var secLi = document.getElementById("secLi");
var sib = secLi.nextSibling;
document.write(sib);
//OR //OR //OR //OR //OR //OR //OR //OR
var secLi = document.getElementById("secLi");
var sib = secLi.nextSibling;
document.write((sib).textContent);
</script>
</body>
I want to get the textnode of the third list(li) item using nextSibling property and write in the document.I know I can use "li.textContent" to access it but I want it this way.
No,I am not looking for "nextElementSibling",I want to acess the "textNode" of "secondli" using "nextSibling" property and that is because if I want to get to the "third li",I must use "nextSibling.nextSibling"twice to get to the "third li".(1)First "nextSibling" is for the "text-node" of the "2nd li" and (2)Second "nextSibling" is for the "3rd li".So I am not able to get the text-node of "2nd li" using "next-sibling" once.
I used text-fixer.com to remove other white-spaces and line breaks even then it dosent work.
Are you perhaps looking for nextElementSibling?
var secLi = document.getElementById('secLi');
secLi.nextSibling; // Is a text node.
secLi.nextElementSibling; // Is the <li> you're looking for, so..
secLi.nextElementSibling.textContent; // Gives you "item3"
Update
To better understand why you want nextElementSibling instead of nextSibling look at what the parent <ul> says its childNodes are:
secLi.parentElement.childNodes;
// [#text, <li>, #text, <li>, #text, <li>, #text, <li>, #text]
You don't want the nextSibling because it's just the empty text between list items. You want the next element (list item).
See https://developer.mozilla.org/en-US/docs/Web/API/NonDocumentTypeChildNode/nextElementSibling
the textnode of the li element is a child of 2nd li element.
So the code would be
var sib = secLi.firstChild.textContent;
document.write(sib);
#brianvaughn
How could I find an element in an HTML document using it's style properties?
here is an example:
HTML:
<ul>
<li style='z-index=1;'>e1</li>
<div style='z-index=8;'>div</div>
<li style='z-index=2;'>e2</li>
<li style='z-index=3;'>e3</li>
<li style='z-index=4;'>e4</li>
<li style='z-index=5;'>e5</li>
<ul>
The question is how do i select, for example..: the element <li> with z-index=4.
and how to select all div's with z-index=8 ...
If the style is set inline, you can use an attribute selector:
$('li[style*="z-index:4"]') //returns any li's with z-index = 4
see here. The advantage to this method is that it is very fast.
If the style is set via a stylesheet, you can access it this way:
var elem;
var elems = $("li");
for(var i=0; i<elems.length; i++) {
if($(elems[i]).css('z-index') == '4') {
elem = elems[i]; //assign elem we found
break; //exit loop early
}
}
Note Webkit browsers, (Safari, Chrome, etc), will not return a z-index value unless it is positioned as well. See this example
Also, for loop is still faster than .filter()
There isn't a style selector (how would it work, the style is a combination of inherited and explicitly stated rules), but you can filter (demo):
var things = $("li").filter(function() {
return $(this).css('z-index') == '4';
});
Now if you are using z-index to attach a piece of data to an HTML element you might have more luck using data attributes (cleaner, and searchable by Sizzle). One interpretation might look like this: (demo)
<div data-id='8'>div</div>
<ul>
<li data-id='1'>e1</li>
<li data-id='2'>e2</li>
<li data-id='3'>e3</li>
<li data-id='4'>e4</li>
<li data-id='5'>e5</li>
<ul>
<script>
alert($('[data-id=4]').text())
alert($('[data-id=8]').text())
</script>
HTML
<ul class="tabbox">
<li></li>
,
<li></li>
,
<li></li>
</ul>
JQuery (My Idea - does NOT work)
$(".tabbox").replace(',' , ''); // This was my idea, and it does not work ..
How can I remove the , from the < ul > ?
It seems to me that you're asking the wrong question.
If the intent is to remove the spurious text nodes (which happen to contain commas) from between the <li> nodes, you should do this:
$('.tabbox').contents().filter(function() {
return (this.nodeType === 3);
}).remove();
Working demo at http://jsfiddle.net/alnitak/gN7yM/
Note the use of .contents() to ensure that text nodes are included in the results.
If instead you want to purify the code to remove anything that isn't an <li> from the <ul>, use this:
$('.tabbox').contents().not(function() {
return (this instanceof HTMLLIElement);
}).remove();
FWIW, since #ShadowWizard reports that this doesn't with with IE < 8.0 I tried:
$('.tabbox').contents().not('li').remove()
and it didn't work. Reading the jQuery source it seems that pure string selectors completely ignore text nodes, but this does work:
$('.tabbox').contents().not(function() {
return $(this).is('li');
}).remove();
EDIT I've changed a couple of the examples above to use .not() instead of .filter() so as to remove the double negative.
One way to clean the list and leave only the list items is such code:
var list = $(".tabbox");
var items = $(".tabbox li");
list.html("");
items.each(function() {
list.append($(this));
});
Live test case: http://jsfiddle.net/TS8Sd/
This will not only remove comma but any other text or elements that do not belong there.
var tabbox = $(".tabbox"),
tabHtml = tabbox.html();
tabbox.html(tabHtml.replace(/,/g , ''));
This would replace all of them.
EDIT:
Although, why would you have a ',' after each li?
var tabHtml = $(".tabbox").html();
$(".tabbox").html(tabHtml.replace(/,/g , '')); //#Tomgrohl already answered it
My example makes use of the function parameter for .html().
$('.tabbox').html(function (index, oldhtml) {
return oldhtml.replace(/,/g, '');
});
jsFiddle Demo
I have some markup where a lot of id's have an id attribute, as well as innerText. I want to select each of these elements, performing a function on the id.
How do I do that?
Something like this?
$('[id]:not(:empty)').each(function(i, el) {
// do stuff
});
Give them a common class:
HTML
<div id="first" class="all"></div>
<div id="second" class="all"></div>
<div id="third" class="all"></div>
jQuery
$('div.all').each(function(index){
processid(this.id);
});
If you are talking about selecting elements whose id (or some permutation of it) is included in its text then
$('[id]').filter(function(){
return $(this).text().indexOf( this.id ) >= 0; // the this.id should be altered to match the permutation you seek ..
}).css('color','red'); // turn those to red
After you comment to #lonesomeday (at the question comments) here is what to do ..
$('[id]').each(function(){
processid(this.id);
});
First select by a regular ID selector and then loop over that selection by filtering .text() non-empty.
$("[id]").each(function() {
if ($(this).text() != "") {
// do stuff
}
});