1d798428 |
1 | <?xml version="1.0"?>\r |
2 | \r |
3 | <bindings id="mailBindings"\r |
4 | xmlns="http://www.mozilla.org/xbl"\r |
5 | xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">\r |
6 | \r |
7 | <!-- Message Pane Widgets -->\r |
8 | <binding id="mail-emailaddress" extends="chrome://global/content/xulBindings.xml#basetext">\r |
9 | <content excludes="observes,template">\r |
10 | <xul:box inherits="orient" autostretch="never" flex="1">\r |
11 | <xul:box orient="vertical" autostretch="never" flex="1">\r |
12 | <xul:text class="emailDisplayButton" context="emailAddressPopup" inherits="value,accesskey,crop"/>\r |
13 | </xul:box>\r |
14 | <xul:image class="emailDisplayImage" inherits="src"/>\r |
15 | </xul:box>\r |
16 | </content>\r |
17 | \r |
18 | <interface> \r |
19 | <method name="setTextAttribute">\r |
20 | <argument name="attributeName"/>\r |
21 | <argument name="attributeValue"/>\r |
22 | <body>\r |
23 | <![CDATA[ \r |
24 | var textNode = document.getAnonymousNodes(this)[0].firstChild.firstChild;\r |
25 | textNode.setAttribute(attributeName, attributeValue);\r |
26 | ]]>\r |
27 | </body>\r |
28 | </method>\r |
29 | \r |
30 | <method name="getTextAttribute">\r |
31 | <argument name="attributeName"/>\r |
32 | <argument name="attributeValue"/>\r |
33 | <body>\r |
34 | <![CDATA[ \r |
35 | var textNode = document.getAnonymousNodes(this)[0].firstChild.firstChild;\r |
36 | return textNode.getAttribute(attributeName, attributeValue);\r |
37 | ]]>\r |
38 | </body>\r |
39 | </method>\r |
40 | </interface>\r |
41 | </binding>\r |
42 | \r |
43 | <binding id="search-menulist-abstract" extends="xul:box">\r |
44 | <content>\r |
45 | <xul:menulist inherits="flex" oncommand="this.parentNode.onSelect(event)">\r |
46 | <xul:menupopup/>\r |
47 | </xul:menulist>\r |
48 | </content>\r |
49 | \r |
50 | <interface>\r |
51 | <property readonly="true" name="validityManager">\r |
52 | <![CDATA[\r |
53 | Components.classes['mozilla.mail.search.validityManager.1'].getService(Components.interfaces.nsIMsgSearchValidityManager);\r |
54 | ]]>\r |
55 | </property>\r |
56 | <property name="searchScope" onget="return this.internalScope;">\r |
57 | <!-- scope ID - retrieve the table -->\r |
58 | <setter>\r |
59 | <![CDATA[\r |
60 | // if scope isn't changing this is a noop\r |
61 | if (this.internalScope == val) return;\r |
62 | \r |
63 | this.internalScope = val;\r |
64 | this.refreshList();\r |
65 | var targets = this.targets;\r |
66 | if (targets) {\r |
67 | for (var i=0; i< targets.length; i++) {\r |
68 | targets[i].searchScope = val;\r |
69 | }\r |
70 | }\r |
71 | ]]>\r |
72 | </setter>\r |
73 | </property>\r |
74 | \r |
75 | <property name="validityTable" readonly="true" onget="return this.validityManager.getTable(this.searchScope)"/>\r |
76 | \r |
77 | <property name="valueStrings" readonly="true">\r |
78 | <getter>\r |
79 | <![CDATA[\r |
80 | var strings = new Array;\r |
81 | var ids = this.valueIds;\r |
82 | var bundle = this.stringBundle;\r |
83 | for (var i=0; i<ids.length; i++)\r |
84 | strings[i] = this.stringBundle.GetStringFromID(ids[i]);\r |
85 | return strings;\r |
86 | ]]>\r |
87 | </getter>\r |
88 | </property>\r |
89 | <property name="targets" readonly="true">\r |
90 | <getter>\r |
91 | <![CDATA[\r |
92 | var forAttrs = this.getAttribute("for");\r |
93 | if (!forAttrs) return null;\r |
94 | var targetIds = forAttrs.split(",");\r |
95 | if (targetIds.length == 0) return null;\r |
96 | \r |
97 | var targets = new Array;\r |
98 | var j=0;\r |
99 | for (var i=0; i<targetIds.length;i++) {\r |
100 | var target = document.getElementById(targetIds[i]);\r |
101 | if (target) targets[j++] = target;\r |
102 | }\r |
103 | return targets;\r |
104 | ]]>\r |
105 | </getter>\r |
106 | </property>\r |
107 | \r |
108 | <!-- value forwards to the internal menulist's "data" attribute -->\r |
109 | <property name="value" onget="return document.getAnonymousNodes(this)[0].selectedItem.getAttribute('data');">\r |
110 | <setter>\r |
111 | <![CDATA[\r |
112 | var menulist = document.getAnonymousNodes(this)[0];\r |
113 | var dataItems = menulist.getElementsByAttribute("data", val);\r |
114 | if (dataItems.length > 0)\r |
115 | menulist.selectedItem = dataItems[0];\r |
116 | ]]>\r |
117 | </setter>\r |
118 | </property>\r |
119 | <method name="refreshList">\r |
120 | <body>\r |
121 | <![CDATA[\r |
122 | var menuItemIds = this.valueIds;\r |
123 | var menuItemStrings = this.valueStrings;\r |
124 | \r |
125 | var menulist = document.getAnonymousNodes(this)[0];\r |
126 | var popup = menulist.firstChild;\r |
127 | \r |
128 | // save our old "data" so we can restore it later\r |
129 | var oldData = menulist.data;\r |
130 | \r |
131 | // remove the old popup children\r |
132 | while (popup.hasChildNodes())\r |
133 | popup.removeChild(popup.lastChild);\r |
134 | \r |
135 | var newSelection;\r |
136 | for (var i=0; i<menuItemIds.length; i++) {\r |
137 | // create the menuitem\r |
138 | var menuitem = document.createElement("menuitem");\r |
139 | menuitem.setAttribute("value", menuItemStrings[i]);\r |
140 | menuitem.setAttribute("data", menuItemIds[i]);\r |
141 | popup.appendChild(menuitem);\r |
142 | \r |
143 | // try to restore the selection\r |
144 | if (!newSelection || oldData == menuItemIds[i].toString()) {\r |
145 | newSelection = menuitem;\r |
146 | }\r |
147 | }\r |
148 | \r |
149 | // now restore the selection\r |
150 | menulist.selectedItem = newSelection\r |
151 | ]]>\r |
152 | </body>\r |
153 | </method>\r |
154 | <method name="onSelect">\r |
155 | <argument name="event"/>\r |
156 | <body>\r |
157 | <![CDATA[\r |
158 | var menulist = document.getAnonymousNodes(this)[0];\r |
159 | \r |
160 | // notify targets\r |
161 | var targets = this.targets;\r |
162 | if (targets) {\r |
163 | for (var i=0; i< targets.length; i++) {\r |
164 | targets[i].parentValue = menulist.data;\r |
165 | }\r |
166 | }\r |
167 | ]]>\r |
168 | </body>\r |
169 | </method>\r |
170 | </interface>\r |
171 | </binding>\r |
172 | \r |
173 | <!-- searchattribute - Subject, Sender, To, CC, etc. -->\r |
174 | <binding id="searchattribute"\r |
175 | extends="chrome://messenger/skin/mailWidgets.xml#search-menulist-abstract">\r |
176 | <interface>\r |
177 | <property name="stringBundle">\r |
178 | <![CDATA[\r |
179 | srGetStrBundle("chrome://messenger/locale/search-attributes.properties");\r |
180 | ]]>\r |
181 | </property>\r |
182 | <property name="valueIds" readonly="true">\r |
183 | <getter>\r |
184 | <![CDATA[\r |
185 | var length = new Object;\r |
186 | return this.validityTable.getAvailableAttributes(length);\r |
187 | ]]>\r |
188 | </getter>\r |
189 | </property>\r |
190 | </interface>\r |
191 | </binding>\r |
192 | \r |
193 | <!-- searchoperator - Contains, Is Less than, etc -->\r |
194 | <binding id="searchoperator"\r |
195 | extends="chrome://messenger/skin/mailWidgets.xml#search-menulist-abstract">\r |
196 | <interface>\r |
197 | <property name="stringBundle">\r |
198 | <![CDATA[\r |
199 | srGetStrBundle("chrome://messenger/locale/search-operators.properties");\r |
200 | ]]>\r |
201 | </property>\r |
202 | <property name="valueIds" readonly="true">\r |
203 | <getter>\r |
204 | <![CDATA[\r |
205 | var length = new Object;\r |
206 | return this.validityTable.getAvailableOperators(this.searchAttribute,length);\r |
207 | ]]>\r |
208 | </getter>\r |
209 | </property>\r |
210 | <property name="parentValue">\r |
211 | <setter>\r |
212 | <![CDATA[\r |
213 | if (this.searchAttribute == val) return;\r |
214 | this.searchAttribute = val;\r |
215 | this.refreshList();\r |
216 | ]]>\r |
217 | </setter>\r |
218 | <getter>\r |
219 | <![CDATA[\r |
220 | return this.searchAttribute;\r |
221 | ]]>\r |
222 | </getter>\r |
223 | </property>\r |
224 | </interface>\r |
225 | </binding>\r |
226 | \r |
227 | <!-- searchvalue - a widget which dynamically changes it's user interface\r |
228 | depending on what type of data it's supposed to be showing\r |
229 | currently handles arbitrary text entry, and menulists for priority and\r |
230 | status\r |
231 | -->\r |
232 | <binding id="searchvalue" extends="xul:deck">\r |
233 | <!-- yeah yeah, this stuff needs to be localized. I'm working on it! -->\r |
234 | <content>\r |
235 | <xul:textfield flex="1" />\r |
236 | <xul:menulist flex="1" >\r |
237 | <xul:menupopup>\r |
238 | <xul:menuitem value="Lowest"/>\r |
239 | <xul:menuitem value="Low"/>\r |
240 | <xul:menuitem value="Normal"/>\r |
241 | <xul:menuitem value="High"/>\r |
242 | <xul:menuitem value="Highest"/>\r |
243 | </xul:menupopup>\r |
244 | </xul:menulist>\r |
245 | <xul:menulist flex="1" >\r |
246 | <xul:menupopup>\r |
247 | <xul:menuitem value="read"/>\r |
248 | <xul:menuitem value="replied"/>\r |
249 | </xul:menupopup>\r |
250 | </xul:menulist>\r |
251 | </content>\r |
252 | <interface>\r |
253 | <!-- parentValue forwards to the attribute -->\r |
254 | <property name="parentValue" onset="this.searchAttribute=val;"\r |
255 | onget="return this.searchAttribute;"/>\r |
256 | <property name="searchAttribute" onget="return this.internalAttribute;">\r |
257 | <setter>\r |
258 | <![CDATA[\r |
259 | // noop if we're not changing it\r |
260 | if (this.internalAttribute == val) return;\r |
261 | this.internalAttribute = val;\r |
262 | // we inherit from a deck, so just use it's index attribute\r |
263 | // to hide/show widgets\r |
264 | if (val == Components.interfaces.nsMsgSearchAttrib.Priority)\r |
265 | this.setAttribute("index", "1");\r |
266 | else if (val == Components.interfaces.nsMsgSearchAttrib.MsgStatus)\r |
267 | this.setAttribute("index", "2");\r |
268 | else\r |
269 | this.setAttribute("index", "0");\r |
270 | ]]>\r |
271 | </setter>\r |
272 | </property>\r |
273 | <property name="value" onget="return this.internalValue;">\r |
274 | <setter>\r |
275 | <![CDATA[\r |
276 | // val is a nsIMsgSearchValue object\r |
277 | this.internalValue = val;\r |
278 | var attrib = val.attrib;\r |
279 | this.searchAttribute = attrib;\r |
280 | if (attrib == Components.interfaces.nsMsgSearchAttrib.Priority)\r |
281 | document.getAnonymousNodes(this)[1].data=val.priority;\r |
282 | else if (attrib == Components.interfaces.nsMsgSearchAttrib.MsgStatus)\r |
283 | document.getAnonymousNodes(this)[2].data=val.status;\r |
284 | else\r |
285 | document.getAnonymousNodes(this)[0].value = val.str;\r |
286 | ]]>\r |
287 | </setter>\r |
288 | </property>\r |
289 | <method name="save">\r |
290 | <body>\r |
291 | <![CDATA[\r |
292 | var searchValue = this.value;\r |
293 | var searchAttribute = this.searchAttribute;\r |
294 | var nsMsgSearchAttrib = Components.interfaces.nsMsgSearchAttrib;\r |
295 | \r |
296 | searchValue.attrib = searchAttribute;\r |
297 | if (searchAttribute == nsMsgSearchAttrib.Priority)\r |
298 | searchValue.priority = document.getAnonymousNodes(this)[1].selectedItem.data;\r |
299 | else if (searchAttribute == nsMsgSearchAttrib.MsgStatus)\r |
300 | searchValue.status = document.getAnonymousNodes(this)[2].selectedItem.data;\r |
301 | else\r |
302 | searchValue.str = document.getAnonymousNodes(this)[0].value;\r |
303 | ]]>\r |
304 | </body>\r |
305 | </method>\r |
306 | <method name="saveTo">\r |
307 | <argument name="searchValue"/>\r |
308 | <body>\r |
309 | <![CDATA[\r |
310 | this.internalValue = searchValue;\r |
311 | this.save();\r |
312 | ]]>\r |
313 | </body>\r |
314 | </method>\r |
315 | </interface>\r |
316 | </binding>\r |
317 | <binding id="searchterm" extends="xul:box">\r |
318 | <interface>\r |
319 | <!-- the actual nsIMsgSearchTerm object -->\r |
320 | <property name="searchTerm" onget="return this.internalSearchTerm">\r |
321 | <setter>\r |
322 | <![CDATA[\r |
323 | this.internalSearchTerm = val;\r |
324 | \r |
325 | var term = val;\r |
326 | // val is a nsIMsgSearchTerm\r |
327 | var searchAttribute=this.searchattribute;\r |
328 | var searchOperator=this.searchoperator;\r |
329 | var searchValue=this.searchvalue;\r |
330 | \r |
331 | // now reflect all attributes of the searchterm into the widgets\r |
332 | if (searchAttribute) searchAttribute.value = term.attrib;\r |
333 | if (searchOperator) searchOperator.value = val.op;\r |
334 | if (searchValue) searchValue.value = term.value;\r |
335 | \r |
336 | this.booleanAnd = val.booleanAnd;\r |
337 | ]]>\r |
338 | </setter>\r |
339 | </property>\r |
340 | \r |
341 | <property name="searchScope">\r |
342 | <getter>\r |
343 | <![CDATA[\r |
344 | var searchAttribute = this.searchattribute;\r |
345 | if (searchAttribute)\r |
346 | return searchAttribute.searchScope;\r |
347 | return undefined;\r |
348 | ]]>\r |
349 | </getter>\r |
350 | <setter>\r |
351 | <![CDATA[\r |
352 | var searchAttribute = this.searchattribute;\r |
353 | if (searchAttribute) searchAttribute.searchScope=val;\r |
354 | ]]>\r |
355 | </setter>\r |
356 | </property>\r |
357 | <!-- the three tags that make up a term - to use, set the\r |
358 | attribute in the XUL to the ID of the term.\r |
359 | -->\r |
360 | <property name="searchattribute" \r |
361 | onget="return document.getElementById(this.getAttribute('searchattribute'));"\r |
362 | onset="this.setAttribute('searchattribute',val.id)"/>\r |
363 | \r |
364 | <property name="searchoperator" \r |
365 | onget="return document.getElementById(this.getAttribute('searchoperator'));"\r |
366 | onset="this.setAttribute('searchoperator',val.id)"/>\r |
367 | \r |
368 | <property name="searchvalue" \r |
369 | onget="return document.getElementById(this.getAttribute('searchvalue'));"\r |
370 | onset="this.setAttribute('searchvalue',val.id)"/>\r |
371 | <property name="booleanNodes">\r |
372 | <![CDATA[\r |
373 | null;\r |
374 | ]]>\r |
375 | </property>\r |
376 | <property name="stringBundle">\r |
377 | <![CDATA[\r |
378 | srGetStrBundle("chrome://messenger/locale/search.properties");\r |
379 | ]]>\r |
380 | </property>\r |
381 | <property name="booleanAnd" onget="return this.internalBooleanAnd">\r |
382 | <setter>\r |
383 | <![CDATA[\r |
384 | // whenever you set this, all nodes in booleanNodes\r |
385 | // are updated to reflect the string\r |
386 | \r |
387 | if (this.internalBooleanAnd == val) return;\r |
388 | this.internalBooleanAnd = val;\r |
389 | \r |
390 | var booleanNodes = this.booleanNodes;\r |
391 | if (!booleanNodes) return;\r |
392 | \r |
393 | var stringBundle = this.stringBundle;\r |
394 | var andString = val ? "And" : "Or";\r |
395 | for (var i=0; i<booleanNodes.length; i++) {\r |
396 | try { \r |
397 | var staticString =\r |
398 | stringBundle.GetStringFromName("search" + andString + i);\r |
399 | if (staticString && staticString.length>0)\r |
400 | booleanNodes[i].setAttribute("value", staticString);\r |
401 | } catch (ex) { /* no error, means string not found */}\r |
402 | }\r |
403 | ]]>\r |
404 | </setter>\r |
405 | </property>\r |
406 | <method name="save">\r |
407 | <body>\r |
408 | <![CDATA[\r |
409 | var searchTerm = this.searchTerm;\r |
410 | searchTerm.attrib = this.searchattribute.value;\r |
411 | searchTerm.op = this.searchoperator.value;\r |
412 | if (this.searchvalue.value)\r |
413 | this.searchvalue.save();\r |
414 | else\r |
415 | this.searchvalue.saveTo(searchTerm.value);\r |
416 | searchTerm.value = this.searchvalue.value;\r |
417 | searchTerm.booleanAnd = this.booleanAnd;\r |
418 | ]]>\r |
419 | </body>\r |
420 | </method>\r |
421 | <!-- if you have a search term element with no search term -->\r |
422 | <method name="saveTo">\r |
423 | <argument name="searchTerm"/>\r |
424 | <body>\r |
425 | <![CDATA[\r |
426 | this.internalSearchTerm = searchTerm;\r |
427 | this.save();\r |
428 | ]]>\r |
429 | </body>\r |
430 | </method>\r |
431 | </interface>\r |
432 | </binding>\r |
433 | </bindings>\r |