You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
9.1 KiB
299 lines
9.1 KiB
/* ========================================================================
|
|
* Bootstrap: dropdownhover.js v1.1.0
|
|
* http://kybarg.github.io/bootstrap-dropdown-hover/
|
|
* ========================================================================
|
|
* Licensed under MIT (https://github.com/kybarg/bootstrap-dropdown-hover/blob/master/LICENSE)
|
|
* ======================================================================== */
|
|
|
|
|
|
+function ($) {
|
|
'use strict';
|
|
|
|
// DROPDOWN CLASS DEFINITION
|
|
// =========================
|
|
|
|
var backdrop = '.dropdown-backdrop'
|
|
|
|
var Dropdownhover = function (element, options) {
|
|
this.options = options
|
|
this.$element = $(element)
|
|
|
|
var that = this
|
|
|
|
// Defining if navigation tree or single dropdown
|
|
this.dropdowns = this.$element.hasClass('dropdown-toggle') ? this.$element.parent().find('.dropdown-menu').parent('.dropdown') : this.$element.find('.dropdown')
|
|
|
|
if (!options.onClick) {
|
|
this.dropdowns.each(function () {
|
|
$(this).on('mouseenter.bs.dropdownhover', function (e) {
|
|
that.show($(this).children('a, button'))
|
|
})
|
|
})
|
|
|
|
this.dropdowns.each(function () {
|
|
$(this).on('mouseleave.bs.dropdownhover', function (e) {
|
|
that.hide($(this).children('a, button'))
|
|
})
|
|
})
|
|
} else {
|
|
this.dropdowns.each(function () {
|
|
$(this).children('a, button').on('click.bs.dropdownhover', function (e) {
|
|
var isActive = $(this).parent().hasClass('open')
|
|
isActive ? that.hide($(this)) : that.show($(this))
|
|
})
|
|
})
|
|
}
|
|
|
|
}
|
|
|
|
Dropdownhover.TRANSITION_DURATION = 300
|
|
Dropdownhover.DELAY = 150
|
|
Dropdownhover.TIMEOUT
|
|
|
|
Dropdownhover.DEFAULTS = {
|
|
onClick: false,
|
|
animations: ['fadeInDown', 'fadeInRight', 'fadeInUp', 'fadeInLeft'],
|
|
}
|
|
|
|
function getParent($this) {
|
|
var selector = $this.attr('data-target')
|
|
|
|
if (!selector) {
|
|
selector = $this.attr('href')
|
|
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
|
|
}
|
|
|
|
var $parent = selector && $(document).find(selector)
|
|
|
|
return $parent && $parent.length ? $parent : $this.parent()
|
|
}
|
|
|
|
function clearMenus(e) {
|
|
if (e && e.which === 3) return
|
|
$(backdrop).remove()
|
|
$('[data-hover="dropdown"]').each(function () {
|
|
var $this = $(this)
|
|
var $parent = getParent($this)
|
|
var relatedTarget = { relatedTarget: this }
|
|
|
|
if (!$parent.hasClass('open')) return
|
|
|
|
if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
|
|
|
|
$parent.trigger(e = $.Event('hide.bs.dropdownhover', relatedTarget))
|
|
|
|
if (e.isDefaultPrevented()) return
|
|
|
|
$this.attr('aria-expanded', 'false')
|
|
$parent.removeClass('open').trigger($.Event('hidden.bs.dropdownhover', relatedTarget))
|
|
})
|
|
}
|
|
|
|
// Opens dropdown menu when mouse is over the trigger element
|
|
Dropdownhover.prototype.show = function (_dropdownLink) {
|
|
var $this = $(_dropdownLink)
|
|
|
|
|
|
window.clearTimeout(Dropdownhover.TIMEOUT)
|
|
// Close all dropdowns
|
|
$('.dropdown').not($this.parents()).each(function () {
|
|
$(this).removeClass('open')
|
|
});
|
|
|
|
var effect = this.options.animations[0]
|
|
|
|
if ($this.is('.disabled, :disabled')) return
|
|
|
|
var $parent = $this.parent()
|
|
var isActive = $parent.hasClass('open')
|
|
|
|
if (!isActive) {
|
|
|
|
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
|
|
// if mobile we use a backdrop because click events don't delegate
|
|
$(document.createElement('div'))
|
|
.addClass('dropdown-backdrop')
|
|
.insertAfter($(this))
|
|
.on('click', clearMenus)
|
|
}
|
|
|
|
var $dropdown = $this.next('.dropdown-menu')
|
|
|
|
$parent.addClass('open')
|
|
$this.attr('aria-expanded', true)
|
|
|
|
// Ensures that all menus that are closed have proper aria tagging.
|
|
$parent.siblings().each(function () {
|
|
if (!$(this).hasClass('open')) {
|
|
$(this).find('[data-hover="dropdown"]').attr('aria-expanded', false);
|
|
}
|
|
})
|
|
|
|
var side = this.position($dropdown)
|
|
|
|
switch (side) {
|
|
case 'top':
|
|
effect = this.options.animations[2]
|
|
break;
|
|
case 'right':
|
|
effect = this.options.animations[3]
|
|
break;
|
|
case 'left':
|
|
effect = this.options.animations[1]
|
|
break;
|
|
default:
|
|
effect = this.options.animations[0]
|
|
break;
|
|
}
|
|
|
|
$dropdown.addClass('animated ' + effect)
|
|
|
|
var transition = $.support.transition && $dropdown.hasClass('animated')
|
|
|
|
transition ?
|
|
$dropdown
|
|
.one('bsTransitionEnd', function () {
|
|
$dropdown.removeClass('animated ' + effect)
|
|
})
|
|
.emulateTransitionEnd(Dropdownhover.TRANSITION_DURATION) :
|
|
$dropdown.removeClass('animated ' + effect)
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// Closes dropdown menu when mouse is out of it
|
|
Dropdownhover.prototype.hide = function (_dropdownLink) {
|
|
|
|
var that = this
|
|
var $this = $(_dropdownLink)
|
|
var $parent = $this.parent()
|
|
var $this_delay = $this.data('dropdown-hover-delay');
|
|
Dropdownhover.TIMEOUT = window.setTimeout(function () {
|
|
$parent.removeClass('open')
|
|
$this.attr('aria-expanded', false)
|
|
}, ($this_delay ? $this_delay : Dropdownhover.DELAY))
|
|
}
|
|
|
|
// Calculating position of dropdown menu
|
|
Dropdownhover.prototype.position = function (dropdown) {
|
|
|
|
var win = $(window);
|
|
|
|
// Reset css to prevent incorrect position
|
|
dropdown.css({ bottom: '', left: '', top: '', right: '' }).removeClass('dropdownhover-top')
|
|
|
|
var viewport = {
|
|
top: win.scrollTop(),
|
|
left: win.scrollLeft()
|
|
};
|
|
viewport.right = viewport.left + win.width();
|
|
viewport.bottom = viewport.top + win.height();
|
|
|
|
var bounds = dropdown.offset();
|
|
bounds.right = bounds.left + dropdown.outerWidth();
|
|
bounds.bottom = bounds.top + dropdown.outerHeight();
|
|
var position = dropdown.position();
|
|
position.right = bounds.left + dropdown.outerWidth();
|
|
position.bottom = bounds.top + dropdown.outerHeight();
|
|
|
|
var side = ''
|
|
|
|
var isSubnow = dropdown.parents('.dropdown-menu').length
|
|
|
|
if (isSubnow) {
|
|
|
|
if (position.left < 0) {
|
|
side = 'left'
|
|
dropdown.removeClass('dropdownhover-right').addClass('dropdownhover-left')
|
|
} else {
|
|
side = 'right'
|
|
dropdown.addClass('dropdownhover-right').removeClass('dropdownhover-left')
|
|
}
|
|
|
|
if (bounds.left < viewport.left) {
|
|
side = 'right'
|
|
dropdown.css({ left: '100%', right: 'auto' }).addClass('dropdownhover-right').removeClass('dropdownhover-left')
|
|
} else if (bounds.right > viewport.right) {
|
|
side = 'left'
|
|
dropdown.css({ left: 'auto', right: '100%' }).removeClass('dropdownhover-right').addClass('dropdownhover-left')
|
|
}
|
|
|
|
if (bounds.bottom > viewport.bottom) {
|
|
dropdown.css({ bottom: 'auto', top: -(bounds.bottom - viewport.bottom) })
|
|
} else if (bounds.top < viewport.top) {
|
|
dropdown.css({ bottom: -(viewport.top - bounds.top), top: 'auto' })
|
|
}
|
|
|
|
} else { // Defines special position styles for root dropdown menu
|
|
|
|
var parentLi = dropdown.parent('.dropdown')
|
|
var pBounds = parentLi.offset()
|
|
pBounds.right = pBounds.left + parentLi.outerWidth()
|
|
pBounds.bottom = pBounds.top + parentLi.outerHeight()
|
|
|
|
if (bounds.right > viewport.right) {
|
|
dropdown.css({ left: -(bounds.right - viewport.right), right: 'auto' })
|
|
}
|
|
|
|
if (bounds.bottom > viewport.bottom && (pBounds.top - viewport.top) > (viewport.bottom - pBounds.bottom) || dropdown.position().top < 0) {
|
|
side = 'top'
|
|
dropdown.css({ bottom: '100%', top: 'auto' }).addClass('dropdownhover-top').removeClass('dropdownhover-bottom')
|
|
} else {
|
|
side = 'bottom'
|
|
dropdown.addClass('dropdownhover-bottom')
|
|
}
|
|
}
|
|
|
|
return side;
|
|
|
|
}
|
|
|
|
|
|
// DROPDOWNHOVER PLUGIN DEFINITION
|
|
// ==========================
|
|
|
|
function Plugin(option) {
|
|
return this.each(function () {
|
|
var $this = $(this)
|
|
var data = $this.data('bs.dropdownhover')
|
|
var settings = $this.data()
|
|
if ($this.data('animations') !== undefined && $this.data('animations') !== null)
|
|
settings.animations = $.isArray(settings.animations) ? settings.animations : settings.animations.split(' ')
|
|
|
|
var options = $.extend({}, Dropdownhover.DEFAULTS, settings, typeof option == 'object' && option)
|
|
|
|
if (!data) $this.data('bs.dropdownhover', (data = new Dropdownhover(this, options)))
|
|
|
|
})
|
|
}
|
|
|
|
var old = $.fn.dropdownhover
|
|
|
|
$.fn.dropdownhover = Plugin
|
|
$.fn.dropdownhover.Constructor = Dropdownhover
|
|
|
|
|
|
// DROPDOWNHOVER NO CONFLICT
|
|
// ====================
|
|
|
|
$.fn.dropdownhover.noConflict = function () {
|
|
$.fn.dropdownhover = old
|
|
return this
|
|
}
|
|
|
|
|
|
// APPLY TO STANDARD DROPDOWNHOVER ELEMENTS
|
|
// ===================================
|
|
$(document).ready(function () {
|
|
$('[data-hover="dropdown"]').each(function () {
|
|
var $target = $(this)
|
|
if ('ontouchstart' in document.documentElement) {
|
|
Plugin.call($target, $.extend({}, $target.data(), { onClick: true }))
|
|
} else {
|
|
Plugin.call($target, $target.data())
|
|
}
|
|
})
|
|
})
|
|
|
|
}(jQuery);
|
|
|