Monitoring Web Page Dynamic Updates With JAWS Step-By-Step

Author’s note: This post is being republished due to a blog crash. This post was originally published in mid 2012.

 

Recently I wanted to have JAWS monitor a webpage in the background while I was doing other things and report to me the latest data in a certain area when I requested it regardless of where else I was working on the PC. In case you can’t imagine this, the specific scenario is to monitor a quote from a trading website that refreshes. I am interested in being able to access information from other sources regardless of where the PC’s and JAWS’s actual focus is. Possibly it is an inspiration from The Qube and the ideas that came before it.

At present this solution is not portable, meaning each website and piece of information that you want to monitor has to be specifically scripted. It’d be nice to have a more portable easier to use solution. I am writing this up in part so anyone else who wants to try this can, and possibly someone will have ideas on how to improve it. For example, is there a way to use XPath to access specific webpage elements from JAWS script?

Background and Requirements

The trading website has a quote frame that can be set to monitor a ticker symbol and refresh approximately every 30 seconds. I wanted to access the latest quote on the page from anywhere, such as while checking email in Outlook.

Looking at the source, the quote was inside a table which was inside a frame. It therefore seemed possible to use JavaScript to extract the value of the quote. In order to make the script callable from anywhere the scripting would have to reside at the Default level of JAWS scripting. The scripts may either be included directly in the default.jss script source or in whatever other favorite means you may have for adding scripts to the default, such as by adding a use statement to call a compiled version.

Finding the Quote Value

The quote value is in a table cell with ID of “tdLast” and the amount changed is in another table cell with ID of “tdChange”. The table is in a frame with a ID of “footer. Since the frame already has an ID it is easier to find using JavaScript. To locate the TD element:

    dom = IEGetCurrentDocument () ; JAWS function to get pointer to currently open and focused page

    frame = dom.frames ;retrieves the array of frames on the page

    footer = frame(“footer”) ;only need this one

    doc = footer.document

quote = doc.getElementById(“tdLast”); the table cell element with the quote

 

You may notice that some of this code seems like it could be combined into one line, such as to go directly to the document of the frame: frame(“footer”).document. However, this does not work; it is a limitation of JAWS script calling COM objects that does not allow for this level of nesting. My advice is to stick to the single statements, it is a bit more typing but makes JAWS happy. And it is easier to debug.

Now that we have the table cell element it is a simple case to access the text by using the DOM property innerText:

    quote.innerText

This last bit of using getElementById() can be used to retrieve the other needed table cell as well that shows the change in the quote’s value.

Depending on your preferences you can parse the data in these cells to read what you want. For example, the “tdQuote” cell in this example has contents such as “25.36 last”. Since I don’t always want to hear “last” I parse it out:

q = StringSegment (quote.innerTEXT, ” \t\r”, 1) ;a return character is between the value and the string last

Setting Up Global Access

In order to have access to the webpage of interest regardless of where focus is we need to store the pointer for the page in a global variable. Then reference the variable instead of using IEGetCurrentDocument() for subsequent requests for the data. This does require that the user do a one-time initialization routine each time she wants to monitor the page. We also have to find an object that will continue to exist, at least as long as the browser is running with the webpage loaded.

I first tried to just cache the pointer to the “footer” frame as this would be the most efficient and not need to continually navigate the DOM to find it. However, the frame does a complete refresh and this destroys the pointer to the frame. Therefore its necessary to store the pointer to the top level webpage instead, and then navigate to the frame and find the table cells with each request for the latest quote.

I created a global variable of type object at the default script level, and then created ascript to store the pointer to the webpage. This requires that the user first navigate to the page, then run the script to set up the initialization. As this is a secured website where the user must first log in, this makes the most sense. (Though ideas on how to automate this are encouraged.) The script that I used to do this:

globals

        object webpage

Script SetQuotePage()

;find and store the object in webpage

Webpage = IEGetCurrentDocument ()

        if webpage then

            say(“quote ready”, OT_NO_DISABLE)

        EndIf

EndScript

Summary

I used default-level scripts and a global variable to access data from a webpage regardless of where the current focus is. I wanted this to be obtainable via a keystroke, and I did not want to use the JAWS Research-It tool as I did not want a window opening and closing when I just wanted the information quickly on the fly without affecting anything else that was being worked on. There may be a more efficient way to parse the webpage and I hope to find one. It would also be nice if this approach could be modified to make it more easily scalable, such as to set points of interest on any webpage with a keystroke and have the ability to automatically determine how to reference the underlying object. This would make it more usable for those who are not developers, and for when webpages change.