SitePoint Sponsor

User Tag List

Results 1 to 10 of 10
  1. #1
    SitePoint Member
    Join Date
    Dec 2004
    Location
    Winnipeg
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Forcing DOM changes to render

    I have a web page on an Intranet site that includes a client-side JavaScript sort that utilizes the JavaScript array sort function. Performance becomes a bit of a problem when large tables are being sorted. Ideally, I'd like to find a more efficient method of sorting so that I can sort several thousand records in the blink of an eye, but I don't think that's going to happen. I'd be happy if I could at least provide some method of letting the user know that the sort was in progress. Each of the column headings on the sortable tables has an onclick event defined that calls the function that performs the sort. I thought that a reasonable solution may be to create a "span" element containing an appropriate image and/or text that was originally defined with "style.display" set to none, and have the sort function change the "stye.display" of that span to "block" at the start of the sort, and then back to "none" when the sort had been completed. Unfortunately, it appears that the DOM changes that set the style.display to "block" are not rendered immediately. Basically what is happening is that the style changes that I make at the end of the sort are being applied, but the style changes I make at the start of the sort are being ignored. If I add some "alert" statements to see what's happening prior to the sort, the style changes actually do take effect. It appears that the "alert" causes something to happen to render the DOM changes. I suspect that this is one of those Homer Simpson "DOH" moments, but at the moment, I'm baffled. How do I force my DOM changes to be rendered immediately? Any help would be GREATLY appreciated.

  2. #2
    SitePoint Evangelist pip's Avatar
    Join Date
    Jun 2001
    Location
    Cape Town, South Africa
    Posts
    548
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    My attempt in fixing something like this would be to create a timeout of about a half a second to a second. In other words, execute the DOM changes, give it half a second and then do the sort.

    Code:
      
      function makeDOMChanges() {
        ...
        wnidow.setTimeout("sortTables()",0500);
      }
    Not sure if something like that would be appropriate in your situation?
    Last edited by pip; Dec 1, 2004 at 02:51.
    - Pip
    ---------------------------------------------------------------------------------
    Nothing takes the taste out of peanut butter quite like unrequited love.

  3. #3
    SitePoint Member
    Join Date
    Dec 2004
    Location
    Winnipeg
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks pip, but that won't do the trick. For testing, I tried changing things such that the onclick event for the table headers calls 2 separate functions - one to change the innerHTML for a span, and one to perform the actual sort. The function that performs the sort then changes the innerHTML again when it is done. The only change that the browser sees is the final change. The first function is as follows:

    function showWait() {
    window.status="Sorting";
    document.getElementById("spanWait").innerHTML="Sorting";
    }

    and the sort function ends with the statements:

    window.status="Sort Complete";
    document.getElementById("spanWait").innerHTML="Sort Complete";

    With this, when the showWait function is called, the status line is changed to "Sorting", but the span retains it's original contents. When the sort is completed, the status line changes to "Sort Complete", and the span is changed to show "Sort Complete".

  4. #4
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    just a wild guess here, but have you tried using createTextNode, removeChild and appendChild instead of innerHTML ?
    innerHTML is not in accordence with the standards, and is rather slow and bugprone (esp. on gecko-based browsers)

  5. #5
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

  6. #6
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    setTimeout idea is correct. Browser doesn't render anything before script returns control, so you need to interrupt the script, let the brower show changes and then continue. The only possibility to do that is setTimeout:

    Code:
    function onClick_1() {
       showWaitBanner();
       doLongJob();
    // this won't work because browser 
    // doesn't receive control until job is done
    }
    
    function onClick_2() {
        showWaitBanner();
        setTimeout("doLongJob()", 1);
    // this works because script
    // temporary terminates here
    }

  7. #7
    SitePoint Member
    Join Date
    Dec 2004
    Location
    Winnipeg
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    THANK YOU VERY MUCH !!!
    It appears that the setTimeout function as suggested by pip and stereofrog does indeed do the trick. Thanks for the great explanation, stereofrog!

    As for the questions asked by kyberfabrikken, I am just using the built-in javascript array.sort function. I basically build a 2 dimensional javascript array from the HTML table data (using innerHTML), do the sort, then re-write the HTML table from the sorted javascript array, again using innerHTML. I had not considered using createTextNode, removeChild and appendChild instead of innerHTML since I am not familiar with them. You mention performance issues with innerHTML, so I will look into using them to rebuild the HTML table. Is there a better option for obtaining the HTML cell contents rather than using innerHTML for that?

  8. #8
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    http://216.239.59.104/search?q=cache...NodeValue.html

    instead of doing this :
    Code:
    document.getElementById("spanWait").innerHTML="Sorting";
    you may do this :
    Code:
    var spanWait = document.getElementById("spanWait");
    while (spanWait.hasChildNodes()) spanWait.removeChild(spanWait.firstChild);
    spanWait.appendChild(document.createTextNode("Sorting"));
    i don't know if it actually solves your concrete problem, but it should increase performance, and it is "the right thing" (tm)

    regarding performance, you may want to review this excellent article :
    http://dhtmlkitchen.com/learn/js/perf/index.jsp

  9. #9
    SitePoint Wizard
    Join Date
    Mar 2001
    Posts
    3,537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You mention performance issues with innerHTML, so I will look into using them to rebuild the HTML table. Is there a better option for obtaining the HTML cell contents rather than using innerHTML for that?
    innerHTML can be faster as the tests here show:
    http://www.quirksmode.org/dom/innerhtml.html

    It surprises me that kyberfabrikken's tests show exchanging DOM methods for innerHTML is faster in this case.

    I don't know how you are doing it now, but you can also try to speed up execution by not using innerHTML to insert one cell at a time in the document. Instead, create your table and insert the cells into the table element, and later insert the whole table at once into the document. If you use DOM methods, create the table element, then append all the rows and td's to the table. Then at the end, append the whole table to your document as the last step.

    Is there a better option for obtaining the HTML cell contents rather than using innerHTML for that?
    I don't know if it is "better" as in faster, but you can get the cell contents the same way that kyberfabrikken showed you. See here for a tutorial on DOM methods:

    http://www.sitepoint.com/article/rough-guide-dom

    To increase the speed of your code, you need a way to measure how fast your code is executing. One way is to download the full featured javascript debugger Venkman and use it's 'profiling' feature:

    https://update.mozilla.org/extension...id=216&vid=512

  10. #10
    SitePoint Evangelist pip's Avatar
    Join Date
    Jun 2001
    Location
    Cape Town, South Africa
    Posts
    548
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I thought the setTimeout method might do the trick. With regards to the sorting, I haven't extensively worked with the array sort function before, so my work here is done.

    L8er
    - Pip
    ---------------------------------------------------------------------------------
    Nothing takes the taste out of peanut butter quite like unrequited love.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •