vendor: 4,583 bytes, lines 1-130
1 2/*! 3 * jQuery UI Widget 1.11.3 4 * http://jqueryui.com 5 * 6 * Copyright jQuery Foundation and other contributors 7 * Released under the MIT license. 8 * http://jquery.org/license 9 * 10 * http://api.jqueryui.com/jQuery.widget/ 11 */ 12 13 14var widget_uuid = 0, 15 widget_slice = Array.prototype.slice; 16 17$.cleanData = (function( orig ) { 18 return function( elems ) { 19 var events, elem, i; 20 for ( i = 0; (elem = elems[i]) != null; i++ ) { 21 try { 22 23 // Only trigger remove when necessary to save time 24 events = $._data( elem, "events" ); 25 if ( events && events.remove ) { 26 $( elem ).triggerHandler( "remove" ); 27 } 28 29 // http://bugs.jquery.com/ticket/8235 30 } catch ( e ) {} 31 } 32 orig( elems ); 33 }; 34})( $.cleanData ); 35 36$.widget = function( name, base, prototype ) { 37 var fullName, existingConstructor, constructor, basePrototype, 38 // proxiedPrototype allows the provided prototype to remain unmodified 39 // so that it can be used as a mixin for multiple widgets (#8876) 40 proxiedPrototype = {}, 41 namespace = name.split( "." )[ 0 ]; 42 43 name = name.split( "." )[ 1 ]; 44 fullName = namespace + "-" + name; 45 46 if ( !prototype ) { 47 prototype = base; 48 base = $.Widget; 49 } 50 51 // create selector for plugin 52 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { 53 return !!$.data( elem, fullName ); 54 }; 55 56 $[ namespace ] = $[ namespace ] || {}; 57 existingConstructor = $[ namespace ][ name ]; 58 constructor = $[ namespace ][ name ] = function( options, element ) { 59 // allow instantiation without "new" keyword 60 if ( !this._createWidget ) { 61 return new constructor( options, element ); 62 } 63 64 // allow instantiation without initializing for simple inheritance 65 // must use "new" keyword (the code above always passes args) 66 if ( arguments.length ) { 67 this._createWidget( options, element ); 68 } 69 }; 70 // extend with the existing constructor to carry over any static properties 71 $.extend( constructor, existingConstructor, { 72 version: prototype.version, 73 // copy the object used to create the prototype in case we need to 74 // redefine the widget later 75 _proto: $.extend( {}, prototype ), 76 // track widgets that inherit from this widget in case this widget is 77 // redefined after a widget inherits from it 78 _childConstructors: [] 79 }); 80 81 basePrototype = new base(); 82 // we need to make the options hash a property directly on the new instance 83 // otherwise we'll modify the options hash on the prototype that we're 84 // inheriting from 85 basePrototype.options = $.widget.extend( {}, basePrototype.options ); 86 $.each( prototype, function( prop, value ) { 87 if ( !$.isFunction( value ) ) { 88 proxiedPrototype[ prop ] = value; 89 return; 90 } 91 proxiedPrototype[ prop ] = (function() { 92 var _super = function() { 93 return base.prototype[ prop ].apply( this, arguments ); 94 }, 95 _superApply = function( args ) { 96 return base.prototype[ prop ].apply( this, args ); 97 }; 98 return function() { 99 var __super = this._super, 100 __superApply = this._superApply, 101 returnValue; 102 103 this._super = _super; 104 this._superApply = _superApply; 105 106 returnValue = value.apply( this, arguments ); 107 108 this._super = __super; 109 this._superApply = __superApply; 110 111 return returnValue; 112 }; 113 })(); 114 }); 115 constructor.prototype = $.widget.extend( basePrototype, { 116 // TODO: remove support for widgetEventPrefix 117 // always use the name + a colon as the prefix, e.g., draggable:start 118 // don't prefix for widgets that aren't DOM-based 119 widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name 120 }, proxiedPrototype, { 121 constructor: constructor, 122 namespace: namespace, 123 widgetName: name, 124 widgetFullName: fullName 125 }); 126 127 // If this widget is being redefined then we need to find all widgets that 128 // are inheriting from it and redefine all of them so that they inherit from 129 // the new version of this widget. We're essentially trying to replace one 130 // level in the prototype chain.
vendor: 25,140 bytes, lines 131-845
131 if ( existingConstructor ) { 132 $.each( existingConstructor._childConstructors, function( i, child ) { 133 var childPrototype = child.prototype; 134 135 // redefine the child widget using the same prototype that was 136 // originally used, but inherit from the new version of the base 137 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); 138 }); 139 // remove the list of existing child constructors from the old constructor 140 // so the old child constructors can be garbage collected 141 delete existingConstructor._childConstructors; 142 } else { 143 base._childConstructors.push( constructor ); 144 } 145 146 $.widget.bridge( name, constructor ); 147 148 return constructor; 149}; 150 151$.widget.extend = function( target ) { 152 var input = widget_slice.call( arguments, 1 ), 153 inputIndex = 0, 154 inputLength = input.length, 155 key, 156 value; 157 for ( ; inputIndex < inputLength; inputIndex++ ) { 158 for ( key in input[ inputIndex ] ) { 159 value = input[ inputIndex ][ key ]; 160 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { 161 // Clone objects 162 if ( $.isPlainObject( value ) ) { 163 target[ key ] = $.isPlainObject( target[ key ] ) ? 164 $.widget.extend( {}, target[ key ], value ) : 165 // Don't extend strings, arrays, etc. with objects 166 $.widget.extend( {}, value ); 167 // Copy everything else by reference 168 } else { 169 target[ key ] = value; 170 } 171 } 172 } 173 } 174 return target; 175}; 176 177$.widget.bridge = function( name, object ) { 178 var fullName = object.prototype.widgetFullName || name; 179 $.fn[ name ] = function( options ) { 180 var isMethodCall = typeof options === "string", 181 args = widget_slice.call( arguments, 1 ), 182 returnValue = this; 183 184 if ( isMethodCall ) { 185 this.each(function() { 186 var methodValue, 187 instance = $.data( this, fullName ); 188 if ( options === "instance" ) { 189 returnValue = instance; 190 return false; 191 } 192 if ( !instance ) { 193 return $.error( "cannot call methods on " + name + " prior to initialization; " + 194 "attempted to call method '" + options + "'" ); 195 } 196 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { 197 return $.error( "no such method '" + options + "' for " + name + " widget instance" ); 198 } 199 methodValue = instance[ options ].apply( instance, args ); 200 if ( methodValue !== instance && methodValue !== undefined ) { 201 returnValue = methodValue && methodValue.jquery ? 202 returnValue.pushStack( methodValue.get() ) : 203 methodValue; 204 return false; 205 } 206 }); 207 } else { 208 209 // Allow multiple hashes to be passed on init 210 if ( args.length ) { 211 options = $.widget.extend.apply( null, [ options ].concat(args) ); 212 } 213 214 this.each(function() { 215 var instance = $.data( this, fullName ); 216 if ( instance ) { 217 instance.option( options || {} ); 218 if ( instance._init ) { 219 instance._init(); 220 } 221 } else { 222 $.data( this, fullName, new object( options, this ) ); 223 } 224 }); 225 } 226 227 return returnValue; 228 }; 229}; 230 231$.Widget = function( /* options, element */ ) {}; 232$.Widget._childConstructors = []; 233 234$.Widget.prototype = { 235 widgetName: "widget", 236 widgetEventPrefix: "", 237 defaultElement: "<div>", 238 options: { 239 disabled: false, 240 241 // callbacks 242 create: null 243 }, 244 _createWidget: function( options, element ) { 245 element = $( element || this.defaultElement || this )[ 0 ]; 246 this.element = $( element ); 247 this.uuid = widget_uuid++; 248 this.eventNamespace = "." + this.widgetName + this.uuid; 249 250 this.bindings = $(); 251 this.hoverable = $(); 252 this.focusable = $(); 253 254 if ( element !== this ) { 255 $.data( element, this.widgetFullName, this ); 256 this._on( true, this.element, { 257 remove: function( event ) { 258 if ( event.target === element ) { 259 this.destroy(); 260 } 261 } 262 }); 263 this.document = $( element.style ? 264 // element within the document 265 element.ownerDocument : 266 // element is window or document 267 element.document || element ); 268 this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); 269 } 270 271 this.options = $.widget.extend( {}, 272 this.options, 273 this._getCreateOptions(), 274 options ); 275 276 this._create(); 277 this._trigger( "create", null, this._getCreateEventData() ); 278 this._init(); 279 }, 280 _getCreateOptions: $.noop, 281 _getCreateEventData: $.noop, 282 _create: $.noop, 283 _init: $.noop, 284 285 destroy: function() { 286 this._destroy(); 287 // we can probably remove the unbind calls in 2.0 288 // all event bindings should go through this._on() 289 this.element 290 .unbind( this.eventNamespace ) 291 .removeData( this.widgetFullName ) 292 // support: jquery <1.6.3 293 // http://bugs.jquery.com/ticket/9413 294 .removeData( $.camelCase( this.widgetFullName ) ); 295 this.widget() 296 .unbind( this.eventNamespace ) 297 .removeAttr( "aria-disabled" ) 298 .removeClass( 299 this.widgetFullName + "-disabled " + 300 "ui-state-disabled" ); 301 302 // clean up events and states 303 this.bindings.unbind( this.eventNamespace ); 304 this.hoverable.removeClass( "ui-state-hover" ); 305 this.focusable.removeClass( "ui-state-focus" ); 306 }, 307 _destroy: $.noop, 308 309 widget: function() { 310 return this.element; 311 }, 312 313 option: function( key, value ) { 314 var options = key, 315 parts, 316 curOption, 317 i; 318 319 if ( arguments.length === 0 ) { 320 // don't return a reference to the internal hash 321 return $.widget.extend( {}, this.options ); 322 } 323 324 if ( typeof key === "string" ) { 325 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } 326 options = {}; 327 parts = key.split( "." ); 328 key = parts.shift(); 329 if ( parts.length ) { 330 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); 331 for ( i = 0; i < parts.length - 1; i++ ) { 332 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; 333 curOption = curOption[ parts[ i ] ]; 334 } 335 key = parts.pop(); 336 if ( arguments.length === 1 ) { 337 return curOption[ key ] === undefined ? null : curOption[ key ]; 338 } 339 curOption[ key ] = value; 340 } else { 341 if ( arguments.length === 1 ) { 342 return this.options[ key ] === undefined ? null : this.options[ key ]; 343 } 344 options[ key ] = value; 345 } 346 } 347 348 this._setOptions( options ); 349 350 return this; 351 }, 352 _setOptions: function( options ) { 353 var key; 354 355 for ( key in options ) { 356 this._setOption( key, options[ key ] ); 357 } 358 359 return this; 360 }, 361 _setOption: function( key, value ) { 362 this.options[ key ] = value; 363 364 if ( key === "disabled" ) { 365 this.widget() 366 .toggleClass( this.widgetFullName + "-disabled", !!value ); 367 368 // If the widget is becoming disabled, then nothing is interactive 369 if ( value ) { 370 this.hoverable.removeClass( "ui-state-hover" ); 371 this.focusable.removeClass( "ui-state-focus" ); 372 } 373 } 374 375 return this; 376 }, 377 378 enable: function() { 379 return this._setOptions({ disabled: false }); 380 }, 381 disable: function() { 382 return this._setOptions({ disabled: true }); 383 }, 384 385 _on: function( suppressDisabledCheck, element, handlers ) { 386 var delegateElement, 387 instance = this; 388 389 // no suppressDisabledCheck flag, shuffle arguments 390 if ( typeof suppressDisabledCheck !== "boolean" ) { 391 handlers = element; 392 element = suppressDisabledCheck; 393 suppressDisabledCheck = false; 394 } 395 396 // no element argument, shuffle and use this.element 397 if ( !handlers ) { 398 handlers = element; 399 element = this.element; 400 delegateElement = this.widget(); 401 } else { 402 element = delegateElement = $( element ); 403 this.bindings = this.bindings.add( element ); 404 } 405 406 $.each( handlers, function( event, handler ) { 407 function handlerProxy() { 408 // allow widgets to customize the disabled handling 409 // - disabled as an array instead of boolean 410 // - disabled class as method for disabling individual parts 411 if ( !suppressDisabledCheck && 412 ( instance.options.disabled === true || 413 $( this ).hasClass( "ui-state-disabled" ) ) ) { 414 return; 415 } 416 return ( typeof handler === "string" ? instance[ handler ] : handler ) 417 .apply( instance, arguments ); 418 } 419 420 // copy the guid so direct unbinding works 421 if ( typeof handler !== "string" ) { 422 handlerProxy.guid = handler.guid = 423 handler.guid || handlerProxy.guid || $.guid++; 424 } 425 426 var match = event.match( /^([\w:-]*)\s*(.*)$/ ), 427 eventName = match[1] + instance.eventNamespace, 428 selector = match[2]; 429 if ( selector ) { 430 delegateElement.delegate( selector, eventName, handlerProxy ); 431 } else { 432 element.bind( eventName, handlerProxy ); 433 } 434 }); 435 }, 436 437 _off: function( element, eventName ) { 438 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + 439 this.eventNamespace; 440 element.unbind( eventName ).undelegate( eventName ); 441 442 // Clear the stack to avoid memory leaks (#10056) 443 this.bindings = $( this.bindings.not( element ).get() ); 444 this.focusable = $( this.focusable.not( element ).get() ); 445 this.hoverable = $( this.hoverable.not( element ).get() ); 446 }, 447 448 _delay: function( handler, delay ) { 449 function handlerProxy() { 450 return ( typeof handler === "string" ? instance[ handler ] : handler ) 451 .apply( instance, arguments ); 452 } 453 var instance = this; 454 return setTimeout( handlerProxy, delay || 0 ); 455 }, 456 457 _hoverable: function( element ) { 458 this.hoverable = this.hoverable.add( element ); 459 this._on( element, { 460 mouseenter: function( event ) { 461 $( event.currentTarget ).addClass( "ui-state-hover" ); 462 }, 463 mouseleave: function( event ) { 464 $( event.currentTarget ).removeClass( "ui-state-hover" ); 465 } 466 }); 467 }, 468 469 _focusable: function( element ) { 470 this.focusable = this.focusable.add( element ); 471 this._on( element, { 472 focusin: function( event ) { 473 $( event.currentTarget ).addClass( "ui-state-focus" ); 474 }, 475 focusout: function( event ) { 476 $( event.currentTarget ).removeClass( "ui-state-focus" ); 477 } 478 }); 479 }, 480 481 _trigger: function( type, event, data ) { 482 var prop, orig, 483 callback = this.options[ type ]; 484 485 data = data || {}; 486 event = $.Event( event ); 487 event.type = ( type === this.widgetEventPrefix ? 488 type : 489 this.widgetEventPrefix + type ).toLowerCase(); 490 // the original event may come from any element 491 // so we need to reset the target on the new event 492 event.target = this.element[ 0 ]; 493 494 // copy original event properties over to the new event 495 orig = event.originalEvent; 496 if ( orig ) { 497 for ( prop in orig ) { 498 if ( !( prop in event ) ) { 499 event[ prop ] = orig[ prop ]; 500 } 501 } 502 } 503 504 this.element.trigger( event, data ); 505 return !( $.isFunction( callback ) && 506 callback.apply( this.element[0], [ event ].concat( data ) ) === false || 507 event.isDefaultPrevented() ); 508 } 509}; 510 511$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { 512 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { 513 if ( typeof options === "string" ) { 514 options = { effect: options }; 515 } 516 var hasOptions, 517 effectName = !options ? 518 method : 519 options === true || typeof options === "number" ? 520 defaultEffect : 521 options.effect || defaultEffect; 522 options = options || {}; 523 if ( typeof options === "number" ) { 524 options = { duration: options }; 525 } 526 hasOptions = !$.isEmptyObject( options ); 527 options.complete = callback; 528 if ( options.delay ) { 529 element.delay( options.delay ); 530 } 531 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { 532 element[ method ]( options ); 533 } else if ( effectName !== method && element[ effectName ] ) { 534 element[ effectName ]( options.duration, options.easing, callback ); 535 } else { 536 element.queue(function( next ) { 537 $( this )[ method ](); 538 if ( callback ) { 539 callback.call( element[ 0 ] ); 540 } 541 next(); 542 }); 543 } 544 }; 545}); 546 547var widget = $.widget; 548 549 550 551/*! 552 * jQuery UI Menu 1.11.3 553 * http://jqueryui.com 554 * 555 * Copyright jQuery Foundation and other contributors 556 * Released under the MIT license. 557 * http://jquery.org/license 558 * 559 * http://api.jqueryui.com/menu/ 560 */ 561 562 563var menu = $.widget( "ui.menu", { 564 version: "1.11.3", 565 defaultElement: "<ul>", 566 delay: 300, 567 options: { 568 icons: { 569 submenu: "ui-icon-carat-1-e" 570 }, 571 items: "> *", 572 menus: "ul", 573 position: { 574 my: "left-1 top", 575 at: "right top" 576 }, 577 role: "menu", 578 579 // callbacks 580 blur: null, 581 focus: null, 582 select: null 583 }, 584 585 _create: function() { 586 this.activeMenu = this.element; 587 588 // Flag used to prevent firing of the click handler 589 // as the event bubbles up through nested menus 590 this.mouseHandled = false; 591 this.element 592 .uniqueId() 593 .addClass( "ui-menu ui-widget ui-widget-content" ) 594 .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ) 595 .attr({ 596 role: this.options.role, 597 tabIndex: 0 598 }); 599 600 if ( this.options.disabled ) { 601 this.element 602 .addClass( "ui-state-disabled" ) 603 .attr( "aria-disabled", "true" ); 604 } 605 606 this._on({ 607 // Prevent focus from sticking to links inside menu after clicking 608 // them (focus should always stay on UL during navigation). 609 "mousedown .ui-menu-item": function( event ) { 610 event.preventDefault(); 611 }, 612 "click .ui-menu-item": function( event ) { 613 var target = $( event.target ); 614 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { 615 this.select( event ); 616 617 // Only set the mouseHandled flag if the event will bubble, see #9469. 618 if ( !event.isPropagationStopped() ) { 619 this.mouseHandled = true; 620 } 621 622 // Open submenu on click 623 if ( target.has( ".ui-menu" ).length ) { 624 this.expand( event ); 625 } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) { 626 627 // Redirect focus to the menu 628 this.element.trigger( "focus", [ true ] ); 629 630 // If the active item is on the top level, let it stay active. 631 // Otherwise, blur the active item since it is no longer visible. 632 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { 633 clearTimeout( this.timer ); 634 } 635 } 636 } 637 }, 638 "mouseenter .ui-menu-item": function( event ) { 639 // Ignore mouse events while typeahead is active, see #10458. 640 // Prevents focusing the wrong item when typeahead causes a scroll while the mouse 641 // is over an item in the menu 642 if ( this.previousFilter ) { 643 return; 644 } 645 var target = $( event.currentTarget ); 646 // Remove ui-state-active class from siblings of the newly focused menu item 647 // to avoid a jump caused by adjacent elements both having a class with a border 648 target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" ); 649 this.focus( event, target ); 650 }, 651 mouseleave: "collapseAll", 652 "mouseleave .ui-menu": "collapseAll", 653 focus: function( event, keepActiveItem ) { 654 // If there's already an active item, keep it active 655 // If not, activate the first item 656 var item = this.active || this.element.find( this.options.items ).eq( 0 ); 657 658 if ( !keepActiveItem ) { 659 this.focus( event, item ); 660 } 661 }, 662 blur: function( event ) { 663 this._delay(function() { 664 if ( !$.contains( this.element[0], this.document[0].activeElement ) ) { 665 this.collapseAll( event ); 666 } 667 }); 668 }, 669 keydown: "_keydown" 670 }); 671 672 this.refresh(); 673 674 // Clicks outside of a menu collapse any open menus 675 this._on( this.document, { 676 click: function( event ) { 677 if ( this._closeOnDocumentClick( event ) ) { 678 this.collapseAll( event ); 679 } 680 681 // Reset the mouseHandled flag 682 this.mouseHandled = false; 683 } 684 }); 685 }, 686 687 _destroy: function() { 688 // Destroy (sub)menus 689 this.element 690 .removeAttr( "aria-activedescendant" ) 691 .find( ".ui-menu" ).addBack() 692 .removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" ) 693 .removeAttr( "role" ) 694 .removeAttr( "tabIndex" ) 695 .removeAttr( "aria-labelledby" ) 696 .removeAttr( "aria-expanded" ) 697 .removeAttr( "aria-hidden" ) 698 .removeAttr( "aria-disabled" ) 699 .removeUniqueId() 700 .show(); 701 702 // Destroy menu items 703 this.element.find( ".ui-menu-item" ) 704 .removeClass( "ui-menu-item" ) 705 .removeAttr( "role" ) 706 .removeAttr( "aria-disabled" ) 707 .removeUniqueId() 708 .removeClass( "ui-state-hover" ) 709 .removeAttr( "tabIndex" ) 710 .removeAttr( "role" ) 711 .removeAttr( "aria-haspopup" ) 712 .children().each( function() { 713 var elem = $( this ); 714 if ( elem.data( "ui-menu-submenu-carat" ) ) { 715 elem.remove(); 716 } 717 }); 718 719 // Destroy menu dividers 720 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); 721 }, 722 723 _keydown: function( event ) { 724 var match, prev, character, skip, 725 preventDefault = true; 726 727 switch ( event.keyCode ) { 728 case $.ui.keyCode.PAGE_UP: 729 this.previousPage( event ); 730 break; 731 case $.ui.keyCode.PAGE_DOWN: 732 this.nextPage( event ); 733 break; 734 case $.ui.keyCode.HOME: 735 this._move( "first", "first", event ); 736 break; 737 case $.ui.keyCode.END: 738 this._move( "last", "last", event ); 739 break; 740 case $.ui.keyCode.UP: 741 this.previous( event ); 742 break; 743 case $.ui.keyCode.DOWN: 744 this.next( event ); 745 break; 746 case $.ui.keyCode.LEFT: 747 this.collapse( event ); 748 break; 749 case $.ui.keyCode.RIGHT: 750 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 751 this.expand( event ); 752 } 753 break; 754 case $.ui.keyCode.ENTER: 755 case $.ui.keyCode.SPACE: 756 this._activate( event ); 757 break; 758 case $.ui.keyCode.ESCAPE: 759 this.collapse( event ); 760 break; 761 default: 762 preventDefault = false; 763 prev = this.previousFilter || ""; 764 character = String.fromCharCode( event.keyCode ); 765 skip = false; 766 767 clearTimeout( this.filterTimer ); 768 769 if ( character === prev ) { 770 skip = true; 771 } else { 772 character = prev + character; 773 } 774 775 match = this._filterMenuItems( character ); 776 match = skip && match.index( this.active.next() ) !== -1 ? 777 this.active.nextAll( ".ui-menu-item" ) : 778 match; 779 780 // If no matches on the current filter, reset to the last character pressed 781 // to move down the menu to the first item that starts with that character 782 if ( !match.length ) { 783 character = String.fromCharCode( event.keyCode ); 784 match = this._filterMenuItems( character ); 785 } 786 787 if ( match.length ) { 788 this.focus( event, match ); 789 this.previousFilter = character; 790 this.filterTimer = this._delay(function() { 791 delete this.previousFilter; 792 }, 1000 ); 793 } else { 794 delete this.previousFilter; 795 } 796 } 797 798 if ( preventDefault ) { 799 event.preventDefault(); 800 } 801 }, 802 803 _activate: function( event ) { 804 if ( !this.active.is( ".ui-state-disabled" ) ) { 805 if ( this.active.is( "[aria-haspopup='true']" ) ) { 806 this.expand( event ); 807 } else { 808 this.select( event ); 809 } 810 } 811 }, 812 813 refresh: function() { 814 var menus, items, 815 that = this, 816 icon = this.options.icons.submenu, 817 submenus = this.element.find( this.options.menus ); 818 819 this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ); 820 821 // Initialize nested menus 822 submenus.filter( ":not(.ui-menu)" ) 823 .addClass( "ui-menu ui-widget ui-widget-content ui-front" ) 824 .hide() 825 .attr({ 826 role: this.options.role, 827 "aria-hidden": "true", 828 "aria-expanded": "false" 829 }) 830 .each(function() { 831 var menu = $( this ), 832 item = menu.parent(), 833 submenuCarat = $( "<span>" ) 834 .addClass( "ui-menu-icon ui-icon " + icon ) 835 .data( "ui-menu-submenu-carat", true ); 836 837 item 838 .attr( "aria-haspopup", "true" ) 839 .prepend( submenuCarat ); 840 menu.attr( "aria-labelledby", item.attr( "id" ) ); 841 }); 842 843 menus = submenus.add( this.element ); 844 items = menus.find( this.options.items ); 845
vendor: 10,338 bytes, lines 846-1165
846 // Initialize menu-items containing spaces and/or dashes only as dividers 847 items.not( ".ui-menu-item" ).each(function() { 848 var item = $( this ); 849 if ( that._isDivider( item ) ) { 850 item.addClass( "ui-widget-content ui-menu-divider" ); 851 } 852 }); 853 854 // Don't refresh list items that are already adapted 855 items.not( ".ui-menu-item, .ui-menu-divider" ) 856 .addClass( "ui-menu-item" ) 857 .uniqueId() 858 .attr({ 859 tabIndex: -1, 860 role: this._itemRole() 861 }); 862 863 // Add aria-disabled attribute to any disabled menu item 864 items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); 865 866 // If the active item has been removed, blur the menu 867 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 868 this.blur(); 869 } 870 }, 871 872 _itemRole: function() { 873 return { 874 menu: "menuitem", 875 listbox: "option" 876 }[ this.options.role ]; 877 }, 878 879 _setOption: function( key, value ) { 880 if ( key === "icons" ) { 881 this.element.find( ".ui-menu-icon" ) 882 .removeClass( this.options.icons.submenu ) 883 .addClass( value.submenu ); 884 } 885 if ( key === "disabled" ) { 886 this.element 887 .toggleClass( "ui-state-disabled", !!value ) 888 .attr( "aria-disabled", value ); 889 } 890 this._super( key, value ); 891 }, 892 893 focus: function( event, item ) { 894 var nested, focused; 895 this.blur( event, event && event.type === "focus" ); 896 897 this._scrollIntoView( item ); 898 899 this.active = item.first(); 900 focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" ); 901 // Only update aria-activedescendant if there's a role 902 // otherwise we assume focus is managed elsewhere 903 if ( this.options.role ) { 904 this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); 905 } 906 907 // Highlight active parent menu item, if any 908 this.active 909 .parent() 910 .closest( ".ui-menu-item" ) 911 .addClass( "ui-state-active" ); 912 913 if ( event && event.type === "keydown" ) { 914 this._close(); 915 } else { 916 this.timer = this._delay(function() { 917 this._close(); 918 }, this.delay ); 919 } 920 921 nested = item.children( ".ui-menu" ); 922 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) { 923 this._startOpening(nested); 924 } 925 this.activeMenu = item.parent(); 926 927 this._trigger( "focus", event, { item: item } ); 928 }, 929 930 _scrollIntoView: function( item ) { 931 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; 932 if ( this._hasScroll() ) { 933 borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; 934 paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; 935 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; 936 scroll = this.activeMenu.scrollTop(); 937 elementHeight = this.activeMenu.height(); 938 itemHeight = item.outerHeight(); 939 940 if ( offset < 0 ) { 941 this.activeMenu.scrollTop( scroll + offset ); 942 } else if ( offset + itemHeight > elementHeight ) { 943 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); 944 } 945 } 946 }, 947 948 blur: function( event, fromFocus ) { 949 if ( !fromFocus ) { 950 clearTimeout( this.timer ); 951 } 952 953 if ( !this.active ) { 954 return; 955 } 956 957 this.active.removeClass( "ui-state-focus" ); 958 this.active = null; 959 960 this._trigger( "blur", event, { item: this.active } ); 961 }, 962 963 _startOpening: function( submenu ) { 964 clearTimeout( this.timer ); 965 966 // Don't open if already open fixes a Firefox bug that caused a .5 pixel 967 // shift in the submenu position when mousing over the carat icon 968 if ( submenu.attr( "aria-hidden" ) !== "true" ) { 969 return; 970 } 971 972 this.timer = this._delay(function() { 973 this._close(); 974 this._open( submenu ); 975 }, this.delay ); 976 }, 977 978 _open: function( submenu ) { 979 var position = $.extend({ 980 of: this.active 981 }, this.options.position ); 982 983 clearTimeout( this.timer ); 984 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) 985 .hide() 986 .attr( "aria-hidden", "true" ); 987 988 submenu 989 .show() 990 .removeAttr( "aria-hidden" ) 991 .attr( "aria-expanded", "true" ) 992 .position( position ); 993 }, 994 995 collapseAll: function( event, all ) { 996 clearTimeout( this.timer ); 997 this.timer = this._delay(function() { 998 // If we were passed an event, look for the submenu that contains the event 999 var currentMenu = all ? this.element : 1000 $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); 1001 1002 // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway 1003 if ( !currentMenu.length ) { 1004 currentMenu = this.element; 1005 } 1006 1007 this._close( currentMenu ); 1008 1009 this.blur( event ); 1010 this.activeMenu = currentMenu; 1011 }, this.delay ); 1012 }, 1013 1014 // With no arguments, closes the currently active menu - if nothing is active 1015 // it closes all menus. If passed an argument, it will search for menus BELOW 1016 _close: function( startMenu ) { 1017 if ( !startMenu ) { 1018 startMenu = this.active ? this.active.parent() : this.element; 1019 } 1020 1021 startMenu 1022 .find( ".ui-menu" ) 1023 .hide() 1024 .attr( "aria-hidden", "true" ) 1025 .attr( "aria-expanded", "false" ) 1026 .end() 1027 .find( ".ui-state-active" ).not( ".ui-state-focus" ) 1028 .removeClass( "ui-state-active" ); 1029 }, 1030 1031 _closeOnDocumentClick: function( event ) { 1032 return !$( event.target ).closest( ".ui-menu" ).length; 1033 }, 1034 1035 _isDivider: function( item ) { 1036 1037 // Match hyphen, em dash, en dash 1038 return !/[^\-\u2014\u2013\s]/.test( item.text() ); 1039 }, 1040 1041 collapse: function( event ) { 1042 var newItem = this.active && 1043 this.active.parent().closest( ".ui-menu-item", this.element ); 1044 if ( newItem && newItem.length ) { 1045 this._close(); 1046 this.focus( event, newItem ); 1047 } 1048 }, 1049 1050 expand: function( event ) { 1051 var newItem = this.active && 1052 this.active 1053 .children( ".ui-menu " ) 1054 .find( this.options.items ) 1055 .first(); 1056 1057 if ( newItem && newItem.length ) { 1058 this._open( newItem.parent() ); 1059 1060 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT 1061 this._delay(function() { 1062 this.focus( event, newItem ); 1063 }); 1064 } 1065 }, 1066 1067 next: function( event ) { 1068 this._move( "next", "first", event ); 1069 }, 1070 1071 previous: function( event ) { 1072 this._move( "prev", "last", event ); 1073 }, 1074 1075 isFirstItem: function() { 1076 return this.active && !this.active.prevAll( ".ui-menu-item" ).length; 1077 }, 1078 1079 isLastItem: function() { 1080 return this.active && !this.active.nextAll( ".ui-menu-item" ).length; 1081 }, 1082 1083 _move: function( direction, filter, event ) { 1084 var next; 1085 if ( this.active ) { 1086 if ( direction === "first" || direction === "last" ) { 1087 next = this.active 1088 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) 1089 .eq( -1 ); 1090 } else { 1091 next = this.active 1092 [ direction + "All" ]( ".ui-menu-item" ) 1093 .eq( 0 ); 1094 } 1095 } 1096 if ( !next || !next.length || !this.active ) { 1097 next = this.activeMenu.find( this.options.items )[ filter ](); 1098 } 1099 1100 this.focus( event, next ); 1101 }, 1102 1103 nextPage: function( event ) { 1104 var item, base, height; 1105 1106 if ( !this.active ) { 1107 this.next( event ); 1108 return; 1109 } 1110 if ( this.isLastItem() ) { 1111 return; 1112 } 1113 if ( this._hasScroll() ) { 1114 base = this.active.offset().top; 1115 height = this.element.height(); 1116 this.active.nextAll( ".ui-menu-item" ).each(function() { 1117 item = $( this ); 1118 return item.offset().top - base - height < 0; 1119 }); 1120 1121 this.focus( event, item ); 1122 } else { 1123 this.focus( event, this.activeMenu.find( this.options.items ) 1124 [ !this.active ? "first" : "last" ]() ); 1125 } 1126 }, 1127 1128 previousPage: function( event ) { 1129 var item, base, height; 1130 if ( !this.active ) { 1131 this.next( event ); 1132 return; 1133 } 1134 if ( this.isFirstItem() ) { 1135 return; 1136 } 1137 if ( this._hasScroll() ) { 1138 base = this.active.offset().top; 1139 height = this.element.height(); 1140 this.active.prevAll( ".ui-menu-item" ).each(function() { 1141 item = $( this ); 1142 return item.offset().top - base + height > 0; 1143 }); 1144 1145 this.focus( event, item ); 1146 } else { 1147 this.focus( event, this.activeMenu.find( this.options.items ).first() ); 1148 } 1149 }, 1150 1151 _hasScroll: function() { 1152 return this.element.outerHeight() < this.element.prop( "scrollHeight" ); 1153 }, 1154 1155 select: function( event ) { 1156 // TODO: It should never be possible to not have an active item at this 1157 // point, but the tests don't trigger mouseenter before click. 1158 this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); 1159 var ui = { item: this.active }; 1160 if ( !this.active.has( ".ui-menu" ).length ) { 1161 this.collapseAll( event, true ); 1162 } 1163 this._trigger( "select", event, ui ); 1164 }, 1165
vendor: 5,729 bytes, lines 1166-1318
1166 _filterMenuItems: function(character) { 1167 var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ), 1168 regex = new RegExp( "^" + escapedCharacter, "i" ); 1169 1170 return this.activeMenu 1171 .find( this.options.items ) 1172 1173 // Only match on items, not dividers or other content (#10571) 1174 .filter( ".ui-menu-item" ) 1175 .filter(function() { 1176 return regex.test( $.trim( $( this ).text() ) ); 1177 }); 1178 } 1179}); 1180 1181 1182 1183/*! 1184 * jQuery UI Autocomplete 1.11.3 1185 * http://jqueryui.com 1186 * 1187 * Copyright jQuery Foundation and other contributors 1188 * Released under the MIT license. 1189 * http://jquery.org/license 1190 * 1191 * http://api.jqueryui.com/autocomplete/ 1192 */ 1193 1194 1195$.widget( "ui.autocomplete", { 1196 version: "1.11.3", 1197 defaultElement: "<input>", 1198 options: { 1199 appendTo: null, 1200 autoFocus: false, 1201 delay: 300, 1202 minLength: 1, 1203 position: { 1204 my: "left top", 1205 at: "left bottom", 1206 collision: "none" 1207 }, 1208 source: null, 1209 1210 // callbacks 1211 change: null, 1212 close: null, 1213 focus: null, 1214 open: null, 1215 response: null, 1216 search: null, 1217 select: null 1218 }, 1219 1220 requestIndex: 0, 1221 pending: 0, 1222 1223 _create: function() { 1224 // Some browsers only repeat keydown events, not keypress events, 1225 // so we use the suppressKeyPress flag to determine if we've already 1226 // handled the keydown event. #7269 1227 // Unfortunately the code for & in keypress is the same as the up arrow, 1228 // so we use the suppressKeyPressRepeat flag to avoid handling keypress 1229 // events when we know the keydown event was used to modify the 1230 // search term. #7799 1231 var suppressKeyPress, suppressKeyPressRepeat, suppressInput, 1232 nodeName = this.element[ 0 ].nodeName.toLowerCase(), 1233 isTextarea = nodeName === "textarea", 1234 isInput = nodeName === "input"; 1235 1236 this.isMultiLine = 1237 // Textareas are always multi-line 1238 isTextarea ? true : 1239 // Inputs are always single-line, even if inside a contentEditable element 1240 // IE also treats inputs as contentEditable 1241 isInput ? false : 1242 // All other element types are determined by whether or not they're contentEditable 1243 this.element.prop( "isContentEditable" ); 1244 1245 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; 1246 this.isNewMenu = true; 1247 1248 this.element 1249 .addClass( "ui-autocomplete-input" ) 1250 .attr( "autocomplete", "off" ); 1251 1252 this._on( this.element, { 1253 keydown: function( event ) { 1254 if ( this.element.prop( "readOnly" ) ) { 1255 suppressKeyPress = true; 1256 suppressInput = true; 1257 suppressKeyPressRepeat = true; 1258 return; 1259 } 1260 1261 suppressKeyPress = false; 1262 suppressInput = false; 1263 suppressKeyPressRepeat = false; 1264 var keyCode = $.ui.keyCode; 1265 switch ( event.keyCode ) { 1266 case keyCode.PAGE_UP: 1267 suppressKeyPress = true; 1268 this._move( "previousPage", event ); 1269 break; 1270 case keyCode.PAGE_DOWN: 1271 suppressKeyPress = true; 1272 this._move( "nextPage", event ); 1273 break; 1274 case keyCode.UP: 1275 suppressKeyPress = true; 1276 this._keyEvent( "previous", event ); 1277 break; 1278 case keyCode.DOWN: 1279 suppressKeyPress = true; 1280 this._keyEvent( "next", event ); 1281 break; 1282 case keyCode.ENTER: 1283 // when menu is open and has focus 1284 if ( this.menu.active ) { 1285 // #6055 - Opera still allows the keypress to occur 1286 // which causes forms to submit 1287 suppressKeyPress = true; 1288 event.preventDefault(); 1289 this.menu.select( event ); 1290 } 1291 break; 1292 case keyCode.TAB: 1293 if ( this.menu.active ) { 1294 this.menu.select( event ); 1295 } 1296 break; 1297 case keyCode.ESCAPE: 1298 if ( this.menu.element.is( ":visible" ) ) { 1299 if ( !this.isMultiLine ) { 1300 this._value( this.term ); 1301 } 1302 this.close( event ); 1303 // Different browsers have different default behavior for escape 1304 // Single press can mean undo or clear 1305 // Double press in IE means clear the whole form 1306 event.preventDefault(); 1307 } 1308 break; 1309 default: 1310 suppressKeyPressRepeat = true; 1311 // search timeout should be triggered before the input value is changed 1312 this._searchTimeout( event ); 1313 break; 1314 } 1315 }, 1316 keypress: function( event ) { 1317 if ( suppressKeyPress ) { 1318 suppressKeyPress = false;
vendor: 16,146 bytes, lines 1319-1793
1319 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 1320 event.preventDefault(); 1321 } 1322 return; 1323 } 1324 if ( suppressKeyPressRepeat ) { 1325 return; 1326 } 1327 1328 // replicate some key handlers to allow them to repeat in Firefox and Opera 1329 var keyCode = $.ui.keyCode; 1330 switch ( event.keyCode ) { 1331 case keyCode.PAGE_UP: 1332 this._move( "previousPage", event ); 1333 break; 1334 case keyCode.PAGE_DOWN: 1335 this._move( "nextPage", event ); 1336 break; 1337 case keyCode.UP: 1338 this._keyEvent( "previous", event ); 1339 break; 1340 case keyCode.DOWN: 1341 this._keyEvent( "next", event ); 1342 break; 1343 } 1344 }, 1345 input: function( event ) { 1346 if ( suppressInput ) { 1347 suppressInput = false; 1348 event.preventDefault(); 1349 return; 1350 } 1351 this._searchTimeout( event ); 1352 }, 1353 focus: function() { 1354 this.selectedItem = null; 1355 this.previous = this._value(); 1356 }, 1357 blur: function( event ) { 1358 if ( this.cancelBlur ) { 1359 delete this.cancelBlur; 1360 return; 1361 } 1362 1363 clearTimeout( this.searching ); 1364 this.close( event ); 1365 this._change( event ); 1366 } 1367 }); 1368 1369 this._initSource(); 1370 this.menu = $( "<ul>" ) 1371 .addClass( "ui-autocomplete ui-front" ) 1372 .appendTo( this._appendTo() ) 1373 .menu({ 1374 // disable ARIA support, the live region takes care of that 1375 role: null 1376 }) 1377 .hide() 1378 .menu( "instance" ); 1379 1380 this._on( this.menu.element, { 1381 mousedown: function( event ) { 1382 // prevent moving focus out of the text field 1383 event.preventDefault(); 1384 1385 // IE doesn't prevent moving focus even with event.preventDefault() 1386 // so we set a flag to know when we should ignore the blur event 1387 this.cancelBlur = true; 1388 this._delay(function() { 1389 delete this.cancelBlur; 1390 }); 1391 1392 // clicking on the scrollbar causes focus to shift to the body 1393 // but we can't detect a mouseup or a click immediately afterward 1394 // so we have to track the next mousedown and close the menu if 1395 // the user clicks somewhere outside of the autocomplete 1396 var menuElement = this.menu.element[ 0 ]; 1397 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { 1398 this._delay(function() { 1399 var that = this; 1400 this.document.one( "mousedown", function( event ) { 1401 if ( event.target !== that.element[ 0 ] && 1402 event.target !== menuElement && 1403 !$.contains( menuElement, event.target ) ) { 1404 that.close(); 1405 } 1406 }); 1407 }); 1408 } 1409 }, 1410 menufocus: function( event, ui ) { 1411 var label, item; 1412 // support: Firefox 1413 // Prevent accidental activation of menu items in Firefox (#7024 #9118) 1414 if ( this.isNewMenu ) { 1415 this.isNewMenu = false; 1416 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { 1417 this.menu.blur(); 1418 1419 this.document.one( "mousemove", function() { 1420 $( event.target ).trigger( event.originalEvent ); 1421 }); 1422 1423 return; 1424 } 1425 } 1426 1427 item = ui.item.data( "ui-autocomplete-item" ); 1428 if ( false !== this._trigger( "focus", event, { item: item } ) ) { 1429 // use value to match what will end up in the input, if it was a key event 1430 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { 1431 this._value( item.value ); 1432 } 1433 } 1434 1435 // Announce the value in the liveRegion 1436 label = ui.item.attr( "aria-label" ) || item.value; 1437 if ( label && $.trim( label ).length ) { 1438 this.liveRegion.children().hide(); 1439 $( "<div>" ).text( label ).appendTo( this.liveRegion ); 1440 } 1441 }, 1442 menuselect: function( event, ui ) { 1443 var item = ui.item.data( "ui-autocomplete-item" ), 1444 previous = this.previous; 1445 1446 // only trigger when focus was lost (click on menu) 1447 if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) { 1448 this.element.focus(); 1449 this.previous = previous; 1450 // #6109 - IE triggers two focus events and the second 1451 // is asynchronous, so we need to reset the previous 1452 // term synchronously and asynchronously :-( 1453 this._delay(function() { 1454 this.previous = previous; 1455 this.selectedItem = item; 1456 }); 1457 } 1458 1459 if ( false !== this._trigger( "select", event, { item: item } ) ) { 1460 this._value( item.value ); 1461 } 1462 // reset the term after the select event 1463 // this allows custom select handling to work properly 1464 this.term = this._value(); 1465 1466 this.close( event ); 1467 this.selectedItem = item; 1468 } 1469 }); 1470 1471 this.liveRegion = $( "<span>", { 1472 role: "status", 1473 "aria-live": "assertive", 1474 "aria-relevant": "additions" 1475 }) 1476 .addClass( "ui-helper-hidden-accessible" ) 1477 .appendTo( this.document[ 0 ].body ); 1478 1479 // turning off autocomplete prevents the browser from remembering the 1480 // value when navigating through history, so we re-enable autocomplete 1481 // if the page is unloaded before the widget is destroyed. #7790 1482 this._on( this.window, { 1483 beforeunload: function() { 1484 this.element.removeAttr( "autocomplete" ); 1485 } 1486 }); 1487 }, 1488 1489 _destroy: function() { 1490 clearTimeout( this.searching ); 1491 this.element 1492 .removeClass( "ui-autocomplete-input" ) 1493 .removeAttr( "autocomplete" ); 1494 this.menu.element.remove(); 1495 this.liveRegion.remove(); 1496 }, 1497 1498 _setOption: function( key, value ) { 1499 this._super( key, value ); 1500 if ( key === "source" ) { 1501 this._initSource(); 1502 } 1503 if ( key === "appendTo" ) { 1504 this.menu.element.appendTo( this._appendTo() ); 1505 } 1506 if ( key === "disabled" && value && this.xhr ) { 1507 this.xhr.abort(); 1508 } 1509 }, 1510 1511 _appendTo: function() { 1512 var element = this.options.appendTo; 1513 1514 if ( element ) { 1515 element = element.jquery || element.nodeType ? 1516 $( element ) : 1517 this.document.find( element ).eq( 0 ); 1518 } 1519 1520 if ( !element || !element[ 0 ] ) { 1521 element = this.element.closest( ".ui-front" ); 1522 } 1523 1524 if ( !element.length ) { 1525 element = this.document[ 0 ].body; 1526 } 1527 1528 return element; 1529 }, 1530 1531 _initSource: function() { 1532 var array, url, 1533 that = this; 1534 if ( $.isArray( this.options.source ) ) { 1535 array = this.options.source; 1536 this.source = function( request, response ) { 1537 response( $.ui.autocomplete.filter( array, request.term ) ); 1538 }; 1539 } else if ( typeof this.options.source === "string" ) { 1540 url = this.options.source; 1541 this.source = function( request, response ) { 1542 if ( that.xhr ) { 1543 that.xhr.abort(); 1544 } 1545 that.xhr = $.ajax({ 1546 url: url, 1547 data: request, 1548 dataType: "json", 1549 success: function( data ) { 1550 response( data ); 1551 }, 1552 error: function() { 1553 response([]); 1554 } 1555 }); 1556 }; 1557 } else { 1558 this.source = this.options.source; 1559 } 1560 }, 1561 1562 _searchTimeout: function( event ) { 1563 clearTimeout( this.searching ); 1564 this.searching = this._delay(function() { 1565 1566 // Search if the value has changed, or if the user retypes the same value (see #7434) 1567 var equalValues = this.term === this._value(), 1568 menuVisible = this.menu.element.is( ":visible" ), 1569 modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey; 1570 1571 if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) { 1572 this.selectedItem = null; 1573 this.search( null, event ); 1574 } 1575 }, this.options.delay ); 1576 }, 1577 1578 search: function( value, event ) { 1579 value = value != null ? value : this._value(); 1580 1581 // always save the actual value, not the one passed as an argument 1582 this.term = this._value(); 1583 1584 if ( value.length < this.options.minLength ) { 1585 return this.close( event ); 1586 } 1587 1588 if ( this._trigger( "search", event ) === false ) { 1589 return; 1590 } 1591 1592 return this._search( value ); 1593 }, 1594 1595 _search: function( value ) { 1596 this.pending++; 1597 this.element.addClass( "ui-autocomplete-loading" ); 1598 this.cancelSearch = false; 1599 1600 this.source( { term: value }, this._response() ); 1601 }, 1602 1603 _response: function() { 1604 var index = ++this.requestIndex; 1605 1606 return $.proxy(function( content ) { 1607 if ( index === this.requestIndex ) { 1608 this.__response( content ); 1609 } 1610 1611 this.pending--; 1612 if ( !this.pending ) { 1613 this.element.removeClass( "ui-autocomplete-loading" ); 1614 } 1615 }, this ); 1616 }, 1617 1618 __response: function( content ) { 1619 if ( content ) { 1620 content = this._normalize( content ); 1621 } 1622 this._trigger( "response", null, { content: content } ); 1623 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { 1624 this._suggest( content ); 1625 this._trigger( "open" ); 1626 } else { 1627 // use ._close() instead of .close() so we don't cancel future searches 1628 this._close(); 1629 } 1630 }, 1631 1632 close: function( event ) { 1633 this.cancelSearch = true; 1634 this._close( event ); 1635 }, 1636 1637 _close: function( event ) { 1638 if ( this.menu.element.is( ":visible" ) ) { 1639 this.menu.element.hide(); 1640 this.menu.blur(); 1641 this.isNewMenu = true; 1642 this._trigger( "close", event ); 1643 } 1644 }, 1645 1646 _change: function( event ) { 1647 if ( this.previous !== this._value() ) { 1648 this._trigger( "change", event, { item: this.selectedItem } ); 1649 } 1650 }, 1651 1652 _normalize: function( items ) { 1653 // assume all items have the right format when the first item is complete 1654 if ( items.length && items[ 0 ].label && items[ 0 ].value ) { 1655 return items; 1656 } 1657 return $.map( items, function( item ) { 1658 if ( typeof item === "string" ) { 1659 return { 1660 label: item, 1661 value: item 1662 }; 1663 } 1664 return $.extend( {}, item, { 1665 label: item.label || item.value, 1666 value: item.value || item.label 1667 }); 1668 }); 1669 }, 1670 1671 _suggest: function( items ) { 1672 var ul = this.menu.element.empty(); 1673 this._renderMenu( ul, items ); 1674 this.isNewMenu = true; 1675 this.menu.refresh(); 1676 1677 // size and position menu 1678 ul.show(); 1679 this._resizeMenu(); 1680 ul.position( $.extend({ 1681 of: this.element 1682 }, this.options.position ) ); 1683 1684 if ( this.options.autoFocus ) { 1685 this.menu.next(); 1686 } 1687 }, 1688 1689 _resizeMenu: function() { 1690 var ul = this.menu.element; 1691 ul.outerWidth( Math.max( 1692 // Firefox wraps long text (possibly a rounding bug) 1693 // so we add 1px to avoid the wrapping (#7513) 1694 ul.width( "" ).outerWidth() + 1, 1695 this.element.outerWidth() 1696 ) ); 1697 }, 1698 1699 _renderMenu: function( ul, items ) { 1700 var that = this; 1701 $.each( items, function( index, item ) { 1702 that._renderItemData( ul, item ); 1703 }); 1704 }, 1705 1706 _renderItemData: function( ul, item ) { 1707 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); 1708 }, 1709 1710 _renderItem: function( ul, item ) { 1711 return $( "<li>" ).text( item.label ).appendTo( ul ); 1712 }, 1713 1714 _move: function( direction, event ) { 1715 if ( !this.menu.element.is( ":visible" ) ) { 1716 this.search( null, event ); 1717 return; 1718 } 1719 if ( this.menu.isFirstItem() && /^previous/.test( direction ) || 1720 this.menu.isLastItem() && /^next/.test( direction ) ) { 1721 1722 if ( !this.isMultiLine ) { 1723 this._value( this.term ); 1724 } 1725 1726 this.menu.blur(); 1727 return; 1728 } 1729 this.menu[ direction ]( event ); 1730 }, 1731 1732 widget: function() { 1733 return this.menu.element; 1734 }, 1735 1736 _value: function() { 1737 return this.valueMethod.apply( this.element, arguments ); 1738 }, 1739 1740 _keyEvent: function( keyEvent, event ) { 1741 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 1742 this._move( keyEvent, event ); 1743 1744 // prevents moving cursor to beginning/end of the text field in some browsers 1745 event.preventDefault(); 1746 } 1747 } 1748}); 1749 1750$.extend( $.ui.autocomplete, { 1751 escapeRegex: function( value ) { 1752 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); 1753 }, 1754 filter: function( array, term ) { 1755 var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" ); 1756 return $.grep( array, function( value ) { 1757 return matcher.test( value.label || value.value || value ); 1758 }); 1759 } 1760}); 1761 1762// live region extension, adding a `messages` option 1763// NOTE: This is an experimental API. We are still investigating 1764// a full solution for string manipulation and internationalization. 1765$.widget( "ui.autocomplete", $.ui.autocomplete, { 1766 options: { 1767 messages: { 1768 noResults: "No search results.", 1769 results: function( amount ) { 1770 return amount + ( amount > 1 ? " results are" : " result is" ) + 1771 " available, use up and down arrow keys to navigate."; 1772 } 1773 } 1774 }, 1775 1776 __response: function( content ) { 1777 var message; 1778 this._superApply( arguments ); 1779 if ( this.options.disabled || this.cancelSearch ) { 1780 return; 1781 } 1782 if ( content && content.length ) { 1783 message = this.options.messages.results( content.length ); 1784 } else { 1785 message = this.options.messages.noResults; 1786 } 1787 this.liveRegion.children().hide(); 1788 $( "<div>" ).text( message ).appendTo( this.liveRegion ); 1789 } 1790}); 1791 1792var autocomplete = $.ui.autocomplete; 1793
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.