Initial commit
[2ch-be.git] / dev-test / rewrite / js / dropdown-enhancement.js
blob02313e5dcb6fa7ec3e3640cd839838b74fde5d4a
1 /* ========================================================================
2  * Bootstrap Dropdowns Enhancement: dropdowns-enhancement.js v3.1.1 (Beta 1)
3  * http://behigh.github.io/bootstrap_dropdowns_enhancement/
4  * ========================================================================
5  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6  * ======================================================================== */
8 (function($) {
9     "use strict";
11     var toggle   = '[data-toggle="dropdown"]',
12         disabled = '.disabled, :disabled',
13         backdrop = '.dropdown-backdrop',
14         menuClass = 'dropdown-menu',
15         subMenuClass = 'dropdown-submenu',
16         namespace = '.bs.dropdown.data-api',
17         eventNamespace = '.bs.dropdown',
18         openClass = 'open',
19         touchSupport = 'ontouchstart' in document.documentElement,
20         opened;
23     function Dropdown(element) {
24         $(element).on('click' + eventNamespace, this.toggle)
25     }
27     var proto = Dropdown.prototype;
29     proto.toggle = function(event) {
30         var $element = $(this);
32         if ($element.is(disabled)) return;
34         var $parent = getParent($element);
35         var isActive = $parent.hasClass(openClass);
36         var isSubMenu = $parent.hasClass(subMenuClass);
37         var menuTree = isSubMenu ? getSubMenuParents($parent) : null;
39         closeOpened(event, menuTree);
41         if (!isActive) {
42             if (!menuTree)
43                 menuTree = [$parent];
45             if (touchSupport && !$parent.closest('.navbar-nav').length && !menuTree[0].find(backdrop).length) {
46                 // if mobile we use a backdrop because click events don't delegate
47                 $('<div class="' + backdrop.substr(1) + '"/>').appendTo(menuTree[0]).on('click', closeOpened)
48             }
50             for (var i = 0, s = menuTree.length; i < s; i++) {
51                 if (!menuTree[i].hasClass(openClass)) {
52                     menuTree[i].addClass(openClass);
53                     positioning(menuTree[i].children('.' + menuClass), menuTree[i]);
54                 }
55             }
56             opened = menuTree[0];
57         }
59         return false;
60     };
62     proto.keydown = function (e) {
63         if (!/(38|40|27)/.test(e.keyCode)) return;
65         var $this = $(this);
67         e.preventDefault();
68         e.stopPropagation();
70         if ($this.is('.disabled, :disabled')) return;
72         var $parent = getParent($this);
73         var isActive = $parent.hasClass('open');
75         if (!isActive || (isActive && e.keyCode == 27)) {
76             if (e.which == 27) $parent.find(toggle).trigger('focus');
77             return $this.trigger('click')
78         }
80         var desc = ' li:not(.divider):visible a';
81         var desc1 = 'li:not(.divider):visible > input:not(disabled) ~ label';
82         var $items = $parent.find(desc1 + ', ' + '[role="menu"]' + desc + ', [role="listbox"]' + desc);
84         if (!$items.length) return;
86         var index = $items.index($items.filter(':focus'));
88         if (e.keyCode == 38 && index > 0)                 index--;                        // up
89         if (e.keyCode == 40 && index < $items.length - 1) index++;                        // down
90         if (!~index)                                      index = 0;
92         $items.eq(index).trigger('focus')
93     };
95     proto.change = function (e) {
97         var
98             $parent,
99             $menu,
100             $toggle,
101             selector,
102             text = '',
103             $items;
105         $menu = $(this).closest('.' + menuClass);
107         $toggle = $menu.parent().find('[data-label-placement]');
109         if (!$toggle || !$toggle.length) {
110             $toggle = $menu.parent().find(toggle);
111         }
113         if (!$toggle || !$toggle.length || $toggle.data('placeholder') === false)
114             return; // do nothing, no control
116         ($toggle.data('placeholder') == undefined && $toggle.data('placeholder', $.trim($toggle.text())));
117         text = $.data($toggle[0], 'placeholder');
119         $items = $menu.find('li > input:checked');
121         if ($items.length) {
122             text = [];
123             $items.each(function () {
124                 var str = $(this).parent().find('label').eq(0),
125                     label = str.find('.data-label');
127                 if (label.length) {
128                     var p = $('<p></p>');
129                     p.append(label.clone());
130                     str = p.html();
131                 }
132                 else {
133                     str = str.html();
134                 }
137                 str && text.push($.trim(str));
138             });
140             text = text.length < 4 ? text.join(', ') : text.length + ' selected';
141         }
143         var caret = $toggle.find('.caret');
145         $toggle.html(text || '&nbsp;');
146         if (caret.length)
147             $toggle.append(' ') && caret.appendTo($toggle);
149     };
151     function positioning($menu, $control) {
152         if ($menu.hasClass('pull-center')) {
153             $menu.css('margin-right', $menu.outerWidth() / -2);
154         }
156         if ($menu.hasClass('pull-middle')) {
157             $menu.css('margin-top', ($menu.outerHeight() / -2) - ($control.outerHeight() / 2));
158         }
159     }
161     function closeOpened(event, menuTree) {
162         if (opened) {
164             if (!menuTree) {
165                 menuTree = [opened];
166             }
168             var parent;
170             if (opened[0] !== menuTree[0][0]) {
171                 parent = opened;
172             } else {
173                 parent = menuTree[menuTree.length - 1];
174                 if (parent.parent().hasClass(menuClass)) {
175                     parent = parent.parent();
176                 }
177             }
179             parent.find('.' + openClass).removeClass(openClass);
181             if (parent.hasClass(openClass))
182                 parent.removeClass(openClass);
184             if (parent === opened) {
185                 opened = null;
186                 $(backdrop).remove();
187             }
188         }
189     }
191     function getSubMenuParents($submenu) {
192         var result = [$submenu];
193         var $parent;
194         while (!$parent || $parent.hasClass(subMenuClass)) {
195             $parent = ($parent || $submenu).parent();
196             if ($parent.hasClass(menuClass)) {
197                 $parent = $parent.parent();
198             }
199             if ($parent.children(toggle)) {
200                 result.unshift($parent);
201             }
202         }
203         return result;
204     }
206     function getParent($this) {
207         var selector = $this.attr('data-target');
209         if (!selector) {
210             selector = $this.attr('href');
211             selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, ''); //strip for ie7
212         }
214         var $parent = selector && $(selector);
216         return $parent && $parent.length ? $parent : $this.parent()
217     }
219     // DROPDOWN PLUGIN DEFINITION
220     // ==========================
222     var old = $.fn.dropdown;
224     $.fn.dropdown = function (option) {
225         return this.each(function () {
226             var $this = $(this);
227             var data = $this.data('bs.dropdown');
229             if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)));
230             if (typeof option == 'string') data[option].call($this);
231         })
232     };
234     $.fn.dropdown.Constructor = Dropdown;
236     $.fn.dropdown.clearMenus = function(e) {
237         $(backdrop).remove();
238         $('.' + openClass + ' ' + toggle).each(function () {
239             var $parent = getParent($(this));
240             var relatedTarget = { relatedTarget: this };
241             if (!$parent.hasClass('open')) return;
242             $parent.trigger(e = $.Event('hide' + eventNamespace, relatedTarget));
243             if (e.isDefaultPrevented()) return;
244             $parent.removeClass('open').trigger('hidden' + eventNamespace, relatedTarget);
245         });
246         return this;
247     };
250     // DROPDOWN NO CONFLICT
251     // ====================
253     $.fn.dropdown.noConflict = function () {
254         $.fn.dropdown = old;
255         return this
256     };
259     $(document).off(namespace)
260         .on('click' + namespace, closeOpened)
261         .on('click' + namespace, toggle, proto.toggle)
262         .on('click' + namespace, '.dropdown-menu > li > input[type="checkbox"] ~ label, .dropdown-menu > li > input[type="checkbox"], .dropdown-menu.noclose > li', function (e) {
263             e.stopPropagation()
264         })
265         .on('change' + namespace, '.dropdown-menu > li > input[type="checkbox"], .dropdown-menu > li > input[type="radio"]', proto.change)
266         .on('keydown' + namespace, toggle + ', [role="menu"], [role="listbox"]', proto.keydown)
267 }(jQuery));