| Line 30: | Line 30: | ||
<code> | <code> | ||
Dim NOM : Set NOM = GetNOM(ActiveWindow) | Dim NOM : Set NOM = GetNOM(ActiveWindow) | ||
| − | + | ||
| − | If Not NOM Is Nothing Then | + | If Not NOM Is Nothing Then |
| − | + | Set currentDocument = NOM.document | |
| − | + | If Not currentDocument Is Nothing Then | |
| − | + | If TypeName(currentDocument) = "HTMLDocument" Then | |
| − | + | Dim location : Set location = currentDocument.location | |
| − | + | If Not location Is Nothing Then | |
| − | + | MsgBox "The URL for this page is: " & location.href | |
| − | + | End If | |
| − | + | End If | |
| − | + | End If | |
| − | End If | + | End If |
</code> | </code> | ||
| Line 49: | Line 49: | ||
' Begin | ' Begin | ||
Option Explicit | Option Explicit | ||
| − | + | ||
Dim NOM, DOMEvents, DOMDocumentEvents, DOMElementEvents | Dim NOM, DOMEvents, DOMDocumentEvents, DOMElementEvents | ||
Set DOMElementEvents = CreateObject("Scripting.Dictionary") | Set DOMElementEvents = CreateObject("Scripting.Dictionary") | ||
| − | + | ||
ConnectEvent DesktopWindow, "OnChildActivate", "OnChildActivate" | ConnectEvent DesktopWindow, "OnChildActivate", "OnChildActivate" | ||
| − | + | ||
Sub OnChildActivate(wObj) | Sub OnChildActivate(wObj) | ||
| − | + | ClearElementEvents() | |
| − | + | If wObj.ModuleName = "IEFRAME" Then | |
| − | + | Set NOM = GetNOM(wObj) | |
| − | + | If Not NOM Is Nothing Then | |
| − | + | DOMEvents = ConnectObject(NOM, "DOM_") | |
| − | + | DOM_onload() | |
| − | + | End If | |
| − | + | End If | |
| − | End Sub | + | End Sub |
| − | + | ||
Function GetNOM(wObj) | Function GetNOM(wObj) | ||
| − | + | Dim ieChildren, ieChild, NOM | |
| − | + | ||
| − | + | ' Begin | |
| − | + | Set GetNOM = Nothing | |
| − | + | Set ieChildren = wObj.Children.FilterByClassAndModule("Internet Explorer_Server", "MSHTML") | |
| − | + | For Each ieChild In ieChildren | |
| − | + | If ieChild.Visible Then | |
| − | + | Set NOM = ieChild.NativeObjectModel | |
| − | + | If Not NOM Is Nothing Then | |
| − | + | Set GetNOM = NOM | |
| − | + | End If | |
| − | + | Exit For | |
| − | + | End If | |
| − | + | Next | |
| − | End Function | + | End Function |
| − | + | ||
| − | Sub DOM_onload() | + | Sub DOM_onload() |
| − | + | Dim document | |
| − | + | ||
| − | + | If Not NOM Is Nothing Then | |
| − | + | Set document = NOM.document | |
| − | + | If Not document Is Nothing Then | |
| − | + | If DOMDocumentEvents <> 0 Then | |
| − | + | Disconnect DOMDocumentEvents | |
| − | + | DOMDocumentEvents = 0 | |
| − | + | End If | |
| − | + | DOMDocumentEvents = ConnectObjectWithParameter(document, "DOC_", document) | |
| − | + | DOC_onreadystatechange document | |
| − | + | End If | |
| − | + | End If | |
| − | End Sub | + | End Sub |
| − | + | ||
| − | + | Sub DOC_onreadystatechange(document) | |
| − | Sub DOC_onreadystatechange(document) | + | Dim readyState, controls, control, controlName |
| − | + | ||
| − | + | On Error Resume Next | |
| − | + | readyState = document.readyState | |
| − | + | If Err.Number <> 0 Then | |
| − | + | readyState = Err.Description | |
| − | + | End If | |
| − | + | On Error Goto 0 | |
| − | + | If readyState = "complete" Then | |
| − | + | ClearElementEvents() | |
| − | + | ||
| − | + | Set controls = document.getElementsByTagName("input") | |
| − | + | If controls.length > 0 Then | |
| − | + | DOMElementEvents.RemoveAll | |
| − | + | For Each control In controls | |
| − | + | If Not DOMElementEvents.Exists(DOMElementEvents.Count + 1) Then | |
| − | + | DOMElementEvents.Add DOMElementEvents.Count + 1, ConnectObjectWithParameter(control, "IE_", control) | |
| − | + | End If | |
| − | + | Next | |
| − | + | End If | |
| − | + | End If | |
| − | + | End Sub | |
| − | End Sub | + | |
| − | + | Sub ClearElementEvents() | |
| − | Sub ClearElementEvents() | + | Dim keys |
| − | + | ||
| − | + | If DOMElementEvents.Count > 0 Then | |
| − | + | ' Disconnect any existing events | |
| − | + | keys = DOMElementEvents.Keys | |
| − | + | For k = 0 To UBound(keys) | |
| − | + | If DOMElementEvents(keys(k)) <> 0 Then | |
| − | + | Disconnect DOMElementEvents(keys(k)) | |
| − | + | DOMElementEvents.Remove keys(k) | |
| − | + | End If | |
| − | + | Next | |
| − | + | End If | |
| − | + | End Sub | |
| − | End Sub | + | |
| − | + | Sub IE_onfocus(theControl) | |
| − | Sub IE_onfocus(theControl) | + | Dim title |
| − | + | ||
| − | + | Select Case TypeName(theControl) | |
| − | + | Case "HTMLAnchorElement" | |
| − | + | ' If the anchor has a title attribute, speak it. | |
| − | + | title = theControl.getAttribute("title") | |
| − | + | If Len(title) > 0 Then | |
| − | + | Speak title | |
| − | + | End If | |
| − | + | Case "HTMLInputElement" | |
| − | + | ' If the control has an ARIA required attribute, speak required | |
| − | + | If theControl.getAttribute("aria-required") Then | |
| − | + | Speak "required" | |
| − | + | End If | |
| − | + | ' If the control is a checkbox, radio button, or standard button, speak the ARIA pressed state | |
| − | + | If theControl.Type = "checkbox" Or theControl.Type = "radio" Or theControl.Type = "button" Then | |
| − | + | Speak theControl.getAttribute("aria-pressed") | |
| − | + | End If | |
| − | + | End Select | |
| − | + | End Sub | |
| − | End Sub | + | ' End |
| − | + | ||
| − | ' End | + | |
</code> | </code> | ||
Revision as of 19:38, 27 September 2011
NOTE: This article applies to Window-Eyes 7.X.
Accessing the IE DOM through Window-Eyes apps isn't trivial, but it's certainly doable, and can provide you with a fairly comprehensive method for getting feedback about a web page, including when specific events occur.
The first steps is obtaining the Native Object Model from the visible Internet Explorer_Server window. This is the window that hosts the web page content. We'll create a simple routine that we can refer to anytime we're after the NOM (Native Object Model).
Function GetNOM(wObj)
Dim ieChildren, ieChild, NOM
' Begin
Set GetNOM = Nothing
Set ieChildren = wObj.Children.FilterByClassAndModule("Internet Explorer_Server", "MSHTML")
For Each ieChild In ieChildren
If ieChild.Visible Then
Set NOM = ieChild.NativeObjectModel
If Not NOM Is Nothing Then
Set GetNOM = NOM
End If
Exit For
End If
Next
End Function
Our function takes one parameter, and that's the window that we're interesting in getting the NOM from. If you have your app associated to Internet Explorer, it's safe to use the ActiveWindow object when calling your GetNOM function. Once you have obtained a valid NOM object, you can then retrieve the document property (IHTMLDocument), or connect to the NOM's events.
The document property can be thought of as the root of the document's tree hierarchy. You can use it, among many other things, to get the location/URL of the current document.
Dim NOM : Set NOM = GetNOM(ActiveWindow) If Not NOM Is Nothing Then Set currentDocument = NOM.document If Not currentDocument Is Nothing Then If TypeName(currentDocument) = "HTMLDocument" Then Dim location : Set location = currentDocument.location If Not location Is Nothing Then MsgBox "The URL for this page is: " & location.href End If End If End If End If
You can also monitor DOM events to determine when things happen, such as when a page loads, or when an even occurs for a specific element. The following proof of concept example demonstrates how to get a DOM object and monitor focus events for input edit boxes. If a focus occurs for an edit box that has the ARIA "required" attribute, it will be spoken. There are some additional enhancements for a fwe other controls as well as anchors. Note that controls typically do not get physical focus while Browse Mode is enabled, so you'll want to make sure that you've turned off Browse Mode before tabbing through controls.
' Begin
Option Explicit
Dim NOM, DOMEvents, DOMDocumentEvents, DOMElementEvents
Set DOMElementEvents = CreateObject("Scripting.Dictionary")
ConnectEvent DesktopWindow, "OnChildActivate", "OnChildActivate"
Sub OnChildActivate(wObj)
ClearElementEvents()
If wObj.ModuleName = "IEFRAME" Then
Set NOM = GetNOM(wObj)
If Not NOM Is Nothing Then
DOMEvents = ConnectObject(NOM, "DOM_")
DOM_onload()
End If
End If
End Sub
Function GetNOM(wObj)
Dim ieChildren, ieChild, NOM
' Begin
Set GetNOM = Nothing
Set ieChildren = wObj.Children.FilterByClassAndModule("Internet Explorer_Server", "MSHTML")
For Each ieChild In ieChildren
If ieChild.Visible Then
Set NOM = ieChild.NativeObjectModel
If Not NOM Is Nothing Then
Set GetNOM = NOM
End If
Exit For
End If
Next
End Function
Sub DOM_onload()
Dim document
If Not NOM Is Nothing Then
Set document = NOM.document
If Not document Is Nothing Then
If DOMDocumentEvents <> 0 Then
Disconnect DOMDocumentEvents
DOMDocumentEvents = 0
End If
DOMDocumentEvents = ConnectObjectWithParameter(document, "DOC_", document)
DOC_onreadystatechange document
End If
End If
End Sub
Sub DOC_onreadystatechange(document)
Dim readyState, controls, control, controlName
On Error Resume Next
readyState = document.readyState
If Err.Number <> 0 Then
readyState = Err.Description
End If
On Error Goto 0
If readyState = "complete" Then
ClearElementEvents()
Set controls = document.getElementsByTagName("input")
If controls.length > 0 Then
DOMElementEvents.RemoveAll
For Each control In controls
If Not DOMElementEvents.Exists(DOMElementEvents.Count + 1) Then
DOMElementEvents.Add DOMElementEvents.Count + 1, ConnectObjectWithParameter(control, "IE_", control)
End If
Next
End If
End If
End Sub
Sub ClearElementEvents()
Dim keys
If DOMElementEvents.Count > 0 Then
' Disconnect any existing events
keys = DOMElementEvents.Keys
For k = 0 To UBound(keys)
If DOMElementEvents(keys(k)) <> 0 Then
Disconnect DOMElementEvents(keys(k))
DOMElementEvents.Remove keys(k)
End If
Next
End If
End Sub
Sub IE_onfocus(theControl)
Dim title
Select Case TypeName(theControl)
Case "HTMLAnchorElement"
' If the anchor has a title attribute, speak it.
title = theControl.getAttribute("title")
If Len(title) > 0 Then
Speak title
End If
Case "HTMLInputElement"
' If the control has an ARIA required attribute, speak required
If theControl.getAttribute("aria-required") Then
Speak "required"
End If
' If the control is a checkbox, radio button, or standard button, speak the ARIA pressed state
If theControl.Type = "checkbox" Or theControl.Type = "radio" Or theControl.Type = "button" Then
Speak theControl.getAttribute("aria-pressed")
End If
End Select
End Sub
' End


