Dodawanie preferencji do rozszerzenia

UWAGA: Tłumaczenie tej strony nie zostało zakończone.
Może być ona niekompletna lub wymagać korekty.
Chcesz pomóc? | Dokończ tłumaczenie | Sprawdź ortografię | Więcej takich stron+.
Poniższy artykuł rozszerza Tworzenie rozszerzenia dynamicznego paska stanu poprzez dodanie wyskakującego menu that lets you quickly switch between multiple stocks to watch. It also adds a preference dialog that lets you switch to a stock other than one of the ones included in the popup menu.

As before, concepts covered in the previous articles in this series won't be rehashed here, so if you haven't already seen them:

Also, for reference, you may want to take a look at System preferencji.

Pobieranie przykładu

Możesz pobrać przykład, aby użyć go do stworzenia własnego rozszerzenia.

Pobierz przykład

Aktualizacja manifestu

Musi zostać zaktualizowany manifest instalacyjny oraz Chrome. Zmiany dotyczą przede wszystkim zmiany ID rozszerzenia. Jednakże musimy dodać dodatkową linię do pliku install.rdf:

 <em:optionsURL>chrome://stockwatcher2/content/options.xul</em:optionsURL>

Powyższa linia określa adres URL pliku XUL, który opisuje opcje dialogu.

Określanie wartości domyślnych

W celu ustawienia domyślnych preferencji należy dodać nowy katalog do paczki rozszerzenia nazwanej "defaults", która będzie zawierał katalog "preferences". Wewnątrz niego tworzymy plik defaults.js opisujący wartości domyślne preferencji:

 pref("stockwatcher2.symbol", "GOOG");

By dowiedzieć się więcej o systemie preferencji przeczytaj API Preferencji.

Kod JavaScript

In order to monitor changes to our preferences, we need to install an observer using the nsIPrefBranch2 interface. To do that, we need to reimplement our code into an object.

That involves turning each function into a member of the StockWatcher class. Let's take a look at each function in the class.

startup()

The StockWatcher.startup() function is called when our extension is first loaded. Its job is to start up the observer to watch for changes to our preferences, instantiate an object to use to manage our preferences, and install an interval routine to update the stock information periodically.

 var StockWatcher = {
   prefs: null,
   tickerSymbol: "",
   
   // Initialize the extension
   
   startup: function()
   {
     // Register to receive notifications of preference changes
     
     this.prefs = Components.classes["@mozilla.org/preferences-service;1"]
         .getService(Components.interfaces.nsIPrefService)
         .getBranch("stockwatcher2.");
     this.prefs.QueryInterface(Components.interfaces.nsIPrefBranch2);
     this.prefs.addObserver("", this, false);
     
     this.tickerSymbol = this.prefs.getCharPref("symbol").toUpperCase();
 
     this.refreshInformation();    
     window.setInterval(this.refreshInformation, 10*60*1000);
   },

Our object has two member variables. prefs is configured by startup() to reference our extension's preferences, while tickerSymbol indicates the stock symbol to monitor.

The first thing the startup() function does is to get a reference to the preferences for our extension. This is done in two steps:

  • First, we get the Preferences service. This component handles preference management for Firefox and any extensions.
  • Second, we call nsIPrefService.getBranch(). This lets us specify a specific branch of the preference tree to access. By default, we would have access to all preferences, but we only want access to those belonging to our own extension, so we specify that we want to access the "stockwatcher2" branch.

After getting the preference branch for our extension, we call the QueryInterface() method on it to be able to use the methods of the nsIPrefBranch2 interface.

The next step is to register a preference observer by calling the addObserver() method to establish that whenever any events occur on the preferences, our object (this) receives notification. When events occur, such as a preference being altered, our observe() method will be called automatically.

Now that we're monitoring the preferences, we can set up to watch the stock information and display it in the status bar panel.

The first thing we need to do is get the currently configured stock symbol to watch from the preferences. To do so, we call the nsIPrefBranch.getCharPref() method, specifying that we want the preference named "symbol", which is where we store the user's selection for the stock to watch. We forcibly convert the symbol to upper-case since that's the way stock symbols are normally displayed.

Next, we call our own refreshInformation() method to immediately fetch and display the current information about the stock the extension is configured to monitor. We'll look at the details of how this method works later.

The last thing the startup() method does is to call the window.setInterval() DOM method to set up a callback that will automatically run our refreshInformation() method every 10 minutes. The interval time is specified in milliseconds.

shutdown()

The StockWatcher.shutdown() method deactivates the observer on the preferences. This is also where we would add any other shutdown tasks we need to perform.

  shutdown: function()
  {
    this.prefs.removeObserver("", this);
  },

observe()

The StockWatcher.observe() function is called whenever an event occurs on the preference branch we're watching. For details on how observers work, read up on the nsIObserver interface.

   observe: function(subject, topic, data)
   {
     if (topic != "nsPref:changed")
     {
       return;
     }
 
     switch(data)
     {
       case "symbol":
         this.tickerSymbol = this.prefs.getCharPref("symbol").toUpperCase();
         this.refreshInformation();
         break;
     }
   },

The topic parameter indicates what type of event occurred. If it's not nsPref:changed, we simply ignore the event, since all we're interested in is changes to the values of our preferences.

Once we've established that the event is in fact a preference change, we look at the data parameter, which contains the name of the preference that changed. In our example, we only have one preference, but you can monitor as many preferences as you wish here.

If the changed preference is "symbol", we grab the updated value of the preference by calling the nsIPrefBranch.getCharPref() method, and stash it in our tickerSymbol variable.

Once we've gotten the updated preference, we call refreshInformation() to immediately update the display with the new stock's information.

watchStock()

While we're at it, let's add a method that sets which stock we want to be watching, changing the preference and immediately requesting a refresh of the display. This method will be used when the user uses the popup menu we'll be adding to change what stock they're watching.

   watchStock: function(newSymbol)
   {
     this.prefs.setCharPref("symbol", newSymbol);
   },

The only new information for us here is the call to the preference object's setCharPref() function, which sets the value of the "symbol" preference.

Note that this call results in our StockWatcher.observe() method being invoked and displayed stock information being updated.

refreshInformation()

This method is slightly revised from previous versions, in that it needs to fetch the preference for the stock to watch and use that to construct the URL to monitor, as well as to construct the string to be displayed in the status bar panel.

   refreshInformation: function()
   {
     // Because we may be called as a callback, we can't rely on
     // "this" referring to the right object, so we need to reference 
     // it by its full name
     
     var symbol = StockWatcher.tickerSymbol;
     
     var fullUrl = "http://quote.yahoo.com/d/quotes.csv?f=sl1d1t1c1ohgv&e=.csv&s="
         + symbol;
     
     function infoReceived()
     {
       var samplePanel = document.getElementById('stockwatcher2');
       var output = httpRequest.responseText;
         
       if (output.length)
       {
         // Remove any whitespace from the end of the string
         output = output.replace(/\W*$/, "");
       
         // Build the tooltip string
         var fieldArray = output.split(",");
         samplePanel.label = symbol + ": " + fieldArray[1];
         samplePanel.tooltipText = "Chg: " + fieldArray[4] + " | " +
             "Open: " + fieldArray[5] + " | " +
             "Low: " + fieldArray[6] + " | " +
             "High: " + fieldArray[7] + " | " +
             "Vol: " + fieldArray[8];
       }
     }
     
     var httpRequest = new XMLHttpRequest();
     
     httpRequest.open("GET", fullUrl, true);
     httpRequest.onload = infoReceived;
     httpRequest.send(null);
   }
 }

Note that we use StockWatcher.tickerSymbol here instead of this.tickerSymbol to get the stock symbol to watch. We do this because since refreshInformation() is usually called as a callback from setInterval. In such cases this doesn't refer to the right object. See Wiązanie metod for detailed explanation.

Once we have the symbol in the local variable symbol, we use that to construct the URL and the string to display in the status bar panel.

Instalowanie nasłuchu zdarzeń

The only thing left to do is to install the event listeners needed to run the startup() and shutdown() routines automatically when the browser window is loaded and unloaded.

window.addEventListener("load", function(e) { StockWatcher.startup(); }, false);
window.addEventListener("unload", function(e) { StockWatcher.shutdown(); }, false);

Design the preference dialog

Now that we've written all the code, we need to build the XUL file for the options dialog.

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
 
<prefwindow id="stockwatcher2-prefs"
     title="StockWatcher 2 Options"
     xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
<prefpane id="sw2-stock-pane" label="Stock Settings">
  <preferences>
    <preference id="pref_symbol" name="stockwatcher2.symbol" type="string"/>
  </preferences>
 
  <hbox align="center">
    <label control="symbol" value="Stock to watch: "/>
    <textbox preference="pref_symbol" id="symbol" maxlength="4"/>
  </hbox>
</prefpane>
 
</prefwindow>

The <preferences> block establishes all the settings we implement as well as their types. In our case, we have a single preference, the stock symbol to monitor. Preferences are identified by name; in this case, the name is "stockwatcher2.symbol".

The actual user interface is described in the <prefpane> block. The <hbox> element is used to lay out the user interface by indicating that the widgets inside it should be positioned horizontally, next to each other in the window.

Our dialog has two widgets in it. The first is a label describing the textbox. The second is the textbox itself, in which the user enters the symbol. The preference property ties the textbox to the "pref_symbol" <preference> element and to the "stockwatcher2.symbol" preference. This lets the preference value automatically be updated to reflect the content of the textbox.

Dodanie kontekstowego menu

Adding the contextual menu is easy; all the work that needs doing is done in the <tt>stockwatcher2.xul</tt> file. The first step is to add the context attribute to the status bar panel:

 <statusbar id="status-bar">
   <statusbarpanel id="stockwatcher2"
     label="Loading..."
     context="stockmenu"
     onclick="StockWatcher.refreshInformation()"
   />
 </statusbar>

Now when the user clicks on the status bar panel, the stock information refreshes, but when they right-click on it, a context menu pops up.

Defining the menu is also easy. All we need to do is add a popupset describing the menu to the statusbar, as follows:

 <popupset>
   <menupopup id="stockmenu">
     <menuitem label="Refresh Now" default="true"
               oncommand="StockWatcher.refreshInformation()"/>
     <menuseparator/>
     <menuitem label="Apple (AAPL)" oncommand="StockWatcher.watchStock('AAPL')"/>
     <menuitem label="Google (GOOG)" oncommand="StockWatcher.watchStock('GOOG')"/>
     <menuitem label="Microsoft (MSFT)" oncommand="StockWatcher.watchStock('MSFT')"/>
     <menuitem label="Yahoo! (YHOO)" oncommand="StockWatcher.watchStock('YHOO')"/>
   </menupopup>
 </popupset>

Each item in the menu has a label property, which specifies the text displayed in the menu, as well as an oncommand property, which indicates the JavaScript code to execute when the user selects that item.

The Refresh Now option calls the StockWatcher.refreshInformation() function, to refresh the display. The rest of the options call the StockWatcher.watchStock() function to start watching a different stock.

For a more detailed tutorial on creating popup menus, zobacz Kurs XUL:Wyskakujące menu.

Autorzy i etykiety dokumentu

Autorzy tej strony: Ptak82, Bedi, splewako, Mgjbot
Ostatnia aktualizacja: splewako,