Generating a clickable HTML link from a javascript array - javascript

I found code online that can select and print a random name from an array, and I'm trying to modify it to print a link instead of a name. I want that link to be clickable, as it would be normally in HTML. I'm not sure how to modify the javascript to do that, however.
This was my method for doing it below. But the result is that it just prints the HTML code on the page, not an interactive link. What's the better way to do this?
let btnRandom = document.querySelector('button');
let result = document.querySelector('h1');
let links = ['https://www.nytimes.com/2019/09/19/climate/air-travel-emissions.html', 'Link2', 'Link3', 'Link4', 'Link5', 'Link6', 'Link7'];
function getRandomNumber(min, max) {
let step1 = max - min + 1;
let step2 = Math.random() *step1;
let result = Math.floor(step2) + min;
return result;
}
btnRandom.addEventListener('click', () => {
let index = getRandomNumber(0, links.length-1);
result.innerText = '<a href ="' + links[index] + '"</a>';
});
Result of my current code:

You could use the innerHTML property instead of innerText to append the link as an actual HTML-element.
Or alternatively follow the approach mentioned here and create a link element and append it to the "result"-node.

Create an <a> element using Document.createElement(). Then append the element to the h1 node with Node.appendChild()
let btnRandom = document.querySelector('button');
let result = document.querySelector('h1');
const links = ['https://www.nytimes.com/2019/09/19/climate/air-travel-emissions.html', 'Link2', 'Link3', 'Link4', 'Link5', 'Link6', 'Link7'];
function getRandomNumber(min, max) {
let step1 = max - min + 1;
let step2 = Math.random() *step1;
let result = Math.floor(step2) + min;
return result;
};
btnRandom.addEventListener('click', () => {
let index = getRandomNumber(0, links.length-1);
const a = document.createElement("a");
a.textContent= links[index];
a.href= links[index];
result.appendChild(a);
});
<button>Ramdom Link</button>
<h1></h1>

Related

sum up user input with javascript

I'm trying to store a user input in a variable and output it.
I actually thought it would be very easy, but right now I'm stuck on this task
I'm trying to store this in an array. but I would also be happy if it was simply stored in a variable and I could output it.
I've been searching for it for a long time, but I have the feeling that I don't know exactly what to look for
here is my code:
let inputValuePrice = document.getElementById("myInput2").value;
let outputSumme = document.getElementById("summe");
outputSumme = parseFloat(inputValuePrice);
let sum = [];
sum.push(outputSumme);
console.log(sum);
<input type="number" id="myInput2" />
<input type="text" id="summe" />
edit:
I'm sorry. I'll explain it again in more detail. I want to add the number after each entry. It is a kind of to-do list with products and prices. each product is entered one by one along with the price. I would then like to add up the price of each product. In this case it is enough for me if it is first output in the console. If it is correct then I will let it output to the html.
if you need to calculate the sum of all inputs values as an integer or a float number it's very simple. you can use a simple function to sums all of your array elements like this:
let inputValuePrice = document.getElementById("myInput2").value;
let outputSumme = document.getElementById("summe");
outputSumme = parseFloat(inputValuePrice);
let sum = [];
sum.push(outputSumme);
console.log(getSumOfArray(sum));
function getSumOfArray(array){
let sumOfElements=0;
for (let i=0;i<array.length;i++){
sumOfElements=sumOfElements+array[i];
}
return sumOfElements;
}
If your array elements are all numbers you can use the reduce operator as follows:
const sumOfArray = sum.reduce((a, b) => a + b, 0)
Unfortunately I don't understand how it works. I have now the products with prices in the indexedDB in my code. There I wanted to read them out and sum them up again in an array. I'll send you the whole code. I would be very grateful for an explanation. what is wrong with my thinking? Here is my code.
This snippet is in a function that when run puts the products in a list in the HTML. The products are created in a foreach loop and in that I intercept the prices and send them outside of the function to another function which then has the data to calculate with. I hope it is understandable. I'll link the whole code at the end of this thread.
let products = makeTransaction('produkte', "readonly");
let request = products.getAll();
request.addEventListener('success', (event) => {
event.preventDefault();
document.querySelector('#product-list').innerHTML = "";
let data = event.target.result;
data.forEach((element) => {
/*-----------Elemente Kreieren------------*/
let li = document.createElement("li");
let edit = document.createElement('i');
let spanPrimary = document.createElement('span');
let inputLabel = document.createElement('label');
let productName = document.createElement('span');
let productPrice = document.createElement('span');
let spanSecondary = document.createElement('span');
let checkBox = document.createElement('input');
let closeBtn = document.createElement("span");
/*-----------Elemente einfügen------------*/
li.setAttribute('data-key', element.id);
productName.appendChild(document.createTextNode(element.title));
productPrice.appendChild(document.createTextNode(element.price + " €"));
spanPrimary.appendChild(productName);
spanPrimary.appendChild(productPrice);
inputLabel.appendChild(checkBox);
spanSecondary.appendChild(inputLabel);
li.appendChild(edit);
li.appendChild(spanPrimary);
li.appendChild(spanSecondary);
li.appendChild(closeBtn);
/*-----------Elemente klassifizieren------------*/
li.className = "mdl-list__item mdl-shadow--2dp";
edit.className = "material-symbols-outlined icon-edit-document";
edit.textContent = 'edit_document';
spanPrimary.className = "mdl-list__item-primary-content";
spanSecondary.className = "mdl-list__item-secondary-action";
inputLabel.className = "mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect";
productName.className = 'product-text';
productPrice.className = 'product-preis';
checkBox.className = "mdl-checkbox__input";
checkBox.setAttribute('id', 'my-id');
checkBox.setAttribute('type', 'checkbox');
closeBtn.className = "material-symbols-outlined hiding-list-item";
closeBtn.textContent = 'close';
componentHandler.upgradeElement(li);
let list = document.getElementById("product-list").appendChild(li);
// Füge die "edit" Funtion hinzu
let editieren = document.getElementsByClassName("icon-edit-document");
for (let i = 0; i < editieren.length; i++) {
editieren[i].onclick = function() {
showProducts(element.id);
}
}
// Füge die "close" Button Funktion hinzu
let close = document.getElementsByClassName("hiding-list-item");
for (let i = 0; i < close.length; i++) {
close[i].onclick = function() {
deleteProduct();
}
}
// Function for totalizing product prices
let produktPreis = element.price
sumPrice(produktPreis);
});
});
request.addEventListener('error', (event) => {
console.log(event.target.error);
});
}
and now the summation...
function sumPrice(produktPreis) {
produktPreis = parseFloat(produktPreis);
let arr = [];
arr.push(produktPreis);
console.log(getSum(arr));
console.log(sumOfArray);
function getSum(array) {
let sumOfElements = 0;
for (let i = 0; i < arr.length; i++) {
sumOfElements = sumOfElements + array[i];
}
return sumOfElements;
}
}
I've always been able to help myself. But I can't get any further with this supposedly simple thing.
and for the completeness. Here is my temporarily hosted website and Github. Thanks also for the previous replies.
Project site
https://liquefied-stripe.000webhostapp.com/
Github
https://github.com/StevoEs/Einkaufsliste/blob/main/main.js
Thanks!

Changing content in multiple columns with a single button click

I am trying to change multiple columns with a single button click, after a click the image should change, the title and a phrase. I am only able to apply this to the first column. I tried iterating the columns with querySelectorAll() and searched answers in other forums.?
Also is it possible to assign a different random image to each column with the same single button click?
Thank you in advance!
const images = ['sandwich', 'cookie', 'monster', 'telegram', 'gym']
const inputName = document.getElementById('input-name');
const inputPhrase = document.getElementById('input-phrase');
const btnSubmit = document.querySelector('.input-btn');
const btnClr = document.querySelector('.clr-btn');
const row = document.querySelectorAll('.column');
const image = document.querySelector('.column img');
const title = document.querySelector('.name');
const phrase = document.querySelector('.phrase');
randomImage = Math.floor(Math.random() * images.length);
logoImage = images[randomImage];
window.addEventListener('DOMContentLoaded', function() {
// createLogo()
})
btnSubmit.addEventListener('click', function(e) {
e.preventDefault()
row.forEach(function(col) {
col.classList.add('change');
image.src = `./images/${logoImage}.png`;
title.textContent = inputName.value
phrase.textContent = inputPhrase.value
})
});
Instead of using a variable to refer to the image/name/phrase, you should reference them by col and queryselector in each iteration.
btnSubmit.addEventListener('click', function(e) {
e.preventDefault()
row.forEach(function(col) {
randomImage = Math.floor(Math.random() * images.length);
col.classList.add('change');
col.querySelector("img").src = './images/' + images[randomImage] + '.png';
col.querySelector(".name").textContent = inputName.value
col.querySelector(".phrase").textContent = inputPhrase.value
})
});

Generate heading IDs based on text content, incrementing by 1 for every duplicate

I'm currently building an auto-generated TOC in Javascript. Step 1 is to take the text content of every h1-6, strip punctuation and spaces, replace with dashes, and lowercase it, then add that as the id, which is what I have here:
function TOC() {
let h2s = document.querySelectorAll("h2");
let h3s = document.querySelectorAll("h3");
let h4s = document.querySelectorAll("h4");
let h5s = document.querySelectorAll("h5");
let h6s = document.querySelectorAll("h6");
let headings = [...h2s, ...h3s, ...h4s, ...h5s, ...h6s];
function cleanID(content) {
let trimmed = content.trim();
let removedPunctuation = trimmed.replace(/[^\w\s]|_/g, "").replace(/\s+/g, " ");
let singleSpacesOnly = removedPunctuation.replace(/\s\s+/g, " ");
let spacesToHyphens = singleSpacesOnly.replace(/\W/g, "-");
let cleanedID = spacesToHyphens.toLowerCase();
return cleanedID;
}
headings.forEach((heading) => {
heading.id = cleanID(heading.textContent);
});
}
TOC();
This works fine except when it comes to duplicate IDs. What I'd like to do is increment by 1 for every duplicate of each heading, and append that. So for example, if I had
<h2>Foo</h2>
<h3>Bar</h3>
<h2>Foo</h2>
<h3>Baz</h3>
<h4>Bar</h4>
I'd like for the IDs to be, respectively, foo, bar, foo-2, baz, bar-2.
The obvious doesn't seem to work:
var cleanedIDs = [];
function cleanID(content) {
...
let increment = 0;
if(cleanedIDs.includes(cleanedID) {
cleanedID = `${cleanedID}-${increment++}`;
cleanedIDs.push(cleanedID);
} else {
cleanedIDs.push(cleanedID);
}
}
Would appreciate help working through the logic of it. I've started a pen here.
You can use reduce to keep track of the count inside an Object. Then just change the id property accordingly.
let headings = [...document.querySelectorAll("h3")];
function headingDups (headings) {
return headings.reduce((store, heading) => {
store[heading.textContent] = (store[heading.textContent] || 0) + 1;
if(store[heading.textContent] > 1) {
heading.id = heading.textContent + "-" + store[heading.textContent]
return store;
}
heading.id = heading.textContent;
return store;
}, {});
}
headingDups(headings);
<h3>hello</h3>
<h3>goodbye</h3>
<h3>h3llo</h3>
<h3>hello</h3>
<h3>h3llo</h3>
<h3>goodbye</h3>

Replacing a div of text with individual spans as letters and iterating through it

I am attempting to replace a div of text with individual span elements of each letter, which is straightforward but I'm trying to have those spans font size increase incrementally and I can't figure out what to throw in the setTimeout function.
<div id ="foo"> Welcome to Here </div>
function test() {
let word = document.getElementById('foo');
let arr = word.split("")
word.innerHTML = "";
arr.forEach((x,index) => {
let newSpan = document.createElement('span')
newSpan.innerHTML = x;
word.appendChild(newSpan);
setTimeout(() => {
????
}, 100 + index*100)
})
}
Do your split on the inner text of your element and the increase the font size of your span:
function test() {
const baseFontSize = 16; // starting font size
const word = document.getElementById('foo');
const text = word.innerText; // split this and not your element object
const arr = text.split("");
word.innerHTML = "";
arr.forEach((x, index) => {
let newSpan = document.createElement('span')
newSpan.innerHTML = x;
word.appendChild(newSpan);
setTimeout(function() {
newSpan.style.fontSize = (baseFontSize + (index * 2)) + 'px'; // increment by 2px
}, 1000 * index) // increment each span a second after the last
})
}
test();
<div id="foo">Welcome to Here</div>
he is another try with settimeout
function test() {
var fontSize = 12;
let word = document.getElementById('foo');
let arr = word.innerHTML.split("")
word.innerHTML = "";
arr.forEach((x,index) => {
var fs = (fontSize + index) +"px";
let newSpan = document.createElement('span')
newSpan.innerHTML = x;
word.appendChild(newSpan);
setTimeout(function(){
newSpan.style.fontSize = fs
}, 2000 + (index * 100));
})
}
test();
span{
display : inline-block;
font-size:12;
}
<div id ="foo"> Welcome to Here </div>
The problem with this code is that getDocumentById() will return a reference to the element, not the text itself.
If the inner content of your div is plain text, you can try this
var domElement = document.getElementById('foo');
var word = domElement.innerText; // Here you get the text itself
domElement.innerText = ''; // Here you clear the previous content which should be text
for (let i = 0; i < word.length; i++) {
var spanElement = document.createElement('span');
spanElement.innerText = word[i];
domElement.appendChild(spanElement);
}
Now if you want to increase the size of the span, you can do it using the counter of the loop as you can see here
spanElement.style.fontSize = i

How to dynamically add <a> tags given an index of HTML page's string?

I'm making a search function for my website. So far, I've found the string the user searches for in the whole website, and I'm able to print the string and the context of the string. I have achieved this by using $.get on my HTML pages, then stripping the HTML to leave the pure text I want to search in. I then find the index of the string I'm looking for, then use substr to find the context of the input string (a few indexes ahead and behind).
Now, I need to link to the original page when a user clicks on a search result. My research says to use <a> tags, but how do I dynamically insert those into the HTML page with the index I have? And the index I have isn't even the complete page; it's stripped of tags.
These are the relevant parts of my code:
JavaScript:
function getIndicesOf(searchStr, str) { //get the indices of searchStr inside of str
var searchStrLen = searchStr.length;
if (searchStrLen == 0) {
return [];
}
var startIndex = 0, index, indices = [];
str = str.toLowerCase();
searchStr = searchStr.toLowerCase();
while ((index = str.indexOf(searchStr, startIndex)) > -1) {
indices.push(index);
startIndex = index + searchStrLen;
}
return indices;
}
function search() {
obj=document.getElementById("searchButton");
obj.onclick = function() {
var searchInput = document.getElementById('searchBox').value;
var allPageContent = ['chap/telem.php', 'chap/nestor.php', 'chap/aeolus.php', 'chap/calypso.php', 'chap/circe.php', 'chap/cyclops.php', 'chap/eumaeus.php', 'chap/hades.php','chap/ithaca.php', 'chap/lestry.php', 'chap/lotus.php', 'chap/nausicaa.php', 'chap/oxen.php', 'chap/penelope.php', 'chap/proteus.php', 'chap/scylla.php', 'chap/sirens.php', 'chap/wrocks.php']; //contains all text
var allText = '';
for (var i = 0; i < allPageContent.length; i++){
$.get(allPageContent[i], function(data){
var div = document.createElement("div");
div.innerHTML = data;
//allText = div.textContent || div.innerText || ""; //gets the text to search in, stripped of html
alltext = data;
allText = allText.replace(/(\r\n\t|\n|\r\t)/gm," ");
console.log(data);
var indices = getIndicesOf(searchInput, allText); //the variable indices is the array that contains the indices of the searched text in the main text
indices.forEach(findContext);
})
}
localStorage.output = '';
function findContext(currentValue, index) {
if (currentValue <= 16) {
searchContext = "..." + allText.substr(currentValue, 100) + "...";
} else {
searchContext = "..." + allText.substr(currentValue-15, 100) + "...";
}
localStorage.output = localStorage.output + searchContext + "<br /><br />";
}
console.log(localStorage.output);
};
};
HTML:
<script>document.getElementById("output").innerHTML = localStorage.output;</script>
It's a bit confusing what you're trying to achieve, considering your HTML, but replying to this
My research says to use <a> tags, but how do I dynamically insert
those into the HTML page with the index I have?
this would do the trick
var output = document.getElementById("output");
var a = document.createElement("a");
var linkText = document.createTextNode("my linked text");
a.appendChild(linkText);
a.href = "http://example.com";
output.appendChild(a);

Categories

Resources