I have the following test code and I want to update the div text and show one, two, three... but the result is only the last
Edit: Because any answer here it depends on "sleep", I don't actually use "sleep" on my code. I replaced the code with a for loop.
<!DOCTYPE html>
<html>
<body>
<button onclick="test()" id="myBtn">test</button><br />
<div id="demo"></div>
<script>
function dosomething() {
for(i=1; i<=500; i++) console.log(i);
}
function test() {
let $myBtn = document.getElementById('myBtn');
$myBtn.style.display = 'none';
document.getElementById("demo").innerHTML = 'one';
dosomething();
document.getElementById("demo").innerHTML = 'two';
dosomething();
document.getElementById("demo").innerHTML = 'three';
dosomething();
document.getElementById("demo").innerHTML = 'stop';
$myBtn.style.display = 'block';
}
</script>
</body>
</html>
In your example the system never has a chance to show you the one, two, three because it's tied up looping in your while and the page is not getting repainted.
You need to give it a break!
You can use the JS function setInterval for this - it will run a given function every time interval. But you also need to know when to stop it - and it's not absolutely accurate as there may be other things going on on your system so don't use it for e.g. implementing a stopwatch.
You can also use the JS function setTimeout which runs just the once, and then you run it again etc until you've output all the texts. Here's a small example:
<html>
<body>
<button onclick="test()" id="myBtn">test</button><br />
<div id="demo"></div>
<script>
let text = ['one', 'two', 'three', 'stop'];
let i = 0; //this indicates which text we are on
function test() {
document.getElementById("demo").innerHTML = text[i];
i++;
if ( i< text.length) {
setTimeout(test,1000);
}
}
</script>
</body>
</html>
You might be better off using the in-built setTimeout function, with some tweaks. Something like:
<html>
<body>
<button onclick="test()" id="myBtn">test</button><br />
<div id="demo"></div>
<script>
var contentArray = ['one', 'two', 'three', 'stop']; // <- declare the array of values you want here
function test() {
let $myBtn = document.getElementById('myBtn');
$myBtn.style.display = 'none';
for(let i = 0; i < contentArray.length; i++){ // <- using 'let' instead of 'var', so a new variable is created on each iteration
setTimeout(function() {
// console.log(i); // <- if you want to see the values, uncomment this line
document.getElementById("demo").innerHTML = contentArray[i];
}, 1000 * (i+1));
};
$myBtn.style.display = 'block';
}
</script>
</body>
</html>
With your self written sleep function, you stopped the Browser from passing the rendering Process until all your code had run.
You have to do something like this:
<!DOCTYPE html>
<html>
<body>
<button onclick="test()" id="myBtn">test</button><br />
<div id="demo"></div>
<script>
function sleep(sleepDurationMS) {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, sleepDurationMS);
});
}
function test() {
let $myBtn = document.getElementById('myBtn');
$myBtn.style.display = 'none';
document.getElementById("demo").innerHTML = 'one';
sleep(1000).then(() => {
document.getElementById("demo").innerHTML = 'two';
sleep(1000).then(() => {
document.getElementById("demo").innerHTML = 'three';
sleep(1000).then(() => {
document.getElementById("demo").innerHTML = 'stop';
$myBtn.style.display = 'block';
});
});
});
}
</script>
</body>
JavaScript is Asynchronous so you will Get 'stop' as output .
Here I am using setTimeout Function() .
You don't need sleep function and here.
<!DOCTYPE html>
<html>
<body>
<button onclick="test()" id="myBtn">test</button><br />
<div id="demo"></div>
<script>
function test() {
let $myBtn = document.getElementById('myBtn');
$myBtn.style.display = 'none';
setTimeout(function () {document.getElementById("demo").innerHTML = 'one';},1000);
setTimeout(function () {document.getElementById("demo").innerHTML = 'two';},2000);
setTimeout(function () {document.getElementById("demo").innerHTML = 'three';},3000);
setTimeout(function () {document.getElementById("demo").innerHTML = 'stop';},4000);
$myBtn.style.display = 'block';
}
</script>
</body>
</html>
Your sleep function is blocking the Event Loop and this line
$myBtn.style.display = 'none';
causes the text to be hidden.
If you want that sleep feature, you should write it in async manner using Promise with setTimeout like this
<!DOCTYPE html>
<html>
<body>
<button onclick="test()" id="myBtn">test</button><br />
<div id="demo"></div>
<script>
const sleep = async (sleepDurationMS) => new Promise((resolve) => setTimeout(() =>
resolve(), sleepDurationMS))
async function test() {
let $myBtn = document.getElementById('myBtn');
document.getElementById("demo").innerHTML = 'one';
await sleep(1000);
document.getElementById("demo").innerHTML = 'two';
await sleep(1000);
document.getElementById("demo").innerHTML = 'three';
await sleep(1000);
document.getElementById("demo").innerHTML = 'stop';
}
</script>
</body>
</html>
Related
I'm seeing something weird with some async Javascript accessing a class method.
I have some Javascript that does a fairly intensive search, which can take some time (about 1 minute), so I want to run it asynchronously.
Here's my MVCE:
<html>
<head>
<script
src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
crossorigin="anonymous"></script>
</head>
<body>
<div id="search-form">
<input id="search-terms" type="text" placeholder="enter search terms" />
<button id="search-button">Search</button>
</div>
</body>
<script type="text/javascript">
class Index {
constructor() {
this.internal_hash = {};
}
get_term_count(){
return Object.keys(this.internal_hash).length;
}
do_big_long_expensive_calculation(){
var i=0;
for(i=0; i<10000; i++){
this.internal_hash[i] = i+1;
}
return i;
}
search_text(text){
var results = this.do_big_long_expensive_calculation();
return results;
}
};
var search_index = new Index;
var search_results = null;
$(document).ready(function(){
async function searchIndex(){
let text = $('#search-terms').val();
console.log('searching index for text:'+text);
console.log('using index with terms:'+search_index.get_term_count());
search_results = search_index.search_text(text);
console.log('results:'+search_results.length);
return search_results;
}
$('#search-button').click(function(){
console.log('search button clicked')
var el = $(this);
el.prop("disabled", true);
el.text('Searching...');
searchIndex()
.then(function(){
console.log('search results found:'+(search_results.length));
el.text('Search');
el.prop("disabled", false);
})
.catch(reason => console.log(reason.message));
});
});
</script>
</html>
If I call:
search_index.search_text('sdfssdfsf')
from the browser's console, it returns the expected 10000.
However, if I click the search button, the console.log statement prints out undefined for the value returned by search_index.search_text.
Why is this? The only thing I can think of is there's some characteristic of async I'm not aware of. Does async Javascript not have access to the same memory as the normal synchronous execution model?
You cant get length of number, return number directly or convert to string and get length
<html>
<head>
<script
src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
crossorigin="anonymous"></script>
</head>
<body>
<div id="search-form">
<input id="search-terms" type="text" placeholder="enter search terms" />
<button id="search-button">Search</button>
</div>
</body>
<script type="text/javascript">
class Index {
constructor() {
this.internal_hash = {};
}
get_term_count(){
return Object.keys(this.internal_hash).length;
}
do_big_long_expensive_calculation(){
var i=0;
for(i=0; i<10000; i++){
this.internal_hash[i] = i+1;
}
return i;
}
search_text(text){
var results = this.do_big_long_expensive_calculation();
return results;
}
};
var search_index = new Index;
var search_results = null;
$(document).ready(function(){
async function searchIndex(){
let text = $('#search-terms').val();
console.log('searching index for text:'+text);
console.log('using index with terms:'+search_index.get_term_count());
search_results = search_index.search_text(text);
console.log('results:'+search_results);
return search_results;
}
$('#search-button').click(function(){
console.log('search button clicked')
var el = $(this);
el.prop("disabled", true);
el.text('Searching...');
searchIndex()
.then(function(){
console.log('search results found:'+(search_results));
el.text('Search');
el.prop("disabled", false);
})
.catch(reason => console.log(reason.message));
});
});
</script>
</html>
I am having a JavaScript code that is having a value in #message but i have not defined anywhere.
Does $("#message").html(result); is something inbuilt in Javascript?
I apologize if it is very basic and stupid question.
It is linked to my another question "
https://stackoverflow.com/questions/41745209/save-javascript-value-when-converting-speech-to-text-via-webkitspeechrecognition#
Complete Code
<!DOCTYPE html>
<html>
<head>
<script src="Content/SpeechScript.js"></script>
<title>Login Screen</title>
<meta charset="utf-8" />
</head>
<body >
<div id="results">
<span id="final_span" class="final"></span>
<span id="interim_span" class="interim"></span>
</div>
<script type="text/javascript">
function Typer(callback) {
speak('Welcome ,Please Speak your CPR Number');
var srcText = 'WelcomeToDanske,PleaseSpeakyourCPR Numberwhat';
var i = 0;
debugger;
var result = srcText[i];
var interval = setInterval(function () {
if (i == srcText.length - 1) {
clearInterval(interval);
callback();
return;
}
i++;
result += srcText[i].replace("\n", "<br />");
$("#message").html(result);
debugger;
document.getElementById('user').innerHTML = result;
// var parent = document.getElementById('parentDiv');
// var text = document.createTextNode('the text');
// var child = document.getElementById('parent');
// child.parentNode.insertBefore(text, child);
// var div = document.getElementById('childDiv');
//var parent = document.getElementById('parentDiv');
//var sibling = document.getElementById('childDiv');
////var text = document.createTextNode('new text');
// //parent.insertBefore(result, sibling);
},
100);
return true;
}
function playBGM() {
startDictation(event);
}
Typer(function () {
playBGM();
});
// say a message
function speak(text, callback) {
var u = new SpeechSynthesisUtterance();
u.text = text;
u.lang = 'en-US';
u.onend = function () {
if (callback) {
callback();
}
};
u.onerror = function (e) {
if (callback) {
callback(e);
}
};
speechSynthesis.speak(u);
}
</script>
</div>
<div id="clockDisplay">
<span id="id1">Welcome:</span>
<table width="100%" border="1"><tr><td width="50%"> Username : </td><td><div id="message"></div></td></tr></table>
</body>
</html>
$("#message").html(result); is something inbuilt in Javascript?
No.
$ is a variable that is no part of the JavaScript spec, nor is it part of the common extensions to JS provided by browsers in webpages. It is commonly used by libraries such as PrototypeJS and jQuery. This particular case looks like jQuery, but you aren't including that library in your page.
Fist off, remember to include jQuery as script in your html document or $ will not be defined.
#message Refers to an element in your html document with the tag of id="message"
To get an element in jQuery, by id, you use this syntax: var Element = $("#ID");
So, to make sure your code works, ensure that both there is an element with the ID message, and a defined variable named result containing the html text to put into your element.
Since you want to append to <div id="clockDisplay"> <span id="user">Username :</span></div>, why not change it to:
<div id="clockDisplay">
<span id="user">Username :</span>
<div id="message"></div>
</div>
Hi I wanted to get my inscription "something" and show it on the screen every 2 seconds.
Something doesn't work. Thanks for all help :)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id = "word">something</div>
<script type="text/javascript">
var myVar = document.getElementById("word");
setInterval(function func1(){
document.write(myVar)
},2000);
func1();
</script>
</body>
</html>
Use this
var myVar = document.getElementById("word").innerHTML;
You don't need to run the function manually, setInterval will execute it every 2 seconds.
setInterval(() => {
const word = document.getElementById('word');
const output = document.getElementById('output');
output.innerHTML = word.innerHTML;
}, 2000);
<div id="word">Something</div>
<div id="output"></div>
add innerHTML to extract data from div.
You don't need to name the recurring function.
var myVar = document.getElementById("word").innerHTML;
setInterval(function(){
document.write(myVar);
// alert(myvar);
},2000);
<div id="word">test</div>
I made a simple timer in javascript using a for loop, but upon clicking the button to call the function test(), the whole page freezes up so I assume I have an infinite loop somewhere
This is my code:
<html>
<head>
<script>
function test() {
var HowLong = 5;
for (var i=0;i<HowLong;i--) {
document.write(HowLong[i] + "<br>");
}
}
</script>
</head>
<body>
<input type="button" onclick="test()" value="Start Timer">
</body>
</html>
Yes you have infinite loop problem in the for loop:
for (var i=0;i<HowLong;i--)
Instead of i-- try i++
for (var i=0;i<HowLong;i++)
One more thing HowLong is not an array so you can't use HowLong[i], just simply use :
document.write(i+ "<br>");
As #jfriend00 has mentioned in comments When you use document.write() after the document is loaded, it will clear the current document and start a new one. In your case your button Start Timer will be cleared. If you want to avoid it you can use div and add value to it.
<html>
<head>
<script>
function test() {
var HowLong = 5;
for(var i=0;i<HowLong;i++) {
document.getElementById("myDiv").innerHTML += i + "<br>";
}
}
</script>
</head>
<body>
<input type="button" onclick="test()" value="Start Timer">
<div id="myDiv"></div>
</body>
</html>
Try this;
for (var i=0;i<HowLong;i++) {
document.write(i + "<br>");
}
<html>
<head>
<script>
var HowLong = 5;
var isRun = false;
function mf(i){
document.getElementById('myAnchor').innerHTML = i;
}
function rt(i)
{
setTimeout(function(){
mf(i++);
if(i!=HowLong+1)rt(i);
else isRun = false;
}, 1000); // 1000ms = 1sec
}
function test() {
var i = 1;
if(!isRun)
{
isRun = true;
rt(i);
}
}
</script>
</head>
<body>
<div id="myAnchor"></div>
<input type="button" onclick="test()" value="Start Timer">
</body>
</html>
you forget to add delay in your loop
I have been making simple Javascript programs that I will run with different websites for my friends, and I have been trying to make a domination style (call of duty gamemode) program using buttons. I have looked at a website and have tried using the set intervals for it but I can't figure out how to make the buttons access the script.
Here is my code:
<!DOCTYPE html>
<html>
<body>
<p id = "blue"></p>
<p id = "red"></p>
<button onclick="StartA()">Start for Red</button>
<button onclick="StopA()">Stop for red</button>
<button onclick="StartB()">Start for Blue</button>
<button onclick="StopB()">Stop for Blue</button>
<script>
var startRed;
var startBlue;
var r=1;
var b=1;
var startA = function(){
var startRed = setInterval(function(){redscore++};,3000)
};
var startB = function(){
var startBlue = setInterval(function(){bluescore++};,3000)
};
var StopA = function(){
clearInterval(startRed);
};
var StopB = function() {
clearInterval(startBlue);
};
document.getElementById("blue").innerHTML=bluescore;
document.getElementById("red").innerHTML=redscore;
</script>
</body>
</html>
JavaScript is case sensitive. You are not consistent with case. Traditionally, JavaScript functions and variables start with a lower case letter and are camel cased.
You were reinitializing variables in functions that were already initialized in the global scope.
You weren't updating the ui with each score change, just at the start.
Below is updated code that should run as you intend. It might be worth while to turn your score keepers into a class, since they are redundant.
Updated Html
<p id="blue"></p>
<p id="red"></p>
<button onclick="startA()">Start for Red</button>
<button onclick="stopA()">Stop for red</button>
<button onclick="startB()">Start for Blue</button>
<button onclick="stopB()">Stop for Blue</button>
Updated javaScript
var startRed;
var startBlue;
var bluescore = 1;
var redscore = 1;
function startA() {
stopA();
startRed = setInterval(function () {
redscore++;
updateUI();
}, 3000)
};
function startB() {
stopB();
startBlue = setInterval(function () {
bluescore++;
updateUI();
}, 3000)
};
function stopA() {
clearInterval(startRed);
};
function stopB() {
clearInterval(startBlue);
};
function updateUI() {
document.getElementById("blue").innerHTML = bluescore;
document.getElementById("red").innerHTML = redscore;
}
updateUI();
jsFiddle
The following code is what you're looking for. The changes are:
Function names now match (startA() => StartA(), startB() => StartB(), etc.)
The <p> elements are updated within the interval (otherwise, they never update)
Remove local vars from within functions
You can view a jsfiddle here: http://jsfiddle.net/5tcNb/
<body>
<script>
var startRed, startBlue;
var redscore = 0, bluescore = 0;
var r = 1, b = 1;
function StartA() {
startRed = setInterval(function() {
redscore++;
document.getElementById("red").innerHTML = redscore;
}, 3000);
};
function StartB() {
startBlue = setInterval(function() {
bluescore++;
document.getElementById("blue").innerHTML = bluescore;
}, 3000);
};
function StopA() {
clearInterval(startRed);
};
function StopB() {
clearInterval(startBlue);
};
</script>
<p id="blue">0</p>
<p id="red">0</p>
<button onclick="StartA()">Start for Red</button>
<button onclick="StopA()">Stop for red</button>
<button onclick="StartB()">Start for Blue</button>
<button onclick="StopB()">Stop for Blue</button>
</body>