Target an Element within another Element - javascript

I'm looking to try to find an element inside another element then add an ID to it as this is a multi dynamic paged Prince document, so far I have the code below but unsure of how to check if the title__container-page DIV is inside the page-first DIV, as there'as more than one page-first element, I only want to add the ID to any page-first element that contains the title__container-page element, at the moment it's adding that ID to all of them.
<script>
var checkedValue = "title__container-page";
var targetModule = document.getElementsByClassName('page-first');
var checkedArray = checkedValue.split(" ");
console.log(checkedArray);
checkedArray.forEach(function (val, key) {
if (val === "") {
checkedArray.splice(key, 1)
}
if (checkedArray.length > 0) {
targetModule[key].id = "column-padding-top";
}
})
</script>

If you want to target an element inside another element you can use queryselector.
var span = document.querySelector("#whatever .something");
span.id = "newId";
console.log(document.getElementById('newId'));
<div id=whatever>
<span class=something></span>
</div>
If you want to do it the long way you can change the context of getElementsByClassName.
var div = document.getElementById("whatever");
var span = div.getElementsByClassName("something")[0];
span.id = "newId";
console.log(document.getElementById('newId'));
<div id=whatever>
<span class=something></span>
</div>

Here are 5 parent divs with class='page-first', 3 of them containing child divs with class='title__container-page':
<div class='page-first'>
<div class='title__container-page'></div>
</div>
<div class='page-first'>
<div class='title__container-page'></div>
</div>
<div class='page-first'>
</div>
<div class='page-first'>
</div>
<div class='page-first'>
<div class='title__container-page'></div>
</div>
Inspect Element:
The following scans over all parent divs, and adds an ID to the parent found to have a child with class='title__container-page':
$('.page-first').each(function() {
this_childs = $(this).children();
this_childs.each(function() {
if($(this).attr('class') == 'title__container-page') {
add_id = 'div_' + Math.floor((Math.random() * 100000) + 1);
$(this).parent().attr('id', add_id); // add id to page-first element
}
})
})
Inspect Element:
This is assuming you can use jQuery.

Related

How to target tag after a class?

<div class="pre-class">
<div>100%</div>
</div>
I'm trying to remove the percent (%) on the text inside the div after the class pre-class with textContent.replace("%","") but I just can't target that specific div
(I'm working on a longer website with a lot of divs and I can't add an ID to it because it's from a shortcode.)
I thought I could do something like this:
var textContent = document.getElementsByClassName('gamipress-progress-bar-completed').getElementsByTagName('div');
You're basically there. Don't forget that getElementsByClassname returns an array, so simply use [0] to retrieve the element. You'll see it working in the snippet below:
var textContent = document.getElementsByClassName('pre-class')[0].getElementsByTagName('div')[0].innerHTML;
console.log(textContent)
<div class="pre-class">
<div>100%</div>
</div>
You can use querySelector
let div = document.querySelector('div.pre-class > div');
div.innerText = div.innerText.replace('%', '')
<div class="pre-class">
<div>100%</div>
</div>
If the div will be the first direct child of the pre-class div, and you have one element with "pre-class" class, this will work
const textContent = document.querySelector('.pre-class').firstElementChild.textContent;
console.log(textContent.replace('%', ''))
<div class="pre-class">
<div>100%</div>
</div>
const content = document.querySelector('.pre-class > div').innerHTML;
content.replace("%", "");
<div class="pre-class">
<div>100%</div>
</div>
This is another way of selecting the div nested in your .pre-class div. Perhaps not the best way of doing this but it's handy to know querySelector works.
If you have lots of divs inside div.pre-class , its better to add specific data attribute to each child div and select the desired div using this:
< div class = 'pre-class' >
<div data-order = 'first' > 1 < /div>
<div data-order = 'second' > 2 < /div>
<div data-order = 'third' > 3 < /div>
</div>
///////////
document.querySelector('div[data-order="first"]')
let containers = document.getElementsByClassName("pre-class");
for (var i = 0; i<containers.length; i++) {
let current = containers[i];
let textNode = current.children[0];
textNode.innerText = textNode.innerText.replace(/(\d)%/, '$1');
};
<div class="pre-class">
<div>100%</div>
</div>
Alternatively, you could use element.querySelector() (or querySelectorAll) to find the correct element(s) to replace.
let textNode = document.querySelector(".pre-class > div"); // use querySelectorAll in case there can be multiple matches.
textNode.innerText = textNode.innerText.replace(/(\d)%/, '$1');
<div class="pre-class">
<div>100%</div>
</div>
Use the child selector (>).
let textDiv=document.querySelector(".pre-class > div");
textDiv.textContent=textDiv.textContent.replace("%","");
This will replace the first direct div inside .pre-class. You can adjust the position of divs using pseudo classes. Like for example, if you want to select the second div inside .pre-class, you would use:
<div class="pre-class">
<div>100%</div>
<div>200%</div>
<div>300%</div>
</div>
let textDiv=document.querySelector(".pre-class > div:nth-child(2)");
textDiv.textContent=textDiv.textContent.replace("%","");

Javascript how to append node in its correct index with wrapper

I need to get user entered markup (tables) and if the table does not contain a div with a the class="table", I need to add the div & class. I need to ignore any other children, such as p, span, and only target elements with tables.
<div class="parent">
<div class="table"><table></table></div>
<div class="table"><table></table></div>
<table></table>
<div><table></table></div>
<div class="table"><table></table></div>
<p></p>
<span></span>
</div>
You can see in the nodelist above, node index 2,3 both need a wrapper div with the class="table", but ignore the p and span.
[].map.call(table, (node) => {
if (!node.parentNode.classList.contains('table')) {
const parent = document.getElementsByClassName('parent');
[].map.call(parent, (nodeChild) => {
const addWrap = document.createElement('div');
addWrap.classList.add('table');
addWrap.appendChild(node);
nodeChild.append(addWrap);
});
}
});
I have tried this, but it appends the node with a wrapper div at the bottom of the index. How do I get the nodes to append in their correct order with the wrapper div? Thanks.
You're better off using a for/loop (using map here is an anti-pattern) to iterate over the child nodes of the parent node and replace the current child node with the new created element.
childNodes
replaceChild
Inspect the output in dev tools to see the change.
const parent = document.querySelector('.parent');
const { childNodes } = parent;
for (let i = 0; i < childNodes.length; i++) {
const el = childNodes[i];
// If the node type is an element
if (el.nodeType === 1) {
// If element is a div add a class
// if it's missing
if (el.tagName === 'DIV' && !el.classList.contains('table')) {
el.classList.add('table');
}
if (el.tagName === 'TABLE') {
const div = document.createElement('div');
div.classList.add('table');
div.appendChild(el);
// Replace the child node with the new div node
parent.replaceChild(div, childNodes[i]);
}
}
};
<div class="parent">
<div class="table"><table></table></div>
<div class="table"><table></table></div>
<table></table>
<div><table></table></div>
<div class="table"><table></table></div>
<p></p>
<span></span>
</div>
I think I understood what you're trying to do. This should find child nodes without a "table" class and wrap them in a div with a "table" class. When you run the snippet it won't show any thing as your elements don't have any content but you should be able to inspect them to see the changes.
// get all parent divs
var parents = document.getElementsByClassName("parent");
// loop over parent divs
for (var i = 0; i < parents.length; i++) {
// get a single parent div
var parent = parents[i];
// loop over child nodes
for (var j = 0; j < parent.childNodes.length; j++) {
// get a single child node
var childNode = parent.childNodes[j];
// if this child node is type 1 (element node)
// and does not have a class of table
if (
childNode.nodeType === 1 &&
!childNode.classList.contains("table")
) {
// create a new div element
var wrap = document.createElement('div');
// give it a class of table
wrap.classList.add("table");
// append a clone of the child node
wrap.appendChild(childNode.cloneNode());
// replace the old child node with the wrapped child node
parent.replaceChild(wrap, childNode);
}
}
}
<div class="parent">
<div class="table"></div>
<div class="table"></div>
<table></table>
<div></div>
<div class="table"></div>
</div>

How to get outermost parent node of inner child in plain JavaScript?

I got stuck in a problem, I wish to write a script that can show all the div ids of an inner div, for example:
<body id="bd">
<div id="canvas">
<div id="nd1">
<div>
My text
</div>
</div>
<div id="nd2">
<div id="hd">Some Text</div>
<div>
<div>
What I want is suppose when I click on div with no ID defined inside "nd1", I should get its parent div (i.e. nd1), and the outermost parent, kind of thing I want.
try
var allChildNodes = document.querySelectorAll("#nd1 div");
nodes = Array.prototype.slice.call(allChildNodes ,0);
nodes.forEach(function(node){
node.addEventListener("click", function(){
console.log("Outer parent" + node.parentNode.outerHTML);
console.log("Outermost parent" + node.parentNode.parentNode.outerHTML);
});
});
To get the array of parent divs
var allChildNodes = document.querySelectorAll("#nd1 div");
nodes = Array.prototype.slice.call(allChildNodes ,0);
nodes.forEach(function(node){
node.addEventListener("click", function(){
var parentDivs = [];
while( !node.parentNode )
{
parentDivs.push(node.parentNode);
node = node.parentNode;
}
console.log("parents" + parentDivs);
});
});
For matching multiple divs starting from a specific string
var allChildNodes = document.querySelectorAll("[id^='nd'] div");

Finding the value of a class within a list

I have
<ul id="list">
<li data-markerid="0" class="">
<div class="list-label">A</div>
<div class="list-details">
<div class="list-content">
<div class="loc-id">2</div>
<div class="loc-addr">England</div>
<div class="loc-dist">2 miles</div>
<div class="loc-addr2">Test</div>
<div class="loc-addr2">Bristol</div>
</div>
</div>
</li>
<li data-markerid="1" class="">
<div class="list-label">A</div>
<div class="list-details">
<div class="list-content">
<div class="loc-id">3</div>
<div class="loc-addr">England</div>
<div class="loc-dist">60 miles</div>
<div class="loc-addr2">Test</div>
<div class="loc-addr2">London</div>
</div>
</div>
</li>
</ul>
I'm wanting to extract the value of this using JQuery.
I tried:
var targetID = $(this).find('.loc-id').text();
But this gets me values of both loc-id's. I want just the one that I'm selecting (clicking).
For full context, please look here: Parsing data using JQuery
$('#list').click(function () {
//Change the src of img
var targetID = $(this).find('.loc-id').text(); // Get the ID
// Since array of objects isn't indexed, need to loop to find the correct one
var foundObject = null;
for (var key in parsedArray) {
if (parsedArray.hasOwnProperty(key) && parsedArray[key].id == targetID) {
foundObject = parsedArray[key];
break;
}
}
// If the object is found, extract the image and set!
if (!foundObject)
return;
var imageSrc = foundObject.LocationPhoto; // From the object
$('#location-image').attr('src', imageSrc); // Set the new source
});
Thanks
In your click handler, this references the <ul> element which has multiple <li> children.
Change the click handler to act as a delegate instead:
$('#list').on('click', 'li', function () {
Now, inside the click handler, this references an <li> element so the search should only yield a single value.
For var targetID = $(this).find('.loc-id').text(); to work, you must be clicking an element that is an ascendant of only one .loc-id. For example:
$('.list-details').on('click',function(){
var targetID = $(this).find('.loc-id').text();
});
You need to change selector. In your event handler. $(this) referes to ul which has multiple loc-id thus when you are using text() its concatenating text.
Use
$('#list li').click(function () {
//Change the src of img
var targetID = $(this).find('.loc-id').text(); // Get the ID
alert('targetID: ' + targetID)
});
instead of
// When we select the item
$('#list').click(function () {
//Change the src of img
var targetID = $(this).find('.loc-id').text(); // Get the ID
DEMO
You could use event.target in case you are delegating on #list:
Demo: http://jsfiddle.net/abhitalks/CxcU8/
$("#list").on("click", function(e) {
var $t = $(e.target);
if ($t.hasClass('loc-id')) {
alert($t.text());
}
});

swap 2 div's index using pure javascript

I have a parent div and it has 9 same div's am trying to swap two div's index. Following is my code:
HTML:
<div id="cont" class="container">
<div class="no">1</div>
<div class="no">2</div>
<div class="no">3</div>
<div class="blank"></div>
<div class="no">4</div>
<div class="no">5</div>
<div class="no">6</div>
<div class="no">7</div>
<div class="no">8</div>
</div>
now I want to swap say 5th and 6th indexed elements. I have no clue how to do that in JavaScript. I know there is function called .index() but how to do that in pure JS.
Here's one implementation: http://jsfiddle.net/x8hWj/2/
function swap(idx1, idx2) {
var container = document.getElementById('cont');
// ditch text nodes and the like
var children = Array.prototype.filter.call(
container.childNodes,
function(node) {
return node.nodeType === 1;
}
);
// get references to the relevant children
var el1 = children[idx1];
var el2 = children[idx2];
var el2next = children[idx2 + 1];
// put the second element before the first
container.insertBefore(el2, el1);
// now put the first element where the second used to be
if (el2next) container.insertBefore(el1, el2next);
else container.appendChild(el1);
}
This starts by getting a list of all element child nodes, then uses insertBefore to rearrange them.

Categories