|
1 <?xml version="1.0"?> |
|
2 |
|
3 <!DOCTYPE bindings [ |
|
4 <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd"> |
|
5 %preferencesDTD; |
|
6 <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd"> |
|
7 %globalKeysDTD; |
|
8 ]> |
|
9 |
|
10 <bindings id="preferencesBindings" |
|
11 xmlns="http://www.mozilla.org/xbl" |
|
12 xmlns:xbl="http://www.mozilla.org/xbl" |
|
13 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> |
|
14 |
|
15 # |
|
16 # = Preferences Window Framework |
|
17 # |
|
18 # The syntax for use looks something like: |
|
19 # |
|
20 # <prefwindow> |
|
21 # <prefpane id="prefPaneA"> |
|
22 # <preferences> |
|
23 # <preference id="preference1" name="app.preference1" type="bool" onchange="foo();"/> |
|
24 # <preference id="preference2" name="app.preference2" type="bool" useDefault="true"/> |
|
25 # </preferences> |
|
26 # <checkbox label="Preference" preference="preference1"/> |
|
27 # </prefpane> |
|
28 # </prefwindow> |
|
29 # |
|
30 |
|
31 <binding id="preferences"> |
|
32 <implementation implements="nsIObserver"> |
|
33 <method name="observe"> |
|
34 <parameter name="aSubject"/> |
|
35 <parameter name="aTopic"/> |
|
36 <parameter name="aData"/> |
|
37 <body> |
|
38 <![CDATA[ |
|
39 for (var i = 0; i < this.childNodes.length; ++i) { |
|
40 var preference = this.childNodes[i]; |
|
41 if (preference.name == aData) { |
|
42 preference.value = preference.valueFromPreferences; |
|
43 } |
|
44 } |
|
45 ]]> |
|
46 </body> |
|
47 </method> |
|
48 |
|
49 <method name="fireChangedEvent"> |
|
50 <parameter name="aPreference"/> |
|
51 <body> |
|
52 <![CDATA[ |
|
53 // Value changed, synthesize an event |
|
54 try { |
|
55 var event = document.createEvent("Events"); |
|
56 event.initEvent("change", true, true); |
|
57 aPreference.dispatchEvent(event); |
|
58 } |
|
59 catch (e) { |
|
60 Components.utils.reportError(e); |
|
61 } |
|
62 ]]> |
|
63 </body> |
|
64 </method> |
|
65 |
|
66 <field name="service"> |
|
67 Components.classes["@mozilla.org/preferences-service;1"] |
|
68 .getService(Components.interfaces.nsIPrefService); |
|
69 </field> |
|
70 <field name="rootBranch"> |
|
71 Components.classes["@mozilla.org/preferences-service;1"] |
|
72 .getService(Components.interfaces.nsIPrefBranch); |
|
73 </field> |
|
74 <field name="defaultBranch"> |
|
75 this.service.getDefaultBranch(""); |
|
76 </field> |
|
77 <field name="rootBranchInternal"> |
|
78 Components.classes["@mozilla.org/preferences-service;1"] |
|
79 .getService(Components.interfaces.nsIPrefBranchInternal); |
|
80 </field> |
|
81 <property name="type" readonly="true"> |
|
82 <getter> |
|
83 <![CDATA[ |
|
84 return document.documentElement.type || ""; |
|
85 ]]> |
|
86 </getter> |
|
87 </property> |
|
88 <property name="instantApply" readonly="true"> |
|
89 <getter> |
|
90 <![CDATA[ |
|
91 var doc = document.documentElement; |
|
92 return this.type == "child" ? doc.instantApply |
|
93 : doc.instantApply || this.rootBranch.getBoolPref("browser.preferences.instantApply"); |
|
94 ]]> |
|
95 </getter> |
|
96 </property> |
|
97 </implementation> |
|
98 </binding> |
|
99 |
|
100 <binding id="preference"> |
|
101 <implementation> |
|
102 <constructor> |
|
103 <![CDATA[ |
|
104 // if the element has been inserted without the name attribute set, |
|
105 // we have nothing to do here |
|
106 if (!this.name) |
|
107 return; |
|
108 |
|
109 this.preferences.rootBranchInternal |
|
110 .addObserver(this.name, this.preferences, false); |
|
111 // In non-instant apply mode, we must try and use the last saved state |
|
112 // from any previous opens of a child dialog instead of the value from |
|
113 // preferences, to pick up any edits a user may have made. |
|
114 if (this.preferences.type == "child" && |
|
115 !this.instantApply && window.opener) { |
|
116 var pdoc = window.opener.document; |
|
117 |
|
118 // Try to find a preference element for the same preference. |
|
119 var preference = null; |
|
120 var parentPreferences = pdoc.getElementsByTagName("preferences"); |
|
121 for (var k = 0; (k < parentPreferences.length && !preference); ++k) { |
|
122 var parentPrefs = parentPreferences[k] |
|
123 .getElementsByAttribute("name", this.name); |
|
124 for (var l = 0; (l < parentPrefs.length && !preference); ++l) { |
|
125 if (parentPrefs[l].localName == "preference") |
|
126 preference = parentPrefs[l]; |
|
127 } |
|
128 } |
|
129 this._setValue(preference ? preference.value |
|
130 : this.valueFromPreferences, false); |
|
131 } |
|
132 else |
|
133 this._setValue(this.valueFromPreferences, false); |
|
134 ]]> |
|
135 </constructor> |
|
136 <destructor> |
|
137 this.preferences.rootBranchInternal |
|
138 .removeObserver(this.name, this.preferences); |
|
139 </destructor> |
|
140 |
|
141 <property name="instantApply"> |
|
142 <getter> |
|
143 return this.getAttribute("instantApply") == "true" || this.preferences.instantApply; |
|
144 </getter> |
|
145 </property> |
|
146 |
|
147 <property name="preferences" onget="return this.parentNode"/> |
|
148 <property name="name" onget="return this.getAttribute('name');"> |
|
149 <setter> |
|
150 if (val == this.name) |
|
151 return val; |
|
152 |
|
153 this.preferences.rootBranchInternal |
|
154 .removeObserver(this.name, this.preferences); |
|
155 this.setAttribute('name', val); |
|
156 this.preferences.rootBranchInternal |
|
157 .addObserver(val, this.preferences, false); |
|
158 |
|
159 return val; |
|
160 </setter> |
|
161 </property> |
|
162 <property name="type" onget="return this.getAttribute('type');" |
|
163 onset="this.setAttribute('type', val); return val;"/> |
|
164 <property name="inverted" onget="return this.getAttribute('inverted') == 'true';" |
|
165 onset="this.setAttribute('inverted', val); return val;"/> |
|
166 <property name="readonly" onget="return this.getAttribute('readonly') == 'true';" |
|
167 onset="this.setAttribute('readonly', val); return val;"/> |
|
168 |
|
169 <field name="_value">null</field> |
|
170 <method name="_setValue"> |
|
171 <parameter name="aValue"/> |
|
172 <parameter name="aUpdate"/> |
|
173 <body> |
|
174 <![CDATA[ |
|
175 if (aUpdate && this.value !== aValue) { |
|
176 this._value = aValue; |
|
177 if (this.instantApply) |
|
178 this.valueFromPreferences = aValue; |
|
179 this.preferences.fireChangedEvent(this); |
|
180 } |
|
181 else if (!aUpdate) { |
|
182 this._value = aValue; |
|
183 this.updateElements(); |
|
184 } |
|
185 return aValue; |
|
186 ]]> |
|
187 </body> |
|
188 </method> |
|
189 <property name="value" onget="return this._value" onset="return this._setValue(val, true);"/> |
|
190 |
|
191 <property name="locked"> |
|
192 <getter> |
|
193 return this.preferences.rootBranch.prefIsLocked(this.name); |
|
194 </getter> |
|
195 </property> |
|
196 |
|
197 <property name="disabled"> |
|
198 <getter> |
|
199 return this.getAttribute("disabled") == "true"; |
|
200 </getter> |
|
201 <setter> |
|
202 <![CDATA[ |
|
203 if (val) |
|
204 this.setAttribute("disabled", "true"); |
|
205 else |
|
206 this.removeAttribute("disabled"); |
|
207 |
|
208 if (!this.id) |
|
209 return val; |
|
210 |
|
211 var elements = document.getElementsByAttribute("preference", this.id); |
|
212 for (var i = 0; i < elements.length; ++i) { |
|
213 elements[i].disabled = val; |
|
214 |
|
215 var labels = document.getElementsByAttribute("control", elements[i].id); |
|
216 for (var j = 0; j < labels.length; ++j) |
|
217 labels[j].disabled = val; |
|
218 } |
|
219 |
|
220 return val; |
|
221 ]]> |
|
222 </setter> |
|
223 </property> |
|
224 |
|
225 <property name="tabIndex"> |
|
226 <getter> |
|
227 return parseInt(this.getAttribute("tabindex")); |
|
228 </getter> |
|
229 <setter> |
|
230 <![CDATA[ |
|
231 if (val) |
|
232 this.setAttribute("tabindex", val); |
|
233 else |
|
234 this.removeAttribute("tabindex"); |
|
235 |
|
236 if (!this.id) |
|
237 return val; |
|
238 |
|
239 var elements = document.getElementsByAttribute("preference", this.id); |
|
240 for (var i = 0; i < elements.length; ++i) { |
|
241 elements[i].tabIndex = val; |
|
242 |
|
243 var labels = document.getElementsByAttribute("control", elements[i].id); |
|
244 for (var j = 0; j < labels.length; ++j) |
|
245 labels[j].tabIndex = val; |
|
246 } |
|
247 |
|
248 return val; |
|
249 ]]> |
|
250 </setter> |
|
251 </property> |
|
252 |
|
253 <property name="hasUserValue"> |
|
254 <getter> |
|
255 <![CDATA[ |
|
256 return this.preferences.rootBranch.prefHasUserValue(this.name) && |
|
257 this.value !== undefined; |
|
258 ]]> |
|
259 </getter> |
|
260 </property> |
|
261 |
|
262 <method name="reset"> |
|
263 <body> |
|
264 // defer reset until preference update |
|
265 this.value = undefined; |
|
266 </body> |
|
267 </method> |
|
268 |
|
269 <field name="_useDefault">false</field> |
|
270 <property name="defaultValue"> |
|
271 <getter> |
|
272 <![CDATA[ |
|
273 this._useDefault = true; |
|
274 var val = this.valueFromPreferences; |
|
275 this._useDefault = false; |
|
276 return val; |
|
277 ]]> |
|
278 </getter> |
|
279 </property> |
|
280 |
|
281 <property name="_branch"> |
|
282 <getter> |
|
283 return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch; |
|
284 </getter> |
|
285 </property> |
|
286 |
|
287 <field name="batching">false</field> |
|
288 |
|
289 <method name="_reportUnknownType"> |
|
290 <body> |
|
291 <![CDATA[ |
|
292 var consoleService = Components.classes["@mozilla.org/consoleservice;1"] |
|
293 .getService(Components.interfaces.nsIConsoleService); |
|
294 var msg = "<preference> with id='" + this.id + "' and name='" + |
|
295 this.name + "' has unknown type '" + this.type + "'."; |
|
296 consoleService.logStringMessage(msg); |
|
297 ]]> |
|
298 </body> |
|
299 </method> |
|
300 |
|
301 <property name="valueFromPreferences"> |
|
302 <getter> |
|
303 <![CDATA[ |
|
304 try { |
|
305 // Force a resync of value with preferences. |
|
306 switch (this.type) { |
|
307 case "int": |
|
308 return this._branch.getIntPref(this.name); |
|
309 case "bool": |
|
310 var val = this._branch.getBoolPref(this.name); |
|
311 return this.inverted ? !val : val; |
|
312 case "wstring": |
|
313 return this._branch |
|
314 .getComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString) |
|
315 .data; |
|
316 case "string": |
|
317 case "unichar": |
|
318 return this._branch |
|
319 .getComplexValue(this.name, Components.interfaces.nsISupportsString) |
|
320 .data; |
|
321 case "fontname": |
|
322 var family = this._branch |
|
323 .getComplexValue(this.name, Components.interfaces.nsISupportsString) |
|
324 .data; |
|
325 var fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"] |
|
326 .createInstance(Components.interfaces.nsIFontEnumerator); |
|
327 return fontEnumerator.getStandardFamilyName(family); |
|
328 case "file": |
|
329 var f = this._branch |
|
330 .getComplexValue(this.name, Components.interfaces.nsILocalFile); |
|
331 return f; |
|
332 default: |
|
333 this._reportUnknownType(); |
|
334 } |
|
335 } |
|
336 catch (e) { } |
|
337 return null; |
|
338 ]]> |
|
339 </getter> |
|
340 <setter> |
|
341 <![CDATA[ |
|
342 // Exit early if nothing to do. |
|
343 if (this.readonly || this.valueFromPreferences == val) |
|
344 return val; |
|
345 |
|
346 // The special value undefined means 'reset preference to default'. |
|
347 if (val === undefined) { |
|
348 this.preferences.rootBranch.clearUserPref(this.name); |
|
349 return val; |
|
350 } |
|
351 |
|
352 // Force a resync of preferences with value. |
|
353 switch (this.type) { |
|
354 case "int": |
|
355 this.preferences.rootBranch.setIntPref(this.name, val); |
|
356 break; |
|
357 case "bool": |
|
358 this.preferences.rootBranch.setBoolPref(this.name, this.inverted ? !val : val); |
|
359 break; |
|
360 case "wstring": |
|
361 var pls = Components.classes["@mozilla.org/pref-localizedstring;1"] |
|
362 .createInstance(Components.interfaces.nsIPrefLocalizedString); |
|
363 pls.data = val; |
|
364 this.preferences.rootBranch |
|
365 .setComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString, pls); |
|
366 break; |
|
367 case "string": |
|
368 case "unichar": |
|
369 case "fontname": |
|
370 var iss = Components.classes["@mozilla.org/supports-string;1"] |
|
371 .createInstance(Components.interfaces.nsISupportsString); |
|
372 iss.data = val; |
|
373 this.preferences.rootBranch |
|
374 .setComplexValue(this.name, Components.interfaces.nsISupportsString, iss); |
|
375 break; |
|
376 case "file": |
|
377 var lf; |
|
378 if (typeof(val) == "string") { |
|
379 lf = Components.classes["@mozilla.org/file/local;1"] |
|
380 .createInstance(Components.interfaces.nsILocalFile); |
|
381 lf.persistentDescriptor = val; |
|
382 if (!lf.exists()) |
|
383 lf.initWithPath(val); |
|
384 } |
|
385 else |
|
386 lf = val.QueryInterface(Components.interfaces.nsILocalFile); |
|
387 this.preferences.rootBranch |
|
388 .setComplexValue(this.name, Components.interfaces.nsILocalFile, lf); |
|
389 break; |
|
390 default: |
|
391 this._reportUnknownType(); |
|
392 } |
|
393 if (!this.batching) |
|
394 this.preferences.service.savePrefFile(null); |
|
395 return val; |
|
396 ]]> |
|
397 </setter> |
|
398 </property> |
|
399 |
|
400 <method name="setElementValue"> |
|
401 <parameter name="aElement"/> |
|
402 <body> |
|
403 <![CDATA[ |
|
404 if (this.locked) |
|
405 aElement.disabled = true; |
|
406 |
|
407 if (!this.isElementEditable(aElement)) |
|
408 return; |
|
409 |
|
410 var rv = undefined; |
|
411 if (aElement.hasAttribute("onsyncfrompreference")) { |
|
412 // Value changed, synthesize an event |
|
413 try { |
|
414 var event = document.createEvent("Events"); |
|
415 event.initEvent("syncfrompreference", true, true); |
|
416 var f = new Function ("event", |
|
417 aElement.getAttribute("onsyncfrompreference")); |
|
418 rv = f.call(aElement, event); |
|
419 } |
|
420 catch (e) { |
|
421 Components.utils.reportError(e); |
|
422 } |
|
423 } |
|
424 var val = rv !== undefined ? rv : (this.instantApply ? this.valueFromPreferences : this.value); |
|
425 // if the preference is marked for reset, show default value in UI |
|
426 if (val === undefined) |
|
427 val = this.defaultValue; |
|
428 |
|
429 /** |
|
430 * Initialize a UI element property with a value. Handles the case |
|
431 * where an element has not yet had a XBL binding attached for it and |
|
432 * the property setter does not yet exist by setting the same attribute |
|
433 * on the XUL element using DOM apis and assuming the element's |
|
434 * constructor or property getters appropriately handle this state. |
|
435 */ |
|
436 function setValue(element, attribute, value) { |
|
437 if (attribute in element) |
|
438 element[attribute] = value; |
|
439 else |
|
440 element.setAttribute(attribute, value); |
|
441 } |
|
442 if (aElement.localName == "checkbox" || |
|
443 aElement.localName == "listitem") |
|
444 setValue(aElement, "checked", val); |
|
445 else if (aElement.localName == "colorpicker") |
|
446 setValue(aElement, "color", val); |
|
447 else if (aElement.localName == "textbox") { |
|
448 // XXXmano Bug 303998: Avoid a caret placement issue if either the |
|
449 // preference observer or its setter calls updateElements as a result |
|
450 // of the input event handler. |
|
451 if (aElement.value !== val) |
|
452 setValue(aElement, "value", val); |
|
453 } |
|
454 else |
|
455 setValue(aElement, "value", val); |
|
456 ]]> |
|
457 </body> |
|
458 </method> |
|
459 |
|
460 <method name="getElementValue"> |
|
461 <parameter name="aElement"/> |
|
462 <body> |
|
463 <![CDATA[ |
|
464 if (aElement.hasAttribute("onsynctopreference")) { |
|
465 // Value changed, synthesize an event |
|
466 try { |
|
467 var event = document.createEvent("Events"); |
|
468 event.initEvent("synctopreference", true, true); |
|
469 var f = new Function ("event", |
|
470 aElement.getAttribute("onsynctopreference")); |
|
471 var rv = f.call(aElement, event); |
|
472 if (rv !== undefined) |
|
473 return rv; |
|
474 } |
|
475 catch (e) { |
|
476 Components.utils.reportError(e); |
|
477 } |
|
478 } |
|
479 |
|
480 /** |
|
481 * Read the value of an attribute from an element, assuming the |
|
482 * attribute is a property on the element's node API. If the property |
|
483 * is not present in the API, then assume its value is contained in |
|
484 * an attribute, as is the case before a binding has been attached. |
|
485 */ |
|
486 function getValue(element, attribute) { |
|
487 if (attribute in element) |
|
488 return element[attribute]; |
|
489 return element.getAttribute(attribute); |
|
490 } |
|
491 if (aElement.localName == "checkbox" || |
|
492 aElement.localName == "listitem") |
|
493 var value = getValue(aElement, "checked"); |
|
494 else if (aElement.localName == "colorpicker") |
|
495 value = getValue(aElement, "color"); |
|
496 else |
|
497 value = getValue(aElement, "value"); |
|
498 |
|
499 switch (this.type) { |
|
500 case "int": |
|
501 return parseInt(value, 10) || 0; |
|
502 case "bool": |
|
503 return typeof(value) == "boolean" ? value : value == "true"; |
|
504 } |
|
505 return value; |
|
506 ]]> |
|
507 </body> |
|
508 </method> |
|
509 |
|
510 <method name="isElementEditable"> |
|
511 <parameter name="aElement"/> |
|
512 <body> |
|
513 <![CDATA[ |
|
514 switch (aElement.localName) { |
|
515 case "checkbox": |
|
516 case "colorpicker": |
|
517 case "radiogroup": |
|
518 case "textbox": |
|
519 case "listitem": |
|
520 case "listbox": |
|
521 case "menulist": |
|
522 return true; |
|
523 } |
|
524 return aElement.getAttribute("preference-editable") == "true"; |
|
525 ]]> |
|
526 </body> |
|
527 </method> |
|
528 |
|
529 <method name="updateElements"> |
|
530 <body> |
|
531 <![CDATA[ |
|
532 if (!this.id) |
|
533 return; |
|
534 |
|
535 // This "change" event handler tracks changes made to preferences by |
|
536 // sources other than the user in this window. |
|
537 var elements = document.getElementsByAttribute("preference", this.id); |
|
538 for (var i = 0; i < elements.length; ++i) |
|
539 this.setElementValue(elements[i]); |
|
540 ]]> |
|
541 </body> |
|
542 </method> |
|
543 </implementation> |
|
544 |
|
545 <handlers> |
|
546 <handler event="change"> |
|
547 this.updateElements(); |
|
548 </handler> |
|
549 </handlers> |
|
550 </binding> |
|
551 |
|
552 <binding id="prefwindow" |
|
553 extends="chrome://global/content/bindings/dialog.xml#dialog"> |
|
554 <resources> |
|
555 <stylesheet src="chrome://global/skin/preferences.css"/> |
|
556 </resources> |
|
557 <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY" |
|
558 closebuttonlabel="&preferencesCloseButton.label;" |
|
559 closebuttonaccesskey="&preferencesCloseButton.accesskey;" |
|
560 role="dialog" |
|
561 #ifdef XP_WIN |
|
562 title="&preferencesDefaultTitleWin.title;"> |
|
563 #else |
|
564 title="&preferencesDefaultTitleMac.title;"> |
|
565 #endif |
|
566 <xul:windowdragbox orient="vertical"> |
|
567 <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar" |
|
568 role="listbox"/> <!-- Expose to accessibility APIs as a listbox --> |
|
569 </xul:windowdragbox> |
|
570 <xul:hbox flex="1" class="paneDeckContainer"> |
|
571 <xul:deck anonid="paneDeck" flex="1"> |
|
572 <children includes="prefpane"/> |
|
573 </xul:deck> |
|
574 </xul:hbox> |
|
575 <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons" pack="end"> |
|
576 #ifdef XP_UNIX |
|
577 <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> |
|
578 <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/> |
|
579 <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> |
|
580 <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> |
|
581 <xul:spacer anonid="spacer" flex="1"/> |
|
582 <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/> |
|
583 <xul:button dlgtype="accept" class="dialog-button" icon="accept"/> |
|
584 #else |
|
585 <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> |
|
586 <xul:spacer anonid="spacer" flex="1"/> |
|
587 <xul:button dlgtype="accept" class="dialog-button" icon="accept"/> |
|
588 <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> |
|
589 <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/> |
|
590 <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/> |
|
591 <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> |
|
592 #endif |
|
593 </xul:hbox> |
|
594 <xul:hbox> |
|
595 <children/> |
|
596 </xul:hbox> |
|
597 </content> |
|
598 <implementation implements="nsITimerCallback"> |
|
599 <constructor> |
|
600 <![CDATA[ |
|
601 if (this.type != "child") { |
|
602 var psvc = Components.classes["@mozilla.org/preferences-service;1"] |
|
603 .getService(Components.interfaces.nsIPrefBranch); |
|
604 this.instantApply = psvc.getBoolPref("browser.preferences.instantApply"); |
|
605 if (this.instantApply) { |
|
606 var docElt = document.documentElement; |
|
607 var acceptButton = docElt.getButton("accept"); |
|
608 acceptButton.hidden = true; |
|
609 var cancelButton = docElt.getButton("cancel"); |
|
610 #ifdef XP_MACOSX |
|
611 // no buttons on Mac except Help |
|
612 cancelButton.hidden = true; |
|
613 // Move Help button to the end |
|
614 document.getAnonymousElementByAttribute(this, "anonid", "spacer").hidden = true; |
|
615 // Also, don't fire onDialogAccept on enter |
|
616 acceptButton.disabled = true; |
|
617 #else |
|
618 // morph the Cancel button into the Close button |
|
619 cancelButton.setAttribute ("icon", "close"); |
|
620 cancelButton.label = docElt.getAttribute("closebuttonlabel"); |
|
621 cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey"); |
|
622 #endif |
|
623 } |
|
624 } |
|
625 this.setAttribute("animated", this._shouldAnimate ? "true" : "false"); |
|
626 var panes = this.preferencePanes; |
|
627 |
|
628 var lastPane = null; |
|
629 if (this.lastSelected) { |
|
630 lastPane = document.getElementById(this.lastSelected); |
|
631 if (!lastPane) { |
|
632 this.lastSelected = ""; |
|
633 } |
|
634 } |
|
635 |
|
636 var paneToLoad; |
|
637 if ("arguments" in window && window.arguments[0] && document.getElementById(window.arguments[0]) && document.getElementById(window.arguments[0]).nodeName == "prefpane") { |
|
638 paneToLoad = document.getElementById(window.arguments[0]); |
|
639 this.lastSelected = paneToLoad.id; |
|
640 } |
|
641 else if (lastPane) |
|
642 paneToLoad = lastPane; |
|
643 else |
|
644 paneToLoad = panes[0]; |
|
645 |
|
646 for (var i = 0; i < panes.length; ++i) { |
|
647 this._makePaneButton(panes[i]); |
|
648 if (panes[i].loaded) { |
|
649 // Inline pane content, fire load event to force initialization. |
|
650 this._fireEvent("paneload", panes[i]); |
|
651 } |
|
652 } |
|
653 this.showPane(paneToLoad); |
|
654 |
|
655 if (panes.length == 1) |
|
656 this._selector.setAttribute("collapsed", "true"); |
|
657 ]]> |
|
658 </constructor> |
|
659 |
|
660 <destructor> |
|
661 <![CDATA[ |
|
662 // Release timers to avoid reference cycles. |
|
663 if (this._animateTimer) { |
|
664 this._animateTimer.cancel(); |
|
665 this._animateTimer = null; |
|
666 } |
|
667 if (this._fadeTimer) { |
|
668 this._fadeTimer.cancel(); |
|
669 this._fadeTimer = null; |
|
670 } |
|
671 ]]> |
|
672 </destructor> |
|
673 |
|
674 <field name="instantApply">false</field> |
|
675 |
|
676 <property name="preferencePanes" |
|
677 onget="return this.getElementsByTagName('prefpane');"/> |
|
678 |
|
679 <property name="type" onget="return this.getAttribute('type');"/> |
|
680 <property name="_paneDeck" |
|
681 onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/> |
|
682 <property name="_paneDeckContainer" |
|
683 onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/> |
|
684 <property name="_selector" |
|
685 onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/> |
|
686 <property name="lastSelected" |
|
687 onget="return this.getAttribute('lastSelected');"> |
|
688 <setter> |
|
689 this.setAttribute("lastSelected", val); |
|
690 document.persist(this.id, "lastSelected"); |
|
691 return val; |
|
692 </setter> |
|
693 </property> |
|
694 <property name="currentPane" |
|
695 onset="return this._currentPane = val;"> |
|
696 <getter> |
|
697 if (!this._currentPane) |
|
698 this._currentPane = this.preferencePanes[0]; |
|
699 |
|
700 return this._currentPane; |
|
701 </getter> |
|
702 </property> |
|
703 <field name="_currentPane">null</field> |
|
704 |
|
705 |
|
706 <method name="_makePaneButton"> |
|
707 <parameter name="aPaneElement"/> |
|
708 <body> |
|
709 <![CDATA[ |
|
710 var radio = document.createElement("radio"); |
|
711 radio.setAttribute("pane", aPaneElement.id); |
|
712 radio.setAttribute("label", aPaneElement.label); |
|
713 // Expose preference group choice to accessibility APIs as an unchecked list item |
|
714 // The parent group is exposed to accessibility APIs as a list |
|
715 if (aPaneElement.image) |
|
716 radio.setAttribute("src", aPaneElement.image); |
|
717 radio.style.listStyleImage = aPaneElement.style.listStyleImage; |
|
718 this._selector.appendChild(radio); |
|
719 return radio; |
|
720 ]]> |
|
721 </body> |
|
722 </method> |
|
723 |
|
724 <method name="showPane"> |
|
725 <parameter name="aPaneElement"/> |
|
726 <body> |
|
727 <![CDATA[ |
|
728 if (!aPaneElement) |
|
729 return; |
|
730 |
|
731 this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id); |
|
732 if (!aPaneElement.loaded) { |
|
733 let OverlayLoadObserver = function(aPane) |
|
734 { |
|
735 this._pane = aPane; |
|
736 } |
|
737 OverlayLoadObserver.prototype = { |
|
738 _outer: this, |
|
739 observe: function (aSubject, aTopic, aData) |
|
740 { |
|
741 this._pane.loaded = true; |
|
742 this._outer._fireEvent("paneload", this._pane); |
|
743 this._outer._selectPane(this._pane); |
|
744 } |
|
745 }; |
|
746 |
|
747 var obs = new OverlayLoadObserver(aPaneElement); |
|
748 document.loadOverlay(aPaneElement.src, obs); |
|
749 } |
|
750 else |
|
751 this._selectPane(aPaneElement); |
|
752 ]]> |
|
753 </body> |
|
754 </method> |
|
755 |
|
756 <method name="_fireEvent"> |
|
757 <parameter name="aEventName"/> |
|
758 <parameter name="aTarget"/> |
|
759 <body> |
|
760 <![CDATA[ |
|
761 // Panel loaded, synthesize a load event. |
|
762 try { |
|
763 var event = document.createEvent("Events"); |
|
764 event.initEvent(aEventName, true, true); |
|
765 var cancel = !aTarget.dispatchEvent(event); |
|
766 if (aTarget.hasAttribute("on" + aEventName)) { |
|
767 var fn = new Function ("event", aTarget.getAttribute("on" + aEventName)); |
|
768 var rv = fn.call(aTarget, event); |
|
769 if (rv == false) |
|
770 cancel = true; |
|
771 } |
|
772 return !cancel; |
|
773 } |
|
774 catch (e) { |
|
775 Components.utils.reportError(e); |
|
776 } |
|
777 return false; |
|
778 ]]> |
|
779 </body> |
|
780 </method> |
|
781 |
|
782 <field name="_initialized">false</field> |
|
783 <method name="_selectPane"> |
|
784 <parameter name="aPaneElement"/> |
|
785 <body> |
|
786 <![CDATA[ |
|
787 #ifdef XP_MACOSX |
|
788 var paneTitle = aPaneElement.label; |
|
789 if (paneTitle != "") |
|
790 document.title = paneTitle; |
|
791 #endif |
|
792 var helpButton = document.documentElement.getButton("help"); |
|
793 if (aPaneElement.helpTopic) |
|
794 helpButton.hidden = false; |
|
795 else |
|
796 helpButton.hidden = true; |
|
797 |
|
798 // Find this pane's index in the deck and set the deck's |
|
799 // selectedIndex to that value to switch to it. |
|
800 var prefpanes = this.preferencePanes; |
|
801 for (var i = 0; i < prefpanes.length; ++i) { |
|
802 if (prefpanes[i] == aPaneElement) { |
|
803 this._paneDeck.selectedIndex = i; |
|
804 |
|
805 if (this.type != "child") { |
|
806 if (aPaneElement.hasAttribute("flex") && this._shouldAnimate && |
|
807 prefpanes.length > 1) |
|
808 aPaneElement.removeAttribute("flex"); |
|
809 // Calling sizeToContent after the first prefpane is loaded |
|
810 // will size the windows contents so style information is |
|
811 // available to calculate correct sizing. |
|
812 if (!this._initialized && prefpanes.length > 1) { |
|
813 if (this._shouldAnimate) |
|
814 this.style.minHeight = 0; |
|
815 window.sizeToContent(); |
|
816 } |
|
817 |
|
818 var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0]; |
|
819 oldPane.selected = !(aPaneElement.selected = true); |
|
820 this.lastSelected = aPaneElement.id; |
|
821 this.currentPane = aPaneElement; |
|
822 this._initialized = true; |
|
823 |
|
824 // Only animate if we've switched between prefpanes |
|
825 if (this._shouldAnimate && oldPane.id != aPaneElement.id) { |
|
826 aPaneElement.style.opacity = 0.0; |
|
827 this.animate(oldPane, aPaneElement); |
|
828 } |
|
829 else if (!this._shouldAnimate && prefpanes.length > 1) { |
|
830 var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer, "").height); |
|
831 var verticalPadding = parseInt(window.getComputedStyle(aPaneElement, "").paddingTop); |
|
832 verticalPadding += parseInt(window.getComputedStyle(aPaneElement, "").paddingBottom); |
|
833 if (aPaneElement.contentHeight > targetHeight - verticalPadding) { |
|
834 // To workaround the bottom border of a groupbox from being |
|
835 // cutoff an hbox with a class of bottomBox may enclose it. |
|
836 // This needs to include its padding to resize properly. |
|
837 // See bug 394433 |
|
838 var bottomPadding = 0; |
|
839 var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0]; |
|
840 if (bottomBox) |
|
841 bottomPadding = parseInt(window.getComputedStyle(bottomBox, "").paddingBottom); |
|
842 window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight; |
|
843 } |
|
844 |
|
845 // XXX rstrong - extend the contents of the prefpane to |
|
846 // prevent elements from being cutoff (see bug 349098). |
|
847 if (aPaneElement.contentHeight + verticalPadding < targetHeight) |
|
848 aPaneElement._content.style.height = targetHeight - verticalPadding + "px"; |
|
849 } |
|
850 } |
|
851 break; |
|
852 } |
|
853 } |
|
854 ]]> |
|
855 </body> |
|
856 </method> |
|
857 |
|
858 <property name="_shouldAnimate"> |
|
859 <getter> |
|
860 <![CDATA[ |
|
861 var psvc = Components.classes["@mozilla.org/preferences-service;1"] |
|
862 .getService(Components.interfaces.nsIPrefBranch); |
|
863 #ifdef XP_MACOSX |
|
864 var animate = true; |
|
865 #else |
|
866 var animate = false; |
|
867 #endif |
|
868 try { |
|
869 animate = psvc.getBoolPref("browser.preferences.animateFadeIn"); |
|
870 } |
|
871 catch (e) { } |
|
872 return animate; |
|
873 ]]> |
|
874 </getter> |
|
875 </property> |
|
876 |
|
877 <method name="animate"> |
|
878 <parameter name="aOldPane"/> |
|
879 <parameter name="aNewPane"/> |
|
880 <body> |
|
881 <![CDATA[ |
|
882 // if we are already resizing, use currentHeight |
|
883 var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight; |
|
884 |
|
885 this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1; |
|
886 var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight); |
|
887 this._animateRemainder = sizeDelta % this._animateIncrement; |
|
888 |
|
889 this._setUpAnimationTimer(oldHeight); |
|
890 ]]> |
|
891 </body> |
|
892 </method> |
|
893 |
|
894 <property name="_sizeIncrement"> |
|
895 <getter> |
|
896 <![CDATA[ |
|
897 var lastSelectedPane = document.getElementById(this.lastSelected); |
|
898 var increment = this._animateIncrement * this._multiplier; |
|
899 var newHeight = this._currentHeight + increment; |
|
900 if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) || |
|
901 (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight)) |
|
902 return 0; |
|
903 |
|
904 if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) || |
|
905 (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight)) |
|
906 increment = this._animateRemainder * this._multiplier; |
|
907 return increment; |
|
908 ]]> |
|
909 </getter> |
|
910 </property> |
|
911 |
|
912 <method name="notify"> |
|
913 <parameter name="aTimer"/> |
|
914 <body> |
|
915 <![CDATA[ |
|
916 if (!document) |
|
917 aTimer.cancel(); |
|
918 |
|
919 if (aTimer == this._animateTimer) { |
|
920 var increment = this._sizeIncrement; |
|
921 if (increment != 0) { |
|
922 window.innerHeight += increment; |
|
923 this._currentHeight += increment; |
|
924 } |
|
925 else { |
|
926 aTimer.cancel(); |
|
927 this._setUpFadeTimer(); |
|
928 } |
|
929 } else if (aTimer == this._fadeTimer) { |
|
930 var elt = document.getElementById(this.lastSelected); |
|
931 var newOpacity = parseFloat(window.getComputedStyle(elt, "").opacity) + this._fadeIncrement; |
|
932 if (newOpacity < 1.0) |
|
933 elt.style.opacity = newOpacity; |
|
934 else { |
|
935 aTimer.cancel(); |
|
936 elt.style.opacity = 1.0; |
|
937 } |
|
938 } |
|
939 ]]> |
|
940 </body> |
|
941 </method> |
|
942 |
|
943 <method name="_setUpAnimationTimer"> |
|
944 <parameter name="aStartHeight"/> |
|
945 <body> |
|
946 <![CDATA[ |
|
947 if (!this._animateTimer) |
|
948 this._animateTimer = Components.classes["@mozilla.org/timer;1"] |
|
949 .createInstance(Components.interfaces.nsITimer); |
|
950 else |
|
951 this._animateTimer.cancel(); |
|
952 this._currentHeight = aStartHeight; |
|
953 |
|
954 this._animateTimer.initWithCallback(this, this._animateDelay, |
|
955 Components.interfaces.nsITimer.TYPE_REPEATING_SLACK); |
|
956 ]]> |
|
957 </body> |
|
958 </method> |
|
959 |
|
960 <method name="_setUpFadeTimer"> |
|
961 <body> |
|
962 <![CDATA[ |
|
963 if (!this._fadeTimer) |
|
964 this._fadeTimer = Components.classes["@mozilla.org/timer;1"] |
|
965 .createInstance(Components.interfaces.nsITimer); |
|
966 else |
|
967 this._fadeTimer.cancel(); |
|
968 |
|
969 this._fadeTimer.initWithCallback(this, this._fadeDelay, |
|
970 Components.interfaces.nsITimer.TYPE_REPEATING_SLACK); |
|
971 ]]> |
|
972 </body> |
|
973 </method> |
|
974 |
|
975 <field name="_animateTimer">null</field> |
|
976 <field name="_fadeTimer">null</field> |
|
977 <field name="_animateDelay">15</field> |
|
978 <field name="_animateIncrement">40</field> |
|
979 <field name="_fadeDelay">5</field> |
|
980 <field name="_fadeIncrement">0.40</field> |
|
981 <field name="_animateRemainder">0</field> |
|
982 <field name="_currentHeight">0</field> |
|
983 <field name="_multiplier">0</field> |
|
984 |
|
985 <method name="addPane"> |
|
986 <parameter name="aPaneElement"/> |
|
987 <body> |
|
988 <![CDATA[ |
|
989 this.appendChild(aPaneElement); |
|
990 |
|
991 // Set up pane button |
|
992 this._makePaneButton(aPaneElement); |
|
993 ]]> |
|
994 </body> |
|
995 </method> |
|
996 |
|
997 <method name="openSubDialog"> |
|
998 <parameter name="aURL"/> |
|
999 <parameter name="aFeatures"/> |
|
1000 <parameter name="aParams"/> |
|
1001 <body> |
|
1002 return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams); |
|
1003 </body> |
|
1004 </method> |
|
1005 |
|
1006 <method name="openWindow"> |
|
1007 <parameter name="aWindowType"/> |
|
1008 <parameter name="aURL"/> |
|
1009 <parameter name="aFeatures"/> |
|
1010 <parameter name="aParams"/> |
|
1011 <body> |
|
1012 <![CDATA[ |
|
1013 var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] |
|
1014 .getService(Components.interfaces.nsIWindowMediator); |
|
1015 var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null; |
|
1016 if (win) { |
|
1017 if ("initWithParams" in win) |
|
1018 win.initWithParams(aParams); |
|
1019 win.focus(); |
|
1020 } |
|
1021 else { |
|
1022 var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : ""); |
|
1023 var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener; |
|
1024 win = parentWindow.openDialog(aURL, "_blank", features, aParams); |
|
1025 } |
|
1026 return win; |
|
1027 ]]> |
|
1028 </body> |
|
1029 </method> |
|
1030 </implementation> |
|
1031 <handlers> |
|
1032 <handler event="dialogaccept"> |
|
1033 <![CDATA[ |
|
1034 if (!this._fireEvent("beforeaccept", this)){ |
|
1035 return false; |
|
1036 } |
|
1037 |
|
1038 if (this.type == "child" && window.opener) { |
|
1039 var psvc = Components.classes["@mozilla.org/preferences-service;1"] |
|
1040 .getService(Components.interfaces.nsIPrefBranch); |
|
1041 var instantApply = psvc.getBoolPref("browser.preferences.instantApply"); |
|
1042 if (instantApply) { |
|
1043 var panes = this.preferencePanes; |
|
1044 for (var i = 0; i < panes.length; ++i) |
|
1045 panes[i].writePreferences(true); |
|
1046 } |
|
1047 else { |
|
1048 // Clone all the preferences elements from the child document and |
|
1049 // insert them into the pane collection of the parent. |
|
1050 var pdoc = window.opener.document; |
|
1051 if (pdoc.documentElement.localName == "prefwindow") { |
|
1052 var currentPane = pdoc.documentElement.currentPane; |
|
1053 var id = window.location.href + "#childprefs"; |
|
1054 var childPrefs = pdoc.getElementById(id); |
|
1055 if (!childPrefs) { |
|
1056 var childPrefs = pdoc.createElement("preferences"); |
|
1057 currentPane.appendChild(childPrefs); |
|
1058 childPrefs.id = id; |
|
1059 } |
|
1060 var panes = this.preferencePanes; |
|
1061 for (var i = 0; i < panes.length; ++i) { |
|
1062 var preferences = panes[i].preferences; |
|
1063 for (var j = 0; j < preferences.length; ++j) { |
|
1064 // Try to find a preference element for the same preference. |
|
1065 var preference = null; |
|
1066 var parentPreferences = pdoc.getElementsByTagName("preferences"); |
|
1067 for (var k = 0; (k < parentPreferences.length && !preference); ++k) { |
|
1068 var parentPrefs = parentPreferences[k] |
|
1069 .getElementsByAttribute("name", preferences[j].name); |
|
1070 for (var l = 0; (l < parentPrefs.length && !preference); ++l) { |
|
1071 if (parentPrefs[l].localName == "preference") |
|
1072 preference = parentPrefs[l]; |
|
1073 } |
|
1074 } |
|
1075 if (!preference) { |
|
1076 // No matching preference in the parent window. |
|
1077 preference = pdoc.createElement("preference"); |
|
1078 childPrefs.appendChild(preference); |
|
1079 preference.name = preferences[j].name; |
|
1080 preference.type = preferences[j].type; |
|
1081 preference.inverted = preferences[j].inverted; |
|
1082 preference.readonly = preferences[j].readonly; |
|
1083 preference.disabled = preferences[j].disabled; |
|
1084 } |
|
1085 preference.value = preferences[j].value; |
|
1086 } |
|
1087 } |
|
1088 } |
|
1089 } |
|
1090 } |
|
1091 else { |
|
1092 var panes = this.preferencePanes; |
|
1093 for (var i = 0; i < panes.length; ++i) |
|
1094 panes[i].writePreferences(false); |
|
1095 |
|
1096 var psvc = Components.classes["@mozilla.org/preferences-service;1"] |
|
1097 .getService(Components.interfaces.nsIPrefService); |
|
1098 psvc.savePrefFile(null); |
|
1099 } |
|
1100 |
|
1101 return true; |
|
1102 ]]> |
|
1103 </handler> |
|
1104 <handler event="command"> |
|
1105 if (event.originalTarget.hasAttribute("pane")) { |
|
1106 var pane = document.getElementById(event.originalTarget.getAttribute("pane")); |
|
1107 this.showPane(pane); |
|
1108 } |
|
1109 </handler> |
|
1110 |
|
1111 <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing"> |
|
1112 <![CDATA[ |
|
1113 if (this.instantApply) |
|
1114 window.close(); |
|
1115 event.stopPropagation(); |
|
1116 event.preventDefault(); |
|
1117 ]]> |
|
1118 </handler> |
|
1119 |
|
1120 <handler event="keypress" |
|
1121 #ifdef XP_MACOSX |
|
1122 key="&openHelpMac.commandkey;" modifiers="accel" |
|
1123 #else |
|
1124 keycode="&openHelp.commandkey;" |
|
1125 #endif |
|
1126 phase="capturing"> |
|
1127 <![CDATA[ |
|
1128 var helpButton = this.getButton("help"); |
|
1129 if (helpButton.disabled || helpButton.hidden) |
|
1130 return; |
|
1131 this._fireEvent("dialoghelp", this); |
|
1132 event.stopPropagation(); |
|
1133 event.preventDefault(); |
|
1134 ]]> |
|
1135 </handler> |
|
1136 </handlers> |
|
1137 </binding> |
|
1138 |
|
1139 <binding id="prefpane"> |
|
1140 <resources> |
|
1141 <stylesheet src="chrome://global/skin/preferences.css"/> |
|
1142 </resources> |
|
1143 <content> |
|
1144 <xul:vbox class="content-box" xbl:inherits="flex"> |
|
1145 <children/> |
|
1146 </xul:vbox> |
|
1147 </content> |
|
1148 <implementation> |
|
1149 <method name="writePreferences"> |
|
1150 <parameter name="aFlushToDisk"/> |
|
1151 <body> |
|
1152 <![CDATA[ |
|
1153 // Write all values to preferences. |
|
1154 var preferences = this.preferences; |
|
1155 for (var i = 0; i < preferences.length; ++i) { |
|
1156 var preference = preferences[i]; |
|
1157 preference.batching = true; |
|
1158 preference.valueFromPreferences = preference.value; |
|
1159 preference.batching = false; |
|
1160 } |
|
1161 if (aFlushToDisk) { |
|
1162 var psvc = Components.classes["@mozilla.org/preferences-service;1"] |
|
1163 .getService(Components.interfaces.nsIPrefService); |
|
1164 psvc.savePrefFile(null); |
|
1165 } |
|
1166 ]]> |
|
1167 </body> |
|
1168 </method> |
|
1169 |
|
1170 <property name="src" |
|
1171 onget="return this.getAttribute('src');" |
|
1172 onset="this.setAttribute('src', val); return val;"/> |
|
1173 <property name="selected" |
|
1174 onget="return this.getAttribute('selected') == 'true';" |
|
1175 onset="this.setAttribute('selected', val); return val;"/> |
|
1176 <property name="image" |
|
1177 onget="return this.getAttribute('image');" |
|
1178 onset="this.setAttribute('image', val); return val;"/> |
|
1179 <property name="label" |
|
1180 onget="return this.getAttribute('label');" |
|
1181 onset="this.setAttribute('label', val); return val;"/> |
|
1182 |
|
1183 <property name="preferenceElements" |
|
1184 onget="return this.getElementsByAttribute('preference', '*');"/> |
|
1185 <property name="preferences" |
|
1186 onget="return this.getElementsByTagName('preference');"/> |
|
1187 |
|
1188 <property name="helpTopic"> |
|
1189 <getter> |
|
1190 <![CDATA[ |
|
1191 // if there are tabs, and the selected tab provides a helpTopic, return that |
|
1192 var box = this.getElementsByTagName("tabbox"); |
|
1193 if (box[0]) { |
|
1194 var tab = box[0].selectedTab; |
|
1195 if (tab && tab.hasAttribute("helpTopic")) |
|
1196 return tab.getAttribute("helpTopic"); |
|
1197 } |
|
1198 |
|
1199 // otherwise, return the helpTopic of the current panel |
|
1200 return this.getAttribute("helpTopic"); |
|
1201 ]]> |
|
1202 </getter> |
|
1203 </property> |
|
1204 |
|
1205 <field name="_loaded">false</field> |
|
1206 <property name="loaded" |
|
1207 onget="return !this.src ? true : this._loaded;" |
|
1208 onset="this._loaded = val; return val;"/> |
|
1209 |
|
1210 <method name="preferenceForElement"> |
|
1211 <parameter name="aElement"/> |
|
1212 <body> |
|
1213 return document.getElementById(aElement.getAttribute("preference")); |
|
1214 </body> |
|
1215 </method> |
|
1216 |
|
1217 <method name="getPreferenceElement"> |
|
1218 <parameter name="aStartElement"/> |
|
1219 <body> |
|
1220 <![CDATA[ |
|
1221 var temp = aStartElement; |
|
1222 while (temp && temp.nodeType == Node.ELEMENT_NODE && |
|
1223 !temp.hasAttribute("preference")) |
|
1224 temp = temp.parentNode; |
|
1225 return temp.nodeType == Node.ELEMENT_NODE ? temp : aStartElement; |
|
1226 ]]> |
|
1227 </body> |
|
1228 </method> |
|
1229 |
|
1230 <method name="userChangedValue"> |
|
1231 <parameter name="aElement"/> |
|
1232 <body> |
|
1233 <![CDATA[ |
|
1234 var element = this.getPreferenceElement(aElement); |
|
1235 if (element.hasAttribute("preference")) { |
|
1236 var preference = document.getElementById(element.getAttribute("preference")); |
|
1237 var prefVal = preference.getElementValue(element); |
|
1238 preference.value = prefVal; |
|
1239 } |
|
1240 ]]> |
|
1241 </body> |
|
1242 </method> |
|
1243 |
|
1244 <property name="contentHeight"> |
|
1245 <getter> |
|
1246 var targetHeight = parseInt(window.getComputedStyle(this._content, "").height); |
|
1247 targetHeight += parseInt(window.getComputedStyle(this._content, "").marginTop); |
|
1248 targetHeight += parseInt(window.getComputedStyle(this._content, "").marginBottom); |
|
1249 return targetHeight; |
|
1250 </getter> |
|
1251 </property> |
|
1252 <field name="_content"> |
|
1253 document.getAnonymousElementByAttribute(this, "class", "content-box"); |
|
1254 </field> |
|
1255 </implementation> |
|
1256 <handlers> |
|
1257 <handler event="command"> |
|
1258 // This "command" event handler tracks changes made to preferences by |
|
1259 // the user in this window. |
|
1260 if (event.sourceEvent) |
|
1261 event = event.sourceEvent; |
|
1262 this.userChangedValue(event.target); |
|
1263 </handler> |
|
1264 <handler event="select"> |
|
1265 // This "select" event handler tracks changes made to colorpicker |
|
1266 // preferences by the user in this window. |
|
1267 if (event.target.localName == "colorpicker") |
|
1268 this.userChangedValue(event.target); |
|
1269 </handler> |
|
1270 <handler event="change"> |
|
1271 // This "change" event handler tracks changes made to preferences by |
|
1272 // the user in this window. |
|
1273 this.userChangedValue(event.target); |
|
1274 </handler> |
|
1275 <handler event="input"> |
|
1276 // This "input" event handler tracks changes made to preferences by |
|
1277 // the user in this window. |
|
1278 this.userChangedValue(event.target); |
|
1279 </handler> |
|
1280 <handler event="paneload"> |
|
1281 <![CDATA[ |
|
1282 // Initialize all values from preferences. |
|
1283 var elements = this.preferenceElements; |
|
1284 for (var i = 0; i < elements.length; ++i) { |
|
1285 try { |
|
1286 var preference = this.preferenceForElement(elements[i]); |
|
1287 preference.setElementValue(elements[i]); |
|
1288 } |
|
1289 catch (e) { |
|
1290 dump("*** No preference found for " + elements[i].getAttribute("preference") + "\n"); |
|
1291 } |
|
1292 } |
|
1293 ]]> |
|
1294 </handler> |
|
1295 </handlers> |
|
1296 </binding> |
|
1297 |
|
1298 <binding id="panebutton" role="xul:listitem" |
|
1299 extends="chrome://global/content/bindings/radio.xml#radio"> |
|
1300 <resources> |
|
1301 <stylesheet src="chrome://global/skin/preferences.css"/> |
|
1302 </resources> |
|
1303 <content> |
|
1304 <xul:image class="paneButtonIcon" xbl:inherits="src"/> |
|
1305 <xul:label class="paneButtonLabel" xbl:inherits="value=label"/> |
|
1306 </content> |
|
1307 </binding> |
|
1308 |
|
1309 </bindings> |
|
1310 |
|
1311 # -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
1312 # This Source Code Form is subject to the terms of the Mozilla Public |
|
1313 # License, v. 2.0. If a copy of the MPL was not distributed with this |
|
1314 # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|
1315 |
|
1316 # |
|
1317 # This is PrefWindow 6. The Code Could Well Be Ready, Are You? |
|
1318 # |
|
1319 # Historical References: |
|
1320 # PrefWindow V (February 1, 2003) |
|
1321 # PrefWindow IV (April 24, 2000) |
|
1322 # PrefWindow III (January 6, 2000) |
|
1323 # PrefWindow II (???) |
|
1324 # PrefWindow I (June 4, 1999) |
|
1325 # |