Trouble getting the index of a child when it is clicked - javascript

I'm trying to get the index of a child within a parent element. I followed the answer here, but ended up with an infinite loop.
My code so far:
var div = document.getElementById("spans");
var spans = div.getElementsByTagName("span");
div.addEventListener('click', function(e) {
var span = e.target;
var spanSiblings = 0;
while((span.previousElementSibling) != null ) {
spanSiblings++;
}
console.log(spanSiblings);
});
The aim is to output 0 when the user clicks on the first span because it's the first child in the "spans" id:
<div id="spans">
<span>This is span #1</span>
<span>This is span #2</span>
<span>This is span #3</span>
</div>
Any help would be appreciated.

As you are not changing the span variable in the loop, the condition will always be the same. If you assign the previous sibling to the variable, then it works:
var div = document.getElementById("spans");
var spans = div.getElementsByTagName("span");
div.addEventListener('click', function(e) {
var span = e.target;
var spanSiblings = 0;
while((span = span.previousElementSibling) != null ) {
spanSiblings++;
}
console.log(spanSiblings);
});
<div id="spans">
<span>This is span #1</span>
<span>This is span #2</span>
<span>This is span #3</span>
</div>

Borrowing a little from jQuery, which checks the elements position with $.inArray in it's index function, you can do
var div = document.getElementById("spans");
var spans = div.getElementsByTagName("span");
div.addEventListener('click', function(e) {
var span = e.target;
var arr = [].slice.call(spans);
var index = arr.indexOf( span );
console.log( index );
});
FIDDLE

You have to modify your while loop condition. You don't have any condition to terminate the while loop. Change your while loop code to
while((span = span.previousElementSibling) != null ) {
spanSiblings++;
}

Related

How to return innertext of sibling element

In GTM i'm trying to return the inner text of a sibling element of the clicked element.
<div class="repair-item-n ">
<div class="repair-slide--54894d33-6c88-488f-95d7-3ec9b6a3ade4">
<div class="restoration_wrap text-center">
<img class="restoration-image">
</div>
<p class="title">Bags</p>
</div>
</div>
For example, on click of class "restoration-image" I want to return the value "Bags".
I have multiple occurrences of this HTML on the page with varinats such as "Shoes", "Hats" etc so I want to know on click of each, which would be the respective text of the "title" class
Try this:
var images = document.querySelectorAll('.restoration-image');
images.forEach(function (image) {
image.addEventListener('click', function (event) {
var parent = this.parentNode;
var nextSibling = parent.nextElementSibling;
alert(nextSibling.innerText)
})
});
This should work for GTM custom JavaScript variables.
function getImgTitle() {
if({{event}} === 'gtm.click') {
var image = {{Click Element}};
var parent = image.parentNode,
nextSibling = parent.nextElementSibling;
return nextSibling.innerText;
}
}
I would do this in a Custom Javascript Variable:
Click - Repair Item Title
function() {
var clickedEl = {{Click Element}};
if (!clickedEl) return;
// Find the mutual parent element
var repairItemEl = clickedEl.closest(".repair-item-n");
if (!repairItemEl) return;
var titleEl = repairItemEl.querySelector(".title");
if (!titleEl) return;
return titleEl.innerText
}}

Puppeteer Getting the text within all the elements with <span> tag in DOM only if it has a <sup> child tag

Newbie here. Experimenting with puppeteer. I have my HTML as given below
<html>
<div id="container">
<span >
Parent Text
<sup name="20">Child Text</sup>
</span>
<span >
Parent Text
<sup name="20">Child Text</sup>
</span>
<span >
Parent Text
<sup name="20">Child Text</sup>
</span>
</div>
</html>
JS File
const list = await page.evaluate(() => {
const spans = document.getElementsByTagName("span")[0];
let data=[];
for (var i = 0; i < spanEntity.children.length; ++i){
if(spanEntity.children[i].innerText ==="Child Text"){
data.push(spans.innerText);
}
}
})
This works for first span element. But how can I do this for all the span elements in DOM. I know we can use querySelectorAll to check for all span elements in DOM. But I'm not aware how to check the for child nodes .Any help will be greatly appreciated. Thank You in advance!!.
With map and filter:
let data = await page.$$eval('span', spans => spans
.filter(span => span.querySelector('sup'))
.map(span => span.innerText)
)
Adjust the code like below and you will traverse through all the span elements:
const spans = document.getElementsByTagName("span");
let data=[];
for (var i = 0; i < spans.length; ++i){
var sup = spans[i].getElementsByTagName("sup");
if(sup[0].innerText ==="Child Text"){
data.push(spans[i].innerText);
}
}
console.log(data);
https://jsfiddle.net/praveen_tamil/6fL2wbkt

How to get the text(which not under any node) from div in javascript

I am learning javascript and I am stuck on a problem.
I need to get the text which comes directly from the div.
Example :
<div id ="parent_div">
<label>text1</label>
text2
</div>
in above HTML I need to get text2 which come directly under the div, but I don't want text1 in output.
So far I have tried
document.getElementById("parent_div").textContent
and
document.getElementById("parent_div").innerText
but I got both text1 and text2.
Please help me to get text2 only.
text1 will always appear, unless you hide it.
To get the sibling text, use:
document.getElementById("parent_div").childNodes[2].textContent;
Check the childNodes property to see where I get the number 2.
You could remove all the texts from the other elements:
var ele = document.getElementById("parent_div");
var text = ele.innerText;
for (var i = 0; i < ele.children.length; i++) {
text = text.replace(ele.children[i].innerText, "");
}
console.log(text);
<div id="parent_div">
<label>text1</label> text2
</div>
Filter by nodeType, you can get all the children from the element, then you can filter by what you need, you're looking for the nodeType 3 that represent all the text elements inside the div, the label is just ignored because is nodeType 1, you can learn more about this here in the documentation, there's my example working. I filtered all the next line texts, to give you only the one that you need.
let el = document.getElementById("parent_div"),
child = el.firstChild,
texts = [];
while (child) {
if (child.nodeType == 3) {
texts.push(child.data);
}
child = child.nextSibling;
}
const text = texts.join("").replace(/\n/ig, '');
console.log(text);
<div id="parent_div">
<label>text1</label>
text2
</div>
Here you can now by more specific with what want you want
You can try following (covers scenarios where there can be multiple text nodes scattered around many child nodes)
var response = ""; // result
document.getElementById("parent_div").childNodes.forEach(function(node){
if (node.nodeType === Node.TEXT_NODE) { // check for text nodes
response += node.textContent.trim(); // adding text nodes
}
});
console.log(response); // trim to get rid of leading and trailing spaces
<div id ="parent_div">
<label>text1</label>
text2
</div>
you could do it like this
var cloned = document.getElementById('parent_div').cloneNode(true);
Array.from(cloned.children).forEach(function(child) {
cloned.removeChild(child);
})
var text2 = cloned.innerText;
<div id ="parent_div">
<label>text1</label>
text2
</div>
I'd like to use jquery in such cases. Just because it makes life easy for me :)
And this is the way you can do that
var allOfThat = $("#parent_div")
.contents()
.filter(function () {
return this.nodeType === 3 && this.nodeValue.trim() !== "";
})[0].nodeValue;
console.log(allOfThat)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id ="parent_div">
<label>text1</label>
text2
</div>

how detect mouse click area in document - jquery - javascript

I have a page with a div element in it. i want when i clicked on outer area of that div element, then fade it out.
but i don't know how detect area of mouse click.
how detect that mouse click point is out of div area or not??
This is not very complicated - you have two options:
1. Asign onclick event to the outer area.
<div id="outer" onclick="$("#inner").fadeOut();">
<div id="inner" onclick="event.cancelBubble=true;/*disable bubling*/">Inner Div</div>
</div>
2. Traverse the dom and compare event.target (event.srcElement)
document.addEventListener("click", function(event) {
var body = document.body;
var target = event.target!=null?event.target:event.srcElement;
var inner = document.getElementById("inner");
while(target!=body) {
if(target==inner) //This means our inner element is clicked - or one of its children
return false;
target=target.parentNode; //Go UP in the document tree
}
$("#inner").fadeOut(); //If we got here, none of element matched our inner DIV, so fade it out
}
One possible jQuery solution:
$(document).on("click", function(e) {
var $div = $("#divId");
if (!$div.is(e.target) && !$div.has(e.target).length) {
$div.fadeOut();
}
});
DEMO: http://jsfiddle.net/5Jb5b/
function clickOn(e)
{
var target = e.target;
var optn = [];
optn.id = target.id;
optn.optnClass = target.className.split(' ');
optn.optnType = target.optnName.toLowerCase();
optn.parent = target.parentNode;
return optn;
}
document.body.onclick = function(e)
{
elem = clickOn(e);
var option_id = elem.id;
alert( 'option ID: '+option_id); // From id or other properties you can compare and find in which area mouse click occured
};

How to update only the text of a DIV and not any other child node

<div id='container'>
This is some text
<span> more text </span>
</div>
How can I update only the text section ("This is some text") while not affecting the "span" ?
pure javascript solution
DEMO
var fieldNameElement = document.getElementById('container');
fieldNameElement.removeChild(fieldNameElement.firstChild);
var newText = document.createTextNode("New Text");
fieldNameElement.insertBefore(newText , fieldNameElement.firstChild);
or
Jquery
DEMO
$('#container').each(function(i,el) {
el.firstChild.data = 'New Title Goes Here';
});
var childNodes = elem.childNodes;
for (var i = 0; i < childNodes.length; i++) {
var child = childNodes[i];
if (child.nodeName == "#text") {
elem.removeChild(child);
i--;
}
}
Works in IE7 (that's what I got). You may need to adjust the nodeName check for different browsers, but the overall concept is the same: don't check for firstChild, check for the type of node by way of the nodeName property.
it would be easiest to format it as such with a paragraph tag and use javascript to just change the innerHTML of the paragraph tag. That is the easiest and shortest way to change only that text.
<div id='container'>
<p id="text">This is some text</p>
<span> more text </span>
</div>

Categories