UNPKG

avvo-styleguide

Version:
193 lines (146 loc) 4.8 kB
/* ======================================================================== * Avvo UI - dropdown.js * ======================================================================== * Forked from Bootstrap dropdown.js v3.3.1 * http://getbootstrap.com/javascript/#dropdowns * ======================================================================== * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ const $ = global.jQuery // DROPDOWN CLASS DEFINITION // ========================= const backdrop = '.dropdown-backdrop' const toggle = '[data-toggle="dropdown"]' const Dropdown = function (element) { $(element).on('click.ui.dropdown', this.toggle) } Dropdown.VERSION = '4.0.0' Dropdown.prototype.toggle = function (e) { const $this = $(this) if ($this.is('.disabled, :disabled')) { return } const $parent = getParent($this) const isActive = $parent.hasClass('open') clearMenus() if (!isActive) { if ('ontouchstart' in document.documentElement) { // if mobile we use a backdrop because click events don't delegate $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus) } const relatedTarget = { relatedTarget: this, } const showEvent = $.Event('show.ui.dropdown', relatedTarget) $parent.trigger(showEvent) if (showEvent.isDefaultPrevented()) { return } $this .trigger('focus') .attr('aria-expanded', 'true') $parent .toggleClass('open') .trigger('shown.ui.dropdown', relatedTarget) } return false } Dropdown.prototype.keydown = function (e) { if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) { return } const $this = $(this) e.preventDefault() e.stopPropagation() if ($this.is('.disabled, :disabled')) { return } const $parent = getParent($this) const isActive = $parent.hasClass('open') if ((!isActive && e.which !== 27) || (isActive && e.which === 27)) { if (e.which === 27) { $parent.find(toggle).trigger('focus') } return $this.trigger('click') } const desc = ' li:not(.divider):visible a' const $items = $parent.find(`[role="menu"]${desc}, [role="listbox"]${desc}`) if (!$items.length) { return } let index = $items.index(e.target) if (e.which === 38 && index > 0) index-- // up if (e.which === 40 && index < $items.length - 1) index++ // down if (!~index) index = 0 $items.eq(index).trigger('focus') } function clearMenus(e) { if (e && e.which === 3) { return } $(backdrop).remove() $(toggle).each(function () { const $this = $(this) const $parent = getParent($this) const relatedTarget = { relatedTarget: this, } if (!$parent.hasClass('open')) { return } const hideEvent = $.Event('hide.ui.dropdown', relatedTarget) $parent.trigger(hideEvent) if (hideEvent.isDefaultPrevented()) { return } $this.attr('aria-expanded', 'false') $parent.removeClass('open').trigger('hidden.ui.dropdown', relatedTarget) }) } function getParent($this) { let selector = $this.attr('data-target') const href = $this.attr('href') if (!selector && /#[A-Za-z]/.test(href)) { selector = href.replace(/.*(?=#[^\s]*$)/, '') } const $parent = selector && $(selector) return $parent && $parent.length ? $parent : $this.parent() } // DROPDOWN PLUGIN DEFINITION // ========================== function Plugin(option) { return this.each(function () { const $this = $(this) let data = $this.data('ui.dropdown') if (!data) { data = new Dropdown(this) $this.data('ui.dropdown', data) } if (typeof option === 'string') { data[option].call($this) } }) } export function init() { const old = $.fn.dropdown $.fn.dropdown = Plugin $.fn.dropdown.Constructor = Dropdown // DROPDOWN NO CONFLICT // ==================== $.fn.dropdown.noConflict = function () { $.fn.dropdown = old return this } // APPLY TO STANDARD DROPDOWN ELEMENTS // =================================== $(document) .on('click.ui.dropdown.data-api', clearMenus) .on('click.ui.dropdown.data-api', '.dropdown form', (e) => { e.stopPropagation() }) .on('click.ui.dropdown.data-api', toggle, Dropdown.prototype.toggle) .on('keydown.ui.dropdown.data-api', toggle, Dropdown.prototype.keydown) .on('keydown.ui.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown) .on('keydown.ui.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown) }