0

I have this function:

function parseScript(_source) {
    var source = _source;
    var scripts = new Array();

    while(source.indexOf("<script") > -1 || source.indexOf("</script") > -1) {
        var s = source.indexOf("<script");
        var s_e = source.indexOf(">", s);
        var e = source.indexOf("</script", s);
        var e_e = source.indexOf(">", e);

        scripts.push(source.substring(s_e+1, e));
        source = source.substring(0, s) + source.substring(e_e+1);
    }
    for(var i=0; i<scripts.length; i++) {
        try {
            eval(scripts[i]);
        }
        catch(ex) {
        }
    }
    return source;
}

It parses and execute Javascript wonderfully except the when in <script type='text/javascript' src='scripts/gen_validatorv31.js'></script> the src file never gets executed.

user1841964
  • 101
  • 1
  • 2
  • 8
  • 3
    Why on earth you need this, why don't you just let browser parse scripts? – Teemu Dec 14 '12 at 18:40
  • I won't get into using `eval` is a good idea or not. But how are you calling your function? It won't execute on its own. – bits Dec 14 '12 at 18:41
  • 1
    Like @Teemu said, why are you doing this? What is wrong with browser doing it? – bits Dec 14 '12 at 18:42
  • @bits I load the content dynamically with AJAX – user1841964 Dec 14 '12 at 18:50
  • @user1841964 Are you receiving javascript code as string as a part of your ajax response? – bits Dec 14 '12 at 18:53
  • 3
    If I understand your question correctly, the problem is that the parser only works on inline javascript - it can't cope with external files which you would have to load instead using `XMLHttpRequest`. (And this is probably a bad idea in most cases) – Stuart Dec 14 '12 at 18:54
  • @Stuart it's probably a better idea than trying to load in a non-JavaScript file and trying to parse only the JavaScript from it, though. – Paul S. Dec 14 '12 at 19:02
  • @PaulS. True, I suppose it's not crazy to load in a single script actually and could be justified where you have really long scripts that might or might not be needed. The usual way of doing this seems to be to append a new script element to the page rather than (as I had guessed) loading it with `XMLHttpRequest` then `eval`uating it. (See http://stackoverflow.com/a/7293359/567595) – Stuart Dec 14 '12 at 19:27
  • You should use [DOM methods to access DOM elements](https://developer.mozilla.org/en-US/docs/Gecko_DOM_Reference/Introduction) (as `script` is) or it's attributes: `document.getElementsByTagName( 'script' )`. No need to parse the HTML by yourself, JS could do that for you. – feeela Dec 14 '12 at 20:00
  • @Stuart So I need to add the option of catching the src's and then using `AddScriptTag(src)` on them? – user1841964 Dec 14 '12 at 20:22

1 Answers1

1

The parser can only evaluate inline scripts in the file you have opened. To evaluate external scripts you would have to find their sources, probably using something like:

var scripts = source.match(/<script[^>]*src=[^>]*>/g);
if (scripts) {
    for (var i = 0; i < scripts.length; i++) {
        src = scripts[i].match(/src=("([^"]*)"|'([^']*)')/);
        src = src[2] || src[3];
        if (src) {
            addScriptTag(src);
        }
    }
}
else console.log('no external scripts found');

where addScriptTag is described in this answer. addScriptTag adds the script to the head, if possible. It will need to be adapted if you need to add script to the body.

However... why do this? It is slow and messy to parse an entire HTML/Javascript page to get the scripts; for instance you might end up loading the same scripts twice or loading two scripts that don't work well together. Also the scripts may not work if inserted at a different point in the head or body. With AJAX you should only be loading the particular elements you need. Usually this means loading bits of data or HTML to be added to the page. If you have long scripts that are not needed at the beginning but might be needed later then it might be justified to dynamically add new scripts to the page. But in many cases probably better to load all needed scripts at the beginning. And if you really need to switch pages completely then isn't it better to use the old-fashioned method of linking to another page?

Community
  • 1
  • 1
Stuart
  • 9,597
  • 1
  • 21
  • 30
  • Uncaught TypeError: Cannot read property '1' of null, Uncaught TypeError: Cannot read property 'length' of null – user1841964 Dec 15 '12 at 12:04
  • Uncaught TypeError: Cannot read property 'length' of null. I'm also experimenting now... – user1841964 Dec 15 '12 at 12:21
  • ok I tried again. The regex needs to catch single quotes as well as double. – Stuart Dec 15 '12 at 13:52
  • This seems to skip over one of the Javascript files `` – user1841964 Dec 15 '12 at 18:56
  • Third time lucky... there was a small error I corrected (`src = scripts[0]` should have been `src = scripts[i]`) – Stuart Dec 15 '12 at 20:06
  • Thanks your code did work! The only problem is that I am left with an `Uncaught ReferenceError: PasswordWidget is not defined` error even thought the function was defined in one of the loaded files, for some reason they are being loaded after the javascript in the form executes. – user1841964 Dec 15 '12 at 22:42
  • Ideally you would check if the script is in the `head` of your source or the `body`, and place it in the same position in the new page; that way it is more likely to run in the same order. – Stuart Dec 15 '12 at 23:08
  • Still get an error :( the weird thing is if I navigate to that page everything works but when I refresh it the script is set to load the same page using the URL, everything stops working and I get the dreaded error. – user1841964 Dec 15 '12 at 23:59