Changing the SpeechSynthesis voice not working - javascript

I have tried all the variations I can find on stackoverflow, but I can still not get the voice to change on SpeechSynthesis
Below is the standalone code that fills a dropdown with all the available voices and allows me to select which voice I want.
Unfortunately this code does not change the voice. Also, before changing the voice. msg.voice is null, even though it has been used to list all the available voices.
Can anyone tell me what is wrong with the code? (console.log(msg.voice); gives a null before being set)
<!doctype html>
<html>
<head>
<SCRIPT>
var msg = new SpeechSynthesisUtterance();
voices = window.speechSynthesis.getVoices();
var numberOfVoices=0;
function Main(){
voiceSelect=document.getElementById("voiceSelect");
setTimeout(getVoicesFunction,2000);
}
function getVoicesFunction(){
msg = new SpeechSynthesisUtterance("hello");
numberOfVoices=0;
speechSynthesis.getVoices().forEach(function(voice) {
var option = document.createElement('option');
option.text = option.value = voice.voiceURI;
voiceSelect.add(option, 0);
numberOfVoices=numberOfVoices+1;
});
voiceSelect.onchange = voiceChange;
}
function voiceChange(){
textToSpeech("this is the old voice");
var selectedOption = this[this.selectedIndex];
selectedVoice = selectedOption.text;
msg = new SpeechSynthesisUtterance();
voices = window.speechSynthesis.getVoices();
msg = new SpeechSynthesisUtterance();
console.log("before change msg.voice");
console.log(msg.voice);
for(i = 0; i < numberOfVoices ; i++) {
if(voices[i].voiceURI === selectedVoice) {
var temp="changing the voice number to "+i;
setTimeout(textToSpeech,2000,temp);
msg.voice = voices[i];
console.log(msg.voice);
var tempVoiceNumber=i;
};
}
setTimeout(textToSpeech,4000,"this is the new voice");
}
function textToSpeech(tspeech){
msg = new SpeechSynthesisUtterance();
msg.text = tspeech;
speechSynthesis.speak(msg);
console.log("speech "+tspeech);
}
</SCRIPT>
</head>
<body onload= "Main()" id= "mainb">
<div id="container">
<select name="Combobox1" size="1" id="voiceSelect">
</select>
</div>
</body>
</html>

IanR, I copied the code and it works for me. I cut out the pitch and rate controls and made the html simpler, but it's basically the same.
If it doesn't work for you are you getting any console errors?
var synth = window.speechSynthesis;
var inputForm = document.querySelector('form');
var inputTxt = document.querySelector('.txt');
var voiceSelect = document.querySelector('select');
/*var pitch = document.querySelector('#pitch');
var pitchValue = document.querySelector('.pitch-value');
var rate = document.querySelector('#rate');
var rateValue = document.querySelector('.rate-value');*/
var voices = [];
function populateVoiceList() {
voices = synth.getVoices();
for (i = 0; i < voices.length; i++) {
var option = document.createElement('option');
option.textContent = voices[i].name + ' (' + voices[i].lang + ')';
if (voices[i].default) {
option.textContent += ' -- DEFAULT';
}
option.setAttribute('data-lang', voices[i].lang);
option.setAttribute('data-name', voices[i].name);
voiceSelect.appendChild(option);
}
}
populateVoiceList();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoiceList;
}
inputForm.onsubmit = function(event) {
event.preventDefault();
var utterThis = new SpeechSynthesisUtterance(inputTxt.value);
var selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');
for (i = 0; i < voices.length; i++) {
if (voices[i].name === selectedOption) {
utterThis.voice = voices[i];
}
}
//utterThis.pitch = pitch.value;
//utterThis.rate = rate.value;
synth.speak(utterThis);
inputTxt.blur();
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>61016951</title>
<script src="61016951.js" defer></script>
</head>
<body>
<div id="div">
<form>
<input type="text" class="txt">
<select></select>
<button type="submit">Play</button>
</form>
</div>
</body>
</html>

Stripping out all the extra bits in your code, here's how you'll need to handle the asynchronous loading on speechSynthesis.getVoices();
if (voiceLoaded()) {
speak();
} else {
speechSynthesis.addEventListener('voiceschanged', speak);
}
function speak() {
const utterance = new SpeechSynthesisUtterance('text');
utterance.voice = getFemaleVoice();
speechSynthesis.speak(utterance);
}
function getFemaleVoice() {
const voiceIndex = 4;
return speechSynthesis.getVoices()[voiceIndex];
}
function voiceLoaded() {
return speechSynthesis.getVoices().length;
}
If the voices array has loaded already then it'll speak the utterance, otherwise this code will add the event listener on the voiceschanged event which will fire once the browser loads the array of voices and then your callback to speak will run.

Related

How to pass Range Values into an HTML sidebar to be ticked or selected then save selections using GAS?

As the sidebar is open, it displays the colors (color name and its HEX #, which are sitting in a sheet) and displays also a checkbox next to each color.
The user ticks the checkbox or selects the colors how many he/she wants all the way down, clicks on save and the list gets saved into an array...maybe PropertiesService.getDocumentProperties()
Here's the code I got for the sidebar and getting the colors from the range:
var ss = SpreadsheetApp.getActiveSpreadsheet();
function showSideBar() {
var ui = SpreadsheetApp.getUi();
var tmp = HtmlService.createTemplateFromFile('pickColor');
var html = tmp.evaluate();
html.setTitle('Escolha as cores');
ui.showSidebar(html);
}
function getColors() {
const colorListSheet = ss.getSheetByName('CadCores');
const colorList = colorListSheet.getRange(2,1,colorListSheet.getLastRow(),2).getValues();
return colorList;
}
Here's the html part, whose body I can't make it dynamic being a newbie. Listed Yellow as an example, but I suppose that having the checkbox, the color name and its hex would require it to be a table, correct?
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<input id="Yello" type="checkbox">
<label for="yellow">Yellow</label>
<br>
<br>
<button id='salvar-cores'>Salvar Cores</button>
<br>
<br>
<script>
let colorArray = 10;//But this would be the getColors' length, right?
function addColor(colors){
for (let i = 0; i < colorArray; i++){
$(i + 1).text(colors[i]);
}
};
google.script.run.withSuccessHandler(addColor).getColors();
</script>
</body>
</html>
Any direction is appreciated.
You can always put a ballot symbol into a select option and toggle on or off. Here is an example.
Code.gs:
function onOpen() {
try {
var menu = SpreadsheetApp.getUi().createMenu("Cad Colors");
menu.addItem("Get Colors", "showGetColors");
menu.addToUi();
}
catch(err) {
Logger.log(err);
}
}
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}
function showGetColors() {
try {
var html = HtmlService.createTemplateFromFile("HTML_GetColors").evaluate();
SpreadsheetApp.getUi().showSidebar(html);
}
catch(err) {
SpreadsheetApp.getUi().alert(err);
}
}
function getColors() {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("CadColors");
return sh.getDataRange().getValues();
}
catch(err) {
Logger.log(err);
}
}
function setColors(checked) {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("CadColors");
sh.getRange(2,3,checked.length,1).setValues(checked);
}
catch(err) {
Logger.log(err);
}
}
Then if the HTML file:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<select id="colorSelect" onchange="colorOnChange()" ondblclick="colorDblClick()"></select>
<input type="button" onclick="colorSaveClick()" value="Save Colors">
<?!= include("JS_GetColors"); ?>
</body>
</html>
I've seperated out the javascript in a seperate file that is included into a HTML Template:
<script>
function colorOnChange() {
try {
var select = document.getElementById("colorSelect");
var option = select.options[select.selectedIndex];
var text = option.text;
text = text.charAt(0) === "☐" ? "☑" : "☐";
text = text.concat(option.text.slice(1));
option.text = text;
}
catch(err) {
alert(err);
}
}
function colorDblClick() {
try {
var select = document.getElementById("colorSelect");
var text = select.value;
var option = null;
text = text.charAt(0) === "☐" ? "☑" : "☐";
text = text.concat(select.value.slice(1));
for( var i=0; i<select.options.length; i++ ) {
option = select.options[i];
if( option.text.slice(1) === text.slice(1) ) {
option.text = text;
break;
}
}
select.value = text;
}
catch(err) {
alert(err);
}
}
function colorSaveClick() {
try {
var select = document.getElementById("colorSelect");
var checked = [];
for( var i=0; i<select.options.length; i++ ) {
// note that checked is an array of arrays
checked.push( select.options[i].text.charAt(0) === "☑" ? [true] : [false] );
}
google.script.run.setColors(checked);
}
catch(err) {
alert(err);
}
}
(function () {
try {
google.script.run.withSuccessHandler(
function (colors) {
try {
var option = null;
var text = null;
// omit first line
for( var i=1; i<colors.length; i++ ) {
option = document.createElement("OPTION");
text = document.createTextNode("☐ "+colors[i][0]+" "+colors[i][1]);
option.appendChild(text);
document.getElementById("colorSelect").appendChild(option);
}
}
catch(err) {
alert(err);
}
}
).getColors();
}
catch(err) {
alert(err);
}
}());
</script>
The only difficulty is handling the select.value. To toggle it you have to double click. Every other one you can select and toggle from the drop down. The status of the selections is returned to the spreadsheet using setColors().
My spreadsheet looks like this:
And the sidebar like this:
I think this could work for you
1. I got all the colors in a spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
function showSideBar() {
var ui = SpreadsheetApp.getUi();
var tmp = HtmlService.createTemplateFromFile('pickColor');
var html = tmp.evaluate();
html.setTitle('Escolha as cores');
ui.showSidebar(html);
}
function getColors() {
const colorListSheet = ss.getSheetByName('CadCores');
const colorList = colorListSheet.getRange(2,1,colorListSheet.getLastRow() -1,2).getValues();
return colorList;
}
function onOpen(){
showSideBar()
}
2. Render the colors in the DOM
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div id='color-name'></div>
<br>
<button id='salvar-cores'>Salvar Cores</button>
<script>
function afterLoad(){
google.script.run.withSuccessHandler(afterDataReturned).getColors();
}
function afterDataReturned(arrayOfArrays){
const item = document.getElementById("color-name")
arrayOfArrays.forEach(function(row){
let input = document.createElement("input")
input.type = "checkbox"
input.id = row[0]
input.value = row[1]
item.appendChild(input)
let label = document.createElement("label")
label.setAttribute('for',row[0])
label.textContent = row[0]
item.appendChild(label)
})
}
document.addEventListener("DOMContentLoaded", afterLoad)
</script>
</body>
</html>
3. Add any other color you want in the sheet and refresh the menu, so it reloads the new colors

How do I add an image to an if statement in Javascript?

I'm new at JavaScript to be patient with me. I'm trying to get this little "game" to work where you drag cards in the drop box, and when you drop the joker card in it says "victory", otherwise it says "betrayal" for the other cards. Everything works great except the part where it says "victory" when you drop the joker. I feel like I have tried everything. The joker card is $(#black_joker)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Drag and Drop</title>
<link rel="stylesheet" href="dragdrop.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
</head>
<body>
<h1>Find the Joker and eliminate him!</h1>
<br>
<input type="button" value="Deal!" id="dealDeck">
<br>
<br>
<br>
<br>
<br>
<div id='dropZone' class='dropZone'> <center>Find the joker card and drop it here to get rid of him once and for all! </center></div>
<script src="dragdrop.js"></script>
</body>
</html>
// JAVASCRIPT
$(document).ready(function () {
$(init);
function init() {
$('.dropZone').droppable({
drop: handleDropEvent
});
}
for (var a=0, all = 53; a < all; a++){
$('#dealDeck').click(function () {
dealCard(randomCard());
});
}
var cardsInDeck = new Array();
var numberOfCardsInDeck = 53;
cardsInDeck[0] = "C1";
cardsInDeck[1] = "C2";
cardsInDeck[2] = "C3";
cardsInDeck[3] = "C4";
cardsInDeck[4] = "C5";
cardsInDeck[5] = "C6";
cardsInDeck[6] = "C7";
cardsInDeck[7] = "C8";
cardsInDeck[8] = "C9";
cardsInDeck[9] = "C10";
cardsInDeck[10] = "C11";
cardsInDeck[11] = "C12";
cardsInDeck[12] = "C13";
cardsInDeck[13] = "D1";
cardsInDeck[14] = "D2";
cardsInDeck[15] = "D3";
cardsInDeck[16] = "D4";
cardsInDeck[17] = "D5";
cardsInDeck[18] = "D6";
cardsInDeck[19] = "D7";
cardsInDeck[20] = "D8";
cardsInDeck[21] = "D9";
cardsInDeck[22] = "D10";
cardsInDeck[23] = "D11";
cardsInDeck[24] = "D12";
cardsInDeck[25] = "D13";
cardsInDeck[26] = "H1";
cardsInDeck[27] = "H2";
cardsInDeck[28] = "H3";
cardsInDeck[29] = "H4";
cardsInDeck[30] = "H5";
cardsInDeck[31] = "H6";
cardsInDeck[32] = "H7";
cardsInDeck[33] = "H8";
cardsInDeck[34] = "H9";
cardsInDeck[35] = "H10";
cardsInDeck[36] = "H11";
cardsInDeck[37] = "H12";
cardsInDeck[38] = "H13";
cardsInDeck[39] = "S1";
cardsInDeck[40] = "S2";
cardsInDeck[41] = "S3";
cardsInDeck[42] = "S4";
cardsInDeck[43] = "S5";
cardsInDeck[44] = "S6";
cardsInDeck[45] = "S7";
cardsInDeck[46] = "S8";
cardsInDeck[47] = "S9";
cardsInDeck[48] = "S10";
cardsInDeck[49] = "S11";
cardsInDeck[50] = "S12";
cardsInDeck[51] = "S13";
cardsInDeck[52] = "black_joker";
function dealCard(i) {
if (numberOfCardsInDeck == 0) return false;
var img = document.createElement("img");
img.src = "http://deetito.com/images/" + cardsInDeck[i] + ".png";
img.id = cardsInDeck[i];
img.width = 100;
img.height = 125;
document.body.appendChild(img);
$('#C1').draggable();
$('#C2').draggable();
$('#C3').draggable();
$('#C4').draggable();
$('#C5').draggable();
$('#C6').draggable();
$('#C7').draggable();
$('#C8').draggable();
$('#C9').draggable();
$('#C10').draggable();
$('#C11').draggable();
$('#C12').draggable();
$('#C13').draggable();
$('#D1').draggable();
$('#D2').draggable();
$('#D3').draggable();
$('#D4').draggable();
$('#D5').draggable();
$('#D6').draggable();
$('#D7').draggable();
$('#D8').draggable();
$('#D9').draggable();
$('#D10').draggable();
$('#D11').draggable();
$('#D12').draggable();
$('#D13').draggable();
$('#H1').draggable();
$('#H2').draggable();
$('#H3').draggable();
$('#H4').draggable();
$('#H5').draggable();
$('#H6').draggable();
$('#H7').draggable();
$('#H8').draggable();
$('#H9').draggable();
$('#H10').draggable();
$('#H11').draggable();
$('#H12').draggable();
$('#H13').draggable();
$('#S1').draggable();
$('#S2').draggable();
$('#S3').draggable();
$('#S4').draggable();
$('#S5').draggable();
$('#S6').draggable();
$('#S7').draggable();
$('#S8').draggable();
$('#S9').draggable();
$('#S10').draggable();
$('#S11').draggable();
$('#S12').draggable();
$('#S13').draggable();
$('#black_joker').draggable();
removeCard(i);
}
function randomCard() {
return Math.floor(Math.random() * numberOfCardsInDeck);
}
function handleDropEvent(event, ui) {
var card = ui.draggable;
if (card == 'black_joker') {
$('#dropZone').html('victory!');}
else {
$('#dropZone').html('betrayal!');}
/*$('#dropZone').droppable({
drop: function(event, ui) {
ui.draggable.remove();
}
});*/
$("#dropZone").on('mouseover', function() {
//alert('bye draggable!');
//ui.draggable.draggable('disable');
//$(this).droppable('disable');
ui.draggable.remove();
})
}
function removeCard(c) {
// simply make every higher numbered card move down 1
for (j = c; j <= numberOfCardsInDeck - 2; j++) {
cardsInDeck[j] = cardsInDeck[j + 1];
}
numberOfCardsInDeck--;
}
});
I believe you are comparing object with string.
ui.draggable should be jQuery object
let card = ui.draggable.attr("id");
compare it with your id or other attribute you wanted to use should work

How long will the nodes after insert into document cost to paint?

I just want to get the nodes's render time when I insert 100000 nodes into document,I had tried few ways,but result unexpected.
Here is the example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>node insert cost time test</title>
<script>
var st = Date.now();
</script>
</head>
<body>
<h1>Placehoder</h1>
<h1 id="h1"></h1>
<h1 id="h2"></h1>
<h1 id="h3"></h1>
<h1 id="h4"></h1>
<h1 id="h5"></h1>
<div id="box"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
var en = Date.now();
$("#h4").html("White cost time:" + (en - st));
</script>
<script>
let data = [];
for(let i =0;i<100000;i++){
data.push({
name:"test",
age:18,
gender:"female"
})
}
const s = Date.now();
let list = data;
const timer = setInterval(() => {
const ss = Date.now();
if ($("#indexid-" + (list.length - 1)).size() > 0) {
const findTime = new Date();
const ft = + findTime;
$("#h5").html(findTime)
$("#h1").html(`The RealTime is ${findTime - s}`)
clearInterval(timer);
}
}, 1)
const tpl = '<div id="indexid-{id}">' +
'<h2>Name:{name}</h2>' +
'<h4>Gender:{gender}</h4>' +
'<h6>Age:{age}</h6>' +
'</div>'
let res = [];
list.forEach((item, index) => {
item.id = index;
let str = tpl.replace(/\{(\w+)\}/gi, function ($, $1) {
if (item[$1] + "") {
return item[$1];
}
return ""
})
res.push(str);
})
//insert 100000 nodes into document
//then get the nodes render time
$("#box").html(res.join(""))
const e = Date.now();
$("#h2").html(`JS execute time:${e - s}ms`)
</script>
</body>
</html>
This works well on desktop browsers,but not on the mobileweb.
On mobile web,the output time is smaller than what it should be.I also used MutationObserver Api,but got the same result,could anyone help me?

How to remove array objects from localStorage using dynamic buttons? [JS only]

New to JS here, been struggling with this one for a few hours now.
So I created a to do list with a button that stores objects in an array inside localStorage and also creates dynamic list items with content and delete buttons. Whenever I click the delete button it removes the dynamic list item but doesn't remove it from localStorage. I can't figure out how to assign each button to the specific array index in localStorage.
https://codepen.io/jupiterisland/pen/ooPXWV
var taskList = []; //build array
if(localStorage.taskList){ //call func to recreate li's on refresh
taskList = JSON.parse(localStorage.taskList) || [];
createTasks(taskList)
}
function submitFunc() {
var task = { //build objects
desc: document.getElementsByTagName("textarea")[0].value,
date: document.getElementsByTagName("input")[0].value,
time: document.getElementsByTagName("input")[1].value,
important: document.getElementsByTagName("input")[1].checked
};
if(task.desc && task.date !== ""){
taskList[taskList.length] = task; //put objects inside array
localStorage.taskList = JSON.stringify(taskList); //store array with stringify
newTaskList = JSON.parse(localStorage.taskList); //retrieve array with parse
createTasks(newTaskList)
document.getElementById("error").style.display = "none";
return false; //prevent submit
} else {
document.getElementById("error").style.display = "block";
document.getElementById("error").innerHTML = "Please enter a task description and a date.";
return false;
}
}
function createTasks (newTaskList){
for (i = 0; i < newTaskList.length; i++) { // display objects in list items
var currentTask = newTaskList[i];
var taskIndex = newTaskList.indexOf(currentTask);
newElement();
function newElement() {
var liNode = document.createElement("li");
var titleNode = document.createElement("h3");
var dNode = document.createElement("p");
var tNode = document.createElement("p");
var delNode = document.createElement("button")
liNode.className = "liNode";
titleNode.className = "titleNode";
dNode.className = "dNode";
tNode.className = "tNode";
delNode.className = "delete";
delNode.innerText = "Delete";
var titleText = newTaskList[i].desc;
var dateText = newTaskList[i].date;
var timeText = newTaskList[i].time;
var descNode = document.createTextNode(titleText);
var dateNode = document.createTextNode(dateText);
var timeNode = document.createTextNode(timeText);
titleNode.appendChild(descNode);
dNode.appendChild(dateNode);
tNode.appendChild(timeNode);
liNode.appendChild(titleNode);
liNode.appendChild(dNode);
liNode.appendChild(tNode);
liNode.appendChild(delNode);
document.getElementById("taskBoard").appendChild(liNode);
if (taskBoard.childElementCount > newTaskList.length) { //remove excess divs
for (n = 0; taskBoard.childElementCount - 2; n++) {
taskBoard.removeChild(taskBoard.firstChild);
}
}
function deleteTasks(){
var listItem = this.parentNode;
var ul = listItem.parentNode;
ul.removeChild(listItem);
}
delNode.addEventListener("click", deleteTasks);
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>My Task Board</h1>
<div class="container">
<form onsubmit="return submitFunc()">
<div>
<label for="">Task:</label>
<textarea name="name" rows="8" cols="80"placeholder="Please enter your task description"></textarea>
</div>
<div>
<label for="">Deadline:</label>
<input type="date" placeholder="Choose a date">
<input type="time" placeholder="Set time">
</div>
<div>
<label for="">Important:</label>
<input type="checkbox" name="" value="">
</div>
<button type="submit" name="button">Add Task</button>
<div id="error"></div>
</form>
</div>
<div>
<ul id="taskBoard"></ul>
</div>
</body>
</html>
var taskList = []; //build array
if(localStorage.taskList){ //call func to recreate li's on refresh
taskList = JSON.parse(localStorage.taskList) || [];
createTasks(taskList)
}
function fakeGuid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
function submitFunc() {
var task = { //build objects
desc: document.getElementsByTagName("textarea")[0].value,
date: document.getElementsByTagName("input")[0].value,
time: document.getElementsByTagName("input")[1].value,
important: document.getElementsByTagName("input")[1].checked,
id :fakeGuid()
};
if(task.desc && task.date !== ""){
taskList[taskList.length] = task; //put objects inside array
localStorage.taskList = JSON.stringify(taskList); //store array with stringify
newTaskList = JSON.parse(localStorage.taskList); //retrieve array with parse
createTasks(newTaskList)
document.getElementById("error").style.display = "none";
return false; //prevent submit
} else {
document.getElementById("error").style.display = "block";
document.getElementById("error").innerHTML = "Please enter a task description and a date.";
return false;
}
}
function createTasks (newTaskList){
for (i = 0; i < newTaskList.length; i++) { // display objects in list items
newElement(i);
function newElement(currentIndex) {
var liNode = document.createElement("li");
var titleNode = document.createElement("h3");
var dNode = document.createElement("p");
var tNode = document.createElement("p");
var delNode = document.createElement("button")
liNode.className = "liNode";
titleNode.className = "titleNode";
dNode.className = "dNode";
tNode.className = "tNode";
delNode.className = "delete";
delNode.innerText = "Delete";
var titleText = newTaskList[i].desc;
var dateText = newTaskList[i].date;
var timeText = newTaskList[i].time;
var descNode = document.createTextNode(titleText);
var dateNode = document.createTextNode(dateText);
var timeNode = document.createTextNode(timeText);
titleNode.appendChild(descNode);
dNode.appendChild(dateNode);
tNode.appendChild(timeNode);
liNode.appendChild(titleNode);
liNode.appendChild(dNode);
liNode.appendChild(tNode);
liNode.appendChild(delNode);
document.getElementById("taskBoard").appendChild(liNode);
if (taskBoard.childElementCount > newTaskList.length) { //remove excess divs
for (n = 0; taskBoard.childElementCount - 2; n++) {
taskBoard.removeChild(taskBoard.firstChild);
}
}
function deleteTasks(node, currentTask) {
var listItem = node.parentNode;
var ul = listItem.parentNode;
ul.removeChild(listItem);
taskList = taskList.filter(function(t) {
return t.id !== currentTask.id;
});
localStorage.taskList = JSON.stringify(taskList); //store array with stringify
}
var currentTask = newTaskList[currentIndex];
delNode.addEventListener("click", () => deleteTasks(delNode, currentTask));
}
}
}
Don't try to use index to manipulate DOM element. Instead use some kind of unique ID. In this case I created a fake GUID.
Read more on closure. The reason you are not able to pass index down to the function is because the index is bound to another context.
Any reason to stringify JSON for local storage? You can simply store an array.

Javascript SetInterval and get value Math.random

I have just created random number. My problems is how to get value random in id and how to set price changes automatically every 5 seconds and the fluctuation amplitude less than +/- 5% compared to the current, I don't know use the setinterval function everybody help me
My code Random Price :
function generateRandomNumber(min,max) {
return (Math.random() * (max - min) + min).toFixed(2);
};
document.getElementById('price1').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price2').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price3').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price4').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price5').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price6').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price7').innerHTML = generateRandomNumber(0,99.99);
It took me a while to work around the recursion issues I was running into, before I came up with a better solution.
//<![CDATA[
// external.js
function RandNumMaker(min, max, withinPercent, secondsInterval, decimalPlaces){
this.withinPercent = withinPercent || 5;
this.secondsInterval = secondsInterval || 5;
this.decimalPlaces;
if(decimalPlaces){
this.decimalPlaces = decimalPlaces;
}
var t = this, ia = [];
function rb(mn, mx){
return mx-Math.random()*(mx-mn);
}
var pn = rb(min, max);
function rn(){
var p = 1;
if(Math.floor(Math.random()*2) === 1)p = -1
return p*(Math.floor(Math.random()*t.withinPercent)+1)/100*pn;
}
function rf(){
var r, d = t.decimalPlaces;
pn += rn();
if(pn < min || pn > max){
return rf();
}
r = pn;
if(d)r = (Math.floor(Math.round(Math.pow(10, d+1)*r)/10)/Math.pow(10, d)).toFixed(d);
return r;
}
this.setDiv = function(div){
div.innerHTML = rf(); ia = [];
var iv = setInterval(function(){
div.innerHTML = rf();
}, this.secondsInterval*1000);
ia.push(iv);
return this;
}
this.stop = function(){
for(var i=0,l=ia.length; i<l; i++){
if(ia[i]){
clearInterval(ia[i]);
}
}
ia = [];
return this;
}
}
var doc, bod, C, E, N, old = onload; // for use on other loads
onload = function(){
if(old)old();
doc = document; bod = doc.body;
C = function(tag){
return doc.createElement(tag);
}
E = function(id){
return doc.getElementById(id);
}
N = function(className, inElement){
var ii = inElement || doc;
var cN = ii.getElementsByClassName(className);
if(cN){
return cN;
}
var tn = ii.getElementsByTagName('*');
for(var i=0,e,a=[],l=tn.length; i<l; i++){
e = tn[i];
if(e.className && e.className === className)a.push(e);
}
return a;
}
var sr = new RandNumMaker(0, 99.99), sl = N('slow');
var fr = new RandNumMaker(0, 99.99), fs = N('fast');
sr.decimalPlaces = 2;
fr.secondsInterval = 0.1; fr.withinPercent = 5;
for(var i=0,l=sl.length; i<l; i++){
sr.setDiv(sl[i]);
}
for(var i=0,l=fs.length; i<l; i++){
fr.setDiv(fs[i]);
}
}
//]]>
/* extrnal.js */
html,body{
padding:0; margin:0;
}
body{
background:#000; overflow-y:scroll;
}
.main{
width:940px; background:#fff; padding:20px; margin:0 auto;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf-8' />
<meta name='viewport' content='width=device-width' />
<title>test</title>
<link type='text/css' rel='stylesheet' href='external.css' />
<script type='text/javascript' src='external.js'></script>
</head>
<body>
<div class='main'>
<div class='slow'></div>
<div class='slow'></div>
<div class='slow'></div>
<div class='slow'></div>
<div class='slow'></div>
<div class='slow'></div>
<div class='slow'></div>
<hr />
<div class='fast'></div>
<div class='fast'></div>
<div class='fast'></div>
<div class='fast'></div>
</div>
</body>
</html>
Should work now!
After you create a new RandNumMaker(min, max) then you can set randomNumMarkerInstance.decimalPlaces, randomNumMakerInstance.withinPercent and randomNumMakerInstance.secondsInterval using simple assignment. randomNumMakerInstance.setDiv(div) starts it. randomNumMakerInstance.stop() stops it.
I think you can understand this code.
I tried to keep your code.
The key is to use setInterval function.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<script>
function generateRandomNumber(min,max) {
return (Math.random() * (max - min) + min).toFixed(2);
};
function assignData(){
document.getElementById('price1').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price2').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price3').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price4').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price5').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price6').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price7').innerHTML = generateRandomNumber(0,99.99);
setInterval(assignData, 5000); //every 5 seconds
}
</script>
<body onload="assignData()">
<h2 id="price1"></h2>
<h2 id="price2"></h2>
<h2 id="price3"></h2>
<h2 id="price4"></h2>
<h2 id="price5"></h2>
<h2 id="price6"></h2>
<h2 id="price7"></h2>
</body>
</html>
My interpretation of your question: all elements to start with a random value between 0 and 99.99, and then every five seconds one randomly selected element is to be updated, changing its value by a random amount within 5% of its current value. (If you want to update every element every five seconds then change the random selection to be a loop instead.)
For simplicity in the demo snippet (click "Run code snippet" to see it work), I've used a group of <li> elements which I select with .querySelectorAll("li"), but if you really want to do it using element IDs you could say .querySelectorAll("#price1,#price2,#price3,#price4,#price5,#price6,#price7").
function generateRandomNumber(min,max) {
return (Math.random() * (max - min) + min).toFixed(2);
}
// get list of elements:
var elements = document.querySelectorAll("li");
// populate all elements initially:
[].forEach.call(elements, function(el) {
el.innerHTML = generateRandomNumber(0,99.99);
});
// update an element at random every second:
setInterval(function update() {
var element = elements[Math.floor(Math.random() * elements.length)];
var currentVal = +element.innerHTML;
element.innerHTML = generateRandomNumber(currentVal * 0.95, currentVal * 1.05);
}, 1000);
<ul>
<li></li><li></li><li></li><li></li><li></li><li></li><li></li>
</ul>
Note that five second intervals seemed too slow for a demo, so I've used one second (1000ms) here.
Further reading:
.querySelectorAll()
Array .forEach() method
Function.prorotype.call()
Math.floor()
unary plus operator
Hope this will help.
<body>
<p id="price1"></p>
<p id="price2"></p>
<p id="price3"></p>
<p id="price4"></p>
<p id="price5"></p>
<p id="price6"></p>
<p id="price7"></p>
</body>
<script>
//set initial random number for the elements
document.getElementById('price1').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price2').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price3').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price4').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price5').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price6').innerHTML = generateRandomNumber(0,99.99);
document.getElementById('price7').innerHTML = generateRandomNumber(0,99.99);
//set random number to elements with fluctuation +/- 5%
setRandomToElements()
function generateRandomNumber(min,max) {
return (Math.random() * (max - min) + min).toFixed(2);
};
function setRandomToElements(){
//get current prices
var currentPrice1 = parseInt(document.getElementById('price1').innerHTML);
var currentPrice2 = parseInt(document.getElementById('price2').innerHTML);
var currentPrice3 = parseInt(document.getElementById('price3').innerHTML);
var currentPrice4 = parseInt(document.getElementById('price4').innerHTML);
var currentPrice5 = parseInt(document.getElementById('price5').innerHTML);
var currentPrice6 = parseInt(document.getElementById('price6').innerHTML);
var currentPrice7 = parseInt(document.getElementById('price7').innerHTML);
var fluctuation = 0.05;//5%
//random new numbers +/-5% current price
document.getElementById('price1').innerHTML = generateRandomNumber(currentPrice1-(currentPrice1*fluctuation), currentPrice1+(currentPrice1*fluctuation));
document.getElementById('price2').innerHTML = generateRandomNumber(currentPrice2-(currentPrice2*fluctuation), currentPrice2+(currentPrice2*fluctuation));
document.getElementById('price3').innerHTML = generateRandomNumber(currentPrice3-(currentPrice3*fluctuation), currentPrice3+(currentPrice3*fluctuation));
document.getElementById('price4').innerHTML = generateRandomNumber(currentPrice4-(currentPrice4*fluctuation), currentPrice4+(currentPrice4*fluctuation));
document.getElementById('price5').innerHTML = generateRandomNumber(currentPrice5-(currentPrice5*fluctuation), currentPrice5+(currentPrice5*fluctuation));
document.getElementById('price6').innerHTML = generateRandomNumber(currentPrice6-(currentPrice6*fluctuation), currentPrice6+(currentPrice6*fluctuation));
document.getElementById('price7').innerHTML = generateRandomNumber(currentPrice7-(currentPrice7*fluctuation), currentPrice7+(currentPrice7*fluctuation));
setInterval(setRandomToElements, 5000);
}
</script>
Fiddle

Categories