JQuery Tooltips with MVC3 and CSS 3.0 (Part 2)

by Admin 25. March 2012 02:56

So in my previous post I explained all of the steps required to create a simple but effective CSS 3 JQuery tooltip implementation.  This was a good start, I had all I needed to fulfill my requirement of a consistent tooltip in my application.  But I needed it to be a little easier to use throughout the application.  A custom Html Helper Extension to the rescue. Creating an HTML Helper is a pretty straight forward task this one, however, needed a bit of special sauce to make it work the way I wanted.

First I wanted to make sure I could bind it to my model, in case in the future I wanted to default it to the [Display] property on the model.  Second I wanted to be able to use the @<text></text> syntax for the contents of the tooltip.  It made sense to work backwards I wanted the control to work like this: 

@Html.InfoTooltipFor(model => model.ToolTipTitle,
			<b>Scott Guthrie</b> – 
			<a href="http://weblogs.asp.net/scottgu/">
				ScottGu's Blog
			</a> One of the best resources for all things Microsoft Web
			<b>Scott Hanselman</b> – 
				<a href="http://www.hanselman.com/blog/">
					Scott Hanselman's Computer Zen
				</a> Another great resource very current and very informative.
			<b>ASP.NET</b> – 
				<a href="http://www.asp.net/mvc">
				</a> The mother of all things ASP.NET MVC


Seemed simple enough so at first I create the Helper as follows:


public static MvcHtmlString InfoTooltipFor<TModel, TValue>(
    this HtmlHelper<TModel> html, 
    Expression<Func<TModel, TValue>> expression, 
    string tooltip)


Nope that won't work... 


And once I thought about it makes sense that a string won't work.  It isn't anything remotely like a string it contains functions, delegates and properties. I know this type of implementation exists I have seen it in other controls.  So how is it done?  After an exhaustive google search I found this article by Phil Haack.  It was close to what I needed, so, after some trial and error I came up with this:

public static MvcHtmlString InfoTooltipFor<TModel, TValue>(this HtmlHelper<TModel> html, 
		Expression<Func<TModel, TValue>> expression, 
		Func<object, HelperResult> tooltip)
	//Get the Model metadata
	ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
	string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
	string tooltipId = metadata.PropertyName ? ? htmlFieldName.Split('.').Last();

	if (String.IsNullOrEmpty(tooltipId))
		return MvcHtmlString.Empty;
	//creates the span tag for the image
	TagBuilder spanTag = new TagBuilder("span");
	spanTag.MergeAttribute("class", "tooltipItem");
	spanTag.MergeAttribute("id", tooltipId);
	spanTag.MergeAttribute("data-tooltip", "tt" + tooltipId);

	TagBuilder imgTag = new TagBuilder("img");
	imgTag.MergeAttributes(new RouteValueDictionary(
			@class = "infoimage",
			src = UrlHelper.GenerateContentUrl("~/Content/info.png", html.ViewContext.HttpContext),
			alt = "info"
	spanTag.InnerHtml = imgTag.ToString(TagRenderMode.Normal);

	//creates the tooltip contents
	TagBuilder tooltipTag = new TagBuilder("div");
	tooltipTag.MergeAttribute("class", "hidden");
	tooltipTag.MergeAttribute("id", "tt" + tooltipId);
	tooltipTag.MergeAttribute("name", "tt" + tooltipId);
	tooltipTag.MergeAttribute("data-tooltip", "tt" + tooltipId);
	tooltipTag.InnerHtml = tooltip(null).ToString();

	return MvcHtmlString.Create(spanTag.ToString(TagRenderMode.Normal) + tooltipTag.ToString(TagRenderMode.Normal));

The key is Func<object, HelperResult> this allows templated items to be passed into helper method.  This was exactly what I needed and poof like magic it worked.  MVC is awesome, creating a control like that in standard ASP.NET would have been a major pain. 

The entire solution is in the attached zip...

EasyTooltips.zip (2.46 mb)

Tags: , , , ,

AJAX | css | jquery | MVC3

JQuery Tooltips with MVC3 and CSS 3.0 (Part 1)

by Admin 24. March 2012 17:58

I am a developer and no graphic artist by any strech of the imagination, but I am often thrown into that roll.   Seriously, how many small projects have the budget for a Graphic artist and a developer, not to mention the fact management rarely knows the difference.  

Regardless, I needed to create some tooltips to be used throughout an internal web application I was creating.  There are about 30 trillion jquery tooltip plugins on the internet, and most of them are good, I felt a little plugin overloaded, so I decide to roll my own.  The CSS 3.0 implementation was pretty simple (only 2 classes):

   border-bottom-left-radius: 15px;
   border-top-left-radius: 0px;
   border-bottom-right-radius: 15px;
   border-top-right-radius: 15px;
   border: 1px solid #0099FF;
   z-index: 20000;
   box-shadow: 3px 3px 2px #808080;

Only a few CSS 3.0 items to mention box-shadow (for the drop shadow effect) and border-radius (for the rounded corners on all but the top right) other than that pretty standard.  The JavaScript was pretty simple as well:

A few global variables:

//A 1/2 Second fade-in/out
var toolTipHideDelay = 500;
//A 1/4 second before the tooltip begins to fade
var toolTipMouseoutDelay = 250;
//The timer to determine when the fade should start
var toolTipHideTimer = null;
//The variable containing the tool tip contents
var tooltipWindow = null;
//The current Id of the tool tip
var tooltipCurrentId = null;

Then the actual tool event handlers:

//standard doc ready event
$(document).ready(function () {
function initializeTooltips() {
    //there is only one window for all tooltips on the page.
    tooltipWindow = $("#tooltipWindow");
    //all tooltips implement the following class
    var tooltipItem = $(".tooltipItem");
    //tooltip mouse events (not using hover because I want the tooltip to follow the cursor
    tooltipItem.mousemove(function (e) {
        //check to see if the tooltip is already opened
        if (toolTipHideTimer) {
            //clear the timeout since the user is hovering over the item again
            //retrieve the tooltip data item from the current element
            if (tooltipCurrentId != $(this).data("tooltip")) {
                setToolTipPosition(this, e);
                //set the tooltip inner content
                tooltipWindow.html($("#" + $(this).data("tooltip")).html());
        } else {
            //show the tooltip
            setToolTipPosition(this, e);
            //the tooltip is hidden do fade it in
            //set the tooltip inner content
            tooltipWindow.html($("#" + $(this).data("tooltip")).html());
    tooltipItem.mouseout(function (e) {
        //get ready to hide the tooltip
        toolTipHideTimer = setTimeout(function () {
            toolTipHideTimer = null;
        }, toolTipMouseoutDelay);
    //tooltip window mouse events
    tooltipWindow.mouseover(function () {
        //keep the tooltip open if the user is over the tooltip window
        if (toolTipHideTimer) {
    tooltipWindow.mouseout(function () {
        //get ready to hide the tooltip
        toolTipHideTimer = setTimeout(function () {
            toolTipHideTimer = null;
        }, toolTipMouseoutDelay);

Then just a simple postion helper:

function setToolTipPosition(item, mouseevent) {
    var tooltipitem = $("#tooltipWindow");
    //set the tool tip to the current mouse position the 
    //2+ is so the user can still click the element under the 
        left: 2+(mouseevent.pageX) + "px",
        top: 2+(mouseevent.pageY) + "px"

So now we have all of the client pieces we need, infact the following html will generate a tooltip:

<h3 style="display:inline-block">For More info hover over the icon</h3>
<span class="tooltipItem" data-tooltip="ttToolTipTitle" id="ToolTipTitle">
  <img alt="info" class="infoimage" src="/Content/info.png" />
<div class="hidden" data-tooltip="ttToolTipTitle" id="ttToolTipTitle" name="ttToolTipTitle">        
            <h4>Learn More from these sites</h4>
                <li><b>Scott Guthrie</b> – <a href="http://weblogs.asp.net/scottgu/">ScottGu's Blog</a> One of the best resources for all things Microsoft Web</li>
                <li><b>Scott Hanselman</b> – <a href="http://www.hanselman.com/blog/">Scott Hanselman's Computer Zen</a> Another great resource very current and very informative.</li>
                <li><b>ASP.NET</b> – <a href="http://www.asp.net/mvc">ASP.NET MVC</a> The mother of all things ASP.NET MVC</li>
<div id="tooltipWindow" class="hidden tooltipwindow">


That looks like this:


So we are good to go, I just didnt want to have to copy all of this HTML for every tooltip I created in the system.  In Part 2 I will talk about how to integrate this with an MVC Html Helper.


Tags: , , ,

css | jquery


<<  March 2018  >>

View posts in large calendar

Page List