Monday, June 11, 2012

Injecting a private jQuery, Part 4: AMD Asynchronous Module Definition

Ok...  What is AMD?  Let me start by saying I just learned about this yesterday, and just barely started understanding it about 2 hours ago.  So I am NO expert on this subject.  I can tell you that AMD (which in my mind originally stood for Advance Micro Devices - that Intel competitor) will not start to mean Asynchronous Module Definition.

I'll take a stab at the meaning now...  AMD means defining your module in such a way that it can be safely loaded (along with its dependencies) asynchronously - without exposing itself globally and clobbering the global namespace (namely window.?).

Again, if you look at jQuery (which is the focus of this series) and peer into the jQuery source, at its very start, it is an anonymous function call that starts the ball rolling.  That anonymous function call then creates the private variable jQuery which is the library of jQuery functions.  At the end of the anonymous function, the private variable is then exposed to the browser by attaching it to BOTH window.jQuery and window.$ (when referencing these variables in your JavaScript code, you will typically not reference the "window." part and just call jQuery and/or $).  But what if there were a way to gain access to that variable WITHOUT attaching it to the global "window." namespace?  That is the essence of AMD and a new family of products known as "AMD Loaders".

An AMD Loader basically instantiates an AMD compliant module and passes the reference of that module to a function - never involving the global namespace.  Making a module AMD compliant is really nothing more than calling a special function on the AMD Loader called "define" which gives the module a "name" and returns the module as an object.  In fact, you may not know this, but jQuery v1.7 is actually an AMD compliant module.  Again, peering into the source code, we find this:

// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;

// Expose jQuery as an AMD module, but only for AMD loaders that
// understand the issues with loading multiple versions of jQuery
// in a page that all might call define(). The loader will indicate
// they have special allowances for multiple jQuery versions by
// specifying define.amd.jQuery = true. Register as a named module,
// since jQuery can be concatenated with other files that may use define,
// but not use a proper concatenation script that understands anonymous
// AMD modules. A named AMD is safest and most robust way to register.
// Lowercase jquery is used because AMD module names are derived from
// file names, and jQuery is normally delivered in a lowercase file name.
// Do this after creating the global so that if an AMD module wants to call
// noConflict to hide this version of jQuery, it will work.
if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
 define( "jquery", [], function () { return jQuery; } );
}

Right after the private jQuery variable is hooked into the global namespace (now starting to be "bad practice"), the source checks for the existence of the "define" function and, if found (along with some other conditions), will call the define function with "jquery" as the common "module name" and returning the private jQuery variable.

OK...  so this is a little hypocritical, right?  I mean, where did the "define" method/function come from?  It must be in the Global Namespace, right?  Well...  Ok, I guess we have to start somewhere, so I'll let that one go.  In fact, if you read some of the documentation on the AMD loaders websites, you can see that they hope for the browsers to adopt a new JavaScript that will have an actual definition for JavaScript Modules so that the global namespace is not needed.  Here is a good initial explanation:
http://unscriptable.com/2011/03/30/curl-js-yet-another-amd-loader/

So where are the AMD loaders at this time?  There are several right now:
http://requirejs.org/
https://github.com/unscriptable/curl
http://bdframework.org/bdLoad/

Now, these are NOT to be confused with asynchronous "loaders".  The "loadJS" function I wrote in Part 3 of this series was an example of an asynchronous loader.  There are more sophisticated loader libraries out there, one of the most prevalent is LABjs:
http://labjs.com/

The AMD loader that I have been researching is RequireJS.  I am not going to try and do a tutorial on RequireJS at this point because I have not done anything practical with it up to this point.  However, I will write a little of what I have learned and how it pertains to this series of articles.

Here are a couple of points to consider:

1) Although jQuery v1.7 is now "AMD Compliant", as we saw above, it is still adding to the global namespace so that it remains backwards compatible.

2) RequireJS has some "special jQuery" coding to recognize if you load an earlier version of jQuery (pre-1.7).  Although I could not find this "special code" as described by this blog post (but I encourage the reading of the blog anyway):
http://www.bennadel.com/blog/2287-Using-jQuery-As-A-Named-Module-In-RequireJS.htm

3) The RequireJS library has a lot of documentation on including jQuery with RequireJS.  The most prevalent one uses a combined requirejs-jquery.js file which is jQuery combined with the RequiredJD library.  I would avoid this structure.  There is a good beginner blog about combining RequireJS with jQuery here:
http://www.bennadel.com/blog/2275-Using-RequireJS-For-Asynchronous-Script-Loading-And-JavaScript-Dependency-Management.htm

4) RequireJS includes a "optimizer" utility for combining multiple scripts together and minify-ing them.  At this point I am ignoring that part of RequireJS.

5) In today's jQuery plugin world, plugins are not actually "modules".  They simply latch on to the global jQuery namespace object and attach themselves there.  This is obviously not very "AMD Compliant".  So RequireJS has many different ways to handle this (order! & use plugins are often sited), but the current "flavor" for handling jQuery plugin dependencies is using RequireJS 2.0 and it's new "shims" configuration.

Here are some other references on jQuery, AMD and RequireJS:

https://github.com/amdjs/amdjs-api/wiki/jQuery-and-AMD
Wiki page on jQuery and AMD.

http://bugs.jquery.com/ticket/10545
This is a bug report/request for jQuery to stop attaching itself to the global namespace and a discussion by the developer of RequireJS as a response.  A few of the links in this article are also interesting reading.

http://addyosmani.com/writing-modular-js/
An excellent article on the proposed new version of JavaScript (ES Harmony) and the current state of AMD.

http://blog.errorception.com/2012/01/writing-quality-third-party-js-part-1.html
Excellent post on writing 3rd-Party JavaScript widgets.

http://alexmarandon.com/articles/web_widget_jquery/
Excellent practical implementation of jQuery in a widget situation.  However, it does not show how to load jQuery plugins that your widget code may depend on.  The author suggests that he simply includes the minified plugin code WITH his script.  That is, once jQuery is loaded, he does NOT load the plugin, but rather includes the plugin minified code in the onload of jQuery so that it executes right there.

http://www.angrycoding.com/2011/09/managing-dependencies-with-requirejs.html
More dependency management for jQuery and RequireJS.

Injecting a private jQuery, Part 3: jQuery and Plugins Asynchronously

Ok...  Part 3 of these blog posts and we are FINALLY going to look at jQuery being "injected".

First, what does 'Injection" mean?

If you look up "JavaScript Injection", you will see a lot of negative posts surrounding malicious code being "injected" into a page or cross-site scripting and how to protect against it.  However what I am talking about and, it you want to Google about it, you might try Dynamically loaded JavaScript.

To understand this, let's first understand what happens when we load jQuery and the UI in the "classic" code.  lets say we have the following code in our html file:


<link type="text/css" href="css/themename/jquery-ui-1.8.21.custom.css" rel="Stylesheet" /> 
<script type="text/javascript" src="js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.21.custom.min.js"></script>


This code is obvious, we load a css, then we load the jQuery library, then we load the UI plug-in.  Because this code is directly entered into our html, it will load synchronously - that is one-at-a-time.  The jQuery library will not load/run until the css is finished and (more importantly), the ui library will not load/run until the jQuery library in finished loading/running.

However, in today's ever complex web 2.0 (or greater) applications, we could be loading tons of JavaScript files and libraries.  Some with dependencies (like jQuery and jQuery-ui) and some with no dependencies. Combine those JavaScript files with CSS files and you could have a mighty long load time as each file is loaded and executed sequentially and synchronously.  So your user could be waiting a long time before they are given control over the page.  How can we lessen that "wait" time?

Enter scripting injection or dynamically loaded scripts.  Basically what happens is that through JavaScript, you ask the DOM to create a script element for you and then you ask the DOM to add that script to the "head" or "body" section of your page.  Here is a sample:

  //Create a 'script' element 
  var scrptE = document.createElement("script");

  // Set it's 'type' attribute 
  scrptE.setAttribute("type", "text/javascript");

  // Set it's 'language' attribute
  scrptE.setAttribute("language", "JavaScript");

  // Set it's 'src' attribute
  scrptE.setAttribute("src", "myjsfile.js");

  // Now add this new element to the head tag
  document.getElementsByTagName("head")[0].appendChild(scrptE);

Very straight forward...  Ask the DOM for a new "script" element, set the element's "type", "language" and (most importantly) the "src" attributes, then append the element to the "head" of the document.  What happens then is that the JavaScript file (myjsfile.js) will load asynchronously - meaning that if you were to add several JavaScript files this way, they would all start loading at the same time - not sequentially!

So, if we were to wrap this code in a function like (ignore the callback function for now):

   function loadJS(jsFile, callback) {
     var scrptE = document.createElement("script");

     // Set it's 'type' attribute 
     scrptE.setAttribute("type", "text/javascript");

     // Set it's 'language' attribute
     scrptE.setAttribute("language", "JavaScript");

     // Set it's 'src' attribute
     scrptE.setAttribute("src", jsFile);

     // Now add this new element to the head tag
     document.getElementsByTagName("head")[0].appendChild(scrptE);
   }


We could then load our non-dependent JavaScript files like this:

   LoadJS('scripts\file1.js', null);
   LoadJS('scripts\file2.js', null);
   LoadJS('scripts\file3.js', null);

All 3 files would load at the same time. So why can we only do this with "non-dependent" files? Because we have no idea in what order these files will finish loading. Although we have called the files in the 1, 2, 3 order, they may very well complete in 3, 1, 2 order.  So this scenario:

   loadJS('scripts/jquery-1.4.4.min.js', null);
   loadJS('scripts/jquery-ui-1.8.21.custom.min.js', null);

Would not work - because it would be possible for the ui library to finish loading (and start executing) before jQuery, and, as I documented in Part 2, there is a dependency between these two JavaScript files.

Before we discuss how to deal with dependencies, lets first look at the more "generic" issue concerning: what if I want to run some code after my JavaScript loads?

Enter "onload" and the "onreadystatechange" event.  I wont go into detail here, but most modern browsers (chrome, firefox) have an event on the script element called "onload" that fires once the script is fully loaded. Of course IE does NOT have this event.  Instead, IE fires a series of events as the script is loading.  the event that fires is called "onreadystatechange" and when this event fires, you check for the readyState property which will eventually end with a state of "loaded" or "complete" (depending on whether the JavaScript was already cached - and sometimes the event will fire in BOTH conditions).  Again, you can Google this in more detail if you want, but this explanation should be enough to understand this additional piece of code that we can add to our loadJS() function.  Before appending the script tag to the DOM, we add this additional piece of code:

   // Add the jQuery script reference
   var scriptAdded = false;
   scrptE.onload = scrptE.onreadystatechange = function () {
      if (!scriptAdded && (!this.readyState ||
                            this.readyState == 'loaded' || 
                            this.readyState == 'complete')) {
         scriptAdded = true;

         // Call callback method to confirm the loading of the script file
         callback();
      };
   };

By adding these lines, we create a cross-browser generic way to know when our script finishes loading so that we can then execute some code based on that fact.  Note the "callback" function is called when the script completes its loading.  The "scriptAdded" variable is used to make sure that IE does not fire the callback method more than once if onreadystatechange fires for BOTH loaded and complete states.

We can now load JavaScript dependencies like this:

   loadJS('scripts/jquery-1.4.4.min.js', function() {
      loadJS('scripts/jquery-ui-1.8.21.custom.min.js', null);
   });

This code snippet will load the jQuery library and, when its finished loading, it will load the jQuery ui library.




Sunday, June 10, 2012

Injecting a private jQuery, Part 2: Plugins and noConflict()

This is my continuing blog about injecting jQuery into a page...  Although I still haven't gotten to the inections part!

In part 1, I discussed jQuery's noConflict() method for using jQuery with other libraries (like prototype) and different versions of jQuery.

In this post, I want to simply make 1 point clear:
When you include a jQuery library, it attaches itself to the current global window.jQuery instance.

So, let's first look at the typical scenario where you load the jQuery library and then the jQuery UI plugin.  From the jQuery UI website:
http://jqueryui.com/docs/Getting_Started

<link type="text/css" href="css/themename/jquery-ui-1.8.21.custom.css" rel="Stylesheet" /> 
<script type="text/javascript" src="js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.21.custom.min.js"></script>

Here we load the UI's CSS file, then jQuery, then the UI library.  Before we look at jQuery UI's "hook" into jQuery, let's take a baby step and look at section from jQuery's on how to author a plugin:
http://docs.jquery.com/Plugins/Authoring
Getting Started

To write a jQuery plugin, start by adding a new function property to the jQuery.fn object where the name of the property is the name of your plugin:

jQuery.fn.myPlugin = function() {

  // Do your awesome plugin stuff here

};


But wait! Where's my awesome dollar sign that I know and love? It's still there, however to make sure that your plugin doesn't collide with other libraries that might use the dollar sign, it's a best practice to pass jQuery to an IIFE (Immediately Invoked Function Expression) that maps it to the dollar sign so it can't be overwritten by another library in the scope of its execution.

(function( $ ) {
  $.fn.myPlugin = function() {
  
    // Do your awesome plugin stuff here

  };
})( jQuery );


Ah, that's better. Now within that closure, we can use the dollar sign in place of jQuery as much as we like.

So you can see that when you author a plugin, the plugin expects the global jQuery (or rather the window.jQuery) variable to be set.

Now let's take a look at the jQuery UI code...  In particular, the jQuery UI core code from:
http://code.google.com/p/jquery-ui/downloads/detail?name=jquery-ui-1.7.3.zip

In jquery-ui.js  we will look at just the top of the code:
/*
 * jQuery UI 1.7.3
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI
 */
;jQuery.ui || (function($) {

var _remove = $.fn.remove,
 isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);

//Helper functions and ui object
$.ui = {
 version: "1.7.3",

And the bottom of the code:
})(jQuery);

Basically the top of the code says: If jQuery.ui is already defined, then skip the rest, otherwise, execute this anonymous function to add the jQuery.ui library to the global jQuery.  Then, you see that the global jQuery variable is passed into the anonymous function so that the "ui" library can be attached to it.

Again, the point of this post is to simply show that when loading a jQuery plug in, the plug will attach to whichever "jQuery" is the current global variable called "jQuery".  A secondary, but perhaps obvious point is that jQuery plugins must be loaded AFTER jQuery.

As I described in my previous post, the global jQuery variable and the ($) can be various versions of jQuery.

In Part 3 of this blog post, I will look at loading jQuery and jQuery plugins asynchronously.

Injecting a private jQuery, Part 1: noConflict()

So here's the situation: At my work, we have several programming "groups".  Some are working on skinning, some are working on applications and still others are working on maps.  Currently, I am on a groups building an application that needs a skin and may display a map...

Here's the rub.  Each group (app, skin, map) all want to use jQuery, but some want to use different versions.  In fact, each group wants to control their own version of jQuery so that they are not effected if one group decides to update their copy of jQuery it does not effect the other group.

At first glance, this sounds reasonable...  But...  How to keep all versions of jQuery separated?  When you initially load the jQuery javascript file, it calls an anonymous function:

(function( window, undefined ) {

// Use the correct document accordingly with window argument (sandbox)
var document = window.document,
 navigator = window.navigator,
 location = window.location;
var jQuery = (function() {

// Define a local copy of jQuery
var jQuery = function( selector, context ) {
  // The jQuery object is actually just the init constructor 'enhanced'
  return new jQuery.fn.init( selector, context, rootjQuery );
 },

 // Map over jQuery in case of overwrite
 _jQuery = window.jQuery,

 // Map over the $ in case of overwrite
 _$ = window.$,
...

Because we are in an anonymous function, the jQuery library is constructed in a variable PRIVATE to the anonymous function.  Besides this, let's look at a few more lines:

This existing window.jQuery & window.$ global variables are saved into private _jQuery and _$ variables.   The reason for the window.$ save is that it is common for a JavaScript library to load and expose itself as window.$.  The classic example typically given is the prototype library which also exposes itself as the window.$ variable.  So, if we loaded prototype, then loaded jQuery, jQuery would overwrite the $ variable and prototype would no longer be available.  However, by saving prototype (or whatever library is exposed by $), after we load jQuery, we can call the jQuery method .noConflict() which looks like this:
 noConflict: function( deep ) {
  if ( window.$ === jQuery ) {
   window.$ = _$;
  }

  if ( deep && window.jQuery === jQuery ) {
   window.jQuery = _jQuery;
  }

  return jQuery;
 },

We have some interesting code here...  Basically what happens is that when we call "noConflict()", the window.$ variable is restored back to its original state (prototype in our example).  The second piece of the code looks at the "deep" Boolean parameter and optionally restores jQuery back to its original state.  This was added a little later to the noConflict() method and was specifically added in the event that you have 2 different versions of jQuery being loaded.  Let's look at the classic examples:

So here is that classic example for restoring the $ variable as given by the jQuery website:
http://docs.jquery.com/Using_jQuery_with_Other_Libraries
 <html>
 <head>
   <script src="prototype.js"></script>
   <script src="jquery.js"></script>
   <script>
     jQuery.noConflict();
     
     // Use jQuery via jQuery(...)
     jQuery(document).ready(function(){
       jQuery("div").hide();
     });
     
     // Use Prototype with $(...), etc.
     $('someid').hide();
   </script>
 </head>
 <body></body>
 </html>

And where you want to use different versions of jQuery (using the .noConflict(true) call), I could not find an "official" example...  I did find a mention of it on:
http://api.jquery.com/jQuery.noConflict/
If necessary, we can free up the jQuery name as well by passing true as an argument to the method. This is rarely necessary, and if we must do this (for example, if we need to use multiple versions of the jQuery library on the same page), we need to consider that most plug-ins rely on the presence of the jQuery variable and may not operate correctly in this situation.
And here is a good blog on the subject:
http://blog.nemikor.com/2009/10/03/using-multiple-versions-of-jquery/

With the example:
<!-- load jQuery 1.1.3 -->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.1.3.js"></script>
<script type="text/javascript" src="jquery.dimensions.min.js"></script>

<!-- revert global jQuery and $ variables and store jQuery in a new variable -->
<script type="text/javascript">
var jQuery_1_1_3 = $.noConflict(true);
</script>

<!-- load jQuery 1.3.2 -->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.3.2.js"></script>

<!-- revert global jQuery and $ variables and store jQuery in a new variable -->
<script type="text/javascript">
var jQuery_1_3_2 = $.noConflict(true);
</script>

The problem with this example is that after all this script runs, the $ and jQuery globals would be left in an undefined state (if nothing was loaded into them before this code.

This is significant because often times you are not just loading jQuery, but several plugins as well.  The typical way that a plugin is installed is that it expects the global window.jQuery to exist and attaches itself to that global instance.

See my Part 2 blog for more information.