Toogle div based on span class value - javascript

I have the following block
<div id="discountText">
<span>some text</span>
<span class="discountType" style="display:none;">
</div>
installerDiscountType contains a discount type (preferred, saved, etc.)
How do I show the div in case <span class="discountType" equals "AAA" and hide it in case it equals something else?
I tried multiple ways but I keep getting undefined values.

This will show "Some Text AAA" It shows "Some Text" because that span does not have class "discountType"
let types = document.querySelectorAll('.discountType')
types.forEach(node => {
if(node.innerText !== "AAA") {
node.style.display = 'none';
}
})
<div id="discountText">
<span>some text</span>
<span class="discountType">Hello world</span>
<span class="discountType">AAA</span>
</div>

Related

How to strip html tags out of selection

I want to strip html tags out of a selected text which is inside a content editable div. Lets say selected text is something like this:
<div contenteditable="true">
<span style="color:red">some text</span>
</div>
So I tried this:
window.getSelection().anchorNode.parentNode.replace(/<\/?[^>]+>/gi, '');
but I get an error that says replace is not a function. I tried also this below:
window.getSelection().anchorNode.parentNode.remove();
but this will remove also the text. Whats the deal here?
Thank you.
Like this
const editable = document.querySelector('div');
const button = document.querySelector('button');
button.addEventListener('click', () => {
alert(editable.innerText);
});
<div contenteditable="true">
<span style="color:red">some text</span>
</div>
<button>Show me the text</button>

get a nested element inside a div by class name

I am trying to get an span element which has a class of main-tag inside a nested div. But i don't want to get that element through querySelector as there are many elements in my html file with the same class and i don't intend to use IDs for that.
I know i am making some mistake in my recursive function. That's why this code is not working.
So for this i'm recursively calling a function to get the desired element. But undefined is returned by found variable.
function getElem(cell, name) {
let found;
if (cell.classList.contains(name)) return cell;
else if (cell.children.length === 0) return null;
else {
found = Array.from(cell.children).find((element) =>
element.classList.contains(name)
);
if (found === undefined) {
Array.from(cell.children).forEach((element) => {
found = getElem(element, name);
});
} else return found;
}
}
console.log(getElem(document.getElementById("block-one"), "main-tag"));
<div id="block-one">
<div class="something-one">
<span class="something-two">Hello</div>
<span class="abc">not found</div>
</div>
<div class="here">
<span class="main-tag">Yes, i am here</div>
<span class="bogus-tag">never find out</div>
</div>
</div>
Your markup is using </div> where </span> is expected.
You can use full CSS selectors with querySelector. So for instance, to find the first element with the class main-tag inside the element with id="block-one", you can do this:
const element = document.querySelector("#block-one .main-tag");
Live Example:
console.log(document.querySelector("#block-one .main-tag"));
<div id="block-one">
<div class="something-one">
<span class="something-two">Hello</span>
<span class="abc">not found</span>
</div>
<div class="here">
<span class="main-tag">Yes, i am here</span>
<span class="bogus-tag">never find out</span>
</div>
</div>
Or alternatively, you can call querySelector on an element to only look at its descendants:
const element = document.getElementById("block-one").querySelector(".main-tag");
Live Example:
console.log(document.getElementById("block-one").querySelector(".main-tag"));
<div id="block-one">
<div class="something-one">
<span class="something-two">Hello</span>
<span class="abc">not found</span>
</div>
<div class="here">
<span class="main-tag">Yes, i am here</span>
<span class="bogus-tag">never find out</span>
</div>
</div>
A key difference between those is that the second one will throw an error if there is no id="block-one" element; the first will just return null. You could fix that using the newish optional chaining operator:
const element = document.getElementById("block-one")?.querySelector(".main-tag");
element will be either A) The matching element if there is one; B) null if there's an id="block-one" element but there are no .main-tag elements in it; or C) undefined if there is no id="block-one" element at all. (Even though document.getElementById returns null when it doesn't find something, the optional chaining operator results in undefined when its left-hand operand is either undefined or null.)
Or just use the document.querySelector option (the first one above), which gives you the matching element or null.
You don't seem to want this from your HTML, but: If you want to allow for the possibility the element itself has the class (getElem seems to allow for that possibility), you can use a group selector:
const element = document.querySelector("#block-one.main-tag, #block-one .main-tag");
Live Example:
console.log(document.querySelector("#block-one.main-tag, #block-one .main-tag"));
<div id="block-one" class="main-tag">
<div class="something-one">
<span class="something-two">Hello</span>
<span class="abc">not found</span>
</div>
<div class="here">
<span class="main-tag">Yes, i am here</span>
<span class="bogus-tag">never find out</span>
</div>
</div>
That works because the first member of the group, #block-one.main-tag (without a space) only matches the id="block-one" element if it has the class. If block-one doesn't have the class but one of its descendants does, that's found by the other member of the group, #block-one .main-tag (with the space). If the block-one element has the class and one of its descendants does, the block-one element is the one found, since it's first in document order (a parent is before its children in document order).
Your HTML is invalid.
When fixed, you can get the span using selectors directly
console.log(document.querySelector("#block-one > div.here > span.main-tag").textContent)
<div id="block-one">
<div class="something-one">
<span class="something-two">Hello</span>
<span class="abc">not found</span>
</div>
<div class="here">
<span class="main-tag">Yes, I am here</span>
<span class="bogus-tag">never find out</span>
</div>
</div>

Javascript targeting the parent div from a string of text

<div class="myDiv">
<span class="mySpan">SAMPLE TEXT A</span>
<span class="mySpan">SAMPLE TEXT B</span>
</div>
I'm struggling to get the right javascript to hide "myDiv" if the text in "mySpan" is "SAMPLE TEXT A".
Somehow like this (you will not see anything, because <div class="myDiv"> is hidden already):
var spans = document.getElementsByClassName('mySpan')
for(var i = 0; i < spans.length; i++) {
if(spans[i].innerHTML === 'SAMPLE TEXT A') spans[i].parentElement.style.display = 'none';
}
<div class="myDiv">
<span class="mySpan">SAMPLE TEXT A</span>
<span class="mySpan">SAMPLE TEXT B</span>
</div>
UPDATE
"What is the significance of the 'for' statement?"
document.getElementsByClassName('mySpan') will select ALL elements with class mySpan, think about it as an array. Then i iterate through all selected span's and finding the case, where innerHTML is equal to our specific string.
"In the if statement, how would I specify just the parent div and not every element with class "myDiv"? There are other elements on the page with that class."
If so, you need to use parentElement (I have updated my answer with needed row).

Replace only text content inside DIV using JavaScript

I want to change only text content inside an h1 tag. Here's my code:
<h1 id="pageTitle" class="ms-core-pageTitle">
<span id="DeltaPlaceHolderPageTitleInTitleArea">
<span>
<span>
<a title="some title" href="/link/page.aspx">Change only this text and keep the rest</a>
</span>
</span>
</span>
</h1>
I've tried this code :
document.getElementById("DeltaPlaceHolderPageTitleInTitleArea").innerHTML = "text changed";
But it doesn't work, here's the result:
<h1 id="pageTitle" class="ms-core-pageTitle">
<span id="DeltaPlaceHolderPageTitleInTitleArea">text changed</span>
</h1>
Any help would be appreciated
You have to use querySelector() method, in order to change text content of hyperlink.
document.querySelector("#pageTitle a").innerHTML = "text changed";
<h1 id="pageTitle" class="ms-core-pageTitle">
<span id="DeltaPlaceHolderPageTitleInTitleArea">
<span>
<span>
<a title="some title" href="/link/page.aspx">Change only this text and keep the rest</a>
</span>
</span>
</span>
</h1>
What you are doing is changing "DeltaPlaceHolderPageTitleInTitleArea" 's innerHTML therefore you replace :
<span>
<span>
<a title="some title" href="/link/page.aspx">Change only this text and keep the rest</a>
</span>
</span>
with:
text changed
What you wanted to change is the title's text am I right ? To do so :
really basic JS:
document.getElementById("DeltaPlaceHolderPageTitleInTitleArea").children[0].children[0].children[0].innerHTML = "text changed";
a bit more advanced :
document.querySelector("DeltaPlaceHolderPageTitleInTitleArea > span > span > a").innerHTML = "text changed";
Or using jQuery :
$("DeltaPlaceHolderPageTitleInTitleArea > span > span > a").text("text changed");
You can try out this.
function changeContent(){
var element = document.getElementById('DeltaPlaceHolderPageTitleInTitleArea');
element.children[0].innerHTML = "whatever";
}
<h1 id="pageTitle" class="ms-core-pageTitle">
<span id="DeltaPlaceHolderPageTitleInTitleArea">
<a title="some title" href="/link/page.aspx">Change only this text and keep the rest</a>
</span>
<button name="change content" onClick="changeContent()">change content</button>
</h1>
You are pointing to the id of the h1 tag and not the anchor ()tag containing the text to be changed. this im not not sure will allow you to insert the text exactly where you want it to be. using the query selector or any other means of selecting the tag wrapping the text you what to change will surely do. if you dont mind, jquery selector will do the job much easier
you can try something like $("#DeltaPlaceHolderPageTitleInTitleArea a").text("")

Surround only text with node

I have some html that is in the form
<span class="prefix">something</span> (Optional)
Text
<span class="badge">Something else</span> (optional, can be multiple)
<span class="postfix">Another thing</span>
And I want to wrap the Text, but not the spans, in another span so that I can extract and replace it using jQuery as necessary. I can't edit the back end code that is generating this HTML. Given that I don't know in advance whether the first span will be there, or how many spans there will be at the end, is there any way to wrap the plain text so that it can be operated on?
I am hoping to get an output that looks something like this:
<span class="prefix">something</span>
<span class="txt">Text</span>
<span class="badge">something else</span>...
<span class="postfix">another thing</span>
Try this:
$('#container').contents()
.filter(function() { return this.nodeType === 3 })
.wrap('<span class="txt" />');
Based on this answer: https://stackoverflow.com/a/5291776/616535
filter() the contents() of the container element to those that are pure text nodes
wrap() them in a span
$('#container').contents().filter(function() {
return $(this)[0].nodeValue && $(this)[0].nodeValue.trim();
}).wrap('<span class="txt"/>');
.txt{
color:green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="container">
<span class="prefix">something</span>
Text
<span class="badge">Something else</span>
<span class="postfix">Another thing</span>
</div>

Categories