Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Tag Cloud with jQuery Effect

0.00/5 (No votes)
7 Mar 2010 1  
Tag Cloud WebControl built on the Star Field jQuery plug-in
DotNetSources_e0004

Table of Contents

Introduction

In this article, I'd like to share a Tag Cloud web control with a star filed jQuery effect. The jQuery plug-in itself was not written by me. You can find the plug-in on [1]. I just wrapped an existing plug-in into a web control in order to be used as quickly as possible for developers who want to avoid the JavaScript. I realize what I have done in this article is not too much, but I still think it could be very useful. Basically, you don't need to touch JavaScript to reach the effect. It is all wrapped for you in a Web Control. As you will see further, you can use it by writing just a few lines, and the effect is quite impressive.

I want to thank the author (BUG SOFTWARE) for this jQuery plug-in.

Live Demo

I'm using this Tag Cloud on my personal page in the right column. You can see it here.

Example of Use

The example is included in the download package, and it's very intuitive. Despite its simplicity, I'll describe the way to use it. It is just about adding a control into a page and filling it with some data. Download the code attached to this article, reference the library DotNetSources_e0004.dll in your web app, and register the control in web.config:

<add tagPrefix="dns" namespace="DotNetSources.Web.Core.Controls" 
                     assembly="DotNetSources_e0004"/>
Listing 1 - Register control namespace

... and use it:

<dns:Tagcloud runat="server" Id="myCloud" Width="400" Height="500" />
Listing 2 - Define a control in a page

Take a note of Width and Height. They must be set to some values; otherwise the control will have the size 0;0. The used jQuery plug-in works fine in any size of the Tag Cloud. Try it and see the effect.

Of course, you have to provide data which will be displayed by the Tagcloud. You can do it in any phase of the page-life cycle between Page_Load and OnPreRender included. In the following listing, you can see the code to bind the data.

List<Tag> tags = new List<Tag>();
tags.Add(new Tag() { Link = "#", Text = ".NET" });
tags.Add(new Tag() { Link = "#", Text = "ASP .NET" });
tags.Add(new Tag() { Link = "#", Text = "JavaScript" });
tags.Add(new Tag() { Link = "#", Text = "WCF" });
tags.Add(new Tag() { Link = "#", Text = "WPF" });
tags.Add(new Tag() { Link = "#", Text = "Silverlight" });
tags.Add(new Tag() { Link = "#", Text = "Web" });
tags.Add(new Tag() { Link = "#", Text = "C#" });
tags.Add(new Tag() { Link = "#", Text = "VB.NET" });
tags.Add(new Tag() { Link = "#", Text = "Visual Studio" });

myCloud.Tags = tags;
Listing 3 - Binding a data to Tag Cloud instance
Note: The control requires the jQuery library to be loaded. So, make sure you have a reference to the jQuery library in your page.

Example of use - Parameterization

You could consider the TagCloud to be too fast, too slow or whatever then you can customize it by the properties exposed on the web control. The following table describes the collection of properties you can use for customizing the behavior. The control does not provide any validation for input values, thus, if you set crazy values to the properties, you get a crazy behavior of the TagCloud. You have to simply try what is suitable for you.

Property Dafault Value Description
Interval 50 Interval between animation frames.
Xpos .5 X pos of where our tags 'fall' from.
Ypos .5 Y pos of where our tags 'fall' from.
Gravity -10 Force of gravity acting to drag Items towards the screen - changing negative / positive changes direction of the 'fall'.
HoverGravityFactor -1 Gravity amount when user hovers over the tag cloud - works a multiplier of opts.gravity
GravityVector 0,0,1 3D vector direction of gravity.
Range -200,300 Range to fall between - the lower the number the closer to the screen.
Table 1 - Table of properties for Tagcloud control

Tip: Stop Animation When Mouse Hover

To stop animation when mouse hover, just set the property HoverGravityFactor to 0.

<dns:Tagcloud runat="server" Id="myCloud" Width="400" Height="500" 
            HoverGravityFactor="0" />
Listing 7 - How to stop animation when mouse hover.

Implementation

The Tagcloud control is created as a web control with client-side capabilities. For a detailed description of this type of control, please read my previous article [2]. The Tagcloud control automatically registers all the JavaScript resources needed for the animation, except the jQuery library. As mentioned earlier, the jQuery loading is up to you in order to be free to choose the version of jQuery. I also mentioned that the control is very easy to use; therefore, I introduced the entire code in Listing 4.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;
using DotNetSources_e0004.Model;
using System.ComponentModel;
using System.Collections;

[assembly: WebResource("DotNetSources_e0004.Controls.Tagcloud.jquery.engine3D.js", 
		"text/javascript", PerformSubstitution = true)]
[assembly: WebResource("DotNetSources_e0004.Controls.Tagcloud.jquery.particlePhysics.js", 
		"text/javascript", PerformSubstitution = true)]
[assembly: WebResource("DotNetSources_e0004.Controls.Tagcloud.jquery.starfieldTagCloud.js", 
		"text/javascript", PerformSubstitution = true)]
[assembly: WebResource("DotNetSources_e0004.Controls.Tagcloud.Tagcloud.js", 
		"text/javascript", PerformSubstitution = true)]

namespace DotNetSources.Web.Core.Controls
{
    public class Tagcloud : WebControl, IScriptControl
    {
        #region Options for TagCloud

        private int interval = 50;

        /// <summary>
        /// Interval between animation frames.
        /// Default: 50
        /// </summary>
        public int Interval {
            get {
                return interval;
            }
            set {
                interval = value;
            }
        }

        private double xpos = .5;

        /// <summary>
        /// x pos of where our tags 'fall' from
        /// Default: .5
        /// </summary>
        public double Xpos {
            get {
                return xpos;
            }
            set {
                xpos = value;
            }
        }

        private double ypos = .5;

        /// <summary>
        /// y pos of where our tags 'fall' from
        /// Default: .5
        /// </summary>
        public double Ypos {
            get {
                return ypos;
            }
            set {
                ypos = value;
            }
        }

        private int gravity = -10;

        /// <summary>
        /// Force of gravity acting to drag 
        /// Items towards the screen - changing negative / positive changes 
        /// direction of the 'fall'
        /// Default: -10
        /// </summary>
        public int Gravity {
            get {
                return gravity;
            }
            set {
                gravity = value;
            }
        }

        private int hoverGravityFactor = -1;

        /// <summary>
        /// Gravity amount when user hovers over the tag cloud - works a multiplier 
        /// of opts.gravity
        /// Default: -1
        /// </summary>
        public int HoverGravityFactor {
            get {
                return hoverGravityFactor;
            }
            set {
                hoverGravityFactor = value;
            }
        }

        private string gravityVector = "0,0,1";

        /// <summary>
        /// 3D vector direction of gravity. 
        /// Default [0,0,1]
        /// </summary>
        public string GravityVector {
            get {
                return gravityVector;
            }
            set {
                gravityVector = value;
            }
        }

        private string range = "-200,300";

        /// <summary>
        /// 2D vector.
        /// Range to fall between - the lower the number the closer to the screen.
        /// Default [-200,300]
        /// </summary>
        public string Range { 
            get { 
                return range; 
            } 
            set { 
                range = value; 
            } 
        }

        #endregion

        public Tagcloud()
            : base(HtmlTextWriterTag.Div)
        {
        }

        public IEnumerable<Tag> Tags { get; set; }

        ScriptManager sm;

        protected override void OnPreRender(EventArgs e)
        {
            if (!this.DesignMode)
            {
                sm = ScriptManager.GetCurrent(Page);
                sm.RegisterScriptControl(this);
            }
            base.OnPreRender(e);

            Literal lit = new Literal();
            if (Tags == null)
                throw new Exception("Fill the Tag property.");
            StringBuilder sb = new StringBuilder();
            sb.Append("<ul>");
            foreach (Tag tag in Tags)
            {
                sb.AppendFormat("<li><a href='{0}'>{1}</a></li>", tag.Link, tag.Text);
            }
            sb.Append("</ul>");
            lit.Text = sb.ToString();
            Controls.Add(lit);
        }

        /// <summary>
        /// 
        /// <summary>
        /// <param name="writer"></param>
        protected override void Render(HtmlTextWriter writer)
        {
            if (!this.DesignMode)
            {
                sm.RegisterScriptDescriptors(this);
            }
            base.Render(writer);
        }


        #region IScriptControl Members

        public IEnumerable<ScriptDescriptor> GetScriptDescriptors()
        {
            ScriptControlDescriptor descriptor =
              new ScriptControlDescriptor("DotNetSources.Tagcloud", this.ClientID);
            descriptor.AddProperty("options", BuildOptions());
            return new ScriptDescriptor[] { descriptor };
        }

        public IEnumerable<ScriptReference> GetScriptReferences()
        {
            List<ScriptReference> ret = new List<ScriptReference>();
            ScriptReference jsReference = new ScriptReference();
            jsReference.Assembly = "DotNetSources_e0004";
            jsReference.Name = "DotNetSources_e0004.Controls.Tagcloud.jquery.engine3D.js";
            ret.Add(jsReference);
            jsReference = new ScriptReference();
            jsReference.Assembly = "DotNetSources_e0004";
            jsReference.Name = 
		"DotNetSources_e0004.Controls.Tagcloud.jquery.particlePhysics.js";
            ret.Add(jsReference);
            jsReference = new ScriptReference();
            jsReference.Assembly = "DotNetSources_e0004";
            jsReference.Name = 
		"DotNetSources_e0004.Controls.Tagcloud.jquery.starfieldTagCloud.js";
            ret.Add(jsReference);
            jsReference = new ScriptReference();
            jsReference.Assembly = "DotNetSources_e0004";
            jsReference.Name = "DotNetSources_e0004.Controls.Tagcloud.Tagcloud.js";
            ret.Add(jsReference);
            return ret.ToArray();
        }

        #endregion

        private Hashtable BuildOptions()
        {
            Hashtable table = new Hashtable();
            table.Add("interval", Interval);
            table.Add("xPos", Xpos);
            table.Add("yPos", Ypos);
            table.Add("gravity", Gravity);
            table.Add("hoverGravityFactor", HoverGravityFactor);
            table.Add("gravityVector", GetVector(GravityVector));
            table.Add("range", GetVector(Range));
            return table;
        }

        private int[] GetVector(string value)
        {
            try
            {
                List<int> ret = new List<int>();
                string[] tmp = value.Split(',');
                foreach (string s in tmp)
                    ret.Add(int.Parse(s.Trim()));
                return ret.ToArray();
            }
            catch (Exception ex)
            {
                throw new Exception(
                    "The vector " + 
                    value + 
                    " is in the wrong format. 
		 Should be the collection of numbers splitted by ','.", 
                    ex);
            }
        }

    }
}
Listing 4 - Tagcloud control

I hope there is nothing complicated in Listing 4. If you don't understand any piece of code, please read [2]. The JavaScript class of Tagcloud is also very simple. It just executed the Star Field Tag cloud plug-in when the page is loaded. See the JavaScript class in Listing 5.

Type.registerNamespace("DotNetSources.Tagcloud");

DotNetSources.Tagcloud = function(element) {
    DotNetSources.Tagcloud.initializeBase(this, [element]);

    // fields
    this._options = null;

    // handlers
    this._onClickHandler = null;
}

DotNetSources.Tagcloud.prototype = {

    initialize: function() {
        DotNetSources.Tagcloud.callBaseMethod(this, 'initialize');
        var t = $('#' + this.get_id());
        t.starfieldTagCloud(this._options);
    },

    get_options: function() {
        return this._options;
    },

    set_options: function(value) {
        this._options = value;
    },

    dispose: function() {
        //Add custom dispose actions here
        DotNetSources.Tagcloud.callBaseMethod(this, 'dispose');
    }
}
DotNetSources.Tagcloud.registerClass('DotNetSources.Tagcloud', Sys.UI.Control);
Listing 5 - The Tagcloud JavaScript class

Points of Interest

This WebControl could also show you the easy way to extend a WebControl of jQuery plug-in. Basically you can apply it to any jQuery plug-in you find on the internet.

Conclusion

Thank you for reading. I hope it was useful for you. As usual, I'm interested in feedback, so don't hesitate to write a comment or vote. Thank you very much.

References

History

  • 1 March 2010
    • Initial release
  • 6 March 2010
    • Code changes
      • Parameterization of animation added
      • Option to stop the animation added
    • Text changes
      • Description of parameterization
      • Sample code updated

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here