2

I need to load JavaScript code (which I don't have control over) from a URL into a div. The JavaScript code is a bunch of document.write() statements. Once the document.write() statements finish executing, I need to extract the resulting text from the div using jQuery or JavaScript and use that text for something else. Currently, I am doing the following to load the JavaScript into the div:

    $('body').append('<div id="mydiv" style="display: none"></div>');
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;
    $('#mydiv').append(script);

How would I know when the document.write statements have finished executing and I can safetly extract the text out of the div and use it? Or, is there a better way of doing this?

stepanian
  • 11,373
  • 8
  • 43
  • 63
  • Use a timer and check whether the `.html()` is the same – Blender Dec 10 '11 at 22:16
  • [try this](http://stackoverflow.com/questions/2463460/run-a-javascript-function-on-script-load) – hackartist Dec 10 '11 at 22:18
  • hackartist: That post is somewhat related, but is also not answered. The getScript function would not work for me because that would load the script into the head (as it's supposed to). – stepanian Dec 10 '11 at 22:23
  • I wonder if you could temporarily override `document.write` with your own function: `var dw = document.write;document.write = function(text) { /* ... monitor and store text... */ }` – Matthew Wilcoxson Dec 16 '14 at 17:55

6 Answers6

2

You can setup an html page that has just this (in this example it's called test2.html):

<script type="application/javascript" src="<url of JavaScript>.js"></script>

You can then load this page into the DOM in an iframe and attach a load event handler that gets the contents of the page after it's done loading. This example then also removes the <iframe> from the DOM:

$(function () {

    //append the iframe onto the body, then select it and attach an event handler for the `load` event
    $('body').append('<iframe id="myiframe" style="display: none"></iframe>').children('iframe').on('load', function () {

                //set the html of the `mydiv` element to the body of the loaded page (test2.html)
        $('#mydiv').html($(this).contents().children().children('body').html());

                //remove the iframe from the DOM
        $(this).remove();

      //set the source of the iframe after the `load` event handler is setup to make sure it fires properly
    }).attr('src', 'test2.html'); 
});

Here is a demo: http://apexeleven.com/stackoverflow/document.write/test.html

Note that .on() is new in jQuery 1.7 and is the same as .bind() in this case.

Jasper
  • 75,717
  • 14
  • 151
  • 146
  • Interesting. Let me look at this. Thanks. – stepanian Dec 10 '11 at 22:35
  • It looks like (without trying it), this will actually work. But my original solution was to have the JavaScript inside the div in the original HTML document and then extract it through jQuery. That solution worked but was messy. This one is even messier :) I will give you the +1 though, because technically, it is a solution. – stepanian Dec 10 '11 at 22:43
1

How would I know when the document.write statements have finished executing and I can safely extract the text out of the div and use it?

Your approach won't work at all.

If the DOM has finished loading (which is probably has if you are starting to manipulate it programatically) then it will be in a closed state so calling document.write will first call document.open which will erase the entire document.

(If the DOM hasn't finished loading, then the content will be written to the end of the document and not to the point where the script is inserted).

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • So the only alternative would be to have the script tag be in the div from the beginning when the document is first loaded? That was my first solution and it worked. But I wanted to do the entire thing programatically. – stepanian Dec 10 '11 at 22:27
  • You can use `document.write` to write the foreign script. But now you have two problems! The iframe solution really is the best one here. – Francis Avila Dec 11 '11 at 01:24
0

what you can do is::

1) initially set the div box to something default (zero or null)

2) set a timer, for 500/1000 MS and check if the text of the div has changed since last time or not.

3) if text is still default, goto 2

4) if text has changed and timeout, take the value as final value, else goto 2.

considering that the remote JS will do all the writing at once, that is, there is no large gap between its document.writes

  • This may work, but it's not very elegant. Isn't there a way using JavaScript or JQuery magic where I can have a callback method called when the JavaScript loads? – stepanian Dec 10 '11 at 22:24
0

You should see the jQuery.getScript() function.

Here is from the doc's example:

$.getScript('ajax/test.js', function(data, textStatus){
   console.log(data); //data returned
   console.log(textStatus); //success
   console.log('Load was performed.');
});
phemios
  • 664
  • 4
  • 9
0
$.getScript('foo.js', function() {
 alert('foo.js was loaded, do something cool now');
});
Jasper
  • 75,717
  • 14
  • 151
  • 146
hackartist
  • 5,172
  • 4
  • 33
  • 48
0

document.write() after your document is loaded will clear your document and start a new one. You don't document.write() into a div that already exists unless it's inline javascript that is included in that div and is loaded as your document loads/renders.

So, that leaves you two options:

1) You can create an empty iframe and load the JS into that iframe and let it render into that iframe. If you have no cooperation from the JS, you will likely have to poll to see when the rendering appears to be done. If you create the iframe properly, you may be able to set up a monitor to see when the iframe is loaded.

2) You can include the JS inline into your div and it will render into your div as your page is loaded. This would require baking the div and the script file into your own page HTML like this:

<div id="renderTarget">
<script src="xxx.js"></script>
</div>

If you did it this way, then you would know that it was done rendering when your own document was done loading.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • It seems like I will go back to my original solution, which was item 2 in your answer. I thought there would be a pure JavaScript solution. Item 1 is too much headache :) – stepanian Dec 10 '11 at 22:49