Thursday, July 5, 2012

Transforms for *.config Files, Part 3: Other Config Files


In Part 1 of this series, we ran through an overview of transforms and how we can leverage then at build time rather than the default publish/deploy time.  In Part 2, we went over how you can add your own transform to Web.config in addition to the Web.Debug.config and Web.Release.config.  In Part 3 of this series, we are going to see how we can leverage transforms for other configuration files – not just Web.config.

What Other Config Files? Maybe Log4Net.config?
When you are working on a web project, you cannot help but use Web.config as it has essential elements needed for every web-based application.  One thing that we do at my work is set up logging for every application.  We use log4net as our logger of choice and we choose to keep the details of the log configuration in a separate file from Web.config.  In the Web.config:
<add key="log4Net.ConfigurationFile" value="log4net.config" />
Which tells log4net to get its configuration from “log4net.config”.

Add a properly formatted log4net.config file to the project (RtClick Project >> Add >> New Item >> C# >> Data >> XML).  Copy and paste this new file and rename the copy to log4net.BASE.config.  You should now have 2 files in your project that look like this:
image

Create the Transformation Files!
What we want to do now is generate the transformation files for our Solution Configurations (like we have for our Web.Config).  If you recall, for the Web.config files, we simply RtClick’ed on the Web.config file and we had a context menu item called “Add Config Transforms (it’s greyed out at this point because we have all the transforms for all of our solution configurations):
image 

So to create the transforms, we should just do the same thing, right?  Well, when we RtClick the log4net.config file, our context menu does not have the “Add Config Transforms” menu item!:
image

It seems that Microsoft assumed that transforms were only good for Web.config!  There is a Visual Studio Add-on that will allow you to do this easily, but before we introduce this product, let’s first do it the “Hard Way”…

Adding Config Transforms Manually (The “Hard Way”)
Let’s say in our log4net.config file we are going to log to a database and in our BASE config file we have the connection string pointing to our Dev SQL server.  You might see a config “connectionString” line that looks like this (lots of other keys have been removed):

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<log4net>
. . .
<appender name="AdoNetAppender_SqlServer" type="log4net.Appender.AdoNetAppender">
. . .
<connectionString name="Log4NetConString" value= "Data Source=otis-web02\otisdevsql;Initial Catalog=WebAppsLog;Persist Security Info=True;User ID=Logger;Password=L0gg3r02;MultipleActiveResultSets=True;" />
. . .
</appender>
. . .
</log4net>
</configuration>




We now want to create a log4net.Release.config that will transform this line to  point to the Production SQL Server.  We will add a new XML file to our project and name the file log4net.Release.config and place the following content in the file:


<?xml version="1.0" ?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<log4net>
<appender name="AdoNetAppender_SqlServer" type="log4net.Appender.AdoNetAppender">
<connectionString name="Log4NetConString" value= "Data Source=ReleaseSQLServer;Initial Catalog=WebAppsLog;Persist Security Info=True;User ID=LogUser;Password=xyz123;MultipleActiveResultSets=True;" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
</appender>
</log4net>
</configuration>


Remember that transforms are, by default, only associated with Web.config files.  So even when you Publish your project, MSBuild will ignore your log4net.Release.config file and will not automatically apply the transform.  You must TELL MSBuild to do this.  From Part 1 of this series, we can open the (Project).wpp.targets file and add the step for MSBuild to transform the log4net.BASE.config file using the log4net.


<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="TransformXml"
AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />

<Target Name="TransformWebBASEConfig" BeforeTargets="BeforeBuild" >
<TransformXml Source="$(ProjectDir)Web.BASE.config"
Transform="$(ProjectDir)Web.$(Configuration).config"
Destination="$(ProjectDir)Web.config" />
</Target>

<Target Name="TransformLog4netBASEConfig" BeforeTargets="BeforeBuild" >
<TransformXml Source="$(ProjectDir)log4net.BASE.config"
Transform="$(ProjectDir)log4net.$(Configuration).config"
Destination="$(ProjectDir)log4net.config" />
</Target>
</Project>


Now, if we Build the project (using the Release configuration), we get the desired log4net.config line with the Connection string set to ReleaseSQLServer:


<connectionString name="Log4NetConString" value="Data Source=ReleaseSQLServer;Initial Catalog=WebAppsLog;Persist Security Info=True;User ID=LogUser;Password=xyz123;MultipleActiveResultSets=True;" />


Objective Complete: Transforming a non-Web.config Config File
Ok, so we accomplished the main objective of this post which is to make a config file other than Web.config do a transform when we build the project.  You can follow the same technique to build your additional transforms (Debug, JDRLocal, etc.).  For the remainder of this post, let’s dig just a little bit deeper.


In Part 4 of this series, I’ll just show you how to format your non-Web.config configuration files so that they appear in the Solution Explorer under the parent configuration file.


Transforms for ANY .config file: 5 Part Series
Part 1: Transforms on Build
This first part does an overview of the default behavior of transforms. It then shows how you can plug into the MSBuild process and apply your transforms at Build time rather than the default publish time.

Part 2: New Config Profiles
The second part of the series shows how to create a new solution configuration and the nuances of what happens behind the scenes (in case you want to delete a configuration). It also discusses having a local development configuration specific to an individual developer.

Part 3: Other Config Files
The third part discusses how to add a configuration for another element of the application (using log4net as an example). This post shows how this process differs from the handling of Web.config.

Part 4: Making the transforms look nice
This fourth part is just a quickie to show how you can manually make your other configuration files sit under their respective parent files.

Part 5: SlowCheetah & Advanced
This fifth and final post is where I try to bring together all of the elements from the previous posts together and introduce a Visual Studio extension that allows much of the previous posts to be accomplished easily and automatically.

Transforms for *.config Files, Part 2: New Config Profiles

Part 1 of this series focused on how to use the default transform profiles and having those profiles applied when you BUILD you application instead of the default time when you PUBLISH your application.  Part 2 of this series will discuss adding NEW configuration profiles.

Remember, the default configuration profiles created when you build your project are “Debug and Release” and can be seen on the menu bar:
image

And the transform files can be seen under Web.config in the Solution Explorer:
image

If we are working with a team and we have multiple deployment (publish) environments (QA – PROD), then we may use the Debug for the QA environment and the Release for the PROD environment.  But I submit that you probably want to re-name your transforms to match the environment they belong to (rename Debug to QA and Release to PROD, etc.)  But for this blog, I want to make a new configuration for my local machine which I will call: JDRLocal (Not just Local because other developers on the team may want to create their OWN configurations that are different than mine – for instance, I am going to point the database to MY local database server).

Create the new Configuration
The last option on the drop-down is “Configuration Manager …”, Select this option and the Configuration Manager will be displayed. On the “Active solution configuration”, there is a drop down that shows you the solution configuration that you already have and an option for New and Edit.  Select the New option:
image

A “New Solution Configuration” dialog box appears.  Type in the name of your new configuration, you can get a head start on the configuration options by selecting an existing configuration settings.  By default, the “Create new project configurations” is set.  Now press “OK” to create the new configuration:
image

Now our new solution configuration was created.  But it’s important to understand that not only was a solution configuration created, but for each project in our solution, a new configuration with the same name was created.  In this example, we only see 1 project, but if we have 6 projects, they would be listed on this screen and each project would have the new configuration “JDRLocal” created for it.  Now close this window.
image

Where is the Transform?
So now, if we look at the drop-down on the menu bar, we can see our new configuration:
image

But the main reason for creating this configuration was so that we could make a transform file for it.  But if you look in the Solution Explorer, you will see that there is still just the Debug and Release Web.*.config files.  How do we get our new transform: Web.JDRLocal.config?

Now that we created the new configuration, there is an option on the Web.config context menu.  RtClick on Web.config and you will see an option to “Add Config Transforms”.  Select this option:
image

Magically, you will see the new transform (Web.JDRLocal.config) appear:
image

You can now modify this transform file to modify your Web.BASE.Config and create a new Web.Config based on your setting for JDRLocal.  When you select this configuration and select “Build” or “Run”, based on the changes from Part 1 of this series, the transforms will be applied and the newly created Web.config will be in effect when you run the program.

How to UNDO a Configuration!
Let’s say you want to remove one of these configurations.  That should be easy, right?  I mean creating the configuration was easy enough, why should the delete be any harder?  Well, it is slightly harder.  If you recall, I mentioned earlier in the Create portion of this posting that not only does the create routine make a solution configuration, but it also makes a project configuration for each project in your solution.  This is important to understand.  Because, while creating a solution configuration automatically creates project configurations, deleting a solution configuration does not automatically remove the project configurations.

To delete the solution configuration, from the configuration drop-down on the menu, select “Configuration Manager …” again and choose “Edit”:
image

In the “Edit Solution Configurations” dialog box, select the configuration you wish to delete and click the “Remove” button.  The configuration is removed from the list, now select “Close”.
image

At this point, you would think that the configuration has been removed completely.  If you look at the drop-down on the Configuration Manager screen, you will see that the configuration has been removed. 
image

However, if you look at the configuration drop-down for each of the Projects in your solution, you will find that the configuration still exists for each project!
image

For each of the projects in your solution, you must select “Edit” from the drop-down list.  You will get an “Edit Project Configurations” dialog box very similar to the “Edit Solution Configurations” dialog box.  You must select the configuration from the list and click “Remove” for each of your project in order to completely remove the configuration from your solution and all project in the solution.

In Part 3 of this blog series, we will discuss how we can apply transforms to other configuration files – not just Web.config.

Transforms for ANY .config file: 5 Part Series
Part 1: Transforms on Build
This first part does an overview of the default behavior of transforms. It then shows how you can plug into the MSBuild process and apply your transforms at Build time rather than the default publish time.

Part 2: New Config Profiles
The second part of the series shows how to create a new solution configuration and the nuances of what happens behind the scenes (in case you want to delete a configuration). It also discusses having a local development configuration specific to an individual developer.

Part 3: Other Config Files
The third part discusses how to add a configuration for another element of the application (using log4net as an example). This post shows how this process differs from the handling of Web.config.

Part 4: Making the transforms look nice
This fourth part is just a quickie to show how you can manually make your other configuration files sit under their respective parent files.

Part 5: SlowCheetah & Advanced
This fifth and final post is where I try to bring together all of the elements from the previous posts together and introduce a Visual Studio extension that allows much of the previous posts to be accomplished easily and automatically.

Transforms for *.config Files, Part 1: Transform on Build

Part 1: Transform on Build
This first installment on Transforms will focus on what exactly transforms are and what their default behavior is and how to make them more useful in your day-to-day development by making them transform during the BUILD process rather than the deployment.

Default Transforms in VS2010 – MVC3 Project Template (and other templates)
2 Default Solution Configurations: Debug & Release
2 Pre-Built Transforms (Debug & Release) + 1 Default Web.config

clip_image002clip_image004

The given Web.config file by default has debugging turned on (debug=”true”):

<system.web>
<compilation debug="true" targetFramework="4.0">
. . .
</compilation>
</system.web>

The “Web.Debug.config” transform does nothing; the “Web.Release.config” transform has this line:


<system.web>
<compilation xdt:Transform="RemoveAttributes(debug)" />
</system.web>


This says:
Find the “compilation” tag and remove the attribute called “debug”. Which means the transformed config file will look like this:


<system.web>
<compilation targetFramework="4.0">
. . .
</compilation>
</system.web>



Most Common Transform: Connection Strings

Web.config might have:



<connectionStrings>
<add name="MyDB"
connectionString="Data Source=TestSvr;Initial Catalog=MyTestDB;Integrated Security=True" />
</connectionStrings>


Web.Release.config transform might have:


<connectionStrings> 
<add name="MyDB"
connectionString="Data Source=ReleaseSvr;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>



Web.config AFTER transform:


<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSvr;Initial Catalog=MyReleaseDB;Integrated Security=True" />
</connectionStrings>


I. Transforms Only Performed On Publish (By Default as a step in the MSBuild Process)
   a. This means that you cannot “test” a transform unless you “test” a publish

II. What if you could make a transform happen earlier – like when you BUILD the solution?
   a. You could then TEST that a transform worked
   b. You could create your own LOCAL transforms

Making a transform happen when you BUILD a solution
Method 1: Modify the Project
RtClick >> Unload project, then RtClick >> Edit *.csproj
Scroll to commented section:



<!-- To modify your build process, add your task inside one of the targets below and
uncomment it. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target> -->


Uncommented the “BeforeBuild” command and inserted the following TransformXml command:


<!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
Other similar extension points exist, see Microsoft.Common.targets. -->
<Target Name="BeforeBuild">
<TransformXml Source="Web.config" Transform="Web.$(Configuration).config" Destination="Web.Transform.config" />
</Target>
<!--
<Target Name="AfterBuild">
</Target> -->


Save, Close, then RtClick >> Reload project & Build. “Show All Files” and you should see “Web.Transform.config” – This file will have the “debug=’true’” removed from the “compilation” tag.

To see what MSBuild is doing:
Tools >> Options >> Projects and Solutions >> Build and Run >> MSBuild project build output verbosity
Normal:
BeforeBuild:
   Transforming Source File: Web.config
   Applying Transform File: Web.Release.config
   Output File: Web.Transform.config
Transformation succeeded


Detailed:
Target "BeforeBuild" in project "c:\projects\applications\MVC3ConfigTest\MVC3ConfigTest\MVC3ConfigTest.csproj" (target "Build" depends on it):
   Task "TransformXml"
      Transforming Source File: Web.config
      Applying Transform File: Web.Release.config
      Executing RemoveAttributes (transform line 18, 18)
         on /configuration/system.web/compilation
      Applying to 'compilation' element (source line 20, 6)
      Removed 'debug' attribute
      Removed 1 attributes
      Done executing RemoveAttributes
      Output File: Web.Transform.config
      Transformation succeeded


Diagnostic:
Target "BeforeBuild: (TargetId:3)" in project "c:\projects\applications\MVC3ConfigTest\MVC3ConfigTest\MVC3ConfigTest.csproj" (target "Build" depends on it):
   Task "TransformXml" (TaskId:4)
      Transforming Source File: Web.config (TaskId:4)
      Applying Transform File: Web.Release.config (TaskId:4)
      Executing RemoveAttributes (transform line 18, 18) (TaskId:4)
         on /configuration/system.web/compilation (TaskId:4)
      Applying to 'compilation' element (source line 20, 6) (TaskId:4)
      Removed 'debug' attribute (TaskId:4)
      Removed 1 attributes (TaskId:4)
      Done executing RemoveAttributes (TaskId:4)
      Output File: Web.Transform.config (TaskId:4)
      Transformation succeeded (TaskId:4)


Need Web.Transform.config to be Web.config, Solution: Web.BASE.config
Web.Transform.config is ok for visually seeing what your transforms are doing, but to actually run your project with the transformed config file, you need the transformed file to be Web.config and in your project folder. But you do not want to overwrite you original Web.config. To accomplish this, copy & paste your Web.config file into your project and name the copied file Web.BASE.config (if you get Debug.BASE and Release.BASE files also, remove them).

To apply the transform to Web.BASE.config and have the result written to Web.config, edit the project and change the TransformXml line to read:



<Target Name="BeforeBuild"> 
<TransformXml Source="Web.BASE.config" Transform="Web.$(Configuration).config" Destination="Web.config" />
</Target>


Save, Close, Reload Project & Build (with Normal MSBuild output verbosity), result:
BeforeBuild:
   Transforming Source File: Web.BASE.config
   Applying Transform File: Web.Release.config
   Output File: Web.config
   Transformation succeeded


MSBuild used Web.BASE.config as the starting file, then applied the transforms in our currently selected configuration (Release) and wrote the results to Web.config. If we now RUN the code, it will use our newly created Web.config settings. So we can easily test the program in BOTH Debug AND Release modes (or any other configuration we might create).

Method 2: (Project).wpp.targets
WPP = Web Publish Pipeline (another name for the MSBuild process)
Revert the *.csproj file back to is original (commented status – no TransformXml line)
RtClick Project >> Add New Item >> Visual C# >> Data >> XML File
Name it: (Project).wpp.targets

In this file add the following:



<?xml version="1.0" encoding="utf-8" ?> 
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="TransformXml" AssemblyFile= "$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="TransformWebBASEConfig" BeforeTargets="BeforeBuild" >
<TransformXml Source="$(ProjectDir)Web.BASE.config" Transform="$(ProjectDir)Web.$(Configuration).config" Destination="$(ProjectDir)Web.config" />
</Target>
</Project>


Save, Close & Build (with Normal Verbosity) and you should see:
TransformWebBASEConfig:
   Transforming Source File:
c:\projects\applications\MVC3ConfigTest\MVC3ConfigTest\Web.BASE.config
   Applying Transform File: c:\projects\applications\MVC3ConfigTest\MVC3ConfigTest\Web.Release.config
   Output File: c:\projects\applications\MVC3ConfigTest\MVC3ConfigTest\Web.config
   Transformation succeeded


If you turn on Detailed verbosity, you can see the following relevant lines:
WebPublishPipelineCustomizeTargetFile = c:\projects\applications\MVC3ConfigTest\MVC3ConfigTest\MVC3ConfigTest.wpp.targets
. . .
Target "TransformWebBASEConfig: (TargetId:3)" in file "c:\projects\applications\MVC3ConfigTest\MVC3ConfigTest\MVC3ConfigTest.wpp.targets" from project "c:\projects\applications\MVC3ConfigTest\MVC3ConfigTest\MVC3ConfigTest.csproj" (target "BeforeBuild" depends on it):
   Task "TransformXml" (TaskId:4)
   Transforming Source File: c:\projects\applications\MVC3ConfigTest\MVC3ConfigTest\Web.BASE.config (TaskId:4)
   Applying Transform File: c:\projects\applications\MVC3ConfigTest\MVC3ConfigTest\Web.Release.config (TaskId:4)
   Executing RemoveAttributes (transform line 18, 18) (TaskId:4)
      on /configuration/system.web/compilation (TaskId:4)
   Applying to 'compilation' element (source line 20, 6) (TaskId:4)
   Removed 'debug' attribute (TaskId:4)
   Removed 1 attributes (TaskId:4)
   Done executing RemoveAttributes (TaskId:4)
   Output File: c:\projects\applications\MVC3ConfigTest\MVC3ConfigTest\Web.config (TaskId:4)
   Transformation succeeded (TaskId:4)
   Done executing task "TransformXml". (TaskId:4)
   Done building target "TransformWebBASEConfig" in project   "MVC3ConfigTest.csproj".: (TargetId:3)


Part 2 of this series will making NEW configuration profiles and incorporating them into your build process.


Transforms for ANY .config file: 5 Part Series
Part 1: Transforms on Build
This first part does an overview of the default behavior of transforms.  It then shows how you can plug into the MSBuild process and apply your transforms at Build time rather than the default publish time.

Part 2: New Config Profiles
The second part of the series shows how to create a new solution configuration and the nuances of what happens behind the scenes (in case you want to delete a configuration). It also discusses having a local development configuration specific to an individual developer.

Part 3: Other Config Files
The third part discusses how to add a configuration for another element of the application (using log4net as an example).  This post shows how this process differs from the handling of Web.config.

Part 4: Making the transforms look nice
This fourth part is just a quickie to show how you can manually make your other configuration files sit under their respective parent files.

Part 5: SlowCheetah & Advanced
This fifth and final post is where I try to bring together all of the elements from the previous posts together and introduce a Visual Studio extension that allows much of the previous posts to be accomplished easily and automatically.

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.