|
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 |
|
5 "use strict"; |
|
6 |
|
7 const Cc = Components.classes; |
|
8 const Ci = Components.interfaces; |
|
9 const Cu = Components.utils; |
|
10 |
|
11 this.EXPORTED_SYMBOLS = [ "AutoCompleteE10S" ]; |
|
12 |
|
13 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
14 Cu.import("resource://gre/modules/Services.jsm"); |
|
15 |
|
16 // nsITreeView implementation that feeds the autocomplete popup |
|
17 // with the search data. |
|
18 let AutoCompleteE10SView = { |
|
19 QueryInterface: XPCOMUtils.generateQI([Ci.nsITreeView, |
|
20 Ci.nsIAutoCompleteController]), |
|
21 treeBox: null, |
|
22 selection: null, |
|
23 treeData: [], |
|
24 |
|
25 get rowCount() { return this.treeData.length; }, |
|
26 setTree: function(treeBox) { this.treeBox = treeBox; }, |
|
27 getCellText: function(idx, column) { return this.treeData[idx] }, |
|
28 isContainer: function(idx) { return false; }, |
|
29 getCellValue: function(idx, column){ return false }, |
|
30 isContainerOpen: function(idx) { return false; }, |
|
31 isContainerEmpty: function(idx) { return false; }, |
|
32 isSeparator: function(idx) { return false; }, |
|
33 isSorted: function() { return false; }, |
|
34 isEditable: function(idx, column) { return false; }, |
|
35 canDrop: function(idx, orientation, dt) { return false; }, |
|
36 getLevel: function(idx) { return 0; }, |
|
37 getParentIndex: function(idx) { return -1; }, |
|
38 hasNextSibling: function(idx, after) { return idx < this.treeData.length - 1 }, |
|
39 toggleOpenState: function(idx) { }, |
|
40 getCellProperties: function(idx, column) { return ""; }, |
|
41 getRowProperties: function(idx) { return ""; }, |
|
42 getImageSrc: function(idx, column) { return null; }, |
|
43 getProgressMode : function(idx, column) { }, |
|
44 cycleHeader: function(column) { }, |
|
45 cycleCell: function(idx, column) { }, |
|
46 selectionChanged: function() { }, |
|
47 performAction: function(action) { }, |
|
48 performActionOnCell: function(action, index, column) { }, |
|
49 getColumnProperties: function(column) { return ""; }, |
|
50 |
|
51 get matchCount() this.rowCount, |
|
52 |
|
53 |
|
54 clearResults: function() { |
|
55 this.treeData = []; |
|
56 }, |
|
57 |
|
58 addResult: function(result) { |
|
59 this.treeData.push(result); |
|
60 }, |
|
61 |
|
62 handleEnter: function(aIsPopupSelection) { |
|
63 AutoCompleteE10S.handleEnter(aIsPopupSelection); |
|
64 }, |
|
65 |
|
66 stopSearch: function(){} |
|
67 }; |
|
68 |
|
69 this.AutoCompleteE10S = { |
|
70 init: function() { |
|
71 let messageManager = Cc["@mozilla.org/globalmessagemanager;1"]. |
|
72 getService(Ci.nsIMessageListenerManager); |
|
73 messageManager.addMessageListener("FormAutoComplete:SelectBy", this); |
|
74 messageManager.addMessageListener("FormAutoComplete:GetSelectedIndex", this); |
|
75 messageManager.addMessageListener("FormAutoComplete:ClosePopup", this); |
|
76 }, |
|
77 |
|
78 search: function(message) { |
|
79 let browserWindow = message.target.ownerDocument.defaultView; |
|
80 this.browser = browserWindow.gBrowser.selectedBrowser; |
|
81 this.popup = this.browser.autoCompletePopup; |
|
82 this.popup.hidden = false; |
|
83 this.popup.setAttribute("width", message.data.width); |
|
84 |
|
85 let rect = message.data; |
|
86 let {x, y} = this.browser.mapScreenCoordinatesFromContent(rect.left, rect.top + rect.height); |
|
87 this.x = x; |
|
88 this.y = y; |
|
89 |
|
90 let formAutoComplete = Cc["@mozilla.org/satchel/form-autocomplete;1"] |
|
91 .getService(Ci.nsIFormAutoComplete); |
|
92 |
|
93 formAutoComplete.autoCompleteSearchAsync(message.data.inputName, |
|
94 message.data.untrimmedSearchString, |
|
95 null, |
|
96 null, |
|
97 this.onSearchComplete.bind(this)); |
|
98 }, |
|
99 |
|
100 onSearchComplete: function(results) { |
|
101 AutoCompleteE10SView.clearResults(); |
|
102 |
|
103 let resultsArray = []; |
|
104 let count = results.matchCount; |
|
105 for (let i = 0; i < count; i++) { |
|
106 let result = results.getValueAt(i); |
|
107 resultsArray.push(result); |
|
108 AutoCompleteE10SView.addResult(result); |
|
109 } |
|
110 |
|
111 this.popup.view = AutoCompleteE10SView; |
|
112 |
|
113 this.browser.messageManager.sendAsyncMessage( |
|
114 "FormAutoComplete:AutoCompleteSearchAsyncResult", |
|
115 {results: resultsArray} |
|
116 ); |
|
117 |
|
118 this.popup.selectedIndex = -1; |
|
119 this.popup.invalidate(); |
|
120 |
|
121 if (count > 0) { |
|
122 this.popup.openPopupAtScreen(this.x, this.y, true); |
|
123 // Bug 947503 - This openPopup call is not triggering the "popupshowing" |
|
124 // event, which autocomplete.xml uses to track the openness of the popup |
|
125 // by setting its mPopupOpen flag. This flag needs to be properly set |
|
126 // for closePopup to work. For now, we set it manually. |
|
127 this.popup.mPopupOpen = true; |
|
128 } else { |
|
129 this.popup.closePopup(); |
|
130 } |
|
131 }, |
|
132 |
|
133 receiveMessage: function(message) { |
|
134 switch (message.name) { |
|
135 case "FormAutoComplete:SelectBy": |
|
136 this.popup.selectBy(message.data.reverse, message.data.page); |
|
137 break; |
|
138 |
|
139 case "FormAutoComplete:GetSelectedIndex": |
|
140 return this.popup.selectedIndex; |
|
141 |
|
142 case "FormAutoComplete:ClosePopup": |
|
143 this.popup.closePopup(); |
|
144 break; |
|
145 } |
|
146 }, |
|
147 |
|
148 handleEnter: function(aIsPopupSelection) { |
|
149 this.browser.messageManager.sendAsyncMessage( |
|
150 "FormAutoComplete:HandleEnter", |
|
151 { selectedIndex: this.popup.selectedIndex, |
|
152 IsPopupSelection: aIsPopupSelection } |
|
153 ); |
|
154 }, |
|
155 |
|
156 stopSearch: function() {} |
|
157 } |
|
158 |
|
159 this.AutoCompleteE10S.init(); |