te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>Javascript: How to update a progress bar in a 'for' loop - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript: How to update a progress bar in a 'for' loop - Stack Overflow

programmeradmin3浏览0评论

I am have an issue with a JS script I am trying to put together. I have an HTML table with somewhere in the neighborhood of 300 rows in it. I have made a sort function that will make the table headers clickable and launch my sort function. I would like to integrate a progress bar because in larger tables (500 - 1000 rows) after a header is clicked the table takes a bit of time to sort (IE is a big offender). The progress bar would tell them how much time remains before the sort is plete. The method I had in mind was a div element that I would resize based on the progression of the sort loop. The problem is that I can't seem to figure out how to integrate such a routine into my loop.

I've researched the issue and taken note of this: How to change progress bar in loop? and this: Using setTimeout to update progress bar when looping over multiple variables

The second topic has a few demos that do essentially what I would like to do as far as the progress bar goes. However, anytime I try to implement the solutions shown in those two posts I either:

A - Crash the browser

B - Progress bar appears to work, but goes from 0 - 100% instantly, not progressively.

I am hoping someone can lead me in the right direction on what to do. This table sort progress indicator must be done using native JS because the contents must be available offline, hence I can't include any jQuery libraries via CDN and bloating the document with the entire jQuery library isn't desired.

I've created a JS fiddle with my code in it. I've stripped out what I had for progress bar code because I kept crashing the browser so all that is there as far as scripts go is the sorting-related code. jsfiddle

Here is the JS itself:

//Change this variable to match the "id" attribute of the
//table that is going to be operated on.
var tableID = "sortable";

/**
 * Attach click events to all the <th> elements in a table to 
 * call the tableSort() function. This function assumes that cells  
 * in the first row in a table are <th> headers tags and that cells
 * in the remaining rows are <td> data tags.
 *
 * @param table The table element to work with.
 * @return void
 */
function initHeaders(table) {
    //Get the table element
    table = document.getElementById(table);
    //Get the number of cells in the header row
    var l = table.rows[0].cells.length;
    //Loop through the header cells and attach the events
    for(var i = 0; i < l; i++) {
        if(table.rows[0].cells[i].addEventListener) { //For modern browsers
            table.rows[0].cells[i].addEventListener("click", tableSort, false);
        } else if(table.rows[0].cells[i].attachEvent) { //IE specific method
            table.rows[0].cells[i].attachEvent("onclick", tableSort);
        }
    }
}

/**
 * Compares values in a column of a table and then sorts the table rows.
 * Subsequent calls to this function will toggle a row between ascending
 * and descending sort directions.
 *
 * @param e The click event passed in from the browser.
 * @return mixed No return value if operation pletes successfully, FALSE on error.
 */
function tableSort(e) { 

    /**
     * Checks to see if a value is numeric.
     *
     * @param n The ining value to check.
     * @return bool TRUE if value is numeric, FALSE otherwise.
     */
    tableSort.isNumeric = function (n) {
        var num = false;
        if(!isNaN(n) && isFinite(n)) {
            num = true;
        }
        return num;
    }

    //Get the element from the click event that was passed.
    if(e.currentTarget) { //For modern browsers
        e = e.currentTarget;
    } else if(window.event.srcElement) { //IE specific method
        e = window.event.srcElement;
    } else {
        console.log("Unable to determine source event. Terminating....");
        return false;
    }

    //Get the index of the cell, will be needed later
    var ndx = e.cellIndex;

    //Toggle between "asc" and "desc" depending on element's id attribute
    if(e.id == "asc") {
        e.id = "desc";
    } else {
        e.id = "asc";
    }

    //Move up from the <th> that was clicked and find the parent table element.
    var parent = e.parentElement;
    var s = parent.tagName;
    while(s.toLowerCase() != "table") {
        parent = parent.parentElement;
        s = parent.tagName;
    }

    /*
    Executes two different loops.  A "for" loop to control how many
    times the table rows are passed looking for values to sort and a
    "while" loop that does the actual paring of values.  The "for"
    loop also controls how many times the embedded "while" loop will
    run since each iteration with force at least one table row into 
    the correct position.   
    */

    //var interval = setInterval( function () { progress.updateProgress() } , 100);
    var rows = parent.tBodies[0].rows.length; //Isolate and count rows only in the <tbody> element.
    if(rows > 1) {  //Make sure there are enough rows to bother with sorting
        var v1; //Value 1 placeholder
        var v2; //Value 2 placeholder
        var tbody = parent.tBodies[0];  //Table body to manipulate
        //Start the for loop (controls amount of table passes)
        for(i = 0; i < rows; i++) {
            var j = 0;  //Counter for swapping routine
            var offset = rows - i - 1;  //Stops next loop from overchecking

            // WANT TO UPDATE PROGRESS BAR HERE

            //Start the while loop (controls number of parisons to make)
            while(j < offset) {             

                //Check to make sure values can be extracted before proceeding
                if(typeof tbody.rows[j].cells[ndx].innerHTML !== undefined && typeof tbody.rows[j + 1].cells[ndx].innerHTML !== undefined) {

                    //Get cell values and pare
                    v1 = tbody.rows[j].cells[ndx].innerHTML;
                    v2 = tbody.rows[j + 1].cells[ndx].innerHTML;
                    if(tableSort.isNumeric(v1) && tableSort.isNumeric(v2)) {
                        //Dealing with two numbers
                        v1 = new Number(v1);
                        v2 = new Number(v2);
                        if(v1 > v2) {
                            if(e.id == "asc") { //v1 moves down
                                tbody.insertBefore(tbody.rows[j + 1], tbody.rows[j]);
                            }
                        } else {
                            if(e.id == "desc") { //v1 moves down
                                tbody.insertBefore(tbody.rows[j + 1], tbody.rows[j]);
                            }
                        }
                    } else if(tableSort.isNumeric(v1) && !tableSort.isNumeric(v2)) {
                        //v2 is a string, v1 is a number and automatically wins
                        if(e.id == "asc") { //v1 moves down
                            tbody.insertBefore(tbody.rows[j + 1], tbody.rows[j]);
                        }
                    } else if(!tableSort.isNumeric(v1) && tableSort.isNumeric(v2)) {
                        //v1 is a string, v2 is a number and automatically wins
                        if(e.id == "desc") { //v1 moves down
                            tbody.insertBefore(tbody.rows[j + 1], tbody.rows[j]);
                        }
                    } else {
                        //Both v1 and v2 are strings, use localeCompare()
                        if(v1.localeCompare(v2) > 0) {
                            if(e.id == "asc") { //v1 moves down
                                tbody.insertBefore(tbody.rows[j + 1], tbody.rows[j]);
                            }
                        } else {
                            if(e.id == "desc") { //v1 moves down
                                tbody.insertBefore(tbody.rows[j + 1], tbody.rows[j]);
                            }
                        }
                    }
                    j++;
                } else {
                    console.log("One of the values turned up undefined");
                }
            }
        }
    }
}

//Wait until DOM is ready and then initialize the table headers.
window.onload = function () {
    initHeaders(tableID);
}

Thanks in advance to anyone who can point me in the right direction.

----- EDIT: ----- Okay so after reading the answers here and making some hefty modifications to how I was going about things I have e up with a much better solution. The progress bar isn't exactly what I wanted, but it is close. (Although I believe that it is showing up on the page just as the sorting is getting ready to finish up.)

I modified my loop to do a O(n log n) quick sort and instead of modifying the DOM directly I instead isolate the table rows to sort and copy them into an array. I then do the sort directly on the array and once it is finished I rebuild the rows and then remove the old rows and append the new ones in. The sort time has been reduced significantly.

Have a look: /

And here is the new JS code:

//Change this variable to match the "id" attribute of the
//table that is going to be operated on.
var tableID = "sortable";

/**
 * Attach click events to all the <th> elements in a table to 
 * call the tableSort() function. This function assumes that cells  
 * in the first row in a table are <th> headers tags and that cells
 * in the remaining rows are <td> data tags.
 *
 * @param table The table element to work with.
 * @return void
 */
function initHeaders(table) {
    //Get the table element
    table = document.getElementById(table);
    //Get the number of cells in the header row
    var l = table.rows[0].cells.length;
    //Loop through the header cells and attach the events
    for(var i = 0; i < l; i++) {
        if(table.rows[0].cells[i].addEventListener) { //For modern browsers
            table.rows[0].cells[i].addEventListener("click", tableSort, false);
        } else if(table.rows[0].cells[i].attachEvent) { //IE specific method
            table.rows[0].cells[i].attachEvent("onclick", tableSort);
        }
    }
}


function tableSort(e) { 

    var runs = 0;
    var pix = 0;
    var ndx = 0;
    var dir = "right";
    var interval = false;

    //Get the element from the click event that was passed.
    if(e.currentTarget) { //For modern browsers
        e = e.currentTarget;
    } else if(window.event.srcElement) { //IE specific method
        e = window.event.srcElement;
    } else {
        console.log("Unable to determine source event. Terminating....");
        return false;
    }

    //Get the index of the cell, will be needed later
    ndx = e.cellIndex;

    //Toggle between "asc" and "desc" depending on element's id attribute
    if(e.id == "asc") {
        e.id = "desc";
    } else {
        e.id = "asc";
    }

    //Move up from the <th> that was clicked and find the parent table element.
    var parent = e.parentElement;
    var s = parent.tagName;
    while(s.toLowerCase() != "table") {
        parent = parent.parentElement;
        s = parent.tagName;
    }

    //Get the rows to operate on as an array
    var rows = document.getElementById("replace").rows;
    var a = new Array();
    for(i = 0; i < rows.length; i++) {
        a.push(rows[i]);
    }

    //Show progress bar ticker
    document.getElementById("progress").style.display = "block";

    /**
     * Show the progress bar ticker animation
     *
     * @param pix The current pixel count to set the <div> margin at.
     */
    function updateTicker(pix) {

                var tick = document.getElementById("progressTicker");
                document.getElementById("progressText").style.display = "block";
                document.getElementById("progressText").innerHTML = "Sorting table...please wait";
                if(dir == "right") {
                    if(pix < 170) {
                        pix += 5;
                        tick.style.marginLeft = pix + "px";
                    } else {
                        dir = "left";
                    }
                } else {
                    if(pix > 0) {
                        pix -= 5;
                        tick.style.marginLeft = pix + "px";
                    } else {
                        dir = "left";
                    }
                }
                interval = window.setTimeout( function () { updateTicker(pix); }, 25);
    }
    updateTicker(pix);

    /**
     * Checks to see if a value is numeric.
     *
     * @param n The ining value to check.
     * @return bool TRUE if value is numeric, FALSE otherwise.
     */
    isNumeric = function (n) {
        var num = false;
        if(!isNaN(n) && isFinite(n)) {
            num = true;
        }
        return num;
    }

    /**
     * Compares two values and determines which one is "bigger".
     *
     * @param x A reference value to check against.
     * @param y The value to be determined bigger or smaller than the reference.
     * @return TRUE if y is greater or equal to x, FALSE otherwise
     */
    function pare(x, y) {
        var bigger = false;
        x = x.cells[ndx].textContent;
        y = y.cells[ndx].textContent;
        //console.log(e.id);
        if(isNumeric(x) && isNumeric(y)) {
            if(y >= x) {
                bigger = (e.id == "asc") ? true : false;
            } else {                
                bigger = (e.id == "desc") ? true : false;
            }
        } else {
            if(y.localeCompare(x) >= 0) {
                bigger = (e.id == "asc") ? true : false;
            } else {                
                bigger = (e.id == "desc") ? true : false;
            }
        }
        return bigger;
    }   

    /**
     * Performs a quicksort O(n log n) on an array.
     *
     * @param array The array that needs sorting
     * @return array The sorted array.
     */
    function nlognSort(array) {
        runs++
        if(array.length > 1) {
            var big = new Array();
            var small = new Array();
            var pivot = array.pop();
            var l = array.length;
            for(i = 0; i < l; i++) {
                if(pare(pivot,array[i])) {
                    big.push(array[i]);
                } else {
                    small.push(array[i]);
                }
            }
            return Array.prototype.concat(nlognSort(small), pivot, nlognSort(big));
        } else {
            return array;
        }
    }


    //Run sort routine  
    b = nlognSort(a);

    //Rebuild <tbody> and replace new with the old
    var tbody = document.createElement("tbody");
    var l = b.length;
    for(i = 0; i < l; i++) {
        tbody.appendChild(b.shift());
    }
    parent.removeChild(document.getElementById("replace"));
    parent.appendChild(tbody);
    tbody.setAttribute("id","replace");
    setTimeout(function () {
        document.getElementById("progress").style.display = "none";
        document.getElementById("progressText").style.display = "none";
        clearTimeout(interval);
    },1500);
}


window.onload = function() {
    initHeaders(tableID);
}

Thanks again everyone!!

I am have an issue with a JS script I am trying to put together. I have an HTML table with somewhere in the neighborhood of 300 rows in it. I have made a sort function that will make the table headers clickable and launch my sort function. I would like to integrate a progress bar because in larger tables (500 - 1000 rows) after a header is clicked the table takes a bit of time to sort (IE is a big offender). The progress bar would tell them how much time remains before the sort is plete. The method I had in mind was a div element that I would resize based on the progression of the sort loop. The problem is that I can't seem to figure out how to integrate such a routine into my loop.

I've researched the issue and taken note of this: How to change progress bar in loop? and this: Using setTimeout to update progress bar when looping over multiple variables

The second topic has a few demos that do essentially what I would like to do as far as the progress bar goes. However, anytime I try to implement the solutions shown in those two posts I either:

A - Crash the browser

B - Progress bar appears to work, but goes from 0 - 100% instantly, not progressively.

I am hoping someone can lead me in the right direction on what to do. This table sort progress indicator must be done using native JS because the contents must be available offline, hence I can't include any jQuery libraries via CDN and bloating the document with the entire jQuery library isn't desired.

I've created a JS fiddle with my code in it. I've stripped out what I had for progress bar code because I kept crashing the browser so all that is there as far as scripts go is the sorting-related code. jsfiddle

Here is the JS itself:

//Change this variable to match the "id" attribute of the
//table that is going to be operated on.
var tableID = "sortable";

/**
 * Attach click events to all the <th> elements in a table to 
 * call the tableSort() function. This function assumes that cells  
 * in the first row in a table are <th> headers tags and that cells
 * in the remaining rows are <td> data tags.
 *
 * @param table The table element to work with.
 * @return void
 */
function initHeaders(table) {
    //Get the table element
    table = document.getElementById(table);
    //Get the number of cells in the header row
    var l = table.rows[0].cells.length;
    //Loop through the header cells and attach the events
    for(var i = 0; i < l; i++) {
        if(table.rows[0].cells[i].addEventListener) { //For modern browsers
            table.rows[0].cells[i].addEventListener("click", tableSort, false);
        } else if(table.rows[0].cells[i].attachEvent) { //IE specific method
            table.rows[0].cells[i].attachEvent("onclick", tableSort);
        }
    }
}

/**
 * Compares values in a column of a table and then sorts the table rows.
 * Subsequent calls to this function will toggle a row between ascending
 * and descending sort directions.
 *
 * @param e The click event passed in from the browser.
 * @return mixed No return value if operation pletes successfully, FALSE on error.
 */
function tableSort(e) { 

    /**
     * Checks to see if a value is numeric.
     *
     * @param n The ining value to check.
     * @return bool TRUE if value is numeric, FALSE otherwise.
     */
    tableSort.isNumeric = function (n) {
        var num = false;
        if(!isNaN(n) && isFinite(n)) {
            num = true;
        }
        return num;
    }

    //Get the element from the click event that was passed.
    if(e.currentTarget) { //For modern browsers
        e = e.currentTarget;
    } else if(window.event.srcElement) { //IE specific method
        e = window.event.srcElement;
    } else {
        console.log("Unable to determine source event. Terminating....");
        return false;
    }

    //Get the index of the cell, will be needed later
    var ndx = e.cellIndex;

    //Toggle between "asc" and "desc" depending on element's id attribute
    if(e.id == "asc") {
        e.id = "desc";
    } else {
        e.id = "asc";
    }

    //Move up from the <th> that was clicked and find the parent table element.
    var parent = e.parentElement;
    var s = parent.tagName;
    while(s.toLowerCase() != "table") {
        parent = parent.parentElement;
        s = parent.tagName;
    }

    /*
    Executes two different loops.  A "for" loop to control how many
    times the table rows are passed looking for values to sort and a
    "while" loop that does the actual paring of values.  The "for"
    loop also controls how many times the embedded "while" loop will
    run since each iteration with force at least one table row into 
    the correct position.   
    */

    //var interval = setInterval( function () { progress.updateProgress() } , 100);
    var rows = parent.tBodies[0].rows.length; //Isolate and count rows only in the <tbody> element.
    if(rows > 1) {  //Make sure there are enough rows to bother with sorting
        var v1; //Value 1 placeholder
        var v2; //Value 2 placeholder
        var tbody = parent.tBodies[0];  //Table body to manipulate
        //Start the for loop (controls amount of table passes)
        for(i = 0; i < rows; i++) {
            var j = 0;  //Counter for swapping routine
            var offset = rows - i - 1;  //Stops next loop from overchecking

            // WANT TO UPDATE PROGRESS BAR HERE

            //Start the while loop (controls number of parisons to make)
            while(j < offset) {             

                //Check to make sure values can be extracted before proceeding
                if(typeof tbody.rows[j].cells[ndx].innerHTML !== undefined && typeof tbody.rows[j + 1].cells[ndx].innerHTML !== undefined) {

                    //Get cell values and pare
                    v1 = tbody.rows[j].cells[ndx].innerHTML;
                    v2 = tbody.rows[j + 1].cells[ndx].innerHTML;
                    if(tableSort.isNumeric(v1) && tableSort.isNumeric(v2)) {
                        //Dealing with two numbers
                        v1 = new Number(v1);
                        v2 = new Number(v2);
                        if(v1 > v2) {
                            if(e.id == "asc") { //v1 moves down
                                tbody.insertBefore(tbody.rows[j + 1], tbody.rows[j]);
                            }
                        } else {
                            if(e.id == "desc") { //v1 moves down
                                tbody.insertBefore(tbody.rows[j + 1], tbody.rows[j]);
                            }
                        }
                    } else if(tableSort.isNumeric(v1) && !tableSort.isNumeric(v2)) {
                        //v2 is a string, v1 is a number and automatically wins
                        if(e.id == "asc") { //v1 moves down
                            tbody.insertBefore(tbody.rows[j + 1], tbody.rows[j]);
                        }
                    } else if(!tableSort.isNumeric(v1) && tableSort.isNumeric(v2)) {
                        //v1 is a string, v2 is a number and automatically wins
                        if(e.id == "desc") { //v1 moves down
                            tbody.insertBefore(tbody.rows[j + 1], tbody.rows[j]);
                        }
                    } else {
                        //Both v1 and v2 are strings, use localeCompare()
                        if(v1.localeCompare(v2) > 0) {
                            if(e.id == "asc") { //v1 moves down
                                tbody.insertBefore(tbody.rows[j + 1], tbody.rows[j]);
                            }
                        } else {
                            if(e.id == "desc") { //v1 moves down
                                tbody.insertBefore(tbody.rows[j + 1], tbody.rows[j]);
                            }
                        }
                    }
                    j++;
                } else {
                    console.log("One of the values turned up undefined");
                }
            }
        }
    }
}

//Wait until DOM is ready and then initialize the table headers.
window.onload = function () {
    initHeaders(tableID);
}

Thanks in advance to anyone who can point me in the right direction.

----- EDIT: ----- Okay so after reading the answers here and making some hefty modifications to how I was going about things I have e up with a much better solution. The progress bar isn't exactly what I wanted, but it is close. (Although I believe that it is showing up on the page just as the sorting is getting ready to finish up.)

I modified my loop to do a O(n log n) quick sort and instead of modifying the DOM directly I instead isolate the table rows to sort and copy them into an array. I then do the sort directly on the array and once it is finished I rebuild the rows and then remove the old rows and append the new ones in. The sort time has been reduced significantly.

Have a look: http://jsfiddle/jnBmp/5/

And here is the new JS code:

//Change this variable to match the "id" attribute of the
//table that is going to be operated on.
var tableID = "sortable";

/**
 * Attach click events to all the <th> elements in a table to 
 * call the tableSort() function. This function assumes that cells  
 * in the first row in a table are <th> headers tags and that cells
 * in the remaining rows are <td> data tags.
 *
 * @param table The table element to work with.
 * @return void
 */
function initHeaders(table) {
    //Get the table element
    table = document.getElementById(table);
    //Get the number of cells in the header row
    var l = table.rows[0].cells.length;
    //Loop through the header cells and attach the events
    for(var i = 0; i < l; i++) {
        if(table.rows[0].cells[i].addEventListener) { //For modern browsers
            table.rows[0].cells[i].addEventListener("click", tableSort, false);
        } else if(table.rows[0].cells[i].attachEvent) { //IE specific method
            table.rows[0].cells[i].attachEvent("onclick", tableSort);
        }
    }
}


function tableSort(e) { 

    var runs = 0;
    var pix = 0;
    var ndx = 0;
    var dir = "right";
    var interval = false;

    //Get the element from the click event that was passed.
    if(e.currentTarget) { //For modern browsers
        e = e.currentTarget;
    } else if(window.event.srcElement) { //IE specific method
        e = window.event.srcElement;
    } else {
        console.log("Unable to determine source event. Terminating....");
        return false;
    }

    //Get the index of the cell, will be needed later
    ndx = e.cellIndex;

    //Toggle between "asc" and "desc" depending on element's id attribute
    if(e.id == "asc") {
        e.id = "desc";
    } else {
        e.id = "asc";
    }

    //Move up from the <th> that was clicked and find the parent table element.
    var parent = e.parentElement;
    var s = parent.tagName;
    while(s.toLowerCase() != "table") {
        parent = parent.parentElement;
        s = parent.tagName;
    }

    //Get the rows to operate on as an array
    var rows = document.getElementById("replace").rows;
    var a = new Array();
    for(i = 0; i < rows.length; i++) {
        a.push(rows[i]);
    }

    //Show progress bar ticker
    document.getElementById("progress").style.display = "block";

    /**
     * Show the progress bar ticker animation
     *
     * @param pix The current pixel count to set the <div> margin at.
     */
    function updateTicker(pix) {

                var tick = document.getElementById("progressTicker");
                document.getElementById("progressText").style.display = "block";
                document.getElementById("progressText").innerHTML = "Sorting table...please wait";
                if(dir == "right") {
                    if(pix < 170) {
                        pix += 5;
                        tick.style.marginLeft = pix + "px";
                    } else {
                        dir = "left";
                    }
                } else {
                    if(pix > 0) {
                        pix -= 5;
                        tick.style.marginLeft = pix + "px";
                    } else {
                        dir = "left";
                    }
                }
                interval = window.setTimeout( function () { updateTicker(pix); }, 25);
    }
    updateTicker(pix);

    /**
     * Checks to see if a value is numeric.
     *
     * @param n The ining value to check.
     * @return bool TRUE if value is numeric, FALSE otherwise.
     */
    isNumeric = function (n) {
        var num = false;
        if(!isNaN(n) && isFinite(n)) {
            num = true;
        }
        return num;
    }

    /**
     * Compares two values and determines which one is "bigger".
     *
     * @param x A reference value to check against.
     * @param y The value to be determined bigger or smaller than the reference.
     * @return TRUE if y is greater or equal to x, FALSE otherwise
     */
    function pare(x, y) {
        var bigger = false;
        x = x.cells[ndx].textContent;
        y = y.cells[ndx].textContent;
        //console.log(e.id);
        if(isNumeric(x) && isNumeric(y)) {
            if(y >= x) {
                bigger = (e.id == "asc") ? true : false;
            } else {                
                bigger = (e.id == "desc") ? true : false;
            }
        } else {
            if(y.localeCompare(x) >= 0) {
                bigger = (e.id == "asc") ? true : false;
            } else {                
                bigger = (e.id == "desc") ? true : false;
            }
        }
        return bigger;
    }   

    /**
     * Performs a quicksort O(n log n) on an array.
     *
     * @param array The array that needs sorting
     * @return array The sorted array.
     */
    function nlognSort(array) {
        runs++
        if(array.length > 1) {
            var big = new Array();
            var small = new Array();
            var pivot = array.pop();
            var l = array.length;
            for(i = 0; i < l; i++) {
                if(pare(pivot,array[i])) {
                    big.push(array[i]);
                } else {
                    small.push(array[i]);
                }
            }
            return Array.prototype.concat(nlognSort(small), pivot, nlognSort(big));
        } else {
            return array;
        }
    }


    //Run sort routine  
    b = nlognSort(a);

    //Rebuild <tbody> and replace new with the old
    var tbody = document.createElement("tbody");
    var l = b.length;
    for(i = 0; i < l; i++) {
        tbody.appendChild(b.shift());
    }
    parent.removeChild(document.getElementById("replace"));
    parent.appendChild(tbody);
    tbody.setAttribute("id","replace");
    setTimeout(function () {
        document.getElementById("progress").style.display = "none";
        document.getElementById("progressText").style.display = "none";
        clearTimeout(interval);
    },1500);
}


window.onload = function() {
    initHeaders(tableID);
}

Thanks again everyone!!

Share Improve this question edited May 23, 2017 at 11:46 CommunityBot 11 silver badge asked Jul 30, 2013 at 21:32 CrackertasticCrackertastic 4,9132 gold badges32 silver badges40 bronze badges 5
  • 1 At first I'd try to get a faster sort by using the native Array::sort with O(n log n), your current algorithm has O(n²). Only if that doesn't help, you would have to write your own fast and asynchronous sort function (which seems a little over your head, judged from the current code quality). – Bergi Commented Jul 30, 2013 at 21:37
  • Don't sort the DOM in-place. While JavaScript itself can sort quite fast, DOM access can be quite slow, especially on older browsers! – Hallvar Helleseth Commented Jul 30, 2013 at 21:39
  • it's just too slow to both rearrange and update a progress bar. you might trying setting visibility:hidden on the table while sorting, that can avoid redraws, and greatly speed up the operation under certain conditions. – dandavis Commented Jul 30, 2013 at 21:40
  • @Bergi Thanks for the tip about the sorting. A look around the internet and wikipedia gave me the info I needed to write up what is hopefully a good implementation of the quick sort. On a side note, I am still getting myself familiar with JS and what goes on under the hood, could you elaborate on what you meant about the current code quality? I didn't take offense to the ment, but was curious if there was something unorthodox I was/am doing. jsfiddle/jnBmp/5 – Crackertastic Commented Aug 1, 2013 at 6:11
  • @HallvarHelleseth Thanks for the info about DOM access. I didn't realize how slow editing the DOM directly could be, and how shoddy looking rearranging rows would be in a loop. – Crackertastic Commented Aug 1, 2013 at 6:15
Add a ment  | 

2 Answers 2

Reset to default 12

Take a look at the following:
http://jsfiddle/6JxQk/

The idea here is to replace your for loop with an asynchronous loop that uses setTimeout(), so you would go from the following:

for (var i = 0; i < rows; i++) {
    // do stuff
}

... to this:

var i = 0;
(function doSort() {
    // update progress
    // do stuff
    i++;
    if (i < rows) {
        setTimeout(doSort, 0);
    }
})();

Although as you can see, this significantly slows down your sorting routine because in addition to updating the progress bar, this will reorder the rows of your table. With this in mind I think you are better off just using a built-in sort rather than your own implementation, and dropping the progress bar.

It may not be exactly what you are looking for - IMHO a progress bar must be used when you have an estimate of how much time a particular operation is going to take or how many bytes need to be transferred. In other non-deterministic cases you must be showing a spinner :-)

发布评论

评论列表(0)

  1. 暂无评论