diff options
author | fat <jacobthornton@gmail.com> | 2013-05-16 23:50:06 +0400 |
---|---|---|
committer | fat <jacobthornton@gmail.com> | 2013-05-16 23:50:06 +0400 |
commit | 92245e8bc70f8d2e48036b7ba088551d07db29ca (patch) | |
tree | 4712d7114a60380513754f54931bd925d556545c /js | |
parent | bdbd268cb9cb64d0a8f6c77e56c139d18e21af5f (diff) |
change dropdown strategy to use an overlay - fixes mobile click anywhere + allows for firefox middle click
Diffstat (limited to 'js')
-rw-r--r-- | js/dropdown.js | 133 | ||||
-rw-r--r-- | js/tests/unit/dropdown.js | 6 |
2 files changed, 58 insertions, 81 deletions
diff --git a/js/dropdown.js b/js/dropdown.js index 342625074e..c3ad78895b 100644 --- a/js/dropdown.js +++ b/js/dropdown.js @@ -18,123 +18,101 @@ * ============================================================ */ -!function ($) { +!function ($) { "use strict"; - "use strict"; // jshint ;_; + // DROPDOWN CLASS DEFINITION + // ========================= - /* DROPDOWN CLASS DEFINITION - * ========================= */ - - var toggle = '[data-toggle=dropdown]' - , Dropdown = function (element) { - var $el = $(element).on('click.dropdown.data-api', this.toggle) - $('html').on('click.dropdown.data-api', function () { - $el.parent().removeClass('open') - }) - } - - Dropdown.prototype = { - - constructor: Dropdown - - , toggle: function (e) { - var $this = $(this) - , $parent - , isActive - - if ($this.is('.disabled, :disabled')) return - - $parent = getParent($this) + var backdrop = '.dropdown-backdrop' + var toggle = '[data-toggle=dropdown]' + var Dropdown = function (element) { + var $el = $(element).on('click.dropdown.data-api', this.toggle) + $('html').on('click.dropdown.data-api', function () { + $el.parent().removeClass('open') + }) + } - isActive = $parent.hasClass('open') + Dropdown.prototype.toggle = function (e) { + var $this = $(this) - clearMenus() + if ($this.is('.disabled, :disabled')) return - if (!isActive) { - $parent.toggleClass('open') - } + var $parent = getParent($this) + var isActive = $parent.hasClass('open') - $this.focus() + clearMenus() - return false + if (!isActive) { + $('<div class="dropdown-backdrop"/>').insertBefore($(this)).on('click', clearMenus) + $parent.toggleClass('open') } - , keydown: function (e) { - var $this - , $items - , $active - , $parent - , isActive - , index + $this.focus() - if (!/(38|40|27)/.test(e.keyCode)) return - - $this = $(this) + return false + } - e.preventDefault() - e.stopPropagation() + Dropdown.prototype.keydown = function (e) { + if (!/(38|40|27)/.test(e.keyCode)) return - if ($this.is('.disabled, :disabled')) return + var $this = $(this) - $parent = getParent($this) + e.preventDefault() + e.stopPropagation() - isActive = $parent.hasClass('open') + if ($this.is('.disabled, :disabled')) return - if (!isActive || (isActive && e.keyCode == 27)) { - if (e.which == 27) $parent.find(toggle).focus() - return $this.click() - } + var $parent = getParent($this) + var isActive = $parent.hasClass('open') - $items = $('[role=menu] li:not(.divider):visible a', $parent) + if (!isActive || (isActive && e.keyCode == 27)) { + if (e.which == 27) $parent.find(toggle).focus() + return $this.click() + } - if (!$items.length) return + var $items = $('[role=menu] li:not(.divider):visible a', $parent) - index = $items.index($items.filter(':focus')) + if (!$items.length) return - if (e.keyCode == 38 && index > 0) index-- // up - if (e.keyCode == 40 && index < $items.length - 1) index++ // down - if (!~index) index = 0 + var index = $items.index($items.filter(':focus')) - $items - .eq(index) - .focus() - } + if (e.keyCode == 38 && index > 0) index-- // up + if (e.keyCode == 40 && index < $items.length - 1) index++ // down + if (!~index) index=0 + $items.eq(index).focus() } function clearMenus() { - $(toggle).each(function () { - getParent($(this)).removeClass('open') - }) + $(backdrop).remove() + $(toggle).each(function () { getParent($(this)).removeClass('open') }) } function getParent($this) { var selector = $this.attr('data-target') - , $parent if (!selector) { selector = $this.attr('href') selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 } - $parent = selector && $(selector) - - if (!$parent || !$parent.length) $parent = $this.parent() + var $parent = selector && $(selector) - return $parent + return $parent && $parent.length ? $parent : $this.parent() } - /* DROPDOWN PLUGIN DEFINITION - * ========================== */ + // DROPDOWN PLUGIN DEFINITION + // ========================== var old = $.fn.dropdown $.fn.dropdown = function (option) { return this.each(function () { var $this = $(this) - , data = $this.data('dropdown') + var data = $this.data('dropdown') + if (!data) $this.data('dropdown', (data = new Dropdown(this))) if (typeof option == 'string') data[option].call($this) }) @@ -143,8 +121,8 @@ $.fn.dropdown.Constructor = Dropdown - /* DROPDOWN NO CONFLICT - * ==================== */ + // DROPDOWN NO CONFLICT + // ==================== $.fn.dropdown.noConflict = function () { $.fn.dropdown = old @@ -152,13 +130,12 @@ } - /* APPLY TO STANDARD DROPDOWN ELEMENTS - * =================================== */ + // APPLY TO STANDARD DROPDOWN ELEMENTS + // =================================== + $(document) - .on('click.dropdown.data-api', clearMenus) .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) - .on('click.dropdown-menu', function (e) { e.stopPropagation() }) .on('click.dropdown.data-api' , toggle, Dropdown.prototype.toggle) .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown) diff --git a/js/tests/unit/dropdown.js b/js/tests/unit/dropdown.js index db84a95a5d..6b66c0974f 100644 --- a/js/tests/unit/dropdown.js +++ b/js/tests/unit/dropdown.js @@ -104,7 +104,7 @@ $(function () { .dropdown() .click() ok(dropdown.parent('.dropdown').hasClass('open'), 'open class added on click') - $('body').click() + $('.dropdown-backdrop').click() ok(!dropdown.parent('.dropdown').hasClass('open'), 'open class removed') dropdown.remove() }) @@ -136,13 +136,13 @@ $(function () { first.click() ok(first.parents('.open').length == 1, 'open class added on click') ok($('#qunit-fixture .open').length == 1, 'only one object is open') - $('body').click() + $('.dropdown-backdrop').click() ok($("#qunit-fixture .open").length === 0, 'open class removed') last.click() ok(last.parent('.open').length == 1, 'open class added on click') ok($('#qunit-fixture .open').length == 1, 'only one object is open') - $('body').click() + $('.dropdown-backdrop').click() ok($("#qunit-fixture .open").length === 0, 'open class removed') $("#qunit-fixture").html("") |