Vyoms OneStopTesting.com - Testing EBooks, Tutorials, Articles, Jobs, Training Institutes etc.
OneStopGate.com - Gate EBooks, Tutorials, Articles, FAQs, Jobs, Training Institutes etc.
OneStopMBA.com - MBA EBooks, Tutorials, Articles, FAQs, Jobs, Training Institutes etc.
OneStopIAS.com - IAS EBooks, Tutorials, Articles, FAQs, Jobs, Training Institutes etc.
OneStopSAP.com - SAP EBooks, Tutorials, Articles, FAQs, Jobs, Training Institutes etc.
OneStopGRE.com - of GRE EBooks, Tutorials, Articles, FAQs, Jobs, Training Institutes etc.
Bookmark and Share Rss Feeds

Tag Cloud in ASP.NET MVC using Clickable HTML 5 Canvas Elements | Articles | Recent Articles | News Article | Interesting Articles | Technology Articles | Articles On Education | Articles On Corporate | Company Articles | College Articles | Articles on Recession
Sponsored Ads
Hot Jobs
Fresher Jobs
Experienced Jobs
Government Jobs
Walkin Jobs
Placement Section
Company Profiles
Interview Questions
Placement Papers
Resources @ VYOMS
Companies In India
Consultants In India
Colleges In India
Exams In India
Latest Results
Notifications In India
Call Centers In India
Training Institutes In India
Job Communities In India
Courses In India
Jobs by Keyskills
Jobs by Functional Areas
Learn @ VYOMS
GATE Preparation
GRE Preparation
GMAT Preparation
IAS Preparation
SAP Preparation
Testing Preparation
MBA Preparation
News @ VYOMS
Freshers News
Job Articles
Latest News
India News Network
Interview Ebook
Get 30,000+ Interview Questions & Answers in an eBook.
Interview Success Kit - Get Success in Job Interviews
  • 30,000+ Interview Questions
  • Most Questions Answered
  • 5 FREE Bonuses
  • Free Upgrades

VYOMS TOP EMPLOYERS

Wipro Technologies
Tata Consultancy Services
Accenture
IBM
Satyam
Genpact
Cognizant Technologies

Home » Articles » Tag Cloud in ASP.NET MVC using Clickable HTML 5 Canvas Elements

Tag Cloud in ASP.NET MVC using Clickable HTML 5 Canvas Elements








Article Posted On Date : Thursday, February 9, 2012


Tag Cloud in ASP.NET MVC using Clickable HTML 5 Canvas Elements
Advertisements

We will build a Tag cloud functionality using HTML5 Canvas. Though HTML5 or Canvas is not a pre-requisite to build a Tag Cloud, we will take it as a use case to learn

    *
      How to Draw text on canvas
    *
      Measure height of text on canvas
    *
      Measure width of text on canvas
    *
      Set Font family and size of text canvas
    *
      Make canvas items clickable. By default, canvas doesn't provide any way of tracking click in individual items on it. A canvas is what it's name implies - a blank slate. It will raise a click event if you click on it, but to detect what you clicked on, you need to wire up some code.

- The Server side code will have examples of

    *
      How a POCO can be made query-able in LINQ.
    *
      Chain LINQ queries

Let's get started. You can get the RavenDB code from here. The final code base is available over here

Step 1: Build and Run the code.

Step 2: Since we start off with an empty database, it will be good to have some test data for us. You can use the attached script (in the final code base) to generate some test blogs.

Build and run the Application once to create the Database (if it doesn't exist already). Start SQL (Express) Management Studio and execute the GenerateBlogData.sql to generate some test data.

You could create some blogs manually too. (Don't forget to mark the newly created blogs as Published else you will have to log in to view them).

Step 3: The Tag cloud should be present in the blog's Index page. So let's update the Index.cshtml. We add an external <div> to encapsulate the entire blog list and Canvas element, and set its width to 900px.

There are two inner <div> elements, one containing the blog items and the other containing the canvas that will have the tag cloud.

index-tag-cloud-div

Step 4: To get data for the tags, we will make an asynchronous call using jQuery to an action method in our Blog controller. Drop in the following script to wire up the controller

js-load-tags

This above code calls the Tags action method on the Blog controller. It will return a string representing a JSON array.

Step 5: The populateTagCloud parameter is a method delegate that will be called once the Action method returns. The implementation is as follows

a. Get the canvas object (tagCloudCanvas)

b. Retrieve the 2D context

c. Convert the string returned from the controller into a JSON object

d. lastXPos and lastYPos handle manage the top left (x, y) co-ordinates as we loop through each tag returned

e. TagSize is a weighted value calculated in the service layer that tells us how big, font of each tag should be. We can use logic like number of hits, most recently accessed or simply the number of blog items with the particular tag to determine the size. The frontend is not concerned with the logic but simply the value of TagSize. As we see below, TagSize is multiplied by ten (10) to get to the final font size.

f. Font size and font family is then set to canvasContext.font property. You can change this value before every attempt to draw text

js-populate-tag-cloud

g. Once the font size and font is set, we retrieve the width of the tag's text using the canvas context's measureText API.

h. The 'if' condition checks if the amount of space remaining after the last write is enough to fit in the new tag. If it is, the new tag is written to the right of the old tag.

i. Else it's written below the previous tag. As you can see positioning is absolute with respect to canvas position.

j. The call to filltext method actually paints the text.

k. tagClickHandler is the method delegate that will actually be called when user clicks on a the tag text in the canvas.

Step 6: The createClickMap function

js-create-clickmaps

 

a. The createClickMap function is passed the following parameters

    *
      The canvas object on which the operations are happening
    *
      Top left (x, y) coordinates of the area containing the tag text
    *
      Width (w) and Height (h) of the text
    *
      Function delegate that should be called if conditions are fulfilled.
    *
      And the Json object containing the Tag Name, Id and other details

b. The first line attaches a click event handler.

c. The inline function generates the relative positions mX and mY for the click location.

d. Checks if the function m returns true by passing it the text position and the click position. By an interesting use of inline function, we have avoided explicit declaration of a map to store the text's location. Instead we let the JS interpreter manage the function tables, where each function will have it's own set of values for x, y, w, h, mx and my.

e. Reference: David Pirek's blog here.

f. The tagClickHandler method generates the Url to the Index page with the tag name as parameter and redirects the page to this Url. This covers all the UI changes we had to do. At this point, if you are a non-ASP.NET developer, you would have realized that if you pass a JSON stream to the Tag cloud, the cloud will render itself and make itself clickable.

If you are looking for JavaScript only solution, you could very well stop here. But if you are a .Net junkie let's move on and wire up the controller and the controller with the layers further down.

Step 7: Retrieving unique Tags for the tag cloud

a. If you remember, we did not have a 'Tag' domain object because at the domain level all we needed earlier was a string representing all the tags. But now we need a separate Tag object so that we can query it, filter it and get unique values out of it.

b. We add a new Tag class to the Domain model. The code looks as follows:

tag-iequatable

c. As we can see it's not a POCO rather a class that implements IEquatable<Tag> interface. As we will see shortly we need only unique Tag names and to control whether an object is should be treated as Equal or not in LINQ we need to implement this interface.

d. In the above code, we implement Equal functionality to return true if the Id and the Name of the tag are the same. As we have learnt, since the wee days of dot net, if you have a custom Equals method you should override GetHashCode and make sure you provide unique hash codes yourself. Hence we have overridden the GetHashCode method as well.

Step 8: Updating the Repository implementations

a. With the tag cloud in place, we will update the repository to return us a list of tags. We will also add an overloaded GetPosts method that will accept isAuthenticated and tagName as parameters and return blogs with the given tagName only.

b. Add the following methods in the abstract class BlogPostRepository

abstract-repository-new-methods

c. Update the RavenBlogPostRepository.cs with empty methods

d. Update the SqlBlogPostRepository.cs with the following GetTags method implementation

repository-get-tags

Let's look at the LINQ query inside the if(userAuthenticated) in a little bit of details. The inList var stores a query to get all the Tags in the system. Now we need the count of how many times a tag has appeared on the blog. This will be a factor that we use to indicate the font size of the tag. The postTags query that selects all the BlogPosts and then flattens them out using the SelectMany to give us a list of the Blog-to-Post relationships.

Next we do a join with the PostTags to determine the tags in use.

The select new statement actually creates a projection of the return values. In this case, we are able to project it into a Domain Tag object. So we end up populating outList with required Domain Tag objects.

The LINQ query in the else statement does an additional join to filter out Tags associated with blogs that are not in Published status. Essentially, we don't consider Tags that are associated with blogs in Draft status.

e. Similar to the GetTags method we implement the GetPosts method as follows

repository-get-posts

This first query returns a list of domain BlogPost objects filtered by the tagName. The second query filters it for blogs in published status only.

Note: Since we are calling post.ToDomainBlogPost() in the query, we need to load the BlogPosts eagerly (no deferred execution). So in this case, inList actually has the data. If we don't do that, LINQ will defer execution to the point of posts.ToList<Domain.Model.BlogPost>(). Now when it executes the query, it tries to project the list into Domain.Model.BlogPost instead of Data.Model.BlogPost. This results in a method not found exception.

Step 9: Updating the ProductService

Now that the Repository is setup to return Tags and Posts filtered by tags, let's update our service layer. One thing we want to do is 'normalize' the PostCount value so that if one tag has 1000 posts associated whereas another has only 1 post associated, we don't end up with Tags that are too big or too small to see. To do that we use the following algorithm:

a. We decide we will show say 10 different sizes of fonts (MAX_FONT_SIZES_COUNT).

b. This count does not co-relate to number of distinct tags or number of blogs each tag is associated with. It is simply the number of different font sizes we will use to represent the tags

c. Determining density: It is the factor that tells how many different tags we will have to lump together in each font size. In our case we are using how many distinct buckets of post tags we have divided by the maximumAllowedCount, which is either MAX_FONT_SIZES_COUNT or the actual number of count.

d. We choose number of posts a tag is associated with as the factor determining the size of the tag font. So we get a list of these numbers. (it is stored in distinctCounts).

e. Then we loop through them and based on the density assign the count a font size. This mapping helps keep the calculate n+m where n = distinct post counts and m = number of tags.

f. Finally we loop through the tags and based on the PostCount assign the font size.

The final code looks as follows:

service-get-tags

Step 10: Updating the Controller.

Getting the Tags

a. The tag cloud calls an Action method called Tags that returns a JSON object. So we will update our BlogController with the following method.

controller-tags

b. This method instantiates the BlogPostService and calls the GetTags method. It also passed the User.Identity object so that we pull up articles based on whether the current user is logged in or not.

c. The service method returns an IEnumerable<Tag> that is converted using the Json helper method.

d. Note the JsonRequestBehavior.AllowGet parameter. Without this method ASP.MVC will block Json requests and you will get null values instead of the Json stream at the front-end.

Filtering Index based on tag name.

a. We update the existing Index method to take a string parameter that is the tag name selected.

b. If the name is null or empty we call the old GetPosts method. Else we call the new GetPosts method and pass it the tag name.

controller-index

c. There is one slight problem here, the Routing engine by default assumes the parameters being passed in an action method map to an Id. It's easy to pass an Id from the UI but the Url would like like

http://myblog.com/Blog/Index/1 where 1 stands for the tag's Id. Instead we want it to say http://myblog.com/Blog/MVC to indicate the current page is showing MVC tags only. To do this, we need to update the Routing table. The Routing table is configured in the Global.asax. The changes are highlighted below. The named parameter name corresponds to the input parameter name in the Action method.

register-routes
Other Changes

a. There are some more cosmetic CSS change for the bread-crumb, the header and footer for each blog post.

b. All the while I was testing without RavenDB server running so I kept getting exceptions. Put in a little exception handling for that.
Conclusion

We started with the simple aim to create a tag cloud and in process, learn a bit of HTML5 Canvas. However on the way we also looked at LINQ and ASP.NET MVC routing.

The next step would be to add hover support on the canvas so that when you hover on the Tags, they change cursor and color to look more realistic.

Last but not least, we are looking at basic HTML5 Canvas manipulation hence the low-level javascript work. You could easily use something like kinetic.js canvas library that encapsulates the creation of Canvas elements and provides extensions for click and hover and drag and drop handlers. We leave that for another day. 






Sponsored Ads



Interview Questions
HR Interview Questions
Testing Interview Questions
SAP Interview Questions
Business Intelligence Interview Questions
Call Center Interview Questions

Databases

Clipper Interview Questions
DBA Interview Questions
Firebird Interview Questions
Hierarchical Interview Questions
Informix Interview Questions
Microsoft Access Interview Questions
MS SqlServer Interview Questions
MYSQL Interview Questions
Network Interview Questions
Object Relational Interview Questions
PL/SQL Interview Questions
PostgreSQL Interview Questions
Progress Interview Questions
Relational Interview Questions
SQL Interview Questions
SQL Server Interview Questions
Stored Procedures Interview Questions
Sybase Interview Questions
Teradata Interview Questions

Microsof Technologies

.Net Database Interview Questions
.Net Deployement Interview Questions
ADO.NET Interview Questions
ADO.NET 2.0 Interview Questions
Architecture Interview Questions
ASP Interview Questions
ASP.NET Interview Questions
ASP.NET 2.0 Interview Questions
C# Interview Questions
Csharp Interview Questions
DataGrid Interview Questions
DotNet Interview Questions
Microsoft Basics Interview Questions
Microsoft.NET Interview Questions
Microsoft.NET 2.0 Interview Questions
Share Point Interview Questions
Silverlight Interview Questions
VB.NET Interview Questions
VC++ Interview Questions
Visual Basic Interview Questions

Java / J2EE

Applet Interview Questions
Core Java Interview Questions
Eclipse Interview Questions
EJB Interview Questions
Hibernate Interview Questions
J2ME Interview Questions
J2SE Interview Questions
Java Interview Questions
Java Beans Interview Questions
Java Patterns Interview Questions
Java Security Interview Questions
Java Swing Interview Questions
JBOSS Interview Questions
JDBC Interview Questions
JMS Interview Questions
JSF Interview Questions
JSP Interview Questions
RMI Interview Questions
Servlet Interview Questions
Socket Programming Interview Questions
Springs Interview Questions
Struts Interview Questions
Web Sphere Interview Questions

Programming Languages

C Interview Questions
C++ Interview Questions
CGI Interview Questions
Delphi Interview Questions
Fortran Interview Questions
ILU Interview Questions
LISP Interview Questions
Pascal Interview Questions
Perl Interview Questions
PHP Interview Questions
Ruby Interview Questions
Signature Interview Questions
UML Interview Questions
VBA Interview Questions
Windows Interview Questions
Mainframe Interview Questions


Copyright © 2001-2024 Vyoms.com. All Rights Reserved. Home | About Us | Advertise With Vyoms.com | Jobs | Contact Us | Feedback | Link to Us | Privacy Policy | Terms & Conditions
Placement Papers | Get Your Free Website | IAS Preparation | C++ Interview Questions | C Interview Questions | Report a Bug | Romantic Shayari | CAT 2024

Fresher Jobs | Experienced Jobs | Government Jobs | Walkin Jobs | Company Profiles | Interview Questions | Placement Papers | Companies In India | Consultants In India | Colleges In India | Exams In India | Latest Results | Notifications In India | Call Centers In India | Training Institutes In India | Job Communities In India | Courses In India | Jobs by Keyskills | Jobs by Functional Areas

Testing Articles | Testing Books | Testing Certifications | Testing FAQs | Testing Downloads | Testing Interview Questions | Testing Jobs | Testing Training Institutes

Gate Articles | Gate Books | Gate Colleges | Gate Downloads | Gate Faqs | Gate Jobs | Gate News | Gate Sample Papers | Gate Training Institutes

MBA Articles | MBA Books | MBA Case Studies | MBA Business Schools | MBA Current Affairs | MBA Downloads | MBA Events | MBA Notifications | MBA FAQs | MBA Jobs
MBA Job Consultants | MBA News | MBA Results | MBA Courses | MBA Sample Papers | MBA Interview Questions | MBA Training Institutes

GRE Articles | GRE Books | GRE Colleges | GRE Downloads | GRE Events | GRE FAQs | GRE News | GRE Training Institutes | GRE Sample Papers

IAS Articles | IAS Books | IAS Current Affairs | IAS Downloads | IAS Events | IAS FAQs | IAS News | IAS Notifications | IAS UPSC Jobs | IAS Previous Question Papers
IAS Results | IAS Sample Papers | IAS Interview Questions | IAS Training Institutes | IAS Toppers Interview

SAP Articles | SAP Books | SAP Certifications | SAP Companies | SAP Study Materials | SAP Events | SAP FAQs | SAP Jobs | SAP Job Consultants
SAP Links | SAP News | SAP Sample Papers | SAP Interview Questions | SAP Training Institutes |


Copyright ©2001-2024 Vyoms.com, All Rights Reserved.
Disclaimer: VYOMS.com has taken all reasonable steps to ensure that information on this site is authentic. Applicants are advised to research bonafides of advertisers independently. VYOMS.com shall not have any responsibility in this regard.