Randal Cunanan
Randal Cunanan

Reputation: 2539

Running javascript after page is fully rendered

I am trying to create a syntax highlighter script. I tried using my script on a code with 10 thousand lines, and all I see is a blank page while it is loading. Everything will just show up after the script has finished its task. By the way, I called my script inside the ready function of jQuery.

$(myFunction);

The script should execute after the page is fully rendered, and the user can actually navigate through the page even if the script is not yet finished. The javascript will run in the background as it highlights the code one by one while not interfering with the responsiveness of the page. Thanks in advance.

EDIT:

To make this clearer, I would like to execute the code after everything is "rendered," not "loaded". Everything should already be visible in the screen and the user can actually see the code come to life as it is being highlighted. Thanks.

Upvotes: 35

Views: 122561

Answers (5)

Alan Currie
Alan Currie

Reputation: 1

I know the original poster will have long since moved on from this 10yr-old question. But I hope this answer may help someone.

First off, good async programming and the use of window.onload are probably a big part of the solution. Individual implementations will vary.

Another problem that we're trying to overcome here, I think, is that too much work is being done in the main thread on the client. Other than writing more efficient code, there's no trick I can think of to get around that problem. The only solution is to not do that work on the main thread. One option is to do more work on the server.

Another option is to use a web worker to put that work in a background thread. You can't directly update the DOM from the worker thread, but you can still do most of the prep work.

If you've never used web workers before, don't be intimidated; they're pretty quick to implement, assuming you know JavaScript. All you really need to get started are new Worker() to start a background thread, postMessage() to send data from the main thread to the worker thread (or vice versa) and the onmessage event handler for receiving the data (in either direction).

It's like a pure function that runs without blocking the DOM, and calls you back with data when it's done.

Here's an example implementation in which there's an initial page render of black text. Meanwhile, the web worker decides blue is better, thinking about it for 2 long, hard seconds, then reporting the result back to the main thread. The main thread then updates the DOM in response.

<body>
  <div id="cool-div"></div>
  <script>
    let myData = [
      "This is my sample data that I want to do a bunch of work to, such as parsing it and returning new html to render.",
    ];
    document.getElementById(
      "cool-div"
    ).innerHTML = `<p style="color:black">${myData}</p>`;
    const myWorker = new Worker("worker.js");
    myWorker.onmessage = (event) =>
      (document.getElementById("cool-div").innerHTML = event.data);
    myWorker.postMessage(myData);
  </script>
</body>

Then in worker.js:

onmessage = (e) => {
  const newData = `<p style="color:blue">${e.data}</div>`;
  //pretend to do hard work, then pass the result back to main thread
  setTimeout(() => postMessage(newData), 2000);
};

Upvotes: 0

Todd Harvey
Todd Harvey

Reputation: 347

in case you didn't try this yet, 9 years later …

$(document).ready(function () {
    window.setTimeout('ctlEmployeeEdit.document_load()', 50);
    });

I guess if you set your time out to 9 years of milliseconds, the page will probably have rendered, but that's just my hypothesis!

Upvotes: 11

synaptik
synaptik

Reputation: 9519

Problem with window.onload approaches

Even if you use the $(window).load approach, your highlighter stuff could get run prior to something from $(document).ready completing, since there may be lots of asynchronous callback functions all over the place.

My approach

I use a combination of waiting for document.readyState == 'complete and setTimeout. The idea is that I want to wait until the page is fully rendered (hence the 'complete') and then further ensure that the $(document).ready JQuery wrapper content has completed (hence the setTimeout).

Here's how I would solve your problem, assuming that 200 milliseconds is ample time for everything inside $(document).ready(function(){ /*...*/ }); to complete.

function highlighterAction() {
    // actually do the highlighting stuff here
}

function highlighter() {
    /*
      The short pause allows any required callback functions
      to execute before actually highlighting, and allows
      the JQuery $(document).ready wrapper to finish.
     */
    setTimeout(function() {
        highlighterAction();
    }, 200);
}

/*
  Only trigger the highlighter after document fully loaded.  This is
  necessary for cases where page load takes a significant length
  of time to fully load.
*/
if (document.readyState == 'complete') {
    highlighter();
} else {
    document.onreadystatechange = function () {
        if (document.readyState === "complete") {
            highlighter();
        }
    }
}

Upvotes: 9

afreeland
afreeland

Reputation: 3979

Not sure exactly how much data is being brought in...but what if on document ready you ran a jquery ajax call and used the completed method to run your highlighter function? If there is a lot of data it will be a slower page load.

Anyways would like similar to this

$.ajax({
            type: "POST",
            url: "Where data is actually stored",
            data: { ChannelTypeID: ChannelTypeID },
            datatype: "html",
            beforeSend: function () {

            },
            success: function (myHTML) {
                $('body').html(myHTML);
            },
            error: function () {
                alert("Ajax request was unsuccessful");
            },
            complete: function () {
                highlighterFunction();
            }
        });

The complete method specifies a function to be run when an AJAX request completes. Hopefully the success will fire early enough to push the data and allow your highlight to work properly

Upvotes: 1

Adam Rackis
Adam Rackis

Reputation: 83366

Do you mean after all the images have been loaded?

I think window.onload is what you're looking for

window.onload = function() {
    //dom not only ready, but everything is loaded
};

EDIT

Per Chris's comment, here's the jQuery way:

$(window).load(function() {
    //dom not only ready, but everything is loaded
});

Upvotes: 36

Related Questions