I want to print a lot of numbers ONE-BY-ONE with AJAX.
something like this: (each new line is update of previous line!)
output is:
1
12
123
1234
12345
123456
...
I tried a lot and read a lot of this same problem, but i couldn't find my right Answer.
The real problem is every FOR LOOP in javascript will NO affect the DOM after it will END the loop. I just want update the DOM inside the FOR LOOP while working on a long running job.
Please look at my code.
$("#btn").on("click", dowork);
function dowork() {
document.getElementById("foo").innerHTML = "working";
setTimeout(function() {
var counter = 100; // i want assign counter = 2000000000
for (var i = 0; i < counter; i++) {
document.getElementById("print_here").innerHTML += i;
}
document.getElementById("foo").innerHTML = "done!";
}, 50);
}
#btn {
background: #1f1f1f;
padding: 10px;
font-weight: bolder;
color: #fff;
width: 50%;
margin: auto;
margin-top: 10px;
text-align: center;
cursor: pointer;
}
#print_here {
overflow-wrap: break-word;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="btn">CLICK TO DO WORK</div>
<div id="foo"></div>
<div id="print_here"></div>
Thanks for any answer and help to solve this problem.
Your DOM is "locked" while it is being updated and redrawn ones the loop is done. You can free up the resource to let the DOM update each time wrapping your DOM change in a setTimeout, similar to:
setTimeout(function(){
document.getElementById("print_here").innerHTML += i;
},1);
To ensure setTimeout uses the correct value for i use let i instead of var i
$("#btn").on("click", dowork);
function dowork() {
document.getElementById("foo").innerHTML = "working";
var counter = 3000; // i want assign counter = 2000000000
for (let i = 0; i < counter; i++) {
setTimeout(function() {
document.getElementById("print_here").innerHTML += i;
}, 1);
}
document.getElementById("foo").innerHTML = "done!";
}
#btn {
background: #1f1f1f;
padding: 10px;
font-weight: bolder;
color: #fff;
width: 50%;
margin: auto;
margin-top: 10px;
text-align: center;
cursor: pointer;
}
#print_here {
overflow-wrap: break-word;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="btn">CLICK TO DO WORK</div>
<div id="foo"></div>
<div id="print_here"></div>
I want change the #foo into "done!" after the FOR statement is END
You could check if you are at your last item you process within the setTimeout, similar to:
if (i == counter - 1){
document.getElementById("foo").innerHTML = "done!";
}
$("#btn").on("click", dowork);
function dowork() {
document.getElementById("foo").innerHTML = "working";
var counter = 3000; // i want assign counter = 2000000000
for (let i = 0; i < counter; i++) {
setTimeout(function() {
document.getElementById("print_here").innerHTML += i;
if (i == counter - 1){
document.getElementById("foo").innerHTML = "done!";
}
}, 1);
}
}
#btn {
background: #1f1f1f;
padding: 10px;
font-weight: bolder;
color: #fff;
width: 50%;
margin: auto;
margin-top: 10px;
text-align: center;
cursor: pointer;
}
#print_here {
overflow-wrap: break-word;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="btn">CLICK TO DO WORK</div>
<div id="foo"></div>
<div id="print_here"></div>
You need to let the call stack complete so the browser can do its work on the page. If you bog down the one main thread, page updates aren't going to occur.
One way to do this is use setImmediate or nextTick. This is non-standard, so check this polyfill: https://www.npmjs.com/package/browser-next-tick
Basically, you do an iteration, then tell the browser to do the next iteration as soon as possible... and this occurs on a fresh call stack.
Here is the working code for you:
$("#btn").on("click", dowork);
function dowork() {
document.getElementById("foo").innerHTML = "working";
setTimeout(function() {
var i, j, row = 5;
var html = "";
for (i = 1; i <= row; i++) {
for (j = 1; j <= i; j++) {
html += "<span>" + j + "</span>";
}
html += "</br>";
}
console.log(html);
document.getElementById("print_here").innerHTML = html;
}, 50);
}
#btn {
background: #1f1f1f;
padding: 10px;
font-weight: bolder;
color: #fff;
width: 50%;
margin: auto;
margin-top: 10px;
text-align: center;
cursor: pointer;
}
#print_here {
overflow-wrap: break-word;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="btn">CLICK TO DO WORK</div>
<div id="foo"></div>
<div id="print_here"></div>
Rows is the number of rows you want to print.
Related
I want this to run but so that it doesn't for 5 seconds after the page fully loads. How would I go about achieving this, I believe its a ,500 somewhere but I am not sure where this would go.
If you have any questions please ask!
Thank you in advance for you help on this matter, its very much appreciated!
$(".demoBookedContentClose").click(function(){
$("body").addClass("demoBookedHidden");
});
function shuffle(array) {
var currentIndex = array.length,
temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
var queue = [];
function setUp() {
var elems = $(".demoBooked").get();
queue = shuffle(elems);
showNext();
}
function showNext() {
var elem = queue.pop();
if (elem) {
$(elem)
.fadeIn(2000)
.delay(5000)
.fadeOut(1000, function(){ setTimeout(showNext,25000); });
} else {
setUp();
}
}
setUp();
.demoBooked {
background: #fff;
box-shadow: 0 1px 2px rgba(0,0,0,0.05), 0 2px 4px rgba(0,0,0,0.08);
border: 1px solid #dddddd;
padding: 20px;
border-radius: 8px;
display: none;
}
.demo-booked-section {
position: fixed;
bottom: 10px;
left: 10px;
z-index: 2;
}
.demoBooked h3 {
font-size: 22px;
font-weight: 900;
margin-bottom: 4px;
}
.demoBooked img {
max-width: 50px;
margin-top: -55px;
border-radius: 100%;
display: inline-block;
}
.demoBookedContent {
display: inline-block;
padding-left: 20px;
}
.demoBooked p {
font-size: 18px;
line-height: 20px;
}
.demoBookedTime {
color: #e12826;
}
.demoBookedContentClose {
position: absolute;
right: 15px;
top: 10px;
font-size: 10px;
cursor: pointer;
}
.demoBookedHidden .demo-booked-section {
display: none!important;
}
.demoBookedTime {
font-size: 15px;
}
#media only screen and (max-width: 768px) {
.demo-booked-section {
display: none!important;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="demo-booked-section">
<div class="demoBooked">
<img src="/wp-content/uploads/2021/01/william-diaz.jpg">
<div class="demoBookedContent">
<span class="demoBookedContentClose">X</span>
<h3>William Diaz</h3>
<p class="demoBookedText">Just started a FREE trial</p>
<p class="demoBookedTime">1hrs ago</p>
</div>
</div>
<div class="demoBooked">
<img src="/wp-content/uploads/2021/01/freya-smith.jpg">
<div class="demoBookedContent">
<span class="demoBookedContentClose">X</span>
<h3>Freya Smith</h3>
<p class="demoBookedText">Just started a FREE trial</p>
<p class="demoBookedTime">3hrs ago</p>
</div>
</div>
</div>
You can delay your function 5 seconds (5000 ms) with an 'setTimeout' functions after your web load:
<script>
window.onload = function() {
setTimeout(function(){
//Your function here
},5000);
}
</script>
Since you want the function to be fired up 5 seconds after the page is fully loaded you will be using a combination of two functions.
I see you are using jQuery in your website
The below code waits until the page is fully loaded then fires up the code inside the brackets.
$( document ).ready(function() {
// code here
});
So inside the above code you will add your 5 seconds waiting function
setTimeout(function(){
// Magic happens here
},5000);
The final code is
$( document ).ready(function() {
setTimeout(function(){
// Magic happens here
},5000);
});
You can use setTimeout which will wait the specified number of milliseconds before running whatever is between the curly braces (in this case I put your setUp function there because I assume that's what you meant by your question).
Because you want the function to run 5 seconds after the page is fully loaded you need to surround the code in a call to window.onload which will make sure that setTimeout only runs once the page has been fully loaded.
window.onload = function() {
setTimeout(function() { setUp(); }, 5000);
}
I'm trying to make a count down so that every 20 sec an alert pops up. I want it to go from 20 to 0 to 20 over and over. I have it working, but it only works once. The rage function dosen't need to be changed, it's the msg function i'm having trouble with. Here's my code.
function rage() {
var i = document.getElementsByName("msg")[6];
var message = document.getElementById("message");
const affichemsg = document.querySelector("msg");
for (i = 0; i < 1; i++) {
message.innerHTML += "Es-tu près ";
}
}
setInterval(rage, 350);
var decompteur = setInterval(msg, 1000);
var temps;
function msg() {
var idTemps = document.getElementById("temps");
temps = parseInt(idTemps.innerHTML);
temps = temps - 1;
idTemps.innerHTML = temps;
if (--temps <= 0) {
alert("!!!!!ES-TU PRÈS!!!!!");
clearInterval(temps);
msg();
idTemps = 20;
var decompteur = setInterval(msg, 1000);
}
}
.titre2 {
width: 650px;
margin: auto;
text-align: center;
border-radius: 35px;
color: #000000;
background-color: #ff0000;
padding: 5px;
margin-bottom: 30px;
}
.bouton {
transition-duration: 0.4s;
border-width: 1px;
cursor: pointer;
}
.boutonOui {
background-color: rgb(234, 234, 234);
}
.boutonOui:hover {
background-color: rgb(177, 177, 177);
}
<div class="header">
<h1 class="titre2">Es-tu près</h1>
</div>
<button
class="bouton boutonOui"
id="boutonOui"
onclick="window.location.href='jeu_educatifs2.html'"
>
Oui
</button>
<div id="temps">20</div>
<div id="message"></div>
<div id="msg" value="6"></div>
the first problem here is that you don't use correctly the method clearInterval. It takes as argument the id of the "timer" created with setInterval. setInterval return directly the id so actually stored it in your variable decompteur and you should use something like that to clear the timer : clearInterval(decompteur).
Also be sure to reset the idTemps with idTemps.innerHTML = 20. Then I don't really understand... Why would you clear the interval then rebuild the same again when you can just set the idTemps.innerHTML so your interval will use the 20 for temps at the next iteration ?
PS: ça fait plaisir de voir un peu de français sur stack :)
You should rewrite your code this way :
function rage() {
var i = document.getElementsByName("msg")[6];
var message = document.getElementById("message");
const affichemsg = document.querySelector("msg");
for (i = 0; i < 1; i++) {
message.innerHTML += "Es-tu près ";
}
}
setInterval(rage, 350);
var decompteur = setInterval(msg, 1000);
function msg() {
var idTemps = document.getElementById("temps");
var temps = parseInt(idTemps.innerHTML) - 1;
idTemps.innerHTML = temps;
if (--temps == 0) {
alert("!!!!!ES-TU PRÈS!!!!!");
idTemps.innerHTML = "20";
}
}
// when you need to, stop decompteur with :
// clearInterval(decompteur);
.titre2 {
width: 650px;
margin: auto;
text-align: center;
border-radius: 35px;
color: #000000;
background-color: #ff0000;
padding: 5px;
margin-bottom: 30px;
}
.bouton {
transition-duration: 0.4s;
border-width: 1px;
cursor: pointer;
}
.boutonOui {
background-color: rgb(234, 234, 234);
}
.boutonOui:hover {
background-color: rgb(177, 177, 177);
}
<div class="header">
<h1 class="titre2">Es-tu près</h1>
</div>
<button class="bouton boutonOui" id="boutonOui" onclick="window.location.href='jeu_educatifs2.html'">
Oui
</button>
<div id="temps">20</div>
<div id="message"></div>
<div id="msg" value="6"></div>
This keep as much of your code as possible, but as Rojo said, your code is very inefficent and there are a lot of things to improve.
Currently, your code is very inefficient. Rather than having your variable temps read from the DOM, you should have the variable update itself:
var temps = 20;
function msg() {
--temps;
}
setInterval(msg, 1000);
Second, you shouldn't be including var inside of that if statement:
if (countdown === 0) {
alert("!!!!!ES-TU PRÈS!!!!!");
clearInterval(decompteur);
// msg(); // You don't need this
temps = 20;
decompteur = setInterval(msg, 1000); // I removed the var
}
Also, you had your variables mixed up (which I fixed)
function rage() {
var i = document.getElementsByName("msg")[6];
var message = document.getElementById("message");
const affichemsg = document.querySelector("msg");
for (i = 0; i < 1; i++) {
message.innerHTML += "Es-tu près ";
}
}
setInterval(rage, 350);
var decompteur = setInterval(msg, 1000);
var temps = 20;
var idTemps = document.getElementById("temps"); // I also moved this outside
function msg() {
--temps;
idTemps.innerHTML = temps;
if (temps === 0) {
alert("!!!!!ES-TU PRÈS!!!!!");
clearInterval(decompteur);
//msg(); //You don't need this
temps = 20;
decompteur = setInterval(msg, 1000);
}
}
.titre2 {
width: 650px;
margin: auto;
text-align: center;
border-radius: 35px;
color: #000000;
background-color: #ff0000;
padding: 5px;
margin-bottom: 30px;
}
.bouton {
transition-duration: 0.4s;
border-width: 1px;
cursor: pointer;
}
.boutonOui {
background-color: rgb(234, 234, 234);
}
.boutonOui:hover {
background-color: rgb(177, 177, 177);
}
<div class="header">
<h1 class="titre2">Es-tu près</h1>
</div>
<button
class="bouton boutonOui"
id="boutonOui"
onclick="window.location.href='jeu_educatifs2.html'"
>
Oui
</button>
<div id="temps">20</div>
<div id="message"></div>
<div id="msg" value="6"></div>
The following code prints the counter value each second and every 20 seconds it prints ALERT. Try to use a similar code for your example because your code is not very clear.
let counter = 0;
setInterval(() => {
counter++;
if (counter % 20 == 0) {
console.log("ALERT! ");
}
console.log("Counter Value: " + (counter % 20));
}, 1000);
I'm using some code I found at Change url when manually scrolled to an id even scrolling to top?.
It works as intended, but Chrome's Console is giving me an error message, "Uncaught TypeError: Cannot read property 'top' of undefined", for the line:
var currentElementTop = $(blocksArr[i]).offset().top;
I'd like to get rid of this error, so what do I need to change/add?
(BTW, I would post this question as a comment on the original post, but for some reason I need a reputation of 50...?)
Here's the code in action:
$(function () {
var currentHash = "#";
var blocksArr = $('.anchor');
$(document).scroll(function () {
var currentTop = window.pageYOffset/1;
for (var i=0; blocksArr.length; i++){
var currentElementTop = $(blocksArr[i]).offset().top;
var hash = $(blocksArr[i]).attr('id');
if (currentElementTop < currentTop && currentTop < currentElementTop + $(blocksArr[i]).height() && currentHash!=hash){
if(history.pushState) {
history.pushState(null, null, '#'+hash);
}
else {
location.hash = '#'+hash;
}
currentHash = hash;
}
}
});
});
html, body {
height: 100%;
min-height: 100%;
font-size: 100%;
text-shadow:none;
margin: 0;
}
div {
min-height: 100%;
font-size: 100px;
padding: 25px 50px;
}
.hero {
line-height: 30vh;
padding: 35vh 10vh;
max-height: 100vh;
min-height: auto;
text-align: center;
}
.red {
background: orangered;
color: white;
}
.white {
background: ghostwhite;
color: black;
}
.blue {
background: blue;
color: white;
}
<div id="Hero" class="anchor red hero">Hero</div>
<div id="About" class="anchor white">About</div>
<div id="What" class="anchor blue">What</div>
<div id="Why" class="anchor white">Why</div>
<div id="Contact" class="anchor red">Contact</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Your for statement is wrong.
for (var i=0; blocksArr.length; i++){
So if you loop makes it to the end of the array it keeps going and it will not have an element. So when you get to i = blocksArr.length, that is when the error occurs. jQuery is doing $(undefined).offset().top and you get the error.
for (var i=0; i < blocksArr.length; i++){
You could try use each:
$('.anchor').each((index, obj) => {
var currentElementTop = $(obj).offset().top;
var hash = $(obj).attr('id');
if (currentElementTop < currentTop && currentTop < currentElementTop + $(obj).height() && currentHash!=hash){
if(history.pushState) {
history.pushState(null, null, '#'+hash);
} else {
location.hash = '#'+hash;
}
currentHash = hash
}
});
This line:
for (var i=0; blocksArr.length; i++){
should be
for (var i=0; i<blocksArr.length; i++){
You're looping from 0 until truthy (blocksArr.length == true) - which it always is. You don't get an infinite loop because it crashes out on
blocksArr[blocksArr.length]
(as array's are 0 based, this should stop at blocksArr[blocksArr.length-1])
If you were to catch/ignore this, your code would get stuck in an infinite loop.
$(function () {
var currentHash = "#";
var blocksArr = $('.anchor');
$(document).scroll(function () {
var currentTop = window.pageYOffset/1;
for (var i=0; i<blocksArr.length; i++){
var currentElementTop = $(blocksArr[i]).offset().top;
var hash = $(blocksArr[i]).attr('id');
if (currentElementTop < currentTop && currentTop < currentElementTop + $(blocksArr[i]).height() && currentHash!=hash){
if(history.pushState) {
history.pushState(null, null, '#'+hash);
}
else {
location.hash = '#'+hash;
}
currentHash = hash;
}
}
});
});
html, body {
height: 100%;
min-height: 100%;
font-size: 100%;
text-shadow:none;
margin: 0;
}
div {
min-height: 100%;
font-size: 100px;
padding: 25px 50px;
}
.hero {
line-height: 30vh;
padding: 35vh 10vh;
max-height: 100vh;
min-height: auto;
text-align: center;
}
.red {
background: orangered;
color: white;
}
.white {
background: ghostwhite;
color: black;
}
.blue {
background: blue;
color: white;
}
<div id="Hero" class="anchor red hero">Hero</div>
<div id="About" class="anchor white">About</div>
<div id="What" class="anchor blue">What</div>
<div id="Why" class="anchor white">Why</div>
<div id="Contact" class="anchor red">Contact</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
You might want to wrap the offending line in a try-catch block. If you are breaking on the error (which it doesn't sound like you are), this will prevent that. Otherwise, this might give you a little bit more detail on what the error is.
Something along these lines:
try {
var currentElementTop = $(blocksArr[i]).offset().top;
}
catch(err) {
console.log(err.message);
}
I don't know how to describe this without making it more complicated.
So look at the result of the code and click on the first link with "Show", then the second one and third one.
When the second link is clicked, first one closes but text remains "Hide" and i want it to change to "Show".
So, when clicking a link, detect if any other link has text "Hide" and change it to "Show".
And please no jQuery...
document.getElementsByClassName("show")[0].onclick = function() {
var x = document.getElementsByClassName("hide")[0];
var y = document.getElementsByClassName("show")[0];
if (x.classList.contains("visible")) {
x.classList.remove("visible");
y.textContent = "Show";
} else {
closeOther();
x.classList.add("visible");
y.textContent = "Hide";
}
};
document.getElementsByClassName("show")[1].onclick = function() {
var x = document.getElementsByClassName("hide")[1];
var y = document.getElementsByClassName("show")[1];
if (x.classList.contains("visible")) {
x.classList.remove("visible");
y.textContent = "Show";
} else {
closeOther();
x.classList.add("visible");
y.textContent = "Hide";
}
};
document.getElementsByClassName("show")[2].onclick = function() {
var x = document.getElementsByClassName("hide")[2];
var y = document.getElementsByClassName("show")[2];
if (x.classList.contains("visible")) {
x.classList.remove("visible");
y.textContent = "Show";
} else {
closeOther();
x.classList.add("visible");
y.textContent = "Hide";
}
};
function closeOther() {
var visible = document.querySelectorAll(".visible"),
i, l = visible.length;
for (i = 0; i < l; ++i) {
visible[i].classList.remove("visible");
}
}
.style {
background-color: yellow;
width: 200px;
height: 200px;
display: inline-block;
}
.hide {
background-color: red;
width: 50px;
height: 50px;
display: none;
position: relative;
top: 50px;
left: 50px;
}
.hide.visible {
display: block;
}
<div class="style">
Show
<div class="hide">
</div>
</div>
<div class="style">
Show
<div class="hide">
</div>
</div>
<div class="style">
Show
<div class="hide">
</div>
</div>
I tried to write a solution which didn't use any javascript at all and worked using CSS alone. I couldn't get it to work though - CSS can identify focus but it can't identify blur (ie. when focus has just been removed).
So here is a solution which uses javascript and the classList API, instead:
var divs = document.getElementsByTagName('div');
function toggleFocus() {
for (var i = 0; i < divs.length; i++) {
if (divs[i] === this) continue;
divs[i].classList.add('show');
divs[i].classList.remove('hide');
}
this.classList.toggle('show');
this.classList.toggle('hide');
}
for (let i = 0; i < divs.length; i++) {
divs[i].addEventListener('click', toggleFocus, false);
}
div {
display: inline-block;
position: relative;
width: 140px;
height: 140px;
background-color: rgb(255,255,0);
}
.show::before {
content: 'show';
}
.hide::before {
content: 'hide';
}
div::before {
color: rgb(0,0,255);
text-decoration: underline;
cursor: pointer;
}
.hide::after {
content: '';
position: absolute;
top: 40px;
left: 40px;
width: 50px;
height: 50px;
background-color: rgb(255,0,0);
}
<div class="show"></div>
<div class="show"></div>
<div class="show"></div>
Like this?
Just added following to closeOther():
visible = document.querySelectorAll(".show"),
i, l = visible.length;
for (i = 0; i < l; ++i) {
visible[i].textContent="Show";
}
I am trying to add automoving with pagination for table in HTML.
For eg i have table with 100 rows and then i am doing pagination for it with 10 records on one page.So there will be 10 pages with 10 records each.
I nedd to do it automatically so that user dont have to specifically click on the page and see.
I used paging.js
with below code
<style type="text/css">
.paging-nav {
text-align: right;
padding-top: 2px;
}
.paging-nav a {
margin: auto 1px;
text-decoration: none;
display: inline-block;
padding: 1px 7px;
background: #91b9e6;
color: white;
border-radius: 3px;
}
.paging-nav .selected-page {
background: #187ed5;
font-weight: bold;
}
.paging-nav,
#tableData {
'width: 400px;
margin: 0 auto;
font-family: Arial, sans-serif;
}
</style>
$(document).ready(function() {
$('#file').paging({limit:10});
});
Here file is id of table which is to be paginated. How can i go about changing page of table automatically? All answers are welcome.
Here is an example for how to start with it..
beware this is just an example, do not copy! for your own protection
//create
el = $("<table></table>");
for (var i = 1; i !== 100; i++) {
el.append("<tr><td>" + i + "</td><td>buuurp</td></tr>");
}
el.data("intStart", 1);
el.appendTo("body");
//fuction
function showRow(j = 10) { //default var j = 10; you can call showRow(50) for 50 as example
var i = $("table").data().intStart; //grabs data that hold the number of currect first element to view
$("tr").hide();
// hides all
$("tr").filter(function(index) {
return index >= i - 1 && index < i + j - 1; //jquery has 0-9 we count in 1-10 so -1
}).show(); //shows the one needed
$("table").data().intStart += j; //addes 'j' to the counter
if ($("table").data().intStart > $("table").children("tr").lenght) {
clearInterval(timer); //if we reach the end we can kill this
}
}
showRow();
var timer = setInterval(function() {
showRow();
}, 3000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>