forked from website/openpower.foundation
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
277 lines
7.4 KiB
JavaScript
277 lines
7.4 KiB
JavaScript
4 years ago
|
/*
|
||
|
* jQuery Superfish Menu Plugin - v1.7.9
|
||
|
* Copyright (c) 2016 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) {
|
||
|
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);
|