/*! * jQuery UI 1.8.5 * * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * http://docs.jquery.com/UI */ (function( $, undefined ) { // prevent duplicate loading // this is only a problem because we proxy existing functions // and we don't want to double proxy them $.ui = $.ui || {}; if ( $.ui.version ) { return; } $.extend( $.ui, { version: "1.8.5", keyCode: { ALT: 18, BACKSPACE: 8, CAPS_LOCK: 20, COMMA: 188, COMMAND: 91, COMMAND_LEFT: 91, // COMMAND COMMAND_RIGHT: 93, CONTROL: 17, DELETE: 46, DOWN: 40, END: 35, ENTER: 13, ESCAPE: 27, HOME: 36, INSERT: 45, LEFT: 37, MENU: 93, // COMMAND_RIGHT NUMPAD_ADD: 107, NUMPAD_DECIMAL: 110, NUMPAD_DIVIDE: 111, NUMPAD_ENTER: 108, NUMPAD_MULTIPLY: 106, NUMPAD_SUBTRACT: 109, PAGE_DOWN: 34, PAGE_UP: 33, PERIOD: 190, RIGHT: 39, SHIFT: 16, SPACE: 32, TAB: 9, UP: 38, WINDOWS: 91 // COMMAND } }); // plugins $.fn.extend({ _focus: $.fn.focus, focus: function( delay, fn ) { return typeof delay === "number" ? this.each(function() { var elem = this; setTimeout(function() { $( elem ).focus(); if ( fn ) { fn.call( elem ); } }, delay ); }) : this._focus.apply( this, arguments ); }, scrollParent: function() { var scrollParent; if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { scrollParent = this.parents().filter(function() { return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); }).eq(0); } else { scrollParent = this.parents().filter(function() { return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); }).eq(0); } return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent; }, zIndex: function( zIndex ) { if ( zIndex !== undefined ) { return this.css( "zIndex", zIndex ); } if ( this.length ) { var elem = $( this[ 0 ] ), position, value; while ( elem.length && elem[ 0 ] !== document ) { // Ignore z-index if position is set to a value where z-index is ignored by the browser // This makes behavior of this function consistent across browsers // WebKit always returns auto if the element is positioned position = elem.css( "position" ); if ( position === "absolute" || position === "relative" || position === "fixed" ) { // IE returns 0 when zIndex is not specified // other browsers return a string // we ignore the case of nested elements with an explicit value of 0 //
value = parseInt( elem.css( "zIndex" ) ); if ( !isNaN( value ) && value != 0 ) { return value; } } elem = elem.parent(); } } return 0; }, disableSelection: function() { return this.bind( "mousedown.ui-disableSelection selectstart.ui-disableSelection", function( event ) { event.preventDefault(); }); }, enableSelection: function() { return this.unbind( ".ui-disableSelection" ); } }); $.each( [ "Width", "Height" ], function( i, name ) { var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], type = name.toLowerCase(), orig = { innerWidth: $.fn.innerWidth, innerHeight: $.fn.innerHeight, outerWidth: $.fn.outerWidth, outerHeight: $.fn.outerHeight }; function reduce( elem, size, border, margin ) { $.each( side, function() { size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0; if ( border ) { size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0; } if ( margin ) { size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0; } }); return size; } $.fn[ "inner" + name ] = function( size ) { if ( size === undefined ) { return orig[ "inner" + name ].call( this ); } return this.each(function() { $.style( this, type, reduce( this, size ) + "px" ); }); }; $.fn[ "outer" + name] = function( size, margin ) { if ( typeof size !== "number" ) { return orig[ "outer" + name ].call( this, size ); } return this.each(function() { $.style( this, type, reduce( this, size, true, margin ) + "px" ); }); }; }); // selectors function visible( element ) { return !$( element ).parents().andSelf().filter(function() { return $.curCSS( this, "visibility" ) === "hidden" || $.expr.filters.hidden( this ); }).length; } $.extend( $.expr[ ":" ], { data: function( elem, i, match ) { return !!$.data( elem, match[ 3 ] ); }, focusable: function( element ) { var nodeName = element.nodeName.toLowerCase(), tabIndex = $.attr( element, "tabindex" ); if ( "area" === nodeName ) { var map = element.parentNode, mapName = map.name, img; if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { return false; } img = $( "img[usemap=#" + mapName + "]" )[0]; return !!img && visible( img ); } return ( /input|select|textarea|button|object/.test( nodeName ) ? !element.disabled : "a" == nodeName ? element.href || !isNaN( tabIndex ) : !isNaN( tabIndex )) // the element and all of its ancestors must be visible && visible( element ); }, tabbable: function( element ) { var tabIndex = $.attr( element, "tabindex" ); return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" ); } }); // support $(function() { var div = document.createElement( "div" ), body = document.body; $.extend( div.style, { minHeight: "100px", height: "auto", padding: 0, borderWidth: 0 }); $.support.minHeight = body.appendChild( div ).offsetHeight === 100; // set display to none to avoid a layout bug in IE // http://dev.jquery.com/ticket/4014 body.removeChild( div ).style.display = "none"; }); // deprecated $.extend( $.ui, { // $.ui.plugin is deprecated. Use the proxy pattern instead. plugin: { add: function( module, option, set ) { var proto = $.ui[ module ].prototype; for ( var i in set ) { proto.plugins[ i ] = proto.plugins[ i ] || []; proto.plugins[ i ].push( [ option, set[ i ] ] ); } }, call: function( instance, name, args ) { var set = instance.plugins[ name ]; if ( !set || !instance.element[ 0 ].parentNode ) { return; } for ( var i = 0; i < set.length; i++ ) { if ( instance.options[ set[ i ][ 0 ] ] ) { set[ i ][ 1 ].apply( instance.element, args ); } } } }, // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains() contains: function( a, b ) { return document.compareDocumentPosition ? a.compareDocumentPosition( b ) & 16 : a !== b && a.contains( b ); }, // only used by resizable hasScroll: function( el, a ) { //If overflow is hidden, the element might have extra content, but the user wants to hide it if ( $( el ).css( "overflow" ) === "hidden") { return false; } var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", has = false; if ( el[ scroll ] > 0 ) { return true; } // TODO: determine which cases actually cause this to happen // if the element doesn't have the scroll set, see if it's possible to // set the scroll el[ scroll ] = 1; has = ( el[ scroll ] > 0 ); el[ scroll ] = 0; return has; }, // these are odd functions, fix the API or move into individual plugins isOverAxis: function( x, reference, size ) { //Determines when x coordinate is over "b" element axis return ( x > reference ) && ( x < ( reference + size ) ); }, isOver: function( y, x, top, left, height, width ) { //Determines when x, y coordinates is over "b" element return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width ); } }); })( jQuery ); /*! * jQuery UI Widget 1.8.5 * * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * http://docs.jquery.com/UI/Widget */ (function( $, undefined ) { // jQuery 1.4+ if ( $.cleanData ) { var _cleanData = $.cleanData; $.cleanData = function( elems ) { for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { $( elem ).triggerHandler( "remove" ); } _cleanData( elems ); }; } else { var _remove = $.fn.remove; $.fn.remove = function( selector, keepData ) { return this.each(function() { if ( !keepData ) { if ( !selector || $.filter( selector, [ this ] ).length ) { $( "*", this ).add( [ this ] ).each(function() { $( this ).triggerHandler( "remove" ); }); } } return _remove.call( $(this), selector, keepData ); }); }; } $.widget = function( name, base, prototype ) { var namespace = name.split( "." )[ 0 ], fullName; name = name.split( "." )[ 1 ]; fullName = namespace + "-" + name; if ( !prototype ) { prototype = base; base = $.Widget; } // create selector for plugin $.expr[ ":" ][ fullName ] = function( elem ) { return !!$.data( elem, name ); }; $[ namespace ] = $[ namespace ] || {}; $[ namespace ][ name ] = function( options, element ) { // allow instantiation without initializing for simple inheritance if ( arguments.length ) { this._createWidget( options, element ); } }; var basePrototype = new base(); // we need to make the options hash a property directly on the new instance // otherwise we'll modify the options hash on the prototype that we're // inheriting from // $.each( basePrototype, function( key, val ) { // if ( $.isPlainObject(val) ) { // basePrototype[ key ] = $.extend( {}, val ); // } // }); basePrototype.options = $.extend( true, {}, basePrototype.options ); $[ namespace ][ name ].prototype = $.extend( true, basePrototype, { namespace: namespace, widgetName: name, widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, widgetBaseClass: fullName }, prototype ); $.widget.bridge( name, $[ namespace ][ name ] ); }; $.widget.bridge = function( name, object ) { $.fn[ name ] = function( options ) { var isMethodCall = typeof options === "string", args = Array.prototype.slice.call( arguments, 1 ), returnValue = this; // allow multiple hashes to be passed on init options = !isMethodCall && args.length ? $.extend.apply( null, [ true, options ].concat(args) ) : options; // prevent calls to internal methods if ( isMethodCall && options.substring( 0, 1 ) === "_" ) { return returnValue; } if ( isMethodCall ) { this.each(function() { var instance = $.data( this, name ); if ( !instance ) { throw "cannot call methods on " + name + " prior to initialization; " + "attempted to call method '" + options + "'"; } if ( !$.isFunction( instance[options] ) ) { throw "no such method '" + options + "' for " + name + " widget instance"; } var methodValue = instance[ options ].apply( instance, args ); if ( methodValue !== instance && methodValue !== undefined ) { returnValue = methodValue; return false; } }); } else { this.each(function() { var instance = $.data( this, name ); if ( instance ) { instance.option( options || {} )._init(); } else { $.data( this, name, new object( options, this ) ); } }); } return returnValue; }; }; $.Widget = function( options, element ) { // allow instantiation without initializing for simple inheritance if ( arguments.length ) { this._createWidget( options, element ); } }; $.Widget.prototype = { widgetName: "widget", widgetEventPrefix: "", options: { disabled: false }, _createWidget: function( options, element ) { // $.widget.bridge stores the plugin instance, but we do it anyway // so that it's stored even before the _create function runs $.data( element, this.widgetName, this ); this.element = $( element ); this.options = $.extend( true, {}, this.options, $.metadata && $.metadata.get( element )[ this.widgetName ], options ); var self = this; this.element.bind( "remove." + this.widgetName, function() { self.destroy(); }); this._create(); this._init(); }, _create: function() {}, _init: function() {}, destroy: function() { this.element .unbind( "." + this.widgetName ) .removeData( this.widgetName ); this.widget() .unbind( "." + this.widgetName ) .removeAttr( "aria-disabled" ) .removeClass( this.widgetBaseClass + "-disabled " + "ui-state-disabled" ); }, widget: function() { return this.element; }, option: function( key, value ) { var options = key, self = this; if ( arguments.length === 0 ) { // don't return a reference to the internal hash return $.extend( {}, self.options ); } if (typeof key === "string" ) { if ( value === undefined ) { return this.options[ key ]; } options = {}; options[ key ] = value; } $.each( options, function( key, value ) { self._setOption( key, value ); }); return self; }, _setOption: function( key, value ) { this.options[ key ] = value; if ( key === "disabled" ) { this.widget() [ value ? "addClass" : "removeClass"]( this.widgetBaseClass + "-disabled" + " " + "ui-state-disabled" ) .attr( "aria-disabled", value ); } return this; }, enable: function() { return this._setOption( "disabled", false ); }, disable: function() { return this._setOption( "disabled", true ); }, _trigger: function( type, event, data ) { var callback = this.options[ type ]; event = $.Event( event ); event.type = ( type === this.widgetEventPrefix ? type : this.widgetEventPrefix + type ).toLowerCase(); data = data || {}; // copy original event properties over to the new event // this would happen if we could call $.event.fix instead of $.Event // but we don't have a way to force an event to be fixed multiple times if ( event.originalEvent ) { for ( var i = $.event.props.length, prop; i; ) { prop = $.event.props[ --i ]; event[ prop ] = event.originalEvent[ prop ]; } } this.element.trigger( event, data ); return !( $.isFunction(callback) && callback.call( this.element[0], event, data ) === false || event.isDefaultPrevented() ); } }; })( jQuery ); /* * jQuery UI Position 1.8.5 * * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * http://docs.jquery.com/UI/Position */ (function( $, undefined ) { $.ui = $.ui || {}; var horizontalPositions = /left|center|right/, verticalPositions = /top|center|bottom/, center = "center", _position = $.fn.position, _offset = $.fn.offset; $.fn.position = function( options ) { if ( !options || !options.of ) { return _position.apply( this, arguments ); } // make a copy, we don't want to modify arguments options = $.extend( {}, options ); var target = $( options.of ), targetElem = target[0], collision = ( options.collision || "flip" ).split( " " ), offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ], targetWidth, targetHeight, basePosition; if ( targetElem.nodeType === 9 ) { targetWidth = target.width(); targetHeight = target.height(); basePosition = { top: 0, left: 0 }; } else if ( targetElem.scrollTo && targetElem.document ) { targetWidth = target.width(); targetHeight = target.height(); basePosition = { top: target.scrollTop(), left: target.scrollLeft() }; } else if ( targetElem.preventDefault ) { // force left top to allow flipping options.at = "left top"; targetWidth = targetHeight = 0; basePosition = { top: options.of.pageY, left: options.of.pageX }; } else { targetWidth = target.outerWidth(); targetHeight = target.outerHeight(); basePosition = target.offset(); } // force my and at to have valid horizontal and veritcal positions // if a value is missing or invalid, it will be converted to center $.each( [ "my", "at" ], function() { var pos = ( options[this] || "" ).split( " " ); if ( pos.length === 1) { pos = horizontalPositions.test( pos[0] ) ? pos.concat( [center] ) : verticalPositions.test( pos[0] ) ? [ center ].concat( pos ) : [ center, center ]; } pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center; pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center; options[ this ] = pos; }); // normalize collision option if ( collision.length === 1 ) { collision[ 1 ] = collision[ 0 ]; } // normalize offset option offset[ 0 ] = parseInt( offset[0], 10 ) || 0; if ( offset.length === 1 ) { offset[ 1 ] = offset[ 0 ]; } offset[ 1 ] = parseInt( offset[1], 10 ) || 0; if ( options.at[0] === "right" ) { basePosition.left += targetWidth; } else if (options.at[0] === center ) { basePosition.left += targetWidth / 2; } if ( options.at[1] === "bottom" ) { basePosition.top += targetHeight; } else if ( options.at[1] === center ) { basePosition.top += targetHeight / 2; } basePosition.left += offset[ 0 ]; basePosition.top += offset[ 1 ]; return this.each(function() { var elem = $( this ), elemWidth = elem.outerWidth(), elemHeight = elem.outerHeight(), marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0, marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0, collisionWidth = elemWidth + marginLeft + parseInt( $.curCSS( this, "marginRight", true ) ) || 0, collisionHeight = elemHeight + marginTop + parseInt( $.curCSS( this, "marginBottom", true ) ) || 0, position = $.extend( {}, basePosition ), collisionPosition; if ( options.my[0] === "right" ) { position.left -= elemWidth; } else if ( options.my[0] === center ) { position.left -= elemWidth / 2; } if ( options.my[1] === "bottom" ) { position.top -= elemHeight; } else if ( options.my[1] === center ) { position.top -= elemHeight / 2; } // prevent fractions (see #5280) position.left = parseInt( position.left ); position.top = parseInt( position.top ); collisionPosition = { left: position.left - marginLeft, top: position.top - marginTop }; $.each( [ "left", "top" ], function( i, dir ) { if ( $.ui.position[ collision[i] ] ) { $.ui.position[ collision[i] ][ dir ]( position, { targetWidth: targetWidth, targetHeight: targetHeight, elemWidth: elemWidth, elemHeight: elemHeight, collisionPosition: collisionPosition, collisionWidth: collisionWidth, collisionHeight: collisionHeight, offset: offset, my: options.my, at: options.at }); } }); if ( $.fn.bgiframe ) { elem.bgiframe(); } elem.offset( $.extend( position, { using: options.using } ) ); }); }; $.ui.position = { fit: { left: function( position, data ) { var win = $( window ), over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(); position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left ); }, top: function( position, data ) { var win = $( window ), over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(); position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top ); } }, flip: { left: function( position, data ) { if ( data.at[0] === center ) { return; } var win = $( window ), over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(), myOffset = data.my[ 0 ] === "left" ? -data.elemWidth : data.my[ 0 ] === "right" ? data.elemWidth : 0, atOffset = data.at[ 0 ] === "left" ? data.targetWidth : -data.targetWidth, offset = -2 * data.offset[ 0 ]; position.left += data.collisionPosition.left < 0 ? myOffset + atOffset + offset : over > 0 ? myOffset + atOffset + offset : 0; }, top: function( position, data ) { if ( data.at[1] === center ) { return; } var win = $( window ), over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(), myOffset = data.my[ 1 ] === "top" ? -data.elemHeight : data.my[ 1 ] === "bottom" ? data.elemHeight : 0, atOffset = data.at[ 1 ] === "top" ? data.targetHeight : -data.targetHeight, offset = -2 * data.offset[ 1 ]; position.top += data.collisionPosition.top < 0 ? myOffset + atOffset + offset : over > 0 ? myOffset + atOffset + offset : 0; } } }; // offset setter from jQuery 1.4 if ( !$.offset.setOffset ) { $.offset.setOffset = function( elem, options ) { // set position first, in-case top/left are set even on static elem if ( /static/.test( $.curCSS( elem, "position" ) ) ) { elem.style.position = "relative"; } var curElem = $( elem ), curOffset = curElem.offset(), curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0, curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0, props = { top: (options.top - curOffset.top) + curTop, left: (options.left - curOffset.left) + curLeft }; if ( 'using' in options ) { options.using.call( elem, props ); } else { curElem.css( props ); } }; $.fn.offset = function( options ) { var elem = this[ 0 ]; if ( !elem || !elem.ownerDocument ) { return null; } if ( options ) { return this.each(function() { $.offset.setOffset( this, options ); }); } return _offset.call( this ); }; } }( jQuery )); /* * jQuery UI Autocomplete 1.8.5 * * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * http://docs.jquery.com/UI/Autocomplete * * Depends: * jquery.ui.core.js * jquery.ui.widget.js * jquery.ui.position.js */ (function( $, undefined ) { $.widget( "ui.autocomplete", { options: { appendTo: "body", delay: 300, minLength: 1, position: { my: "left top", at: "left bottom", collision: "none" }, source: null }, _create: function() { var self = this, doc = this.element[ 0 ].ownerDocument; this.element .addClass( "ui-autocomplete-input" ) .attr( "autocomplete", "off" ) // TODO verify these actually work as intended .attr({ role: "textbox", "aria-autocomplete": "list", "aria-haspopup": "true" }) .bind( "keydown.autocomplete", function( event ) { if ( self.options.disabled ) { return; } var keyCode = $.ui.keyCode; switch( event.keyCode ) { case keyCode.PAGE_UP: self._move( "previousPage", event ); break; case keyCode.PAGE_DOWN: self._move( "nextPage", event ); break; case keyCode.UP: self._move( "previous", event ); // prevent moving cursor to beginning of text field in some browsers event.preventDefault(); break; case keyCode.DOWN: self._move( "next", event ); // prevent moving cursor to end of text field in some browsers event.preventDefault(); break; case keyCode.ENTER: case keyCode.NUMPAD_ENTER: // when menu is open or has focus if ( self.menu.element.is( ":visible" ) ) { event.preventDefault(); } //passthrough - ENTER and TAB both select the current element case keyCode.TAB: if ( !self.menu.active ) { return; } self.menu.select( event ); break; case keyCode.ESCAPE: self.element.val( self.term ); self.close( event ); break; default: // keypress is triggered before the input value is changed clearTimeout( self.searching ); self.searching = setTimeout(function() { // only search if the value has changed if ( self.term != self.element.val() ) { self.selectedItem = null; self.search( null, event ); } }, self.options.delay ); break; } }) .bind( "focus.autocomplete", function() { if ( self.options.disabled ) { return; } self.selectedItem = null; self.previous = self.element.val(); }) .bind( "blur.autocomplete", function( event ) { if ( self.options.disabled ) { return; } clearTimeout( self.searching ); // clicks on the menu (or a button to trigger a search) will cause a blur event self.closing = setTimeout(function() { self.close( event ); self._change( event ); }, 150 ); }); this._initSource(); this.response = function() { return self._response.apply( self, arguments ); }; this.menu = $( "" ) .addClass( "ui-autocomplete" ) .appendTo( $( this.options.appendTo || "body", doc )[0] ) // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown) .mousedown(function( event ) { // clicking on the scrollbar causes focus to shift to the body // but we can't detect a mouseup or a click immediately afterward // so we have to track the next mousedown and close the menu if // the user clicks somewhere outside of the autocomplete var menuElement = self.menu.element[ 0 ]; if ( event.target === menuElement ) { setTimeout(function() { $( document ).one( 'mousedown', function( event ) { if ( event.target !== self.element[ 0 ] && event.target !== menuElement && !$.ui.contains( menuElement, event.target ) ) { self.close(); } }); }, 1 ); } // use another timeout to make sure the blur-event-handler on the input was already triggered setTimeout(function() { clearTimeout( self.closing ); }, 13); }) .menu({ focus: function( event, ui ) { var item = ui.item.data( "item.autocomplete" ); if ( false !== self._trigger( "focus", null, { item: item } ) ) { // use value to match what will end up in the input, if it was a key event if ( /^key/.test(event.originalEvent.type) ) { self.element.val( item.value ); } } }, selected: function( event, ui ) { var item = ui.item.data( "item.autocomplete" ), previous = self.previous; // only trigger when focus was lost (click on menu) if ( self.element[0] !== doc.activeElement ) { self.element.focus(); self.previous = previous; } if ( false !== self._trigger( "select", event, { item: item } ) ) { self.term = item.value; self.element.val( item.value ); } self.close( event ); self.selectedItem = item; }, blur: function( event, ui ) { // don't set the value of the text field if it's already correct // this prevents moving the cursor unnecessarily if ( self.menu.element.is(":visible") && ( self.element.val() !== self.term ) ) { self.element.val( self.term ); } } }) .zIndex( this.element.zIndex() + 1 ) // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 .css({ top: 0, left: 0 }) .hide() .data( "menu" ); if ( $.fn.bgiframe ) { this.menu.element.bgiframe(); } }, destroy: function() { this.element .removeClass( "ui-autocomplete-input" ) .removeAttr( "autocomplete" ) .removeAttr( "role" ) .removeAttr( "aria-autocomplete" ) .removeAttr( "aria-haspopup" ); this.menu.element.remove(); $.Widget.prototype.destroy.call( this ); }, _setOption: function( key, value ) { $.Widget.prototype._setOption.apply( this, arguments ); if ( key === "source" ) { this._initSource(); } if ( key === "appendTo" ) { this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] ) } }, _initSource: function() { var self = this, array, url; if ( $.isArray(this.options.source) ) { array = this.options.source; this.source = function( request, response ) { response( $.ui.autocomplete.filter(array, request.term) ); }; } else if ( typeof this.options.source === "string" ) { url = this.options.source; this.source = function( request, response ) { if (self.xhr) { self.xhr.abort(); } self.xhr = $.getJSON( url, request, function( data, status, xhr ) { if ( xhr === self.xhr ) { response( data ); } self.xhr = null; }); }; } else { this.source = this.options.source; } }, search: function( value, event ) { value = value != null ? value : this.element.val(); // always save the actual value, not the one passed as an argument this.term = this.element.val(); if ( value.length < this.options.minLength ) { return this.close( event ); } clearTimeout( this.closing ); if ( this._trigger("search") === false ) { return; } return this._search( value ); }, _search: function( value ) { this.element.addClass( "ui-autocomplete-loading" ); this.source( { term: value }, this.response ); }, _response: function( content ) { if ( content.length ) { content = this._normalize( content ); this._suggest( content ); this._trigger( "open" ); } else { this.close(); } this.element.removeClass( "ui-autocomplete-loading" ); }, close: function( event ) { clearTimeout( this.closing ); if ( this.menu.element.is(":visible") ) { this._trigger( "close", event ); this.menu.element.hide(); this.menu.deactivate(); } }, _change: function( event ) { if ( this.previous !== this.element.val() ) { this._trigger( "change", event, { item: this.selectedItem } ); } }, _normalize: function( items ) { // assume all items have the right format when the first item is complete if ( items.length && items[0].label && items[0].value ) { return items; } return $.map( items, function(item) { if ( typeof item === "string" ) { return { label: item, value: item }; } return $.extend({ label: item.label || item.value, value: item.value || item.label }, item ); }); }, _suggest: function( items ) { var ul = this.menu.element .empty() .zIndex( this.element.zIndex() + 1 ), menuWidth, textWidth; this._renderMenu( ul, items ); // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate this.menu.deactivate(); this.menu.refresh(); this.menu.element.show().position( $.extend({ of: this.element }, this.options.position )); menuWidth = ul.width( "" ).outerWidth(); textWidth = this.element.outerWidth(); ul.outerWidth( Math.max( menuWidth, textWidth ) ); }, _renderMenu: function( ul, items ) { var self = this; $.each( items, function( index, item ) { self._renderItem( ul, item ); }); }, _renderItem: function( ul, item) { return $( "
  • " ) .data( "item.autocomplete", item ) .append( $( "" ).text( item.label ) ) .appendTo( ul ); }, _move: function( direction, event ) { if ( !this.menu.element.is(":visible") ) { this.search( null, event ); return; } if ( this.menu.first() && /^previous/.test(direction) || this.menu.last() && /^next/.test(direction) ) { this.element.val( this.term ); this.menu.deactivate(); return; } this.menu[ direction ]( event ); }, widget: function() { return this.menu.element; } }); $.extend( $.ui.autocomplete, { escapeRegex: function( value ) { return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); }, filter: function(array, term) { var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); return $.grep( array, function(value) { return matcher.test( value.label || value.value || value ); }); } }); }( jQuery )); /* * jQuery UI Menu (not officially released) * * This widget isn't yet finished and the API is subject to change. We plan to finish * it for the next release. You're welcome to give it a try anyway and give us feedback, * as long as you're okay with migrating your code later on. We can help with that, too. * * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * http://docs.jquery.com/UI/Menu * * Depends: * jquery.ui.core.js * jquery.ui.widget.js */ (function($) { $.widget("ui.menu", { _create: function() { var self = this; this.element .addClass("ui-menu ui-widget ui-widget-content ui-corner-all") .attr({ role: "listbox", "aria-activedescendant": "ui-active-menuitem" }) .click(function( event ) { if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) { return; } // temporary event.preventDefault(); self.select( event ); }); this.refresh(); }, refresh: function() { var self = this; // don't refresh list items that are already adapted var items = this.element.children("li:not(.ui-menu-item):has(a)") .addClass("ui-menu-item") .attr("role", "menuitem"); items.children("a") .addClass("ui-corner-all") .attr("tabindex", -1) // mouseenter doesn't work with event delegation .mouseenter(function( event ) { self.activate( event, $(this).parent() ); }) .mouseleave(function() { self.deactivate(); }); }, activate: function( event, item ) { this.deactivate(); if (this.hasScroll()) { var offset = item.offset().top - this.element.offset().top, scroll = this.element.attr("scrollTop"), elementHeight = this.element.height(); if (offset < 0) { this.element.attr("scrollTop", scroll + offset); } else if (offset >= elementHeight) { this.element.attr("scrollTop", scroll + offset - elementHeight + item.height()); } } this.active = item.eq(0) .children("a") .addClass("ui-state-hover") .attr("id", "ui-active-menuitem") .end(); this._trigger("focus", event, { item: item }); }, deactivate: function() { if (!this.active) { return; } this.active.children("a") .removeClass("ui-state-hover") .removeAttr("id"); this._trigger("blur"); this.active = null; }, next: function(event) { this.move("next", ".ui-menu-item:first", event); }, previous: function(event) { this.move("prev", ".ui-menu-item:last", event); }, first: function() { return this.active && !this.active.prevAll(".ui-menu-item").length; }, last: function() { return this.active && !this.active.nextAll(".ui-menu-item").length; }, move: function(direction, edge, event) { if (!this.active) { this.activate(event, this.element.children(edge)); return; } var next = this.active[direction + "All"](".ui-menu-item").eq(0); if (next.length) { this.activate(event, next); } else { this.activate(event, this.element.children(edge)); } }, // TODO merge with previousPage nextPage: function(event) { if (this.hasScroll()) { // TODO merge with no-scroll-else if (!this.active || this.last()) { this.activate(event, this.element.children(":first")); return; } var base = this.active.offset().top, height = this.element.height(), result = this.element.children("li").filter(function() { var close = $(this).offset().top - base - height + $(this).height(); // TODO improve approximation return close < 10 && close > -10; }); // TODO try to catch this earlier when scrollTop indicates the last page anyway if (!result.length) { result = this.element.children(":last"); } this.activate(event, result); } else { this.activate(event, this.element.children(!this.active || this.last() ? ":first" : ":last")); } }, // TODO merge with nextPage previousPage: function(event) { if (this.hasScroll()) { // TODO merge with no-scroll-else if (!this.active || this.first()) { this.activate(event, this.element.children(":last")); return; } var base = this.active.offset().top, height = this.element.height(); result = this.element.children("li").filter(function() { var close = $(this).offset().top - base + height - $(this).height(); // TODO improve approximation return close < 10 && close > -10; }); // TODO try to catch this earlier when scrollTop indicates the last page anyway if (!result.length) { result = this.element.children(":first"); } this.activate(event, result); } else { this.activate(event, this.element.children(!this.active || this.first() ? ":last" : ":first")); } }, hasScroll: function() { return this.element.height() < this.element.attr("scrollHeight"); }, select: function( event ) { this._trigger("selected", event, { item: this.active }); } }); }(jQuery));