/*

 * jQuery Superfish Menu Plugin

 * Copyright (c) 2013 Joel Birch

 *

 * Dual licensed under the MIT and GPL licenses:

 *	http://www.opensource.org/licenses/mit-license.php

 *	http://www.gnu.org/licenses/gpl.html

 */



(function ($, w) {

	"use strict";



	var methods = (function () {

		// private properties and methods go here

		var c = {

				bcClass: 'sf-breadcrumb',

				menuClass: 'sf-js-enabled',

				anchorClass: 'sf-with-ul',

				menuArrowClass: 'sf-arrows'

			},

			ios = (function () {

				var ios = /^(?![\w\W]*Windows Phone)[\w\W]*(iPhone|iPad|iPod)/i.test(navigator.userAgent);

				if (ios) {

					// tap anywhere on iOS to unfocus a submenu

					$('html').css('cursor', 'pointer').on('click', $.noop);

				}

				return ios;

			})(),

			wp7 = (function () {

				var style = document.documentElement.style;

				return ('behavior' in style && 'fill' in style && /iemobile/i.test(navigator.userAgent));

			})(),

			unprefixedPointerEvents = (function () {

				return (!!w.PointerEvent);

			})(),

			toggleMenuClasses = function ($menu, o, add) {

				var classes = c.menuClass,

					method;

				if (o.cssArrows) {

					classes += ' ' + c.menuArrowClass;

				}

				method = (add) ? 'addClass' : 'removeClass';

				$menu[method](classes);

			},

			setPathToCurrent = function ($menu, o) {

				return $menu.find('li.' + o.pathClass).slice(0, o.pathLevels)

					.addClass(o.hoverClass + ' ' + c.bcClass)

						.filter(function () {

							return ($(this).children(o.popUpSelector).hide().show().length);

						}).removeClass(o.pathClass);

			},

			toggleAnchorClass = function ($li, add) {

				var method = (add) ? 'addClass' : 'removeClass';

				$li.children('a')[method](c.anchorClass);

			},

			toggleTouchAction = function ($menu) {

				var msTouchAction = $menu.css('ms-touch-action');

				var touchAction = $menu.css('touch-action');

				touchAction = touchAction || msTouchAction;

				touchAction = (touchAction === 'pan-y') ? 'auto' : 'pan-y';

				$menu.css({

					'ms-touch-action': touchAction,

					'touch-action': touchAction

				});

			},

			getMenu = function ($el) {

				return $el.closest('.' + c.menuClass);

			},

			getOptions = function ($el) {

				return getMenu($el).data('sfOptions');

			},

			over = function () {

				var $this = $(this),

					o = getOptions($this);

				clearTimeout(o.sfTimer);

				$this.siblings().superfish('hide').end().superfish('show');

			},

			close = function (o) {

				o.retainPath = ($.inArray(this[0], o.$path) > -1);

				this.superfish('hide');



				if (!this.parents('.' + o.hoverClass).length) {

					o.onIdle.call(getMenu(this));

					if (o.$path.length) {

						$.proxy(over, o.$path)();

					}

				}

			},

			out = function () {

				var $this = $(this),

					o = getOptions($this);

				if (ios) {

					$.proxy(close, $this, o)();

				}

				else {

					clearTimeout(o.sfTimer);

					o.sfTimer = setTimeout($.proxy(close, $this, o), o.delay);

				}

			},

			touchHandler = function (e) {

				var $this = $(this),

					o = getOptions($this),

					$ul = $this.siblings(e.data.popUpSelector);



				if (o.onHandleTouch.call($ul) === false) {

					return this;

				}



				if ($ul.length > 0 && $ul.is(':hidden')) {

					$this.one('click.superfish', false);

					if (e.type === 'MSPointerDown' || e.type === 'pointerdown') {

						$this.trigger('focus');

					} else {

						$.proxy(over, $this.parent('li'))();

					}

				}

			},

			applyHandlers = function ($menu, o) {

				var targets = 'li:has(' + o.popUpSelector + ')';

				if ($.fn.hoverIntent && !o.disableHI) {

					$menu.hoverIntent(over, out, targets);

				}

				else {

					$menu

						.on('mouseenter.superfish', targets, over)

						.on('mouseleave.superfish', targets, out);

				}

				var touchevent = 'MSPointerDown.superfish';

				if (unprefixedPointerEvents) {

					touchevent = 'pointerdown.superfish';

				}

				if (!ios) {

					touchevent += ' touchend.superfish';

				}

				if (wp7) {

					touchevent += ' mousedown.superfish';

				}

				$menu

					.on('focusin.superfish', 'li', over)

					.on('focusout.superfish', 'li', out)

					.on(touchevent, 'a', o, touchHandler);

			};



		return {

			// public methods

			hide: function (instant) {

				if (this.length) {

					var $this = this,

						o = getOptions($this);

					if (!o) {

						return this;

					}

					var not = (o.retainPath === true) ? o.$path : '',

						$ul = $this.find('li.' + o.hoverClass).add(this).not(not).removeClass(o.hoverClass).children(o.popUpSelector),

						speed = o.speedOut;



					if (instant) {

						$ul.show();

						speed = 0;

					}

					o.retainPath = false;



					if (o.onBeforeHide.call($ul) === false) {

						return this;

					}



					$ul.stop(true, true).animate(o.animationOut, speed, function () {

						var $this = $(this);

						o.onHide.call($this);

					});

				}

				return this;

			},

			show: function () {

				var o = getOptions(this);

				if (!o) {

					return this;

				}

				var $this = this.addClass(o.hoverClass),

					$ul = $this.children(o.popUpSelector);



				if (o.onBeforeShow.call($ul) === false) {

					return this;

				}



				$ul.stop(true, true).animate(o.animation, o.speed, function () {

					o.onShow.call($ul);

				});

				return this;

			},

			destroy: function () {

				return this.each(function () {

					var $this = $(this),

						o = $this.data('sfOptions'),

						$hasPopUp;

					if (!o) {

						return false;

					}

					$hasPopUp = $this.find(o.popUpSelector).parent('li');

					clearTimeout(o.sfTimer);

					toggleMenuClasses($this, o);

					toggleAnchorClass($hasPopUp);

					toggleTouchAction($this);

					// remove event handlers

					$this.off('.superfish').off('.hoverIntent');

					// clear animation's inline display style

					$hasPopUp.children(o.popUpSelector).attr('style', function (i, style) {

						if (typeof style !== 'undefined') {

						return style.replace(/display[^;]+;?/g, '');

						}

					});

					// reset 'current' path classes

					o.$path.removeClass(o.hoverClass + ' ' + c.bcClass).addClass(o.pathClass);

					$this.find('.' + o.hoverClass).removeClass(o.hoverClass);

					o.onDestroy.call($this);

					$this.removeData('sfOptions');

				});

			},

			init: function (op) {

				return this.each(function () {

					var $this = $(this);

					if ($this.data('sfOptions')) {

						return false;

					}

					var o = $.extend({}, $.fn.superfish.defaults, op),

						$hasPopUp = $this.find(o.popUpSelector).parent('li');

					o.$path = setPathToCurrent($this, o);



					$this.data('sfOptions', o);



					toggleMenuClasses($this, o, true);

					toggleAnchorClass($hasPopUp, true);

					toggleTouchAction($this);

					applyHandlers($this, o);



					$hasPopUp.not('.' + c.bcClass).superfish('hide', true);



					o.onInit.call(this);

				});

			}

		};

	})();



	$.fn.superfish = function (method, args) {

		if (methods[method]) {

			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));

		}

		else if (typeof method === 'object' || ! method) {

			return methods.init.apply(this, arguments);

		}

		else {

			return $.error('Method ' +  method + ' does not exist on jQuery.fn.superfish');

		}

	};



	$.fn.superfish.defaults = {

		popUpSelector: 'ul,.sf-mega', // within menu context

		hoverClass: 'sfHover',

		pathClass: 'overrideThisToUse',

		pathLevels: 1,

		delay: 800,

		animation: {opacity: 'show'},

		animationOut: {opacity: 'hide'},

		speed: 'normal',

		speedOut: 'fast',

		cssArrows: true,

		disableHI: false,

		onInit: $.noop,

		onBeforeShow: $.noop,

		onShow: $.noop,

		onBeforeHide: $.noop,

		onHide: $.noop,

		onIdle: $.noop,

		onDestroy: $.noop,

		onHandleTouch: $.noop

	};



})(jQuery, window);



/*



 * Supposition v0.2 - an optional enhancer for Superfish jQuery menu widget.



 *



 * Copyright (c) 2008 Joel Birch - based mostly on work by Jesse Klaasse and credit goes largely to him.



 * Special thanks to Karl Swedberg for valuable input.



 *



 * Dual licensed under the MIT and GPL licenses:



 *  http://www.opensource.org/licenses/mit-license.php



 *  http://www.gnu.org/licenses/gpl.html



 */



/*



 * This is not the original jQuery Supposition plugin.



 * Please refer to the README for more information.



 */







(function($){



  $.fn.supposition = function(){



    var $w = $(window), /*do this once instead of every onBeforeShow call*/



    _offset = function(dir) {



      return window[dir == 'y' ? 'pageYOffset' : 'pageXOffset']



      || document.documentElement && document.documentElement[dir=='y' ? 'scrollTop' : 'scrollLeft']



      || document.body[dir=='y' ? 'scrollTop' : 'scrollLeft'];



    },



    onHide = function(){



      this.css({bottom:''});



    },



    onBeforeShow = function(){



      this.each(function(){



        var $u = $(this);



        $u.css('display','block');



        var $mul = $u.closest('.sf-menu'),



        level = $u.parents('ul').length,



        menuWidth = $u.width(),



        menuParentWidth = $u.closest('li').outerWidth(true),



        menuParentLeft = $u.closest('li').offset().left,



        totalRight = $w.width() + _offset('x'),



        menuRight = $u.offset().left + menuWidth,



        exactMenuWidth = (menuRight > (menuParentWidth + menuParentLeft)) ? menuWidth - (menuRight - (menuParentWidth + menuParentLeft)) : menuWidth;



        if ($u.parents('.sf-js-enabled').hasClass('rtl')) {



          if (menuParentLeft < exactMenuWidth) {



            if (($mul.hasClass('sf-horizontal') && level == 1) || ($mul.hasClass('sf-navbar') && level == 2)){



              $u.css({left:0,right:'auto'});



            }



            else {



              $u.css({left:menuParentWidth + 'px',right:'auto'});



            }



            $u.parent().addClass('sf-supposition-active');



          }



        }



        else {



          if (menuRight > totalRight && menuParentLeft > menuWidth) {



            if (($mul.hasClass('sf-horizontal') && level == 1) || ($mul.hasClass('sf-navbar') && level == 2)){



              $u.css({right:0,left:'auto'});



            }



            else {



              $u.css({right:menuParentWidth + 'px',left:'auto'});



            }



            $u.parent().addClass('sf-supposition-active');



          }



        }



        var windowHeight = $w.height(),



        offsetTop = $u.offset().top,



        menuParentShadow = ($mul.hasClass('sf-shadow') && $u.css('padding-bottom').length > 0) ? parseInt($u.css('padding-bottom').slice(0,-2)) : 0,



        menuParentHeight = ($mul.hasClass('sf-vertical')) ? '-' + menuParentShadow : $u.parent().outerHeight(true) - menuParentShadow,



        menuHeight = $u.height(),



        baseline = windowHeight + _offset('y');



        var expandUp = ((offsetTop + menuHeight > baseline) && (offsetTop > menuHeight));



        if (expandUp) {



          $u.css({bottom:menuParentHeight + 'px',top:'auto'});



        }



        $u.css('display','none');



      });



    };







    return this.each(function() {



      var o = $.fn.superfish.o[this.serial]; /* get this menu's options */







      /* if callbacks already set, store them */



      var _onBeforeShow = o.onBeforeShow,



      _onHide = o.onHide;







      $.extend($.fn.superfish.o[this.serial],{



        onBeforeShow: function() {



          onBeforeShow.call(this); /* fire our Supposition callback */



          _onBeforeShow.call(this); /* fire stored callbacks */



        },



        onHide: function() {



          onHide.call(this); /* fire our Supposition callback */



          _onHide.call(this); /* fire stored callbacks */



        }



      });



    });



  };



})(jQuery);