firstChild node issue for DOM traversal in Javascript - javascript

Building this basic to-do list from scratch to try and teach myself Javascript. I found out through the API that there is a firstChild function that will target the first child of a parent node.
If I have..
<div class = "parentNode">
<div id = "i0">
TEXT HERE
</div>
<div id = "i1">
</div>
</div>
Then I have some button that is designated to the function:
document.getElementById('myButton').onclick = function () {
var parentNode = document.getElementById('parentNode');
var childNode = parentNode.firstChild.innerHTML;
alert('childNode');
}
Why would this not return TEXT HERE in the alert box?

There are a few things going on here. First, you are looking for an element that does not exist
var parentNode = document.getElementById('parentNode');
is looking for an id. This can be remedied by using an id="parentNode on the element, or you can query by class name instead using querySelectorMDN
var parentNode = document.querySelector('.parentNode');
Next, alert('childNode'); will always alert the string "childNode" and not the variable childNode so that needs to be alert(childNode).
Lastly, and perhaps most interesting, is that .firstChild will get the first childNode of the set of childNodes. This can be a #text node (which it is), becuase of the whitespace used between the end of the <div class = "parentNode"> and the beginning of <div id = "i0">.
As opposed to using .firstChild, you can use children[0] which will only look at elements. Here is a snippet that shows this behavior.
document.getElementById('myButton').onclick = function () {
var parentNode = document.querySelector('.parentNode');
var childNode = parentNode.children[0].innerHTML;
alert(childNode);
}
<button id="myButton" type="button">Click To Check Node</button>
<div class = "parentNode">
<div id = "i0">
TEXT HERE
</div>
<div id = "i1">
</div>
</div>

Related

getElementById from ancestor element to remove child's class

I want to use a parent element with getElementById.
For example: I want to use ancestor id "test" to remove class "myClass".
HTML
<div id="test">
<div id="test-child-one">
...
</div>
<div id="test-child-two">
...
</div>
<div id="test-child-three">
<div class="myClass"></div>
</div>
</div>
Javascript
var element = document.getElementById("test");
element.className = element.className.replace(/\bmyClass\b/g, "");
It won't work. Please help! Thanks.
You could do this:
//If you want to remove the class from all decendants
//Get all decendants with class "myClass"
const childEles = document.getElementById('test').querySelectorAll('.myClass');
//Or per David
const childEles = document.querySelectorAll('#test .myClass');
//Iterate the collection and remove "myClass" from all decendants
for(let x = 0; x < childEles.length; x++){
childEles[x].classList.remove("myClass");
}
//If you only want to remove the first decendant
document.getElementById('test').querySelectorAll('.myClass')[0].classList.remove("myClass");
//Or per David
document.querySelectorAll('#test .myClass')[0].classList.remove("myClass);
Do like Ryan Wilson specified it or simple one-liner:
document.getElementById("test").querySelectorAll('.myClass').forEach(function (el) { el.classList.remove("myClass"); });
Or a beautiful way, if you have transpiler between your code and browser:
removeChildrenClass = (parentId, childClass) => document.querySelectorAll(`#${parentId} .${childClass}`).forEach(el => el.classList.remove(childClass));
removeChildrenClass("test", "myClass");
Expanding on the other answers provided, it seems as though you are looking for querySelectorAll. Given that you already have some ancestor element element, querySelectorAll can be used to find all children with the specified class. To build on your example:
Using querySelectorAll
// Example constant element IDs/classes
var parentId = "test";
var targetClass = "myClass";
// The given parent element
var element = document.getElementById(parentId);
// Iterate over all children `elem`s with the target class
element.querySelectorAll(targetClass).forEach(function (elem) {
elem.classList.remove(targetClass);
});
This is just an example to demonstrate how querySelectorAll can be used on specific elements to solve exactly such a problem. Note that querySelectorAll will match multiple classes containing myClass if they exist, if you want to specifically remove the first such class, you might use querySelector instead.

Identify cloned DOM element

I am using MediumEditor which a WYSIWYG editor using contenteditables. I need to assign different IDs to each element inside of the contentEditable, but (when you press Enter) the editor will clone a paragraph from an esiting one with all it's attributes. I am wondering if there is a way to identify the new <p> element from the one it was cloned from? The new element can be placed either before or after the existing one.
UPDATE:
Here's an example:
https://jsfiddle.net/wwoh7e62/
<div id="container">
<p id="myid" class="myclass" data-id="myid">some text</p>
</div>
<button onclick="doClone(); myFunc();">clone</button>
<script>
doClone = function() {
var container = document.getElementById('container');
var node = container.getElementsByTagName('p')[0].cloneNode(false);
node.innerHTML = 'cloned node';
container.appendChild(node);
}
myFunc = function () {
console.log('my func');
}
</script>
The code in doClone I don't have access to. My code should reside in the myFunc function.
While I was typing the fiddle I realized that the solution will probably be in attaching an event listener (which is not cloned) and the new node will be the one that does not have the event listener.
UPDATE:
ids that were assigned previously need to stay the same as thay are used to identify particular nodes.
You can try this :
Remove the id from "p"
<div id="container">
<p class="myclass" data-id="myid">some text</p>
</div>
<button onclick="doClone(); myFunc();">clone</button>
Then update them into your Func function :
var length = document.getElementById("container").getElementsByTagName("p").length;
for(var i=0; i < length; i++) {
document.getElementById("container").getElementsByTagName("p")[i].id = i;
}
Does this help ?

javascript selectors

How does one select DOM elements in javascript?
Like for example:
<div class="des">
<h1>Test</h1>
<div class="desleft">
<p>Lorem Ipsum.</p>
</div>
<div class="Right">
<button>Test</button>
</div>
</div>
Now how do i select h1? This is just a part of a bigger Page, so cannot use getElementsByTagName(), since others might get selected. Also since there might be other h1's in the document later, i cannot attach the index(body's) to above.
Is there a simple way to select, say <h1> tag which is under the classname of desleft?
I cannot use jQuery or any other libraries.
You can use this to get to your H1:
var des = document.getElementsByClassName('des')
var fc = des[0].getElementsByTagName('h1')
alert(fc[0].innerHTML)
w3.org has selectors now (http://www.w3.org/TR/selectors-api/#examples). Here are 2 different ways that worked for me on Chrome. You may want to use querySelectorAll function that returns a list.
<script type="text/javascript">
//looks for <h1> tag under <div> with className "des"
showOff1 = function() {
var x = document.querySelector(".des h1");
alert(x.innerHTML);
}
//looks for <div> tag with className "desleft" and then use previousSibling to traceback <h1> tag
showOff2 = function() {
var y = document.querySelector("div.desleft");
var z = y.previousSibling.previousSibling;
alert(z.innerHTML);
}
</script>
<body onload="showOff2();">
Use querySelectorAll
You can use querySelectorAll:
// Will return a NodeList even if there is only one element found
var heading = document.querySelectorAll('.des > h1');
heading[1].style.color = 'red'; // NodeList is similar to an array
This will return a NodeList.
or
Use querySelector to return the first element found:
var first_heading = document.querySelector('.des > h1');
first_heading.style.color = 'blue';
Commonly used with an id selector #single-header-id.
Here's a demo
getElementsByTag()
Would be a function that you can start with, and then you can filter for the DOMElements that have the class.
var h1_array = document.getElementsByTag('h1');
var h1_class_array = [];
for (var i=0, len=h1_array.length; i < len; i++) {
if (h1_array[i].className.indexOf('classname') !== -1) {
h1_class_array.push(h1_array[i]);
}
}
The .indexOf function returns -1 if the needle is not found in the haystack.
Now re-reading your question, why not just give your h1's id's ?
DOM traversal is one of javascript's glaring issues (enter jQuery).
a simple getElementById() would save you a headache, and ids on all your h1's would be much cleaner in the end than trying to formulate an algorithm to select them by other means.
If you mean to select a h1 that is before the first element of class desleft, you could always do this:
document.getElementsByClassName("desleft")[0].previousSibling.previousSibling
Example: http://jsfiddle.net/Xeon06/ZMJJk/
previousSibling needs to be called twice because of the empty text node between the two. That's why using libraries to do this stuff is really the best way to go.
var h1 = document.querySelector('.desleft').previousElementSibling;
Find element with className='desleft' using selector '.desleft'
Just move back to previous element (not to previous node!)

JS Prototype get element by class?

I got the following code and I'm trying to make it match on a class instead of on an id:
Html:
<div id='testdiv'>
<div class="lol">
[First Title|<a class="external" href="http://test.com">http://test.com</a>]
Another line
[Second Title|<a class="external" href="http://test.com">http://test.com</a>]
More text
[Third Title|<a class="external" href="http://test.com">http://test.com</a>]
</div>
</div>
Javascript:
var textContainer = document.getElementById("testdiv");
var linkText = textContainer.innerHTML;
var pattern = /\[([^|]+)\|([^>]+.?)[^<]*(<\/a>)\]/g;
var result = linkText.replace(pattern, "$2$1$3");
textContainer.innerHTML = result;
Full example: http://jsfiddle.net/JFC72/17/
How can I make it match on "myclass" instead?
Thanks!
Use a css selector in prototype.
var textContainer = $$('div.myclass')[0];
jsfiddle
I think you need the $$ method. It selects DOM elements that match a CSS selector strict. In this case you want
var elements = $$('.myclass');
It returns a list of all matching elements in document order. You can access them by index or operating on all of them with things like each
http://www.prototypejs.org/api/utility
This is what Prototype is about. getElementById is oooold
Here is a working example of how you would use each in Prototype to loop through all elements with a class of order-cc-charged.
var order_cc_charged = 0;
$$('order-cc-charged').each(function (elem) {
order_cc_charged += parseFloat($('order-cc-charged').innerHTML);
});

How to get the first inner element?

So I want to get the first <a> tag in this <div>. This is really driving me nuts. Thanks for any help.
HTML
<div id="PGD" class="album" onmouseover="load(this)">
<a class="dl" href="#">DOWNLOAD</a>
</div>
Javascript
function load(dl)
{
var ID = $(dl).attr('id');
var elemnt = $('ID:first').attr('id');
}
Non-jQuery: (was not tagged with jQuery before, so I included this)
If you want to get the first child element only:
var element = document.getElementById('PGD').children[0];
If you want to get the first anchor element:
var element = document.getElementById('PGD').getElementsByTagName('a')[0];
With jQuery:
var element = $('#PGD').find('a:first');
// or, to avoid jQuery's pseudo selecors:
// var element = $('#PGD').find('a').first();
and actually your function can just be
function load(dl)
{
var element = $(dl).find('a:first');
}
Update:
As you are using jQuery, I suggest to not attach the click handler in your HTML markup. Do it the jQuery way:
$(function() {
$("#PGD").mouseover(function() {
$(this).find('a:first').attr('display','inline');
alert($(this).find('a:first').attr('display'));
});
});
and your HTML:
<div id="PGD" class="album">
<a class="dl" href="#">DOWNLOAD</a>
</div>
​See for yourself: http://jsfiddle.net/GWgjB/
$("#PGD").children("a:first")
This will give you the first child "a" tag, but not the descendents. E.g.
<div id="log">
<p>Foo</p>
Hello
Hello
</div>
Will give you : Hello
$(ID).find(':first')
See find jQuery command.
$('#PGD').find('a:first')
Actualy I've not understanding problem, so I'm trying correct your function, to make it clear for you:
function load(dl)
{
// var ID = $(dl).attr('id');
// var elemnt = $('ID:first').attr('id'); // Here is error-mast be like $(ID+':first')
var ID = $(dl).attr('id');
var elemnt = $(ID).find('*:first').attr('id');
}
I supose dl that is $('#PGD'). But child element A have not attribute id, what are you trying to find?
Also See: http://api.jquery.com/category/selectors/

Categories

Resources