
// Version 0.05
// Author: Andrian Zubko (http://search.cpan.org/~ondr/)

// class constructor
hints = function (maxWidth, delimeter)
{
	// parameters
	this.maxWidth = maxWidth ? maxWidth : '300px';
	this.delimeter = delimeter;

	// safari fix
	if (/Safari/.test(navigator.userAgent) && !document.compatMode) {
		// while body is not loaded, this parameter
		// equivalent to zero in strict mode in this browser
		document.compatMode =
			document.documentElement.offsetHeight
				? 'BackCompat' : 'CSS1Compat';
	}

	// initialization method should be started after body
	// will be loaded, but before all media content will be loaded
	if (/Opera|Firefox/.test(navigator.userAgent)) {
		window.addEventListener('DOMContentLoaded',
			function ()
			{
				var object = this;
				return function () { object.init() }
			}.call(this), false
		);
	} else if (/Explorer/.test(navigator.appName)) {
		var interval = window.setInterval(
			function ()
			{
				var object = this;
				return function ()
				{
					try {
						// this method can be used only after body has
						// fully loaded. otherwise we catching error
						document.documentElement.doScroll('left');
					} catch (e) {
						return;
					}
					window.clearInterval(interval);
					object.init();
				}
			}.call(this), 10
		);
	} else if (/Safari/.test(navigator.userAgent)) {
		var interval = window.setInterval(
			function ()
			{
				var object = this;
				return function ()
				{
					if (/loaded|complete/.test(document.readyState)) {
						window.clearInterval(interval);
						object.init();
					}
				}
			}.call(this), 10
		);
	}
}

// initialization method
hints.prototype.init = function ()
{
	// overlay iframe specialy for IE
	if (/Explorer/.test(navigator.appName)) {
		this.oIFrame = document.createElement('iframe');
		this.oIFrame.className = 'hints';
		document.body.appendChild(this.oIFrame);
	}

	// attaching specials events to all elements with titles or alts
	var elements = document.getElementsByTagName('*');
	for (var i = 0; i < elements.length; ++i) {
		this.init_fixElement(elements[i]);
	}
}

// attaching specials events to element, if
// this element having title or alt
hints.prototype.init_fixElement = function (element)
{
	if (!element.getAttribute) {
		return;
	}
	var text = element.getAttribute('title');
	if (text == null || typeof(text) == 'object' || /^\s*$/.test(text)) {
		text = element.getAttribute('alt');
		if (typeof(text) == 'object') {
			return;
		}
	}
	element.removeAttribute('title');
	element.removeAttribute('alt');
	if (text == null || /^\s*$/.test(text)) {
		return;
	}
	element.onmouseover = function (text)
	{
		var object = this;
		return function (event) { object.show(event, text) }
	}.call(this, text);
	element.onmousemove = function ()
	{
		var object = this;
		return function (event) { object.move(event) }
	}.call(this);
	element.onmouseout = function ()
	{
		var object = this;
		return function () { object.hide() }
	}.call(this);
}

// hint creation
hints.prototype.show = function (event, text)
{
	// clearing up
	this.hide();

	// substrate div
	this.sDiv = document.createElement('div');
	this.sDiv.className = 'hints';
	document.body.appendChild(this.sDiv);

	// content div
	var cDiv = document.createElement('div');
	this.sDiv.appendChild(cDiv);

	// text transforming and placing to content div
	var parts;
	if (this.delimeter) {
		parts = text.split(this.delimeter);
	} else {
		parts = [ text ];
	}
	for (var i in parts) {
		if (/^\s*$/.test(parts[i])) {
			continue;
		}
		var paragraph = document.createElement('p');
		paragraph.appendChild(
			document.createTextNode(
				parts[i].replace(/^\s+/, '').replace(/\s+$/, '')
			)
		);
		cDiv.appendChild(paragraph);
	}

	// width checking
	var sDivOWidth1 = this.sDiv.offsetWidth;
	this.sDiv.style.width = this.maxWidth;
	var sDivOWidth2 = this.sDiv.offsetWidth;
	if (sDivOWidth1 < sDivOWidth2) {
		this.sDiv.style.width = sDivOWidth1 + 'px';
	} else {
		this.sDiv.style.width = sDivOWidth2 + 'px';
	}

	// overlay placing
	if (/Explorer/.test(navigator.appName)) {
		this.oIFrame.style.width = this.sDiv.offsetWidth + 'px';
		this.oIFrame.style.height = this.sDiv.offsetHeight + 'px';
		this.oIFrame.style.display = 'block';
	}

	// moving hint to needed place
	this.move(event);
}

// hint moving
hints.prototype.move = function (event)
{
	if (!this.sDiv) {
		return;
	}

	// mouse position
	var mouseX = window.event
		? window.event.clientX
			: event.clientX;
	var mouseY = window.event
		? window.event.clientY
			: event.clientY;

	// moving hint on X coordinate
	if (((document.compatMode == 'CSS1Compat' && !window.opera)
			? document.documentElement.clientWidth : document.body.clientWidth)
				- mouseX - this.sDiv.offsetWidth - 16 < 2) {
		this.sDiv.style.left =
			((document.documentElement.scrollLeft || document.body.scrollLeft)
				+ mouseX - 8 - this.sDiv.offsetWidth) + 'px';
	} else {
		this.sDiv.style.left =
			((document.documentElement.scrollLeft || document.body.scrollLeft)
				+ mouseX + 16) + 'px';
	}
	if (/Explorer/.test(navigator.appName)) {
		this.oIFrame.style.left = this.sDiv.style.left;
	}

	// moving hint on Y coordinate
	if (((document.compatMode == 'CSS1Compat' && !window.opera)
			? document.documentElement.clientHeight : document.body.clientHeight)
				- mouseY - this.sDiv.offsetHeight - 16 < 2) {
		this.sDiv.style.top =
			((document.documentElement.scrollTop || document.body.scrollTop)
				+ mouseY - 4 - this.sDiv.offsetHeight) + 'px';
	} else {
		this.sDiv.style.top =
			((document.documentElement.scrollTop || document.body.scrollTop)
				+ mouseY + 16) + 'px';
	}
	if (/Explorer/.test(navigator.appName)) {
		this.oIFrame.style.top = this.sDiv.style.top;
	}
}

// hint hiding
hints.prototype.hide = function ()
{
	if (!this.sDiv) {
		return;
	}

	// cleaning up
	document.body.removeChild(this.sDiv);
	delete(this.sDiv);
	if (/Explorer/.test(navigator.appName)) {
		this.oIFrame.style.display = 'none';
	}
}
