
/*
 * CFWMenu v1.0.0 - jQuery for DDRMenu 1.2.2
 * Copyright (c) 2011 David Young / CFWebmasters.com
 *
 * Dual licensed under the MIT and GPL licenses:
 * 	http://www.opensource.org/licenses/mit-license.php
 * 	http://www.gnu.org/licenses/gpl.html
 * 
 * Includes "hoverIntent" jQuery plugin by Brian Cherne.
 */
 
 if(typeof(jQuery)!=='undefined'&&window.jQuery){	 
	(function ($) {
		/* hoverIntent by Brian Cherne */
		$.fn.hoverIntent = function (f, g) {
			// default configuration options
			var cfg = {
				sensitivity: 7,
				interval: 100,
				timeout: 0
			};
			// override configuration options with user supplied object
			cfg = $.extend(cfg, g ? { over: f, out: g} : f);

			// instantiate variables
			// cX, cY = current X and Y position of mouse, updated by mousemove event
			// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
			var cX, cY, pX, pY;

			// A private function for getting mouse position
			var track = function (ev) {
				cX = ev.pageX;
				cY = ev.pageY;
			};

			// A private function for comparing current and previous mouse position
			var compare = function (ev, ob) {
				ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
				// compare mouse positions to see if they've crossed the threshold
				if ((Math.abs(pX - cX) + Math.abs(pY - cY)) < cfg.sensitivity) {
					$(ob).unbind("mousemove", track);
					// set hoverIntent state to true (so mouseOut can be called)
					ob.hoverIntent_s = 1;
					return cfg.over.apply(ob, [ev]);
				} else {
					// set previous coordinates for next time
					pX = cX; pY = cY;
					// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
					ob.hoverIntent_t = setTimeout(function () { compare(ev, ob); }, cfg.interval);
				}
			};

			// A private function for delaying the mouseOut function
			var delay = function (ev, ob) {
				ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
				ob.hoverIntent_s = 0;
				return cfg.out.apply(ob, [ev]);
			};

			// A private function for handling mouse 'hovering'
			var handleHover = function (e) {
				// next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
				var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
				while (p && p != this) { try { p = p.parentNode; } catch (e) { p = this; } }
				if (p == this) { return false; }

				// copy objects to be passed into t (required for event object to be passed in IE)
				var ev = jQuery.extend({}, e);
				var ob = this;

				// cancel hoverIntent timer if it exists
				if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }

				// else e.type == "onmouseover"
				if (e.type == "mouseover") {
					// set "previous" X and Y position based on initial entry point
					pX = ev.pageX; pY = ev.pageY;
					// update "current" X and Y position based on mousemove
					$(ob).bind("mousemove", track);
					// start polling interval (self-calling timeout) to compare mouse coordinates over time
					if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout(function () { compare(ev, ob); }, cfg.interval); }

					// else e.type == "onmouseout"
				} else {
					// unbind expensive mousemove event
					$(ob).unbind("mousemove", track);
					// if hoverIntent state is true, then call the mouseOut function after the specified delay
					if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout(function () { delay(ev, ob); }, cfg.timeout); }
				}
			};

			// bind the function to the two event listeners
			return this.mouseover(handleHover).mouseout(handleHover);
		};

		$.fn.cfwMenu = function () {
			var m_Menu = $.fn.cfwMenu,
				m_over = function () {
					var $this = $(this).addClass('cfw-hover'), menu = m_getmenu($this);
					clearTimeout(menu.timer);
					$this.cfwShowMenu().siblings().cfwHideMenu();
				},
				m_out = function () {
					var $this = $(this), menu = m_getmenu($this);
					clearTimeout(menu.timer);
					menu.timer = setTimeout(function () { $this.cfwHideMenu(); }, 200);
				},
				m_getmenu = function ($item) {
					return $item.parents('ul.cfw-root:first')[0];
				}
			return this.each(function () {
				var $this = $(this);
				$this
					.find('li:has(ul)')
						.addClass('has-subs')
						.hoverIntent(m_over, m_out)
						.not('.cfw-current')
						.cfwHideMenu()
						.find('a')
							.each(function () {
								var $a = $(this);
								var $li = $a.parent('li');
								$a.focus(function () { m_over.call($li); }).blur(function () { m_out.call($li); });
							})
						.end()
					.end();

				if (!($this.find('li.cfw-first').length > 0)) {
					$this
						.find('li:first-child')
							.addClass('cfw-first')
						.end()
						.find('li:last-child')
							.addClass('cfw-last')
						.end()
				}

			});
		};

		var OnHide = function () {
			this.removeClass('cfw-hover').find('ul').hide().css('visibility', 'hidden').end().find('.cfw-hover').removeClass('cfw-hover');
		};
		var OnShow = function () {

		};
		$.fn.extend({
			cfwHideMenu: function () {
				var $li = this,$ul = this.find('>ul');
				$ul.animate({ 'height': 'hide', 'opacity': 'hide' }, 100, function () { OnHide.call($li); });
				return this;
			},
			cfwShowMenu: function () {
				var $li = this,$ul = this.find('>ul:hidden').css('visibility', 'visible');
				$ul.animate({ 'height': 'show', 'opacity': 'show' }, 200, function () { OnShow.call($li); });
				return this;
			}
		});
	})(jQuery);
}

