sn-jquery-ui-rails 6.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (177) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +2 -0
  5. data/Gemfile +3 -0
  6. data/History.md +168 -0
  7. data/License.txt +2 -0
  8. data/README.md +311 -0
  9. data/Rakefile +258 -0
  10. data/VERSIONS.md +39 -0
  11. data/app/assets/images/jquery-ui/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  12. data/app/assets/images/jquery-ui/ui-icons_444444_256x240.png +0 -0
  13. data/app/assets/images/jquery-ui/ui-icons_555555_256x240.png +0 -0
  14. data/app/assets/images/jquery-ui/ui-icons_777620_256x240.png +0 -0
  15. data/app/assets/images/jquery-ui/ui-icons_777777_256x240.png +0 -0
  16. data/app/assets/images/jquery-ui/ui-icons_cc0000_256x240.png +0 -0
  17. data/app/assets/images/jquery-ui/ui-icons_ffffff_256x240.png +0 -0
  18. data/app/assets/javascripts/jquery-ui/core.js +15 -0
  19. data/app/assets/javascripts/jquery-ui/data.js +41 -0
  20. data/app/assets/javascripts/jquery-ui/disable-selection.js +48 -0
  21. data/app/assets/javascripts/jquery-ui/effect.all.js +15 -0
  22. data/app/assets/javascripts/jquery-ui/effect.js +1637 -0
  23. data/app/assets/javascripts/jquery-ui/effects/effect-blind.js +73 -0
  24. data/app/assets/javascripts/jquery-ui/effects/effect-bounce.js +113 -0
  25. data/app/assets/javascripts/jquery-ui/effects/effect-clip.js +68 -0
  26. data/app/assets/javascripts/jquery-ui/effects/effect-drop.js +72 -0
  27. data/app/assets/javascripts/jquery-ui/effects/effect-explode.js +114 -0
  28. data/app/assets/javascripts/jquery-ui/effects/effect-fade.js +50 -0
  29. data/app/assets/javascripts/jquery-ui/effects/effect-fold.js +92 -0
  30. data/app/assets/javascripts/jquery-ui/effects/effect-highlight.js +60 -0
  31. data/app/assets/javascripts/jquery-ui/effects/effect-puff.js +46 -0
  32. data/app/assets/javascripts/jquery-ui/effects/effect-pulsate.js +67 -0
  33. data/app/assets/javascripts/jquery-ui/effects/effect-scale.js +60 -0
  34. data/app/assets/javascripts/jquery-ui/effects/effect-shake.js +77 -0
  35. data/app/assets/javascripts/jquery-ui/effects/effect-size.js +194 -0
  36. data/app/assets/javascripts/jquery-ui/effects/effect-slide.js +79 -0
  37. data/app/assets/javascripts/jquery-ui/effects/effect-transfer.js +43 -0
  38. data/app/assets/javascripts/jquery-ui/escape-selector.js +23 -0
  39. data/app/assets/javascripts/jquery-ui/focusable.js +86 -0
  40. data/app/assets/javascripts/jquery-ui/form-reset-mixin.js +80 -0
  41. data/app/assets/javascripts/jquery-ui/form.js +22 -0
  42. data/app/assets/javascripts/jquery-ui/i18n/datepicker-af.js +37 -0
  43. data/app/assets/javascripts/jquery-ui/i18n/datepicker-ar-DZ.js +39 -0
  44. data/app/assets/javascripts/jquery-ui/i18n/datepicker-ar.js +39 -0
  45. data/app/assets/javascripts/jquery-ui/i18n/datepicker-az.js +37 -0
  46. data/app/assets/javascripts/jquery-ui/i18n/datepicker-be.js +37 -0
  47. data/app/assets/javascripts/jquery-ui/i18n/datepicker-bg.js +38 -0
  48. data/app/assets/javascripts/jquery-ui/i18n/datepicker-bs.js +37 -0
  49. data/app/assets/javascripts/jquery-ui/i18n/datepicker-ca.js +37 -0
  50. data/app/assets/javascripts/jquery-ui/i18n/datepicker-cs.js +37 -0
  51. data/app/assets/javascripts/jquery-ui/i18n/datepicker-cy-GB.js +45 -0
  52. data/app/assets/javascripts/jquery-ui/i18n/datepicker-da.js +37 -0
  53. data/app/assets/javascripts/jquery-ui/i18n/datepicker-de.js +37 -0
  54. data/app/assets/javascripts/jquery-ui/i18n/datepicker-el.js +37 -0
  55. data/app/assets/javascripts/jquery-ui/i18n/datepicker-en-AU.js +37 -0
  56. data/app/assets/javascripts/jquery-ui/i18n/datepicker-en-GB.js +37 -0
  57. data/app/assets/javascripts/jquery-ui/i18n/datepicker-en-NZ.js +37 -0
  58. data/app/assets/javascripts/jquery-ui/i18n/datepicker-eo.js +37 -0
  59. data/app/assets/javascripts/jquery-ui/i18n/datepicker-es.js +37 -0
  60. data/app/assets/javascripts/jquery-ui/i18n/datepicker-et.js +45 -0
  61. data/app/assets/javascripts/jquery-ui/i18n/datepicker-eu.js +36 -0
  62. data/app/assets/javascripts/jquery-ui/i18n/datepicker-fa.js +73 -0
  63. data/app/assets/javascripts/jquery-ui/i18n/datepicker-fi.js +37 -0
  64. data/app/assets/javascripts/jquery-ui/i18n/datepicker-fo.js +45 -0
  65. data/app/assets/javascripts/jquery-ui/i18n/datepicker-fr-CA.js +37 -0
  66. data/app/assets/javascripts/jquery-ui/i18n/datepicker-fr-CH.js +37 -0
  67. data/app/assets/javascripts/jquery-ui/i18n/datepicker-fr.js +39 -0
  68. data/app/assets/javascripts/jquery-ui/i18n/datepicker-gl.js +37 -0
  69. data/app/assets/javascripts/jquery-ui/i18n/datepicker-he.js +37 -0
  70. data/app/assets/javascripts/jquery-ui/i18n/datepicker-hi.js +37 -0
  71. data/app/assets/javascripts/jquery-ui/i18n/datepicker-hr.js +37 -0
  72. data/app/assets/javascripts/jquery-ui/i18n/datepicker-hu.js +36 -0
  73. data/app/assets/javascripts/jquery-ui/i18n/datepicker-hy.js +37 -0
  74. data/app/assets/javascripts/jquery-ui/i18n/datepicker-id.js +37 -0
  75. data/app/assets/javascripts/jquery-ui/i18n/datepicker-is.js +45 -0
  76. data/app/assets/javascripts/jquery-ui/i18n/datepicker-it-CH.js +37 -0
  77. data/app/assets/javascripts/jquery-ui/i18n/datepicker-it.js +37 -0
  78. data/app/assets/javascripts/jquery-ui/i18n/datepicker-ja.js +37 -0
  79. data/app/assets/javascripts/jquery-ui/i18n/datepicker-ka.js +48 -0
  80. data/app/assets/javascripts/jquery-ui/i18n/datepicker-kk.js +37 -0
  81. data/app/assets/javascripts/jquery-ui/i18n/datepicker-km.js +37 -0
  82. data/app/assets/javascripts/jquery-ui/i18n/datepicker-ko.js +37 -0
  83. data/app/assets/javascripts/jquery-ui/i18n/datepicker-ky.js +38 -0
  84. data/app/assets/javascripts/jquery-ui/i18n/datepicker-lb.js +45 -0
  85. data/app/assets/javascripts/jquery-ui/i18n/datepicker-lt.js +45 -0
  86. data/app/assets/javascripts/jquery-ui/i18n/datepicker-lv.js +45 -0
  87. data/app/assets/javascripts/jquery-ui/i18n/datepicker-mk.js +37 -0
  88. data/app/assets/javascripts/jquery-ui/i18n/datepicker-ml.js +37 -0
  89. data/app/assets/javascripts/jquery-ui/i18n/datepicker-ms.js +37 -0
  90. data/app/assets/javascripts/jquery-ui/i18n/datepicker-nb.js +49 -0
  91. data/app/assets/javascripts/jquery-ui/i18n/datepicker-nl-BE.js +37 -0
  92. data/app/assets/javascripts/jquery-ui/i18n/datepicker-nl.js +37 -0
  93. data/app/assets/javascripts/jquery-ui/i18n/datepicker-nn.js +49 -0
  94. data/app/assets/javascripts/jquery-ui/i18n/datepicker-no.js +50 -0
  95. data/app/assets/javascripts/jquery-ui/i18n/datepicker-pl.js +37 -0
  96. data/app/assets/javascripts/jquery-ui/i18n/datepicker-pt-BR.js +45 -0
  97. data/app/assets/javascripts/jquery-ui/i18n/datepicker-pt.js +44 -0
  98. data/app/assets/javascripts/jquery-ui/i18n/datepicker-rm.js +61 -0
  99. data/app/assets/javascripts/jquery-ui/i18n/datepicker-ro.js +40 -0
  100. data/app/assets/javascripts/jquery-ui/i18n/datepicker-ru.js +37 -0
  101. data/app/assets/javascripts/jquery-ui/i18n/datepicker-sk.js +37 -0
  102. data/app/assets/javascripts/jquery-ui/i18n/datepicker-sl.js +38 -0
  103. data/app/assets/javascripts/jquery-ui/i18n/datepicker-sq.js +37 -0
  104. data/app/assets/javascripts/jquery-ui/i18n/datepicker-sr-SR.js +37 -0
  105. data/app/assets/javascripts/jquery-ui/i18n/datepicker-sr.js +37 -0
  106. data/app/assets/javascripts/jquery-ui/i18n/datepicker-sv.js +37 -0
  107. data/app/assets/javascripts/jquery-ui/i18n/datepicker-ta.js +53 -0
  108. data/app/assets/javascripts/jquery-ui/i18n/datepicker-th.js +37 -0
  109. data/app/assets/javascripts/jquery-ui/i18n/datepicker-tj.js +37 -0
  110. data/app/assets/javascripts/jquery-ui/i18n/datepicker-tr.js +37 -0
  111. data/app/assets/javascripts/jquery-ui/i18n/datepicker-uk.js +38 -0
  112. data/app/assets/javascripts/jquery-ui/i18n/datepicker-vi.js +37 -0
  113. data/app/assets/javascripts/jquery-ui/i18n/datepicker-zh-CN.js +37 -0
  114. data/app/assets/javascripts/jquery-ui/i18n/datepicker-zh-HK.js +37 -0
  115. data/app/assets/javascripts/jquery-ui/i18n/datepicker-zh-TW.js +37 -0
  116. data/app/assets/javascripts/jquery-ui/ie.js +17 -0
  117. data/app/assets/javascripts/jquery-ui/jquery-1-7.js +91 -0
  118. data/app/assets/javascripts/jquery-ui/keycode.js +47 -0
  119. data/app/assets/javascripts/jquery-ui/labels.js +65 -0
  120. data/app/assets/javascripts/jquery-ui/plugin.js +46 -0
  121. data/app/assets/javascripts/jquery-ui/position.js +500 -0
  122. data/app/assets/javascripts/jquery-ui/safe-active-element.js +42 -0
  123. data/app/assets/javascripts/jquery-ui/safe-blur.js +23 -0
  124. data/app/assets/javascripts/jquery-ui/scroll-parent.js +47 -0
  125. data/app/assets/javascripts/jquery-ui/tabbable.js +38 -0
  126. data/app/assets/javascripts/jquery-ui/unique-id.js +51 -0
  127. data/app/assets/javascripts/jquery-ui/version.js +17 -0
  128. data/app/assets/javascripts/jquery-ui/widget.js +735 -0
  129. data/app/assets/javascripts/jquery-ui/widgets/accordion.js +618 -0
  130. data/app/assets/javascripts/jquery-ui/widgets/autocomplete.js +689 -0
  131. data/app/assets/javascripts/jquery-ui/widgets/button.js +391 -0
  132. data/app/assets/javascripts/jquery-ui/widgets/checkboxradio.js +291 -0
  133. data/app/assets/javascripts/jquery-ui/widgets/controlgroup.js +300 -0
  134. data/app/assets/javascripts/jquery-ui/widgets/datepicker.js +2123 -0
  135. data/app/assets/javascripts/jquery-ui/widgets/dialog.js +954 -0
  136. data/app/assets/javascripts/jquery-ui/widgets/draggable.js +1259 -0
  137. data/app/assets/javascripts/jquery-ui/widgets/droppable.js +502 -0
  138. data/app/assets/javascripts/jquery-ui/widgets/menu.js +680 -0
  139. data/app/assets/javascripts/jquery-ui/widgets/mouse.js +230 -0
  140. data/app/assets/javascripts/jquery-ui/widgets/progressbar.js +181 -0
  141. data/app/assets/javascripts/jquery-ui/widgets/resizable.js +1207 -0
  142. data/app/assets/javascripts/jquery-ui/widgets/selectable.js +314 -0
  143. data/app/assets/javascripts/jquery-ui/widgets/selectmenu.js +697 -0
  144. data/app/assets/javascripts/jquery-ui/widgets/slider.js +757 -0
  145. data/app/assets/javascripts/jquery-ui/widgets/sortable.js +1561 -0
  146. data/app/assets/javascripts/jquery-ui/widgets/spinner.js +581 -0
  147. data/app/assets/javascripts/jquery-ui/widgets/tabs.js +931 -0
  148. data/app/assets/javascripts/jquery-ui/widgets/tooltip.js +526 -0
  149. data/app/assets/javascripts/jquery-ui.js +56 -0
  150. data/app/assets/stylesheets/jquery-ui/accordion.css +26 -0
  151. data/app/assets/stylesheets/jquery-ui/all.css +14 -0
  152. data/app/assets/stylesheets/jquery-ui/autocomplete.css +19 -0
  153. data/app/assets/stylesheets/jquery-ui/base.css +32 -0
  154. data/app/assets/stylesheets/jquery-ui/button.css +85 -0
  155. data/app/assets/stylesheets/jquery-ui/checkboxradio.css +37 -0
  156. data/app/assets/stylesheets/jquery-ui/controlgroup.css +68 -0
  157. data/app/assets/stylesheets/jquery-ui/core.css +100 -0
  158. data/app/assets/stylesheets/jquery-ui/datepicker.css +188 -0
  159. data/app/assets/stylesheets/jquery-ui/dialog.css +104 -0
  160. data/app/assets/stylesheets/jquery-ui/draggable.css +15 -0
  161. data/app/assets/stylesheets/jquery-ui/menu.css +67 -0
  162. data/app/assets/stylesheets/jquery-ui/progressbar.css +31 -0
  163. data/app/assets/stylesheets/jquery-ui/resizable.css +81 -0
  164. data/app/assets/stylesheets/jquery-ui/selectable.css +20 -0
  165. data/app/assets/stylesheets/jquery-ui/selectmenu.css +53 -0
  166. data/app/assets/stylesheets/jquery-ui/slider.css +78 -0
  167. data/app/assets/stylesheets/jquery-ui/sortable.css +15 -0
  168. data/app/assets/stylesheets/jquery-ui/spinner.css +55 -0
  169. data/app/assets/stylesheets/jquery-ui/tabs.css +54 -0
  170. data/app/assets/stylesheets/jquery-ui/theme.css.erb +453 -0
  171. data/app/assets/stylesheets/jquery-ui/tooltip.css +22 -0
  172. data/app/assets/stylesheets/jquery-ui.css +1 -0
  173. data/lib/jquery/ui/rails/engine.rb +8 -0
  174. data/lib/jquery/ui/rails/version.rb +8 -0
  175. data/lib/jquery/ui/rails.rb +2 -0
  176. data/lib/jquery-ui-rails.rb +1 -0
  177. metadata +248 -0
@@ -0,0 +1,680 @@
1
+ //= require jquery-ui/keycode
2
+ //= require jquery-ui/position
3
+ //= require jquery-ui/safe-active-element
4
+ //= require jquery-ui/unique-id
5
+ //= require jquery-ui/version
6
+ //= require jquery-ui/widget
7
+
8
+ /*!
9
+ * jQuery UI Menu 1.12.1
10
+ * http://jqueryui.com
11
+ *
12
+ * Copyright jQuery Foundation and other contributors
13
+ * Released under the MIT license.
14
+ * http://jquery.org/license
15
+ */
16
+
17
+ //>>label: Menu
18
+ //>>group: Widgets
19
+ //>>description: Creates nestable menus.
20
+ //>>docs: http://api.jqueryui.com/menu/
21
+ //>>demos: http://jqueryui.com/menu/
22
+ //>>css.structure: ../../themes/base/core.css
23
+ //>>css.structure: ../../themes/base/menu.css
24
+ //>>css.theme: ../../themes/base/theme.css
25
+
26
+ ( function( factory ) {
27
+ if ( typeof define === "function" && define.amd ) {
28
+
29
+ // AMD. Register as an anonymous module.
30
+ define( [
31
+ "jquery",
32
+ "../keycode",
33
+ "../position",
34
+ "../safe-active-element",
35
+ "../unique-id",
36
+ "../version",
37
+ "../widget"
38
+ ], factory );
39
+ } else {
40
+
41
+ // Browser globals
42
+ factory( jQuery );
43
+ }
44
+ }( function( $ ) {
45
+
46
+ return $.widget( "ui.menu", {
47
+ version: "1.12.1",
48
+ defaultElement: "<ul>",
49
+ delay: 300,
50
+ options: {
51
+ icons: {
52
+ submenu: "ui-icon-caret-1-e"
53
+ },
54
+ items: "> *",
55
+ menus: "ul",
56
+ position: {
57
+ my: "left top",
58
+ at: "right top"
59
+ },
60
+ role: "menu",
61
+
62
+ // Callbacks
63
+ blur: null,
64
+ focus: null,
65
+ select: null
66
+ },
67
+
68
+ _create: function() {
69
+ this.activeMenu = this.element;
70
+
71
+ // Flag used to prevent firing of the click handler
72
+ // as the event bubbles up through nested menus
73
+ this.mouseHandled = false;
74
+ this.element
75
+ .uniqueId()
76
+ .attr( {
77
+ role: this.options.role,
78
+ tabIndex: 0
79
+ } );
80
+
81
+ this._addClass( "ui-menu", "ui-widget ui-widget-content" );
82
+ this._on( {
83
+
84
+ // Prevent focus from sticking to links inside menu after clicking
85
+ // them (focus should always stay on UL during navigation).
86
+ "mousedown .ui-menu-item": function( event ) {
87
+ event.preventDefault();
88
+ },
89
+ "click .ui-menu-item": function( event ) {
90
+ var target = $( event.target );
91
+ var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
92
+ if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
93
+ this.select( event );
94
+
95
+ // Only set the mouseHandled flag if the event will bubble, see #9469.
96
+ if ( !event.isPropagationStopped() ) {
97
+ this.mouseHandled = true;
98
+ }
99
+
100
+ // Open submenu on click
101
+ if ( target.has( ".ui-menu" ).length ) {
102
+ this.expand( event );
103
+ } else if ( !this.element.is( ":focus" ) &&
104
+ active.closest( ".ui-menu" ).length ) {
105
+
106
+ // Redirect focus to the menu
107
+ this.element.trigger( "focus", [ true ] );
108
+
109
+ // If the active item is on the top level, let it stay active.
110
+ // Otherwise, blur the active item since it is no longer visible.
111
+ if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
112
+ clearTimeout( this.timer );
113
+ }
114
+ }
115
+ }
116
+ },
117
+ "mouseenter .ui-menu-item": function( event ) {
118
+
119
+ // Ignore mouse events while typeahead is active, see #10458.
120
+ // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
121
+ // is over an item in the menu
122
+ if ( this.previousFilter ) {
123
+ return;
124
+ }
125
+
126
+ var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
127
+ target = $( event.currentTarget );
128
+
129
+ // Ignore bubbled events on parent items, see #11641
130
+ if ( actualTarget[ 0 ] !== target[ 0 ] ) {
131
+ return;
132
+ }
133
+
134
+ // Remove ui-state-active class from siblings of the newly focused menu item
135
+ // to avoid a jump caused by adjacent elements both having a class with a border
136
+ this._removeClass( target.siblings().children( ".ui-state-active" ),
137
+ null, "ui-state-active" );
138
+ this.focus( event, target );
139
+ },
140
+ mouseleave: "collapseAll",
141
+ "mouseleave .ui-menu": "collapseAll",
142
+ focus: function( event, keepActiveItem ) {
143
+
144
+ // If there's already an active item, keep it active
145
+ // If not, activate the first item
146
+ var item = this.active || this.element.find( this.options.items ).eq( 0 );
147
+
148
+ if ( !keepActiveItem ) {
149
+ this.focus( event, item );
150
+ }
151
+ },
152
+ blur: function( event ) {
153
+ this._delay( function() {
154
+ var notContained = !$.contains(
155
+ this.element[ 0 ],
156
+ $.ui.safeActiveElement( this.document[ 0 ] )
157
+ );
158
+ if ( notContained ) {
159
+ this.collapseAll( event );
160
+ }
161
+ } );
162
+ },
163
+ keydown: "_keydown"
164
+ } );
165
+
166
+ this.refresh();
167
+
168
+ // Clicks outside of a menu collapse any open menus
169
+ this._on( this.document, {
170
+ click: function( event ) {
171
+ if ( this._closeOnDocumentClick( event ) ) {
172
+ this.collapseAll( event );
173
+ }
174
+
175
+ // Reset the mouseHandled flag
176
+ this.mouseHandled = false;
177
+ }
178
+ } );
179
+ },
180
+
181
+ _destroy: function() {
182
+ var items = this.element.find( ".ui-menu-item" )
183
+ .removeAttr( "role aria-disabled" ),
184
+ submenus = items.children( ".ui-menu-item-wrapper" )
185
+ .removeUniqueId()
186
+ .removeAttr( "tabIndex role aria-haspopup" );
187
+
188
+ // Destroy (sub)menus
189
+ this.element
190
+ .removeAttr( "aria-activedescendant" )
191
+ .find( ".ui-menu" ).addBack()
192
+ .removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
193
+ "tabIndex" )
194
+ .removeUniqueId()
195
+ .show();
196
+
197
+ submenus.children().each( function() {
198
+ var elem = $( this );
199
+ if ( elem.data( "ui-menu-submenu-caret" ) ) {
200
+ elem.remove();
201
+ }
202
+ } );
203
+ },
204
+
205
+ _keydown: function( event ) {
206
+ var match, prev, character, skip,
207
+ preventDefault = true;
208
+
209
+ switch ( event.keyCode ) {
210
+ case $.ui.keyCode.PAGE_UP:
211
+ this.previousPage( event );
212
+ break;
213
+ case $.ui.keyCode.PAGE_DOWN:
214
+ this.nextPage( event );
215
+ break;
216
+ case $.ui.keyCode.HOME:
217
+ this._move( "first", "first", event );
218
+ break;
219
+ case $.ui.keyCode.END:
220
+ this._move( "last", "last", event );
221
+ break;
222
+ case $.ui.keyCode.UP:
223
+ this.previous( event );
224
+ break;
225
+ case $.ui.keyCode.DOWN:
226
+ this.next( event );
227
+ break;
228
+ case $.ui.keyCode.LEFT:
229
+ this.collapse( event );
230
+ break;
231
+ case $.ui.keyCode.RIGHT:
232
+ if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
233
+ this.expand( event );
234
+ }
235
+ break;
236
+ case $.ui.keyCode.ENTER:
237
+ case $.ui.keyCode.SPACE:
238
+ this._activate( event );
239
+ break;
240
+ case $.ui.keyCode.ESCAPE:
241
+ this.collapse( event );
242
+ break;
243
+ default:
244
+ preventDefault = false;
245
+ prev = this.previousFilter || "";
246
+ skip = false;
247
+
248
+ // Support number pad values
249
+ character = event.keyCode >= 96 && event.keyCode <= 105 ?
250
+ ( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
251
+
252
+ clearTimeout( this.filterTimer );
253
+
254
+ if ( character === prev ) {
255
+ skip = true;
256
+ } else {
257
+ character = prev + character;
258
+ }
259
+
260
+ match = this._filterMenuItems( character );
261
+ match = skip && match.index( this.active.next() ) !== -1 ?
262
+ this.active.nextAll( ".ui-menu-item" ) :
263
+ match;
264
+
265
+ // If no matches on the current filter, reset to the last character pressed
266
+ // to move down the menu to the first item that starts with that character
267
+ if ( !match.length ) {
268
+ character = String.fromCharCode( event.keyCode );
269
+ match = this._filterMenuItems( character );
270
+ }
271
+
272
+ if ( match.length ) {
273
+ this.focus( event, match );
274
+ this.previousFilter = character;
275
+ this.filterTimer = this._delay( function() {
276
+ delete this.previousFilter;
277
+ }, 1000 );
278
+ } else {
279
+ delete this.previousFilter;
280
+ }
281
+ }
282
+
283
+ if ( preventDefault ) {
284
+ event.preventDefault();
285
+ }
286
+ },
287
+
288
+ _activate: function( event ) {
289
+ if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
290
+ if ( this.active.children( "[aria-haspopup='true']" ).length ) {
291
+ this.expand( event );
292
+ } else {
293
+ this.select( event );
294
+ }
295
+ }
296
+ },
297
+
298
+ refresh: function() {
299
+ var menus, items, newSubmenus, newItems, newWrappers,
300
+ that = this,
301
+ icon = this.options.icons.submenu,
302
+ submenus = this.element.find( this.options.menus );
303
+
304
+ this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
305
+
306
+ // Initialize nested menus
307
+ newSubmenus = submenus.filter( ":not(.ui-menu)" )
308
+ .hide()
309
+ .attr( {
310
+ role: this.options.role,
311
+ "aria-hidden": "true",
312
+ "aria-expanded": "false"
313
+ } )
314
+ .each( function() {
315
+ var menu = $( this ),
316
+ item = menu.prev(),
317
+ submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
318
+
319
+ that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
320
+ item
321
+ .attr( "aria-haspopup", "true" )
322
+ .prepend( submenuCaret );
323
+ menu.attr( "aria-labelledby", item.attr( "id" ) );
324
+ } );
325
+
326
+ this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
327
+
328
+ menus = submenus.add( this.element );
329
+ items = menus.find( this.options.items );
330
+
331
+ // Initialize menu-items containing spaces and/or dashes only as dividers
332
+ items.not( ".ui-menu-item" ).each( function() {
333
+ var item = $( this );
334
+ if ( that._isDivider( item ) ) {
335
+ that._addClass( item, "ui-menu-divider", "ui-widget-content" );
336
+ }
337
+ } );
338
+
339
+ // Don't refresh list items that are already adapted
340
+ newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
341
+ newWrappers = newItems.children()
342
+ .not( ".ui-menu" )
343
+ .uniqueId()
344
+ .attr( {
345
+ tabIndex: -1,
346
+ role: this._itemRole()
347
+ } );
348
+ this._addClass( newItems, "ui-menu-item" )
349
+ ._addClass( newWrappers, "ui-menu-item-wrapper" );
350
+
351
+ // Add aria-disabled attribute to any disabled menu item
352
+ items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
353
+
354
+ // If the active item has been removed, blur the menu
355
+ if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
356
+ this.blur();
357
+ }
358
+ },
359
+
360
+ _itemRole: function() {
361
+ return {
362
+ menu: "menuitem",
363
+ listbox: "option"
364
+ }[ this.options.role ];
365
+ },
366
+
367
+ _setOption: function( key, value ) {
368
+ if ( key === "icons" ) {
369
+ var icons = this.element.find( ".ui-menu-icon" );
370
+ this._removeClass( icons, null, this.options.icons.submenu )
371
+ ._addClass( icons, null, value.submenu );
372
+ }
373
+ this._super( key, value );
374
+ },
375
+
376
+ _setOptionDisabled: function( value ) {
377
+ this._super( value );
378
+
379
+ this.element.attr( "aria-disabled", String( value ) );
380
+ this._toggleClass( null, "ui-state-disabled", !!value );
381
+ },
382
+
383
+ focus: function( event, item ) {
384
+ var nested, focused, activeParent;
385
+ this.blur( event, event && event.type === "focus" );
386
+
387
+ this._scrollIntoView( item );
388
+
389
+ this.active = item.first();
390
+
391
+ focused = this.active.children( ".ui-menu-item-wrapper" );
392
+ this._addClass( focused, null, "ui-state-active" );
393
+
394
+ // Only update aria-activedescendant if there's a role
395
+ // otherwise we assume focus is managed elsewhere
396
+ if ( this.options.role ) {
397
+ this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
398
+ }
399
+
400
+ // Highlight active parent menu item, if any
401
+ activeParent = this.active
402
+ .parent()
403
+ .closest( ".ui-menu-item" )
404
+ .children( ".ui-menu-item-wrapper" );
405
+ this._addClass( activeParent, null, "ui-state-active" );
406
+
407
+ if ( event && event.type === "keydown" ) {
408
+ this._close();
409
+ } else {
410
+ this.timer = this._delay( function() {
411
+ this._close();
412
+ }, this.delay );
413
+ }
414
+
415
+ nested = item.children( ".ui-menu" );
416
+ if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
417
+ this._startOpening( nested );
418
+ }
419
+ this.activeMenu = item.parent();
420
+
421
+ this._trigger( "focus", event, { item: item } );
422
+ },
423
+
424
+ _scrollIntoView: function( item ) {
425
+ var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
426
+ if ( this._hasScroll() ) {
427
+ borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
428
+ paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
429
+ offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
430
+ scroll = this.activeMenu.scrollTop();
431
+ elementHeight = this.activeMenu.height();
432
+ itemHeight = item.outerHeight();
433
+
434
+ if ( offset < 0 ) {
435
+ this.activeMenu.scrollTop( scroll + offset );
436
+ } else if ( offset + itemHeight > elementHeight ) {
437
+ this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
438
+ }
439
+ }
440
+ },
441
+
442
+ blur: function( event, fromFocus ) {
443
+ if ( !fromFocus ) {
444
+ clearTimeout( this.timer );
445
+ }
446
+
447
+ if ( !this.active ) {
448
+ return;
449
+ }
450
+
451
+ this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
452
+ null, "ui-state-active" );
453
+
454
+ this._trigger( "blur", event, { item: this.active } );
455
+ this.active = null;
456
+ },
457
+
458
+ _startOpening: function( submenu ) {
459
+ clearTimeout( this.timer );
460
+
461
+ // Don't open if already open fixes a Firefox bug that caused a .5 pixel
462
+ // shift in the submenu position when mousing over the caret icon
463
+ if ( submenu.attr( "aria-hidden" ) !== "true" ) {
464
+ return;
465
+ }
466
+
467
+ this.timer = this._delay( function() {
468
+ this._close();
469
+ this._open( submenu );
470
+ }, this.delay );
471
+ },
472
+
473
+ _open: function( submenu ) {
474
+ var position = $.extend( {
475
+ of: this.active
476
+ }, this.options.position );
477
+
478
+ clearTimeout( this.timer );
479
+ this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
480
+ .hide()
481
+ .attr( "aria-hidden", "true" );
482
+
483
+ submenu
484
+ .show()
485
+ .removeAttr( "aria-hidden" )
486
+ .attr( "aria-expanded", "true" )
487
+ .position( position );
488
+ },
489
+
490
+ collapseAll: function( event, all ) {
491
+ clearTimeout( this.timer );
492
+ this.timer = this._delay( function() {
493
+
494
+ // If we were passed an event, look for the submenu that contains the event
495
+ var currentMenu = all ? this.element :
496
+ $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
497
+
498
+ // If we found no valid submenu ancestor, use the main menu to close all
499
+ // sub menus anyway
500
+ if ( !currentMenu.length ) {
501
+ currentMenu = this.element;
502
+ }
503
+
504
+ this._close( currentMenu );
505
+
506
+ this.blur( event );
507
+
508
+ // Work around active item staying active after menu is blurred
509
+ this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
510
+
511
+ this.activeMenu = currentMenu;
512
+ }, this.delay );
513
+ },
514
+
515
+ // With no arguments, closes the currently active menu - if nothing is active
516
+ // it closes all menus. If passed an argument, it will search for menus BELOW
517
+ _close: function( startMenu ) {
518
+ if ( !startMenu ) {
519
+ startMenu = this.active ? this.active.parent() : this.element;
520
+ }
521
+
522
+ startMenu.find( ".ui-menu" )
523
+ .hide()
524
+ .attr( "aria-hidden", "true" )
525
+ .attr( "aria-expanded", "false" );
526
+ },
527
+
528
+ _closeOnDocumentClick: function( event ) {
529
+ return !$( event.target ).closest( ".ui-menu" ).length;
530
+ },
531
+
532
+ _isDivider: function( item ) {
533
+
534
+ // Match hyphen, em dash, en dash
535
+ return !/[^\-\u2014\u2013\s]/.test( item.text() );
536
+ },
537
+
538
+ collapse: function( event ) {
539
+ var newItem = this.active &&
540
+ this.active.parent().closest( ".ui-menu-item", this.element );
541
+ if ( newItem && newItem.length ) {
542
+ this._close();
543
+ this.focus( event, newItem );
544
+ }
545
+ },
546
+
547
+ expand: function( event ) {
548
+ var newItem = this.active &&
549
+ this.active
550
+ .children( ".ui-menu " )
551
+ .find( this.options.items )
552
+ .first();
553
+
554
+ if ( newItem && newItem.length ) {
555
+ this._open( newItem.parent() );
556
+
557
+ // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
558
+ this._delay( function() {
559
+ this.focus( event, newItem );
560
+ } );
561
+ }
562
+ },
563
+
564
+ next: function( event ) {
565
+ this._move( "next", "first", event );
566
+ },
567
+
568
+ previous: function( event ) {
569
+ this._move( "prev", "last", event );
570
+ },
571
+
572
+ isFirstItem: function() {
573
+ return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
574
+ },
575
+
576
+ isLastItem: function() {
577
+ return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
578
+ },
579
+
580
+ _move: function( direction, filter, event ) {
581
+ var next;
582
+ if ( this.active ) {
583
+ if ( direction === "first" || direction === "last" ) {
584
+ next = this.active
585
+ [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
586
+ .eq( -1 );
587
+ } else {
588
+ next = this.active
589
+ [ direction + "All" ]( ".ui-menu-item" )
590
+ .eq( 0 );
591
+ }
592
+ }
593
+ if ( !next || !next.length || !this.active ) {
594
+ next = this.activeMenu.find( this.options.items )[ filter ]();
595
+ }
596
+
597
+ this.focus( event, next );
598
+ },
599
+
600
+ nextPage: function( event ) {
601
+ var item, base, height;
602
+
603
+ if ( !this.active ) {
604
+ this.next( event );
605
+ return;
606
+ }
607
+ if ( this.isLastItem() ) {
608
+ return;
609
+ }
610
+ if ( this._hasScroll() ) {
611
+ base = this.active.offset().top;
612
+ height = this.element.height();
613
+ this.active.nextAll( ".ui-menu-item" ).each( function() {
614
+ item = $( this );
615
+ return item.offset().top - base - height < 0;
616
+ } );
617
+
618
+ this.focus( event, item );
619
+ } else {
620
+ this.focus( event, this.activeMenu.find( this.options.items )
621
+ [ !this.active ? "first" : "last" ]() );
622
+ }
623
+ },
624
+
625
+ previousPage: function( event ) {
626
+ var item, base, height;
627
+ if ( !this.active ) {
628
+ this.next( event );
629
+ return;
630
+ }
631
+ if ( this.isFirstItem() ) {
632
+ return;
633
+ }
634
+ if ( this._hasScroll() ) {
635
+ base = this.active.offset().top;
636
+ height = this.element.height();
637
+ this.active.prevAll( ".ui-menu-item" ).each( function() {
638
+ item = $( this );
639
+ return item.offset().top - base + height > 0;
640
+ } );
641
+
642
+ this.focus( event, item );
643
+ } else {
644
+ this.focus( event, this.activeMenu.find( this.options.items ).first() );
645
+ }
646
+ },
647
+
648
+ _hasScroll: function() {
649
+ return this.element.outerHeight() < this.element.prop( "scrollHeight" );
650
+ },
651
+
652
+ select: function( event ) {
653
+
654
+ // TODO: It should never be possible to not have an active item at this
655
+ // point, but the tests don't trigger mouseenter before click.
656
+ this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
657
+ var ui = { item: this.active };
658
+ if ( !this.active.has( ".ui-menu" ).length ) {
659
+ this.collapseAll( event, true );
660
+ }
661
+ this._trigger( "select", event, ui );
662
+ },
663
+
664
+ _filterMenuItems: function( character ) {
665
+ var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
666
+ regex = new RegExp( "^" + escapedCharacter, "i" );
667
+
668
+ return this.activeMenu
669
+ .find( this.options.items )
670
+
671
+ // Only match on items, not dividers or other content (#10571)
672
+ .filter( ".ui-menu-item" )
673
+ .filter( function() {
674
+ return regex.test(
675
+ $.trim( $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
676
+ } );
677
+ }
678
+ } );
679
+
680
+ } ) );