Linking JS message loop to HTML header - javascript

I have been trying to make a loop of messages that change every hour (One is visible at a time) I'm decent at HTML, but I'm pretty bad at JS. (Message should go in h3)
I tried to link my JS loop into a HTML text element, but I failed.
h3 = document.createElement("h3");
var messages = "Message 1", "Message 2", "Message 3", "Message 4", "Message 5", "Message 6";
var counter = 0;
function myLoop() {
setTimeout(myLoop, 3, 600, 000);
document.getElementById("Message")
document.body.appendChild(h3);
}
myLoop();
<h3>
<h3 id="Message"></h3>
</h3>

do not wrap headers in headers
It looks like you wanted an Array of messages. I show you below how to make such a thing
You would not need to use appendChild when the element already exists on the page
3,600,000 is not valid milliseconds. Use 3600000 or 60*60*1000
In my code below I use an eventListener to wait with the execution until the html elements on the page are available
The statement (counter++)%len will start at 0 and wrap at length of array of messages using the remainder operator %. It saves an if (counter=> length) counter = 0;
The => is an Arrow_functions making the construct
const functionName (parameter) => { };
functionally equivalent (there are a few other things) to
function functionName(parameter) { };
Change the 2000 to 3600000 if you need every hour
const messages = ["Message 1", "Message 2", "Message 3", "Message 4", "Message 5", "Message 6"];
const len = messages.length;
let counter = 0;
window.addEventListener("DOMContentLoaded", () => { // when the page has loaded and the h3 is available
const h3 = document.getElementById("Message");
const myLoop = () => h3.textContent = messages[(counter++) % len]; // loop and wrap
myLoop(); // run once immediately
setInterval(myLoop, 2000); // then run every 2 seconds
});
<div>
<h3 id="Message"></h3>
</div>

Use this soulution if you want to have different time intervals between messages, but if you are fine with same repeated interval he solution above is more of "best practice".
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h3 id="Message"></h3>
<script>
var h3elem = document.getElementById('Message');
h3elem.innerHTML = "Starting text"
function myLoop() {
let messages = ['Message 1', 'Message 2', 'Message 3', 'Message 4', 'Message 5', 'Message 6'];
let timeouts = [1000, 2000, 3000, 5000, 6000, 7000];
for (let i = 0; i< messages.length; i++) {
setTimeout(() => {
h3elem.innerHTML = messages[i]
console.log("timeout", i)
}, timeouts[i])
}
}
myLoop();
</script>
</body>
</html>
Btw, while investigating this, I was down on my knees, when found out that it will work with let i = 0 and will not with var i = 0.
here is the explanation why https://medium.com/#axionoso/watch-out-when-using-settimeout-in-for-loop-js-75a047e27a5f.

Related

Button calls entirely different function than what its supposed to

What i want to happen is when i click the button after typing yes, it says "OLD MAN: thats good to hear, whats your name?" but instead it calls a different function saying the else answer for the question that has not been added yet. This is probably me being very dumb, because im new and bad at html/jss but if anyone sees why this is happening and let me know it would be greatly apreciated
the html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet"type="text/css"/>
<script src="script.js"></script>
</head>
<body onload="onload()">
<center>
<h1 class="Title"> Text Adventure HMTL </h1>
<h5> Please write your answer directly how it was written after the question</h5>
<br><br>
</center>
<p id="currentQuestion">
<p id="givenAnswers"></p>
<input type="textbox" id="answer" placeholder="Type your answer here">
<input id="enter" type="button" onclick="wakeUp()" value="enter">
</body>
</html>
the js:
var answers="Yes<br>No"
var name=""
function onload(){
document.getElementById("currentQuestion") .innerHTML=currentQuestion=currentQuestion
document.getElementById("givenAnswers").innerHTML=answers
}
function wakeUp(){
document.getElementById("currentQuestion").innerHTML=currentQuestion
document.getElementById("givenAnswers").innerHTML=answers
if(document.getElementById("answer").value=="No" || document.getElementById("answer").value=="no" )
{
currentQuestion="You did not wake up, the game has ended, please restart"
answers=""
document.getElementById("answer").value=""
onload()
document.getElementById("enter").onlclick = "dead()"
}
else if(document.getElementById("answer").value=="Yes" || "yes" ){
currentQuestion="OLD MAN: Good morning, how are you feeling?"
answers="Good<br>Bad<br>Else"
document.getElementById("answer").value=""
document.getElementById("enter").onlclick = howUFeel()
}
else{
document.getElementById("answer").value=""
}
}
function dead(){
currentQuestion="You have died, please restart"
document.getElementById("currentQuestion").innerHTML=currentQuestion
document.getElementById("answer").value=""
onload()
}
function howUFeel(){
if (document.getElementById("answer").value == "else" || "Else" )
{
currentQuestion="What do you mean by else? care to elaborate?"
answers="No"
onload()
document.getElementById("answer").value=""
}
else if(document.getElementById("answer").value == "good" || "Good" ){
currentQuestion="OLD MAN: Im Happy to hear it, do you by chance remember your name?"
}
else{
}
}
Here you can test it and see what it does: https://idkwthisgoingon.kitten3604.repl.co/
Edited Answer
You are using if incorrectly: if(something == option1 || option2) doesn't work like you think it does.
do:
if(document.getElementById('answer').value == option1 || document.getElementById('answer').value == option2)
in your checks.
if(something == string1 || string2) will always return true because a non-empty string is always considered true when converting into a boolean therefore the second condition in the if statement, which is string2, will be true
EDIT
While I already answered the question, I would like to give you a piece of advice:
Try to generalize your code as much as you can. it will make your code shorter and more readable, and it will also become helpful when adding functionality and complexity to the code.
Here is my implementation of the dialog mechanic which tries to follow this advice:
/* the dialog is represented by a nested object of the following form:
const dialogTree = {
'output': 'First Question',
'options': {
'option1': {
'output': 'new question',
'onselect': '\\<function to be executed when answering with this option\\>',
'options': {
'option1.1': {'output': 'new question', 'onselect': '...', 'options': {'...': '...'}},
'option1.2': {'output': 'new question', 'onselect': '...', 'options': {'...': '...'}},
}
},
'option2': {
'output': 'new question',
'onselect': '<function to be executed when answering with this option, leave empty for no special effects>',
'options': {
'option2.1': {'output': 'new question', 'onselect': '...', 'options': {'...': '...'}},
'option2.2': {'output': 'new question', 'onselect': '...', 'options': {'...': '...'}},
}
},
}
};
*/
// notes:
// - onselect is for special effects so don't include it if you don't want anything to happen (outside of the dialog continuing of course)
// - don't use special characters in the 'output' value (for instance <,>), instead use their entity number (see example)
// example for a dialog tree:
const dialogTree = {
'output': 'How are you feeling today?',
'options': {
'Good': {
'output': 'That\'s great, do you have anything to say to me?',
'options': {
'Not really': {'onselect': die},
'Yes, but it\'s a secret, so come close': {
'output': 'Ok, I\'m close, what is it?',
'options': {'&#60I can\'t think of a funny thing to write here&#62': {'onselect': die}}}
}
},
'Bad': {
'output': 'Why?',
'options': {
'Because this code looks bad': {
'output': 'That\'s hurtful :(',
'options': {
'*truthful': {'onselect': die}
}
},
'Because I don\'t like you': {
'onselect': die
},
}
},
'I don\'t want to talk': {
'onselect': die,
}
}
};
let prefix = 'Old Man: '; // prefix to go before each message
let dialogPath = []; // stores array of the answers so far
// some elements:
let questionEl = document.getElementById('current-question');
let givenAnswersEl = document.getElementById('given-answers');
let dialogDivEl = document.getElementById('dialog');
let deathMsgEl = document.getElementById('death-message');
// the current dialog tree (object):
let currentDialogTree = Object.create(dialogTree);
// function to be called to update the html to match the dialog data:
function flush() {
// setting current question:
questionEl.innerHTML = prefix + currentDialogTree.output;
// clearing the given answers:
givenAnswersEl.innerHTML = '';
let id = 0;
// adding given answers one by one.
for(let option in currentDialogTree.options) {
let newOption = document.createElement('input');
newOption.type = 'radio';
newOption.name = 'option';
newOption.value = option;
newOption.id = `option-${id}`;
givenAnswersEl.appendChild(newOption); // adding the option to the div
let newLabel = document.createElement('label');
newLabel.innerHTML = option;
newLabel.for = `option-${id}`;
givenAnswersEl.appendChild(newLabel); // adding the label to the div
givenAnswersEl.appendChild(document.createElement('br')); // adding a break to the div
id ++;
}
}
flush();
function getAnswer() {
let options = givenAnswersEl.children;
// for each of the given answers check if it is checked, and if so return it:
for(let option of options) {
if(option.checked) {
return option.value;
}
}
// if none found, return false:
return false;
}
// function to be called when user submits an answer:
function submit() {
let answer = getAnswer();
// check if an answer was given:
if(!answer) { return; }
// update dialog:
dialogPath.push(answer);
currentDialogTree = currentDialogTree.options[answer];
if(currentDialogTree.onselect) {
if(currentDialogTree.onselect()) {
// if an onselect function has a return value then we assume that it is die(), so we return:
return;
};
}
flush();
}
// function to be called when recalculating the current dialog tree:
function updateCurrentTree() {
// reset dialog tree:
currentDialogTree = Object.create(dialogTree);
// for each option in the dialogPath, narrow the dialogTree as if that option was chosen
for(let option of dialogPath) {
currentDialogTree = currentDialogTree.options[option];
}
}
function die() {
// hide dialog div:
dialogDivEl.style.display = 'none';
// show respawn div:
deathMsgEl.style.display = 'initial';
return true;
}
// function to be called to reset the dialog:
function reset() {
// hide respawn div:
deathMsgEl.style.display = 'none';
// show dialog div:
dialogDivEl.style.display = 'initial';
dialogPath.length = 0; // clearing the dialog path
updateCurrentTree(); // updating currnet dialog tree
flush();
}
// function for going back one step in the dialog:
function backstep() {
if(dialogPath.length) {
dialogPath.pop();
updateCurrentTree();
flush();
}
}
body {
font-family: cursive;
}
#given-answers {
margin-top: 10px;
margin-bottom: 10px;
}
button {
font-weight: bold;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="dialog">
<p id="current-question"></p>
<div id="given-answers">
</div>
<button id="enter" onclick="submit()">enter</button>
<button id="backstep" onclick="backstep()">undo</button>
</div>
<div id="death-message" style="display: none;">
<p>You died! click the button to restart</p>
<button id="restart" onclick="reset()">restart</button>
</div>
</body>
</html>

looping through object in the DOM

try to loop through objet & array by pressing button and show every object inside the DOM but it's just show the last objet once i press the button
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="btn">press</button>
<h1 id="name">name </h1>
<h1 id="age">age</h1>
<script >
const info =[{name : "john", age :"20"},{name : "bob", age :"25"},{name : "wil", age :"30"}]
const btn = document.getElementById('btn')
const name1 = document.getElementById('name')
const age = document.getElementById('age')
btn.addEventListener('click', show)
function show(){
for( i = 0; i < info.length; i++){
name1.innerHTML = info[i].name
age.innerHTML = info[i].age
}
console.log(info);
}
</script>
</body>
</html>
Just look at your code here.
for( i = 0; i < info.length; i++){
name1.innerHTML = info[i].name
age.innerHTML = info[i].age
}
When first time loops runs (for index 0), it stores the value (john and 20) in the html h1 tags.
<h1 id="name">name </h1>
<h1 id="age">age</h1>
And now when the loop run for index 1, then (bob and 25) is storing in the same h1 tags. So, previous values vanished. So in this way, the loop keeps running until the last index. So, it is showing only the last values of the array.
There is a solution that you can do. I have modified your code.
for( i = 0; i < info.length; i++){
if (i = 0){
name1.innerHTML = info[i].name
age.innerHTML = info[i].age
}
else{
name1.innerHTML += info[i].name
age.innerHTML += info[i].age
}
}
In this way, all the names and ages will be show in the h1 tags. This is just for basic understanding that where you are doing mistake.
If you want to show each name and age pair on different h1 tags. You can use Nodes. You create h1 element in the Javascript, and then put text inside the h1 and then use appendChild to place it as a last child in any div you wanted to place or you can use insertBefore to place it as the first child.
You can see the Link of W3Schools mentioned below to understand how element nodes are created and append in the html.
https://www.w3schools.com/jsref/met_node_appendchild.asp
You can create an index variable and store the current index and then get the element at that particular index and then increment it at the end. This is how you can get one by one name and age till last.
const info = [{
name: "john",
age: "20"
}, {
name: "bob",
age: "25"
}, {
name: "wil",
age: "30"
}]
const btn = document.getElementById('btn')
const name1 = document.getElementById('name')
const age = document.getElementById('age')
btn.addEventListener('click', show)
let index = 0;
function show() {
if (index < info.length) {
name1.textContent = info[index].name;
age.textContent = info[index].age;
index++;
}
}
<button id="btn">press</button>
<h1 id="name">name </h1>
<h1 id="age">age</h1>

quote generator without repeating not working

Hi I want to use the RandomQuoteGenerator Script and I found one on stackoverflow but I want it to not repeat the quotes, I found a solution here but it is not working for me. I am getting undefined error when clicking on the button. The original script provided in the above link is working fine but if I change the function as mentioned in the above link, I am getting undefined messages instead of quotes.
My Generator.js
var quotes = [
//success quotes
{
quote: "If you set your goals ridiculously high and it's a failure, you will fail above everyone else's success.",
source: "James Cameron",
tag: "success"
},
{
quote: "The Way Get Started Is To Quit Talking And Begin Doing",
source: "Walt Disney",
tag: "success"
},
{
quote: "Don’t Let Yesterday Take Up Too Much Of Today.",
source: "Will Rogers",
tag: "success"
},
{
quote: "We Generate Fears While We Sit. We Overcome Them By Action",
source: "Dr. Henry Link",
tag: "success"
},
//health quotes
{
quote: "Early to bed and early to rise, makes a man healthy wealthy and wise.",
source: "Benjamin Franklin",
tag: "health"
},
{
quote: "Let food be thy medicine and medicine be thy food.",
source: "Hippocrates",
tag: "health"
},
{
quote: "If you can’t pronounce it, don’t eat it.",
source: "Common Sense",
tag: "health"
},
{
quote: "Health is like money, we never have a true idea of its value until we lose it.",
source: "Josh Billings",
tag: "health"
},
//spirituality quotes
{
quote: "Life is really simple, but men insist on making it complicated.",
source: "Confucius",
tag: "spirituality"
},
{
quote: "My religion is very simple. My religion is kindness.",
source: "Dalai Lama",
tag: "spirituality"
},
{
quote: "Knowing others is wisdom; knowing the self is enlightenment.",
source: "Tao Te Ching",
tag: "spirituality"
},
{
quote: "When there is love in your heart, everything outside of you also becomes lovable.",
source: "Veeresh",
tag: "spirituality"
}
];
document.getElementById('loadQuote').addEventListener("click", printQuote, true);
//Sets up interval to show print qutoe every 15 seconds
var intervalID = window.setInterval(myCallback, 15000);
function myCallback() {
printQuote();
}
// Gets a random quote from array Quotes
function getRandomQuote () {
return quotes.splice(Math.floor(Math.random() * quotes.length), 1);
}
//prints quote to html
function printQuote() {
var getQuote = getRandomQuote();
var message = '';
message += '<p class ="quote">' + getQuote.quote + '</p>';
message += '<p class ="source">' + getQuote.source + '</p>';
message += '<p class ="tag">' + getQuote.tag + '</p>';
document.getElementById('quote-box').innerHTML = message;
newColor();
}
// function that will generate random color to the backgroun
var newColor = function randomColor() {
document.body.style.background = '#'+(Math.random()*0xFFFFFF<<0).toString(16);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Random Quotes</title>
<link href='https://fonts.googleapis.com/css?family=Playfair+Display:400,400italic,700,700italic' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div class="container">
<div id="quote-box">
<p class="quote">Be the change you wish to see in the world! </p>
<p class="source">Ghandi </p>
</div>
<button id="loadQuote">Show another quote</button>
</div>
<script src="quotes.js"></script>
<script src="generate.js"></script>
</body>
</html>
Your function getRandomQuote() returns an array so in order to access the object you need to access the first element of that array. Like this...
getQuote[0].quote

Loop is only displaying the last string in an array when adding it a span tag

I want to change the word in the span tag every 1.5 seconds but so far it is just displaying the last word in the array 'list'.
Here is my javascript
var list = [
"websites",
"user interfaces"
];
setInterval(function() {
for(var count = 0; count < list.length; count++) {
document.getElementById("word").innerHTML = list[count];
}}, 1500);
And here is the html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<span id="word"></span>
</body>
</html>
You don't need a for loop, just use that setInterval, your counter or even simpler using Array manipulation:
var list = [
"websites",
"user interfaces",
"cool neh?"
];
var count = 0; // Separate your count
function changeWord() { // Separate your concerns
document.getElementById("word").innerHTML = list[count];
count = ++count % list.length; // Increment and loop counter
}
changeWord(); // First run,
setInterval(changeWord, 1500); // Subsequent loops
<span id="word"></span>
If you want to not use a counter but do it using array manipulation:
var list = [
"websites",
"user interfaces",
"cool neh?"
];
var ELWord = document.getElementById("word"); // Cache elements you use often
function changeWord() {
ELWord.innerHTML = list[0]; // Use always the first key.
list.push(list.shift()); // Push the first key to the end of list.
}
changeWord();
setInterval(changeWord, 1500);
<span id="word"></span>
P.S: The inverse would be using list.unshift(list.pop()) as you can see here.
Performance-wise the solution using counter should be faster but you have a small Array so the difference should not raise any concerns.
You may wanna try this. Not looping, just calling a changeWord function every 1.5 sec.
var list = [
"websites",
"user interfaces"
];
var count = 0;
function changeWord() {
document.getElementById("word").innerHTML = list[count];
count = count < list.length-1 ? count+1 : 0;
}
setInterval(function() { changeWord(); }, 1500);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<span id="word"></span>
</body>
</html>
I would do this job by setTimeout() as follows,
function loopTextContent(a, el, dur = 1500){
var i = -1,
len = a.length,
STID = 0,
looper = _ => (el.textContent = a[i = ++i%len], STID = setTimeout(looper,dur));
looper();
return _ => STID;
}
var list = ["websites", "user interfaces", "user experience", "whatever"],
getSTID = loopTextContent(list, document.getElementById("word"));
setTimeout(_ => clearTimeout(getSTID()),10000);
<span id="word"></span>
Better use setTimeout. Every iteration should have its own timeout. See also
(() => {
const words = document.querySelector('#words');
typeWords([
"web sites",
"user interfaces",
"rare items",
"other stuff",
"lizard sites",
"ftp sites",
"makebelief sites",
"fake news sites",
"et cetera"
]);
function typeWords(list) {
list.push(list.shift()) && (words.innerHTML = list[list.length-1]);
setTimeout(() => typeWords(list), 1500);
}
})();
<div id="words"></div>
The problem with your code is whenever your interval function is called,loop get executed and prints the element because you are replacing the whole innerHtml on each iteration.
You can try the following code if u want to print whole list element again and again after interval.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<span id="word"></span>
</body>
The javascript code :
var list = [
"websites",
"user interfaces"
];
var count=0;
function print()
{
document.getElementById("word").innerHTML = list[count];
count += 1;
count%=list.length;
}
setInterval( print(), 1000);

How to fetch data from a database using PHP and pass it to Javascript

I am making a website using HTML, CSS, MySQL and Javascript that will allow the user to login and play a quiz, the quiz has 40 questions.
The Javascript code bellow is a countdown timer, that contains the variable named "questions" after 40 seconds, it will pass automatically to the next question.
var i = 0;
var cEl = document.getElementById('countdown');
var qEl = document.getElementById('question');
var questions = [
'Question1 ?',
'Question2 ?',
'Question3 ?',
'Question4 ?'
];
var Countdown = function (time) {
this.time = time;
this.observers = [];
};
Countdown.prototype.start = function () {
setTimeout(function () {
if (this.time-- > 0) {
this.updateObservers();
this.start();
}
}.bind(this), 1000);
};
Countdown.prototype.addObserver = function (observer) {
this.observers.push(observer);
};
Countdown.prototype.updateObservers = function () {
var i, l = this.observers.length;
for (i = 0; i < l; i++) {
this.observers[i](this.time);
}
};
function printTime (time) {
cEl.innerHTML = time + 's';
}
function nextQuestion (time) {
if (time <= 0) run();
}
function run () {
var c;
if (i < questions.length) {
qEl.innerHTML = questions[i++];
c = new Countdown(40);
c.addObserver(printTime);
c.addObserver(nextQuestion);
printTime(c.time);
c.start();
} else {
document.body.innerHTML = 'Fin du quiz';
}
}
run();
And this is the part of my "quiz.php" file where I want the questions to be inserted :
<!doctype html>
<html>
<head>
<title>
Quiz
</title>
</head>
<body class="no-scroll">
<div>
<!-- some code here -->
</div>
<!-- some code here -->
<script src="js/countdown_script.js"></script>
</body>
</html>
For now, the questions are in the following variable :
var questions = [
'Question1 ?',
'Question2 ?',
'Question3 ?',
'Question4 ?'
];
But I want to use questions and their answers that are already in a database, each question has 2 or 3 possible answers, I've read that I'm not supposed to add the php code inside of a .js file, I tried to add the questions variable in the php code bellow but it did not work :
<!doctype html>
<html>
<head>
<title>
Quiz
</title>
</head>
<body class="no-scroll">
<div>
<!-- some code here -->
</div>
<!-- some code here -->
<script src="js/countdown_script.js">
var questions = [
'Question1 ?',
'Question2 ?',
'Question3 ?',
'Question4 ?'
];</script>
</body>
</html>
What is the best way to do that in my case? Given that I'm still a beginner and I only know html, css, some javascript, php and mysql.
You need to make a small API.
Step 1. make an additional page in your application that will output clean JSON array with data from the dataabse
For example: myApiWithQuestions.php
{
questions: {
question1: {
"content":"content of the question",
"possibleAnswers":[
"something", "another answer"
]
},
question2: {
"content":"content of the question",
"possibleAnswers":[
"something", "another answer"
]
},
}}
Step 2: Make an ajax call using JQuery to look for the page you have just created
$(document).ready(){
$.ajax({
url: "myApiWithQuestions.php",
})
.done(function( data ) {
//use data as an array, iterate through it and put your questions to the DOM
});
}
On .done function continue with execution of your script
Where did you read that you're not supposed to run PHP code in Javascript?
Anyway, it doesn't really matter: you can. I do it all the time.
<script type="text/javascript" src="js/countdown_script.js">
<script type="text/javascript"><!--
var questions = [
<?php
//create and run your mysql query
//loop through your results
while($row=mysql_fetch_array($results)){
//print your results in javascript format
printf("'%s ?'\n",$row['question']);
}
?>
];
--></script>

Categories