1

I'm trying to include a JS file in my website via Ajax by getting it from one of my GitHub repositories, using Rawgit. For some reason, it doesn't work when I use the development or production URLs, but when I use the raw version of my files directly from Github, the problem stops. I don't experience any problems when I use the development URL for a CSS file. Does anyone know why this happens?

Here's my code:

$.get("https://rawgit.com/Larpee/The-Khan-Quiz/master/game.js", function (game) {
    var sketchProc = function (processingInstance) {
        with (processingInstance) {
            size(400, 400);
            frameRate(30);
            eval(game);
        }
    };

    var canvas = document.getElementById("game");
    var processingInstance = new Processing(canvas, sketchProc);
});

Update: I think the problem occurs because GitHub (not Rawgit), serves the files as .txt files, while RawGit serves them as .js.

I would still like to receive an explanation for why getting my JavaScript files with a .js extension isn't working, though

1 Answer 1

2
+50

For RawGit, you get content-type: application/javascript;charset=utf-8 as expected, and GitHub gives Content-Type: text/plain; charset=utf-8. That seems to be the only difference.

I checked your example and found that when using RawGit (and getting a script response), the success callback wouldn't execute at all, but using GitHub it would (adding a console.log('foo'); statement, for example. I also found that eval() run on your script throws an exception:

Uncaught ReferenceError: createFont is not defined

I made a repo myself with a placeholder JS file that was syntactically correct, in which case success callbacks for $.get() on both RawGit and GitHub did execute, and later added a reference to an undefined name, which caused the call to the RawGit URL fail to execute its callback.

The lesson? When you get a script with $.get(), it is actually immediately executed, and if that eval() fails then everything ends there, silently. This is supported by jQuery getScript load vs execution, which also implies that this (in my opinion) kind of crazy way of dealing with script data ended in version 2.1.0.

Which leads me to suggest that, apart from fixing your script, you should either use $.getScript() (not sure if you have to ensure the result header has application/javascript), or explicitly insert a script element with JS and have an onload callback:

(function(d, script) {
    script = d.createElement('script');
    script.type = 'text/javascript';
    script.async = true;
    script.onload = function(){
        // remote script has loaded
    };
    script.src = '[RawGit URL]';
    d.getElementsByTagName('head')[0].appendChild(script);
}(document));

Additionally, the with block you use should become:

var sketchProc = function (processing) { 
    processing.size(400, 400); 
    processing.frameRate(30); 
}

var canvas = $('#game'); // use jQuery since you have it 
var processingInstance = new Processing(canvas, sketchProc);

// game code now manipulates `processingInstance`
// either directly in scope (or even better as object with parameter)
processingInstance.draw = function () {
    var processing = this;
    // if your code originally used `processing` throughout,
    // do this so that it refers to the specific instance you've created
    // ...
}
processingInstance.loop();
// if initialized without a `.draw()` method like above, you need to start the loop manually once there is one 

The Processing.js documentation has a lot of examples that are basically in Java and require small modifications to properly deal with JS scope. Sad!

Sign up to request clarification or add additional context in comments.

12 Comments

Thank you very much for your great effort, but there's still something I don't understand: if the problem with my code is that jQuery is executing my script without even running the callback, how would avoid this behavior (I don't want the script to be executed, just the callback, since I'm using eval() on the string containing the script from there)?
When $.get() receives data it's told is JavaScript, it calls $.globalEval() with that content as an argument, which runs eval() on the data in the global scope. That is the default behavior, it doesn't seem you can change it. Your problem is that when your script is executed in the global scope, it throws an error because there's (at least one) reference to a variable that's undefined in the global scope, and so the rest of $.get(), which includes running callbacks on the result, fails silently. There are a few different ways to fix this.
Yes, the calls to undefined functions and variables are because the code uses a library called Processing.js, which contains a lot of predefined functions for drawing and animating elements in the canvas tag. That's why I need to code to be executed only inside the callback. I guess I'll keep making the Ajax code receive the code as a text file, which solves the problem. Thank you for explaining the issue to me, it was making me go crazy. I'll give you the bounty
Why are you loading the script dynamically?
Because I needed the callback function that's executed with the Ajax call. What else would you suggest?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.