css
8 years ago
chosen.jquery.js
8 years ago
chosen.jquery.min.js
10 years ago
jquery.ddslick.min.js
10 years ago
jquery.mjs.pmxe_nestedSortable.js
7 years ago
jquery.timepicker.js
8 years ago
jquery.tipsy.js
5 years ago
moment.js
9 years ago
select2.min.js
12 years ago
ui.autocomplete.js
12 years ago
ui.datepicker.js
12 years ago
ui.autocomplete.js
607 lines
| 1 | /* |
| 2 | * jQuery UI Autocomplete 1.8.10 |
| 3 | * |
| 4 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) |
| 5 | * Dual licensed under the MIT or GPL Version 2 licenses. |
| 6 | * http://jquery.org/license |
| 7 | * |
| 8 | * http://docs.jquery.com/UI/Autocomplete |
| 9 | * |
| 10 | * Depends: |
| 11 | * jquery.ui.core.js |
| 12 | * jquery.ui.widget.js |
| 13 | * jquery.ui.position.js |
| 14 | */ |
| 15 | (function( $, undefined ) { |
| 16 | |
| 17 | // used to prevent race conditions with remote data sources |
| 18 | var requestIndex = 0; |
| 19 | |
| 20 | $.widget( "ui.autocomplete", { |
| 21 | options: { |
| 22 | appendTo: "body", |
| 23 | delay: 300, |
| 24 | minLength: 1, |
| 25 | position: { |
| 26 | my: "left top", |
| 27 | at: "left bottom", |
| 28 | collision: "none" |
| 29 | }, |
| 30 | source: null |
| 31 | }, |
| 32 | |
| 33 | pending: 0, |
| 34 | |
| 35 | _create: function() { |
| 36 | var self = this, |
| 37 | doc = this.element[ 0 ].ownerDocument, |
| 38 | suppressKeyPress; |
| 39 | |
| 40 | this.element |
| 41 | .addClass( "ui-autocomplete-input" ) |
| 42 | .attr( "autocomplete", "off" ) |
| 43 | // TODO verify these actually work as intended |
| 44 | .attr({ |
| 45 | role: "textbox", |
| 46 | "aria-autocomplete": "list", |
| 47 | "aria-haspopup": "true" |
| 48 | }) |
| 49 | .bind( "keydown.autocomplete", function( event ) { |
| 50 | if ( self.options.disabled || self.element.attr( "readonly" ) ) { |
| 51 | return; |
| 52 | } |
| 53 | |
| 54 | suppressKeyPress = false; |
| 55 | var keyCode = $.ui.keyCode; |
| 56 | switch( event.keyCode ) { |
| 57 | case keyCode.PAGE_UP: |
| 58 | self._move( "previousPage", event ); |
| 59 | break; |
| 60 | case keyCode.PAGE_DOWN: |
| 61 | self._move( "nextPage", event ); |
| 62 | break; |
| 63 | case keyCode.UP: |
| 64 | self._move( "previous", event ); |
| 65 | // prevent moving cursor to beginning of text field in some browsers |
| 66 | event.preventDefault(); |
| 67 | break; |
| 68 | case keyCode.DOWN: |
| 69 | self._move( "next", event ); |
| 70 | // prevent moving cursor to end of text field in some browsers |
| 71 | event.preventDefault(); |
| 72 | break; |
| 73 | case keyCode.ENTER: |
| 74 | case keyCode.NUMPAD_ENTER: |
| 75 | // when menu is open and has focus |
| 76 | if ( self.menu.active ) { |
| 77 | // #6055 - Opera still allows the keypress to occur |
| 78 | // which causes forms to submit |
| 79 | suppressKeyPress = true; |
| 80 | event.preventDefault(); |
| 81 | } |
| 82 | //passthrough - ENTER and TAB both select the current element |
| 83 | case keyCode.TAB: |
| 84 | if ( !self.menu.active ) { |
| 85 | return; |
| 86 | } |
| 87 | self.menu.select( event ); |
| 88 | break; |
| 89 | case keyCode.ESCAPE: |
| 90 | self.element.val( self.term ); |
| 91 | self.close( event ); |
| 92 | break; |
| 93 | default: |
| 94 | // keypress is triggered before the input value is changed |
| 95 | clearTimeout( self.searching ); |
| 96 | self.searching = setTimeout(function() { |
| 97 | // only search if the value has changed |
| 98 | if ( self.term != self.element.val() ) { |
| 99 | self.selectedItem = null; |
| 100 | self.search( null, event ); |
| 101 | } |
| 102 | }, self.options.delay ); |
| 103 | break; |
| 104 | } |
| 105 | }) |
| 106 | .bind( "keypress.autocomplete", function( event ) { |
| 107 | if ( suppressKeyPress ) { |
| 108 | suppressKeyPress = false; |
| 109 | event.preventDefault(); |
| 110 | } |
| 111 | }) |
| 112 | .bind( "focus.autocomplete", function() { |
| 113 | if ( self.options.disabled ) { |
| 114 | return; |
| 115 | } |
| 116 | |
| 117 | self.selectedItem = null; |
| 118 | self.previous = self.element.val(); |
| 119 | }) |
| 120 | .bind( "blur.autocomplete", function( event ) { |
| 121 | if ( self.options.disabled ) { |
| 122 | return; |
| 123 | } |
| 124 | |
| 125 | clearTimeout( self.searching ); |
| 126 | // clicks on the menu (or a button to trigger a search) will cause a blur event |
| 127 | self.closing = setTimeout(function() { |
| 128 | self.close( event ); |
| 129 | self._change( event ); |
| 130 | }, 150 ); |
| 131 | }); |
| 132 | this._initSource(); |
| 133 | this.response = function() { |
| 134 | return self._response.apply( self, arguments ); |
| 135 | }; |
| 136 | this.menu = $( "<ul></ul>" ) |
| 137 | .addClass( "ui-autocomplete" ) |
| 138 | .appendTo( $( this.options.appendTo || "body", doc )[0] ) |
| 139 | // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown) |
| 140 | .mousedown(function( event ) { |
| 141 | // clicking on the scrollbar causes focus to shift to the body |
| 142 | // but we can't detect a mouseup or a click immediately afterward |
| 143 | // so we have to track the next mousedown and close the menu if |
| 144 | // the user clicks somewhere outside of the autocomplete |
| 145 | var menuElement = self.menu.element[ 0 ]; |
| 146 | if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { |
| 147 | setTimeout(function() { |
| 148 | $( document ).one( 'mousedown', function( event ) { |
| 149 | if ( event.target !== self.element[ 0 ] && |
| 150 | event.target !== menuElement && |
| 151 | !$.ui.contains( menuElement, event.target ) ) { |
| 152 | self.close(); |
| 153 | } |
| 154 | }); |
| 155 | }, 1 ); |
| 156 | } |
| 157 | |
| 158 | // use another timeout to make sure the blur-event-handler on the input was already triggered |
| 159 | setTimeout(function() { |
| 160 | clearTimeout( self.closing ); |
| 161 | }, 13); |
| 162 | }) |
| 163 | .menu({ |
| 164 | focus: function( event, ui ) { |
| 165 | var item = ui.item.data( "item.autocomplete" ); |
| 166 | if ( false !== self._trigger( "focus", event, { item: item } ) ) { |
| 167 | // use value to match what will end up in the input, if it was a key event |
| 168 | if ( /^key/.test(event.originalEvent.type) ) { |
| 169 | self.element.val( item.value ); |
| 170 | } |
| 171 | } |
| 172 | }, |
| 173 | selected: function( event, ui ) { |
| 174 | var item = ui.item.data( "item.autocomplete" ), |
| 175 | previous = self.previous; |
| 176 | |
| 177 | // only trigger when focus was lost (click on menu) |
| 178 | if ( self.element[0] !== doc.activeElement ) { |
| 179 | self.element.focus(); |
| 180 | self.previous = previous; |
| 181 | // #6109 - IE triggers two focus events and the second |
| 182 | // is asynchronous, so we need to reset the previous |
| 183 | // term synchronously and asynchronously :-( |
| 184 | setTimeout(function() { |
| 185 | self.previous = previous; |
| 186 | self.selectedItem = item; |
| 187 | }, 1); |
| 188 | } |
| 189 | |
| 190 | if ( false !== self._trigger( "select", event, { item: item } ) ) { |
| 191 | self.element.val( item.value ); |
| 192 | } |
| 193 | // reset the term after the select event |
| 194 | // this allows custom select handling to work properly |
| 195 | self.term = self.element.val(); |
| 196 | |
| 197 | self.close( event ); |
| 198 | self.selectedItem = item; |
| 199 | }, |
| 200 | blur: function( event, ui ) { |
| 201 | // don't set the value of the text field if it's already correct |
| 202 | // this prevents moving the cursor unnecessarily |
| 203 | if ( self.menu.element.is(":visible") && |
| 204 | ( self.element.val() !== self.term ) ) { |
| 205 | self.element.val( self.term ); |
| 206 | } |
| 207 | } |
| 208 | }) |
| 209 | .zIndex( this.element.zIndex() + 1 ) |
| 210 | // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 |
| 211 | .css({ top: 0, left: 0 }) |
| 212 | .data( "menu" ); |
| 213 | if ( $.fn.bgiframe ) { |
| 214 | this.menu.element.bgiframe(); |
| 215 | } |
| 216 | }, |
| 217 | |
| 218 | destroy: function() { |
| 219 | this.element |
| 220 | .removeClass( "ui-autocomplete-input" ) |
| 221 | .removeAttr( "autocomplete" ) |
| 222 | .removeAttr( "role" ) |
| 223 | .removeAttr( "aria-autocomplete" ) |
| 224 | .removeAttr( "aria-haspopup" ); |
| 225 | this.menu.element.remove(); |
| 226 | $.Widget.prototype.destroy.call( this ); |
| 227 | }, |
| 228 | |
| 229 | _setOption: function( key, value ) { |
| 230 | $.Widget.prototype._setOption.apply( this, arguments ); |
| 231 | if ( key === "source" ) { |
| 232 | this._initSource(); |
| 233 | } |
| 234 | if ( key === "appendTo" ) { |
| 235 | this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] ) |
| 236 | } |
| 237 | if ( key === "disabled" && value && this.xhr ) { |
| 238 | this.xhr.abort(); |
| 239 | } |
| 240 | }, |
| 241 | |
| 242 | _initSource: function() { |
| 243 | var self = this, |
| 244 | array, |
| 245 | url; |
| 246 | if ( $.isArray(this.options.source) ) { |
| 247 | array = this.options.source; |
| 248 | this.source = function( request, response ) { |
| 249 | response( $.ui.autocomplete.filter(array, request.term) ); |
| 250 | }; |
| 251 | } else if ( typeof this.options.source === "string" ) { |
| 252 | url = this.options.source; |
| 253 | this.source = function( request, response ) { |
| 254 | if ( self.xhr ) { |
| 255 | self.xhr.abort(); |
| 256 | } |
| 257 | self.xhr = $.ajax({ |
| 258 | url: url, |
| 259 | data: request, |
| 260 | dataType: "json", |
| 261 | autocompleteRequest: ++requestIndex, |
| 262 | success: function( data, status ) { |
| 263 | if ( this.autocompleteRequest === requestIndex ) { |
| 264 | response( data ); |
| 265 | } |
| 266 | }, |
| 267 | error: function() { |
| 268 | if ( this.autocompleteRequest === requestIndex ) { |
| 269 | response( [] ); |
| 270 | } |
| 271 | } |
| 272 | }); |
| 273 | }; |
| 274 | } else { |
| 275 | this.source = this.options.source; |
| 276 | } |
| 277 | }, |
| 278 | |
| 279 | search: function( value, event ) { |
| 280 | value = value != null ? value : this.element.val(); |
| 281 | |
| 282 | // always save the actual value, not the one passed as an argument |
| 283 | this.term = this.element.val(); |
| 284 | |
| 285 | if ( value.length < this.options.minLength ) { |
| 286 | return this.close( event ); |
| 287 | } |
| 288 | |
| 289 | clearTimeout( this.closing ); |
| 290 | if ( this._trigger( "search", event ) === false ) { |
| 291 | return; |
| 292 | } |
| 293 | |
| 294 | return this._search( value ); |
| 295 | }, |
| 296 | |
| 297 | _search: function( value ) { |
| 298 | this.pending++; |
| 299 | this.element.addClass( "ui-autocomplete-loading" ); |
| 300 | |
| 301 | this.source( { term: value }, this.response ); |
| 302 | }, |
| 303 | |
| 304 | _response: function( content ) { |
| 305 | if ( !this.options.disabled && content && content.length ) { |
| 306 | content = this._normalize( content ); |
| 307 | this._suggest( content ); |
| 308 | this._trigger( "open" ); |
| 309 | } else { |
| 310 | this.close(); |
| 311 | } |
| 312 | this.pending--; |
| 313 | if ( !this.pending ) { |
| 314 | this.element.removeClass( "ui-autocomplete-loading" ); |
| 315 | } |
| 316 | }, |
| 317 | |
| 318 | close: function( event ) { |
| 319 | clearTimeout( this.closing ); |
| 320 | if ( this.menu.element.is(":visible") ) { |
| 321 | this.menu.element.hide(); |
| 322 | this.menu.deactivate(); |
| 323 | this._trigger( "close", event ); |
| 324 | } |
| 325 | }, |
| 326 | |
| 327 | _change: function( event ) { |
| 328 | if ( this.previous !== this.element.val() ) { |
| 329 | this._trigger( "change", event, { item: this.selectedItem } ); |
| 330 | } |
| 331 | }, |
| 332 | |
| 333 | _normalize: function( items ) { |
| 334 | // assume all items have the right format when the first item is complete |
| 335 | if ( items.length && items[0].label && items[0].value ) { |
| 336 | return items; |
| 337 | } |
| 338 | return $.map( items, function(item) { |
| 339 | if ( typeof item === "string" ) { |
| 340 | return { |
| 341 | label: item, |
| 342 | value: item |
| 343 | }; |
| 344 | } |
| 345 | return $.extend({ |
| 346 | label: item.label || item.value, |
| 347 | value: item.value || item.label |
| 348 | }, item ); |
| 349 | }); |
| 350 | }, |
| 351 | |
| 352 | _suggest: function( items ) { |
| 353 | var ul = this.menu.element |
| 354 | .empty() |
| 355 | .zIndex( this.element.zIndex() + 1 ); |
| 356 | this._renderMenu( ul, items ); |
| 357 | // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate |
| 358 | this.menu.deactivate(); |
| 359 | this.menu.refresh(); |
| 360 | |
| 361 | // size and position menu |
| 362 | ul.show(); |
| 363 | this._resizeMenu(); |
| 364 | ul.position( $.extend({ |
| 365 | of: this.element |
| 366 | }, this.options.position )); |
| 367 | }, |
| 368 | |
| 369 | _resizeMenu: function() { |
| 370 | var ul = this.menu.element; |
| 371 | ul.outerWidth( Math.max( |
| 372 | ul.width( "" ).outerWidth(), |
| 373 | this.element.outerWidth() |
| 374 | ) ); |
| 375 | }, |
| 376 | |
| 377 | _renderMenu: function( ul, items ) { |
| 378 | var self = this; |
| 379 | $.each( items, function( index, item ) { |
| 380 | self._renderItem( ul, item ); |
| 381 | }); |
| 382 | }, |
| 383 | |
| 384 | _renderItem: function( ul, item) { |
| 385 | return $( "<li></li>" ) |
| 386 | .data( "item.autocomplete", item ) |
| 387 | .append( $( "<a></a>" ).text( item.label ) ) |
| 388 | .appendTo( ul ); |
| 389 | }, |
| 390 | |
| 391 | _move: function( direction, event ) { |
| 392 | if ( !this.menu.element.is(":visible") ) { |
| 393 | this.search( null, event ); |
| 394 | return; |
| 395 | } |
| 396 | if ( this.menu.first() && /^previous/.test(direction) || |
| 397 | this.menu.last() && /^next/.test(direction) ) { |
| 398 | this.element.val( this.term ); |
| 399 | this.menu.deactivate(); |
| 400 | return; |
| 401 | } |
| 402 | this.menu[ direction ]( event ); |
| 403 | }, |
| 404 | |
| 405 | widget: function() { |
| 406 | return this.menu.element; |
| 407 | } |
| 408 | }); |
| 409 | |
| 410 | $.extend( $.ui.autocomplete, { |
| 411 | escapeRegex: function( value ) { |
| 412 | return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); |
| 413 | }, |
| 414 | filter: function(array, term) { |
| 415 | var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); |
| 416 | return $.grep( array, function(value) { |
| 417 | return matcher.test( value.label || value.value || value ); |
| 418 | }); |
| 419 | } |
| 420 | }); |
| 421 | |
| 422 | }( jQuery )); |
| 423 | |
| 424 | /* |
| 425 | * jQuery UI Menu (not officially released) |
| 426 | * |
| 427 | * This widget isn't yet finished and the API is subject to change. We plan to finish |
| 428 | * it for the next release. You're welcome to give it a try anyway and give us feedback, |
| 429 | * as long as you're okay with migrating your code later on. We can help with that, too. |
| 430 | * |
| 431 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) |
| 432 | * Dual licensed under the MIT or GPL Version 2 licenses. |
| 433 | * http://jquery.org/license |
| 434 | * |
| 435 | * http://docs.jquery.com/UI/Menu |
| 436 | * |
| 437 | * Depends: |
| 438 | * jquery.ui.core.js |
| 439 | * jquery.ui.widget.js |
| 440 | */ |
| 441 | (function($) { |
| 442 | |
| 443 | $.widget("ui.menu", { |
| 444 | _create: function() { |
| 445 | var self = this; |
| 446 | this.element |
| 447 | .addClass("ui-menu ui-widget ui-widget-content ui-corner-all") |
| 448 | .attr({ |
| 449 | role: "listbox", |
| 450 | "aria-activedescendant": "ui-active-menuitem" |
| 451 | }) |
| 452 | .click(function( event ) { |
| 453 | if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) { |
| 454 | return; |
| 455 | } |
| 456 | // temporary |
| 457 | event.preventDefault(); |
| 458 | self.select( event ); |
| 459 | }); |
| 460 | this.refresh(); |
| 461 | }, |
| 462 | |
| 463 | refresh: function() { |
| 464 | var self = this; |
| 465 | |
| 466 | // don't refresh list items that are already adapted |
| 467 | var items = this.element.children("li:not(.ui-menu-item):has(a)") |
| 468 | .addClass("ui-menu-item") |
| 469 | .attr("role", "menuitem"); |
| 470 | |
| 471 | items.children("a") |
| 472 | .addClass("ui-corner-all") |
| 473 | .attr("tabindex", -1) |
| 474 | // mouseenter doesn't work with event delegation |
| 475 | .mouseenter(function( event ) { |
| 476 | self.activate( event, $(this).parent() ); |
| 477 | }) |
| 478 | .mouseleave(function() { |
| 479 | self.deactivate(); |
| 480 | }); |
| 481 | }, |
| 482 | |
| 483 | activate: function( event, item ) { |
| 484 | this.deactivate(); |
| 485 | if (this.hasScroll()) { |
| 486 | var offset = item.offset().top - this.element.offset().top, |
| 487 | scroll = this.element.attr("scrollTop"), |
| 488 | elementHeight = this.element.height(); |
| 489 | if (offset < 0) { |
| 490 | this.element.attr("scrollTop", scroll + offset); |
| 491 | } else if (offset >= elementHeight) { |
| 492 | this.element.attr("scrollTop", scroll + offset - elementHeight + item.height()); |
| 493 | } |
| 494 | } |
| 495 | this.active = item.eq(0) |
| 496 | .children("a") |
| 497 | .addClass("ui-state-hover") |
| 498 | .attr("id", "ui-active-menuitem") |
| 499 | .end(); |
| 500 | this._trigger("focus", event, { item: item }); |
| 501 | }, |
| 502 | |
| 503 | deactivate: function() { |
| 504 | if (!this.active) { return; } |
| 505 | |
| 506 | this.active.children("a") |
| 507 | .removeClass("ui-state-hover") |
| 508 | .removeAttr("id"); |
| 509 | this._trigger("blur"); |
| 510 | this.active = null; |
| 511 | }, |
| 512 | |
| 513 | next: function(event) { |
| 514 | this.move("next", ".ui-menu-item:first", event); |
| 515 | }, |
| 516 | |
| 517 | previous: function(event) { |
| 518 | this.move("prev", ".ui-menu-item:last", event); |
| 519 | }, |
| 520 | |
| 521 | first: function() { |
| 522 | return this.active && !this.active.prevAll(".ui-menu-item").length; |
| 523 | }, |
| 524 | |
| 525 | last: function() { |
| 526 | return this.active && !this.active.nextAll(".ui-menu-item").length; |
| 527 | }, |
| 528 | |
| 529 | move: function(direction, edge, event) { |
| 530 | if (!this.active) { |
| 531 | this.activate(event, this.element.children(edge)); |
| 532 | return; |
| 533 | } |
| 534 | var next = this.active[direction + "All"](".ui-menu-item").eq(0); |
| 535 | if (next.length) { |
| 536 | this.activate(event, next); |
| 537 | } else { |
| 538 | this.activate(event, this.element.children(edge)); |
| 539 | } |
| 540 | }, |
| 541 | |
| 542 | // TODO merge with previousPage |
| 543 | nextPage: function(event) { |
| 544 | if (this.hasScroll()) { |
| 545 | // TODO merge with no-scroll-else |
| 546 | if (!this.active || this.last()) { |
| 547 | this.activate(event, this.element.children(".ui-menu-item:first")); |
| 548 | return; |
| 549 | } |
| 550 | var base = this.active.offset().top, |
| 551 | height = this.element.height(), |
| 552 | result = this.element.children(".ui-menu-item").filter(function() { |
| 553 | var close = $(this).offset().top - base - height + $(this).height(); |
| 554 | // TODO improve approximation |
| 555 | return close < 10 && close > -10; |
| 556 | }); |
| 557 | |
| 558 | // TODO try to catch this earlier when scrollTop indicates the last page anyway |
| 559 | if (!result.length) { |
| 560 | result = this.element.children(".ui-menu-item:last"); |
| 561 | } |
| 562 | this.activate(event, result); |
| 563 | } else { |
| 564 | this.activate(event, this.element.children(".ui-menu-item") |
| 565 | .filter(!this.active || this.last() ? ":first" : ":last")); |
| 566 | } |
| 567 | }, |
| 568 | |
| 569 | // TODO merge with nextPage |
| 570 | previousPage: function(event) { |
| 571 | if (this.hasScroll()) { |
| 572 | // TODO merge with no-scroll-else |
| 573 | if (!this.active || this.first()) { |
| 574 | this.activate(event, this.element.children(".ui-menu-item:last")); |
| 575 | return; |
| 576 | } |
| 577 | |
| 578 | var base = this.active.offset().top, |
| 579 | height = this.element.height(); |
| 580 | result = this.element.children(".ui-menu-item").filter(function() { |
| 581 | var close = $(this).offset().top - base + height - $(this).height(); |
| 582 | // TODO improve approximation |
| 583 | return close < 10 && close > -10; |
| 584 | }); |
| 585 | |
| 586 | // TODO try to catch this earlier when scrollTop indicates the last page anyway |
| 587 | if (!result.length) { |
| 588 | result = this.element.children(".ui-menu-item:first"); |
| 589 | } |
| 590 | this.activate(event, result); |
| 591 | } else { |
| 592 | this.activate(event, this.element.children(".ui-menu-item") |
| 593 | .filter(!this.active || this.first() ? ":last" : ":first")); |
| 594 | } |
| 595 | }, |
| 596 | |
| 597 | hasScroll: function() { |
| 598 | return this.element.height() < this.element.attr("scrollHeight"); |
| 599 | }, |
| 600 | |
| 601 | select: function( event ) { |
| 602 | this._trigger("selected", event, { item: this.active }); |
| 603 | } |
| 604 | }); |
| 605 | |
| 606 | }(jQuery)); |
| 607 |