Introduction
This article helps to understand - How to:
- use a tooltip in MVC app
- use the project resource for tooltip info
- customize the cluetip, jquery plugin, to display dynamic title
This sample web app integrates tooltip in an MVC view (MainPage.cshtml). The app is written using - VS2010 MVC3,C#, JQuery and cluetip plugin. The cluetip can be downloaded from http://plugins.learningjquery.com/cluetip.
Sample Web page with tooltip
How Does It Display Tooltip
When user clicks on the view, the HTML element that has the tooltip does an ajax call to action
method in the controller
class. The action
method returns the tooltip information. The model
class reads the information from resource and passes to the Ajax post call.The information to be displayed in tooltip is part of the project resource.
The cluetip is good for decent tooltips. It is easy to use. But you may have to do some customization like "dynamic title update" that you see in the project.
Using the Code
How Does It Work
In a typical MVC app, the code functionality is split into model, controller & the view(HTML). In this sample, the model's GetToolTip()
returns the tooltip as ToolTipMvcModel
object. The ToolTipMvcModel
has 2 fields- Field
and Description
. Field
is tootip title, and the Description
is actual tooltip. The controller's ToolTip()
action method calls model
's GetToolTip()
method. The ToolTip()
method is attributed with [HttpPost]
so that only the 'post' requests can call this method. Finally the view(cshtml file), tooltip is invoked on click event of the HTML element. This click
event does an ajax call that executes the controller's ToolTip()
method.
Model Code
The information to be displayed for tooltip is stored in the project resource(resx file) and is accessed through the model
class.The static
method GetToolTip()
of the model
class returns the tooltip information. The tooltip information is stored as name, value pair in the resource. The name stores the year and value stores Field
and Description
that are to be populated to ToolTipMvcModel
object. The Field
and Description
are delimited using $_$_$
.
public static ToolTipMvcModel GetToolTip(string toolTipId)
{
ToolTipMvcModel item = new ToolTipMvcModel(toolTipId);
System.Resources.ResourceSet set = ToolTipMvc.TooTipMvcResource.ResourceManager.
GetResourceSet(System.Globalization.CultureInfo.CurrentCulture, true, true);
string strRes = set.GetString(toolTipId);
bool bfound = false;
if(!string.IsNullOrEmpty(strRes))
{
string[] strData = strRes.Split(splitParam,StringSplitOptions.None);
if(strData.Length >= 2)
{
try
{
item.Field = strData[0].Split(new string[] { "==" }, StringSplitOptions.None).Where(
x => string.Compare("field", x.Trim(), true) != 0).First();
item.Description = strData[1].Split(new string[] { "==" }, StringSplitOptions.None).Where(
x => string.Compare("description", x.Trim(), true) != 0).First();
bfound = true;
}
catch (Exception) { }
}
}
if (!bfound)
{
item.Field = "Error";
item.Description = "Sorry Tool Tip for the selected year not found!";
}
return item;
}
Controller Code
The action method ToolTip()
in controller calls Model
class method GetToolTip().
The TooTip()
method is invoked only by view's post requests. This is the reason it uses [HttpPost]
attribute. Because our intention is to serve only Ajax calls, for non Ajax calls the method returns an empty string
.
[HttpPost]
public ActionResult ToolTip(string id)
{
if (!Request.IsAjaxRequest())
return Json("");
ToolTipMvc.Models.ToolTipMvcModel model =
ToolTipMvc.Models.ToolTipMvcModel.GetToolTip(id);
return Json(model);
}
View Code
The view (MainPage.cshml in sample) does two things - define the HTML elements and register the elements with tooltip control by calling RegisterToolTip()
JavaScript method.
<a href="#" id="ctrl2011" title="tooltip">2011 Spellingbee winning word: Cymotrichous</a>
$(document).ready(function () {
RegisterToolTip(<a href="mailto:'@Url.Action("ToolTip")'">
'@Url.Action("ToolTip")'</a>, 'ctrl2011', 2011);
});
Following is RegisterToolTip()
JavaScript method. This is extended on cluetip basic behavior. On Ajax call return, clutip()
calls ajaxProcess
callback. The ajaxProcess
callback stores the title in element's DOM using jquery data()
function. The Cluetip
expects(atleast the current version) a static title, title that you hardcode during HTML page design. But we have a dynamic title from project resource so the only option is to use 'onshow
' callback, and set the title.
function RegisterToolTip(action, ctrlId, dispInfoId) {
$("#" + ctrlId).attr("rel", action).cluetip({
closePosition: "top",
activation: 'click',
width: 350,
sticky: true,
debug: true,
showTitle: true,
dropShadow: true,
cluetipClass: 'default',
closeText: '<div class="ui-state-error-icon ui-icon-closethick"
id="close" title="Close"/>',
mouseOutClose: true,
ajaxSettings: {
type: "post",
dataType: "json",
data: { "id": dispInfoId }
},
ajaxProcess: function (dataOut) {
$("#" + ctrlId).data("title", dataOut["Field"]);
return dataOut["Description"];
},
onShow: function (ct, c) {
var t = $("#" + ctrlId).data("title");
$("#cluetip-title").text(t);
}
});
}
Points of Interest
The main problem I encountered with cluetip is that it does not allow dynamic title by default. This is because the cluetip()
call already constructed the title. This I learned by debugging its code. But we get the dynamic title on Ajax call, the Ajax call returned title is set in onShow
callback.