Find div and then go backward to a specific div (jQuery) - javascript

I want to find the matching "identifier" and then add a class to the div with classname "two", for example "found".
html example
<div id="list">
<div class="box">
/* Part ONE */
<div class="one">
<div class="one_one">
<span class="identifier">1234</span>
</div>
</div>
/* Part TWO */
<div class="two"></div>
</div>
...
</div>
I tried:
var identifier = $("#list").find(".box > .one > .one_one > span:contains('1234')");
if (....) {
identifier.closest(".one").addClass("found");
}
I only managed to go back to the div with the classname "one", but I need the div with classname "two" (unfortunately it is outside the parent tree of the identifier).

Traverse the DOM up to a common parent and then find the target element within that parent. For example:
identifier.closest(".box").find(".two").addClass("found");

Related

Change text in a div if another div has a specific attribute

I would like to change a text in a div if another div has a specific attribute, in my case data-value.
In the specific if a div has an attribute data-value="cars" another div should have the text "Buy".
In the specific if data-value="cars" I would like to change the text "1" into "Buy"
<div class="one">1</div>
Here the sample code
<div class="dynamic">
<div class="content">
<div data-value="cars">
Cars
</div>
<div data-value="truck">
Truck
</div>
<div data-value="moto">
Moto
</div>
</div>
</div>
<div class="change">
<div>
1
</div>
<div>
2
</div>
</div>
How can I achieve that in JS?
you need to first perform a query on the existence of any element within the content having the data-value attribute of "cars"
use the document.querySelector() function
if (document.querySelector('.dynamic .content [data-value="cars"]')) ...
then you need to set the text content of all the div elements within the change that have the value 1, using the .textContent attribute
document.querySelectorAll('.change div')
.forEach(div => if( div.textContent=="1") div.textContent="Buy");
putting all pieces together
if (document.querySelector('.dynamic .content [data-value="cars"]')) {
document.querySelectorAll('.change div')
.forEach(div => if(div.textContent=="1") div.textContent="Buy" );
}

JavaScript: Use a wildcard to select all child elements from a PARENT element

I need to select ALL child elements from <div id="VidContainer"> who's ID's pattern is abc- and then a randomly generated number, followed by -container. Ej, "abc-985224562456540-container"
Because the numbers in the middle are randomly generated, a loop won't work. When the numbers have more than 10 digits, JS's engine enters into an "eternal loop" and the browser crashes.
After selecting the elemnets, I need to delete all <div found, with the matching pattern.
What would be the wildcard JavaScript needs to use to select them?
And what would be the best approach to delete those elements?
Dummy HTML:
<div id="VidContainer">
...some more html...
<div id="abc-13-container">Text 13</div>
...some more html...
<div id="abc-9999-container">Text 10</div>
...some more html...
<div id="abc-21540540640-container">Text 19</div>
...some more html...
</div>
I got most of the code. I just can't find a way to get the child element's ID (wildcard)
//Defind element ID
var elementID = "abc" + wildcard + "-container";
var parent = document.getElementById("VidContainer");
//Selet all elements to be deleted
var elements = document.getElementById(elementID);
// Removes an element from the document
while (elements.length) { parent.parentNode.removeChild(elements[0]); }
You can match both the start and end of an attribute with a CSS selector:
var items = document.querySelectorAll("#VidContainer>[id^=abc-][id$=-container]");
console.log("matching items to delete: ", items.length);
for (let item of items) item.remove();
<div id="VidContainer">
<div id="abc-13-container">Text 13</div>
<div id="abc-9999-container">Text 10</div>
<div id="hithere">Hi There</div>
<div id="abc-21540540640-container">Text 19</div>
<div id="something">Something</div>
</div>
You could use querySelectorAll() with the appropriate CSS selector. Not a wildcard solution, but still:
// arrow function to get all the elements
// that are (still) part of the DOM
const getElements = () => {
return document.querySelectorAll('#VidContainer [id^="abc-"][id$="-container"]')
}
// arrow function to DRY code removal
const remE = e => e.parentNode.removeChild(e)
// adding "self-delete on click" to all appropriate elements
getElements().forEach(e => {
e.addEventListener('click', function(e) {
remE(e.target)
})
})
// adding "delete all appropriate elements on click"
document.getElementById('clearAll').addEventListener('click', function(e) {
getElements().forEach(e => {
remE(e)
})
})
[id^='abc-'][id$='-container'] {
font-weight: 700;
cursor: pointer;
}
<div id="VidContainer">
...some more html...
<div id="abc-13-container">Text 13 - click text to remove item</div>
...some more html...
<div id="abc-9999-container">Text 10 - click text to remove item</div>
...some more html...
<div id="abc-21540540640-container">Text 19 - click text to remove item</div>
...some more html...
</div>
<button id="clearAll">Clear all</button>
This is a solution that has all the functions for correct removal (one-by-one or all at once).

find children while moving upwards in dom

This can be sound little confusing but here it is.
What i want is to find the children(OF CLASS PARENT ) when user clicks on class target.
Important: I am not aware of children class & child inside html structure.Target class can be after 'blah' like in first case OR can be directly after children like in second case.
Information available: class "PARENt" and $(this) [class target]
Find: Children(ID) of class PARENT (you cannot use class .children)
<div class="parent">
<div class="children" id="1">
<div class="blah">
<div class="target">TARGET</div>
</div>
</div>
<div class="children" id="2">
<div class="target">TARGET</div>
</div>
<div class="children" id="3">
<div class="blah">
<div class="target">TARGET</div>
</div>
</div>
Example:
Clicking Target 1 would produce: ID = 1
Clicking Target 2 would produce: ID = 2
Clicking Target 3 would produce: ID = 3
If you want to find only ONE ID use:
$('.target').click(function() {
var found = false;
var parent;
var previous;
while(!found) {
if (previous) {
parent = previous.parent();
} else {
parent = $(this).parent();
}
if (parent.hasClass('parent')) {
found = previous;
}
previous = parent;
}
console.log(found.attr('id'));
});
Demo.
To literally answer your question:
$(".parent *") will give you ALL of the children of .parent no matter how many layers deep
To practically answer your question:
Limit possible elements, classes, IDs, etc.
$(".parent div, .parent span, .parent .child ...etc")
You can also grab only the immediate children of an element or set of elements by using the > CSS selector:
$(".parent > *") for example, will give you ALL of the immediate children of .parent
In the context of your problem
$(".target").on("click", function () {
$(this).closest(".parent").children();
// OR
$(this).closest(".parent").find("*");
});
To get the specific ID Given your current DOM structure...
$(".target").on("click", function () {
var id = $(this).closest("[id]").attr("id");
console.log(id);
});
Use .parentsUntil() to get the set of all parents up to (but not including) .parent. Then get the last element of this to get the child of the parent.
$(".target").click(function() {
var child = $(this).parentsUntil(".parent").last();
console.log(child.attr('id'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="parent">
<div class="children" id="1">
<div class="blah">
<div class="target">TARGET</div>
</div>
</div>
<div class="children" id="2">
<div class="target">TARGET</div>
</div>
<div class="children" id="3">
<div class="blah">
<div class="target">TARGET</div>
</div>
</div>
</div>
Another

how to append li tag into ul in angularjs?

I have a html like this
<div>
<div class="submain">
<div><ul><ul><div>
<div g-directive>click</div>
</div>
<div class="submain">
<div><ul><ul><div>
<div g-directive>click</div>
</div>
<div class="submain">
<div><ul><ul><div>
<div ng-directive>click</div>
</div>
<div>
when i click on particular div(click div), i want to append one li tag into the ul tag of before particular clicked div.
i have directive like this, i have tried this but it is not working
app.directive('ngDirective',function()
{
return function(scope,element,attrs)
{
element.bind('click',function()
{
element.prev().children('ul').append('<li></li>');
});
}
});
how to append li tag into ul that is children of div ?
Just a rough example of what you could do:
HTML
<div>
<div class="submain">
<div><ul>
<li ng-show="showLI">{{content}}</li>
<ul><div>
<div ng-click="toggleLI()">click</div>
</div>
<div>
JS
$scope.showLI = false;
$scope.toggleLI = function() {
$scope.showLI = !$scope.showLI;
}
Your code doesn't work, because of wrong element selector. .children searches only the first level of children elements, so basically <div class="submain"> doesn't have children element <ul>. You can use .find('ul') instead, it searches the whole tree downwards

"Cut and Paste" - moving nodes in the DOM with Javascript

I have html code that looks roughly like this:
<div id="id1">
<div id="id2">
<p>some html</p>
<span>maybe some more</span>
</div>
<div id="id3">
<p>different text here</p>
<input type="text">
<span>maybe even a form item</span>
</div>
</div>
Obviously there's more to it than that, but that's the basic idea. What I need to do is switch the location of #id2 and #id3, so the result is:
<div id="id1">
<div id="id3">...</div>
<div id="id2">...</div>
</div>
Does anyone know of a function (I'm sure I'm not the first person to require this functionality) that can read and write the two nodes (and all their children) so as to swap their location in the DOM?
In this case, document.getElementById('id1').appendChild(document.getElementById('id2')); should do the trick.
More generally you can use insertBefore().
This function takes any node that is passed into it and wraps it with the tag given. In the example code snippet I wrapped a span tag with a section tag.
function wrap(node, tag) {
node.parentNode.insertBefore(document.createElement(tag), node);
node.previousElementSibling.appendChild(node);
}
function wrap(node, tag) {
node.parentNode.insertBefore(document.createElement(tag), node);
node.previousElementSibling.appendChild(node);
}
let toWrap = document.querySelector("#hi");
wrap(toWrap, "section");
console.log(document.querySelector("section > #hi"), " section wrapped element");
<span id="hi">hello there!</span>
You can use
insertAdjacentElement instead of appendChild to have more control about the position of element with respect to a target element.
Syntax: targetElement.insertAdjacentElement(position, element).
It has four position codes as:
'beforebegin': Before the targetElement itself.
'afterbegin': Just inside the targetElement, before its first child.
'beforeend': Just inside the targetElement, after its last child.
'afterend': After the targetElement itself.
it appears as:
//beforebegin
<p>
//afterbegin
foo
//beforeend
</p>
//afterend
In your case, you can write the code as:
document.getElementById('id2').insertAdjacentElement('beforebegin', document.getElementById('id3'));
Note that this way, you don't need reference the parent (container) element!
Also consider You have more elements than id2, id3, eg: id4, id5, id6. Now, if you want to reposition for example id5 after id2, its as simple as:
function changePosition() {
document.getElementById('id2').insertAdjacentElement('afterend', document.getElementById('id5'));
}
<div id='container'>
<div id='id1'>id1</div>
<div id='id2'><u>id2</u></div>
<div id='id3'>id3</div>
<div id='id4'>id4</div>
<div id='id5'><b>id5</b></div>
<div id='id6'>id6</div>
</div>
<p><input type='button' onclick="changePosition()" value="change position"></p>
In my opinion is worth adding that if you need just a visual change (the DOM will stay the same but I will change in the UI) you can use the CSS order property.
It is probably more efficient that working on the DOM like the other answers, althought again doesn't really change the DOM structure so of course is not a real answer to this question.
Example:
document.addEventListener("DOMContentLoaded", function () {
const btnEl = document.getElementById('btn-swap');
const elToSwap = document.getElementById('id2');
btnEl.addEventListener('click', e => {
elToSwap.classList.toggle("first");
});
});
.container {
display: flex;
flex-direction: column;
}
.first {
order: -1;
}
<div class="container">
<div id="id1">first DIV</div>
<div id="id2">second DIV</div>
</div>
<button id="btn-swap">swap divs</button>
Short
I just add button (at the bottom) and js to your html
id3.after(id2);
function swap() {
id3.after(id2);
}
<div id="id1">
<div id="id2">
<p>some html</p>
<span>maybe some more</span>
</div>
<div id="id3">
<p>different text here</p>
<input type="text">
<span>maybe even a form item</span>
</div>
</div>
<button onclick="swap()">swap</button>

Categories

Resources