Change innerHTML of span which part of the name changes in time - javascript

I'm trying to change the .innerHTML of a span for which the name changes every time I refresh the page (only some part of that name changes)
So for example, I always use this to change the span's innerHTML:
document.getElementsByClassName('something')[0].innerHTML='new text';
but my problem is that the site now adds random characters after that "something", for example:
<span class="something RANDOM123 random212312">some text</span>
and my question is, is this possible to find this span and change the innerHTML of it just by looking for the first part of the class name which is "something"?

Maybe you can use partial selector:
$('[class^="value"]') <-- starts with string
$('[class$="value"]') <-- ends with string
// using jQuery
$('[class^="something"]')[0].innerHTML='new text';
// using document
document.querySelectorAll('[class^="something"]')[1].innerHTML='new other text';
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="something RANDOM123 random212312">some text</span>
<span class="something RANDOM123 random212312">some other text</span>

Can you just add an ID to the spans you want to update? Then just search by those IDs? That's likely the correct way to do it. Otherwise, you might have to write your own thing that loops through the collection of spans in the document and check the class to see if it starts with "something" (prehaps indexOf === 0).
function GetSomethingSpans() {
const AllSpans = document.getElementsByTagName('span');
const AllSpanCount = AllSpans.length;
const SomethingSpans = [];
for (var i = 0; i < AllSpanCount; i++) {
if (AllSpans[i].className.indexOf("something") === 0) {
SomethingSpans.push(AllSpans[i]);
}
}
return SomethingSpans;
}
This is entirely untested, and there might be bugs. But hopefully it's a useful starting point. Could probably adjust it to have a parameter that is the class you're looking for, and you don't have to make it be the first class... hopefully this gets you going.

document.querySelectorAll("something") will retrieve all elements that have that class, regardless of what others classes are added to the element.

Related

Avoiding extra use of span

My question is that I have an html code <p> Hello World </p>
And want to change the css of every letter using JavaScript. Essentially, I will change the background color to make an animation. Is there a way to do this without making a span or some sort of tag around every letter and going through all that struggle?
I have my string array with colors and a method to call the correct color (data-index attribute).
Thanks!
EDIT: I have the entire word changing color and thought of an idea by making a function that iterates over the indexes of the innerHTML string and assigns a data-index to the letter's span by editing the function provided below by Cymen. Is this a good approach?
No, you will need to use a tag that supports background-color. You can easily wrap a string of characters in spans like so:
function wrapInSpans(string) {
return '<span>' + string.split('').join('</span><span>') + '</span>';
}
You would have to use a JavaScript function to wrap each character in a <span>.
window.onload = function() { // when everything loads, run the function
var elem = document.getElementById( "someId" );
var text = elem.innerHTML; // get the <p>'s text content
elem.innerHTML = ""; // then make the <p> empty
for( var i=0; i<text.length; i++ ) { // for each character in the text
elem.innerHTML += "<span>"+text[i]+"</span>";
}
};
Remember to change "someId" to the id of your <p> element.
You can access each individual character inside the for loop with text[i].
This would take quite a bit of code to spell out completely, but, if it's very important in your case to not actually add some type of wrapping element, then I believe this would be possible via a dynamically generated background image.
Roughly the steps would be:
Create a Range with a start and end around each character in the .textContents of the element you care about.
.getBoundingClientRect() on each range to get its rendered dimensions.
Draw rectangles of the desired color to a <canvas>.
Export the <canvas> as a data URI.
Use the data URI as a background-image.
Repeat for each block displayed element that you care about.
Be advised that there will, no doubt, be various edge cases in this approach and possible browser support limitations. Obviously just wrapping each character is a much simpler.

Make getElementsByClassName differ between 2 classes with the same name

I got a HTML page with two div/class elements with the same name, called "notifications". However, I want to count only the latter ones and dont count the first one.
The first one looks like this:
<a href="mynotifcations"><div class="notification">1</div>
This one should be excluded.
The later ones look like this:
<div class="notiheader"><span class="notification">2 notifications</span>
Right now I get the notification like this
document.getElementsByClassName("notification");
If I cycle through it, it returns "1" and then "2 notifications".
I would rather get merely the "2 notifications", or better yet just the number 2 as an integer.
How do I manage to do achieve that? I'm really running out of ideas :/
I would have to say that is a strange setup, but here is a way:
<script>
var special = document.querySelectorAll( "span.notification" );
alert (special[1].innerHTML);
</script>
It might be better to add a class to distinguish them (that's what they're for), but if you must, you can use document.querySelectorAll() to match the specific ones you're looking for:
document.querySelectorAll("div .notification")
This will only match divs with the notification class.
var elementsWanted = document.querySelectorAll("div .notification");
for(var i = 0; i < elementsWanted.length; i++){
elementsWanted[i].style.backgroundColor = "yellow";
}
<div class="notification">Span</div>
<div class="notiheader"><span class="notification">Div</span>
<div class="notiheader"><span class="notification">Div</span>
<div class="notiheader"><span class="notification">Div</span>
<div class="notiheader"><span class="notification">Div</span>
Try this, here we first get all the notification classes, x.length gives the total no of notification classes in the html. Then do your stuff based on its index(zero based index).
function hookSecondNotification() {
var x = document.getElementsByClassName("notification")[1];
// x.style.backgroundColor = "red";
// here do your stuffs.
}

How to use innertHTML, in this following situation

We were given an assignment to basically make a Madlib by having the user enter words into textfields and then replacing words in a hidden paragraph existing in the html page. We have to use JavaScript and CSS.
the paragraph in the html page:
<span id="story" display="hidden">
Rain was still lashing the windows, which were now <span id="adjs1">__adjective__</span>, but inside all looked bright and cheerful. The firelight glowed over
the countless <span id="adjs2">___adjective___</span> <span id="plnouns">___plural_noun___</span> where people sat <span id="verbs1">___verb_with_ing___</span>
, talking, doing homework or, in the case of Fred and George Weasley, trying to find out what would happen if you fed a <span id="foods">___food___</span> to a
<span id="monsters1">___monster___</span>. Fred had "rescued" the <span id="adjs3">___adjective___</span>, fire-dwelling <span id="monsters2">___monster___</
span> from a Care of Magical Creatures class and it was now<span id="verbs2">___verb_with_ing___</span> gently on a table surrounded by a knot of curious peopl.
</span>
Everything was going fine till I keep missing on getting the results I want.
function generateMadlib(){
// Display the story. The story is initially hidden.
document.getElementById("story").style.display = "inline";
// Get the words from the textboxes.
var formElements = $("#madlibForm :text");
// Find the word locations on the hidden paragraph.
var storyWords = $("#story span");
// Replace word loc values with with formElement values
for (var i = 0; i < formElements.length; i++)
{
storyWords.eq(i).innerHTML = formElements.eq(i).val();
}
}
This line
storyWords.eq(i).innerHTML = formElements.eq(i).val();
doesn't change the values inside the spans within the paragraph. (the code returns the proper input on the textfields)
I also tried using the browser console and manually changing document.getElementById("adjs1").innerHTML = "test"; it will return "test" but the value doesn't actually change. Can anyone clarify what .innerHTML actually does?
.eq(i) returns a jQuery object so it don't have the innerHTML property, so you can use .html() to set the html content
storyWords.eq(i).html(formElements.eq(i).val())
or you can use .get() which will return a dom element reference
storyWords.get(i).innerHTML = formElements.eq(i).val();
But you can simplify the overall implementation like
function generateMadlib() {
// Display the story. The story is initially hidden.
$("#story").css('display', "inline");
// Get the words from the textboxes.
var formElements = $("#madlibForm :text");
$("#story span").html(function (idx) {
return formElements.eq(idx).val();
})
}

JS - Remove a tag without deleting content

I am wondering if it is possible to remove a tag but leave the content in tact? For example, is it possible to remove the SPAN tag but leave SPAN's content there?
<p>The weather is sure <span>sunny</span> today</p> //original
<p>The weather is sure sunny today</p> //turn it into this
I have tried using this method of using replaceWith(), but it it turned the HTML into
<p>
"The weather is sure "
"sunny"
" today"
</p>
EDIT : After testing all of your answers, I realized that my code is at fault. The reason why I keep getting three split text nodes is due to the insertion of the SPAN tag. I'll create another question to try to fix my problem.
<p>The weather is sure <span>sunny</span> today</p>;
var span=document.getElementsByTagName('span')[0]; // get the span
var pa=span.parentNode;
while(span.firstChild) pa.insertBefore(span.firstChild, span);
pa.removeChild(span);
jQuery has easier ways:
var spans = $('span');
spans.contents().unwrap();
With different selector methods, it is possible to remove deeply nested spans or just direct children spans of an element.
There are several ways to do it. Jquery is the most easy way:
//grab and store inner span html
var content = $('p span').html;
//"Re"set inner p html
$('p').html(content);
Javascript can do the same using element.replace. (I don't remember the regex to do the replace in one stroke, but this is the easy way)
paragraphElement.replace("<span>", "");
paragraphElement.replace("</span>", "");
It's just three text nodes instead of one. It doesn't make a visible difference does it?
If it's a problem, use the DOM normalize method to combine them:
$(...)[0].normalize();
$(function(){
var newLbl=$("p").clone().find("span").remove().end().html();
alert(newLbl);
});​
Example : http://jsfiddle.net/7gWdM/6/
If you're not looking for a jQuery solution, here something that's a little more lightweight and focused on your scenario.
I created a function called getText() and I used it recursively. In short, you can get the child nodes of your p element and retrieve all the text nodes within that p node.
Just about everything in the DOM is a node of some sort. Looking up at the following links I found that text nodes have a numerical nodeType value of 3, and when you identify where your text nodes are, you get their nodeValueand return it to be concatenated to the entire, non-text-node-free value.
https://developer.mozilla.org/en/nodeType
https://developer.mozilla.org/En/DOM/Node.nodeValue
var para = document.getElementById('p1') // get your paragraphe
var texttext = getText(para); // pass the paragraph to the function
para.innerHTML = texttext // set the paragraph with the new text
function getText(pNode) {
if (pNode.nodeType == 3) return pNode.nodeValue;
var pNodes = pNode.childNodes // get the child nodes of the passed element
var nLen = pNodes.length // count how many there are
var text = "";
for (var idx=0; idx < nLen; idx++) { // loop through the child nodes
if (pNodes[idx].nodeType != 3 ) { // if the child not isn't a text node
text += getText(pNodes[idx]); // pass it to the function again and
// concatenate it's value to your text string
} else {
text += pNodes[idx].nodeValue // otherwise concatenate the value of the text
// to the entire text
}
}
return text
}
I haven't tested this for all scenarios, but it will do for what you're doing at the moment. It's a little more complex than a replace string since you're looking for the text node and not hardcoding to remove specific tags.
Good Luck.
If someone is still looking for that, the complete solution that has worked for me is:
Assuming we have:
<p>hello this is the <span class="highlight">text to unwrap</span></p>
the js is:
// get the parent
var parentElem = $(".highlight").parent();
// replacing with the same contents
$(".highlight").replaceWith(
function() {
return $(this).contents();
}
);
// normalize parent to strip extra text nodes
parentElem.each(function(element,index){
$(this)[0].normalize();
});
If it’s the only child span inside the parent, you could do something like this:
HTML:
<p class="parent">The weather is sure <span>sunny</span> today</p>;
JavaScript:
parent = document.querySelector('.parent');
parent.innerHTML = parent.innerText;
So just replace the HTML of the element with its text.
You can remove the span element and keep the HTML content or internal text intact. With jQuery’s unwrap() method.
<html>
<head>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("button").click(function(){
$("p").find("span").contents().unwrap();
});
});
</script>
</head>
<body>
<p>The weather is sure <span style="background-color:blue">sunny</span> today</p>
<button type="button">Remove span</button>
</body>
</html>
You can see an example here: How to remove a tag without deleting its content with jQuery

javascript grabbing span tag with both class and id

I have a span tag
<span class="vi-is1-prcp" id="v4-25">US $99.00</span>
I would like to grab it using pure javascript. JQuery or any other library is not allowed. Is that possible?
I recon that
getElementById('v4-25')
won't work since I have to specify class, too, correct?
Thank you,
So,
<div id="listprice">asdasdasdasdasd</div>
var string = document.getElementById('v4-25');
document.getElementById('listprice').innerHTML = string;
should print value of 'v4-25' in 'listpirce' ?
H
getElementById will work just fine. Just make sure you're running it after the page has loaded.
First of all, ids are unique. You can't have more than one. therefore, when you select element by id, you can only bring back one element (this is good).
Secondly, after you get an element, you have to do something with it. var string = document.getElementById('v4-25'); only gets you the element, but it looks like you want var string = document.getElementById('v4-25').innerHTML; for the price. If you do want the id instead you can do var string = document.getElementById('v4-25').id; but because that just returns "v4-25" it's a bit redundant.
There is no reason to add a class. Run the script after that dom element is loaded like this.
<span class="vi-is1-prcp" id="v4-25">US $99.00</span>
<script>
var elm = document.getElementById('v4-25');
</script>

Categories