Concepts covered in the previous sample won't be reiterated here; instead, refer to the downloadable sample code or to the previous sample for further details.
Download the sample
You can download a copy of this sample to look over, or to use as the basis for your own extension. Or, if you've already got the code from the Creating a status bar extension sample, you can follow this tutorial to update that existing code with new features.
Update the install manifest
Replace all occurrences of the first sample's ID, "status-bar-sample-1", with the new sample's ID, "stockwatcher", and update the front end metadata to describe our new extension.
See Install Manifests for details.
Update the chrome manifest
The chrome manifest needs only a minor update from the previous sample; simply replace the ID of the first sample, "status-bar-sample-1", with the name of the new sample, "stockwatcher".
If you need to brush up, visit the Chrome Manifest section.
Write the XUL file
We need a slightly more complicated XUL file this time, in order to add a reference to the JavaScript code that will do the real work:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE overlay> <overlay id="stockwatcher-overlay" xmlns="https://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <script type="application/javascript" src="chrome://stockwatcher/content/stockwatcher.js"/> <!-- Firefox --> <statusbar id="status-bar"> <statusbarpanel id="stockwatcher" label="Loading..." tooltiptext="Current value" onclick="StockWatcher.refreshInformation()" /> </statusbar> </overlay>
Also, notice that the definition of the status bar panel now includes a new property, onclick
, which references the JavaScript function that will be executed whenever the user clicks on the status bar panel. Our extension will refresh the stock information display when the user clicks the panel.
Write the JavaScript code
The work of fetching the stock quote and updating the status bar panel's display is handled by the JavaScript code in the file stockwatcher.js
.
Unlike our previous sample, this one is implemented as an object. We do this because in future samples in this series, we're going to be doing things that are easier to do if our extension is implemented that way.
We use the window.addEventListener()
DOM function to tell Firefox to call the StockWatcher.startup()
function when a new browser window is opened:
window.addEventListener("load", function(e) { StockWatcher.startup(); }, false);
Our new extension has two primary functions: startup()
and refreshInformation()
. The refreshInformation()
function contains another function, called infoReceived()
. The following sections will examine these one by one.
startup()
The startup()
function is called when a new browser window is opened. We end up reloading data from each of the windows once in 10 minutes - fixing this by creating a JS component responsible for communication with the server is a good idea for one of the future articles
startup: function() { this.refreshInformation(); window.setInterval(this.refreshInformation, 10*60*1000); },
This starts by calling our refreshInformation()
function, which is responsible for fetching and displaying stock ticker information in the status bar panel. We do this so that upon loading, the stock information is displayed as soon as possible.
After doing that, we install an interval routine on the browser window by calling window.setInterval()
. This configures our refreshInformation()
routine to be called every 10 minutes (the time interval is specified in milliseconds).
refreshInformation()
The refreshInformation()
function is called whenever we want to update the stock information. It's called whenever the user clicks on the status bar panel, when our extension is first added to a browser window, and by the interval handler to periodically update the display.
refreshInformation: function() { var httpRequest = null; var fullUrl = 'https://quote.yahoo.com/d/quotes.csv?f=sl1d1t1c1ohgv&e=.csv&s=GOOG'; // ... httpRequest = new XMLHttpRequest(); httpRequest.open('GET', fullUrl, true); httpRequest.onload = infoReceived; httpRequest.send(null); }
The httpRequest
variable will contain an XMLHttpRequest
object. This object is used to configure and run an HTTP request on a web server, which we'll use to fetch the stock quote data.
The fullUrl
variable is the complete URL to use when requesting a stock quote. In this case, we're using Yahoo's comma-separated values return to fetch easily-parsed stock quote data for Google (ticker symbol GOOG).
refreshInformation()
embeds another function, infoReceived()
, which we'll look at separately shortly.
The first thing we do is create a new XMLHttpRequest
object to use for processing our request. We open the request, specifying that we wish to perform an HTTP "GET" command with the URL fullUrl
. The true
Boolean value in the third parameter indicates that we want to process the request asynchronously.
Setting the httpRequest.onload
property to our infoReceived()
function configures the request to call infoReceived()
when the response is received from the server. Finally, we send the request to the server and return.
infoReceived()
When the server responds to our request, our the infoReceived()
function, which is embedded inside refreshInformation()
, gets called automatically.
We embed this function inside refreshInformation()
so that its variable scope includes the variables used by that function. Due to the way JavaScript works, if infoReceived()
were outside refreshInformation()
, it would not have access to the same variable scope. In fact, even the this
value would not match, so we couldn't get at the same variables and functions that way.
function infoReceived() { var samplePanel = document.getElementById('stockwatcher'); var output = httpRequest.responseText; if (output.length) { // Remove whitespace from the end of the string; // this gets rid of the end-of-line characters output = output.replace(/\W*$/, ''); // Build the tooltip string var fieldArray = output.split(','); // Assert that fieldArray[0] == 'GOOG' samplePanel.label = 'GOOG: ' + fieldArray[1]; samplePanel.tooltipText = 'Chg: ' + fieldArray[4] + ' | ' + 'Open: ' + fieldArray[5] + ' | ' + 'Low: ' + fieldArray[6] + ' | ' + 'High: ' + fieldArray[7] + ' | ' + 'Vol: ' + fieldArray[8]; } }
The first thing we do here is get the status bar panel into the variable samplePanel
by calling the document.getElementById()
DOM function. We need this so that we can make changes to the status bar panel itself.
We then fetch the result returned by the web server into the variable output
from the XMLHttpRequest.responseText
property.
The text we receive back from the server looks something like this:
"GOOG",414.20,"5/1/2006","1:36pm",-3.74,417.85,419.44,412.19,4760215
We then parse the text. We use the split()
string function to split the comma-separated value string into its individual parts, with each field in a separate element in the array fieldArray
. At index 0 is the ticker symbol itself, which we don't need since we know which stock we're looking at.
The status bar panel's label is set to indicate the current value of the stock, which is stored in fieldArray
, by setting the samplePanel.label
property.
We then set the tooltip for the status bar panel by assigning an appropriate string to the samplePanel.tooltipText
property. The string is built from a combination of static strings and various elements from the fieldArray
array.
See it in action
Now you can install it and try it out. You should see something that looks like this:
In this screenshot, we also have the previous sample running, displaying the text "Hello World."