RND Websites

YUI3 Tooltip module

by on Apr.09, 2010, under Javascript

Just quickly posting this bit of code that I’ve written to have a play with YUI3. There’s definitely room for improvement (e.g. making Tooltip inherit from the Overlay widget) and I haven’t tested the code thoroughly yet. But for a first try with a library, I figured it was nice enough to get the expected result:

YUI.add('tooltip', function (Y) {
	var Tip = function (config) {
		Tip.superclass.constructor.apply(this, arguments);
	};

	Tip.ATTRS = {
		offsetX: {
			value: 10,
			setter: function (val) {
				return val;
			}
		},
		offsetY: {
			value: 10,
			setter: function (val) {
				return val;
			}
		},
		showDelay: {
			value: 0.5,
			setter: function (val) {
				return val*1000;
			},
			validator: function (val) {
				return Y.Lang.isNumber(val) && (val >= 0);
			}
		},
		hideDelay: {
			value: 1.5,
			setter: function (val) {
				return val*1000;
			},
			validator: function (val) {
				return Y.Lang.isNumber(val) && (val >= 0);
			}
		}
	};

	Tip.HTML_PARSER = {
		header: function (srcNode) {
			var h = srcNode.getAttribute("title").match(/header=\[([^\]]*)\]/);
			if (h !== null && h.length > 1) {
				return h[1];
			}
			return "";
		},
		body: function (srcNode) {
			var b = srcNode.getAttribute("title").match(/body=\[([^\]]*)\]/);
			if (b !== null && b.length > 1) {
				return b[1];
			}
			return "";
		}
	};

	Tip.NAME = "tooltip";

	Y.extend(Tip, Y.Widget, {
		_srcNode: null,
		_tipNode: null,
		_config: null,
		_timers: null,
		initializer: function (config) {
			this._config = config;
			this._srcNode = config.srcNode;
			this._createTipNode(config.header, config.body);
			this._timers = {
				show: null,
				hide: null
			};
			Y.on("mouseenter", Y.bind(this._onMouseEnter, this), this._srcNode);
			Y.on("mouseleave", Y.bind(this._onMouseLeave, this), this._srcNode);
		},
		destructor: function () {
			this._onMouseEnter.detach();
			this._onMouseLeave.detach();
			this._tipNode.remove();
		},
		_createTipNode: function (header, body) {
			this._tipNode = new Y.Overlay({
				headerContent: header,
				bodyContent: body,
				visible: false,
				width:"280px",
				constrain: true
			});
			this._srcNode.setAttribute("title", "");
			this._tipNode.render();
		},
		_onMouseEnter: function (e) {
			if (Y.BOL.activeTooltip !== null) {
				Y.BOL.activeTooltip.hide();
				Y.BOL.activeTooltip = null;
			}
			if (this._timers.hide !== null) {
				this._timers.hide = clearTimeout(this._timers.hide);
			}
			this._timers.show = setTimeout(Y.bind(function () {
				this._tipNode.set("xy", [e.pageX+this.get("offsetX"), e.pageY+this.get("offsetY")]);
				this._tipNode.show();
				Y.BOL.activeTooltip = this;
			}, this), this.get("showDelay"));
		},
		_onMouseLeave: function (e) {
			if (this._timers.show !== null) {
				this._timers.show = clearTimeout(this._timers.show);
			}
			this._timers.hide = setTimeout(Y.bind(function () {
				this.hide();
				Y.BOL.activeTooltip = null;
			}, this), this.get("hideDelay"));
		},
		hide: function () {
			if (this._timers.show !== null) {
				this._timers.show = clearTimeout(this._timers.show);
			}
			this._tipNode.hide();
		}
	});

	Y.namespace('BOL');
	Y.BOL.Tooltip = Tip;
	Y.BOL.activeTooltip = null;
},
'1.0',
{
	requires: ['event-mouseenter', 'overlay']
});

To use it, the HTML needs to look like this:

<div id="testDiv" class="tooltip_trigger" title="header=[Verzendkosten per bestelling] body=[Nederland: &amp;euro; 1,95&lt;br&gt;Belgi&amp;euml;: &amp;euro; 0,00&lt;br&gt;Overige Europa, Noord- en Midden-Amerika, Cara&amp;iuml;bisch gebied, Azi&amp;euml;, Australi&amp;euml;, Nieuw-Zeeland: van &amp;euro; 3,45 tot &amp;euro; 19,80&lt;br&gt;&lt;br&gt;&lt;strong&gt;Let op!&lt;/strong&gt; Software, pc-accessoires, elektronica en telefonie worden niet in het buitenland bezorgd.&lt;br&gt;&lt;br&gt;]">Test</div>

And finally, to call it:

YUI().use('tooltip', function (Y) {
	Y.all(".tooltip_trigger").each(function (trgNode) {
		var tip = new Y.BOL.Tooltip({
			srcNode: trgNode
		});
	})
})

1 Comment for this entry

  • Marc

    Most important improvement for me would be to use only one tooltip instance for all tooltips on the page and dynamically switch content. Much more resource efficient. It would mean moving the Y.all function inside and just referencing the tooltip class in the constructor.

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Categories