| Line 7: | Line 7: | ||
<code> | <code> | ||
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 |
</code> | </code> | ||
Revision as of 19:36, 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


