 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Do you think this tutorial is beneficial to the AHK Community? |
| Yeah, I think this tutorial is a great value-add to the Community. |
|
79% |
[ 19 ] |
| Nope - I think this tutorial is a waste of web space. |
|
4% |
[ 1 ] |
| I think this tutorial would be better if it incorporated AHK_L & COM_L. |
|
16% |
[ 4 ] |
|
| Total Votes : 24 |
|
| Author |
Message |
jethrow
Joined: 24 May 2009 Posts: 794 Location: Iowa, USA
|
Posted: Thu Nov 12, 2009 1:51 am Post subject: Basic Webpage Controls with JavaScript / COM - Tutorial |
|
|
Basic Webpage Controls with JavaScript / COM
This tutorial requires the COM Standard Library.
Purpose
The purpose of this tutorial is to teach the intermediate AHK user how to start using the COM Standard Library to control webpages. My goal is to provide methods for controlling webpages, similar to how the AHK Control Commands can control Windows Applications. This tutorial is going to be high level, but will provide links to those who want to dig deeper into these concepts. You don't need to have much programming experience, but I will assume you feel comfortable writing and executing AHK scripts. We will be covering the following three topics:- The HTML DOM - (Document Object Model) A basic understanding of the HTML DOM is essential for controlling webpages. This is because it's a "map" or "heirarchy" for accessing parts of the webpage. The HTML DOM is not language dependent, but rather the model for how the webpage document is constructed.
- JavaScript - We will cover some basic JavaScript because it is the scripting language of the web, and is supported by most web browsers. Controlling webpages using JavaScript is not the primary aim of this tutorial, but it will prove valuable because you should be able to find plenty of useful JavaScript examples online. This will be helpful because in my opinion, the simplest way to start using COM is to learn some basic JavaScript, and then "translate" that code to use with Sean's COM Library.
- COM - (Component Object Model) All you really need to know about COM for this tutorial is that Internet Explorer is a COM object - which means we can use the COM functions to manipulate it. Using Sean's COM functions is the most effective way to control an Internet Explorer Webpage with AHK.
Disclaimers
For this tutorial, I will show you how to control webpages using JavaScript, along with the AHK COM "translation" in green - note Sean's post below. (Using the COM Library will require Internet Explorer, but JavaScript can be used with most Web Browsers) The guidelines for "translating" JavaScript can be found in the first post of the COM Standard Library thread.
Some other tutorials that helped me out, and inspired this tutorial can be found here:
- COM Tutorial by tank - Study the basics from this; I will not be covering them.
- Control/manipulate webpages using JavaScript by daonlyfreez
- W3Schools - Many links listed below will take you to this website, which is an excellent resource for learning JavaScript in depth.Thank You:
- Chris Malet for creating AutoHotkey
- Sean for creating the COM Standard Library
- Both daonlyfreez & tank for the tutorials listed above
- tank, sinkfaze, & jaco0646 for reviewing this tutorial
Terms - The following terms will be used throughout this tutorial. You may use these links for a more in-depth description of each item.
HTML DOM, JavaScript, COM, Methods, document, value, element, form, name, ID, Input, Tag, selectedIndex, checked, innerText, innerHTML
Methods - The following Methods will be used throughout this tutorial. (comparable to built-in functions for AHK)
alert(), getElementById(), getElementsByName(), getElementsByTagName(), focus(), click()
Before we begin, this tutorial will be using examples that start with javascript: - which you will feed through the URL Address bar. These examples will be based on (and can be used with) the Search Forum webPage. Our first example will use the alert() method to pop-up a message box that says Hello World! Simply put this javascript in your URL Address bar and hit enter: | Code: | javascript: alert('Hello World!')
COM_Invoke(pwb, "Navigate", "javascript: alert('Hello World!')") |
Accessing WebPage Contents - HTML DOM
To understand how to use Javascript to control a webpage, you need a general understanding of the HTML DOM. It is similar to a "map" or "heirarchy" of the Webpage, as shown here:
*Image is from this website, which is another great resource for learning Javascript.
In the image above, note the document object - you will be using this object quite often. To access the Webpage, you will need to navigate through the HTML DOM. Here are some simple ways to do this:- Object Name & Index
Say you want to get the value of the 1st element in the 1st form, which will be the Search for Keywords Input Box. The path would look like this (a collection of objects starts at 0):
| Code: | | document.forms[0].elements[0].value | Now if you want to show the value of the element in a pop-up, simply put this javascript in your URL Address bar and hit enter: | Code: | javascript: alert(document.forms[0].elements[0].value)
MsgBox % COM_Invoke(pwb, "document.forms[0].elements[0].value") |
Object's Name / ID Attribute
You can also use the objects name or ID. For example, the 1st forms name is SearchForm, with its 1st elements name being search_keywords. The following javascript fed throught the address bar would produce the same results: | Code: | javascript: alert(document.SearchForm.search_keywords.value)
MsgBox % COM_Invoke(pwb, "document.SearchForm.search_keywords.value") | Or if you only know the elements name is search_keywords, you could display the value of that element using all, which references all the elements on the webpage: | Code: | javascript: alert(document.all.search_keywords.value)
MsgBox % COM_Invoke(pwb, "document.all.search_keywords.value") |
getElement Methods
If you want to get an element(s) based on limited criteria, you can use the following 3 methods:- getElementById(id) - returns a reference to the first object with the specified ID
- getElementsByName(name) - Returns a collection of objects with the specified name
- getElementsByTagName(tagname) - Returns a collection of objects with the specified tagname
The following example will display the value of the Search for Author Input Box, which is the 4th element on the webpage with an INPUT Tag:
(Note - the item number may be dynamic) | Code: | javascript: alert(document.getElementsByTagName('input')[3].value)
MsgBox % COM_Invoke(pwb, "document.getElementsByTagName[input].item[3].value") |
Controlling the WebPage
So far we have just retrieved information from the webpage. Now lets start controlling the webpage. Note - if the JavaScript doesn't end with a Method, use void 0.- Focus on a Webpage Element - focus()
Sets the focus to the Search for Keywords Input Box:
| Code: | javascript: document.all.search_keywords.focus()
COM_Invoke(pwb, "document.all.search_keywords.focus") |
Click on a Webpage Element - click()
Clicks the Search button: | Code: | javascript: document.getElementsByTagName('input')[11].click()
COM_Invoke(pwb, "document.getElementsByTagName[input].item[11].click") |
Set Value of an Input Field - value
Sets the value of the Search for Keywords Input Box: | Code: | javascript: document.all.search_keywords.value = 'Input Value'; void 0
COM_Invoke(pwb, "document.all.search_keywords.value", "Input Value") |
Dropdown Box Selection - selectedIndex | Quote: | | <SELECT class=post name=sort_by><OPTION selected value=0>Post Time</OPTION><OPTION value=1>Post Subject</OPTION><OPTION value=2>Topic Title</OPTION><OPTION value=3>Author</OPTION><OPTION value=4>Forum</OPTION></SELECT> | This is the HTML for the Sort By Dropdown. The following will set the Dropdown to Author: | Code: | javascript: document.all.sort_by.selectedIndex = 3; void 0 ; Note - you could use value = 3
COM_Invoke(pwb, "document.all.sort_by.selectedIndex", 3) |
Radio / Checkbox Selection - checked | Quote: | | <INPUT value=ASC type=radio name=sort_dir> Ascending<BR><INPUT value=DESC CHECKED type=radio name=sort_dir> Descending | This is the HTML for the Sort By Radio selection. The following will set the Radio to Ascending: | Code: | javascript: document.all.sort_dir[0].checked = true; void 0
COM_Invoke(pwb, "document.all.sort_dir[0].checked", "True") |
Get Text from a WebPage Element - innerText
Say you want to get the text at the top of the page (innerHTML will give you all the HTML): | Code: | | text := COM_Invoke(pwb, "document.getElementsByTagName[TD].item[2].innerText") |
There you have it! These techniques should help get you started. Next, I would recommend the following:- Try these Controls out on some of your favorite webpages.
- Find some more JavaScript examples, and then try "translating" them to COM. (JavaScript is well documented online)
- Learn additional ways to access the HTML DOM.
You may be wondering, "How do I find information about the element so I can access it?" Good question! The following tools can help you with that.
Helpful Tools- iWebBrowser2 Learner - This program will give you information about IE webpage elements as you hover over them.
- IE HTML Element Spy - This program will show you the information and source code of each element by dragging the curser over the webpage.
Frequently Asked Questions
What is a pwb?
- A variable that contains a pointer to the web browser object (Internet Explorer). Here is a simple script for creating one:
| Code: | COM_Init() ; Initialize COM
pwb := COM_CreateObject( "InternetExplorer.Application" ) ; Create an IE object
COM_Invoke( pwb, "Visible", "True" ) ; Make the IE object visible
COM_Invoke( pwb, "Navigate", "www.AutoHotkey.com" ) ; Navigate to a webpage
; when finished
COM_Release( pwb ) ; Always release COM objects
COM_Term() ; Always Uninitialize COM |
How to access an existing IE object?
- Sean's GetWebBrowser() function is great for this, and can be found here. Here is a function that accesses an IE object by window name:
| Code: | IEGet( name="" )
{
IfEqual, Name,, WinGetTitle, Name, ahk_class IEFrame ; Get active window if no parameter
Name := ( Name="New Tab - Windows Internet Explorer" ) ? "about:Tabs" : RegExReplace( Name, " - (Windows|Microsoft) Internet Explorer" )
oShell := COM_CreateObject( "Shell.Application" ) ; Contains reference to all explorer windows
Loop, % COM_Invoke( oShell, "Windows.Count" ) {
If pwb := COM_Invoke( oShell, "Windows.item[" A_Index-1 "]" )
If ( COM_Invoke( pwb, "LocationName" ) = name && InStr( COM_Invoke( pwb, "FullName" ), "iexplore.exe" ) )
Break
COM_Release( pwb ), pwb := ""
}
COM_Release( oShell )
Return, pwb
} |
How to know when the webpage in done loading?
- Sean's IEReady() function is great for this, and can be found here. Here is an example using the ReadyState property, which should work in may scenarios:
| Code: | COM_Invoke( pwb, "Navigate", "www.AutoHotkey.com" )
While, COM_Invoke( pwb, "ReadyState" ) <> 4
Sleep, 10 |
- OR - here is an example using the DocumentComplete event:
| Code: | COM_Init()
pwb := COM_CreateObject( "InternetExplorer.Application" )
COM_Invoke( pwb, "Visible", "True" )
sink := COM_ConnectObject( pwb, "IE_" ), loading = 1 ; Connect IE object & set var "loading" as TRUE
COM_Invoke( pwb, "Navigate", "www.AutoHotkey.com" )
While, loading
Sleep, 10
MsgBox, DONE!
COM_DisconnectObject( sink ) ; Disconnect IE object
COM_Release( pwb ), COM_Term()
Return
IE_DocumentComplete() { ; the "IE_" prefix corresponds to the COM_ConnectObject() function above
Global loading = 0 ; Break the While-Loop
} |
What if all this stuff is too confusing for me?
- I would recommend tank's iWeb Functions, which are designed to make web automation more simple. _________________ AHKL, COM_L,Webpage Controls,Donate to AHK
Last edited by jethrow on Tue Feb 09, 2010 11:22 pm; edited 11 times in total |
|
| Back to top |
|
 |
tank
Joined: 21 Dec 2007 Posts: 2416 Location: Louisville KY USA
|
Posted: Thu Nov 12, 2009 2:16 am Post subject: |
|
|
BRAVO
Thanks for this. My threads are out of date and i just dont have the kind of patience and grammer to produce something like this.
Users should be directed to this thread in the future instead of my IE based COM threads. This work supercedes all of mine _________________ Basic Webpage Controls with JavaScript / COM - Tutorial by Jethrow
 |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2224
|
Posted: Fri Nov 13, 2009 1:56 pm Post subject: |
|
|
| Very nice. IMO, however, it would've been even more clear if done using COM_L for AHK_L than COM for the old AHK. COM_Invoke being explicit may distract users from the main point. |
|
| Back to top |
|
 |
jethrow
Joined: 24 May 2009 Posts: 794 Location: Iowa, USA
|
Posted: Fri Nov 13, 2009 2:51 pm Post subject: |
|
|
Thanks for the feedback guys - I was hoping this would prove benificial to the community.
| Sean wrote: | | IMO, however, it would've been even more clear if done using COM_L for AHK_L than COM for the old AHK. COM_Invoke being explicit may distract users from the main point. |
I agree 100% If fact, that distraction was one of the main reasons I had originally decided to write this tutorial - to help bridge users gap in understanding. I had just finished writing this when Lexikos released AHK_L with object support. Then, when you released COM_L, I thought this tutorial would become rapidly outdated (which I still think). However, who knows when Chris will implement object support into the regular AHK release? Once that happens, I'll probably update this tutorial. _________________ AHKL, COM_L,Webpage Controls,Donate to AHK |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2224
|
Posted: Fri Nov 13, 2009 3:36 pm Post subject: |
|
|
It's a DOM tutorial, so, there are a lot to clarify other than just syntax. When, using JavaScript the top/base object is the Window object, not WebBrowser object. In fact, WebBrowser object is neither part of nor essential for DOM manipulation. So, in strict sense,
| Code: | | javascript: document.all[11].click() | is actually equivalent to | Code: | | COM_Invoke(window, "document.all[11].click()") | not to | Code: | | COM_Invoke(pwb, "document.all[11].click()") |
However, this tutorial uses pwb in all of the examples, which might lead readers to believe that using WebBrowser object is inevitable for DOM manipulation, not a mere convenience. |
|
| Back to top |
|
 |
jethrow
Joined: 24 May 2009 Posts: 794 Location: Iowa, USA
|
Posted: Fri Nov 13, 2009 4:06 pm Post subject: |
|
|
| Sean wrote: | | When, using JavaScript the top/base object is the Window object, not WebBrowser object. |
Thank you for pointing this out Sean. I hadn't even thought about, nor fully understood this. In your example, this would be technically accurate, right? | Code: | | window := COM_Invoke(pwb, "contentWindow") |
EDIT - and these are the ignorant questions I end up asking if I don't study & test the code before I ask questions. See tank's answer in the next post. _________________ AHKL, COM_L,Webpage Controls,Donate to AHK
Last edited by jethrow on Fri Nov 13, 2009 5:15 pm; edited 2 times in total |
|
| Back to top |
|
 |
tank
Joined: 21 Dec 2007 Posts: 2416 Location: Louisville KY USA
|
Posted: Fri Nov 13, 2009 4:09 pm Post subject: |
|
|
Contentwindow is not accessable from the browser object but from a frame object
to get a window object from a pwb is done as thus
| Code: | window:=com_invoke(pwb,"document.parentwindow")
window:=COM_QueryService(pwb, "{332C4427-26CB-11D0-B483-00C04FD90119}", "{332C4427-26CB-11D0-B483-00C04FD90119}") | contentWindow is typically used to aquire a window handle from a frame _________________ Basic Webpage Controls with JavaScript / COM - Tutorial by Jethrow
 |
|
| Back to top |
|
 |
tank
Joined: 21 Dec 2007 Posts: 2416 Location: Louisville KY USA
|
Posted: Fri Nov 13, 2009 4:25 pm Post subject: |
|
|
Even more confusing because Document must be accessed with COM prior to accessing Window.
I generally dont climb back up to or query DOM for the window unles i need to use the execScript method
For sheer convenience I am going to post some JScript and VBS that as far as I can tell isn’t easily found elsewhere.
The main thing to know is the browser encompasses the toolbars and address bar while the window object refers only to the content area
JScript that creates a new browser and navigates
| Code: | <script language="jscript">
var pwb = new ActiveXObject("InternetExplorer.Application");
pwb.visible=true;
pwb.Navigate("www.AutoHotkey.com");
</script> |
Same as above but in VBS
| Code: | <script language="vbscript">
set pwb = CreateObject("InternetExplorer.Application")
pwb.visible=true
pwb.Navigate("www.AutoHotkey.com")
set pwb = nothing ' releases the variable
</script> |
Replicates most of the functionality of the IEGet function posted above in AHK.
| Code: | <script language="vbscript">
Function IEGet(Title)
''Gets window by the title
''Title is case sensitive
Set oShellApplication = CreateObject( "Shell.Application" )
Set oWindows = oShellApplication.Windows
For Each oWindow In oWindows
if InStr(1,oWindow.LocationName,Title,1) > 0 and InStr(1,oWindow.FullName,"iexplore.exe",1) > 0 then
set IEGet=oWindow '' create an object variable
exit for
end if
next
Set oWindows = nothing
Set oShellApplication = nothing
End Function
</script> | obviously this can be done in JScript as well but I will not bother. From here we can begin to see the similarities in the code structure _________________ Basic Webpage Controls with JavaScript / COM - Tutorial by Jethrow

Last edited by tank on Tue Nov 24, 2009 5:22 pm; edited 1 time in total |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4116 Location: Belgrade
|
Posted: Fri Nov 13, 2009 4:38 pm Post subject: |
|
|
I guess its possible to create script and framework from the scripts around the forum that:
1. Loads given HTML into the IE control.
2. Crates the tree presentation of DOM or all automatable objects with user filter.
3. Let the user associate some code with the objectl; some hardcoded operations would be nice for start and plugin architecture to add more; click, send, size for the start. Dynamic function calls could be used as plugins for new operations if desired.
4. Let the user save such project and run it. _________________
 |
|
| Back to top |
|
 |
tank
Joined: 21 Dec 2007 Posts: 2416 Location: Louisville KY USA
|
Posted: Fri Nov 13, 2009 4:49 pm Post subject: |
|
|
are you refering to an ahk Browser in a GUI that functions much the same as HTA applications?
If so of course IMO triggering an ahk script to run from an html page is super easy if its a trusted source
you can use the FileRun function with an onclick event to trigger scripts even pass command line parameters the below i copied from my own proprietary library. I use this in a call center environment with great reliability
IF not obvious the below is VBS
| Code: | Set oShell = CreateObject( "WScript.Shell" )
Set objFSO = CreateObject("Scripting.FileSystemObject")
Function FileRun(strFile,filename,async)
'' strFile - full run command line example format """C:\Program Files\AutoHotkey\AutoHotkey.exe"" /ErrorStdOut ""C:\Documents and Settings\nbk64jq\Desktop\MyHots.ahk"" CMDArg"""
'' filename - path and filename
FileRun=false
'' async - wait for file to exit before continuing accepts true false
e=FileExists(filename)
if e then
r=isRunning(filename)
if not r then
oShell.Run strFile, 6, async
FileRun=true
end if
end if
End Function
Function isRunning(CmdTitle)
isRunning=false
For Each strProcess In GetObject("winmgmts:").InstancesOf("win32_process")
if InStr(1,strProcess.CommandLine,CmdTitle,1) > "2" then
isRunning=true
end if
next
End Function
Function FileExists(strFile)
FileExists = objFSO.FileExists(strFile)
End Function |
Edit I have tried using events from ahk for this but in non standard deployment if IE these fail and in the past caused the gui to crash if to many events were triggered _________________ Basic Webpage Controls with JavaScript / COM - Tutorial by Jethrow
 |
|
| Back to top |
|
 |
sinkfaze
Joined: 19 Mar 2008 Posts: 2721 Location: the tunnel(?=light)
|
Posted: Fri Nov 13, 2009 8:31 pm Post subject: |
|
|
So given the discussion in this thread about "recursing" through frames to a page element, is it possible to amend some of the current iWeb functions or create a new iWeb function(s) to accommodate frame recursion? Or is it just something worth mentioning in the course of this tutorial, for example?
BTW - Excellent tutorial jethrow, glad I could help in whatever small way I could.  _________________ Try Quick Search for Autohotkey or see the tutorial for newbies. |
|
| Back to top |
|
 |
tank
Joined: 21 Dec 2007 Posts: 2416 Location: Louisville KY USA
|
Posted: Fri Nov 13, 2009 8:57 pm Post subject: |
|
|
edit i spose your refering to this library
iWeb functions
i have considered recurse into frames for some time now but unfortunately the options and depth of recursion seem a bit complex to make reliable I might get around to it sometime in the future but it really seems that frames might be somthing we want to leave ot users more versed in DOM and using Invoke exclusively _________________ Basic Webpage Controls with JavaScript / COM - Tutorial by Jethrow

Last edited by tank on Sat Nov 14, 2009 9:36 am; edited 1 time in total |
|
| Back to top |
|
 |
sinkfaze
Joined: 19 Mar 2008 Posts: 2721 Location: the tunnel(?=light)
|
Posted: Fri Nov 13, 2009 10:25 pm Post subject: |
|
|
Would something like this be feasible? Obviously the user will be responsible for obtaining the frames themselves:
| Code: | iWeb_clickDomObj(pwb,obj,frame="") { ; frame is comma delimited list of frames by name/id/number
If pWin:=iWeb_DomWin(pwb) {
if frame {
Loop, Parse, frame, `,
framePath.="document.all[" A_LoopField "].contentwindow."
COM_Invoke(pWin,framePath . "document.all.item[" obj "].click")
}
else
COM_Invoke(pWin,"Document.all.item[" obj "].click")
d=1
COM_Release(pWin), VarSetCapacity(framePath,0)
}
Return d
}
; example usage
iWeb_clickDomObj(pwb,"username","_sweclient,_swecontent,_sweview,_svf1") |
Probably very sloppy code by your standards but you get the general idea. _________________ Try Quick Search for Autohotkey or see the tutorial for newbies. |
|
| Back to top |
|
 |
Carcophan
Joined: 24 Dec 2008 Posts: 841 Location: :noitacoL
|
Posted: Fri Nov 13, 2009 11:08 pm Post subject: |
|
|
Does this mean I have to change my Sig now?  _________________ "Unfortunately a "COM for Dummies" book would be a little like "Neurosurgery for Dummies," in the end you're just gonna have to learn" ~Tank |
|
| Back to top |
|
 |
tank
Joined: 21 Dec 2007 Posts: 2416 Location: Louisville KY USA
|
Posted: Fri Nov 13, 2009 11:28 pm Post subject: |
|
|
Very astute my young padawan
I spose if you want to update the other functions I havent time right now ill update the zip file with it or you can wait months (perhaps years ) tll i get around to it
@Carcophan no probably not the vast majority still wont follow this tutorial since they have no interest whatsoever in actually learning javascript or DOM. This tutorial is still aimed at folks who know at least that much and to help them convert similar javascript to compatable COM.AHK
Most still wont understand COM DOM or scripting so I think the quote still applies _________________ Basic Webpage Controls with JavaScript / COM - Tutorial by Jethrow
 |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|