jquery-ui-middleman 4.1.0

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