0

This question is a consequence of another question of mine.

The code is:

<script type='text/javascript'>
    var scripts = [ 
        "http://www.---.com/include/jquery-1.8.3.min.js",
        "http://www.---.com/include/functions.js",
        "http://www.---.com/include/myjs.js",
        "http://www.---.com/include/plugins/bxslider/bxslider.js" 
    ];
    function downloadJSAtOnload() { 
        for( var i=0; i<scripts.length; i++ ) {
            var element = document.createElement('script');
            element.src = scripts[i];
            document.body.appendChild(element);
        }
        $(document).ready(function(){
            $('#mainslide .bxslider').bxSlider({
                slideWidth: '960',
                mode: 'vertical',
                speed: '500',
                captions: false,
                pager: false,
                controls: false,
                nextText: 'Next',
                prevText: 'Prev',
                auto: true,
                autoHover: true,
                pause: 3000
            });
        });
    }
    if (window.addEventListener) window.addEventListener('load', downloadJSAtOnload, false);
    else if (window.attachEvent) window.attachEvent('onload', downloadJSAtOnload);
    else window.onload = downloadJSAtOnload;
</script>

The error generated is "Uncaught ReferenceError: $ is not defined ".

The strange is that everything works perfectly (slideshow, lightbox, ...) in lots of browsers and verions. Just in IE8 and Safari 4 an alert is showed to the user.

Community
  • 1
  • 1
Marco Panichi
  • 1,068
  • 1
  • 18
  • 31
  • Maybe they are too slow to actually load the jquery files after the script elements are created before they get to the first $? why not just declare them in script tags in the head or something? – d'alar'cop Apr 11 '13 at 12:50
  • 1
    You're asynchronously loading the scripts... There is no way jQuery'd be loaded by the time the `$` call executes. – Fabrício Matté Apr 11 '13 at 12:50
  • At the moment you are trying to access `$`, the scripts (including jQuery) have not been loaded yet. – Felix Kling Apr 11 '13 at 12:50
  • http://requirejs.org/ – Ram Apr 11 '13 at 12:51
  • You confirmed my fears. But how can I solve the problem? I don't want to use script tags @d'alar'cop because I'm trying to follow [Google suggestion](https://developers.google.com/speed/docs/best-practices/payload?hl=it#DeferLoadingJS) to defer the load of javascript – Marco Panichi Apr 11 '13 at 12:54

5 Answers5

2

Since you are dynamically adding the JS libraries to the document, you will required a callback function after the scripts are loaded in order to initialize the bxSlider. Ideally the callback should be called after the bxSlider has loaded.

element.setAttribute("type","text/javascript");
element.onload = callBackFunction;
document.body.appendChild(element);

var callBackFunction() {
            $('#mainslide .bxslider').bxSlider({
                slideWidth: '960',
                mode: 'vertical',
                speed: '500',
                captions: false,
                pager: false,
                controls: false,
                nextText: 'Next',
                prevText: 'Prev',
                auto: true,
                autoHover: true,
                pause: 3000
            });
}
msapkal
  • 8,268
  • 2
  • 31
  • 48
  • I don't think the scripts will necessarily be loaded in order. You would have to listen for every script and run the callback once all of them are loaded. – Felix Kling Apr 11 '13 at 13:01
  • Thank you very much for your answer Mahesh, I'll try to adapt your code to my needs – Marco Panichi Apr 11 '13 at 19:29
0

Those browsers may well be too slow to actually load the jQuery files after the script elements are created in the body before they get to the first $.

Why not declare them in script tags in the head of your document?

d'alar'cop
  • 2,357
  • 1
  • 14
  • 18
  • 1
    *"Those browsers may well be too slow"*: It has nothing to do with the browser speed. Even if the scripts would be loaded instantly, they wouldn't be evaluated until the current script execution terminated. JavaScript is single threaded and the engine does not stop a currently running execution (to execute other code). – Felix Kling Apr 11 '13 at 12:54
  • @FelixKling Well OP reports that it works in other browsers. Perhaps your comment about 'evaluation' differs between implementations - indeed all that is needed is that the JS functions etc be available when they are called right? – d'alar'cop Apr 11 '13 at 12:56
  • I don't know. I cannot imagine how this code could work in any browser, unless jQuery is included in any other way (beforehand) which, for some reason, fails in IE and Safari. – Felix Kling Apr 11 '13 at 12:58
  • @FelixKling Yes, good point. worth some investigation I think. Anyway, based on the info from the OP (which as we all know, is often sketchy) this is what seemed to me to be the "answer" regardless. – d'alar'cop Apr 11 '13 at 13:03
0

You add your scripts to the document body (they should really be in the head) but don't wait for them to be downloaded and executed before accessing jQuery in $(document).ready(...) so I would expect this to fail at least some of the time. You need to attach to the document onready event without using jQuery.

Tim Rogers
  • 21,297
  • 6
  • 52
  • 68
0

separate import the jquery example

<script src="http://www.---.com/include/jquery-1.8.3.min.js"> </ script>
0

Take your function out of document.ready() and add it to the end of your jQuery.js file. That way it will only be run after jQuery loads.

bobs12
  • 154
  • 6