98 suppressKeyPress = false; |
102 suppressKeyPress = false; |
99 suppressInput = false; |
103 suppressInput = false; |
100 suppressKeyPressRepeat = false; |
104 suppressKeyPressRepeat = false; |
101 var keyCode = $.ui.keyCode; |
105 var keyCode = $.ui.keyCode; |
102 switch ( event.keyCode ) { |
106 switch ( event.keyCode ) { |
103 case keyCode.PAGE_UP: |
107 case keyCode.PAGE_UP: |
104 suppressKeyPress = true; |
|
105 this._move( "previousPage", event ); |
|
106 break; |
|
107 case keyCode.PAGE_DOWN: |
|
108 suppressKeyPress = true; |
|
109 this._move( "nextPage", event ); |
|
110 break; |
|
111 case keyCode.UP: |
|
112 suppressKeyPress = true; |
|
113 this._keyEvent( "previous", event ); |
|
114 break; |
|
115 case keyCode.DOWN: |
|
116 suppressKeyPress = true; |
|
117 this._keyEvent( "next", event ); |
|
118 break; |
|
119 case keyCode.ENTER: |
|
120 |
|
121 // when menu is open and has focus |
|
122 if ( this.menu.active ) { |
|
123 |
|
124 // #6055 - Opera still allows the keypress to occur |
|
125 // which causes forms to submit |
|
126 suppressKeyPress = true; |
108 suppressKeyPress = true; |
127 event.preventDefault(); |
109 this._move( "previousPage", event ); |
128 this.menu.select( event ); |
110 break; |
129 } |
111 case keyCode.PAGE_DOWN: |
130 break; |
112 suppressKeyPress = true; |
131 case keyCode.TAB: |
113 this._move( "nextPage", event ); |
132 if ( this.menu.active ) { |
114 break; |
133 this.menu.select( event ); |
115 case keyCode.UP: |
134 } |
116 suppressKeyPress = true; |
135 break; |
117 this._keyEvent( "previous", event ); |
136 case keyCode.ESCAPE: |
118 break; |
137 if ( this.menu.element.is( ":visible" ) ) { |
119 case keyCode.DOWN: |
138 if ( !this.isMultiLine ) { |
120 suppressKeyPress = true; |
139 this._value( this.term ); |
121 this._keyEvent( "next", event ); |
|
122 break; |
|
123 case keyCode.ENTER: |
|
124 |
|
125 // when menu is open and has focus |
|
126 if ( this.menu.active ) { |
|
127 |
|
128 // #6055 - Opera still allows the keypress to occur |
|
129 // which causes forms to submit |
|
130 suppressKeyPress = true; |
|
131 event.preventDefault(); |
|
132 this.menu.select( event ); |
140 } |
133 } |
141 this.close( event ); |
134 break; |
142 |
135 case keyCode.TAB: |
143 // Different browsers have different default behavior for escape |
136 if ( this.menu.active ) { |
144 // Single press can mean undo or clear |
137 this.menu.select( event ); |
145 // Double press in IE means clear the whole form |
138 } |
146 event.preventDefault(); |
139 break; |
147 } |
140 case keyCode.ESCAPE: |
148 break; |
141 if ( this.menu.element.is( ":visible" ) ) { |
149 default: |
142 if ( !this.isMultiLine ) { |
150 suppressKeyPressRepeat = true; |
143 this._value( this.term ); |
151 |
144 } |
152 // search timeout should be triggered before the input value is changed |
145 this.close( event ); |
153 this._searchTimeout( event ); |
146 |
154 break; |
147 // Different browsers have different default behavior for escape |
|
148 // Single press can mean undo or clear |
|
149 // Double press in IE means clear the whole form |
|
150 event.preventDefault(); |
|
151 } |
|
152 break; |
|
153 default: |
|
154 suppressKeyPressRepeat = true; |
|
155 |
|
156 // search timeout should be triggered before the input value is changed |
|
157 this._searchTimeout( event ); |
|
158 break; |
155 } |
159 } |
156 }, |
160 }, |
157 keypress: function( event ) { |
161 keypress: function( event ) { |
158 if ( suppressKeyPress ) { |
162 if ( suppressKeyPress ) { |
159 suppressKeyPress = false; |
163 suppressKeyPress = false; |
167 } |
171 } |
168 |
172 |
169 // Replicate some key handlers to allow them to repeat in Firefox and Opera |
173 // Replicate some key handlers to allow them to repeat in Firefox and Opera |
170 var keyCode = $.ui.keyCode; |
174 var keyCode = $.ui.keyCode; |
171 switch ( event.keyCode ) { |
175 switch ( event.keyCode ) { |
172 case keyCode.PAGE_UP: |
176 case keyCode.PAGE_UP: |
173 this._move( "previousPage", event ); |
177 this._move( "previousPage", event ); |
174 break; |
178 break; |
175 case keyCode.PAGE_DOWN: |
179 case keyCode.PAGE_DOWN: |
176 this._move( "nextPage", event ); |
180 this._move( "nextPage", event ); |
177 break; |
181 break; |
178 case keyCode.UP: |
182 case keyCode.UP: |
179 this._keyEvent( "previous", event ); |
183 this._keyEvent( "previous", event ); |
180 break; |
184 break; |
181 case keyCode.DOWN: |
185 case keyCode.DOWN: |
182 this._keyEvent( "next", event ); |
186 this._keyEvent( "next", event ); |
183 break; |
187 break; |
184 } |
188 } |
185 }, |
189 }, |
186 input: function( event ) { |
190 input: function( event ) { |
187 if ( suppressInput ) { |
191 if ( suppressInput ) { |
188 suppressInput = false; |
192 suppressInput = false; |
214 |
213 |
215 // disable ARIA support, the live region takes care of that |
214 // disable ARIA support, the live region takes care of that |
216 role: null |
215 role: null |
217 } ) |
216 } ) |
218 .hide() |
217 .hide() |
|
218 |
|
219 // Support: IE 11 only, Edge <= 14 |
|
220 // For other browsers, we preventDefault() on the mousedown event |
|
221 // to keep the dropdown from taking focus from the input. This doesn't |
|
222 // work for IE/Edge, causing problems with selection and scrolling (#9638) |
|
223 // Happily, IE and Edge support an "unselectable" attribute that |
|
224 // prevents an element from receiving focus, exactly what we want here. |
|
225 .attr( { |
|
226 "unselectable": "on" |
|
227 } ) |
219 .menu( "instance" ); |
228 .menu( "instance" ); |
220 |
229 |
221 this._addClass( this.menu.element, "ui-autocomplete", "ui-front" ); |
230 this._addClass( this.menu.element, "ui-autocomplete", "ui-front" ); |
222 this._on( this.menu.element, { |
231 this._on( this.menu.element, { |
223 mousedown: function( event ) { |
232 mousedown: function( event ) { |
224 |
233 |
225 // prevent moving focus out of the text field |
234 // Prevent moving focus out of the text field |
226 event.preventDefault(); |
235 event.preventDefault(); |
227 |
|
228 // IE doesn't prevent moving focus even with event.preventDefault() |
|
229 // so we set a flag to know when we should ignore the blur event |
|
230 this.cancelBlur = true; |
|
231 this._delay( function() { |
|
232 delete this.cancelBlur; |
|
233 |
|
234 // Support: IE 8 only |
|
235 // Right clicking a menu item or selecting text from the menu items will |
|
236 // result in focus moving out of the input. However, we've already received |
|
237 // and ignored the blur event because of the cancelBlur flag set above. So |
|
238 // we restore focus to ensure that the menu closes properly based on the user's |
|
239 // next actions. |
|
240 if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) { |
|
241 this.element.trigger( "focus" ); |
|
242 } |
|
243 } ); |
|
244 }, |
236 }, |
245 menufocus: function( event, ui ) { |
237 menufocus: function( event, ui ) { |
246 var label, item; |
238 var label, item; |
247 |
239 |
248 // support: Firefox |
240 // support: Firefox |
269 } |
261 } |
270 } |
262 } |
271 |
263 |
272 // Announce the value in the liveRegion |
264 // Announce the value in the liveRegion |
273 label = ui.item.attr( "aria-label" ) || item.value; |
265 label = ui.item.attr( "aria-label" ) || item.value; |
274 if ( label && $.trim( label ).length ) { |
266 if ( label && String.prototype.trim.call( label ).length ) { |
275 this.liveRegion.children().hide(); |
267 clearTimeout( this.liveRegionTimer ); |
276 $( "<div>" ).text( label ).appendTo( this.liveRegion ); |
268 this.liveRegionTimer = this._delay( function() { |
|
269 this.liveRegion.html( $( "<div>" ).text( label ) ); |
|
270 }, 100 ); |
277 } |
271 } |
278 }, |
272 }, |
279 menuselect: function( event, ui ) { |
273 menuselect: function( event, ui ) { |
280 var item = ui.item.data( "ui-autocomplete-item" ), |
274 var item = ui.item.data( "ui-autocomplete-item" ), |
281 previous = this.previous; |
275 previous = this.previous; |
453 }, |
447 }, |
454 |
448 |
455 _response: function() { |
449 _response: function() { |
456 var index = ++this.requestIndex; |
450 var index = ++this.requestIndex; |
457 |
451 |
458 return $.proxy( function( content ) { |
452 return function( content ) { |
459 if ( index === this.requestIndex ) { |
453 if ( index === this.requestIndex ) { |
460 this.__response( content ); |
454 this.__response( content ); |
461 } |
455 } |
462 |
456 |
463 this.pending--; |
457 this.pending--; |
464 if ( !this.pending ) { |
458 if ( !this.pending ) { |
465 this._removeClass( "ui-autocomplete-loading" ); |
459 this._removeClass( "ui-autocomplete-loading" ); |
466 } |
460 } |
467 }, this ); |
461 }.bind( this ); |
468 }, |
462 }, |
469 |
463 |
470 __response: function( content ) { |
464 __response: function( content ) { |
471 if ( content ) { |
465 if ( content ) { |
472 content = this._normalize( content ); |
466 content = this._normalize( content ); |