2011-12-22 56 views
2

更新: 由我自己找到解决方案,看到答案如何为firefox工具栏自定义自动完成文本框?

+3

所以你复制一串代码,你不明白,它粘贴到文件,你惊讶它不起作用? – 2011-12-22 22:18:00

+0

我知道这是一个老问题,但你应该把解决方案放在答案中,并将其标记为已接受,因为这显示为未答复 – 2013-08-04 23:04:28

+0

@FilipeSilva你是对的,现在修复它 – remi 2013-08-06 17:00:09

回答

3

我自己找到了解决方案,希望它能帮助别人。

我不得不这样做完全一样如下:

在我创建了一个名为“成分”新目录的扩展目录。

在那个目录里面,我创建了一个带有自定义自动完成名称的js文件,在本例中为“simpleautocomplete.js”。该js文件的内容是:

/* 
* https://developer.mozilla.org/en/How_to_implement_custom_autocomplete_search_component 
*/ 
const Ci = Components.interfaces; 

const CLASS_ID = Components.ID("6224daa1-71a2-4d1a-ad90-01ca1c08e323"); 
const CLASS_NAME = "Simple AutoComplete"; 
const CONTRACT_ID = "@mozilla.org/autocomplete/search;1?name=simple-autocomplete"; 

try{ 
    Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); 
} catch (x) { 
} 


// Implements nsIAutoCompleteResult 
function SimpleAutoCompleteResult(searchString, searchResult, 
            defaultIndex, errorDescription, 
            results, comments) { 
    this._searchString = searchString; 
    this._searchResult = searchResult; 
    this._defaultIndex = defaultIndex; 
    this._errorDescription = errorDescription; 
    this._results = results; 
    this._comments = comments; 
} 

SimpleAutoCompleteResult.prototype = { 
    _searchString: "", 
    _searchResult: 0, 
    _defaultIndex: 0, 
    _errorDescription: "", 
    _results: [], 
    _comments: [], 

    getLabelAt: function(index) { return this._results[index]; }, 

    /** 
    * The original search string 
    */ 
    get searchString() { 
    return this._searchString; 
    }, 

    /** 
    * The result code of this result object, either: 
    *   RESULT_IGNORED (invalid searchString) 
    *   RESULT_FAILURE (failure) 
    *   RESULT_NOMATCH (no matches found) 
    *   RESULT_SUCCESS (matches found) 
    */ 
    get searchResult() { 
    return this._searchResult; 
    }, 

    /** 
    * Index of the default item that should be entered if none is selected 
    */ 
    get defaultIndex() { 
    return this._defaultIndex; 
    }, 

    /** 
    * A string describing the cause of a search failure 
    */ 
    get errorDescription() { 
    return this._errorDescription; 
    }, 

    /** 
    * The number of matches 
    */ 
    get matchCount() { 
    return this._results.length; 
    }, 

    /** 
    * Get the value of the result at the given index 
    */ 
    getValueAt: function(index) { 
    return this._results[index]; 
    }, 

    /** 
    * Get the comment of the result at the given index 
    */ 
    getCommentAt: function(index) { 
    return this._comments[index]; 
    }, 

    /** 
    * Get the style hint for the result at the given index 
    */ 
    getStyleAt: function(index) { 
    if (!this._comments[index]) 
     return null; // not a category label, so no special styling 

    if (index == 0) 
     return "suggestfirst"; // category label on first line of results 

    return "suggesthint"; // category label on any other line of results 
    }, 

    /** 
    * Get the image for the result at the given index 
    * The return value is expected to be an URI to the image to display 
    */ 
    getImageAt : function (index) { 
    return ""; 
    }, 

    /** 
    * Remove the value at the given index from the autocomplete results. 
    * If removeFromDb is set to true, the value should be removed from 
    * persistent storage as well. 
    */ 
    removeValueAt: function(index, removeFromDb) { 
    this._results.splice(index, 1); 
    this._comments.splice(index, 1); 
    }, 

    QueryInterface: function(aIID) { 
    if (!aIID.equals(Ci.nsIAutoCompleteResult) && !aIID.equals(Ci.nsISupports)) 
     throw Components.results.NS_ERROR_NO_INTERFACE; 
    return this; 
    } 
}; 


// Implements nsIAutoCompleteSearch 
function SimpleAutoCompleteSearch() { 
} 

SimpleAutoCompleteSearch.prototype = { 
    classID: CLASS_ID, 
    classDescription: CLASS_NAME, 
    contractID: CONTRACT_ID, 

    /* 
    * Search for a given string and notify a listener (either synchronously 
    * or asynchronously) of the result 
    * 
    * @param searchString - The string to search for 
    * @param searchParam - An extra parameter 
    * @param previousResult - A previous result to use for faster searchinig 
    * @param listener - A listener to notify when the search is complete 
    */ 
    startSearch: function(searchString, searchParam, result, listener) { 
    // This autocomplete source assumes the developer attached a JSON string 
    // to the the "autocompletesearchparam" attribute or "searchParam" property 
    // of the <textbox> element. The JSON is converted into an array and used 
    // as the source of match data. Any values that match the search string 
    // are moved into temporary arrays and passed to the AutoCompleteResult 
    if (searchParam.length > 0) { 
     var nativeJSON = Components.classes["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON); 
     var searchResults = nativeJSON.decode(searchParam); 
     var results = []; 
     var comments = []; 
     for (i=0; i<searchResults.length; i++) { 
     if (searchResults[i].value.indexOf(searchString) == 0) { 
      results.push(searchResults[i].value); 
      if (searchResults[i].comment) 
      comments.push(searchResults[i].comment); 
      else 
      comments.push(null); 
     } 
     } 
     var newResult = new SimpleAutoCompleteResult(searchString, Ci.nsIAutoCompleteResult.RESULT_SUCCESS, 0, "", results, comments); 
     listener.onSearchResult(this, newResult); 
    } 
    }, 

    /* 
    * Stop an asynchronous search that is in progress 
    */ 
    stopSearch: function() { 
    }, 

    QueryInterface: function(aIID) { 
    if (!aIID.equals(Ci.nsIAutoCompleteSearch) && !aIID.equals(Ci.nsISupports)) 
     throw Components.results.NS_ERROR_NO_INTERFACE; 
    return this; 
    }, 
    _QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIAutoCompleteSearch]) 
}; 

// Factory 
var SimpleAutoCompleteSearchFactory = { 
    singleton: null, 
    createInstance: function (aOuter, aIID) { 
    if (aOuter != null) 
     throw Components.results.NS_ERROR_NO_AGGREGATION; 
    if (this.singleton == null) 
     this.singleton = new SimpleAutoCompleteSearch(); 
    return this.singleton.QueryInterface(aIID); 
    } 
}; 

// Module 
var SimpleAutoCompleteSearchModule = { 
    registerSelf: function(aCompMgr, aFileSpec, aLocation, aType) { 
    aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar); 
    aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType); 
    }, 

    unregisterSelf: function(aCompMgr, aLocation, aType) { 
    aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar); 
    aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);   
    }, 

    getClassObject: function(aCompMgr, aCID, aIID) { 
    if (!aIID.equals(Components.interfaces.nsIFactory)) 
     throw Components.results.NS_ERROR_NOT_IMPLEMENTED; 

    if (aCID.equals(CLASS_ID)) 
     return SimpleAutoCompleteSearchFactory; 

    throw Components.results.NS_ERROR_NO_INTERFACE; 
    }, 

    canUnload: function(aCompMgr) { return true; } 
}; 

// Module initialization 
function NSGetModule(aCompMgr, aFileSpec) { return SimpleAutoCompleteSearchModule; } 

if (XPCOMUtils.generateNSGetFactory){ 
    var NSGetFactory = XPCOMUtils.generateNSGetFactory([SimpleAutoCompleteSearch]); 
} 

我将此代码添加到chrome.manifest用于:

component {6224daa1-71a2-4d1a-ad90-01ca1c08e323} components/simpleautocomplete.js 
contract @mozilla.org/autocomplete/search;1?name=simple-autocomplete {6224daa1-71a2-4d1a-ad90-01ca1c08e323} 

在XUL文件中我添加:

<textbox type="autocomplete" autocompletesearch="simple-autocomplete" 
autocompletesearchparam='[{"value":"param1"},{"value":"param2"}]' /> 

重要提示:当设置autocompletesearchparam属性的赋值必须是两个单引号而不是双引号。只有里面的值必须用双引号括在上面的xul中。

就是这样。

当我测试了我的扩展并在自动完成文本框中输入“p”时,词组“param1”和“param2”被加强。

var searchTextField = document.getElementById("searchTextField"); 
var param1 = "Param1", param2 = "Param2"; 
paramsToSet = "["; 

paramsToSet += "{\"value\" : \"" + param1 + "\"},"; 
paramsToSet += "{\"value\" : \"" + param2 + "\"},"; 

paramsToSet = paramsToSet.substring(0, paramsToSet.length-1); // to remove the last "," 
paramsToSet += "]"; 
paramsToSet = paramsToSet.toLowerCase(); // important! 
searchTextField.setAttribute("autocompletesearchparam", paramsToSet); 

注1:请注意,自动完成的文本框只接受小写字母文本

我还可以进行如下设置在js文件中的PARAMS。注意2:如果将参数设置为文本框是动态的并需要一些时间,例如 - 当客户端在文本框中键入内容并将输入的文本发送到服务器时,将包含该参数的响应附加到文本框和此过程需要一些时间(大约一秒或一半),那么弹出式自动完成将不会弹出,因为客户端开始键入时自动完成搜索参数为空。在这种情况下,有可能迫使自动完成,当你有PARAMS在这样的文本框设置为弹出:

searchTextField.open = true;  
+0

感谢remi,你节省了很多我的时间和精力。 :) – Subh 2014-08-31 15:07:16

+0

嗨雷米,感谢这个有用的职位。我有一个要求,我需要从搜索列表中选择值并显示在文本框中。因此,我可以针对该特定搜索选择启动事件。你可以请教我如何实现这一目标。在此先感谢,Subh – Subh 2014-09-01 18:07:48