user1413341
user1413341

Reputation: 226

How do I update the html displayed for each iteration of a for loop in javascript / jquery?

How would I have the h1 change for each iteration of the loop? This code now only displays the h1 text after everything is done.

for (i=0; i<array.length; i++) {
  $("body > h1").text("Processing #" + i);
  // things that take a while to do
}

Additional info: if I resize the window as it loops, the html updates.

Upvotes: 5

Views: 9437

Answers (5)

cocco
cocco

Reputation: 16706

if the process is very long you can use this script which shows every notification for a specific time interval.

here is the code..

html

<div id="ccNotificationBox"></div>

css

#ccNotificationBox{
 -webkit-animation-name:;
 -webkit-animation-duration:2s;/*Notification duration*/
 box-sizing:border-box;
 border-radius:16px;
 padding:16px;
 background-color:rgba(0,0,0,0.7);
 top:-100%;
 right:16px;
 position:fixed;
 color:#fff;
}
#ccNotificationBox.active{
 -webkit-animation-name:note;
 top:16px;
}
@-webkit-keyframes note{
0%   {opacity:0;}
20%  {opacity:1;}
80%  {opacity:1;}
100% {opacity:0;}
}

javascript

var coccoNotification=(function(){
var
nA=[],
nB,
rdy=true;
function nP(a){
 nA.push(a);
 !rdy||(nR(),rdy=false);
}
function nR(){
 nB.innerHTML=nA[0];console.log(nA[0]);
 nB.offsetWidth=nB.offsetWidth;//reflow ios
 nB.classList.add('active');
}
function nC(){
 nB.classList.remove('active');
 nB.innerHTML='';
 nA.shift();
 nA.length>0?nR():(rdy=true);
}
function init(){
 nB=document.getElementById('ccNotificationBox');
 nB.addEventListener('webkitAnimationEnd',nC,false);
 window.removeEventListener('load',init,false);
}
window.addEventListener('load',init,false);
return nP
})();

usage

coccoNotification('notification 1');

example

http://jsfiddle.net/f6dkE/1/

info

the example above is perfect for external js as you use just one global variable which is the name of the function ... in my case coccoNotification

here is a different approach but it does the same

http://jsfiddle.net/ZXL4q/11/

Upvotes: 0

Kaizen Programmer
Kaizen Programmer

Reputation: 3818

DEMO

I've spent a bit of time working out a jquery function that seems to solve this. Basically, it's a process handler that you can add any number of processes to and then call run to sequentially call these in a asynchronous way.

$.fn.LongProcess = function () {
    var _this = this;
    this.notifications = [];
    this.actions = [];

    this.add = function (_notification, _action) {
        this.notifications.push(_notification);
        this.actions.push(_action);
    };
    this.run = function () {

        if (!_this.actions && !_this.notifications) {
            return "Empty";
        }
        //******************************************************************
        //This section makes the actions lag one step behind the notifications.
        var notification = null;
        if (_this.notifications.length > 0) notification = _this.notifications.shift();

        var action = null;
        if ((_this.actions.length >= _this.notifications.length + 2) || (_this.actions.length > 0 && _this.notifications.length == 0)) 
            action = _this.actions.shift();
        //****************************************************************
        if (!action && !notification) {
            return "Completed";
        }

        if (action) action();        
        if (notification) notification();

        setTimeout(_this.run, 1000); 
        //setTimeout(_this.run,1); //set to 1 after you've entered your actual long running process. The 1000 is there to just show the delay.
    }
    return this;
};

How to use with <h1 class="processStatus"></h1>:

$(function () {
    var process = $().LongProcess();

    //process.add(notification function, action function);
    process.add(function () {
        $(".processStatus").text("process1");
    }, function () {
        //..long process stuff
        alert("long process 1");
    });

    process.add(function () {
        $(".processStatus").text("process2");
    }, function () {
        //..long process stuff
        alert("long process 2");
    });

    process.add(function () {
        $(".processStatus").text("process3");
    }, function () {
        //..long process stuff
        alert("long process 3");
    });

    process.run();
});

Upvotes: 0

James Daly
James Daly

Reputation: 1406

var array = ['one', 'two', 'three']
var i = 0;

var refreshIntervalId = setInterval(function() {
    length = array.length;
    if (i < (array.length +1)) {
        $("h1").text("Processing #" + i);
    } else {
        clearInterval(refreshIntervalId);
    }
    i++     
}, 1000);

http://jsfiddle.net/3fj9E/

Upvotes: 7

Brandon
Brandon

Reputation: 39212

Sometimes you can force a render by forcing a recalculation of layout

for (i=0; i<array.length; i++) {
  $("body > h1").text("Processing #" + i)
      .width();  // force browser to recalculate layout
  // things that take a while to do
}

It might not work in all browsers.

A better way, that does not block the browser so much:

function doThings(array) {
   var queueWork,
       i = -1,
       work = function () {
          // do work for array[i]
          // ...
          queueWork();
       };

   queueWork = function () {
       if (++i < array.length) {
          $("body > h1").text("Processing #" + i);
          setTimeout(work, 0); // yield to browser
       }
   };
}


doThings(yourArray);

Upvotes: 1

Blazemonger
Blazemonger

Reputation: 92983

Use a setInterval with a one-millisecond delay:

var i=0, j=array.length;
var iv = setInterval(function() {
    $("h1").text("Processing #" + i);
    // things that take a while to do
    if (++i>=j) clearInterval(iv);
}, 1);

http://jsfiddle.net/mblase75/sP9p7/

Upvotes: 4

Related Questions