📄 autocomplete.js
字号:
}
};
/**
* Makes query request to the data source.
*
* @param {string} sQuery Query string.
* @private
*/
YAHOO.widget.AutoComplete.prototype._sendQuery = function(sQuery) {
// Delimiter has been enabled
var aDelimChar = (this.delimChar) ? this.delimChar : null;
if(aDelimChar) {
// Loop through all possible delimiters and find the latest one
// A " " may be a false positive if they are defined as delimiters AND
// are used to separate delimited queries
var nDelimIndex = -1;
for(var i = aDelimChar.length-1; i >= 0; i--) {
var nNewIndex = sQuery.lastIndexOf(aDelimChar[i]);
if(nNewIndex > nDelimIndex) {
nDelimIndex = nNewIndex;
}
}
// If we think the last delimiter is a space (" "), make sure it is NOT
// a false positive by also checking the char directly before it
if(aDelimChar[i] == " ") {
for (var j = aDelimChar.length-1; j >= 0; j--) {
if(sQuery[nDelimIndex - 1] == aDelimChar[j]) {
nDelimIndex--;
break;
}
}
}
// A delimiter has been found so extract the latest query
if (nDelimIndex > -1) {
var nQueryStart = nDelimIndex + 1;
// Trim any white space from the beginning...
while(sQuery.charAt(nQueryStart) == " ") {
nQueryStart += 1;
}
// ...and save the rest of the string for later
this._sSavedQuery = sQuery.substring(0,nQueryStart);
// Here is the query itself
sQuery = sQuery.substr(nQueryStart);
}
else if(sQuery.indexOf(this._sSavedQuery) < 0){
this._sSavedQuery = null;
}
}
// Don't search queries that are too short
if (sQuery.length < this.minQueryLength) {
if (this._nDelayID != -1) {
clearTimeout(this._nDelayID);
}
this._clearList();
return;
}
sQuery = encodeURIComponent(sQuery);
this._nDelayID = -1; // Reset timeout ID because request has been made
this.dataRequestEvent.fire(this, sQuery);
this.dataSource.getResults(this._populateList, sQuery, this);
};
/**
* Hides all visuals related to the array of <li> elements in the container.
*
* @private
*/
YAHOO.widget.AutoComplete.prototype._clearList = function() {
this._oContainer._oContent.scrollTop = 0;
var aItems = this._aListItems;
if(aItems && (aItems.length > 0)) {
for(var i = aItems.length-1; i >= 0 ; i--) {
aItems[i].style.display = "none";
}
}
if (this._oCurItem) {
this._toggleHighlight(this._oCurItem,"from");
}
this._oCurItem = null;
this._nDisplayedItems = 0;
this._sCurQuery = null;
this._toggleContainer(false);
};
/**
* Populates the array of <li> elements in the container with query
* results. This method is passed to YAHOO.widget.DataSource#getResults as a
* callback function so results from the datasource are returned to the
* auto complete instance.
*
* @param {string} sQuery The query string
* @param {object} aResults An array of query result objects from the data source
* @param {string} oSelf The auto complete instance
* @private
*/
YAHOO.widget.AutoComplete.prototype._populateList = function(sQuery, aResults, oSelf) {
if(aResults === null) {
oSelf.dataErrorEvent.fire(oSelf, sQuery);
}
if (!oSelf._bFocused || !aResults) {
return;
}
var isOpera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
var contentStyle = oSelf._oContainer._oContent.style;
contentStyle.width = (!isOpera) ? null : "";
contentStyle.height = (!isOpera) ? null : "";
var sCurQuery = decodeURIComponent(sQuery);
oSelf._sCurQuery = sCurQuery;
oSelf._bItemSelected = false;
if(oSelf._maxResultsDisplayed != oSelf.maxResultsDisplayed) {
oSelf._initList();
}
var nItems = Math.min(aResults.length,oSelf.maxResultsDisplayed);
oSelf._nDisplayedItems = nItems;
if (nItems > 0) {
oSelf._initContainerHelpers();
var aItems = oSelf._aListItems;
// Fill items with data
for(var i = nItems-1; i >= 0; i--) {
var oItemi = aItems[i];
var oResultItemi = aResults[i];
oItemi.innerHTML = oSelf.formatResult(oResultItemi, sCurQuery);
oItemi.style.display = "list-item";
oItemi._sResultKey = oResultItemi[0];
oItemi._oResultData = oResultItemi;
}
// Empty out remaining items if any
for(var j = aItems.length-1; j >= nItems ; j--) {
var oItemj = aItems[j];
oItemj.innerHTML = null;
oItemj.style.display = "none";
oItemj._sResultKey = null;
oItemj._oResultData = null;
}
if(oSelf.autoHighlight) {
// Go to the first item
var oFirstItem = aItems[0];
oSelf._toggleHighlight(oFirstItem,"to");
oSelf.itemArrowToEvent.fire(oSelf, oFirstItem);
oSelf._typeAhead(oFirstItem,sQuery);
}
else {
oSelf._oCurItem = null;
}
// Expand the container
oSelf._toggleContainer(true);
}
else {
oSelf._clearList();
}
oSelf.dataReturnEvent.fire(oSelf, sQuery, aResults);
};
/**
* When YAHOO.widget.AutoComplete#bForceSelection is true and the user attempts
* leave the text input box without selecting an item from the query results,
* the user selection is cleared.
*
* @private
*/
YAHOO.widget.AutoComplete.prototype._clearSelection = function() {
var sValue = this._oTextbox.value;
var sChar = (this.delimChar) ? this.delimChar[0] : null;
var nIndex = (sChar) ? sValue.lastIndexOf(sChar, sValue.length-2) : -1;
if(nIndex > -1) {
this._oTextbox.value = sValue.substring(0,nIndex);
}
else {
this._oTextbox.value = "";
}
this._sSavedQuery = this._oTextbox.value;
// Fire custom event
this.selectionEnforceEvent.fire(this);
};
/**
* Whether or not user-typed value in the text input box matches any of the
* query results.
*
* @private
*/
YAHOO.widget.AutoComplete.prototype._textMatchesOption = function() {
var foundMatch = false;
for(var i = this._nDisplayedItems-1; i >= 0 ; i--) {
var oItem = this._aListItems[i];
var sMatch = oItem._sResultKey.toLowerCase();
if (sMatch == this._sCurQuery.toLowerCase()) {
foundMatch = true;
break;
}
}
return(foundMatch);
};
/**
* Updates in the text input box with the first query result as the user types,
* selecting the substring that the user has not typed.
*
* @param {object} oItem The <li> element item whose data populates the input field
* @param {string} sQuery Query string
* @private
*/
YAHOO.widget.AutoComplete.prototype._typeAhead = function(oItem, sQuery) {
// Don't update if turned off
if (!this.typeAhead) {
return;
}
var oTextbox = this._oTextbox;
var sValue = this._oTextbox.value; // any saved queries plus what user has typed
// Don't update with type-ahead if text selection is not supported
if(!oTextbox.setSelectionRange && !oTextbox.createTextRange) {
return;
}
// Select the portion of text that the user has not typed
var nStart = sValue.length;
this._updateValue(oItem);
var nEnd = oTextbox.value.length;
this._selectText(oTextbox,nStart,nEnd);
var sPrefill = oTextbox.value.substr(nStart,nEnd);
this.typeAheadEvent.fire(this,sQuery,sPrefill);
};
/**
* Selects text in a text input box.
*
* @param {object} oTextbox Text input box element in which to select text
* @param {number} nStart Starting index of text string to select
* @param {number} nEnd Ending index of text selection
* @private
*/
YAHOO.widget.AutoComplete.prototype._selectText = function(oTextbox, nStart, nEnd) {
if (oTextbox.setSelectionRange) { // For Mozilla
oTextbox.setSelectionRange(nStart,nEnd);
}
else if (oTextbox.createTextRange) { // For IE
var oTextRange = oTextbox.createTextRange();
oTextRange.moveStart("character", nStart);
oTextRange.moveEnd("character", nEnd-oTextbox.value.length);
oTextRange.select();
}
else {
oTextbox.select();
}
};
/**
* Syncs auto complete container with its helpers.
*
* @param {boolean} bShow True if container is expanded, false if collapsed
* @private
*/
YAHOO.widget.AutoComplete.prototype._toggleContainerHelpers = function(bShow) {
var bFireEvent = false;
var width = this._oContainer._oContent.offsetWidth + "px";
var height = this._oContainer._oContent.offsetHeight + "px";
if(this.useIFrame && this._oContainer._oIFrame) {
bFireEvent = true;
if(this.alwaysShowContainer || bShow) {
this._oContainer._oIFrame.style.width = width;
this._oContainer._oIFrame.style.height = height;
}
else {
this._oContainer._oIFrame.style.width = 0;
this._oContainer._oIFrame.style.height = 0;
}
}
if(this.useShadow && this._oContainer._oShadow) {
bFireEvent = true;
if(this.alwaysShowContainer || bShow) {
this._oContainer._oShadow.style.width = width;
this._oContainer._oShadow.style.height = height;
}
else {
this._oContainer._oShadow.style.width = 0;
this._oContainer._oShadow.style.height = 0;
}
}
};
/**
* Animates expansion or collapse of the container.
*
* @param {boolean} bShow True if container should be expanded, false if
* container should be collapsed
* @private
*/
YAHOO.widget.AutoComplete.prototype._toggleContainer = function(bShow) {
// Implementer has container always open so don't mess with it
if(this.alwaysShowContainer) {
// Fire these events to give implementers a hook into the container
// being populated and being emptied
if(bShow) {
this.containerExpandEvent.fire(this);
}
else {
this.containerCollapseEvent.fire(this);
}
this._bContainerOpen = bShow;
return;
}
var oContainer = this._oContainer;
// Container is already closed
if (!bShow && !this._bContainerOpen) {
oContainer._oContent.style.display = "none";
return;
}
// If animation is enabled...
var oAnim = this._oAnim;
if (oAnim && oAnim.getEl() && (this.animHoriz || this.animVert)) {
// If helpers need to be collapsed, do it right away...
// but if helpers need to be expanded, wait until after the container expands
if(!bShow) {
this._toggleContainerHelpers(bShow);
}
if(oAnim.isAnimated()) {
oAnim.stop();
}
// Clone container to grab current size offscreen
var oClone = oContainer._oContent.cloneNode(true);
oContainer.appendChild(oClone);
oClone.style.top = "-9000px";
oClone.style.display = "block";
// Current size of the container is the EXPANDED size
var wExp = oClone.offsetWidth;
var hExp = oClone.offsetHeight;
// Calculate COLLAPSED sizes based on horiz and vert anim
var wColl = (this.animHoriz) ? 0 : wExp;
var hColl = (this.animVert) ? 0 : hExp;
// Set animation sizes
oAnim.attributes = (bShow) ?
{width: { to: wExp }, height: { to: hExp }} :
{width: { to: wColl}, height: { to: hColl }};
// If opening anew, set to a collapsed size...
if(bShow && !this._bContainerOpen) {
oContainer._oContent.style.width = wColl+"px";
oContainer._oContent.style.height = hColl+"px";
}
// Else, set it to its last known size.
else {
oContainer._oContent.style.width = wExp+"px";
oContainer._oContent.style.height = hExp+"px";
}
oContainer.removeChild(oClone);
oClone = null;
var oSelf = this;
var onAnimComplete = function() {
// Finish the collapse
oAnim.onComplete.unsubscribeAll();
if(bShow) {
oSelf.containerExpandEvent.fire(oSelf);
}
else {
oContainer._oContent.style.display = "none";
oSelf.containerCollapseEvent.fire(oSelf);
}
oSelf._toggleContainerHelpers(bShow);
};
// Display container and animate it
oContainer._oContent.style.display = "block";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -