Well, unless you've been hiding under a rock for the past year or so you've undoubtedly heard about jQuery.
jQuery is an amazingly useful javascript library that makes it easy to create UI widgets and effects with just a few pieces of code. One of the offshoots of the base jQuery library is the
jQuery UI library which uses the power of the jQuery base library to create some very useful UI widgets such as an Accordion, Tabs, DatePicker etc. They have also combined this with a very nice css based theming system named
ThemeRoller which provides some standard themes as well as allowing you to customize these themes online and download the whole package.
What I'm going to show you today is how you can take the markup, javscript and css necessary for the
jQuery Accordion and integrate it into an Aggregator skin template. An Aggregator skin template is made up of multiple files that reside in their own folder under the skins folder. They are read in at runtime, combined with special tokens and then output to the browser. I have
full documentation on the template system on the wiki so I'm not going to repeat everything here. The main focus of this article will be to step you through the process of taking html markup from another library and integrating it into it's own Aggregator template. The other thing I need to tell you is that the methods used in this article will only work with Aggregator 5.6.5 and above. A demo page has also been set up so you can
see the results live.
If we look at the docs page for the
jQuery Accordion widget we can see the basic html markup needed for the accordion. It looks like this:
<div id="accordion">
<div>
<a href="#">First header</a>
<div>First content</div>
</div>
<div>
<a href="#">Second header</a>
<div>Second content</div>
</div>
</div>
To simplify this, lets remove the repetitive parts so we are left with a single accordion section:
<div id="accordion">
<div>
<a href="#">First header</a>
<div>First content</div>
</div>
</div>
Now, lets take the variable text in this html (First Header and First Content) and replace it with the tokens that the Aggregator module will replace with our content, namely the tab caption and the tab page.
<div id="accordion">
<div>
<a href="#">[TABCAPTION]</a>
<div>[TABPAGE]</div>
</div>
</div>
The next thing I want to do is replace the id="accordion" with a unique id for this Aggregator. Remember, it's possible to put two Aggregators on the same page with the same skin for both, so you want to make sure you are targeting the proper elements with the jQuery calls. In this case we are going to create an id at runtime with the tag [UNIQUE] which is replaced with a unique string for the particular instance of Aggregator that it is used in. In the current version of Aggregator (5.6.5 at time of writing), the [UNIQUE] tag is replaced with the text 'Agg123_' where 123 is the moduleid of the module but this could change in future versions so please don't hard code it into your scripts. If you use the [UNIQUE] token, it will always be unique for the current instance of the Aggregator.
<div id="[UNIQUE]Accordion">
<div>
<a href="#">[TABCAPTION]</a>
<div>[TABPAGE]</div>
</div>
</div>
Ok, so now we have the html to produce a jQuery UI Accordion with exactly one section but we want to extend this so it works for as many tabs as we have in the module. What we'll do next is cut up this snippet of html into the specific template files that Aggregator understands in the context of a skin.
The first file we'll create is the layout.html file. This file is the initial file that the Aggregator loads and parses when rendering itself. The layout file is rendered exactly once so we're going to put our initialization code in here. I'll separate it into three distinct sections with comments so you can see what each piece does.
Layout.html
<!-- section 1 - jquery reference section -->
<link type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.0/themes/excite-bike/jquery-ui.css" rel="stylesheet" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/jquery-ui.min.js"></script>
<!-- section 2 - jquery accordion init -->
<script type="text/javascript">
$(document).ready(function(){
$("#[UNIQUE]Accordion").accordion();
});
</script>
<!-- section 3 - start of Aggregator layout -->
[TABSTRIP]
If you have done any work with jQuery in the past you'll recognize most of this code. The code in section 1 merely references the necessary css and javascript routines necessary for the jQuery. There is one caveat with this method of including the javascript in the skin. This will work fine if you have only one instance of this skin on your page. If you were to add another instance of an Aggregator on the same page with this same skin, you are going to have those references twice on the page. If you are going to have various jQuery code scattered throughout your site, you would be better served by referencing the css and javascript in a single spot on your site, for instance in your default.aspx page or putting the code in a script injection module that is included on each page. In DNN5, the second line in the code above that references the /1.3.2/jquery.js file is already included so you would only need to add lines 1 and 3 to every page. In addition, the css and script references are also better inside the <HEAD> tag of the page. Also of note, I'm using the excite-bike theme in this example. If you wanted to use another one of the standard themes, just change the excite-bike reference to something else such as cupertino. Alternatively you could use the
ThemeRoller studio and download your own custom theme and link to that.
The code in section 2 needs to be run each time this skin loads. This code uses the jQuery ready function to intialize the accordion for the div we created with an id of [UNIQUE]Accordion. The #[UNIQUE]Accordion reference is the selector syntax needed so that the accordion is applied to that particular div.
The code in section 3 is simply an Aggregator token that is replaced with the contents of the TabStrip.html template file. Let's go ahead and create that template file now.
TabStrip.html
<div id="[UNIQUE]Accordion">
[TABS]
</div>
The TabStrip.html file is rendered whenever the [TABSTRIP] token is found in the template. Because it's only referenced this once in the Layout.html file, it will only be rendered a single time. If you look back at our final html markup a few paragraphs ago, you should see a similarity to the code in the TabStrip.html file. We want to include the main accordion div, but we've replaced the accordion section with the [TABS] token. The [TABS] token will be replaced with an instance of the Tab.html file for each tab in our module. This is going to give us the repetition of content that we need to produce each section of the Accordion. Let's go ahead and create the tab template now.
Tab.html
<h3><a href="#">[TABCAPTION]</a></h3>
[TABPAGE]
The Tab.html file is rendered for each tab in our module. For instance if we have 4 tabs in our module, this template is called 4 times, parsed and rendered into our output. In this code you can see a couple of new tokens namely [TABCAPTION] and [TABPAGE]. TABCAPTION is replaced with the caption of the current tab we are rendering, and TABPAGE is replaced with the content of the TabPage.html template that we'll create now.
TabPage.html
<div>
[TABPAGECONTENT]
</div>
The TabPage.html file is rendered whenever the [TABPAGE] token is found in the template. Because a TabPage is related to a tab, it will be rendered for the current tab we are rendering. There is one new token to mention here, namely the [TABPAGECONTENT] token. This token is replaced with the actual html content of the tab. It could be just the html you've entered in a tab, or it could be an RSS item if you have activated that functionality or it could also include any modules you are inserting into the tab.
We have one last file that we need to take care of and that is the Script.txt file. When a skin is rendered, the module looks for a Script.txt file in the skin folder and if it does not find one it uses the default Script.txt file located under \Resources\Scripts. Since this accordion skin is unlike the normal skins that are included with Aggregator, we don't really want to reference the default file. We also don't need any additional scripting to be done so we're just going to include a very simple script that has a single function in it named [UNIQUE]Initialize. The [UNIQUE]Initialize function is a required function for the smooth running of an Aggregator skin and is the only required function we need to create if we decide to use our own Script.txt file. Here then is the contents of our Script.txt file.
Script.txt
<script type="text/javascript">
function [UNIQUE]Initialize() {}
</script>
Well, I spoke too soon when I said that was the last file. There are 4 other files inside our skin folder that I'll briefly mention. Three of them are empty files because we don't need their functionality for this particular skin and the other only if you are using the RSS functionality. The three empty files are named Paging.html, PagingItem.html and styles.css. The file that formats our RSS items is named RSSContent.html and has some basic RSS item layout inside it. You can read more about these files in the wiki where I more fully
explain all the tokens and template files.
Packaging up your skin
It is a very simple process to package up your skin. You merely create the proper folders under the skins folder and then ftp your files into it. For my example I have created a skin folder named jQuery and template sub folder named Accordion. The full folder structure would then be DESKTOPMODULES\DNNStuff - Aggregator\Skins\JQueryUI\Accordion. These folders will show up in the Aggregator settings as jQuery in the Tab Skin dropdown, and when you choose that you will see Accordion in the Tab Template dropdown.
Once you have this done, you should be able to choose the skin and
see the results. I have also attached the full skin zip file so you can skip the editing if you wish. If you are logged in as host, you can use the Upload Skin menu option to upload this directly to your system without having to use ftp.
Final Thoughts
I hope this tutorial has shown you the light and helped you to better understand the power of the Aggregator templating model. You've seen how you can take a 3rd party script or library and integrate it into it's own skin. There are many other javascript libraries, widgets and scripts out there that you could do the very same thing to. Use your imagination and see what you can come up with. If you have a template you'd like to share, please email me at support@dnnstuff.com and I'll post it for others to enjoy.
Download
jQueryUi Skin File