MozillaZine


Userchrome.js function to store and use a global variable

User Help for Mozilla Thunderbird
user2018
 
Posts: 87
Joined: September 23rd, 2018, 11:07 am

Post Posted January 5th, 2021, 2:10 pm

I have several buttons in Thunderbird whose functionality is supported through functions defined in the Userchrome.js file. Most of the functions perform a first common task and then a specific task. In some cases I do not want to perform the common task, so I was thinking about duplicating each function, so that one version performs the common task as well as the specific function task and the other version only performs the specific function task; in this way, I would duplicate the number of buttons.

I know how to implement that solution, but I think that it would be better to consider an alternative:

1) Have a function implementing some kind of "toggle" such that if the button is pressed a global variable performCommonAction is toggled (change from true to false or vice versa).
2) Show in the Thunderbird's toolbar show always the value of the global variable performCommonAction (so that you know the current status and the effect of clicking the toggle button).
3) Now in each function I can check if the global variable performCommonAction is true or not and, depending on its value, perform the common action or omit it.

Is it possible to do this easily? Does it make sense? I'm not sure 1) if global variables can be used (and how) and 2) how to add a string to the Thunderbird's status bar so that I can always know the value of the global variable.

Any advice is welcome.

morat
 
Posts: 4194
Joined: February 3rd, 2009, 6:29 pm

Post Posted January 5th, 2021, 5:10 pm

Here is a preference tracker toggle button example for Thunderbird 78.

The button uses the |window.__unique_identifier_preference_observer| global variable.

Code: Select all
(function () {
  if (location == "chrome://messenger/content/messenger.xul" ||
      location == "chrome://messenger/content/messenger.xhtml") {
    try {
      var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
      var toolbarbutton = document.createElementNS(XUL_NS, "toolbarbutton");
      toolbarbutton.addEventListener("command", function (aEvent) {
        var win = aEvent.target.ownerDocument.defaultView;
        var uid = "__unique_identifier_preference_observer";
        if (typeof win[uid] == "undefined") {
          win[uid] = {};
          win[uid].prefObserver = function (subject, topic, data) {
            // do not track these preferences
            if (data != "example.alpha" &&
                data != "example.beta" &&
                data != "example.gamma" &&
                data != "example.delta" &&
                data != "example.epsilon") {
              win[uid].prefObserver.prefArray.push(data);
            }
          };
          aEvent.target.checked = true;
          win[uid].prefObserver.prefArray = [];
          Services.prefs.addObserver("", win[uid].prefObserver, false);
        } else {
          var dialogTitle = "Preference Tracker";
          if (win[uid].prefObserver.prefArray.length > 0) {
            var dialogText = "Do you want to copy a preference to the clipboard?";
            var selectedIndex = {value: null};
            var ok = Services.prompt.select(win, dialogTitle, dialogText,
         //   win[uid].prefObserver.prefArray.length, win[uid].prefObserver.prefArray, // Thunderbird 68
                                                      win[uid].prefObserver.prefArray, // Thunderbird 78
                selectedIndex);
            if (ok) {
              var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"].
                getService(Components.interfaces.nsIClipboardHelper);
              clipboard.copyString(win[uid].prefObserver.prefArray[selectedIndex.value]);
            } else {
              var data = [];
              var out = win[uid].prefObserver.prefArray.join("\n");
              data.push('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">', "<html>", "<head>");
              data.push('<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">');
              data.push("<title>" + "Preference Tracker" + "</title>", "</head>", "<body>");
              data.push("<pre>", out, "</pre>", "</body>", "</html>");
              win.document.getElementById("tabmail").openTab("contentTab", {
                contentPage: "data:text/html;charset=utf-8;base64," + btoa(data.join("\n")),
                background: true});
              win.document.getElementById("tabmail").openTab("contentTab", {
                contentPage: "about:config?filter=" + "/" + out.replace(/\n/g, "|") + "/",
                background: true});
            }
          } else {
            var dialogText = "No preference changes were found.";
            Services.prompt.alert(win, dialogTitle, dialogText);
          }
          aEvent.target.checked = false;
          Services.prefs.removeObserver("", win[uid].prefObserver);
          delete win[uid];
        }
      }, false);
      var dataUrl = "data:image/png;base64," +
        "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACGElEQVQ4y5WSzUtUURiHn3" +
        "PObSaZGW9U6jRiWlqNEEGEtHE1tQlqY2mbFlFZRLUPIqyFf0BCRB8WDQZFMqQRBMkgWLSY" +
        "IdLQGQYs/Lhl4zTjV/l1r9PiLrLhVvbbvJvzPOe873kFf8mp87frgQYgBNQCCSAKRO7fOv" +
        "caQPwJPn3hzgngSkWoLqhvL6eodAPz6SmmPxqMRWNJoLX95tkOR8GZS/fqgbsnLzcF95T5" +
        "GJzN0zcMLNvH59MTjPW8SALN0kkgpGyoOFAXdBd7mVqAvqRAWxEUFYHXCxsr/ZTt2x8UUj" +
        "ZoTgKpZEivCmCa8DgJbjf4isHjAU0D0wR2BcgMyJCjQChVu75Ep28YNGXDmzaD7gWXgiUL" +
        "XG6dQaVqHVuQUiQWMtOwLFjnsm/WveBXUIldmZtBSpFwnoGS0bnxNABK2c92KfABW7Drt0" +
        "9fEUpGHQWxRLz0ZfgBi7kMlmX3vGTBLPAFSI1k6O8ZSEqlIr99Y/5d2xGgu7n1DdnAXgzD" +
        "4FDjRUqqSymv8cH3WbIjad6/GkgCrW3XGzu0Qpj4Q456TDoNGFvxt+dSH2ZyKUKpVZsopI" +
        "jcaDn2axNXw0P9MzyaqGbc0q3wsyca/4gshN9OlDBo+vNhY/dB1hBZCPdaW/Ndn6saiV3t" +
        "XYtADU0GWn5ks2I04+G5uTP/1Kg5TvxaJ2uMFpnccdjHYnfO0ugytjURb4nwH/kJY5fLVw" +
        "3nkJIAAAAASUVORK5CYII=";
      var props = {
        id: "__unique_identifier_preference_tracker_button",
        class: "toolbarbutton-1 chromeclass-toolbar-additional",
        label: "Preference Tracker",
        tooltiptext: "Preference Tracker" + "\n" + "\n" +
          "L: enable or disable preference tracker" + "\n" +
          "R: open button context popup",
        style: 'list-style-image: url("' + dataUrl + '"); -moz-image-region: auto;',
      };
      for (var p in props) toolbarbutton.setAttribute(p, props[p]);
      var toolbar = document.getElementById("mail-toolbar-menubar2");
      var toolbaritem = document.getElementById("menubar-items");
      toolbar.insertBefore(toolbarbutton, toolbaritem.nextSibling);
    } catch (e) {
      Components.utils.reportError(e); // [check] Show Content Messages
    }
  }
})();

The developers removed the array length param in the Services.prompt.select method in Firefox 69.

nsIPromptService
http://searchfox.org/mozilla-release/so ... ervice.idl
http://searchfox.org/mozilla-esr68/sour ... ervice.idl

user2018 wrote:how to add a string to the Thunderbird's status bar

Create your own label element like...

Reference
http://searchfox.org/comm-esr78/search? ... rect=false
http://searchfox.org/comm-esr78/search? ... andglue.js

user2018
 
Posts: 87
Joined: September 23rd, 2018, 11:07 am

Post Posted January 6th, 2021, 10:04 am

Thank you very much for the suggestion! I was trying the example, but I am not completely clear about its purpose and how it works. If I click on the button it remains pressed/selected, if I click again then I get the message "No preference changes were found." and then the button stops being pressed/selected. Is this code designed to store a set of boolean variables? In my case I just need to keep track of a single boolean variable (true/false, depending on the click of the button), maybe this is what is confusing me. In that case, how can I define the global variable __unique_identifier_preference_observer so that I can query its value in the other functions that I have in my userChrome.js file?

Concerning the second part, in order to define a label like "<label id="unreadMessageCount" class="statusbarpanel"/>", do I need to modify the messenger.xhtml file? Or I can do it all just using userChrome.js and userChrome.css? If I define something like "<label id="idMyPreferenceValue" class="statusbarpanel"/>", how can I assign the location of the label to be the status bar?

Any hint would be great.

morat
 
Posts: 4194
Joined: February 3rd, 2009, 6:29 pm

Post Posted January 6th, 2021, 11:27 am

Preference Tracker usage:

* click Preference Tracker button to enable
* Tools > Options > General > Scrolling
* toggle "Use autoscrolling"
* toggle "Use smooth scrolling"
* click Preference Tracker button again to disable
* select a preference
* click "OK" to copy selected preference to clipboard
* or click "Cancel" to open filtered about:config tab

How to create a label element on the status bar:

Code: Select all
(function () {
  // create global variable
  var win = window;
  var uid = "__unique_identifier_example_boolean";
  win[uid] = true;

  // create label element on status bar
  var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  var label = document.createElementNS(XUL_NS, "label");
  label.setAttribute("id", "__unique_identifier_example_label");
  label.setAttribute("class", "statusbarpanel");
  label.setAttribute("value", "Cowabunga: " + win[uid]);
  var statusbar = document.getElementById("status-bar");
  var unreadElement = document.getElementById("unreadMessageCount");
  statusbar.insertBefore(label, unreadElement.nextSibling);
})();

XUL label
http://developer.mozilla.org/docs/Archive/Mozilla/XUL/label

user2018
 
Posts: 87
Joined: September 23rd, 2018, 11:07 am

Post Posted January 6th, 2021, 12:17 pm

Thanks a lot!! I managed to get my use case working in a good enough way. There is only a minor nuisance: as I update the status bar each time prefixing the current value of the variable to the previous value (i.e., I execute "statusbar.insertBefore(label, unreadElement.nextSibling);" every time the variable changes its value), the length of the string in the status bar continuously grow: is there any way to reset the status bar to just the original (unmodified) value?

morat
 
Posts: 4194
Joined: February 3rd, 2009, 6:29 pm

Post Posted January 6th, 2021, 12:53 pm

How to update the global variable:

Code: Select all
(function () {
  var win = window;
  var uid = "__unique_identifier_example_boolean";
  win[uid] = false;
})();

How to update the label element on the status bar:

Code: Select all
(function () {
  var win = window;
  var uid = "__unique_identifier_example_boolean";
  if (typeof win[uid] == "undefined") {
    // global variable is not defined
  } else {
    var label = document.getElementById("__unique_identifier_example_label");
    if (label) {
      label.setAttribute("value", "Cowabunga: " + win[uid]);
    }
  }
})();

user2018
 
Posts: 87
Joined: September 23rd, 2018, 11:07 am

Post Posted January 7th, 2021, 2:47 am

Thanks a lot!! I was missing the last part ("label.setAttribute...").

Return to Thunderbird Support


Who is online

Users browsing this forum: Bing [Bot] and 4 guests