diff options
Diffstat (limited to 'www/js/jquery-ui-1.8.5/jquery.ui.autocomplete.js')
| -rw-r--r-- | www/js/jquery-ui-1.8.5/jquery.ui.autocomplete.js | 555 | 
1 files changed, 555 insertions, 0 deletions
| diff --git a/www/js/jquery-ui-1.8.5/jquery.ui.autocomplete.js b/www/js/jquery-ui-1.8.5/jquery.ui.autocomplete.js new file mode 100644 index 0000000..105f7ca --- /dev/null +++ b/www/js/jquery-ui-1.8.5/jquery.ui.autocomplete.js @@ -0,0 +1,555 @@ +/* + * 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 = $( "<ul></ul>" ) +			.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 $( "<li></li>" ) +			.data( "item.autocomplete", item ) +			.append( $( "<a></a>" ).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)); | 
