How to use innertHTML, in this following situation - javascript

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();
})
}

Related

How do I initialize a whole div from LocalStorage in HTML without breaking it with "/"?

So, I am creating a "favorites page" using local storage to store the items that you click to add to favorites, the items are normal cards like this (just an example):
<div class="card__box">
<div class="heart-wrapper"></div>
<div onclick="link('index.html?BI=auditoria')">
<div class="card__icon"><img src="./assets/icons/auditoria.png"></div>
<div class="icon__text">
<span class="icon__header"><strong>Auditoria</strong></span>
</div>
</div>
</div>
I am saving them in local storage with outer.HTML
(how localStorage is saving them)
the thing is, when I try to show them in the HTML the LocalStorage give the value with some alterations like bars "/" and "\n". (like this):
"<div class="card_mini_box"> \n <div class="times-mini-wrapper"><a href="#" class="fas fa-times" id="auditoria" aria-hidden="true">\n <div onclick="link('index.html?BI=auditoria')">\n <div class="card_mini_icon"><img src="./assets/icons/auditoria.png">\n <div class="icon_mini_text">\n <span class="icon_mini_header">Auditoria\n \n \n "
As u can see all messed up.
I am saving them in localstorage like this:
let favorites = JSON.parse(localStorage.getItem('favorites')) || []
const source = favdiv.outerHTML;
favorites.push(source);
localStorage.setItem('favorites', JSON.stringify(favorites));
(favdiv is the whole div selected)
And I am trying to show them in HTML like this:
var output = document.getElementById("mini__cards");
var element = document.createElement("div");
element.textContent = localStorage.getItem('favorites');
output.appendChild(element);
please help me I tried a lot of different methods and none of them worked.
Already Tried saving with innerHTML and also tried to put them in html with innerHTML as well.
for this method to work, some details were missing when saving and showing the favorites.
When getting the div, use innerHTML, it gets the elements inside the selected div, so there is no risk of duplicating IDs.
Before saving, removing breaking lines.
When showing data, remember to use a loop to show all stored data.
Your code would look like this to save:
var favorites = JSON.parse(localStorage.getItem("favorites")) || [];
var favdiv =
document.getElementById("divs").innerHTML.replace(/(\r\n|\n|\r|\s\s)/gm, "");
favorites.push(favdiv);
localStorage.setItem("favorites", JSON.stringify(favorites));
Using replace, I remove line breaks, with \n and \r.
And to view the saved divs, I use a forEach to go through the entire array, create a template and show its content as the last element:
var favorites = JSON.parse(localStorage.getItem("favorites"));
var output = document.getElementById("mini__cards");
favorites.forEach((favorite) => {
let tempElement = document.createElement("template");
tempElement.innerHTML = favorite.trim();
output.append(tempElement.content);
});
More detailed explanation about above code: https://stackoverflow.com/a/35385518/20815693
This is the result for your case, using jquery this code can be reduced and easier to handle DOM. I hope I have helped you.

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

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.

work on all <span> at the current <div> then check for the value of an attribute of the <span>

i am kinda stuck with my javascript, I am making a greasemonkey script for a site, that restricts me to use plain-old javascript only. For now, my script currently does is, search for all the tables, and table row with ProjectTable-row then for each ProjectTable-row look for a div with ProjectTable-status, if that div is not found, it will delete the whole row.
it works great.
document.getElementById("gmSomeID").onclick = function showAlert() {
console.log('invoked');
var projectDescriptions = document.querySelectorAll('tr.ProjectTable-row'),
projectDescriptions = Array.prototype.slice.call(projectDescriptions);
projectDescriptions.forEach(function(el) {
if (el.querySelector('div.ProjectTable-status')) {
} else {
el.parentNode.removeChild(el);
}
});
}
but, now I do not know how to work on the current div and loop on all span inside it. I am still 2 steps short.
Loop on all span
Search for all span which contains data-content="apple" if none of the span has this attribute, then delete it.
Something like this:
For a HTML tag like this:
<div class="ProjectTable-status">
<span data-content="apple">
</span>
</div>
this will not be deleted data-content is apple.
For a HTML tag like this:
<div class="ProjectTable-status">
<span data-content="banana">
</span>
</div>
this will be deleted, no span has data-content="apple".
For HTML code like this:
<div class="ProjectTable-status">
<span data-content="banana"></span>
<span data-content="apple"></span>
</div>
this will NOT be deleted, the div contains at least 1 span that has data-content of apple.
I have no idea, how to proceed now and really tired or trying anything, i do not even know how to check for attribute value.
Hope someone can guide or put me at the right path.
Thanks!
Starting with what you provided, I've just slightly refactored it to check for an "apple" span within each div as it loops through. Using continue, we can execute the next iteration of the loop without deleting the div element if we find that it contains an "apple" span. This code is not tested, but just what came off the top of my head, so it might need some tweaking.
document.getElementById("gmSomeID").onclick = function showAlert() {
console.log('invoked');
var projectDescriptions = document.querySelectorAll('tr.ProjectTable-row'),
projectDescriptions = Array.prototype.slice.call(projectDescriptions);
//pointer to work with current div
var currentDiv;
projectDescriptions.forEach(function(el) {
currentDiv = el.querySelector('div.ProjectTable-status');
//do we have a div?
if (currentDiv) {
//look for an apple within the div
if(currentDiv.querySelector('span[data-content="apple"]')){
//go to the next iteration of the loop without delete
continue;
}
}
//if we made it this far, we didn't find an apple
el.parentNode.removeChild(el);
});
};

I can't get numbers to show up in jsfiddle

http://jsfiddle.net/HKhw8/67/
HTML:
<p>You can see this text... <span id="text"></span></p>
<p>...but not this: <span id="mathStuffs"></span></p>
<p>Number variables don't seem to show, either- <span id="num"></span></p>
JavaScript:
var text = 'Hello'
var i = 50;
document.getElementById('text').innerHTML = text;
document.getElementById('mathStuffs').innerHTML = math.pow(5,2);
document.getElementById('number').innerHTML = i;
The code doesn't show up in the preview like some of the nicely color-coded syntax highlighting like I've seen in previous posts- sorry about that.
I originally thought that console.log() was the problem, so I have this example set up. Regular text variables show up, but I can't seem to get the numbers or functions that return numbers to appear. Is there something I'm doing wrong? I've tried fiddling with the No wrap - in setting, but I can't understand. I've tried Chrome and FF.
math is not a class of javascript it should be Math
document.getElementById('mathStuffs').innerHTML = Math.pow(5,2);
Also one of the reference of a div is wrong
document.getElementById('number').innerHTML = i;
it should be num
document.getElementById('num').innerHTML = i;

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

Categories