<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>TechBubble &#187; Javascript</title>
	<atom:link href="http://www.kalyani.com/tag/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kalyani.com</link>
	<description>Nik Kalyani&#039;s Irrationally Exuberant Musings on Technology</description>
	<lastBuildDate>Mon, 23 Jan 2012 08:16:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>DotNetNuke Widgets Guide (Part 4 of 4)</title>
		<link>http://www.kalyani.com/2010/01/dotnetnuke-widgets-guide-part-4-of-4/</link>
		<comments>http://www.kalyani.com/2010/01/dotnetnuke-widgets-guide-part-4-of-4/#comments</comments>
		<pubDate>Tue, 12 Jan 2010 09:07:00 +0000</pubDate>
		<dc:creator>nik</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[DotNetNuke]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Modules]]></category>
		<category><![CDATA[Skins]]></category>
		<category><![CDATA[Widgets]]></category>

		<guid isPermaLink="false">http://kalyani.com/?p=1039</guid>
		<description><![CDATA[This is the last post in my four-part series on DotNetNuke Widgets. Here&#8217;s a review of the other posts in this series: Part 1 &#8211; Overview of DotNetNuke Widgets Part 2 &#8211; DotNetNuke Widgets reference Part 3 &#8211; Insights into how you can develop your own Widgets for DotNetNuke In this post, I&#8217;ll walk you <a href='http://www.kalyani.com/2010/01/dotnetnuke-widgets-guide-part-4-of-4/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>This is the last post in my four-part series on DotNetNuke Widgets. Here&#8217;s a review of the other posts in this series:</p>
<ul>
<li><a href="/2009/12/dotnetnuke-widgets-guide-part-1-of-4/">Part 1</a> &#8211; Overview of DotNetNuke Widgets</li>
<li><a href="/2009/12/dotnetnuke-widgets-guide-part-2-of-4/">Part 2</a> &#8211; DotNetNuke Widgets reference</li>
<li><a href="/2010/01/dotnetnuke-widgets-guide-part-3-of-4/">Part 3</a> &#8211; Insights into how you can develop your own Widgets for DotNetNuke</li>
</ul>
<p>In this post, I&#8217;ll walk you through the code of the TechBubble CatalogWidget. This Widget displays a carousel of Product thumbnail images. You can click on any thumbnail to see a larger version of the image. You can then move your cursor over any portion of the larger image to see a zoomed in image of the area below the cursor. I created this Widget to convey multiple concepts:</p>
<ul>
<li>Passing data through Widget markup parameters</li>
<li>Using a Widget to integrate multiple jQuery plugins seamlessly</li>
<li>Using behavior injection to dynamically add event-handling to UI elements</li>
<li>Dynamically injecting stylesheets and scripts into the page</li>
<li>Using jQuery UI themes</li>
</ul>
<p>Let&#8217;s start by looking at a mockup of the Widget (created using my favorite mockup tool &#8211; <a href="http://balsamiq.com" target="_blank">Balsamiq</a>).</p>
<p style="text-align: center;"><a href="http://kalyani.com/wp-content/uploads/2010/01/mockup2.png"><img class="aligncenter size-full wp-image-1057" style="border: 0pt none;" title="CatalogWidget Mockup" src="http://kalyani.com/wp-content/uploads/2010/01/mockup2.png" alt="CatalogWidget Mockup" width="569" height="491" /></a></p>
<p style="text-align: center;">
<p>In order to implement this UI, I decided to use two jQuery plugins:</p>
<ul>
<li><a href="http://www.ferretarmy.com/files/jQuery/ImageCarousel/ImageCarousel.html" target="_blank">ImageCarousel</a></li>
<li><a href="http://www.mind-projects.it/projects/jqzoom/" target="_blank">jqZoom</a></li>
</ul>
<p>(These are arbitrary choices&#8230;I am sure that there are other plugins that would work equally well or better.)</p>
<p>I have setup two live demos of the Widget so you can get a feel for the Widget&#8217;s UI:</p>
<ul>
<li><a href="http://demo.kalyani.com/Widgets/CatalogWidgetDemo1.aspx" target="_blank">Demo with default data</a> (Ducati bikes)</li>
<li><a href="http://demo.kalyani.com/Widgets/CatalogWidgetDemo2.aspx" target="_blank">Demo with custom data</a> (Maxim&#8217;s 10 Hottest Women)</li>
</ul>
<p>You can download the Widget at the link below and follow along with the technical discussion that follows. I have also included a short slideshow that shows a screen grab of the installation process and the two demos.</p>
Note: There is a file embedded within this post, please visit this post to download the file.
<p>[smooth=id:1;]</p>
<p>Here are the properties that supported by the CatalogWidget:</p>
<p><em><strong>photoUrl</strong> (required) &#8211; </em>A URL to the location where the images for the Widget will be found. The Widget uses the following convention for image names: {label}.{extension} for hi-res image displayed in zoom area, {label}_thumb.{extension} for thumbnail image and {label}_small.{extension} for small image displayed when thumbnail is clicked. {label} and {extension} are explained in the description for other parameters.</p>
<p><em><strong>theme</strong> (optional, default=ui-lightness)</em> &#8211; Name of the jQuery UI theme that should be loaded from Google&#8217;s CDN for jQuery themes. The list of supported themes can be found on the <a href="http://jqueryui.com/themeroller/" target="_blank">jQuery Themeroller</a> page. The theme name should match the defined name on the Themeroller page, with spaces in the name replaced with the hyphen character.</p>
<p><em><strong>carouselWidth</strong> (optional, default=500)</em> &#8211; Width of the carousel used to display the thumbnails in pixels. The number of thumbnails displayed will depend on the width of each thumbnail and the value of this parameter.</p>
<p><em><strong>zoomWidth</strong> (optional, default=250)</em> &#8211; Width of the zoomed image area in pixels.</p>
<p><em><strong>zoomHeight</strong> (optional, default=250)</em> &#8211; Height of the zoomed image area in pixels.</p>
<p><em><strong>moreInfoHandler</strong> (optional) </em>- Name of a function that will be called with a parameter of {label} when the information icon that appears to the right of the product name link is clicked. If this parameter is not specified, the information icon will not be displayed.</p>
<p><em><strong>extension</strong> (optional, default=jpg)</em> &#8211; The file extension for all images.</p>
<p><em><strong>Product Data</strong></em> &#8211; In addition to these parameters, the Widget supports an unlimited number of additional product data parameters. Any parameter specified other than the above, is treated as product data. The value of the &#8220;name&#8221; attribute of the parameter will be used for the product {label} and the value of the &#8220;value&#8221; attribute will be used for the product&#8217;s descriptive name. Example: &lt;param name=&#8221;ABC1000&#8243; value=&#8221;ABC 1000 Super Duper Product&#8221; /&gt;.</p>
<p>OK, now we have that out of the way, let&#8217;s get started with building the Widget. The Widget is going to exist in the namespace &#8220;<strong>TechBubble.Widgets</strong>,&#8221; so by convention, the Widget file will be named &#8220;<strong>TechBubble.Widgets.CatalogWidget.js</strong>&#8221; and it will be located in <strong>~/Resources/Widgets/User/TechBubble</strong>. All resources for this Widget will be in <strong>~/Resources/Widgets/User/TechBubble/CatalogWidgetResources</strong>. Here&#8217;s the code for namespace registration and the Widget constructor:</p>
<pre class="brush: javascript">Type.registerNamespace(&amp;quot;TechBubble.Widgets&amp;quot;);
TechBubble.Widgets.CatalogWidget = function(widget)
{
    TechBubble.Widgets.CatalogWidget.initializeBase(this, [widget]);
    this.catalogResourcesUrl =
                    $dnn.baseResourcesUrl +
                    &amp;quot;Widgets/User/TechBubble/CatalogWidgetResources/&amp;quot;;
    this.photoUrl = &amp;quot;&amp;quot;;
    this.theme = &amp;quot;ui-lightness&amp;quot;;
    this.carouselWidth = &amp;quot;800&amp;quot;;
    this.zoomWidth = &amp;quot;250&amp;quot;;
    this.zoomHeight = &amp;quot;250&amp;quot;;
    this.moreInfoHandler = &amp;quot;&amp;quot;;
    this.extension = &amp;quot;jpg&amp;quot;;
    this.products = [];
    this.hasProducts = false;

    if (!TechBubble.Widgets.CatalogWidget.Initialized)
    {
        $.getScript(this.catalogResourcesUrl +
                    &amp;quot;scripts/jQuery-ui-1.7.2.custom.min.js&amp;quot;);

        $.getScript(this.catalogResourcesUrl +
                    &amp;quot;scripts/jquery.metadata.js&amp;quot;);

        TechBubble.Widgets.CatalogWidget.Initialized = true;
    }
}
TechBubble.Widgets.CatalogWidget.inheritsFrom(
            DotNetNuke.UI.WebControls.Widgets.BaseWidget);
TechBubble.Widgets.CatalogWidget.registerClass(
            &amp;quot;TechBubble.Widgets.CatalogWidget&amp;quot;,
            DotNetNuke.UI.WebControls.Widgets.BaseWidget);</pre>
<p>In the constructor, we define default values for the various properties (parameters) that the Widget supports. In addition the variable <strong>TechBubble.Widgets.CatalogWidget.Initialized</strong> is used as a flag to prevent the jQuery UI and jQuery metadata plugin from being loaded. A nice optimization for this code would be to check for the actual existence of the plugin, instead of using a flag. In addition to the constructor, the calls to <strong>inheritsFrom()</strong> and <strong>registerClass()</strong> are standard calls for every Widget for setting inheritance and registering the class.</p>
<pre class="brush: javascript">TechBubble.Widgets.CatalogWidget.prototype =
{
    render:
        function()
        {
            // Parse widget parameters
            this._getParams();

            // Load some sample data to display if none
            // has been specified
            if (!this.hasProducts)
                this._getSampleData();

            // Create a DIV element and swap out the Widget&#039;s
            // defining &amp;lt;object&amp;gt; element with it by calling
            // the base render() method (can&#039;t use jQuery
            // shortcut to create element)
            var div =document.createElement(&amp;quot;div&amp;quot;);
            div.setAttribute(&amp;quot;style&amp;quot;,&amp;quot;width:&amp;quot; + this.carouselWidth + &amp;quot;px&amp;quot;);
            TechBubble.Widgets.CatalogWidget.callBaseMethod(this, &amp;quot;render&amp;quot;, [div]);

            this._renderCarousel();

            this._renderZoomer();
        },

        _getParams:
        function()
        {
		// Enumerate and retrieve parameters
		// . . . code omitted
        },

        _renderCarousel:
        function()
        {
		// Render the Carousel plugin
		// . . . code omitted
        },

        _renderZoomer:
        function()
        {
		// Render the Zoomer plugin
		// . . . code omitted
        },

        _injectStyleSheet:
        function(name, isTheme)
        {
		// Inject a stylesheet into the page
		// . . . code omitted
        },

        _getThumbnailList:
        function(list, photoUrl)
        {
            return(productList);
        },

         _getSampleData:
         function()
         {
		// Use and display Widget with sample data
		// . . . code omitted
         }
}</pre>
<p>Next, let&#8217;s review the code for the Widget&#8217;s prototype where the required method <strong>render()</strong> is declared along with various private methods (prefixed with underscore). In the <strong>render()</strong> method, we start by getting the parameters. Then, if no products are defined, we use some sample product information. Next, we swap out the &lt;object&gt; element defining the Widget with a &lt;div&gt; element. This &lt;div&gt; element will become the parent container for the rest of the Widget which is rendered in the <strong>_renderCarousel()</strong> and the <strong>_renderZoomer()</strong> methods. Next in the code are a number of helper methods. I won&#8217;t go into a line-by-line explanation, but highlight a few things I think are noteworthy:</p>
<p><strong>Script Injection:</strong> I use the jQuery method <strong>$.getScript(</strong>scriptUrl, anonymous function<strong>)</strong> in several places. This is a useful method when you want to inject a script into the DOM and want to ensure that any dependent code is not executed until the asynchronous loading of the script is completed. By putting all the dependent code in an anonymous function defined in the second parameter of this method I could achieve this goal.</p>
<p><strong>Behavior Injection:</strong> In <strong>_renderZoomer()</strong>, I iterate through each thumbnail in the carousel and use the shortcut for the jQuery <strong>bind() </strong>method <strong>$(this).click()</strong> to inject a click handler for each of the thumbnail images. This is cleaner and more efficient than adding an <strong>onClick</strong> attribute when defining the HTML markup for each thumbnail.</p>
<pre class="brush: javascript">DotNetNuke.UI.WebControls.Widgets.renderWidgetType(&amp;quot;TechBubble.Widgets.CatalogWidget&amp;quot;);</pre>
<p>We wrap-up the Widget code by telling the Widget framework to render all Widgets of the type <strong>TechBubble.Widgets.CatalogWidget</strong>.</p>
<p>This also wraps-up my series on DotNetNuke Widgets. I hope you found the content and examples useful and are inspired to build your own DotNetNuke Widgets.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kalyani.com/2010/01/dotnetnuke-widgets-guide-part-4-of-4/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>DotNetNuke Widgets Guide (Part 3 of 4)</title>
		<link>http://www.kalyani.com/2010/01/dotnetnuke-widgets-guide-part-3-of-4/</link>
		<comments>http://www.kalyani.com/2010/01/dotnetnuke-widgets-guide-part-3-of-4/#comments</comments>
		<pubDate>Mon, 04 Jan 2010 22:52:00 +0000</pubDate>
		<dc:creator>nik</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[DotNetNuke]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Modules]]></category>
		<category><![CDATA[Skins]]></category>
		<category><![CDATA[Widgets]]></category>

		<guid isPermaLink="false">http://kalyani.com/?p=1021</guid>
		<description><![CDATA[Continuing my series on DotNetNuke Widgets, here is Part 3 where I provide insights into how you can develop your own Widgets for DotNetNuke. If you haven&#8217;t already done so, read Part 1 (overview of DotNetNuke Widgets) and Part 2 (DotNetNuke Widgets reference) to better understand the concepts explored in this post. Let&#8217;s get started. <a href='http://www.kalyani.com/2010/01/dotnetnuke-widgets-guide-part-3-of-4/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://kalyani.com/wp-content/uploads/2009/12/Widgets.png"><img class="alignright size-full wp-image-1017" style="border: 0pt none; margin: 5px;" title="Widgets" src="http://kalyani.com/wp-content/uploads/2009/12/Widgets.png" alt="Widgets" width="200" height="199" /></a></p>
<p>Continuing my series on DotNetNuke Widgets, here is Part 3 where I provide insights into how you can develop your own Widgets for DotNetNuke. If you haven&#8217;t already done so, read <a href="http://kalyani.com/2009/12/dotnetnuke-widgets-guide-part-1-of-4/">Part 1</a> (overview of DotNetNuke Widgets) and <a href="http://kalyani.com/2009/12/dotnetnuke-widgets-guide-part-2-of-4/">Part 2</a> (DotNetNuke Widgets reference) to better understand the concepts explored in this post. Let&#8217;s get started.</p>
<div class="SubHead">Location and Naming Conventions</div>
<p>Widgets are located in two places: <strong>~/Resources/Widgets/DNN</strong> for Core Widgets and <strong>~/Resources/Widgets/User/&lt;CompanyName&gt;</strong> for user Widgets. The Widget file names are <strong>&lt;WidgetName&gt;.js</strong> for Core Widgets and <strong>&lt;CompanyName&gt;.Widgets.&lt;WidgetName&gt;.js</strong> for user Widgets.</p>
<div class="SubHead">Widget Anatomy</div>
<p>Let&#8217;s walk through the three basic sections of code that constitute a Widget:</p>
<p><strong>Namespace, Inheritance and Constructor</strong></p>
<p>Using the ASP.NET AJAX library, we register the namespace for our widget and define its inheritance from the BaseWidget class. Finally, we define the constructor.</p>
<pre class="brush: javascript">
Type.registerNamespace(&amp;quot;YourCompany.Widgets&amp;quot;);
YourCompany.Widgets.SampleWidget.inheritsFrom(DotNetNuke.UI.WebControls.Widgets.BaseWidget);
YourCompany.Widgets.SampleWidget = function(widget)
{
    YourCompany.Widgets.SampleWidget.initializeBase(this, [widget]);
}
</pre>
<p><strong>Render Method<br />
</strong></p>
<p>Every Widget must implement the render() method. Typically, this method will follow a pattern consisting of two steps: (1) enumerate the parameters specified in the Widget declaration (i.e. &lt;param&gt; elements) and assign them to local variables, (2) do some processing based on the parameters and call the render() method. When you call the render() method in Step 2, you pass in a DOM element that you create. The framework will replace the &lt;object&gt; element with which the Widget was defined with your DOM element and assign it the original ID that the &lt;object&gt; element was given. What your code does during Step #2 in order to populate the contents of the DOM element you create or manipulate other elements of the page is entirely up to you. Your Widget has access to any DOM element and can make calls to any other custom scripts, ASP.NET AJAX library functions, jQuery plugins etc.</p>
<pre class="brush: javascript">
YourCompany.Widgets.SampleWidget.prototype =
{
   render:
   function()
   {
      var params = this._widget.childNodes;
      if (params != null)
      {
          // Do something
      }

      var div = document.createElement(&amp;quot;div&amp;quot;);
      // Do some work here to add content to the div
      YourCompany.Widgets.SampleWidget.callBaseMethod(this, &amp;quot;render&amp;quot;, [div]);
   }
}
</pre>
<p><strong>Registration and Rendering</strong></p>
<p>The last thing you have to do in your Widget is to register its class and tell the Widget framework that it can render all instances of your Widget present on the page.</p>
<pre class="brush: javascript">
YourCompany.Widgets.SampleWidget.registerClass(&amp;quot;YourCompany.Widgets.SampleWidget&amp;quot;, DotNetNuke.UI.WebControls.Widgets.BaseWidget);
DotNetNuke.UI.WebControls.Widgets.renderWidgetType(&amp;quot;YourCompany.Widgets.SampleWidget&amp;quot;);
</pre>
<p>The above is all you need in order to create the basic scaffolding for a Widget. Add your custom code, save the file following the expected name and location conventions and you can start using your Widget right away (you&#8217;ll have to do some more work to package the Widget if you want it to be installable using the DotNetNuke Extension Wizard).</p>
<p>If you would like to see the code for a functional user Widget, you can download and install the <a href="../2009/12/module-print-widget-for-dotnetnuke/">Module Print Widget</a>. The module displays a dropdown that allows a page viewer to select from a list of modules on the page and print any single module thus eliminating the need to display a print icon on every module.</p>
<p>Stay tuned for the last part in this series where I take you step-by-step through the process of building a Product Catalog Widget that makes use of third-party jQuery plugins, injects stylesheets dynamically and renders a nice UI using the jQuery UI extensions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kalyani.com/2010/01/dotnetnuke-widgets-guide-part-3-of-4/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Module Print Widget for DotNetNuke</title>
		<link>http://www.kalyani.com/2009/12/module-print-widget-for-dotnetnuke/</link>
		<comments>http://www.kalyani.com/2009/12/module-print-widget-for-dotnetnuke/#comments</comments>
		<pubDate>Wed, 30 Dec 2009 01:50:09 +0000</pubDate>
		<dc:creator>nik</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[DotNetNuke]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Widgets]]></category>

		<guid isPermaLink="false">http://kalyani.com/?p=1003</guid>
		<description><![CDATA[If you are like me and want your websites to have a clean, unblemished look, then most likely you have either turned off the Print functionality in your DotNetNuke module settings or just use containers that don&#8217;t display the icon. While this does make the site look cleaner, it also takes away the functionality. I <a href='http://www.kalyani.com/2009/12/module-print-widget-for-dotnetnuke/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>If you are like me and want your websites to have a clean, unblemished look, then most likely you have either turned off the Print functionality in your DotNetNuke module settings or just use containers that don&#8217;t display the icon. While this does make the site look cleaner, it also takes away the functionality. I gave this some thought and concluded that a Widget would be a great way to provide the functionality for printing the content of modules on a page. I envisioned a selector that the user would click on that would allow them to print the content for a single module. A skin designer could embed the Widget directly into the skin, or a site administrator could selectively add it to pages using an HTML module.</p>
<p><a href="http://kalyani.com/wp-content/uploads/2009/12/ModulePrintWidget.png"><img class="aligncenter size-full wp-image-1007" title="Module Print Widget" src="http://kalyani.com/wp-content/uploads/2009/12/ModulePrintWidget.png" alt="Module Print Widget" width="529" height="390" /></a></p>
<p>A couple hours of hacking later I present to you the ModulePrintWidget for DotNetNuke. It&#8217;s simple and easy to use. When added to a page, it creates a drop-down list of each module on the page. A user can select a module from the list to see a preview, then click a Print icon to print the contents of that module. Here&#8217;s a short 45-second YouTube video that demonstrates the Widget in action: <strong><a href="http://www.youtube.com/watch?v=hCMTbqcstIM&amp;fmt=22" target="_blank">TechBubble ModulePrintWidget</a></strong></p>
<p>You can download the Widget package at the link below (install as Superuser from the Extensions page):</p>
Note: There is a file embedded within this post, please visit this post to download the file.
<p>You can also see a <a title="ModulePrintWidget Demo" href="http://demo.kalyani.com/widgets/moduleprintwidget.aspx" target="_blank">live demo of the ModulePrintWidget</a>.</p>
<p>To use the Widget, add the following HTML so that it appears once on a page. You can add the markup anywhere that HTML is supported (module, skin, skin object, container):</p>
<pre class="brush: html">&amp;lt;object id=&amp;quot;MyWidget&amp;quot; codetype=&amp;quot;dotnetnuke/client&amp;quot; codebase=&amp;quot;TechBubble.Widgets.ModulePrintWidget&amp;quot;&amp;gt;&amp;lt;/object&amp;gt;</pre>
<p>If you want to customize the appearance and language, use the optional parameters:</p>
<pre class="brush: html">&amp;lt;object id=&amp;quot;MyWidget&amp;quot; codetype=&amp;quot;dotnetnuke/client&amp;quot; codebase=&amp;quot;TechBubble.Widgets.ModulePrintWidget&amp;quot;&amp;gt;
 &amp;lt;param name=&amp;quot;selectorCssClass&amp;quot; value=&amp;quot;Class-to-style-dropdown&amp;quot; /&amp;gt;
 &amp;lt;param name=&amp;quot;selectText&amp;quot; value=&amp;quot;Default-text-for-dropdown&amp;quot; /&amp;gt;
&amp;lt;/object&amp;gt;</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.kalyani.com/2009/12/module-print-widget-for-dotnetnuke/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>DotNetNuke Widgets Guide (Part 2 of 4)</title>
		<link>http://www.kalyani.com/2009/12/dotnetnuke-widgets-guide-part-2-of-4/</link>
		<comments>http://www.kalyani.com/2009/12/dotnetnuke-widgets-guide-part-2-of-4/#comments</comments>
		<pubDate>Wed, 30 Dec 2009 00:33:17 +0000</pubDate>
		<dc:creator>nik</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[DotNetNuke]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Modules]]></category>
		<category><![CDATA[Skins]]></category>
		<category><![CDATA[Widgets]]></category>

		<guid isPermaLink="false">http://kalyani.com/?p=974</guid>
		<description><![CDATA[This is Part 2 of my four-part series on DotNetNuke Widgets. In Part 1 of the series, I covered some fundamental concepts related to DotNetNuke Widgets. In this post, I will introduce you to a few of the Widgets that are included with the DotNetNuke distribution. Before getting started I&#8217;d like to make one observation&#8230;these <a href='http://www.kalyani.com/2009/12/dotnetnuke-widgets-guide-part-2-of-4/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://kalyani.com/wp-content/uploads/2009/12/Widgets.png"><img class="alignright size-full wp-image-1017" style="border: 0pt none; margin: 5px;" title="Widgets" src="http://kalyani.com/wp-content/uploads/2009/12/Widgets.png" alt="Widgets" width="200" height="199" /></a>This is Part 2 of my four-part series on DotNetNuke Widgets. In <a href="http://kalyani.com/2009/12/dotnetnuke-widgets-guide-part-1-of-4/">Part 1 of the series</a>, I covered some fundamental concepts related to DotNetNuke Widgets. In this post, I will introduce you to a few of the Widgets that are included with the DotNetNuke distribution. Before getting started I&#8217;d like to make one observation&#8230;these widgets were created prior to the inclusion of jQuery within the DotNetNuke Core. While the Widgets are production-ready, they could use some refactoring to take advantage of jQuery&#8217;s efficient engine for selecting and manipulating DOM elements.</p>
<p>All Widgets follow the same format for embedding in any extension (module, skin, skin object, container)</p>
<pre class="brush: html">&amp;lt;object codebase=&amp;quot;{WidgetType}&amp;quot; codetype=&amp;quot;dotnetnuke/client&amp;quot; id=&amp;quot;{WidgetId}&amp;quot;&amp;gt;
	&amp;lt;param name=&amp;quot;{WidgetParameterName}&amp;quot; value=&amp;quot;{WidgetParameterValue}&amp;quot; /&amp;gt;
&amp;lt;/object&amp;gt;</pre>
<p>{WidgetType} (required) = fully qualified Type name of the Widget<br />
{WidgetId} (required) = arbitrary ID for the Widget&#8217;s DOM element (must be unique on the page)</p>
<p>A Widget can have zero or more child elements, each with a &#8220;name&#8221; and &#8220;value&#8221; attribute with corresponding {WidgetParameterName} and {WidgetParameterValue} values. Widget parameter names are case-insensitive. Widget parameter values are always case-sensitive.</p>
<div class="SubHead">StyleScrubberWidget</div>
<p>The purpose of this Widget is to &#8220;scrub&#8221; the appearance of a DotNetNuke page by removing undesirable attributes from specific elements on the page. For example, you may have a module that has a hard-coded &#8220;style&#8221; or &#8220;width&#8221; attribute that is disrupting the appearance of a page. You don&#8217;t really want to change the source code for the module (if it&#8217;s available) and you really want to use the module. This is where StyleScrubber Widget comes to the rescue. It enumerates a series of rules you provide and removes the undesirable attributes allowing elements to be fully styled with CSS. This Widget may appear any number of times on a page.</p>
<h3>Parameters</h3>
<p><strong><em>classNames</em></strong> (required) &#8211; A list of class names separated by semi-colons. The Widget will only act on elements with a matching &#8220;class&#8221; attribute. At least one value must be specified. Example: <em>head; normal; topic</em></p>
<p><strong><em>tag</em></strong> (optional) &#8211; A HTML element tag name which acts as a filter in selecting elements. The default value is <em>*</em> which implies all elements. Example: <em>div</em></p>
<p><strong><em>removeAttribute</em></strong> (optional) &#8211; The name of the attribute which should be stripped from all elements that match the <em>classNames</em> and <em>tag</em> conditions. The removeAttribute parameter may be repeated multiple times to specify more than one attribute that should be removed. Example: <em>style</em> (strips the &#8220;style&#8221; attribute)</p>
<p><strong><em>recursive</em></strong> (optional) &#8211; Value of <em>true</em> or <em>false</em> to indicate if the scrubbing cascades indiscriminately through all child elements of a matched element. Default is <em>false.</em></p>
<h3>Example</h3>
<p>Remove all &#8220;width&#8221; and &#8220;style&#8221; attributes from TABLE elements that have a class value of &#8220;Normal&#8221; or &#8220;NormalBold&#8221;</p>
<pre class="brush: html">&amp;lt;object codebase=&amp;quot;StyleScrubberWidget&amp;quot; codetype=&amp;quot;dotnetnuke/client&amp;quot; id=&amp;quot;ScrubTable&amp;quot;&amp;gt;
	&amp;lt;param name=&amp;quot;classNames&amp;quot; value=&amp;quot;Normal;NormalBold&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;tag&amp;quot; value=&amp;quot;table&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;removeAttribute&amp;quot; value=&amp;quot;width&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;removeAttribute&amp;quot; value=&amp;quot;style&amp;quot; /&amp;gt;
&amp;lt;/object&amp;gt;</pre>
<div class="SubHead">RelocationWidget</div>
<p>The purpose of this Widget is to move or &#8220;relocate&#8221; content so that they visual location of the content differs from the physical location of the content in the page. The primary use-case is SEO. Using the RelocationWidget it is possible to have content as close to the top of the page as possible while moving the navigation lower down on the page. Since search bots do not run scripts, this arrangement is optimal for them. Users with script-enabled browsers will see the navigation in its intended location. This Widget may appear any number of times on a page.</p>
<h3>Parameters</h3>
<p><strong><em>sourceId</em></strong> (required) &#8211; ID of the DOM element that contains the HTML content that will be relocated. It is recommended that you apply a CSS style of &#8220;display:none&#8221; to this element so it is not initially visible in the user&#8217;s browser.</p>
<p><strong><em>targetId</em></strong> (required) &#8211; ID of the DOM element where the HTML content from the <em>sourceId </em>element will be moved. It is recommended that you apply a CSS style for &#8220;width&#8221; and &#8220;height&#8221; matching the dimensions that the relocated content will occupy. Doing so prevents other elements on the page from visually moving around when the Widget performs its action.<em> </em></p>
<h3>Example</h3>
<p>Move all content from element &#8220;NavTemp&#8221; to &#8220;Nav&#8221;</p>
<pre class="brush: html">&amp;lt;object codebase=&amp;quot;RelocationWidget&amp;quot; codetype=&amp;quot;dotnetnuke/client&amp;quot; id=&amp;quot;MoveIt&amp;quot;&amp;gt;
	&amp;lt;param name=&amp;quot;sourceId&amp;quot; value=&amp;quot;NavTemp&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;targetId&amp;quot; value=&amp;quot;Nav&amp;quot; /&amp;gt;
&amp;lt;/object&amp;gt;</pre>
<div class="SubHead">RotatorWidget</div>
<p>Changes content within an element at a pre-defined interval. The content can be sourced from a location on the page, an RSS feed or sequentially numbered images. This widget is ideal for scenarios in which the content to be rotated is not known ahead of time and no interactivity is desired from the end-user. This Widget may appear any number of times on a page.</p>
<h3>Parameters</h3>
<p><strong><em>elementId</em></strong> (required) &#8211; ID of the DOM element where the rotating content will be rendered.</p>
<p><strong><em>height</em></strong> (required) &#8211; Height of the rotated content in pixels.</p>
<p><strong><em>width</em></strong> (required) &#8211; Width of the rotated content in pixels</p>
<p><strong><em>interval</em></strong> (optional) &#8211; Time interval in milliseconds for content rotation. Default is 2500 milliseconds.</p>
<p><strong><em>direction</em></strong> (optional) &#8211; Direction in which new content slides. Values are <em>UP</em>, <em>DOWN</em>, <em>RIGHT</em>, <em>LEFT </em>(default), <em>BLEND</em></p>
<p><strong><em>transition</em></strong> (optional, experimental) &#8211; Transition effect for new content. Values are <em>SLIDE</em>, <em>SNAP</em> (default)</p>
<p>The RotatorWidget can rotate content from three sources. Content from all the sources is aggregated, then displayed so you can combine multiple sources in the same RotatorWidget instance if desired.</p>
<p><span style="text-decoration: underline;"><strong>RSS Feed Source</strong><br />
</span></p>
<p><strong><em>feedUrl </em></strong>(required for RSS feeds)<em> </em>- URL of the RSS 2.0 feed from which content will be sourced</p>
<p><strong><em>feedAttribute</em></strong><em> </em>(required for RSS feeds) -<strong> </strong>Name of the element that contains the content to be rotated. Yahoo Pipes is used to retrieve the feed.</p>
<p><span style="text-decoration: underline;"><strong>Sequential Image Source</strong><br />
</span></p>
<p><strong><em>imageUrl</em></strong><em> </em>(required for images) &#8211; The base URL where the images to be rotated are located. Must end in slash (&#8220;/&#8221;).</p>
<p><strong><em>imageTemplate</em></strong> (required for images) &#8211; The file name template for each image. The token {INDEX} may be used to indicate where the sequence number will be injected. The sequence begins at 1. Example: <em>portrait{INDEX}.jpg </em>for images names portrait1.jpg, portrait2.jpg, portrait3.jpg etc.</p>
<p><strong><em>imageCount</em> </strong>(required for images) &#8211; The number of images available for rotation.</p>
<p><strong><em>imageScale</em></strong> (optional) &#8211; Indicates if images should be scaled by width or by height. Values are <em>WIDTH</em> and <em>HEIGHT </em>or blank (default) for no scaling.</p>
<p><span style="text-decoration: underline;"><strong>Page Content Source</strong></span></p>
<p><strong><em>contentElementId</em></strong> (required for content) &#8211; ID of the DOM element that contains the content to be rotated. The Widget expects the DOM element to have zero or more child elements. The content of each child element is treated as a separate rotation item. Example: A &lt;UL&gt; element with multiple &lt;LI&gt; elements where each &lt;LI&gt; element contains one item of content.</p>
<p><strong>Example</strong></p>
<p>Rotate 10 images stored in a folder at an interval of 5 seconds.</p>
<pre class="brush: html">&amp;lt;object codebase=&amp;quot;RotatorWidget&amp;quot; codetype=&amp;quot;dotnetnuke/client&amp;quot; id=&amp;quot;Animate&amp;quot;&amp;gt;
	&amp;lt;param name=&amp;quot;elementId&amp;quot; value=&amp;quot;PageHeader&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;height&amp;quot; value=&amp;quot;100&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;width&amp;quot; value=&amp;quot;400&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;interval&amp;quot; value=&amp;quot;5000&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;imageUrl&amp;quot; value=&amp;quot;/Portals/0/HeaderImages/&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;imageTemplate&amp;quot; value=&amp;quot;header{INDEX}.png&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;imageCount&amp;quot; value=&amp;quot;10&amp;quot; /&amp;gt;
&amp;lt;/object&amp;gt;</pre>
<div class="SubHead">StyleSheetWidget</div>
<p>The purpose of this Widget is to provide a user interface that enables users to switch stylesheets in order to customize their browsing experience. This Widget may appear any number of times on a page.</p>
<h3>Parameters</h3>
<p><strong><em>template</em></strong> (required) &#8211; The StyleSheetWidget renders an interface element for each stylesheet that the user can select from. The <em>template</em> parameter is used to specify the HTML markup that will be rendered for each stylesheet in the set. The HTML markup must be encoded and can use the tokens {TEXT} (replaced with the name of each stylesheet as specified in other parameters), {ID} (replaced with a unique identifier for each interface element that is rendered) and {CLASS} (replaced with &#8220;class&#8221; attribute and value). Example: <em>&lt;div title=&#8221;{TEXT}&#8221; {ID} {CLASS}&gt;&lt;/div&gt;</em></p>
<p><strong><em>default</em></strong> (required) &#8211; The value of the stylesheet that should be selected by default.</p>
<p><strong><em>baseUrl</em></strong> (required) &#8211; The URL where the stylesheets are located.</p>
<p><strong><em>cssClass</em></strong> (required) &#8211; The CSS class value to be used on interface elements corresponding to a stylesheet that is not selected.</p>
<p><strong><em>selectedCssClass</em></strong> (required) &#8211; The CSS class value to be used on the interface element corresponding to the selected stylesheet.</p>
<p>In addition to the above, one parameter (name and value) is required for each stylesheet. The &#8220;name&#8221; attribute should contain the stylesheet filename and the &#8220;value&#8221; attribute should contain the human-friendly label associated with the stylesheet.</p>
<h3>Example</h3>
<p>Allow the user to select from five different color palettes.</p>
<pre class="brush: html">&amp;lt;object codebase=&amp;quot;StyleSheetWidget&amp;quot; codetype=&amp;quot;dotnetnuke/client&amp;quot; id=&amp;quot;ColorSelector&amp;quot;&amp;gt;
	&amp;lt;param name=&amp;quot;template&amp;quot; value=&amp;quot;&amp;amp;lt;div title=&amp;quot;{TEXT}&amp;quot; {ID} {CLASS}&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;default&amp;quot; value=&amp;quot;blue&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;baseUrl&amp;quot; value=&amp;quot;&amp;lt;%= SkinPath %&amp;gt;css/&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;cssClass&amp;quot; value=&amp;quot;Icon&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;selectedCssClass&amp;quot; value=&amp;quot;Icon-Selected&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;red&amp;quot; value=&amp;quot;Fire-engine Red&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;blue&amp;quot; value=&amp;quot;Midnight Blue&amp;quot; /&amp;gt;
	&amp;lt;param name=&amp;quot;yellow&amp;quot; value=&amp;quot;Sunflower Yellow&amp;quot; /&amp;gt;
&amp;lt;/object&amp;gt;</pre>
<div class="SubHead">EmbedWidget</div>
<p>This Widget is somewhat unique in that its purpose is to provide a standard way for embedding any embeddable content from other websites. Using this Widget, you create a &#8220;snippet&#8221; for any such content once using whatever unique requirements the source site may have. Once the snippet is created, you can then use the embeddable content multiple times within DotNetNuke using the standard Widget embedding syntax.</p>
<h3>Parameters</h3>
<p><strong><em>publisher</em></strong> (required for user content) &#8211; This parameter tells the EmbedWidget where to look for the embeddable content. If it is not specified, the Widget looks for content in the folder &#8220;~/Resources/Widgets/DNN/EmbedWidgetResources/{type parameter value}/&#8221; If this parameter is specified, the Widget looks for content in the folder &#8220;~/Resources/Widgets/User/{publisher parameter value}/EmbedWidgetResources/{type parameter value}/&#8221;</p>
<p><strong><em>type</em></strong> (required) &#8211; The type of content to embed. This value must correspond to a file named &#8220;{lowercase type parameter value}.snippet.htm&#8221; in the folder location specified above. The file must be a plain-text file containing solely the HTML markup necessary for rendering the content.</p>
<p>In addition to the above parameters, you can specify and arbitrary number of name/value parameters that are passed to the content snippet file when the content is rendered by the Widget. The value may be a single value or multiple values concatenated using a delimiter character. The default delimiter is &#8220;;&#8221;. You can overrride the delimiter by specifying the &#8220;multiValueDelimiter&#8221; parameter described below. Review the individual snippet file for each type of embeddable content for supported parameters specific to that content type.</p>
<p><strong><em>multiValueDelimiter</em></strong> (optional) &#8211; Character used to delimit multi-value parameters.</p>
<p>When the Widget is rendered, the snippet file is parsed and token substitution is performed using values specified in the parameters. The syntax for tokens is:</p>
<p><strong> { parameter name :   token template : default template  }</strong></p>
<p>For each token, the Widget checks to see if a corresponding named parameter is available. If so, it replaces the token with the token template otherwise it uses the default template. In order to substitute parameter values in the token template, placeholders are used. Placeholders are numeric and in the format {0}, {1}, {2} etc. The Widget substitutes values in the order they are specified.</p>
<p>For example: { width : width=&#8221;{0}&#8221; : width=&#8221;500&#8243; }  OR { coordinates : x={0},y={1} : x=100,y=100 }</p>
<h3>Example</h3>
<p>Embed a Flickr slideshow</p>
<pre class="brush: html">&amp;lt;object codebase=&amp;quot;EmbedWidget&amp;quot; codetype=&amp;quot;dotnetnuke/client&amp;quot; id=&amp;quot;Flickr&amp;quot;&amp;gt;
	&amp;lt;param name=&amp;quot;type&amp;quot; value=&amp;quot;Flickr&amp;quot; /&amp;gt;
&amp;lt;/object&amp;gt;</pre>
<div class="SubHead">VisibilityWidget</div>
<p>The purpose of this Widget is to enable an HTML element on a page to toggle the visibility of a container element located elsewhere on the page. The Widget included with DotNetNuke is now deprecated. Joe Brinkman has updated the Widget&#8217;s code and the updated one will be available in a future DotNetNuke release. You can read all about Joe&#8217;s enhancements in his blog post <a href="http://blog.theaccidentalgeek.com/post/2009/12/29/DotNetNuke-Tips-and-Tricks-15-DotNetNuke-Visibility-Widget.aspx" target="_blank"><strong>DotNetNuke Tips and Tricks #15: DotNetNuke Visibility Widget</strong></a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kalyani.com/2009/12/dotnetnuke-widgets-guide-part-2-of-4/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>DotNetNuke Widgets Guide (Part 1 of 4)</title>
		<link>http://www.kalyani.com/2009/12/dotnetnuke-widgets-guide-part-1-of-4/</link>
		<comments>http://www.kalyani.com/2009/12/dotnetnuke-widgets-guide-part-1-of-4/#comments</comments>
		<pubDate>Sat, 26 Dec 2009 05:00:43 +0000</pubDate>
		<dc:creator>nik</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[DotNetNuke]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Modules]]></category>
		<category><![CDATA[Skins]]></category>
		<category><![CDATA[Widgets]]></category>

		<guid isPermaLink="false">http://kalyani.com/?p=898</guid>
		<description><![CDATA[Starting with Release 5.x, the DotNetNuke platform has included a Javascript-based Widgets framework for dynamically injecting client-side interactivity into skins and modules. Like most Open Source developers, I thoroughly enjoyed coding the Widget framework but neglected to document it properly. In this four-part series I hope to correct this shortcoming. In Part 1, I will <a href='http://www.kalyani.com/2009/12/dotnetnuke-widgets-guide-part-1-of-4/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://kalyani.com/wp-content/uploads/2009/12/Widgets.png"><img class="alignright size-full wp-image-1017" style="border: 0pt none; margin: 5px;" title="Widgets" src="http://kalyani.com/wp-content/uploads/2009/12/Widgets.png" alt="Widgets" width="200" height="199" /></a>Starting with Release 5.x, the DotNetNuke platform has included a Javascript-based Widgets framework for dynamically injecting client-side interactivity into skins and modules. Like most <a class="zem_slink" title="Open Source" rel="wikinvest" href="http://www.wikinvest.com/concept/Open_Source">Open Source</a> developers, I thoroughly enjoyed coding the Widget framework but neglected to document it properly. In this four-part series I hope to correct this shortcoming. In Part 1, I will introduce some fundamental concepts of the DotNetNuke Widget Framework. In Part 2, I will provide a reference for existing widgets that are included with DotNetNuke. In Part 3, I will step through the process of developing a Widget. Finally, in Part 4 I will create a working Widget that you can download and use to increase your understanding of the framework and to build your own Widgets.</p>
<h3>Widget Fundamentals</h3>
<p>Just as you can add modules to a DotNetNuke page to add application functionality, so also can you add Widgets to DotNetNuke skins and modules to add interactivity. For example, in a skin, Widgets may enable a user to dynamically switch a stylesheet to change page appearance, add a photo gallery, embed a video etc. In a module, Widgets can provide interface elements for navigation, drag-and-drop sorting capabilities etc. Widgets are first-class citizens of DotNetNuke&#8217;s extensibility model and can therefore be packaged individually or in combination with DotNetNuke modules and skins using the familiar DotNetNuke manifest and zip file model. Widgets are created using Javascript code that builds on the Microsoft ASP.NET AJAX client-side library and can leverage jQuery or any other client-side framework for additional capabilities. They can be embedded into any extension type that manifests itself in the client browser (module, skin, skin object, container) and use a syntax that should be familiar to skin designers. Here&#8217;s an example of a Flickr Widget:</p>
<pre class="brush: html">
&amp;lt;object codebase=&amp;quot;EmbedWidget&amp;quot; codetype=&amp;quot;dotnetnuke/client&amp;quot; id=&amp;quot;MyWidget&amp;quot;&amp;gt;
    &amp;lt;param value=&amp;quot;Flickr&amp;quot; name=&amp;quot;type&amp;quot; /&amp;gt;
&amp;lt;/object&amp;gt;
</pre>
<p>That&#8217;s it&#8230;three lines of HTML markup to embed a Flickr slideshow like the image below instantly into a DotNetNuke page. Go ahead&#8230;try it out by adding the above markup in an HTML module (in source)&#8230;I&#8217;ll wait.</p>
<p><a href="http://kalyani.com/wp-content/uploads/2009/12/EmbedWidget-Flickr.png"><img class="aligncenter size-medium wp-image-906" title="EmbedWidget-Flickr" src="http://kalyani.com/wp-content/uploads/2009/12/EmbedWidget-Flickr-300x250.png" alt="Flickr slideshow using EmbedWidget" width="300" height="250" /></a></p>
<p>At this point you are probably wondering what the benefit of Widgets is if they are coded in Javascript and make use of pre-existing client-side libraries. After all it&#8217;s not that difficult to embed a simple &lt;script&gt; element into your skin or module and add any code that you desire directly at the appropriate location. And using my simplistic example of a Flickr slideshow, you could just as easily get the embed code for the slideshow and use it directly.</p>
<h3>Five Reasons for using the Widget framework</h3>
<p>Let&#8217;s address these questions by reviewing the five primary reasons for using the Widgets framework:</p>
<p><strong>Clean Markup:</strong> Using Widgets enables you to keep the HTML markup for your skin or module clean and script-free. Since Widgets are embedded using the standard &lt;object&gt; element, you can add functionality without sacrificing readability. In fact, Widgets lend themselves to more semantic markup as the intent of the markup is usually evident from the name of the Widget and the parameter name/value pairs. Embedding script directly or referencing an external script makes your markup harder to read and maintain.</p>
<p><strong>Reusability:</strong> If you have some Javascript code that needs to be used in multiple skins or modules, wrapping it into a Widget makes it easy for you to re-use the code while taking advantage of DotNetNuke&#8217;s packaging and versioning capabilities. Sure, you could store a script file in a central location and reference it, but Widgets afford you greater control in using, deploying and maintaining the code. Furthermore, by implementing the code as a Widget, you now have the ability to easily pass parameters without messing around with querystring parameters to script file references or in-line Javascript variable declarations. Such reusability does come at a small price in terms of time and effort required, so it&#8217;s probably not a good idea to create a Widget for a single-use script.</p>
<p><strong>Testability and Maintainability:</strong> Unlike context-less Javascript files or embedded script, Widgets are stand-alone, contextual entities. Therefore they can be tested and debugged in a variety of scenarios quickly and easily with minimal effort. If you just add a &lt;script&gt; reference to a Javascript file in your HTML markup, you have no way of knowing if the dependencies for the script are being loaded or not. You have no idea if any variable necessary to pass parameters to the script are already on the page or not. These issues are eliminated using Widgets. When you use a Widget, you know that its dependencies will be correctly loaded and its parameters are available in the Widget&#8217;s HTML markup itself.</p>
<p><strong>Performance:</strong> Browsers execute inline script and fetch scripts referenced using the &lt;script&gt; element synchronously while rendering a page (you could use the &#8220;defer&#8221; attribute, but browser support for this is not consistent). This puts an unnecessary wait penalty on the site visitor. Using jQuery&#8217;s document.ready() method mitigates this somewhat, but remember, the browser still has to switch context from HTML to Javascript, parse the script and then switch context back to HTML. Widgets provide a cleaner way to add client-side interactivity as they are loaded at the end of a page when the DOM is ready. Thus, the visitor will have a better user experience as HTML, CSS and images will already have been rendered. If you would like to learn more about how browsers handle script, read <a href="http://dev.opera.com/articles/view/timing-and-synchronization-in-javascript/" target="_blank">Timing and Synchronization in JavaScript</a>.</p>
<p><strong>Behavior Injection and Modification:</strong> It&#8217;s quite easy to add &#8220;onclick&#8221; and &#8220;onmouseover&#8221; attributes to HTML elements to add client-side interactivity. Unfortunately, this results in horrible markup that is difficult to maintain and difficult to debug. Widgets force you to use behavior injection and modification in order to attach events to DOM elements. This keeps all behavioral code in one location and makes it incredibly easy to maintain through good use of jQuery selectors. It&#8217;s also results in a cleaner separation between the markup and the script.</p>
<p>Hopefully this information has provided you with enough knowledge to understand when Widgets are a good idea and when they are not. Now let&#8217;s take a deeper look at the client-side page life-cycle to understand the Widget rendering process.</p>
<h3>Widget Rendering Process</h3>
<p>Widgets are rendered only if the Site Setting &#8220;Enable Skin Widgets&#8221; is checked. This value is checked by default, so you can be assured that Widgets will render on most DotNetNuke sites. (We should probably re-name this setting to &#8220;Enable Client-side Widgets&#8221;&#8230;when I was first coding the Widget framework, I was focused on usage scenarios involving skins and used the term &#8220;skin widgets.&#8221; The term stuck even though Widgets can be used in any DotNetNuke extension that renders code to the browser.) By enabling this setting, a single reference to a Javascript file is injected into the very end of the page:</p>
<pre class="brush: html">&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;/Resources/Shared/scripts/initWidgets.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;</pre>
<p>When the script loads, it initiates a four-step process: Framework Initialization, Widget Detection, Widget Instantiation and Widget Rendering. This process is illustrated below:</p>
<p><a href="http://kalyani.com/wp-content/uploads/2009/12/Widget-Process.png"><img class="aligncenter size-full wp-image-928" title="Widget-Process" src="http://kalyani.com/wp-content/uploads/2009/12/Widget-Process.png" alt="Widget Rendering Process" width="473" height="498" /></a></p>
<p>The Widget framework uses jQuery to load all required scripts in an asynchronous manner. When a script is done loading, an event is fired to carry out the next step in the rendering process. All of this happens pretty fast, and most notably, after the page is already rendered in the browser. If you view the HTML source for the page, you will see no difference in the markup from what was originally sent by the server (i.e. &lt;object&gt; elements). However, if you query the DOM using FireBug or a similar tool, you will see that each &lt;object&gt; Widget element has been replaced with a &lt;div&gt; or similar element with the same ID as originally given to the &lt;object&gt; element. This enables you to use CSS for styling the Widget using an ID selector (i.e. #MyWidget).</p>
<p>In this post, I provided an introduction to the DotNetNuke Widget Framework. In the next post in this series, I will introduce you to the Widgets included with DotNetNuke and provide a usage reference for each Widget.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kalyani.com/2009/12/dotnetnuke-widgets-guide-part-1-of-4/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>XHTML-Compliant Technique for Passing Parameters to Javascript Script Files</title>
		<link>http://www.kalyani.com/2008/08/xhtml-compliant-technique-for-passing-parameters-to-javascript-script-files/</link>
		<comments>http://www.kalyani.com/2008/08/xhtml-compliant-technique-for-passing-parameters-to-javascript-script-files/#comments</comments>
		<pubDate>Fri, 22 Aug 2008 08:00:00 +0000</pubDate>
		<dc:creator>nik</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.techbubble.net/Blog/tabid/57/EntryId/211/XHTML-Compliant-Technique-for-Passing-Parameters-to-Javascript-Script-Files.aspx</guid>
		<description><![CDATA[Joe Brinkman posted a technique to pass parameters to Javascript script files. The approach is simple &#8212; append a standard querystring to the script URL and obtain the parameters by locating the script element using the ID attribute, and parsing the key-value pairs from the &#8220;src&#8221; attribute. A sample usage is like this: &#38;lt;script id=&#38;quot;MyScript&#38;quot; <a href='http://www.kalyani.com/2008/08/xhtml-compliant-technique-for-passing-parameters-to-javascript-script-files/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Joe Brinkman <a href="http://blog.theaccidentalgeek.com/post/2008/08/21/Passing-parameters-to-JavaScript-files.aspx">posted</a> a technique to pass parameters to <cite>Javascript</cite> script files. The approach is simple &#8212; append a standard querystring to the script URL and obtain the parameters by locating the script element using the ID attribute, and parsing the key-value pairs from the &#8220;src&#8221; attribute. A sample usage is like this:</p>
<pre class="brush: html">
&amp;lt;script id=&amp;quot;MyScript&amp;quot; src=&amp;quot;http://www.foo.com/myscript.js?obj1=ABC&amp;amp;amp;obj2=XYZ&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
</pre>
<p>This is a great approach and works well for most scenarios, except in those situations where HTML 4.01 Strict markup is desired. In this case there are two problems that would cause validation to fail:</p>
<p>1) The <cite>HTML</cite> &#8220;script&#8221; element does not support an ID attribute. Yes, this is true. Verify it for yourself <a href="http://www.w3.org/TR/html401/interact/scripts.html#edef-SCRIPT">here</a>.</p>
<p>2) The ampersand (&#8220;&amp;&#8221;) character is a predefined entity and <a href="http://www.w3.org/TR/xhtml1/#C_12">must be expressed as an entity reference</a> &#8220;&amp;&#8221;</p>
<p>So, is there a simple way to work around this issue. Of course, otherwise the title of this post would be totally false advertising.</p>
<p>Here is the revised code snippet I propose in lieu of the one above:</p>
<pre class="brush: html">&amp;lt;script src=&amp;quot;http://www.foo.com/myscript.js#obj1/ABC/obj2/XYZ&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;</pre>
<p>Let&#8217;s break it down.</p>
<p>1) <strong>The ID attribute has been removed.</strong> Even without the ID attribute there is still a simple way to reference the script element. The trick is to take advantage of the fact that as the browser is rendering the page, it executes JS code immediately when encountered. As a result, if the code in your JS file queries the DOM, the last script element in the DOM is a self-reference (i.e. a reference to the script element that loaded the code being executed). Thus, using <em>document.getElementsByTagName(&#8220;script&#8221;)</em> and referencing the last element in the array, provides an easy way to get the current script reference.</p>
<p>2) <strong>The standard querystring separator &#8220;?&#8221; has been replaced by &#8220;#&#8221;.</strong> This is not necessary, but something I did for semantic reasons. To overcome the &#8220;&amp;&#8221; entity issue, I used a slash (&#8220;/&#8221;) character for separating not only key-value pairs, but keys and values too. The reason for this will become evident in a bit, but since I modified the querystring to something non-standard, I felt it was important to also remove the &#8220;?&#8221; separator which is a prefix for querystring. Instead, I used a hash (&#8220;#&#8221;) character which is a pointer to a document fragment and does not have any semantic value in the context of a JS script URL. (In fact the JS URL hash technique is a common way to pass data in cross-domain XMLHttp requests for this reason and also because it does not cause a page re-load.)</p>
<p>3) <strong>Key-Value pairs. </strong>The last change I made is to use a path-based approach to key-value pairs instead of Key=Value format. I did this because it is a common technique in RESTful URL&#8217;s, is easier to read and much simpler to parse. In fact, using a single &#8220;for&#8230;&#8221; loop, it becomes a trivial task to create an associative array of all the parameters for ready reference.</p>
<p>Here&#8217;s the code wrapped into a function with a sample call:</p>
<pre class="brush: javascript">

var myParams = getScriptUrlParams();
alert(myParams[&amp;quot;obj1&amp;quot;]);
alert(myParams[&amp;quot;obj2&amp;quot;]);

function getScriptUrlParams()
{
	var scriptTags = document.getElementsByTagName(&amp;quot;script&amp;quot;);

	// This code is assumed to be in a file so the &amp;quot;src&amp;quot; attribute
	// is guaranteed to be present...no error-checking is needed
	var urlFrags = scriptTags[scriptTags.length-1].src.split(&amp;quot;#&amp;quot;);

	var urlParams=[];
	var urlParamRaw = [];
	if (urlFrags.length &amp;gt; 1)
	{
	    urlParamRaw = urlFrags[1].split(&amp;quot;/&amp;quot;);
	    if (urlParamRaw.length &amp;gt;= 2)
	    {
	    	for(var param=0;param&amp;lt;urlParamRaw.length;param+=2)
	            urlParams[urlParamRaw[param]] = (urlParamRaw.length &amp;gt;= param + 1 ? unescape(urlParamRaw[param+1]) : null);
    	    }
	}

	return(urlParams);
}
</pre>
<p>What do you think? Is this a simpler approach or is it more complicated? Are there other techniques for working around the X<cite>HTML</cite> validation issue.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kalyani.com/2008/08/xhtml-compliant-technique-for-passing-parameters-to-javascript-script-files/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to Foil Blog Content Harvesters</title>
		<link>http://www.kalyani.com/2008/06/how-to-foil-blog-content-harvesters/</link>
		<comments>http://www.kalyani.com/2008/06/how-to-foil-blog-content-harvesters/#comments</comments>
		<pubDate>Sat, 28 Jun 2008 08:00:00 +0000</pubDate>
		<dc:creator>nik</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.techbubble.net/Blog/tabid/57/EntryId/205/How-to-Foil-Blog-Content-Harvesters.aspx</guid>
		<description><![CDATA[On the LinkedInBloggers group, there is an interesting discussion on how to prevent blog harvesting. Turning off RSS feeds and subscription feeds seemed to be the suggested solution. I think this is an impractical solution and makes your blog harder to find and harder to consume with RSS readers. I wonder if disabling RSS/subscription widgets <a href='http://www.kalyani.com/2008/06/how-to-foil-blog-content-harvesters/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>On the <a href="http://tech.groups.yahoo.com/group/LinkedinBloggers/">LinkedInBloggers</a> group, there is an interesting <a href="http://tech.groups.yahoo.com/group/LinkedinBloggers/message/6837">discussion</a> on how to prevent blog harvesting. Turning off RSS feeds and subscription feeds seemed to be the suggested solution. I think this is an impractical solution and makes your blog harder to find and harder to consume with RSS readers.</p>
<p>I wonder if disabling RSS/subscription widgets is the only way? What if there was a simple way to ensure that your content only displays in a browser if it is being served from your site and when displayed on a harvester&#8217;s site, it simply redirects the browser back to your site?</p>
<p>I came up with a solution that might work. My solution is based on two assumptions:</p>
<p>1) RSS readers ignore Javascript</p>
<p>2) Most blog engines have a templating feature that allow the URL of the blog post to be injected anywhere on the page containing the post</p>
<p>The solution is pretty simple:</p>
<p>Embed a simple script in your blog post that checks to see if the location where your blog content is being displayed is valid (i.e. your blog) or invalid (i.e. harvester site). If it is invalid, then redirect the browser to your blog.</p>
<p>Not only does this approach thwart harvesters (at least until they filter out the script), but it has the added benefit of getting the search traffic from the harvester&#8217;s site back to your blog.</p>
<p>Let&#8217;s walk through the changes you would make to your blog&#8217;s template in order to enable this capability:</p>
<p>Original blog HTML:</p>
<pre class="brush: html">This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog.</pre>
<hr size="2" />
Steps for modifying blog HTML:</p>
<p><strong>Step 1: Add DIV element wrapper for content<br />
</strong></p>
<pre class="brush: html">
&amp;lt;div id=&amp;quot;BlogContent&amp;quot; title=&amp;quot;http://www.yourblogsite.com/URL-of-your-blog-post.htm&amp;quot;&amp;gt;This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog.&amp;lt;/div&amp;gt;
</pre>
<p>I used an id of &#8220;BlogContent&#8221; but you can use anything you want. If your blog displays the entire contents of more than blog post on a page, you will want this entry to be changed for each blog. In that case, try using &#8220;BlogContent{{ ID }}&#8221; where {{ ID }} is your blog engine&#8217;s token for some unique identifier associated with your blog. If you take this approach, be sure to modify the &#8220;BlogContent&#8221; string in Step 2 also.</p>
<p>Also, note the URL in the value of the &#8220;title&#8221; attribute of the</p>
<div>
<p>containing the blog content. You should not actually type in a URL there, but instead use the token feature of your blog engine that will inject the URL of the blog post page. Something like:</p>
<pre class="brush: html">&amp;lt;div id=&amp;quot;BlogContent&amp;quot; title=&amp;quot;{{ PostURL }}&amp;quot;&amp;gt;</pre>
<p>({{ ID }} and {{PostURL}} are not an actual tokens&#8230;I just made them up. You will need to look at your blog engine&#8217;s documentation to figure out the tokens you should use.)</p>
<p>This URL serves two purposes:<br />
- It provides a standards-compliant way to include the original URL of your blog in the blog content so that no matter where the content is posted, the original URL is always in the <cite>HTML</cite> source code, and<br />
- It provides the script in Step 2 to have a known place to find the original URL</p>
<p><strong>Step 2: Embed script to foil harvesters</strong></p>
<p><strong> </strong>The script to embed is:</p>
<pre class="brush: html">&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;// &amp;lt;![CDATA[

var blogContent = document.getElementById(&amp;quot;BlogContent&amp;quot;);
if (location.href.toLowerCase().indexOf(blogContent.title.toLowerCase()) != 0) location.href = blogContent.title;
// ]]&amp;gt;&amp;lt;/script&amp;gt;
</pre>
<p>Here&#8217;s what the script is doing:</p>
<p>a) Find the HTML element containing the blog content</p>
<pre class="brush: javascript">var blogContent = document.getElementById(&amp;quot;BlogContent&amp;quot;);</pre>
<p>b) Test if the content is running on the original site, if not, then redirect to the original site</p>
<pre class="brush: javascript">
if (location.href.toLowerCase().indexOf(blogContent.title.toLowerCase()) != 0) location.href = blogContent.title;
</pre>
<p>Here&#8217;s what the final content might look like:</p>
<pre class="brush: html">
&amp;lt;div id=&amp;quot;BlogContent&amp;quot; title=&amp;quot;{{PostURL}}&amp;quot;&amp;gt;This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog.
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;// &amp;lt;![CDATA[

var blogContent = document.getElementById(&amp;quot;BlogContent&amp;quot;);
if (location.href.toLowerCase().indexOf(blogContent.title.toLowerCase()) != 0) location.href = blogContent.title;
// ]]&amp;gt;&amp;lt;/script&amp;gt;</pre>
<p><strong>Step 3: (Optional) Putting the script in a separate file</strong></p>
<p>Instead of placing the script in each blog post as described above, you can also put the script into a separate file such as <strong>harvestblock.js</strong>. This will reduce the page size as the entire script will not be repeated for each blog post. You only need to include this part of the script in the file</p>
<pre class="brush: javascript">var blogContent = document.getElementById(&amp;quot;BlogContent&amp;quot;);
if (location.href.toLowerCase().indexOf(blogContent.title.toLowerCase()) != 0) location.href = blogContent.title;</pre>
<p>If you do this, the revised content might look like:</p>
<pre class="brush: html">
&amp;lt;div id=&amp;quot;BlogContent&amp;quot; title=&amp;quot;{{PostURL}}&amp;quot;&amp;gt;This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog. This is the content of my blog.
&amp;lt;script src=&amp;quot;http://www.yourblog.com/harvestblock.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/div&amp;gt;
</pre>
<p>Note: The URL used for the script must be a fully-qualified URL because it must work no matter whether the content is running on your site or on the harvester&#8217;s site.</p>
<hr size="2" />
Let&#8217;s look at what happens when you make this change:</p>
<p><strong>1) User looking at content on your site<br />
</strong><br />
The script will detect a match between the URL being displayed in the browser and the URL of the blog post. As a result, it will do nothing and there will be no change in behavior from what your users are already seeing.</p>
<p><strong>2) User looking at content in their RSS reader</strong></p>
<p>The script will not run and as a result there will be no change in behavior from what your users are already seeing.</p>
<p><strong>3) User looking at content on harvester site</strong></p>
<p>The script will detect a mis-match between the URL being displayed in the browser and the URL of the blog post. As a result, it will redirect the user to the original blog post.</p>
<p>This solution is not fool-proof. If a harvester is stripping script embedded in a blog post then it will not work. I highly doubt this will happen very often because most harvested content is simply the content from the RSS feed as-is.</p>
<p>If you employ this solution please provide information on the specific token you use with your blogging engine in the comments.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.kalyani.com/2008/06/how-to-foil-blog-content-harvesters/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

