jquery-ui-rails 2.0.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of jquery-ui-rails might be problematic. Click here for more details.

Files changed (131) hide show
  1. data/History.md +15 -0
  2. data/License.txt +2 -3
  3. data/README.md +17 -19
  4. data/Rakefile +79 -28
  5. data/lib/jquery/ui/rails/version.rb +1 -1
  6. data/vendor/assets/javascripts/jquery.ui.accordion.js +537 -417
  7. data/vendor/assets/javascripts/jquery.ui.all.js +17 -14
  8. data/vendor/assets/javascripts/jquery.ui.autocomplete.js +311 -339
  9. data/vendor/assets/javascripts/jquery.ui.button.js +63 -59
  10. data/vendor/assets/javascripts/jquery.ui.core.js +134 -112
  11. data/vendor/assets/javascripts/jquery.ui.datepicker-ar-DZ.js +2 -2
  12. data/vendor/assets/javascripts/jquery.ui.datepicker-ar.js +3 -3
  13. data/vendor/assets/javascripts/jquery.ui.datepicker-az.js +3 -3
  14. data/vendor/assets/javascripts/jquery.ui.datepicker-bg.js +16 -16
  15. data/vendor/assets/javascripts/jquery.ui.datepicker-bs.js +5 -5
  16. data/vendor/assets/javascripts/jquery.ui.datepicker-ca.js +13 -13
  17. data/vendor/assets/javascripts/jquery.ui.datepicker-cs.js +3 -3
  18. data/vendor/assets/javascripts/jquery.ui.datepicker-cy-GB.js +1 -1
  19. data/vendor/assets/javascripts/jquery.ui.datepicker-da.js +9 -9
  20. data/vendor/assets/javascripts/jquery.ui.datepicker-de.js +2 -2
  21. data/vendor/assets/javascripts/jquery.ui.datepicker-el.js +1 -1
  22. data/vendor/assets/javascripts/jquery.ui.datepicker-eo.js +2 -2
  23. data/vendor/assets/javascripts/jquery.ui.datepicker-es.js +6 -6
  24. data/vendor/assets/javascripts/jquery.ui.datepicker-et.js +1 -1
  25. data/vendor/assets/javascripts/jquery.ui.datepicker-eu.js +3 -3
  26. data/vendor/assets/javascripts/jquery.ui.datepicker-fa.js +3 -3
  27. data/vendor/assets/javascripts/jquery.ui.datepicker-fi.js +5 -5
  28. data/vendor/assets/javascripts/jquery.ui.datepicker-fo.js +3 -3
  29. data/vendor/assets/javascripts/jquery.ui.datepicker-fr-CH.js +3 -3
  30. data/vendor/assets/javascripts/jquery.ui.datepicker-fr.js +2 -2
  31. data/vendor/assets/javascripts/jquery.ui.datepicker-gl.js +6 -6
  32. data/vendor/assets/javascripts/jquery.ui.datepicker-he.js +2 -2
  33. data/vendor/assets/javascripts/jquery.ui.datepicker-hr.js +3 -3
  34. data/vendor/assets/javascripts/jquery.ui.datepicker-hy.js +3 -3
  35. data/vendor/assets/javascripts/jquery.ui.datepicker-id.js +3 -3
  36. data/vendor/assets/javascripts/jquery.ui.datepicker-is.js +11 -11
  37. data/vendor/assets/javascripts/jquery.ui.datepicker-it.js +3 -3
  38. data/vendor/assets/javascripts/jquery.ui.datepicker-ja.js +3 -3
  39. data/vendor/assets/javascripts/jquery.ui.datepicker-kk.js +2 -2
  40. data/vendor/assets/javascripts/jquery.ui.datepicker-ko.js +1 -1
  41. data/vendor/assets/javascripts/jquery.ui.datepicker-lt.js +3 -3
  42. data/vendor/assets/javascripts/jquery.ui.datepicker-lv.js +1 -1
  43. data/vendor/assets/javascripts/jquery.ui.datepicker-ml.js +1 -1
  44. data/vendor/assets/javascripts/jquery.ui.datepicker-ms.js +3 -3
  45. data/vendor/assets/javascripts/jquery.ui.datepicker-nl.js +1 -1
  46. data/vendor/assets/javascripts/jquery.ui.datepicker-no.js +18 -18
  47. data/vendor/assets/javascripts/jquery.ui.datepicker-pl.js +2 -2
  48. data/vendor/assets/javascripts/jquery.ui.datepicker-pt-BR.js +7 -7
  49. data/vendor/assets/javascripts/jquery.ui.datepicker-pt.js +6 -6
  50. data/vendor/assets/javascripts/jquery.ui.datepicker-rm.js +2 -2
  51. data/vendor/assets/javascripts/jquery.ui.datepicker-ro.js +2 -2
  52. data/vendor/assets/javascripts/jquery.ui.datepicker-ru.js +3 -3
  53. data/vendor/assets/javascripts/jquery.ui.datepicker-sk.js +2 -2
  54. data/vendor/assets/javascripts/jquery.ui.datepicker-sl.js +6 -6
  55. data/vendor/assets/javascripts/jquery.ui.datepicker-sq.js +2 -2
  56. data/vendor/assets/javascripts/jquery.ui.datepicker-sr-SR.js +2 -2
  57. data/vendor/assets/javascripts/jquery.ui.datepicker-sr.js +2 -2
  58. data/vendor/assets/javascripts/jquery.ui.datepicker-sv.js +9 -9
  59. data/vendor/assets/javascripts/jquery.ui.datepicker-th.js +3 -3
  60. data/vendor/assets/javascripts/jquery.ui.datepicker-tj.js +1 -1
  61. data/vendor/assets/javascripts/jquery.ui.datepicker-tr.js +2 -2
  62. data/vendor/assets/javascripts/jquery.ui.datepicker-uk.js +3 -3
  63. data/vendor/assets/javascripts/jquery.ui.datepicker-vi.js +2 -2
  64. data/vendor/assets/javascripts/jquery.ui.datepicker-zh-CN.js +2 -2
  65. data/vendor/assets/javascripts/jquery.ui.datepicker-zh-HK.js +2 -2
  66. data/vendor/assets/javascripts/jquery.ui.datepicker-zh-TW.js +2 -2
  67. data/vendor/assets/javascripts/jquery.ui.datepicker.js +51 -59
  68. data/vendor/assets/javascripts/jquery.ui.dialog.js +402 -409
  69. data/vendor/assets/javascripts/jquery.ui.draggable.js +79 -75
  70. data/vendor/assets/javascripts/jquery.ui.droppable.js +10 -17
  71. data/vendor/assets/javascripts/jquery.ui.effect-blind.js +84 -0
  72. data/vendor/assets/javascripts/jquery.ui.effect-bounce.js +115 -0
  73. data/vendor/assets/javascripts/jquery.ui.effect-clip.js +69 -0
  74. data/vendor/assets/javascripts/jquery.ui.effect-drop.js +67 -0
  75. data/vendor/assets/javascripts/jquery.ui.effect-explode.js +99 -0
  76. data/vendor/assets/javascripts/jquery.ui.effect-fade.js +32 -0
  77. data/vendor/assets/javascripts/jquery.ui.effect-fold.js +78 -0
  78. data/vendor/assets/javascripts/jquery.ui.effect-highlight.js +52 -0
  79. data/vendor/assets/javascripts/jquery.ui.effect-pulsate.js +65 -0
  80. data/vendor/assets/javascripts/jquery.ui.effect-scale.js +320 -0
  81. data/vendor/assets/javascripts/jquery.ui.effect-shake.js +76 -0
  82. data/vendor/assets/javascripts/jquery.ui.effect-slide.js +66 -0
  83. data/vendor/assets/javascripts/jquery.ui.effect-transfer.js +49 -0
  84. data/vendor/assets/javascripts/jquery.ui.effect.all.js +14 -0
  85. data/vendor/assets/javascripts/jquery.ui.effect.js +1276 -0
  86. data/vendor/assets/javascripts/jquery.ui.menu.js +614 -0
  87. data/vendor/assets/javascripts/jquery.ui.mouse.js +22 -20
  88. data/vendor/assets/javascripts/jquery.ui.position.js +367 -158
  89. data/vendor/assets/javascripts/jquery.ui.progressbar.js +10 -14
  90. data/vendor/assets/javascripts/jquery.ui.resizable.js +143 -149
  91. data/vendor/assets/javascripts/jquery.ui.selectable.js +22 -28
  92. data/vendor/assets/javascripts/jquery.ui.slider.js +88 -106
  93. data/vendor/assets/javascripts/jquery.ui.sortable.js +97 -95
  94. data/vendor/assets/javascripts/jquery.ui.spinner.js +482 -0
  95. data/vendor/assets/javascripts/jquery.ui.tabs.js +1189 -580
  96. data/vendor/assets/javascripts/jquery.ui.tooltip.js +402 -0
  97. data/vendor/assets/javascripts/jquery.ui.widget.js +373 -117
  98. data/vendor/assets/stylesheets/jquery.ui.accordion.css.erb +10 -13
  99. data/vendor/assets/stylesheets/jquery.ui.all.css.erb +4 -3
  100. data/vendor/assets/stylesheets/jquery.ui.autocomplete.css.erb +10 -44
  101. data/vendor/assets/stylesheets/jquery.ui.base.css.erb +7 -3
  102. data/vendor/assets/stylesheets/jquery.ui.button.css.erb +6 -4
  103. data/vendor/assets/stylesheets/jquery.ui.core.css.erb +5 -4
  104. data/vendor/assets/stylesheets/jquery.ui.datepicker.css.erb +4 -3
  105. data/vendor/assets/stylesheets/jquery.ui.dialog.css.erb +6 -5
  106. data/vendor/assets/stylesheets/jquery.ui.menu.css.erb +34 -0
  107. data/vendor/assets/stylesheets/jquery.ui.progressbar.css.erb +4 -3
  108. data/vendor/assets/stylesheets/jquery.ui.resizable.css.erb +4 -3
  109. data/vendor/assets/stylesheets/jquery.ui.selectable.css.erb +4 -3
  110. data/vendor/assets/stylesheets/jquery.ui.slider.css.erb +4 -3
  111. data/vendor/assets/stylesheets/jquery.ui.spinner.css.erb +27 -0
  112. data/vendor/assets/stylesheets/jquery.ui.tabs.css.erb +8 -8
  113. data/vendor/assets/stylesheets/jquery.ui.theme.css.erb +8 -7
  114. data/vendor/assets/stylesheets/jquery.ui.tooltip.css.erb +25 -0
  115. metadata +24 -19
  116. data/dependencies.js +0 -31
  117. data/vendor/assets/javascripts/jquery.effects.all.js +0 -14
  118. data/vendor/assets/javascripts/jquery.effects.blind.js +0 -51
  119. data/vendor/assets/javascripts/jquery.effects.bounce.js +0 -80
  120. data/vendor/assets/javascripts/jquery.effects.clip.js +0 -56
  121. data/vendor/assets/javascripts/jquery.effects.core.js +0 -612
  122. data/vendor/assets/javascripts/jquery.effects.drop.js +0 -52
  123. data/vendor/assets/javascripts/jquery.effects.explode.js +0 -81
  124. data/vendor/assets/javascripts/jquery.effects.fade.js +0 -34
  125. data/vendor/assets/javascripts/jquery.effects.fold.js +0 -58
  126. data/vendor/assets/javascripts/jquery.effects.highlight.js +0 -52
  127. data/vendor/assets/javascripts/jquery.effects.pulsate.js +0 -53
  128. data/vendor/assets/javascripts/jquery.effects.scale.js +0 -180
  129. data/vendor/assets/javascripts/jquery.effects.shake.js +0 -59
  130. data/vendor/assets/javascripts/jquery.effects.slide.js +0 -52
  131. data/vendor/assets/javascripts/jquery.effects.transfer.js +0 -47
@@ -1,17 +1,3 @@
1
- //= require jquery.effects.blind
2
- //= require jquery.effects.bounce
3
- //= require jquery.effects.clip
4
- //= require jquery.effects.core
5
- //= require jquery.effects.drop
6
- //= require jquery.effects.explode
7
- //= require jquery.effects.fade
8
- //= require jquery.effects.fold
9
- //= require jquery.effects.highlight
10
- //= require jquery.effects.pulsate
11
- //= require jquery.effects.scale
12
- //= require jquery.effects.shake
13
- //= require jquery.effects.slide
14
- //= require jquery.effects.transfer
15
1
  //= require jquery.ui.accordion
16
2
  //= require jquery.ui.autocomplete
17
3
  //= require jquery.ui.button
@@ -20,6 +6,21 @@
20
6
  //= require jquery.ui.dialog
21
7
  //= require jquery.ui.draggable
22
8
  //= require jquery.ui.droppable
9
+ //= require jquery.ui.effect-blind
10
+ //= require jquery.ui.effect-bounce
11
+ //= require jquery.ui.effect-clip
12
+ //= require jquery.ui.effect-drop
13
+ //= require jquery.ui.effect-explode
14
+ //= require jquery.ui.effect-fade
15
+ //= require jquery.ui.effect-fold
16
+ //= require jquery.ui.effect-highlight
17
+ //= require jquery.ui.effect-pulsate
18
+ //= require jquery.ui.effect-scale
19
+ //= require jquery.ui.effect-shake
20
+ //= require jquery.ui.effect-slide
21
+ //= require jquery.ui.effect-transfer
22
+ //= require jquery.ui.effect
23
+ //= require jquery.ui.menu
23
24
  //= require jquery.ui.mouse
24
25
  //= require jquery.ui.position
25
26
  //= require jquery.ui.progressbar
@@ -27,5 +28,7 @@
27
28
  //= require jquery.ui.selectable
28
29
  //= require jquery.ui.slider
29
30
  //= require jquery.ui.sortable
31
+ //= require jquery.ui.spinner
30
32
  //= require jquery.ui.tabs
33
+ //= require jquery.ui.tooltip
31
34
  //= require jquery.ui.widget
@@ -1,20 +1,23 @@
1
1
  //= require jquery.ui.core
2
2
  //= require jquery.ui.widget
3
+ //= require jquery.ui.menu
3
4
  //= require jquery.ui.position
4
5
 
5
6
  /*!
6
- * jQuery UI Autocomplete 1.8.24
7
+ * jQuery UI Autocomplete 1.9.2
8
+ * http://jqueryui.com
7
9
  *
8
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
9
- * Dual licensed under the MIT or GPL Version 2 licenses.
10
+ * Copyright 2012 jQuery Foundation and other contributors
11
+ * Released under the MIT license.
10
12
  * http://jquery.org/license
11
13
  *
12
- * http://docs.jquery.com/UI/Autocomplete
14
+ * http://api.jqueryui.com/autocomplete/
13
15
  *
14
16
  * Depends:
15
17
  * jquery.ui.core.js
16
18
  * jquery.ui.widget.js
17
19
  * jquery.ui.position.js
20
+ * jquery.ui.menu.js
18
21
  */
19
22
  (function( $, undefined ) {
20
23
 
@@ -22,6 +25,8 @@
22
25
  var requestIndex = 0;
23
26
 
24
27
  $.widget( "ui.autocomplete", {
28
+ version: "1.9.2",
29
+ defaultElement: "<input>",
25
30
  options: {
26
31
  appendTo: "body",
27
32
  autoFocus: false,
@@ -32,241 +37,335 @@ $.widget( "ui.autocomplete", {
32
37
  at: "left bottom",
33
38
  collision: "none"
34
39
  },
35
- source: null
40
+ source: null,
41
+
42
+ // callbacks
43
+ change: null,
44
+ close: null,
45
+ focus: null,
46
+ open: null,
47
+ response: null,
48
+ search: null,
49
+ select: null
36
50
  },
37
51
 
38
52
  pending: 0,
39
53
 
40
54
  _create: function() {
41
- var self = this,
42
- doc = this.element[ 0 ].ownerDocument,
43
- suppressKeyPress;
44
- this.isMultiLine = this.element.is( "textarea" );
55
+ // Some browsers only repeat keydown events, not keypress events,
56
+ // so we use the suppressKeyPress flag to determine if we've already
57
+ // handled the keydown event. #7269
58
+ // Unfortunately the code for & in keypress is the same as the up arrow,
59
+ // so we use the suppressKeyPressRepeat flag to avoid handling keypress
60
+ // events when we know the keydown event was used to modify the
61
+ // search term. #7799
62
+ var suppressKeyPress, suppressKeyPressRepeat, suppressInput;
63
+
64
+ this.isMultiLine = this._isMultiLine();
65
+ this.valueMethod = this.element[ this.element.is( "input,textarea" ) ? "val" : "text" ];
66
+ this.isNewMenu = true;
45
67
 
46
68
  this.element
47
69
  .addClass( "ui-autocomplete-input" )
48
- .attr( "autocomplete", "off" )
49
- // TODO verify these actually work as intended
50
- .attr({
51
- role: "textbox",
52
- "aria-autocomplete": "list",
53
- "aria-haspopup": "true"
54
- })
55
- .bind( "keydown.autocomplete", function( event ) {
56
- if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) {
70
+ .attr( "autocomplete", "off" );
71
+
72
+ this._on( this.element, {
73
+ keydown: function( event ) {
74
+ if ( this.element.prop( "readOnly" ) ) {
75
+ suppressKeyPress = true;
76
+ suppressInput = true;
77
+ suppressKeyPressRepeat = true;
57
78
  return;
58
79
  }
59
80
 
60
81
  suppressKeyPress = false;
82
+ suppressInput = false;
83
+ suppressKeyPressRepeat = false;
61
84
  var keyCode = $.ui.keyCode;
62
85
  switch( event.keyCode ) {
63
86
  case keyCode.PAGE_UP:
64
- self._move( "previousPage", event );
87
+ suppressKeyPress = true;
88
+ this._move( "previousPage", event );
65
89
  break;
66
90
  case keyCode.PAGE_DOWN:
67
- self._move( "nextPage", event );
91
+ suppressKeyPress = true;
92
+ this._move( "nextPage", event );
68
93
  break;
69
94
  case keyCode.UP:
70
- self._keyEvent( "previous", event );
95
+ suppressKeyPress = true;
96
+ this._keyEvent( "previous", event );
71
97
  break;
72
98
  case keyCode.DOWN:
73
- self._keyEvent( "next", event );
99
+ suppressKeyPress = true;
100
+ this._keyEvent( "next", event );
74
101
  break;
75
102
  case keyCode.ENTER:
76
103
  case keyCode.NUMPAD_ENTER:
77
104
  // when menu is open and has focus
78
- if ( self.menu.active ) {
105
+ if ( this.menu.active ) {
79
106
  // #6055 - Opera still allows the keypress to occur
80
107
  // which causes forms to submit
81
108
  suppressKeyPress = true;
82
109
  event.preventDefault();
110
+ this.menu.select( event );
83
111
  }
84
- //passthrough - ENTER and TAB both select the current element
112
+ break;
85
113
  case keyCode.TAB:
86
- if ( !self.menu.active ) {
87
- return;
114
+ if ( this.menu.active ) {
115
+ this.menu.select( event );
88
116
  }
89
- self.menu.select( event );
90
117
  break;
91
118
  case keyCode.ESCAPE:
92
- self.element.val( self.term );
93
- self.close( event );
119
+ if ( this.menu.element.is( ":visible" ) ) {
120
+ this._value( this.term );
121
+ this.close( event );
122
+ // Different browsers have different default behavior for escape
123
+ // Single press can mean undo or clear
124
+ // Double press in IE means clear the whole form
125
+ event.preventDefault();
126
+ }
94
127
  break;
95
128
  default:
96
- // keypress is triggered before the input value is changed
97
- clearTimeout( self.searching );
98
- self.searching = setTimeout(function() {
99
- // only search if the value has changed
100
- if ( self.term != self.element.val() ) {
101
- self.selectedItem = null;
102
- self.search( null, event );
103
- }
104
- }, self.options.delay );
129
+ suppressKeyPressRepeat = true;
130
+ // search timeout should be triggered before the input value is changed
131
+ this._searchTimeout( event );
105
132
  break;
106
133
  }
107
- })
108
- .bind( "keypress.autocomplete", function( event ) {
134
+ },
135
+ keypress: function( event ) {
109
136
  if ( suppressKeyPress ) {
110
137
  suppressKeyPress = false;
111
138
  event.preventDefault();
139
+ return;
112
140
  }
113
- })
114
- .bind( "focus.autocomplete", function() {
115
- if ( self.options.disabled ) {
141
+ if ( suppressKeyPressRepeat ) {
116
142
  return;
117
143
  }
118
144
 
119
- self.selectedItem = null;
120
- self.previous = self.element.val();
121
- })
122
- .bind( "blur.autocomplete", function( event ) {
123
- if ( self.options.disabled ) {
145
+ // replicate some key handlers to allow them to repeat in Firefox and Opera
146
+ var keyCode = $.ui.keyCode;
147
+ switch( event.keyCode ) {
148
+ case keyCode.PAGE_UP:
149
+ this._move( "previousPage", event );
150
+ break;
151
+ case keyCode.PAGE_DOWN:
152
+ this._move( "nextPage", event );
153
+ break;
154
+ case keyCode.UP:
155
+ this._keyEvent( "previous", event );
156
+ break;
157
+ case keyCode.DOWN:
158
+ this._keyEvent( "next", event );
159
+ break;
160
+ }
161
+ },
162
+ input: function( event ) {
163
+ if ( suppressInput ) {
164
+ suppressInput = false;
165
+ event.preventDefault();
124
166
  return;
125
167
  }
168
+ this._searchTimeout( event );
169
+ },
170
+ focus: function() {
171
+ this.selectedItem = null;
172
+ this.previous = this._value();
173
+ },
174
+ blur: function( event ) {
175
+ if ( this.cancelBlur ) {
176
+ delete this.cancelBlur;
177
+ return;
178
+ }
179
+
180
+ clearTimeout( this.searching );
181
+ this.close( event );
182
+ this._change( event );
183
+ }
184
+ });
126
185
 
127
- clearTimeout( self.searching );
128
- // clicks on the menu (or a button to trigger a search) will cause a blur event
129
- self.closing = setTimeout(function() {
130
- self.close( event );
131
- self._change( event );
132
- }, 150 );
133
- });
134
186
  this._initSource();
135
- this.menu = $( "<ul></ul>" )
187
+ this.menu = $( "<ul>" )
136
188
  .addClass( "ui-autocomplete" )
137
- .appendTo( $( this.options.appendTo || "body", doc )[0] )
138
- // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
139
- .mousedown(function( event ) {
189
+ .appendTo( this.document.find( this.options.appendTo || "body" )[ 0 ] )
190
+ .menu({
191
+ // custom key handling for now
192
+ input: $(),
193
+ // disable ARIA support, the live region takes care of that
194
+ role: null
195
+ })
196
+ .zIndex( this.element.zIndex() + 1 )
197
+ .hide()
198
+ .data( "menu" );
199
+
200
+ this._on( this.menu.element, {
201
+ mousedown: function( event ) {
202
+ // prevent moving focus out of the text field
203
+ event.preventDefault();
204
+
205
+ // IE doesn't prevent moving focus even with event.preventDefault()
206
+ // so we set a flag to know when we should ignore the blur event
207
+ this.cancelBlur = true;
208
+ this._delay(function() {
209
+ delete this.cancelBlur;
210
+ });
211
+
140
212
  // clicking on the scrollbar causes focus to shift to the body
141
213
  // but we can't detect a mouseup or a click immediately afterward
142
214
  // so we have to track the next mousedown and close the menu if
143
215
  // the user clicks somewhere outside of the autocomplete
144
- var menuElement = self.menu.element[ 0 ];
216
+ var menuElement = this.menu.element[ 0 ];
145
217
  if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
146
- setTimeout(function() {
147
- $( document ).one( 'mousedown', function( event ) {
148
- if ( event.target !== self.element[ 0 ] &&
149
- event.target !== menuElement &&
150
- !$.ui.contains( menuElement, event.target ) ) {
151
- self.close();
218
+ this._delay(function() {
219
+ var that = this;
220
+ this.document.one( "mousedown", function( event ) {
221
+ if ( event.target !== that.element[ 0 ] &&
222
+ event.target !== menuElement &&
223
+ !$.contains( menuElement, event.target ) ) {
224
+ that.close();
152
225
  }
153
226
  });
154
- }, 1 );
227
+ });
155
228
  }
229
+ },
230
+ menufocus: function( event, ui ) {
231
+ // #7024 - Prevent accidental activation of menu items in Firefox
232
+ if ( this.isNewMenu ) {
233
+ this.isNewMenu = false;
234
+ if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
235
+ this.menu.blur();
236
+
237
+ this.document.one( "mousemove", function() {
238
+ $( event.target ).trigger( event.originalEvent );
239
+ });
156
240
 
157
- // use another timeout to make sure the blur-event-handler on the input was already triggered
158
- setTimeout(function() {
159
- clearTimeout( self.closing );
160
- }, 13);
161
- })
162
- .menu({
163
- focus: function( event, ui ) {
164
- var item = ui.item.data( "item.autocomplete" );
165
- if ( false !== self._trigger( "focus", event, { item: item } ) ) {
166
- // use value to match what will end up in the input, if it was a key event
167
- if ( /^key/.test(event.originalEvent.type) ) {
168
- self.element.val( item.value );
169
- }
170
- }
171
- },
172
- selected: function( event, ui ) {
173
- var item = ui.item.data( "item.autocomplete" ),
174
- previous = self.previous;
175
-
176
- // only trigger when focus was lost (click on menu)
177
- if ( self.element[0] !== doc.activeElement ) {
178
- self.element.focus();
179
- self.previous = previous;
180
- // #6109 - IE triggers two focus events and the second
181
- // is asynchronous, so we need to reset the previous
182
- // term synchronously and asynchronously :-(
183
- setTimeout(function() {
184
- self.previous = previous;
185
- self.selectedItem = item;
186
- }, 1);
241
+ return;
187
242
  }
243
+ }
188
244
 
189
- if ( false !== self._trigger( "select", event, { item: item } ) ) {
190
- self.element.val( item.value );
191
- }
192
- // reset the term after the select event
193
- // this allows custom select handling to work properly
194
- self.term = self.element.val();
195
-
196
- self.close( event );
197
- self.selectedItem = item;
198
- },
199
- blur: function( event, ui ) {
200
- // don't set the value of the text field if it's already correct
201
- // this prevents moving the cursor unnecessarily
202
- if ( self.menu.element.is(":visible") &&
203
- ( self.element.val() !== self.term ) ) {
204
- self.element.val( self.term );
245
+ // back compat for _renderItem using item.autocomplete, via #7810
246
+ // TODO remove the fallback, see #8156
247
+ var item = ui.item.data( "ui-autocomplete-item" ) || ui.item.data( "item.autocomplete" );
248
+ if ( false !== this._trigger( "focus", event, { item: item } ) ) {
249
+ // use value to match what will end up in the input, if it was a key event
250
+ if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
251
+ this._value( item.value );
205
252
  }
253
+ } else {
254
+ // Normally the input is populated with the item's value as the
255
+ // menu is navigated, causing screen readers to notice a change and
256
+ // announce the item. Since the focus event was canceled, this doesn't
257
+ // happen, so we update the live region so that screen readers can
258
+ // still notice the change and announce it.
259
+ this.liveRegion.text( item.value );
260
+ }
261
+ },
262
+ menuselect: function( event, ui ) {
263
+ // back compat for _renderItem using item.autocomplete, via #7810
264
+ // TODO remove the fallback, see #8156
265
+ var item = ui.item.data( "ui-autocomplete-item" ) || ui.item.data( "item.autocomplete" ),
266
+ previous = this.previous;
267
+
268
+ // only trigger when focus was lost (click on menu)
269
+ if ( this.element[0] !== this.document[0].activeElement ) {
270
+ this.element.focus();
271
+ this.previous = previous;
272
+ // #6109 - IE triggers two focus events and the second
273
+ // is asynchronous, so we need to reset the previous
274
+ // term synchronously and asynchronously :-(
275
+ this._delay(function() {
276
+ this.previous = previous;
277
+ this.selectedItem = item;
278
+ });
279
+ }
280
+
281
+ if ( false !== this._trigger( "select", event, { item: item } ) ) {
282
+ this._value( item.value );
206
283
  }
284
+ // reset the term after the select event
285
+ // this allows custom select handling to work properly
286
+ this.term = this._value();
287
+
288
+ this.close( event );
289
+ this.selectedItem = item;
290
+ }
291
+ });
292
+
293
+ this.liveRegion = $( "<span>", {
294
+ role: "status",
295
+ "aria-live": "polite"
207
296
  })
208
- .zIndex( this.element.zIndex() + 1 )
209
- // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
210
- .css({ top: 0, left: 0 })
211
- .hide()
212
- .data( "menu" );
297
+ .addClass( "ui-helper-hidden-accessible" )
298
+ .insertAfter( this.element );
299
+
213
300
  if ( $.fn.bgiframe ) {
214
- this.menu.element.bgiframe();
301
+ this.menu.element.bgiframe();
215
302
  }
303
+
216
304
  // turning off autocomplete prevents the browser from remembering the
217
305
  // value when navigating through history, so we re-enable autocomplete
218
306
  // if the page is unloaded before the widget is destroyed. #7790
219
- self.beforeunloadHandler = function() {
220
- self.element.removeAttr( "autocomplete" );
221
- };
222
- $( window ).bind( "beforeunload", self.beforeunloadHandler );
307
+ this._on( this.window, {
308
+ beforeunload: function() {
309
+ this.element.removeAttr( "autocomplete" );
310
+ }
311
+ });
223
312
  },
224
313
 
225
- destroy: function() {
314
+ _destroy: function() {
315
+ clearTimeout( this.searching );
226
316
  this.element
227
317
  .removeClass( "ui-autocomplete-input" )
228
- .removeAttr( "autocomplete" )
229
- .removeAttr( "role" )
230
- .removeAttr( "aria-autocomplete" )
231
- .removeAttr( "aria-haspopup" );
318
+ .removeAttr( "autocomplete" );
232
319
  this.menu.element.remove();
233
- $( window ).unbind( "beforeunload", this.beforeunloadHandler );
234
- $.Widget.prototype.destroy.call( this );
320
+ this.liveRegion.remove();
235
321
  },
236
322
 
237
323
  _setOption: function( key, value ) {
238
- $.Widget.prototype._setOption.apply( this, arguments );
324
+ this._super( key, value );
239
325
  if ( key === "source" ) {
240
326
  this._initSource();
241
327
  }
242
328
  if ( key === "appendTo" ) {
243
- this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
329
+ this.menu.element.appendTo( this.document.find( value || "body" )[0] );
244
330
  }
245
331
  if ( key === "disabled" && value && this.xhr ) {
246
332
  this.xhr.abort();
247
333
  }
248
334
  },
249
335
 
336
+ _isMultiLine: function() {
337
+ // Textareas are always multi-line
338
+ if ( this.element.is( "textarea" ) ) {
339
+ return true;
340
+ }
341
+ // Inputs are always single-line, even if inside a contentEditable element
342
+ // IE also treats inputs as contentEditable
343
+ if ( this.element.is( "input" ) ) {
344
+ return false;
345
+ }
346
+ // All other element types are determined by whether or not they're contentEditable
347
+ return this.element.prop( "isContentEditable" );
348
+ },
349
+
250
350
  _initSource: function() {
251
- var self = this,
252
- array,
253
- url;
351
+ var array, url,
352
+ that = this;
254
353
  if ( $.isArray(this.options.source) ) {
255
354
  array = this.options.source;
256
355
  this.source = function( request, response ) {
257
- response( $.ui.autocomplete.filter(array, request.term) );
356
+ response( $.ui.autocomplete.filter( array, request.term ) );
258
357
  };
259
358
  } else if ( typeof this.options.source === "string" ) {
260
359
  url = this.options.source;
261
360
  this.source = function( request, response ) {
262
- if ( self.xhr ) {
263
- self.xhr.abort();
361
+ if ( that.xhr ) {
362
+ that.xhr.abort();
264
363
  }
265
- self.xhr = $.ajax({
364
+ that.xhr = $.ajax({
266
365
  url: url,
267
366
  data: request,
268
367
  dataType: "json",
269
- success: function( data, status ) {
368
+ success: function( data ) {
270
369
  response( data );
271
370
  },
272
371
  error: function() {
@@ -279,17 +378,27 @@ $.widget( "ui.autocomplete", {
279
378
  }
280
379
  },
281
380
 
381
+ _searchTimeout: function( event ) {
382
+ clearTimeout( this.searching );
383
+ this.searching = this._delay(function() {
384
+ // only search if the value has changed
385
+ if ( this.term !== this._value() ) {
386
+ this.selectedItem = null;
387
+ this.search( null, event );
388
+ }
389
+ }, this.options.delay );
390
+ },
391
+
282
392
  search: function( value, event ) {
283
- value = value != null ? value : this.element.val();
393
+ value = value != null ? value : this._value();
284
394
 
285
395
  // always save the actual value, not the one passed as an argument
286
- this.term = this.element.val();
396
+ this.term = this._value();
287
397
 
288
398
  if ( value.length < this.options.minLength ) {
289
399
  return this.close( event );
290
400
  }
291
401
 
292
- clearTimeout( this.closing );
293
402
  if ( this._trigger( "search", event ) === false ) {
294
403
  return;
295
404
  }
@@ -300,6 +409,7 @@ $.widget( "ui.autocomplete", {
300
409
  _search: function( value ) {
301
410
  this.pending++;
302
411
  this.element.addClass( "ui-autocomplete-loading" );
412
+ this.cancelSearch = false;
303
413
 
304
414
  this.source( { term: value }, this._response() );
305
415
  },
@@ -321,26 +431,35 @@ $.widget( "ui.autocomplete", {
321
431
  },
322
432
 
323
433
  __response: function( content ) {
324
- if ( !this.options.disabled && content && content.length ) {
434
+ if ( content ) {
325
435
  content = this._normalize( content );
436
+ }
437
+ this._trigger( "response", null, { content: content } );
438
+ if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
326
439
  this._suggest( content );
327
440
  this._trigger( "open" );
328
441
  } else {
329
- this.close();
442
+ // use ._close() instead of .close() so we don't cancel future searches
443
+ this._close();
330
444
  }
331
445
  },
332
446
 
333
447
  close: function( event ) {
334
- clearTimeout( this.closing );
335
- if ( this.menu.element.is(":visible") ) {
448
+ this.cancelSearch = true;
449
+ this._close( event );
450
+ },
451
+
452
+ _close: function( event ) {
453
+ if ( this.menu.element.is( ":visible" ) ) {
336
454
  this.menu.element.hide();
337
- this.menu.deactivate();
455
+ this.menu.blur();
456
+ this.isNewMenu = true;
338
457
  this._trigger( "close", event );
339
458
  }
340
459
  },
341
-
460
+
342
461
  _change: function( event ) {
343
- if ( this.previous !== this.element.val() ) {
462
+ if ( this.previous !== this._value() ) {
344
463
  this._trigger( "change", event, { item: this.selectedItem } );
345
464
  }
346
465
  },
@@ -350,7 +469,7 @@ $.widget( "ui.autocomplete", {
350
469
  if ( items.length && items[0].label && items[0].value ) {
351
470
  return items;
352
471
  }
353
- return $.map( items, function(item) {
472
+ return $.map( items, function( item ) {
354
473
  if ( typeof item === "string" ) {
355
474
  return {
356
475
  label: item,
@@ -369,8 +488,6 @@ $.widget( "ui.autocomplete", {
369
488
  .empty()
370
489
  .zIndex( this.element.zIndex() + 1 );
371
490
  this._renderMenu( ul, items );
372
- // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
373
- this.menu.deactivate();
374
491
  this.menu.refresh();
375
492
 
376
493
  // size and position menu
@@ -381,7 +498,7 @@ $.widget( "ui.autocomplete", {
381
498
  }, this.options.position ));
382
499
 
383
500
  if ( this.options.autoFocus ) {
384
- this.menu.next( new $.Event("mouseover") );
501
+ this.menu.next();
385
502
  }
386
503
  },
387
504
 
@@ -396,28 +513,31 @@ $.widget( "ui.autocomplete", {
396
513
  },
397
514
 
398
515
  _renderMenu: function( ul, items ) {
399
- var self = this;
516
+ var that = this;
400
517
  $.each( items, function( index, item ) {
401
- self._renderItem( ul, item );
518
+ that._renderItemData( ul, item );
402
519
  });
403
520
  },
404
521
 
405
- _renderItem: function( ul, item) {
406
- return $( "<li></li>" )
407
- .data( "item.autocomplete", item )
408
- .append( $( "<a></a>" ).text( item.label ) )
522
+ _renderItemData: function( ul, item ) {
523
+ return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
524
+ },
525
+
526
+ _renderItem: function( ul, item ) {
527
+ return $( "<li>" )
528
+ .append( $( "<a>" ).text( item.label ) )
409
529
  .appendTo( ul );
410
530
  },
411
531
 
412
532
  _move: function( direction, event ) {
413
- if ( !this.menu.element.is(":visible") ) {
533
+ if ( !this.menu.element.is( ":visible" ) ) {
414
534
  this.search( null, event );
415
535
  return;
416
536
  }
417
- if ( this.menu.first() && /^previous/.test(direction) ||
418
- this.menu.last() && /^next/.test(direction) ) {
419
- this.element.val( this.term );
420
- this.menu.deactivate();
537
+ if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
538
+ this.menu.isLastItem() && /^next/.test( direction ) ) {
539
+ this._value( this.term );
540
+ this.menu.blur();
421
541
  return;
422
542
  }
423
543
  this.menu[ direction ]( event );
@@ -426,6 +546,11 @@ $.widget( "ui.autocomplete", {
426
546
  widget: function() {
427
547
  return this.menu.element;
428
548
  },
549
+
550
+ _value: function() {
551
+ return this.valueMethod.apply( this.element, arguments );
552
+ },
553
+
429
554
  _keyEvent: function( keyEvent, event ) {
430
555
  if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
431
556
  this._move( keyEvent, event );
@@ -438,7 +563,7 @@ $.widget( "ui.autocomplete", {
438
563
 
439
564
  $.extend( $.ui.autocomplete, {
440
565
  escapeRegex: function( value ) {
441
- return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
566
+ return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
442
567
  },
443
568
  filter: function(array, term) {
444
569
  var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
@@ -448,188 +573,35 @@ $.extend( $.ui.autocomplete, {
448
573
  }
449
574
  });
450
575
 
451
- }( jQuery ));
452
-
453
- /*
454
- * jQuery UI Menu (not officially released)
455
- *
456
- * This widget isn't yet finished and the API is subject to change. We plan to finish
457
- * it for the next release. You're welcome to give it a try anyway and give us feedback,
458
- * as long as you're okay with migrating your code later on. We can help with that, too.
459
- *
460
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
461
- * Dual licensed under the MIT or GPL Version 2 licenses.
462
- * http://jquery.org/license
463
- *
464
- * http://docs.jquery.com/UI/Menu
465
- *
466
- * Depends:
467
- * jquery.ui.core.js
468
- * jquery.ui.widget.js
469
- */
470
- (function($) {
471
-
472
- $.widget("ui.menu", {
473
- _create: function() {
474
- var self = this;
475
- this.element
476
- .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
477
- .attr({
478
- role: "listbox",
479
- "aria-activedescendant": "ui-active-menuitem"
480
- })
481
- .click(function( event ) {
482
- if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
483
- return;
484
- }
485
- // temporary
486
- event.preventDefault();
487
- self.select( event );
488
- });
489
- this.refresh();
490
- },
491
-
492
- refresh: function() {
493
- var self = this;
494
-
495
- // don't refresh list items that are already adapted
496
- var items = this.element.children("li:not(.ui-menu-item):has(a)")
497
- .addClass("ui-menu-item")
498
- .attr("role", "menuitem");
499
-
500
- items.children("a")
501
- .addClass("ui-corner-all")
502
- .attr("tabindex", -1)
503
- // mouseenter doesn't work with event delegation
504
- .mouseenter(function( event ) {
505
- self.activate( event, $(this).parent() );
506
- })
507
- .mouseleave(function() {
508
- self.deactivate();
509
- });
510
- },
511
576
 
512
- activate: function( event, item ) {
513
- this.deactivate();
514
- if (this.hasScroll()) {
515
- var offset = item.offset().top - this.element.offset().top,
516
- scroll = this.element.scrollTop(),
517
- elementHeight = this.element.height();
518
- if (offset < 0) {
519
- this.element.scrollTop( scroll + offset);
520
- } else if (offset >= elementHeight) {
521
- this.element.scrollTop( scroll + offset - elementHeight + item.height());
577
+ // live region extension, adding a `messages` option
578
+ // NOTE: This is an experimental API. We are still investigating
579
+ // a full solution for string manipulation and internationalization.
580
+ $.widget( "ui.autocomplete", $.ui.autocomplete, {
581
+ options: {
582
+ messages: {
583
+ noResults: "No search results.",
584
+ results: function( amount ) {
585
+ return amount + ( amount > 1 ? " results are" : " result is" ) +
586
+ " available, use up and down arrow keys to navigate.";
522
587
  }
523
588
  }
524
- this.active = item.eq(0)
525
- .children("a")
526
- .addClass("ui-state-hover")
527
- .attr("id", "ui-active-menuitem")
528
- .end();
529
- this._trigger("focus", event, { item: item });
530
- },
531
-
532
- deactivate: function() {
533
- if (!this.active) { return; }
534
-
535
- this.active.children("a")
536
- .removeClass("ui-state-hover")
537
- .removeAttr("id");
538
- this._trigger("blur");
539
- this.active = null;
540
589
  },
541
590
 
542
- next: function(event) {
543
- this.move("next", ".ui-menu-item:first", event);
544
- },
545
-
546
- previous: function(event) {
547
- this.move("prev", ".ui-menu-item:last", event);
548
- },
549
-
550
- first: function() {
551
- return this.active && !this.active.prevAll(".ui-menu-item").length;
552
- },
553
-
554
- last: function() {
555
- return this.active && !this.active.nextAll(".ui-menu-item").length;
556
- },
557
-
558
- move: function(direction, edge, event) {
559
- if (!this.active) {
560
- this.activate(event, this.element.children(edge));
591
+ __response: function( content ) {
592
+ var message;
593
+ this._superApply( arguments );
594
+ if ( this.options.disabled || this.cancelSearch ) {
561
595
  return;
562
596
  }
563
- var next = this.active[direction + "All"](".ui-menu-item").eq(0);
564
- if (next.length) {
565
- this.activate(event, next);
566
- } else {
567
- this.activate(event, this.element.children(edge));
568
- }
569
- },
570
-
571
- // TODO merge with previousPage
572
- nextPage: function(event) {
573
- if (this.hasScroll()) {
574
- // TODO merge with no-scroll-else
575
- if (!this.active || this.last()) {
576
- this.activate(event, this.element.children(".ui-menu-item:first"));
577
- return;
578
- }
579
- var base = this.active.offset().top,
580
- height = this.element.height(),
581
- result = this.element.children(".ui-menu-item").filter(function() {
582
- var close = $(this).offset().top - base - height + $(this).height();
583
- // TODO improve approximation
584
- return close < 10 && close > -10;
585
- });
586
-
587
- // TODO try to catch this earlier when scrollTop indicates the last page anyway
588
- if (!result.length) {
589
- result = this.element.children(".ui-menu-item:last");
590
- }
591
- this.activate(event, result);
592
- } else {
593
- this.activate(event, this.element.children(".ui-menu-item")
594
- .filter(!this.active || this.last() ? ":first" : ":last"));
595
- }
596
- },
597
-
598
- // TODO merge with nextPage
599
- previousPage: function(event) {
600
- if (this.hasScroll()) {
601
- // TODO merge with no-scroll-else
602
- if (!this.active || this.first()) {
603
- this.activate(event, this.element.children(".ui-menu-item:last"));
604
- return;
605
- }
606
-
607
- var base = this.active.offset().top,
608
- height = this.element.height(),
609
- result = this.element.children(".ui-menu-item").filter(function() {
610
- var close = $(this).offset().top - base + height - $(this).height();
611
- // TODO improve approximation
612
- return close < 10 && close > -10;
613
- });
614
-
615
- // TODO try to catch this earlier when scrollTop indicates the last page anyway
616
- if (!result.length) {
617
- result = this.element.children(".ui-menu-item:first");
618
- }
619
- this.activate(event, result);
597
+ if ( content && content.length ) {
598
+ message = this.options.messages.results( content.length );
620
599
  } else {
621
- this.activate(event, this.element.children(".ui-menu-item")
622
- .filter(!this.active || this.first() ? ":last" : ":first"));
600
+ message = this.options.messages.noResults;
623
601
  }
624
- },
625
-
626
- hasScroll: function() {
627
- return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight");
628
- },
629
-
630
- select: function( event ) {
631
- this._trigger("selected", event, { item: this.active });
602
+ this.liveRegion.text( message );
632
603
  }
633
604
  });
634
605
 
635
- }(jQuery));
606
+
607
+ }( jQuery ));