Nov
18
Posted by:
Ian Robinson
11/18/2011 12:20 PM
There have been some exciting changes made with respect to working with JavaScript in DNN 6.1 that give developers more flexibility and everyone faster sites. More importantly, the groundwork has now been laid to build an even better “client side story” for DotNetNuke in future versions.
However, there have been a few bumps on the road while making such significant changes in the framework, and I’d like to make sure everyone is aware of them and provide an opportunity for discussion in the comments.
First, let’s start with the history of jQuery and jQuery UI usage in DNN, and then we’ll talk about where we are now. Please, bear with me as we take a detailed historical journey.
DotNetNuke 5
DotNetNuke 5.0 introduced a new API method to allow for registration of jQuery. This has been the standard way to register jQuery in the core as well as third party modules ever since.
However, some module developers, wanting to still support older versions of DotNetNuke (e.g. 4.x), bypassed the public API and checked the internal flag (HttpContext.Current.Items("jquery_registered")) that denotes whether jQuery has been registered. This wasn’t/isn’t the only technique to support backwards compatibility though, Bruce Chapman has a nice bit of code on his blog that supports the same functionality without sneaking around the public API.
Another important point to note is that when DotNetNuke loads jQuery, it is always loaded in the <head> of the document. This is because jQuery is a framework-level dependency that needs to be loaded prior to any consuming JavaScript, such as script placed in a skin, a page header, registered by a third party module, etc.
DotNetNuke 6
The only real important thing to note is that DotNetNuke 6 introduced jQuery UI into the core framework. At this time, jQuery UI was placed in-between the body and the form.
DotNetNuke 6.1
DotNetNuke 6.1 introduced the new Client Resource Management API. The API allows for specific placement of JS files, using a registration provider. In 6.1, the available options were:
- PageHeaderProvider (appended to the head)
- DnnBodyProvider (top of the form)
- DnnFormBottomProvider (bottom of the form)
jQuery was the only script to use PageHeaderProvider, the rest would use DnnBodyProvider, save for one (a search related script) that would use DnnFormBottomProvider. This was done to try to replicate, as much as possible, what was there previously with respect to order.
Also of important note, the ability to take advantage of the HttpContext key workaround to find out if jQuery was already loaded was removed in DotnetNuke 6.1.0, as the internals of our jQuery registration system changed to use our new Client Resource Management API, and we no longer needed to use this HttpContext key for tracking. The unfortunate side effect of this is that now those modules that were using this technique would load jQuery again. Sometimes this will cause issues, sometimes it will not. It all depends on if anything is extending jQuery in-between the first and second registration. More on that later.
DotNetNuke 6.1.1
The were two specific issues with 6.1.0 that were fixed in DotNetNuke 6.1.1. The first was that the contents of a DotNetNuke Page’s header and Styles skin objects were not being placed in the right order in the page head. This caused issues with ordering when one of these two techniques was being used.
The fix for this issue was to create a new registration provider “DnnPageHeaderProvider” and use this instead of the “regular” PageHeaderProvider, the difference between the two is small but important: The DotNetNuke version inserts the contents at a specific location, whereas the other dynamically appends its contents to the end of the head. Usage of the DotNetNuke version ensures that things are loaded in the expected order.
The second was that jQuery UI was being loaded “too low” in the document. If someone were writing code that depended on jQuery, the possibility existed for them to register their code prior to jQuery being loaded. The decision was to move jQuery UI to the head – to treat it the same way as jQuery. This would improve the overall situation for those that want to take advantage of jQuery UI, by ensuring that it is loaded prior to virtually any consuming code.
The Current Situation
In DotNetNuke 6.1 or 6.1.1, if a module is relying on the internal implementation of the jQuery registration API to avoid loading jQuery more than once, it is not working. jQuery is being loaded twice.
If the second version of jQuery is loaded *after* jQuery UI, which in 6.1.1, it probably is, then jQuery UI will not be available. Here’s why:
- jQuery is loaded by the DotNetNuke framework. The jQuery object is defined.
- jQuery UI is loaded by the DotNetNuke framework. The jQuery object is extended with jQuery UI specific functionality.
- jQuery is loaded again, and the jQuery object is redefined. And, effectively, jQuery UI was “wiped out”.
This may cause the Manage buttons to stop working, as they rely on jQuery UI’s draggable functionality. Also, other module functionality may be broken as well if it depends on jQuery UI.
Next steps/Action Items
The long term answer here is that module developers need to use the public API directly, or use a method such as Bruce Chapman uses that handles using the API without being dependent on a particular version of DNN.
In the short term, if you are locked into a situation where you cannot change the module, and you cannot move back to a previous version of DotNetNuke, the only stop-gap measure that will work is to load jQuery UI again somewhere on the page. This should probably be avoided at all costs, as you will not only have two copies of jQuery on the page, but now two copies of jQuery UI – but if you absolutely have to fix this issue in-place, I would suggest putting a text/html module on the page and placing a jQuery UI script reference in the header or footer. Here is the snippet:
<script type=”text/javascript” src=””http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js”></script>
Summary
Managing JS dependencies is undoubtedly tricky business. I hope that this tour of jQuery & jQuery UI in DotNetNuke history is helpful in understanding the "what?” and the “why?” of the implementation, and how we arrived at seeing these issues in DNN 6.1 and 6.1.1.
Although there have been some significant short term challenges, I believe these challenges will help us, as a whole community, get it right. The average DotNetNuke site contains code from a wide variety of developers. In order to be truly successful, all developers need to settle on a common practice.
9 comment(s) so far...
Re: jQuery & jQuery UI in DNN 6.1.0 and 6.1.1
Thanks Ian this is very helpful. Can you explain the relationship between this and the jQuery settings in the Host Settings? What are the pros and cons of using the Installed vs Hosted jQuery and jQuery-UI? How does the hosted version get updated? Do I have to do it manually or does a DNN upgrade do it? I have the latest DNN 6.1.1 and my UI version is 1.8.13, not 1.8.16. Has is gone from .13 to .16 since DNN 6.1.1 was released? Main main version is 1.6.1, but it says my installed version is 1.6.4.
Is it a bad practice to put a jQuery link directly into a skin file? I wanted to use jQuery.truncate to do a Read More / Show Less on comments in my Active Social journal. So I put a reference directly in my skin to this file.
/resources/shared/scripts/jquery/jquery.truncate.min.js
I know you can't do a full class on this right now, but again I would appreciate any best practices to follow and short term solutions.
Any help in understanding how to manage this if I am not an expert would be great since apparently it can be a big deal.
By Cliff Hammock on
11/18/2011 2:04 PM
|
Re: jQuery & jQuery UI in DNN 6.1.0 and 6.1.1
Hey Cliff,
First, you're welcome! I'm glad the information is helpful.
Whether you use the hosted version of jQuery or jQuery UI isn't going to directly impact any of the load order or competition issues described in the blog post. Also, the new API allows for seamless usage of the hosted files just as before, whether you have files combined or not (which is very nice).
The real thing to think about is just version compatibility. DotNetNuke "comes with" certain versions of each library, and is internally tested with those versions. As time moves forward, the framework moves to newer versions of each library. If a given module is incompatible with the version that DotNetNuke is using, you may run into issues. But, for the most part, jQuery maintains backwards compatibility, and the vendor/module developer will (hopefully) inform you if there is a known compatibility issue.
As for DotNetNuke upgrades impacting the hosted URL of jQuery or jQuery UI, I don't honestly have enough information to give a satisfactory answer right now. I'll look into it and try to update here with a comment.
Regarding embedding scripts in skins - I'd say that, yes, it is a bad practice to directly reference jQuery or jQuery UI. However, if it's a plug-in, it is probably fine to reference from a skin. The best way to do so though, would be to leverage the new DnnJsInclude control in your skin. That will allow it to participate in the file combination (if enabled) and also allow it to remove duplicate registrations. More information about that can be found here: www.dotnetnuke.com/Resources/Wiki/Page/Client-Resource-Management-API.aspx.
Hope that helps!
Ian
By Ian Robinson on
11/18/2011 2:25 PM
|
Re: jQuery & jQuery UI in DNN 6.1.0 and 6.1.1
I've created a couple of snippets of HTML that help explain things a bit further.
The first illustrates the position of various elements in the DOM in DNN 6.1.1: gist.github.com/1377662
The second illustrates how jQuery UI can be wiped out by loading jQuery more than once. gist.github.com/1377658
Ian
By Ian Robinson on
11/18/2011 2:35 PM
|
Re: jQuery & jQuery UI in DNN 6.1.0 and 6.1.1
Thanks this is very helpful, I'll start trying
By haythem hassan on
11/18/2011 4:20 PM
|
Re: jQuery & jQuery UI in DNN 6.1.0 and 6.1.1
Very nice summary! Thanks
By Phil Speth on
11/19/2011 10:49 AM
|
Re: jQuery & jQuery UI in DNN 6.1.0 and 6.1.1
Thanks Ian!
By Bill Quinn on
11/19/2011 9:56 PM
|
Re: jQuery & jQuery UI in DNN 6.1.0 and 6.1.1
Ian, I'm runnig a review blog with my friends, we were using a third party blog (Ventrian News Articles) module and so far it was working great before DNN 6.1.1 upgrade. If you take a look at following post: www.androidincelemeleri.com/blog/tabid/104/sp/31/Samsung-Galaxy-W-Incelemesi.aspx You will notice that Jquery popup under Ilgili Resimler section can't display the photo correctly. What would you suggest me to handle this problem?
I'm going to try putting [script type=”text/javascript” src=””http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js”>
By Ismet Dumlupinar on
11/27/2011 9:40 PM
|
Re: jQuery & jQuery UI in DNN 6.1.0 and 6.1.1
Ismet,
It looks like you may be experiencing CSS z-index issues, not JavaScript issues. Take a look at the wiki for more info: www.dotnetnuke.com/Resources/Wiki/Page/DotNetNuke-6-Developer-Quick-Start.aspx#CSS:_Important_Notes__5
Ian
By Ian Robinson on
11/27/2011 9:53 PM
|
Re: jQuery & jQuery UI in DNN 6.1.0 and 6.1.1
I have added another blog post which covers off the topics that Ian has discussed here. This includes a code library you can include in your projects so you can target all versions of DNN but allows you to leverage the 6.1 improvements if the code is implemented in a DNN 6.1 installation.
This takes it further than the previous post already linked because it allows you to write the code once, but have the extra power of DNN 6.1 used when it is available.
See here for more details: www.ifinity.com.au/2011/12/05/Implementing_jQuery__jQuery_UI_and_Javascript_libraries_across_DotNetNuke_Versions
By Bruce Chapman on
12/5/2011 5:59 PM
|