2

What I am doing

I am creating a distributable jQuery widget library which inserts an anchor on HTML page.

Issue

In 'MyWidget.prototype.Render' method (of JS), its giving me following error - "jQuery is not defined" However, its working fine in 'MyWidget.prototype.ResolveJqueryAndLoadAdditionalJsAndCss' method.

HTML Snippet

<html>
<head>
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
    <a href="http://yahoo.com">Anchor - by user code</a>

    <!-- Widget Script: Starts -->
    <script type="text/javascript" src="widget.js" ></script>
    <Script type="text/javascript"> 
        var customWidget = new MyWidget();
        customWidget.Render({ anchorText:'Hola!!!' });
    </script>
    <!-- Widget Script: Ends -->
</body>
</html>

JS Code(widget.js)

    var MyWidget = function() {
    // Localize jQuery variable
    var jQuery;
    // Load jQuery if not present
    if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.4.2') {
        var script_tag = document.createElement('script');
        script_tag.setAttribute("type","text/javascript");
        script_tag.setAttribute("src", "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js");
        if (script_tag.readyState) {
        script_tag.onreadystatechange = function () { // For old versions of IE
            if (this.readyState == 'complete' || this.readyState == 'loaded') {
                this.ResolveJqueryAndLoadAdditionalJsAndCss();
            }
        };
        } else {
            script_tag.onload = this.ResolveJqueryAndLoadAdditionalJsAndCss;
        }
        // Try to find the head, otherwise default to the documentElement
        (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
    } else {
        // The jQuery version on the window is the one we want to use
        jQuery = window.jQuery;
        this.ResolveJqueryAndLoadAdditionalJsAndCss();
    }
    };

MyWidget.prototype.ResolveJqueryAndLoadAdditionalJsAndCss = function() {
        // Restore $ and window.jQuery to their previous values and store the
        // new jQuery in our local jQuery variable
        jQuery = window.jQuery.noConflict(true);
        jQuery(document).ready(function($) {
            $.when(
                $.getScript( "http://www.jacklmoore.com/colorbox/jquery.colorbox.js" ),
                $.Deferred(function( deferred ){
                    $( deferred.resolve );
                })
            ).done(function(){ });
            // Loading Custom CSS
            var css_link = $("<link>", { rel: "stylesheet", type: "text/css", href: "https://raw.github.com/premasagar/cleanslate/master/cleanslate.css" });
            css_link.appendTo('head');
            css_link = $("<link>", { rel: "stylesheet", type: "text/css", href: "http://www.jacklmoore.com/colorbox/example4/colorbox.css" });
            css_link.appendTo('head');
            css_link = $("<link>", { rel: "stylesheet", type: "text/css", href: "widget.css" });
            css_link.appendTo('head');
        });
    };

MyWidget.prototype.Render = function(data){
        jQuery(document).ready(function($) {
            $('<a href="http://wikipedia.com" class="cleanslate custom widgetExternalPage">' + data.anchorText + '</a>').appendTo('body');
            $(".widgetExternalPage").colorbox({iframe:true, width:"80%", height:"80%"});
        });
    };
  • 1
    well i dont see you loading jquery anywhere in your code so maybe thats it? – Matt617 Jan 04 '14 at 13:55
  • its loaded dynamically by script in widget.js... Check out following code at line no 8 script_tag.setAttribute("src", "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"); Also, I have checked via inspector, its getting loaded correctly in browser – user3133397 Jan 04 '14 at 14:01
  • ah well thats an asyncronous load... the rest of your script keeps executing before JQuery loads. can you move it to your header in the HTML portion? if so that would be safer. if not there are other techniques for ensuring load. the easiest would be to use a settimeout (be careful this is not the most reliable, just the easiest) – Matt617 Jan 04 '14 at 14:25
  • Yes! Now, using console.log(), I can verify the same.... But, I can't ask user to put the script at header as it may degrade their page performance... Other than settimeout, what other options do I have? – user3133397 Jan 04 '14 at 14:46
  • @Matt617 I wrapped code of Render inside window.addEventListener("load", doStuff, true); and that seems to do the magic and ensures all required JS/CSS are loaded correctly. However, can you confirm if its a good practice to use "window.addEventListener" inside distributable widget library? – user3133397 Jan 04 '14 at 15:00
  • @Matt617 Now, 'colorbox()' which is present inside 'http://www.jacklmoore.com/colorbox/jquery.colorbox.js' isn't available. Any idea on how can we get around this? – user3133397 Jan 04 '14 at 15:25
  • window.addEventListener can get you in some trouble if people are using similar events or timing with multiple widgets on a screen but if you use unique keys you should be fine. – Matt617 Jan 04 '14 at 16:52
  • that link you send is "not found". – Matt617 Jan 04 '14 at 16:53
  • @matt617 sry for typo, correct url is http://www.jacklmoore.com/colorbox/jquery.colorbox.js . now, i'm not sure about what do you mean by unique key.... Can you please give some pointer or if there is any better alternative that i can use? – user3133397 Jan 04 '14 at 17:33
  • here is a good post about addEventListner http://stackoverflow.com/questions/6925146/best-practice-on-adding-event-listeners-javascript-html – Matt617 Jan 05 '14 at 03:42
  • also if your getting the not found its probably because its not loaded at the time you call it, again you can use a set timeout or another event listener for your code. this happens every time you load a new file... thats just how javascript works – Matt617 Jan 05 '14 at 03:43
  • @Matt617 I have created the fully functional plugin and would appreciate your comments on it - http://codereview.stackexchange.com/questions/38830/is-this-js-widget-written-correctly-and-production-ready – user3133397 Jan 08 '14 at 15:43

1 Answers1

-1

well, you are re-defining jQuery. Actually, you are re-declaring any variable is also re-setting the value of it. Here, you are setting the value of jQuery to undefined. You should not do this.

If you want, you can do it like:

var jQuery = jQuery || undefined;

This may help, good luck!

Ashish Kumar
  • 2,991
  • 3
  • 18
  • 27
  • no he isnt, he is declaring a new variable called jquery in local scope. I agree that is not a great pracitce (Call it something else) but he is not overwriting the global jQuery variable. – Matt617 Jan 08 '14 at 20:44