DOM Methods get the right element from a Node - Using only JavaScript - javascript

I am doing an exercise, but I am stuck. I need to get the first line of each paragraph after each "H4", but at the moment it is getting all the "P" from the first "H4".
I got an HTML and a JavaScript, the idea is to get a news summary after Bizarre News Summary, I have created the 'UL', 'LI' and appended them
function newsSnippets() {
let classNewsarticle = document.getElementsByClassName("newsarticle"); // Get classes by name 'newsarticle'
let headlinesId = document.getElementById("headlines"); // Get Id 'headlines'
let newsSummary = document.createElement("div"); // Create DIV
headlinesId.appendChild(newsSummary); // Append headlines to DIV
let newsSummaryList = document.createElement("ul"); // Create UL
newsSummary.appendChild(newsSummaryList); // Append UL to DIV
console.log(classNewsarticle);
for (let i = 0; i < classNewsarticle.length; i++) {
let newsSummaryListItem = document.createElement("LI"); // Create an LI for each H4
newsSummaryList.appendChild(newsSummaryListItem); // Append the LI to the UL
let getH4 = document.getElementsByTagName("H4")[i].childNodes[0].nodeValue;
let getH4Node = document.createTextNode(getH4);
let ellipsis = document.createTextNode(" . . . ");
let p = document.getElementsByTagName("P")[i].innerHTML;
let pNode = document.createTextNode(p);
newsSummaryListItem.appendChild(getH4Node) + // Append the texts node to the LI element
newsSummaryListItem.appendChild(ellipsis) +
newsSummaryListItem.appendChild(pNode);
let newsList = document.createElement("LI"); // Create the inline text anchor
document.body.insertBefore(newsList, newsSnippets[i]); // Insert the text anchor before headings
}
}
window.onload = newsSnippets;
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JavaScript</title>
<link rel="stylesheet" type="text/css" href="styles/styles.css">
<script src="scripts/fma_t1.3.js"></script>
</head>
<body>
<div id="wrappermain">
<h1>Bizarre News Mash Up</h1>
<section id="headlines">
<h2>Bizarre News Summary</h2>
</section>
<section id="news">
<h3>News Stories in Full</h3>
<article class="newsarticle">
<h4>What a load of Bull!</h4>
<p>Chinese Kung Fu Masters are seeking the ultimate opponents</p>
<p>Several times a week, kung fu teacher Ren Ruzhi enters a ring to spar with a bovine opponent around five times his weight and capable of killing him.</p>
<p>Ren’s mixing of martial arts and bullfighting worries his mother, but the 24-year-old has never been hurt. Besides, he says, grappling with a snorting bull is exciting.</p>
<p>It symbolizes the bravery of a man,” Ren told Reuters in Jiaxing in China’s eastern province of Zhejiang.</P>
</article>
<article class="newsarticle">
<h4>Has Anybody got a Tissue?</h4>
<p>A Hawaiian monk seal got an eel caught in its nose ― and it wasn’t the first time for these endangered creatures.</p>
<p>The Hawaiian Monk Seal Research Program posted a startling pic of the poor pup on Monday, and the National Oceanic and Atmospheric Administration Fisheries provided more details in a post on Wednesday.</p>
</article>
<article class="newsarticle">
<h4>Dog Pulls Off Spectacular Save During Argentina Soccer Match</h4>
<p>A pooch invaded the pitch during a Federal A league match between Juventud Unida and Defensores de Belgrano over the weekend.</p>
<p>Juventud Unida were already comfortably ahead against Defensores de Belgrano in their league clash when the dog made his unexpected cameo.</p>
</article>
<article class="newsarticle">
<h4>Nobody Beats The Laws of Nature</h4>
<p>A 69-year-old Dutch man has failed in his attempt to legally declare himself 20 years younger.</p>
<p>Last month, motivational speaker Emile Ratelband filed a lawsuit against the Dutch government requesting that his date of birth be switched from March 11, 1949, to March 11, 1969.</p>
</article>
</section>
</div>
<!-- Stories from Huffington Post. Used for Teaching purposes -->
</body>
</html>

This seems a little too complicated. If you are allowed to, try something like this:
function newsSnippets() {
const results = document.evaluate('//article[#class="newsarticle"]', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
let temp = "<div><ul>"
for (let i = 0; i < results.snapshotLength; i++) {
let node = results.snapshotItem(i);
let new_item = "<li>"+node.querySelector('h4').innerText+ '...' +node.querySelector('p').innerText+"</li>";
temp += new_item;
}
temp += "</ul></div>"
let target = document.querySelector('section#headlines');
target.insertAdjacentHTML('beforeend', temp);
}

I was able to came up with an answer myself and it works just fine.
function newsSnippets() {
let classNewsarticle = document.getElementsByClassName("newsarticle"); // Get classes by name 'newsarticle'
let headlinesId = document.getElementById("headlines"); // Get Id 'headlines'
let newsSummary = document.createElement("div"); // Create DIV
headlinesId.appendChild(newsSummary); // Append headlines to DIV
let newsSummaryList = document.createElement("ul"); // Create UL
newsSummary.appendChild(newsSummaryList); // Append UL to DIV
for (let i = 0; i < classNewsarticle.length; i++) {
let newsSummaryListItem = document.createElement("LI"); // Create an LI for each H4
newsSummaryList.appendChild(newsSummaryListItem); // Append the LI to the UL
let getH4 = document.getElementsByTagName("H4")[i]; // Get H4s
let getH4Text = getH4.childNodes[0].nodeValue; // Get H4s Nodes
let getH4Node = document.createTextNode(getH4Text); // Get H4s HTML Text
let ellipsis = document.createTextNode(" . . . "); // Create Text Node Ellipsis
let p = getH4.nextElementSibling.innerHTML; // Get P as the Next Element Sibling from each H4
let pText = document.createTextNode(p); // Create Text Node for each first P after H4
newsSummaryListItem.appendChild(getH4Node) + // Append the textNodes to the LI element
newsSummaryListItem.appendChild(ellipsis) +
newsSummaryListItem.appendChild(pText);
}
}
window.onload = newsSnippets;

Related

How to add break tags after inserting a paragraph into html using javascript's createElement

I've successfully inserted a paragraph element into html page using javascript but the 2nd consecutive paragraph comes side by side and I wish to add a break tag to print them in another line, how do I do that?
Here is a screenshot of my output:
Here is my javascript code:
function newtask(){
let ask = prompt("Enter the description of task");
const para = document.createElement("p");
const Textnode = document.createTextNode(ask);
para.appendChild(Textnode);
let text= document.getElementById("new")
text.appendChild(Textnode);
}
Here is the relevant html
<script src="index.js"></script>
<h1>To do List</h1>
<button onclick="newtask()">New Task</button>
<div id="new">
<p>test</p>
</div>
You were appending Textnode to your parent element, not your new <p> element. Here's a quick rewrite that should give you your desired results.
Firstly, create the new <p> element, then modify its innerText property. After that, just append your new <p>.
function newtask() {
const text = document.getElementById("new");
const ask = prompt("Enter the description of task");
const para = document.createElement("p");
para.innerText = ask;
text.appendChild(para);
}
You can wrap your p inside a div and add a display: flex configuration.
const paraDiv = document.createElement("div");
// Add your style configuration to your paraDiv
function newtask(){
let ask = prompt("Enter the description of task");
const para = document.createElement("p");
paraDiv.appendChild(para)
const Textnode = document.createTextNode(ask);
para.appendChild(Textnode);
let text= document.getElementById("new")
text.appendChild(Textnode);
}

My newly created html element to show Item Size on each order detail row only shows on the top row

Edited with my progress:
Noob here. I know just enough javascript to get myself in trouble. Case and point: my webstore has an existing template for a packing list and I'm trying to add the item Size to it.
For each ordered item, the packing list has an element [itemname] which contains the Item + Size. I wrote a function that passes [itemname], breaks out just the size, and returns it. I'd like to display that size on the line item beside quantity, or anywhere on the detail line.
The itemSize tag is only showing on the top detail line. It is not inserting where it should.
Spent way too much time on this issue. Can anyone help?
<!--START: items-->
<div class="row">
<div class="invoice-id">[id]</div>
<div class="invoice-items">
[itemname]<!--START: warehouse_location--><br />
[warehouse_location] [warehouse_aisle] [warehouse_bin] [warehouse_custom]<!--END: warehouse_location-->
</div>
<div id="itemSize"></div>
<div class="invoice-qty">[numitems]<br /> </div>
<div class="clear"></div>
</div>
<hr>
<script language="JavaScript" type="text/javascript" >
function myFunction(txt){
var str = txt.substr( txt.indexOf(";")+1, txt.length - txt.indexOf(";"));
console.log(str);
var newDiv= document.createElement("div");
var newContent = document.createTextNode(str);
newDiv.appendChild(newContent);
var currentDiv = document.getElementById("itemSize");
var nextDiv = document.getElementById("invoice-qty");
currentDiv .insertBefore(newDiv, nextDiv );
}
myFunction("[itemname]");
</script>
<!--END: items-->
This is the packing list output. The "bag of 6 tarts" or "7oz med" should be on each line beside the respective item.
Attribute id should be unique. You can generate a dynamic id, something like: id-[index] and then in your JS function target the id that matches each item.
function myFunction(txt, index) {
var str = txt.substr( txt.indexOf(";")+1, txt.length txt.indexOf(";"));
var newDiv= document.createElement("div");
var newContent = document.createTextNode(str);
newDiv.appendChild(newContent);
var currentDiv = document.getElementById(`itemSize-${index}`);
var nextDiv = document.getElementById("invoice-qty");
currentDiv .insertBefore(newDiv, nextDiv );
}

For loop not working as expected with string replacement

I am trying to make a javascript webextension that adds a couple of numbers eg. "123" to the end of the inner text of a hyperlink text to each product on a shopping website, eg. http://www.tomleemusic.ca
For example, if I go to this link, http://tomleemusic.ca/catalogsearch/result/?cat=0&q=piano
I want to add the item's identification number to the end of the product's name.
name of product and the href tag are in its item link, tomleemusic.ca/xxxxxx with the x's being the item number
However with my following code, I simply append the item number of the first item in the list to every item, instead of a different item number for each item.
var productsListLink = document.querySelectorAll(".products-grid .item .product-name a:not(.product-image)");
for (var i = 0; i < productsListLink.length; i++) {
var a = productsListLink[i];
var name = a.innerHTML || "";
var addon = document.querySelector(".products-grid .item .product-name a:not(.product-image)").getAttribute('href');
var newaddon = addon.replace("http://tomleemusic.ca/","");
name += newaddon;
a.innerHTML = name;
a.setAttribute('title', name);
}
In this line, you're grabbing only the first matching element:
var addon = document.querySelector(".products-grid .item .product-name a:not(.product-image)").getAttribute('href')
You already have the element you're actually working with in each loop iteration in a; just use that instead:
var addon = a.getAttribute('href')
Example:
var productsListLink = document.querySelectorAll(".products-grid .item .product-name a:not(.product-image)");
for (var i = 0; i < productsListLink.length; i++) {
var a = productsListLink[i];
var name = a.innerHTML || "";
var addon = a.getAttribute('href');
var newaddon = addon.replace("http://tomleemusic.ca/","");
name += newaddon;
a.innerHTML = name;
a.setAttribute('title', name);
}
<div class="products-grid">
<div class="item">
<span class="product-name">
</span>
</div>
<div class="item">
<span class="product-name">
</span>
</div>
<div class="item">
<span class="product-name">
</span>
</div>
</div>
querySelector will always return the first matching element. Thus, when you do
var addon = document.querySelector(".products-grid .item .product-name a:not(.product-image)").getAttribute('href');
you're selecting the first a (the one you get in your first iteration).
But, you can make the code a whole lot cleaner by using array methods and a regular expression to match the id:
Array.prototype.forEach.call(
document.querySelectorAll(".products-grid .item .product-name a:not(.product-image)"),
(productNameElement) => {
const idMatch = productNameElement.href.match(/\d+$/);
if (idMatch) productNameElement.appendChild(document.createTextNode(idMatch[0]));
});
Also note that only some of the elements have an ID number. For example, one of the search results:
BENCHWORLD SONATA 1c Single Adjustable Artist <span class="searchindex-highlight">Piano</span> Bench In Polished Walnut
doesn't have one, so it would be good to check that there's a match first.

How to create 'add to favourite' feature in a html cordova android app?

I am creating a song book app using phonegap. In index.html i have list of songs in li tags. when i click on a particular song it will open that particular song's lyrics in another local html file.
I want to add a 'favourite button'. When the favourite button is clicked I want that particular song to be added to the favourites list. When user open the favourite page it should display list of their favourite songs, and when they click a song in favourite page it should open that particular song's lyrics html page.
I am an intermediate user of HTML and a beginner in JavaScript.
Please help me accomplish this,
Thanks in advance.
Because this is a 'pretty broad' question, it is hard to find an answer for this, but I'd suggest making an array, storing the favorite songs into it, then when you open the favorites.html page, it gets the array, and writes the information to the page.
e.g. when a favorite button is clicked on a song page, it writes: the name of the song(exampleSong), the page of the song(exampleSong.html), and other random details that you need, and going to the favorites.html should get a document ready function that reads the array and writes the page.
Sorry if I can't help that much, but this was a really broad question.
If you need help, here are some examples that I created
(This gets the array of favorites, and prints them out)
var favorites = [
["ExampleSong", "exampleSong.html"],
["LorddirtCoolSong", "LorddirtCoolSong.html"],
["StackOverflowIsAwesome", "StackOverflowIsAwesome.html"]
];
var containerA = document.getElementById("favoritesA");
for (var i in favorites)
{
for (var j in favorites[i])
{
var newElement = document.createElement("p");
newElement.innerHTML = favorites[i][j];
containerA.appendChild(newElement);
}
}
var containerB = document.getElementById("favoritesB");
for (var i in favorites)
{
var newElement = document.createElement("p");
newElement.innerHTML = "<h4>Favorite Song " + i + "</h4>";
containerB.appendChild(newElement);
for (var j in favorites[i])
{
var newElement = document.createElement("p");
newElement.innerHTML = favorites[i][j];
containerB.appendChild(newElement);
}
}
var containerC = document.getElementById("favoritesC");
for (var i in favorites)
{
var newElement = document.createElement("p");
newElement.innerHTML = "<h4>Favorite Song " + i + "</h4>";
containerC.appendChild(newElement);
for (var j in favorites[i])
{
if(j == 1){
}else{
var newElement = document.createElement("p");
newElement.innerHTML = "<a href='" + favorites[i][1] + "'>" + favorites[i][j] + "</a>";
containerC.appendChild(newElement);
}
}
}
.favoriteSongs{
border: 2px solid black;
display: block;
}
<!--
EXAMPLE 1A: Print out the Favorites
-->
<hr>
<h2>Example 1A: Print favorites out</h2>
<div id='favoritesA' class='favorites'>
</div>
<hr>
<!--
EXAMPLE 1B: Now you know the order of the songs!
-->
<h2>Example 1B: Print favorites out with formatting</h2>
<div id='favoritesB' class='favorites'>
</div>
<hr>
<!--
EXAMPLE 1C: Link them
-->
<h2>Example 1C: Link to the page</h2>
<div id='favoritesC' class='favorites'>
</div>
<hr>
Very self explanatory, it gets the array of favorite songs, with the name and url, gets the container, which is <div id='favorites'></div> and writes the contents into it.
(oh wait, i just noticed I spent so long working on this hahaha.)
Examples:
1A: All I did was search the array favorites, and print out every single thing in the array. Simple.
1B: Slightly different, it's the same as the last, but I added a <h4> tag before every array in the array. (Yes, arrays inside arrays inside arrays are confusing).
1C: Instead of printing out both of the arrays inside the arrays, just print out the first thing inside the arrays in the arrays, and add a link pointing to the second thing inside the arrays in the arrays. Confused already? Just read it through and you'll understand.
Hi I found a solution using another SO question.
First we will create a local storage and store song details in that local storage key.
then we will retrieve that information in favorite.html using localStorage.getItem(key);
The following is my code for first song song1.html
when button pressed song link will be appended to local storage
<!DOCTYPE html>
<html>
<body onload="mySong()">
<button onclick="mySongOne()">add to favorite</button>
<script>
function mySong() {
localStorage.setItem("favsong", "");
}
function appendToStorage(name, data){
var old = localStorage.getItem(name);
if(old === null) old = "";
localStorage.setItem(name, old + data);
}
function mySongOne() {
appendToStorage("favsong", "<a href='https://www.song1.com'><h1>song1</h1></a>");
}
</script>
</body>
</html>
for another song song2.html
when button pressed second song link will be appended to local storage
<!DOCTYPE html>
<html>
<body>
<button onclick="mySongTwo()">add to favorite</button>
<script>
function appendToStorage(name, data){
var old = localStorage.getItem(name);
if(old === null) old = "";
localStorage.setItem(name, old + data);
}
function mySongTwo() {
appendToStorage("favsong", "<a href='https://song2.com'><h1>song2</h1></a>");
}
</script>
</body>
</html>
and favorite.html
on page load it will show details from local storage
<!DOCTYPE html>
<html>
<body onload="yourFunction()">
<div id="result"></div>
<script>
function yourFunction() {
document.getElementById("result").innerHTML = localStorage.getItem("favsong");
}
</script>
</body>
</html>

Javascript: My .textContent works, but not my innerHTML

I have a strange problem. In general, when I set a variable as textContent, it shows it, but it doesn't when I set it as innerHTML
More precisely
Here is the HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Dynamic Menu</title>
</head>
<body id="top">
<h1>The Extremadura Region of Western Spain</h1>
<h2 >Geography Of The Region</h2>
<p>The autonomous community of Extremadura is in western Spain alongside the Portuguese border.
It borders the Spanish regions of Castilla y Leon, Castilla La Mancha and Andalucía as well as Portugal (to the West).
Covering over 40,000 square kilometers it has two provinces: Cáceres in the North and Badajoz in the South.</p>
<h2>Where To Stay</h2>
<p>There is a wide range of accommodation throughout Extremadura including small inns and guest houses ('Hostals') or
think about renting a 'casa rural' (country house) if you are travelling in a group.</p>
<h2>Climate</h2>
<p>Generally Mediterranean, except for the north, where it is continental. Generally known for its extremes,
including very hot and dry summers with frequent droughts, and its long and mild winters.</p>
<h2>What To See</h2>
<p>Extremadura hosts major events all year round including theater, music, cinema, literature and folklore.
Spectacular venues include castles, medieval town squares and historic centers.
There are special summer theater festivals in the Mérida, Cáceres, Alcántara and Alburquerque.</p>
<h2>Gastronomy</h2>
<p>The quality of Extremaduran food arises from the fine quality of the local ingredients.
In addition to free-range lamb and beef, fabulous cheeses, red and white wines, olive oil, honey and paprika,
Extremadura is particularly renowned for Iberian ham. The 'pata negra' (blackfoot) pigs are fed on acorns in the
cork-oak forests, the key to producing the world's best ham and cured sausages.</p>
<script src="lunch.js"></script>
</body>
</html>
Here is the script
function lop(){
var hs = document.getElementsByTagName('h2');
for(var g = 0; g<hs.length; g++){
hs[g].setAttribute('id', g);
}
var budy = document.getElementById('top'); //Gets the body id
var nnn = document.createElement('nav'); //Creats a nav event
var uuu = "<ul > \
<li id='one'> <a href='#0'>Geography Of The Region </a> </li> \
<li id='two'> <a href='#1'>Where To Stay </a> </li> \
<li id='tre'> <a href='#2'>Climate </a> </li> \
<li id='for'> <a href='#3'>What To See</a> </li> \
<li id='fiv'> <a href='#4'>Gastronomy</a> </li>";
// li: 55-60 make the HTML
nnn.innerHTML = uuu; //Sets the HTML to the nav
var h = document.getElementsByTagName('h2')[0]; // Get the specific element
budy.insertBefore(nnn, h); // inserts the element nav and the whole html before h
var ps = document.getElementsByTagName('p');
var hih = ' AAAAA ';
for(var g = 0; g<ps.length; g++){
ps[g].nextSibling.innerText = hih;
}
}
lop(); //cals the function so it executes
So basicly in this exercise i have to create an ul within the script and without modyfing the HTML.
I successed in creating an ul. Then I have to creat a link that brings me to the top of the page. Which is this part here:
var ps = document.getElementsByTagName('p');
var hih = ' AAAAA ';
for(var g = 0; g<ps.length; g++){
ps[g].nextSibling.innerText = hih;
}
Here I try to creat a link that bring me back to the top. Im using the advantage that chrome has blank space betwwen sibling to creat that link in there.
The problem is that it doesn't show. When I go to my debugger, I have no errors, but nothings shows. If change ps[g].nextSibling.innerText = hih; for .textContent it shows the whole think.
I know the difference between .innerHTML and .textContent (or I think), so why doesn't it show my link and can I make it show ?
I don't understand you use nextSibling. If you want to use innerHTML, you can use bellow script
ps[g].innerHTML = ps[g].innerHTML + hih;
You can read about nextSibling in https://www.w3schools.com/jsref/prop_node_nextsibling.asp
Ok so a friend of mine changed my procedure and here what he did:
var ps = document.getElementsByTagName('p');
var hih = '<br /><br /> To the top ';
for(var g = 0; g<ps.length; g++) {
ps[g].innerHTML += hih;
}
In other words, what I learned from this 3h of js, is that you can't change a blank child's HTML, but only his text.

Categories