How to target a div using content inside the div - javascript

I have 2 divs with same class name but different strings inside the div. I want to use an insertAfter the first div to display some additional text, but the text is being displayed under both divs:
<div class='test'>First Div</div>
<div class='test'>Second Div</div>
My approach:
if ( document.getElementsByClassName('test')[0]
&& document.getElementsByClassName('test')[0].innerHTML == 'First Div'
) {
$('<h2>Inserting New Text</h2>').insertAfter('.test')[0];
}
But this adds the text after both the First Div and the Second Div. I want to know if there is a way to insert only once or insert after matching the string

Just keep it simple, find all elements with target class and pick the first one:
const el = document.getElementsByClassName('test')
$('<div>new text</div>').insertAfter(el[0])
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='test'>First Div</div>
<div class='test'>Second Div</div>

You can ask javascript to find the elements of the class and then convert the result into an array and find the first element that matches your condition.
const elements = Array.from(document.getElementsByClassName("test"));
const target = elements.find(el => el.innerHTML === 'First Div');
$('<h2>Inserting New Text</h2>').insertAfter(target);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='test'>First Div</div>
<div class='test'>Second Div</div>

No need for jQuery here. Use insertAdjacentHTML to add the new element.
// Pick up the first element with the test class
const el = document.querySelector('.test');
// Use `insertAdjacentHTML` to add the new div after it
el.insertAdjacentHTML('afterend', '<div>new text</div>');
<div class="test">First Div</div>
<div class="test">Second Div</div>

Related

Javascript: getelementsbyid inside of class that is changing (active)

This is my HTML code:
<div class="foo active">
<div id="bar">
Hello world!
</div>
</div>
Hello world!
The div class active is always changing so i first need to get into the class foo active
How can I get to change "Hello world!"?
var targetDiv = document.getElementByClassName("foo active")[0].getElementsById("bar");
is not working.
I know when the code is like this:
<div id="foo">
<div class="bar">
Hello world!
</div>
</div>
I just need to:
var targetDiv = document.getElementById("foo").getElementsByClassName("bar")[0];
You just need to target the ID of "bar".
document.getElementById("bar").innerHTML = "new text";
If you want to access an element with an id in HTML, you do not have to use:
var targetDiv = document.getElementByClassName("foo")[0].getElementsById("bar");
You can simply do this:
var targetDiv = document.getElementsById("bar");
Also, You need something to run the code. Example if you click a button the text changes or if you want the text to change as soon as the DOM content loads you can add the DOMContentLoaded event listener.
Try this code:
<div class="foo">
<div id="bar">
Hello world!
</div>
<button onClick = "changeText()">Change Text!</button>
changeText = () => {
const targetVar = document.getElementById("bar");
targetVar.innerHTML = "Something else!";
}
To provide some context as to why this is happening, getElementById and getElementsByClassName return an Element and an array of Elements respectively. The Element object has a series of functions available to call, including (but not limited to) getElementsByClassName. However, the getElementById function is not available on Elements, only on the Document object itself, meaning that you can't call it in the way you were attempting to in your first example.
To circumvent this, you can either find the element by ID straight away and work from there
var targetDiv = document.getElementById("foo")
or you can use querySelector and querySelectorAll
const targetDiv = document.querySelector(".foo.active #bar")
// The result you want
const targetDiv = document.querySelector(".foo.active #bar")
console.log(targetDiv)
// An example of a result not filtered by the active class
const exampleDiv = document.querySelectorAll(".foo #bar")
console.log(exampleDiv)
<div class="foo active">
<div id="bar">
Hello world!
</div>
</div>
<div class="foo inactive">
<div id="bar">
Hello world!
</div>
</div>
Note that ideally there is only one element with a given ID on a page as IDs are intended to be unique. With that being said, my example isn't best practice, but it sounds like in your example there may be multiple elements with the same ID.

javascript replace node and all of it childs with anothe code

How can you replace HTML tag with all tags branching inside using Javascript with other HTML code?
example:
<div class="a">
<div class="sub-a1">
<div class="sub-a12">
</div>
</div>
<div class="sub-a2">
<div class="sub-b">
</div>
</div>
I wanna replace all tags from tag div class 'a' including all sub nodes with another code.
is that's possible?
please help me.
const target = document.querySelector(".a");
target.innerHTML = //place your html here as string
Yes, this is possible. If you want to keep the div.a elements and just change the "subnodes" you have to use innerHTML in stead of outerHTML.
const divs = [...document.getElementsByClassName("a")]; //make a copy of the HTML collection so that they can be removed without being removed in the array
const newElement = "<h1>Replaced Element</h1>"; //this is your replacement element
for (let i = 0; i < divs.length; i++) { // loop through all the divs
divs[i].outerHTML = newElement; // set the outer html for the div to the replacement elemzent
}
You can do with .replaceWith() with a valid HTML code.
function replace() {
var para = document.createElement("P"); // Create a <p> element
para.innerText = "This is a paragraph"; // Insert text
document.querySelector(".a").replaceWith(para);
}
<div class="a">
<div class="sub-a1">
<div class="sub-a12">
<h4>Sample content1</h4>
</div>
</div>
<div class="sub-a2">
<div class="sub-b">
<h4>Sample content2</h4>
</div>
</div>
</div>
<button onclick="replace();"/>Click to Replace</button>

How to select leaf node using jQuery :contains selector?

I want to get leaf elements containing specific text, and I used :contains selector. However, this selector selects includes every parent nodes too. Here is my example.
<div id='parent1'>
<p id='target1'>Red balloon</p>
<div id='target2'>Blue balloon</div>
</div>
<div id='parent2'>
<span id='target3'>Brown balloon</span>
</div>
In this case, I just want to get elements containing text balloon. I expected to get 3 elements(target1, target2, target3) by $(":contains('balloon')"), but it returns every nodes including parent nodes of targets. (e.g. html, body, and every parent div)
How can I select only targets?
p.s Above HTML is only example. HTML can be vary, so the answer should be generic.
use indexOf("balloon") > -1 to find id the word balloon is found
var arr = $("div").children().map(function(){
if($(this).text().indexOf("balloon") > -1 )
return $(this).attr("id")
}).get();
console.log(arr)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='parent1'>
<p id='target1'>Red balloon</p>
<div id='target2'>Blue balloon</div>
</div>
<div id='parent2'>
<span id='target3'>Brown balloon</span>
</div>
The solution below, look for all elements containing the word and clone these elements, This way we can be sure only to get "correct" amount of elements
Just remove .length and you have access to the elements.
var s = $(":contains('balloon')").not("script").filter(function() {
return (
$(this).clone() //clone the element
.children() //select all the children
.remove() //remove all the children
.end() //again go back to selected element
.filter(":contains('balloon')").length > 0)
}).length;
console.log(s)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='parent1'>
<p id='target1'>Red balloon</p>
<div id='target2'>Blue balloon</div>
</div>
<div id='parent2'>
<span id='target3'>Brown balloon</span>
</div>

Targeting Multiple Elements with One Function

I have a function that assigns dynamic classes to my div's. This function is a that runs on the page. After the page loads, all 10 of my primary 's have classes ".info1" or ".info2" etc...
I am trying to write a Jquery function that changes the class of the div you click on, and only that one. Here is what I have attempted:
$(".info" + (i ++)).click(function(){
$(".redditPost").toggleClass("show")
});
I have also tried:
$(".info" + (1 + 1)).click(function(){
$(".redditPost").toggleClass("show")
});
And
$(".info" + (i + 1)).click(function(){
$(".redditPost").toggleClass("show")
});
EDITED MY HTML: DIV RedditPost is actually a sibling to Info's parent
<div class="listrow news">
<div class="newscontainer read">
<div class=".info1"></div>
<div class="redditThumbnail"></div>
<div class="articleheader read">
</div>
<div class="redditPost mediumtext"></div>
</div>
My issue is two fold.
The variable selection for ".info" 1 - 10 isn't working because i doesn't have a value.
If I did target the correct element it would change all ".redditPost" classes instead of just targeting the nearest div.
Try like this.
$("[class^='info']").click(funtion(){
$(this).parent().find('.redditPost').toggleClass("show");
});
Alternative:
$('.listrow').each(function(){
var trigger = $(this).find("[class^='info']");
var target = $(this).find('.redditPost');
trigger.click(function(){
target.toggleClass("show");
});
});
Try this
$("div[class*='info']").click(function(){
$(this).parent().find(".redditPost").toggleClass("show")
});
Explanation:
$("div[class*='info'])
Handles click for every div with a class containing the string 'info'
$(this).parent().find(".redditPost")
Gets the redditPost class of the current clicked div
Since the class attribute can have several classes separated by spaces, you want to use the .filter() method with a RegEx to narrow down the element selection as follows:
$('div[class*="info"]').filter(function() {
return /\binfo\d+\b/g.test( $(this).attr('class') );
}).on('click', function() {
$(this).siblings('.redditPost').toggleClass('show');
});
.show {
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="listrow news">
<div class="newscontainer read">
<div class="info1">1</div>
<div class="redditThumbnailinfo">2</div>
<div class="articleheader read">3</div>
<div class="redditPost mediumtext">4</div>
</div>
</div>

How do I use a function argument for this jquery code, or is there a better solution?

I have about 50 p tags and next to these are again 50 divs. on click of each p tag, its div should be shown and the rest hidden. How do i acheive this. I can use something like below:
$(function() {
$('.p1').click(function(){
$('.div1').show();
$('.div2','.div3','.div4','.div5','.div6',.........,'.div50').hide()
})
$('.p2').click(function(){
$('.div2').show();
$('.div1','.div3','.div4','.div5','.div6',.........,'.div50').hide()
})
//////////////
//////
})
but as you see that this is not an effiecient solution. I am also not sure how the jquery each can be leveraged here or how can this implementation be done using arrays. Can somebody point me in the right direction. I think we should use a function and pass that no. as a parameter, but I dont know how to use custom functions in jquery.
UPDATE:
This is what I have done
$(function() {
$('.p1').click(function() {
$('.div').hide();
$('.d1').show();
})
})
I have added the class div to all of my 50 divs and I am showing d1 on click of p1. Now how do I replace 1 for each instance till 50.
I would have a common class to all div and p so that the binding the handler and the hide can be simple. And for the div, I would associate a data-tag to each p to link each p tag to div
<p class="p1 pclass" data-showdiv="div1">
...
</p>
<p class="p2 pclass" data-showdiv="div2">
..
<div class="mydiv div1" ..>
..
</div>
<div class="mydiv div2" ..>
..
</div>
And the script would be,
$(function() {
$('.pclass').click(function(){
$('.mydiv').hide();
$('.' + $(this).data('showdiv')).show();
});
});
As Jason told,
Use this
$('p').click(function() {
$('div').hide();
$(this).next('div').show();
});
If the div is next to each paragraph.
But, if there's an element between p and div, it wont work.
For you problem, you can do,
$('p').click(function() {
$('div').hide();
var divClass = $(this).attr("class").replace('p','div');
$('.' + divClass).show();
});
provided you have only p1, p2 .... in paragrah classes ;)
Update
See this fiddle
Notice , we have <br> tags between <p> and <div> as you wanted.
Assuming your HTML structure is
<p>Some text</p>
<div>More text to hide and show</div>
<p>Some text</p>
<div>More text to hide and show</div>
<p>Some text</p>
<div>More text to hide and show</div>
....
Use the following in your $(function(){}); method:
$('p').click(function() {
$('div').hide();
$(this).next('div').show();
});
var dvs = ['.div1','.div2','.div3','.div4','.div5','.div6',.........,'.div50'];
$('p').click(function() {
var index = parseInt(this.className.replace('p','')) - 1;
$(dvs[index]).show();
$(dvs.join(', ')).not(dvs[index]).hide();
});
The jQuery click event will automatically be registered on all elements that match the selector, so you shouldn't have to use the each() method. I would suggest having two CSS classes to distinguish between elements that have this toggling behaviour and elements that are primary (i.e. should be shown when their parent is clicked).
The markup:
<body>
<p class="togglable">
<div class="primary">
This is the primary div that will be shown when our parent is clicked.
</div>
<div>Regular div child</div>
<p>Nested paragraph</p>
<ul>
<li>A list perhaps</li>
</ul>
</p>
<p class="togglable">
<div class="primary">
This is the primary div that will be shown when our parent is clicked.
</div>
<div>Regular div child</div>
<p>Nested paragraph</p>
<ul>
<li>A list perhaps</li>
</ul>
</p>
<p>This is a normal paragraph</p>
</body>
The code:
$(function () {
$('.togglable').click(function () {
// hide all our children
$(this).children().hide();
// now only show our primary chlid
// NOTE: we pass 'this' as the second argument
// so that the selector will only apply to the
// children of the element that was clicked
// (i.e. we are providing a custom context for the selector).
$('.primary', this).show();
// You could even use the position of the child as well:
// $(this).children().first().show();
// This will show the first child element.
});
});
In this example all elements with the class togglable will show their primary child element when clicked and hide all other child elements.

Categories