mobile/android/chrome/content/config.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4 "use strict";
michael@0 5
michael@0 6 const {classes: Cc, interfaces: Ci, manager: Cm, utils: Cu} = Components;
michael@0 7 Cu.import("resource://gre/modules/Services.jsm");
michael@0 8
michael@0 9 const VKB_ENTER_KEY = 13; // User press of VKB enter key
michael@0 10 const INITIAL_PAGE_DELAY = 500; // Initial pause on program start for scroll alignment
michael@0 11 const PREFS_BUFFER_MAX = 30; // Max prefs buffer size for getPrefsBuffer()
michael@0 12 const PAGE_SCROLL_TRIGGER = 200; // Triggers additional getPrefsBuffer() on user scroll-to-bottom
michael@0 13 const FILTER_CHANGE_TRIGGER = 200; // Delay between responses to filterInput changes
michael@0 14 const INNERHTML_VALUE_DELAY = 100; // Delay before providing prefs innerHTML value
michael@0 15
michael@0 16 let gStringBundle = Services.strings.createBundle("chrome://browser/locale/config.properties");
michael@0 17 let gClipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
michael@0 18
michael@0 19
michael@0 20 /* ============================== NewPrefDialog ==============================
michael@0 21 *
michael@0 22 * New Preference Dialog Object and methods
michael@0 23 *
michael@0 24 * Implements User Interfaces for creation of a single(new) Preference setting
michael@0 25 *
michael@0 26 */
michael@0 27 var NewPrefDialog = {
michael@0 28
michael@0 29 _prefsShield: null,
michael@0 30
michael@0 31 _newPrefsDialog: null,
michael@0 32 _newPrefItem: null,
michael@0 33 _prefNameInputElt: null,
michael@0 34 _prefTypeSelectElt: null,
michael@0 35
michael@0 36 _booleanValue: null,
michael@0 37 _booleanToggle: null,
michael@0 38 _stringValue: null,
michael@0 39 _intValue: null,
michael@0 40
michael@0 41 _positiveButton: null,
michael@0 42
michael@0 43 get type() {
michael@0 44 return this._prefTypeSelectElt.value;
michael@0 45 },
michael@0 46
michael@0 47 set type(aType) {
michael@0 48 this._prefTypeSelectElt.value = aType;
michael@0 49 switch(this._prefTypeSelectElt.value) {
michael@0 50 case "boolean":
michael@0 51 this._prefTypeSelectElt.selectedIndex = 0;
michael@0 52 break;
michael@0 53 case "string":
michael@0 54 this._prefTypeSelectElt.selectedIndex = 1;
michael@0 55 break;
michael@0 56 case "int":
michael@0 57 this._prefTypeSelectElt.selectedIndex = 2;
michael@0 58 break;
michael@0 59 }
michael@0 60
michael@0 61 this._newPrefItem.setAttribute("typestyle", aType);
michael@0 62 },
michael@0 63
michael@0 64 // Init the NewPrefDialog
michael@0 65 init: function AC_init() {
michael@0 66 this._prefsShield = document.getElementById("prefs-shield");
michael@0 67
michael@0 68 this._newPrefsDialog = document.getElementById("new-pref-container");
michael@0 69 this._newPrefItem = document.getElementById("new-pref-item");
michael@0 70 this._prefNameInputElt = document.getElementById("new-pref-name");
michael@0 71 this._prefTypeSelectElt = document.getElementById("new-pref-type");
michael@0 72
michael@0 73 this._booleanValue = document.getElementById("new-pref-value-boolean");
michael@0 74 this._stringValue = document.getElementById("new-pref-value-string");
michael@0 75 this._intValue = document.getElementById("new-pref-value-int");
michael@0 76
michael@0 77 this._positiveButton = document.getElementById("positive-button");
michael@0 78 },
michael@0 79
michael@0 80 // Called to update positive button to display text ("Create"/"Change), and enabled/disabled status
michael@0 81 // As new pref name is initially displayed, re-focused, or modifed during user input
michael@0 82 _updatePositiveButton: function AC_updatePositiveButton(aPrefName) {
michael@0 83 this._positiveButton.textContent = gStringBundle.GetStringFromName("newPref.createButton");
michael@0 84 this._positiveButton.setAttribute("disabled", true);
michael@0 85 if (aPrefName == "") {
michael@0 86 return;
michael@0 87 }
michael@0 88
michael@0 89 // If item already in list, it's being changed, else added
michael@0 90 let item = document.querySelector(".pref-item[name=" + aPrefName.quote() + "]");
michael@0 91 if (item) {
michael@0 92 this._positiveButton.textContent = gStringBundle.GetStringFromName("newPref.changeButton");
michael@0 93 } else {
michael@0 94 this._positiveButton.removeAttribute("disabled");
michael@0 95 }
michael@0 96 },
michael@0 97
michael@0 98 // When we want to cancel/hide an existing, or show a new pref dialog
michael@0 99 toggleShowHide: function AC_toggleShowHide() {
michael@0 100 if (this._newPrefsDialog.classList.contains("show")) {
michael@0 101 this.hide();
michael@0 102 } else {
michael@0 103 this._show();
michael@0 104 }
michael@0 105 },
michael@0 106
michael@0 107 // When we want to show the new pref dialog / shield the prefs list
michael@0 108 _show: function AC_show() {
michael@0 109 this._newPrefsDialog.classList.add("show");
michael@0 110 this._prefsShield.setAttribute("shown", true);
michael@0 111
michael@0 112 // Initial default field values
michael@0 113 this._prefNameInputElt.value = "";
michael@0 114 this._updatePositiveButton(this._prefNameInputElt.value);
michael@0 115
michael@0 116 this.type = "boolean";
michael@0 117 this._booleanValue.value = "false";
michael@0 118 this._stringValue.value = "";
michael@0 119 this._intValue.value = "";
michael@0 120
michael@0 121 this._prefNameInputElt.focus();
michael@0 122
michael@0 123 window.addEventListener("keypress", this.handleKeypress, false);
michael@0 124 },
michael@0 125
michael@0 126 // When we want to cancel/hide the new pref dialog / un-shield the prefs list
michael@0 127 hide: function AC_hide() {
michael@0 128 this._newPrefsDialog.classList.remove("show");
michael@0 129 this._prefsShield.removeAttribute("shown");
michael@0 130
michael@0 131 window.removeEventListener("keypress", this.handleKeypress, false);
michael@0 132 },
michael@0 133
michael@0 134 // Watch user key input so we can provide Enter key action, commit input values
michael@0 135 handleKeypress: function AC_handleKeypress(aEvent) {
michael@0 136 // Close our VKB on new pref enter key press
michael@0 137 if (aEvent.keyCode == VKB_ENTER_KEY)
michael@0 138 aEvent.target.blur();
michael@0 139 },
michael@0 140
michael@0 141 // New prefs create dialog only allows creating a non-existing preference, doesn't allow for
michael@0 142 // Changing an existing one on-the-fly, tap existing/displayed line item pref for that
michael@0 143 create: function AC_create(aEvent) {
michael@0 144 if (this._positiveButton.getAttribute("disabled") == "true") {
michael@0 145 return;
michael@0 146 }
michael@0 147
michael@0 148 switch(this.type) {
michael@0 149 case "boolean":
michael@0 150 Services.prefs.setBoolPref(this._prefNameInputElt.value, (this._booleanValue.value == "true") ? true : false);
michael@0 151 break;
michael@0 152 case "string":
michael@0 153 Services.prefs.setCharPref(this._prefNameInputElt.value, this._stringValue.value);
michael@0 154 break;
michael@0 155 case "int":
michael@0 156 Services.prefs.setIntPref(this._prefNameInputElt.value, this._intValue.value);
michael@0 157 break;
michael@0 158 }
michael@0 159
michael@0 160 this.hide();
michael@0 161 },
michael@0 162
michael@0 163 // Display proper positive button text/state on new prefs name input focus
michael@0 164 focusName: function AC_focusName(aEvent) {
michael@0 165 this._updatePositiveButton(aEvent.target.value);
michael@0 166 },
michael@0 167
michael@0 168 // Display proper positive button text/state as user changes new prefs name
michael@0 169 updateName: function AC_updateName(aEvent) {
michael@0 170 this._updatePositiveButton(aEvent.target.value);
michael@0 171 },
michael@0 172
michael@0 173 // In new prefs dialog, bool prefs are <input type="text">, as they aren't yet tied to an
michael@0 174 // Actual Services.prefs.*etBoolPref()
michael@0 175 toggleBoolValue: function AC_toggleBoolValue() {
michael@0 176 this._booleanValue.value = (this._booleanValue.value == "true" ? "false" : "true");
michael@0 177 }
michael@0 178 }
michael@0 179
michael@0 180
michael@0 181 /* ============================== AboutConfig ==============================
michael@0 182 *
michael@0 183 * Main AboutConfig object and methods
michael@0 184 *
michael@0 185 * Implements User Interfaces for maintenance of a list of Preference settings
michael@0 186 *
michael@0 187 */
michael@0 188 var AboutConfig = {
michael@0 189
michael@0 190 contextMenuLINode: null,
michael@0 191 filterInput: null,
michael@0 192 _filterPrevInput: null,
michael@0 193 _filterChangeTimer: null,
michael@0 194 _prefsContainer: null,
michael@0 195 _loadingContainer: null,
michael@0 196 _list: null,
michael@0 197
michael@0 198 // Init the main AboutConfig dialog
michael@0 199 init: function AC_init() {
michael@0 200 this.filterInput = document.getElementById("filter-input");
michael@0 201 this._prefsContainer = document.getElementById("prefs-container");
michael@0 202 this._loadingContainer = document.getElementById("loading-container");
michael@0 203
michael@0 204 let list = Services.prefs.getChildList("");
michael@0 205 this._list = list.sort().map( function AC_getMapPref(aPref) {
michael@0 206 return new Pref(aPref);
michael@0 207 }, this);
michael@0 208
michael@0 209 // Display the current prefs list (retains searchFilter value)
michael@0 210 this.bufferFilterInput();
michael@0 211
michael@0 212 // Setup the prefs observers
michael@0 213 Services.prefs.addObserver("", this, false);
michael@0 214 },
michael@0 215
michael@0 216 // Uninit the main AboutConfig dialog
michael@0 217 uninit: function AC_uninit() {
michael@0 218 // Remove the prefs observer
michael@0 219 Services.prefs.removeObserver("", this);
michael@0 220
michael@0 221 // Ensure pref adds/changes/resets flushed to disk on unload
michael@0 222 Services.prefs.savePrefFile(null);
michael@0 223 },
michael@0 224
michael@0 225 // Clear the filterInput value, to display the entire list
michael@0 226 clearFilterInput: function AC_clearFilterInput() {
michael@0 227 this.filterInput.value = "";
michael@0 228 this.bufferFilterInput();
michael@0 229 },
michael@0 230
michael@0 231 // Buffer down rapid changes in filterInput value from keyboard
michael@0 232 bufferFilterInput: function AC_bufferFilterInput() {
michael@0 233 if (this._filterChangeTimer) {
michael@0 234 clearTimeout(this._filterChangeTimer);
michael@0 235 }
michael@0 236
michael@0 237 this._filterChangeTimer = setTimeout((function() {
michael@0 238 this._filterChangeTimer = null;
michael@0 239 // Display updated prefs list when filterInput value settles
michael@0 240 this._displayNewList();
michael@0 241 }).bind(this), FILTER_CHANGE_TRIGGER);
michael@0 242 },
michael@0 243
michael@0 244 // Update displayed list when filterInput value changes
michael@0 245 _displayNewList: function AC_displayNewList() {
michael@0 246 // This survives the search filter value past a page refresh
michael@0 247 this.filterInput.setAttribute("value", this.filterInput.value);
michael@0 248
michael@0 249 // Don't start new filter search if same as last
michael@0 250 if (this.filterInput.value == this._filterPrevInput) {
michael@0 251 return;
michael@0 252 }
michael@0 253 this._filterPrevInput = this.filterInput.value;
michael@0 254
michael@0 255 // Clear list item selection / context menu, prefs list, get first buffer, set scrolling on
michael@0 256 this.selected = "";
michael@0 257 this._clearPrefsContainer();
michael@0 258 this._addMorePrefsToContainer();
michael@0 259 window.onscroll = this.onScroll.bind(this);
michael@0 260
michael@0 261 // Pause for screen to settle, then ensure at top
michael@0 262 setTimeout((function() {
michael@0 263 window.scrollTo(0, 0);
michael@0 264 }).bind(this), INITIAL_PAGE_DELAY);
michael@0 265 },
michael@0 266
michael@0 267 // Clear the displayed preferences list
michael@0 268 _clearPrefsContainer: function AC_clearPrefsContainer() {
michael@0 269 // Quick clear the prefsContainer list
michael@0 270 let empty = this._prefsContainer.cloneNode(false);
michael@0 271 this._prefsContainer.parentNode.replaceChild(empty, this._prefsContainer);
michael@0 272 this._prefsContainer = empty;
michael@0 273
michael@0 274 // Quick clear the prefs li.HTML list
michael@0 275 this._list.forEach(function(item) {
michael@0 276 delete item.li;
michael@0 277 });
michael@0 278 },
michael@0 279
michael@0 280 // Get a small manageable block of prefs items, and add them to the displayed list
michael@0 281 _addMorePrefsToContainer: function AC_addMorePrefsToContainer() {
michael@0 282 // Create filter regex
michael@0 283 let filterExp = this.filterInput.value ?
michael@0 284 new RegExp(this.filterInput.value, "i") : null;
michael@0 285
michael@0 286 // Get a new block for the display list
michael@0 287 let prefsBuffer = [];
michael@0 288 for (let i = 0; i < this._list.length && prefsBuffer.length < PREFS_BUFFER_MAX; i++) {
michael@0 289 if (!this._list[i].li && this._list[i].test(filterExp)) {
michael@0 290 prefsBuffer.push(this._list[i]);
michael@0 291 }
michael@0 292 }
michael@0 293
michael@0 294 // Add the new block to the displayed list
michael@0 295 for (let i = 0; i < prefsBuffer.length; i++) {
michael@0 296 this._prefsContainer.appendChild(prefsBuffer[i].getOrCreateNewLINode());
michael@0 297 }
michael@0 298
michael@0 299 // Determine if anything left to add later by scrolling
michael@0 300 let anotherPrefsBufferRemains = false;
michael@0 301 for (let i = 0; i < this._list.length; i++) {
michael@0 302 if (!this._list[i].li && this._list[i].test(filterExp)) {
michael@0 303 anotherPrefsBufferRemains = true;
michael@0 304 break;
michael@0 305 }
michael@0 306 }
michael@0 307
michael@0 308 if (anotherPrefsBufferRemains) {
michael@0 309 // If still more could be displayed, show the throbber
michael@0 310 this._loadingContainer.style.display = "block";
michael@0 311 } else {
michael@0 312 // If no more could be displayed, hide the throbber, and stop noticing scroll events
michael@0 313 this._loadingContainer.style.display = "none";
michael@0 314 window.onscroll = null;
michael@0 315 }
michael@0 316 },
michael@0 317
michael@0 318 // If scrolling at the bottom, maybe add some more entries
michael@0 319 onScroll: function AC_onScroll(aEvent) {
michael@0 320 if (this._prefsContainer.scrollHeight - (window.pageYOffset + window.innerHeight) < PAGE_SCROLL_TRIGGER) {
michael@0 321 if (!this._filterChangeTimer) {
michael@0 322 this._addMorePrefsToContainer();
michael@0 323 }
michael@0 324 }
michael@0 325 },
michael@0 326
michael@0 327
michael@0 328 // Return currently selected list item node
michael@0 329 get selected() {
michael@0 330 return document.querySelector(".pref-item.selected");
michael@0 331 },
michael@0 332
michael@0 333 // Set list item node as selected
michael@0 334 set selected(aSelection) {
michael@0 335 let currentSelection = this.selected;
michael@0 336 if (aSelection == currentSelection) {
michael@0 337 return;
michael@0 338 }
michael@0 339
michael@0 340 // Clear any previous selection
michael@0 341 if (currentSelection) {
michael@0 342 currentSelection.classList.remove("selected");
michael@0 343 currentSelection.removeEventListener("keypress", this.handleKeypress, false);
michael@0 344 }
michael@0 345
michael@0 346 // Set any current selection
michael@0 347 if (aSelection) {
michael@0 348 aSelection.classList.add("selected");
michael@0 349 aSelection.addEventListener("keypress", this.handleKeypress, false);
michael@0 350 }
michael@0 351 },
michael@0 352
michael@0 353 // Watch user key input so we can provide Enter key action, commit input values
michael@0 354 handleKeypress: function AC_handleKeypress(aEvent) {
michael@0 355 if (aEvent.keyCode == VKB_ENTER_KEY)
michael@0 356 aEvent.target.blur();
michael@0 357 },
michael@0 358
michael@0 359 // Return the target list item node of an action event
michael@0 360 getLINodeForEvent: function AC_getLINodeForEvent(aEvent) {
michael@0 361 let node = aEvent.target;
michael@0 362 while (node && node.nodeName != "li") {
michael@0 363 node = node.parentNode;
michael@0 364 }
michael@0 365
michael@0 366 return node;
michael@0 367 },
michael@0 368
michael@0 369 // Return a pref of a list item node
michael@0 370 _getPrefForNode: function AC_getPrefForNode(aNode) {
michael@0 371 let pref = aNode.getAttribute("name");
michael@0 372
michael@0 373 return new Pref(pref);
michael@0 374 },
michael@0 375
michael@0 376 // When list item name or value are tapped
michael@0 377 selectOrToggleBoolPref: function AC_selectOrToggleBoolPref(aEvent) {
michael@0 378 let node = this.getLINodeForEvent(aEvent);
michael@0 379
michael@0 380 // If not already selected, just do so
michael@0 381 if (this.selected != node) {
michael@0 382 this.selected = node;
michael@0 383 return;
michael@0 384 }
michael@0 385
michael@0 386 // If already selected, and value is boolean, toggle it
michael@0 387 let pref = this._getPrefForNode(node);
michael@0 388 if (pref.type != Services.prefs.PREF_BOOL) {
michael@0 389 return;
michael@0 390 }
michael@0 391
michael@0 392 this.toggleBoolPref(aEvent);
michael@0 393 },
michael@0 394
michael@0 395 // When finalizing list input values due to blur
michael@0 396 setIntOrStringPref: function AC_setIntOrStringPref(aEvent) {
michael@0 397 let node = this.getLINodeForEvent(aEvent);
michael@0 398
michael@0 399 // Skip if locked
michael@0 400 let pref = this._getPrefForNode(node);
michael@0 401 if (pref.locked) {
michael@0 402 return;
michael@0 403 }
michael@0 404
michael@0 405 // Boolean inputs blur to remove focus from "button"
michael@0 406 if (pref.type == Services.prefs.PREF_BOOL) {
michael@0 407 return;
michael@0 408 }
michael@0 409
michael@0 410 // String and Int inputs change / commit on blur
michael@0 411 pref.value = aEvent.target.value;
michael@0 412 },
michael@0 413
michael@0 414 // When we reset a pref to it's default value (note resetting a user created pref will delete it)
michael@0 415 resetDefaultPref: function AC_resetDefaultPref(aEvent) {
michael@0 416 let node = this.getLINodeForEvent(aEvent);
michael@0 417
michael@0 418 // If not already selected, do so
michael@0 419 if (this.selected != node) {
michael@0 420 this.selected = node;
michael@0 421 }
michael@0 422
michael@0 423 // Reset will handle any locked condition
michael@0 424 let pref = this._getPrefForNode(node);
michael@0 425 pref.reset();
michael@0 426 },
michael@0 427
michael@0 428 // When we want to toggle a bool pref
michael@0 429 toggleBoolPref: function AC_toggleBoolPref(aEvent) {
michael@0 430 let node = this.getLINodeForEvent(aEvent);
michael@0 431
michael@0 432 // Skip if locked, or not boolean
michael@0 433 let pref = this._getPrefForNode(node);
michael@0 434 if (pref.locked) {
michael@0 435 return;
michael@0 436 }
michael@0 437
michael@0 438 // Toggle, and blur to remove field focus
michael@0 439 pref.value = !pref.value;
michael@0 440 aEvent.target.blur();
michael@0 441 },
michael@0 442
michael@0 443 // When Int inputs have their Up or Down arrows toggled
michael@0 444 incrOrDecrIntPref: function AC_incrOrDecrIntPref(aEvent, aInt) {
michael@0 445 let node = this.getLINodeForEvent(aEvent);
michael@0 446
michael@0 447 // Skip if locked
michael@0 448 let pref = this._getPrefForNode(node);
michael@0 449 if (pref.locked) {
michael@0 450 return;
michael@0 451 }
michael@0 452
michael@0 453 pref.value += aInt;
michael@0 454 },
michael@0 455
michael@0 456 // Observe preference changes
michael@0 457 observe: function AC_observe(aSubject, aTopic, aPrefName) {
michael@0 458 let pref = new Pref(aPrefName);
michael@0 459
michael@0 460 // Ignore uninteresting changes, and avoid "private" preferences
michael@0 461 if (aTopic != "nsPref:changed") {
michael@0 462 return;
michael@0 463 }
michael@0 464
michael@0 465 // If pref type invalid, refresh display as user reset/removed an item from the list
michael@0 466 if (pref.type == Services.prefs.PREF_INVALID) {
michael@0 467 document.location.reload();
michael@0 468 return;
michael@0 469 }
michael@0 470
michael@0 471 // If pref not already in list, refresh display as it's being added
michael@0 472 let item = document.querySelector(".pref-item[name=" + pref.name.quote() + "]");
michael@0 473 if (!item) {
michael@0 474 document.location.reload();
michael@0 475 return;
michael@0 476 }
michael@0 477
michael@0 478 // Else we're modifying a pref
michael@0 479 item.setAttribute("value", pref.value);
michael@0 480 let input = item.querySelector("input");
michael@0 481 input.setAttribute("value", pref.value);
michael@0 482 input.value = pref.value;
michael@0 483
michael@0 484 pref.default ?
michael@0 485 item.querySelector(".reset").setAttribute("disabled", "true") :
michael@0 486 item.querySelector(".reset").removeAttribute("disabled");
michael@0 487 },
michael@0 488
michael@0 489 // Quick context menu helpers for about:config
michael@0 490 clipboardCopy: function AC_clipboardCopy(aField) {
michael@0 491 let pref = this._getPrefForNode(this.contextMenuLINode);
michael@0 492 if (aField == 'name') {
michael@0 493 gClipboardHelper.copyString(pref.name);
michael@0 494 } else {
michael@0 495 gClipboardHelper.copyString(pref.value);
michael@0 496 }
michael@0 497 }
michael@0 498 }
michael@0 499
michael@0 500
michael@0 501 /* ============================== Pref ==============================
michael@0 502 *
michael@0 503 * Individual Preference object / methods
michael@0 504 *
michael@0 505 * Defines a Pref object, a document list item tied to Preferences Services
michael@0 506 * And the methods by which they interact.
michael@0 507 *
michael@0 508 */
michael@0 509 function Pref(aName) {
michael@0 510 this.name = aName;
michael@0 511 }
michael@0 512
michael@0 513 Pref.prototype = {
michael@0 514 get type() {
michael@0 515 return Services.prefs.getPrefType(this.name);
michael@0 516 },
michael@0 517
michael@0 518 get value() {
michael@0 519 switch (this.type) {
michael@0 520 case Services.prefs.PREF_BOOL:
michael@0 521 return Services.prefs.getBoolPref(this.name);
michael@0 522 case Services.prefs.PREF_INT:
michael@0 523 return Services.prefs.getIntPref(this.name);
michael@0 524 case Services.prefs.PREF_STRING:
michael@0 525 default:
michael@0 526 return Services.prefs.getCharPref(this.name);
michael@0 527 }
michael@0 528
michael@0 529 },
michael@0 530 set value(aPrefValue) {
michael@0 531 switch (this.type) {
michael@0 532 case Services.prefs.PREF_BOOL:
michael@0 533 Services.prefs.setBoolPref(this.name, aPrefValue);
michael@0 534 break;
michael@0 535 case Services.prefs.PREF_INT:
michael@0 536 Services.prefs.setIntPref(this.name, aPrefValue);
michael@0 537 break;
michael@0 538 case Services.prefs.PREF_STRING:
michael@0 539 default:
michael@0 540 Services.prefs.setCharPref(this.name, aPrefValue);
michael@0 541 }
michael@0 542 },
michael@0 543
michael@0 544 get default() {
michael@0 545 return !Services.prefs.prefHasUserValue(this.name);
michael@0 546 },
michael@0 547
michael@0 548 get locked() {
michael@0 549 return Services.prefs.prefIsLocked(this.name);
michael@0 550 },
michael@0 551
michael@0 552 reset: function AC_reset() {
michael@0 553 Services.prefs.clearUserPref(this.name);
michael@0 554 },
michael@0 555
michael@0 556 test: function AC_test(aValue) {
michael@0 557 return aValue ? aValue.test(this.name) : true;
michael@0 558 },
michael@0 559
michael@0 560 // Get existing or create new LI node for the pref
michael@0 561 getOrCreateNewLINode: function AC_getOrCreateNewLINode() {
michael@0 562 if (!this.li) {
michael@0 563 this.li = document.createElement("li");
michael@0 564
michael@0 565 this.li.className = "pref-item";
michael@0 566 this.li.setAttribute("name", this.name);
michael@0 567
michael@0 568 // Click callback to ensure list item selected even on no-action tap events
michael@0 569 this.li.addEventListener("click",
michael@0 570 function(aEvent) {
michael@0 571 AboutConfig.selected = AboutConfig.getLINodeForEvent(aEvent);
michael@0 572 },
michael@0 573 false
michael@0 574 );
michael@0 575
michael@0 576 // Contextmenu callback to identify selected list item
michael@0 577 this.li.addEventListener("contextmenu",
michael@0 578 function(aEvent) {
michael@0 579 AboutConfig.contextMenuLINode = AboutConfig.getLINodeForEvent(aEvent);
michael@0 580 },
michael@0 581 false
michael@0 582 );
michael@0 583
michael@0 584 this.li.setAttribute("contextmenu", "prefs-context-menu");
michael@0 585
michael@0 586 // Create list item outline, bind to object actions
michael@0 587 this.li.innerHTML =
michael@0 588 "<div class='pref-name' " +
michael@0 589 "onclick='AboutConfig.selectOrToggleBoolPref(event);'>" +
michael@0 590 this.name +
michael@0 591 "</div>" +
michael@0 592 "<div class='pref-item-line'>" +
michael@0 593 "<input class='pref-value' value='' " +
michael@0 594 "onblur='AboutConfig.setIntOrStringPref(event);' " +
michael@0 595 "onclick='AboutConfig.selectOrToggleBoolPref(event);'>" +
michael@0 596 "</input>" +
michael@0 597 "<div class='pref-button reset' " +
michael@0 598 "onclick='AboutConfig.resetDefaultPref(event);'>" +
michael@0 599 gStringBundle.GetStringFromName("pref.resetButton") +
michael@0 600 "</div>" +
michael@0 601 "<div class='pref-button toggle' " +
michael@0 602 "onclick='AboutConfig.toggleBoolPref(event);'>" +
michael@0 603 gStringBundle.GetStringFromName("pref.toggleButton") +
michael@0 604 "</div>" +
michael@0 605 "<div class='pref-button up' " +
michael@0 606 "onclick='AboutConfig.incrOrDecrIntPref(event, 1);'>" +
michael@0 607 "</div>" +
michael@0 608 "<div class='pref-button down' " +
michael@0 609 "onclick='AboutConfig.incrOrDecrIntPref(event, -1);'>" +
michael@0 610 "</div>" +
michael@0 611 "</div>";
michael@0 612
michael@0 613 // Delay providing the list item values, until the LI is returned and added to the document
michael@0 614 setTimeout(this._valueSetup.bind(this), INNERHTML_VALUE_DELAY);
michael@0 615 }
michael@0 616
michael@0 617 return this.li;
michael@0 618 },
michael@0 619
michael@0 620 // Initialize list item object values
michael@0 621 _valueSetup: function AC_valueSetup() {
michael@0 622
michael@0 623 this.li.setAttribute("type", this.type);
michael@0 624 this.li.setAttribute("value", this.value);
michael@0 625
michael@0 626 let valDiv = this.li.querySelector(".pref-value");
michael@0 627 valDiv.value = this.value;
michael@0 628
michael@0 629 switch(this.type) {
michael@0 630 case Services.prefs.PREF_BOOL:
michael@0 631 valDiv.setAttribute("type", "button");
michael@0 632 this.li.querySelector(".up").setAttribute("disabled", true);
michael@0 633 this.li.querySelector(".down").setAttribute("disabled", true);
michael@0 634 break;
michael@0 635 case Services.prefs.PREF_STRING:
michael@0 636 valDiv.setAttribute("type", "text");
michael@0 637 this.li.querySelector(".up").setAttribute("disabled", true);
michael@0 638 this.li.querySelector(".down").setAttribute("disabled", true);
michael@0 639 this.li.querySelector(".toggle").setAttribute("disabled", true);
michael@0 640 break;
michael@0 641 case Services.prefs.PREF_INT:
michael@0 642 valDiv.setAttribute("type", "number");
michael@0 643 this.li.querySelector(".toggle").setAttribute("disabled", true);
michael@0 644 break;
michael@0 645 }
michael@0 646
michael@0 647 this.li.setAttribute("default", this.default);
michael@0 648 if (this.default) {
michael@0 649 this.li.querySelector(".reset").setAttribute("disabled", true);
michael@0 650 }
michael@0 651
michael@0 652 if (this.locked) {
michael@0 653 valDiv.setAttribute("disabled", this.locked);
michael@0 654 this.li.querySelector(".pref-name").setAttribute("locked", true);
michael@0 655 }
michael@0 656 }
michael@0 657 }
michael@0 658

mercurial