diff options
author | Jim Brandt <jbrandt@bestpractical.com> | 2020-01-11 00:18:59 +0300 |
---|---|---|
committer | Jim Brandt <jbrandt@bestpractical.com> | 2020-01-11 00:18:59 +0300 |
commit | 9e384d2378e11bf118a53d05bf67a3ca200efca1 (patch) | |
tree | ba3a7237f0fbe8191161f039da3465d21bafb9c2 /devel | |
parent | fc56d158592d9cd8b29728609c2fa67f4ad1a369 (diff) | |
parent | 10393c8dfc8179e05830cf2512d47cdb07d5bdb1 (diff) |
Merge branch '4.6/upgrade-superfish'
Diffstat (limited to 'devel')
-rw-r--r-- | devel/third-party/README | 5 | ||||
-rw-r--r-- | devel/third-party/superfish.js | 278 |
2 files changed, 283 insertions, 0 deletions
diff --git a/devel/third-party/README b/devel/third-party/README index 9f8780ea9c..76c5484383 100644 --- a/devel/third-party/README +++ b/devel/third-party/README @@ -78,3 +78,8 @@ License: MIT Description: A set of SVG icons. Icon files are installed via npm, then webpack tree-shakes to generate js for only the icons we use. Origin: https://github.com/FortAwesome/Font-Awesome/tree/master/js-packages/%40fortawesome License: Icons: CC BY 4.0, Code: MIT License + +* superfish-1.7.10 +Description: an enhanced Suckerfish-style menu jQuery plugin +Origin: https://github.com/joeldbirch/superfish +License: MIT and GPL diff --git a/devel/third-party/superfish.js b/devel/third-party/superfish.js new file mode 100644 index 0000000000..2503662c36 --- /dev/null +++ b/devel/third-party/superfish.js @@ -0,0 +1,278 @@ +/* + * jQuery Superfish Menu Plugin - v1.7.10 + * Copyright (c) 2018 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); |