﻿(function ($) {
	// Display extra information
	$.fn.dextra = function () {
		var args = arguments;
		return this.each(function () {
			new Dextra(this, args);
		});
	}

	var $container = null;
	var timerId = null;
	var active = null;
	var timeout = 300;

	function Dextra(element, params) {
		var self = this;

		var $element = $(element);
		var cache = true;
		var cached = null;

		var defaults = {
			content: null,
			cache: true,
			effect: "none",
			position: "bottom",
			maxHeight: false,
			display: false
		}

		function init() {
			if ($element.data("dextra")) return;
			$element.data("dextra", self);

			var options;
			if (params.length == 2 || typeof params[0] == "function" || params[0].content === undefined) {
				defaults.content = params[0];
				if (params.length > 1) options = params[1];
			} else {
				options = params[0];
			}

			if (!options) options = {};
			options = $.extend({}, defaults, options);

			$element.hover(function (e) {
				if ($container == null) {
					$container = $("<div class='dextra-container' style='display:none; position: absolute; z-index: 9999;'></div>");
					$container.appendTo(document.body);

					$container.hover(function () {
						window.clearTimeout(timerId);
					}, function () {
						timerId = window.setTimeout(function () {
							$container.fadeOut(200);
							active = null;
						}, timeout);
					});
				}

				window.clearTimeout(timerId);
				if (active == self) return;

				$container.stop(true, true);
				$container.hide();
				active = self;

				var $window = $(window);
				var $body;

				var reposition = function () {
					// Reset styles so we can calculate correct height
					$container.css({ "height": "auto", "overflow-y": "visible" });
					if (options.maxHeight && $container.height() > options.maxHeight) {
						$container.css({ "height": options.maxHeight, "overflow-y": "scroll" });
					}

					var offset = $element.offset();
					var height = $element.outerHeight();
					var width = $element.outerWidth();

					var y = 0;
					var x = 0;

					if (options.position.context !== undefined) {
						if (options.position.context == "bottom") {
							x = offset.left + options.position.x;
							y = offset.top + height + options.position.y;
						}
					} else {
						var positions = options.position.split(" ");
						for (var i in positions) {
							var pos = positions[i];
							switch (pos) {
								case "top":
									y = offset.top;
									break;

								case "left":
									x = offset.left - $container.outerWidth();
									break;

								case "right":
									x = offset.left + width;
									break;

								case "bottom":
								default:
									if(positions.length == 1) x = e.pageX + 20;
									y = offset.top + height;
									break;
							}
						}

						if (!y) y = offset.top;
					}

					$container.css({
						top: y,
						left: x
					});

					switch (options.effect) {
						case "slideDown":
							$container.slideDown(200);
							break;
						case "fadeIn":
							$container.fadeIn(200);
							break;
						default:
							$container.show();
							break;
					}
				}

				var response = function (content) {
					$body.html(content);
					if (options.display) {
						$body.addClass(options.display);
						if (options.display == "list") $body.find("li:odd").addClass("alt");
					}
					if (active != self) return;
					reposition();
				}

				if (!options.cache || !cached) {
					if ($body != null) $body.remove();
					$body = $("<div class='dextra-body'></div>");
					if (options.cache) cached = $body;

					$container.children().hide();
					$container.append($body);

					if (typeof options.content == "function") {
						options.content.call($element[0], { body: $body, response: response });
					} else {
						response(options.content);
					}
				} else {
					$body = cached;
					$container.children().hide();
					$body.show();
					reposition();
				}

			}, function () {
				timerId = window.setTimeout(function () {
					$container.fadeOut(200);
					active = null;
				}, timeout);

			}).click(function () {
				$container.hide();
				active = null;
			});
		}

		init();
	}
})(jQuery);
