1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5var EXPORTED_SYMBOLS = ["FormAutoCompleteResult"];
6
7function FormAutoCompleteResult(
8  searchString,
9  searchResult,
10  defaultIndex,
11  errorDescription,
12  items,
13  prevResult
14) {
15  this.searchString = searchString;
16  this._searchResult = searchResult;
17  this._defaultIndex = defaultIndex;
18  this._errorDescription = errorDescription;
19  this._items = items;
20  this._formHistResult = prevResult;
21  this.entries = prevResult ? prevResult.wrappedJSObject.entries : [];
22}
23
24FormAutoCompleteResult.prototype = {
25  // The user's query string
26  searchString: "",
27
28  // The result code of this result object, see |get searchResult| for possible values.
29  _searchResult: 0,
30
31  // The default item that should be entered if none is selected
32  _defaultIndex: 0,
33
34  // The reason the search failed
35  _errorDescription: "",
36
37  /**
38   * A reference to the form history nsIAutocompleteResult that we're wrapping.
39   * We use this to forward removeEntryAt calls as needed.
40   */
41  _formHistResult: null,
42
43  entries: null,
44
45  get wrappedJSObject() {
46    return this;
47  },
48
49  /**
50   * @returns {number} the result code of this result object, either:
51   *         RESULT_IGNORED   (invalid searchString)
52   *         RESULT_FAILURE   (failure)
53   *         RESULT_NOMATCH   (no matches found)
54   *         RESULT_SUCCESS   (matches found)
55   */
56  get searchResult() {
57    return this._searchResult;
58  },
59
60  /**
61   * @returns {number} the default item that should be entered if none is selected
62   */
63  get defaultIndex() {
64    return this._defaultIndex;
65  },
66
67  /**
68   * @returns {string} the reason the search failed
69   */
70  get errorDescription() {
71    return this._errorDescription;
72  },
73
74  /**
75   * @returns {number} the number of results
76   */
77  get matchCount() {
78    return this._items.length;
79  },
80
81  _checkIndexBounds(index) {
82    if (index < 0 || index >= this._items.length) {
83      throw Components.Exception(
84        "Index out of range.",
85        Cr.NS_ERROR_ILLEGAL_VALUE
86      );
87    }
88  },
89
90  /**
91   * Retrieves a result
92   * @param   {number} index   the index of the result requested
93   * @returns {string}         the result at the specified index
94   */
95  getValueAt(index) {
96    this._checkIndexBounds(index);
97    return this._items[index].value;
98  },
99
100  getLabelAt(index) {
101    this._checkIndexBounds(index);
102    return this._items[index].label || this._items[index].value;
103  },
104
105  /**
106   * Retrieves a comment (metadata instance)
107   * @param {number} index    the index of the comment requested
108   * @returns {Object}        the comment at the specified index
109   */
110  getCommentAt(index) {
111    this._checkIndexBounds(index);
112    return this._items[index].comment;
113  },
114
115  /**
116   * Retrieves a style hint specific to a particular index.
117   * @param   {number} index   the index of the style hint requested
118   * @returns {string|null}    the style hint at the specified index
119   */
120  getStyleAt(index) {
121    this._checkIndexBounds(index);
122
123    if (this._formHistResult && index < this._formHistResult.matchCount) {
124      return "fromhistory";
125    }
126
127    if (
128      this._formHistResult &&
129      this._formHistResult.matchCount > 0 &&
130      index == this._formHistResult.matchCount
131    ) {
132      return "datalist-first";
133    }
134
135    return null;
136  },
137
138  /**
139   * Retrieves an image url.
140   * @param   {number} index  the index of the image url requested
141   * @returns {string}        the image url at the specified index
142   */
143  getImageAt(index) {
144    this._checkIndexBounds(index);
145    return "";
146  },
147
148  /**
149   * Retrieves a result
150   * @param   {number} index   the index of the result requested
151   * @returns {string}         the result at the specified index
152   */
153  getFinalCompleteValueAt(index) {
154    return this.getValueAt(index);
155  },
156
157  /**
158   * Returns true if the value at the given index is removable
159   * @param   {number}  index  the index of the result to remove
160   * @returns {boolean}        True if the value is removable
161   */
162  isRemovableAt(index) {
163    this._checkIndexBounds(index);
164    return this._items[index].removable;
165  },
166
167  /**
168   * Removes a result from the resultset
169   * @param {number}  index    the index of the result to remove
170   */
171  removeValueAt(index) {
172    this._checkIndexBounds(index);
173    // Forward the removeValueAt call to the underlying result if we have one
174    // Note: this assumes that the form history results were added to the top
175    // of our arrays.
176    if (this._formHistResult && index < this._formHistResult.matchCount) {
177      // Delete the history result from the DB
178      this._formHistResult.removeValueAt(index);
179    }
180    this._items.splice(index, 1);
181  },
182
183  // nsISupports
184  QueryInterface: ChromeUtils.generateQI(["nsIAutoCompleteResult"]),
185};
186