eGet() - Grab Internet Explorer Elements Easily

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
berban
Posts: 97
Joined: 14 Apr 2014, 03:20

eGet() - Grab Internet Explorer Elements Easily

04 Jul 2016, 02:55

I use this code to make simple macros for internet explorer, which I still use out of habit. For example, this simple script allows you to quickly move to the next page in a google search, forum thread, or almost any variety of sites:

Code: Select all

#IfWinActive ahk_class IEFrame                                          ; if an internet explorer window is open
~Space Up::
If (A_PriorHotkey = A_ThisHotkey) and (A_TimeSincePriorHotkey < 200)    ; If you double tap spacebar...
	eGet("a", "Next.*|(.* )?\>+").Click()                           ; ...script will click on "a" elements that start with "Next" or end with ">"
Return
The main feature of this function is that it allows you to grab elements that don't have an ID or Name attribute, but there are several other features which can help make macros even easier.

eGet(Tag, Text, AfterTag, AfterText)
  • Tag: A space-delimited list with the format <tagname> <attribute>=<RegEx_Needle> <attribute>=<RegEx_Needle> ...
    • Tagname: Put whatever tag you are looking for, e.g. a, span, img, etc. Use an asterisk ( * ) to look at all tags. (Note: using * will reduce performance because the script will now need to check likely hundreds more tags.)
    • Attribute: (Optional) Attribute of the element you want to filter by, e.g. href, src, or width. Note: Use "ClassName" instead of "Class" (this is how AutoHotkey sees this attribute).
      To find out the attributes of elements in a webpage, right click and select "Inspect Element" or use IE Element Spy: http://www.vowsoft.com/ies/
    • RegEx_Needle: A regular expression needle to match against the tag. The script by default pads the expression with is)^\s*(%Needle%)\s*$, i.e. case-insensitive and matches entire phrase except leading and trailing spaces. But you can change this by changing TagRegExStart and TagRegExEnd in the function. You can include strings with spaces by enclosing the string in quotation marks, e.g. input value="some spaces and ""quotation marks"""
  • Text: Text passed to this parameter is matched against the innerText of the element for a match, once more using a regular expression. It is equivalent to putting innerText="value" in the Tag parameter. If the desired tag is an input field, this parameter will also match the Class, Value, ID, or Name attributes (input elements never contain an innerText).
  • AfterTag: The last two parameters are if you want to find a given element that comes AFTER another given element, which can be useful in certain situations. AfterTag contains the tag name and attribute matches for the FIRST element, using the same format as the Tag parameter.
  • AfterText: The innerText match to use for the first element, again using the same format as the Text parameter.
Special "attribute" values: These are not HTML attributes but rather give the script additional directions for finding the element you want.
  • All: If you put "All" somewhere after the tag name, the script will return an array containing all elements that match your criteria instead of simply the first one.
  • #=n: Will find the nth occurrence of your match and return that. For instance, a #=5 will fetch the 5th a element. Specify "last" to retrieve the last element found that matches the criteria given.
The function returns a pointer to the DOM element if it is found, and 0 if it is not found. You can then use .click() or .focus() on these elements, or retrieve other properties. The function also stores the DOM element in the global variable "Element".

One important variable which is not passed as a parameter is the pointer to the web browser object. If an internet explorer window is currently active when eGet() is called, it will use this window. If you want to use another window, set the global variable "pwb" to the pointer to that browser object using the included function PWB_Get(). The web browser pointer will continue to be used for any additional eGet() calls within the next 2 seconds (for performance reasons), after which it will reset. To disable this behavior use PWB_Clear("Off").

Code:

Code: Select all

; === eGet(TAG, TEXT) ===
;
; Returns element object for the element if it is found in the current web browser object (global variable PWB).
; If there is no current web browser object, the active internet explorer window will become the current web browser object
;
; --- Parameters ---
;
; TAG
; Indicate a tag name (i.e. a, input, span, div, etc). Indicate an asterisk (*) for any tag (will make search more time-consuming).
; After the tag name you may optionally include a space and then a space-delimited list of tag attributes to match in the following format;
; attribute=value otherattribute=pattern.* lastattribute="value with spaces"
; All values are in case-insensitive RegEx format and will be assumed to be the entire space-trimmed matching string, i.e. they become i)^\s*%Value%\s*$
;
; TEXT
; Text passed to this parameter is matched against the innerText of the element for a match. It is equivalent to putting innerText="value" in the TAG parameter.
; If the desired TAG is an input field, this parameter will also match the Class, Value, ID, or Name attributes (input elements never contain an innerText).

; Use ID attribute for shorter, more efficient searching. Use IDRegEx attribute if you want to search ID using a regular expression

; To-do: Fix weird attribute names: see https://html.spec.whatwg.org/multipage/syntax.html#attributes-2

eGet(Tag, Text="", AfterTag="", AfterText="") ; ; https://autohotkey.com/boards/viewtopic.php?t=19889
{
	Static UserConfig_A := "foo"
	, TagRegExStart := "is)^\s*("
	, TagRegExEnd := ")\s*$"
	;----------------------------------------------------------------------------------------------------
	Global Element := ""
	EditableInputClasses = Text,Password,Checkbox
	If !(PWB := PWB_Init())
		Return False
	SpecialAttributes := "#,All", Delimiter := Chr(1), Literal := """", After := "", EditableInputClasses := "," EditableInputClasses ","
	Loop 2 {
		If (A_Index = 2)
			If (AfterTag = "") and (AfterText = "")
				Break
			Else
				After := "After"
		If RegExMatch(%After%Tag, "i)^[a-z0-9:]+(?=\s|$)", %After%TagName) and (%After%TagName <> "All")
			%After%Tag := SubStr(%After%Tag, StrLen(%After%TagName) + 1)
		Else
			%After%TagName := "*", %After%Tag := A_Space %After%Tag
		@5 := 1, %After%AttributesList := Text Delimiter, %After%n := 0, %After%# := 1
		While (@5 := RegExMatch(%After%Tag, "i)\s(?:!([a-z:\-]+)|(\+|-)?([\w#:\-]+)=?(" Literal "(?:[^" Literal "]|" Literal Literal ")*" Literal "(?=\s|$)|\S*))", @, @5 + StrLen(@)))
			If (@1 <> "")
				%After%Tag := SubStr(%After%Tag, 1, @5 + StrLen(@)) UserConfig_%@1% SubStr(%After%Tag, @5 + StrLen(@))
			Else If (@4 <> "") {
				If (InStr(@4, Literal) = 1) and (@4 <> Literal) and (SubStr(@4, 0, 1) = Literal) and (@4 := SubStr(@4, 2, -1))
					StringReplace, @4, @4, %Literal%%Literal%, %Literal%, All
				%After%%@3% := @4, %After%AttributesList .= @3 Delimiter
			} Else
				%After%%@3% := @2 = "+" ? True : @2 = "-" ? False : True
		Loop, Parse, SpecialAttributes, `,
			StringReplace, %After%AttributesList, %After%AttributesList, %A_LoopField%%Delimiter%, , All
	}
	If (ID <> "") and (After = "") { ; short circuit to check for element IDs
		Loop % 1 + PWB.Document.ParentWindow.Frames.Length {
			If (A_Index = 1)
				Document := PWB.Document
			Else If !IsObject(Document := PWB.Document.ParentWindow.Frames[A_Index - 2].Document)
				Document := ComObj(9, ComObjQuery(PWB.Document.ParentWindow.Frames[A_Index - 2], "{332C4427-26CB-11D0-B483-00C04FD90119}", "{332C4427-26CB-11D0-B483-00C04FD90119}"), 1).Document.DocumentElement
			If (Element := Document.getElementById(ID))
				Return Element
		}
	}
	If All
		Element := Object()
	If (AfterAll <> "") or (After# = "Last") {
		MsgBox, 262160, %A_ScriptName% - %A_ThisFunc%(): Error,  The "All" and "# = Last" options are not supported for the "After" element.
		Return False
	}
	If After and (TagName <> AfterTagName) {
		QueryTag := "*"
		If (TagName <> "*")
			AttributesList .= "Tagname" Delimiter
		If (AfterTagName <> "*")
			AfterAttributesList .= "Tagname" Delimiter
	} Else
		QueryTag := TagName
	Loop % 1 + PWB.Document.ParentWindow.Frames.Length {
		If (A_Index = 1)
			Document := PWB.Document
		Else If !IsObject(Document := PWB.Document.ParentWindow.Frames[A_Index - 2].Document)
			Document := ComObj(9, ComObjQuery(PWB.Document.ParentWindow.Frames[A_Index - 2], "{332C4427-26CB-11D0-B483-00C04FD90119}", "{332C4427-26CB-11D0-B483-00C04FD90119}"), 1).Document.DocumentElement ; http://www.autohotkey.com/board/topic/91443-comie-error-0x80070005-access-is-denied-with-paypal/
		Loop % Document.GetElementsByTagName(QueryTag).Length {
			@ := Document.GetElementsByTagName(QueryTag)[A_Index - 1]
			Loop, Parse, %After%AttributesList, %Delimiter%
				If (A_Index = 1) {
					If (%After%Text <> "") and !RegExMatch((%After%TagName <> "input") ? @.innerText : !InStr(EditableInputClasses, "," @.Type ",") and (@.Value <> "") ? @.Value : (@.ID <> "") ? @.ID : @.Name, TagRegExStart %After%Text TagRegExEnd)
						Break
				} Else If (A_LoopField = "") and ((++%After%n = %After%#) or ((After = "") and (All or ((# = "Last") and !(Last := @))))) {
					If After {
						After =
						Break
					}
					If !All
						Return Element := @, PWB_Clear()
					Element.Insert(@)
				} Else If !RegExMatch(@[A_LoopField], TagRegExStart %After%%A_LoopField% TagRegExEnd)
					Break
		}
	}
	Return All ? Element : Element := Last ? Last : False, PWB_Clear()
}

; === eWait() ===
;
; Waits for the tag to appear

eWait(Tag, Text="", Timeout=4, ErrorAction="Exit", NewPWBEvery=4, Sleep=150)
{
	Global PWB, Element
	If Timeout
		End := A_TickCount + Abs(Timeout) * 1000
		; m("to")
	While !eGet(Tag, Text)
		If (Mod(A_Index, NewPWBEvery + 1) = 0)
			PWB := ""
		Else If (End > A_TickCount)
			Sleep %Sleep%
		Else If (Timeout < 0)
			Return False
		Else
			Exit
	If Element
		Return Element
	Else If (ErrorAction = "Exit")
		Exit
	Else If (ErrorAction = "ExitApp")
		ExitApp
	Else
		Return
}

; === Dump(TAGNAME) ===
;
; Dumps the outerHTML of all elements of TAGNAME type into a blank notepad file. Used for debugging and to see all elements that AutoHotkey can access.

Dump(TagName="*")
{
	EditorPath = "%A_AhkPath%\..\..\Utilities\Notepad++\Notepad++.exe" ; "%A_AhkPath%\..\SciTE\SciTE.exe"
	OutputFile = %A_Temp%\COM+IE_Dump.txt
	Tooltips = %True%
	ReplaceInnerHTMLWith := " ... <TAG #%n%> ... " ; False
	;------------------------------------------------------------------------------------------------------------------------
	If !(PWB := PWB_Init())
		Return False
	FileDelete, %OutputFile%
	VarSetCapacity(Output, 50000), n := 0, SpecialChar := Chr(1)
	If Tooltips
		Tooltips := Floor(PWB.Document.GetElementsByTagName(TagName).Length ** 0.3)
	Loop % 1 + PWB.Document.ParentWindow.Frames.Length {
		Output .= (A_Index = 1 ? "" : SpecialChar SpecialChar) "============================================================= Frame " A_Index " =============================================================" SpecialChar
		If (A_Index = 1)
			Document := PWB.Document
		Else If !IsObject(Document := PWB.Document.ParentWindow.Frames[A_Index - 2].Document)
			Document := ComObj(9, ComObjQuery(PWB.Document.ParentWindow.Frames[A_Index - 2], "{332C4427-26CB-11D0-B483-00C04FD90119}", "{332C4427-26CB-11D0-B483-00C04FD90119}"), 1).Document.DocumentElement
		Loop % Document.GetElementsByTagName(TagName).Length {
			n += 1, @ := Document.GetElementsByTagName(TagName)[A_Index - 1].outerHTML
			If ReplaceInnerHTMLWith and (@ <> "") {
				StartPos := 1
				While InStr(Output, @, False, StartPos)
					StartPos := InStr(Output, @, False, StartPos) + StrLen(@)
				If (StartPos <> 1) {
					Transform, ReplacementString, Deref, %ReplaceInnerHTMLWith%
					Output := SubStr(Output, 1, StartPos - StrLen(@) - 1) ReplacementString SubStr(Output, StartPos)
				}
			}
			Output .= SpecialChar n A_Tab @
			If (Mod(n, Tooltips) = 1)
				ToolTip, % "Number: " n "`n" SubStr(RegExReplace(@, ".{40}\K", "`n"), 1, 400)
		}
	}
	If Tooltips
		ToolTip
	Output := RegExReplace(Output, "`r`n?|`r?`n", "`r`n`t")
	StringReplace, Output, Output, %SpecialChar%, `r`n, All
	FileAppend, %Output%, %OutputFile%
	Run, %EditorPath% "%OutputFile%", , UseErrorLevel
	If ErrorLevel
		Run, "%OutputFile%"
	Return Output, PWB_Clear()
}

; === ElementFromPoint() ===
;
; Gets element from x and y coordinates

ElementFromPoint(x="", y="")
{
	; Send ^0
	Global PWB, Element
	If (x = "") and (y = "") {
		CoordMode, Mouse
		MouseGetPos, x, y
	}
	WinGet, IE, List, ahk_class IEFrame
	Loop %IE% {
		ControlGet, HWND, HWND, , Internet Explorer_Server1, % "ahk_id " IE%A_Index%
		WinGetPos, x0, y0, x1, y1, ahk_id %HWND%
		If (x >= x0) and (x <= x0 + x1) and (y >= y0) and (y <= y0 + y1) {
			PWB := PWB_Get("ahk_id " IE%A_Index%)
			Return Element := PWB.Document.elementFromPoint(x - x0, y - y0)
		}
	}
}

;=================================================== Helper Functions ===================================================

PWB_Init(WinTitle="")
{
	Global PWB, Element
	PWB_Clear(False), ComObjError(False)
	If !PWB or (WinTitle <> "") {
		TitleMatchMode := A_TitleMatchMode, Element := ""
		SetTitleMatchMode, RegEx
		HWND := WinExist("ahk_class IEFrame")
		SetTitleMatchMode, %TitleMatchMode%
		If !HWND
			Return PWB_Error("No internet explorer windows exist.", A_ThisFunc)
		If (WinTitle <> "") {
			IfWinExist, %WinTitle% ahk_class IEFrame
				PWB := PWB_Get(WinTitle)
			Else
				PWB := PWB_MatchTitle(WinTitle)
		}
		Else IfWinActive, ahk_class IEFrame
			PWB := PWB_Get("A")
		Else
			PWB := PWB_Get("ahk_id " HWND)
	}
	Return PWB
}

; === PWB_MatchTitle(WINTITLE) ===
;
; Returns the web browser object of the window with the specified title. Uses fuzzy string matching to match given title with all browser objects.

PWB_MatchTitle(WinTitle)
{
	Explorers := ComObjCreate("Shell.Application").Windows, BestScore := 0
	While (3 > Iteration := A_Index)
		For This In Explorers
			If InStr(This.FullName "|", "\iexplore.exe|")
				If (Iteration = 1) and (WinTitle = This.LocationName)
					Return PWB := This
				Else If (Iteration = 2) and (BestScore < Score := %A_ThisFunc%_Compare(WinTitle, This.LocationName))
					BestScore := Score, PWB := This
	Return PWB
}

; === PWB_Get(WINTITLE, SVR#) ===
;
; Gets a pointer to web browser object (pwb) from an already existing internet explorer window

PWB_Get(WinTitle="A", Svr#=1) ; Jethrow - http://www.autohotkey.com/board/topic/47052-basic-webpage-controls-with-javascript-com-tutorial/
{
	Static msg := DllCall("RegisterWindowMessage", "str", "WM_HTML_GETOBJECT")
	, IID := "{0002DF05-0000-0000-C000-000000000046}" ; IID_IWebBrowserApp
	;,IID := "{332C4427-26CB-11D0-B483-00C04FD90119}" ; IID_IHTMLWindow2
	SendMessage, msg, 0, 0, Internet Explorer_Server%Svr#%, %WinTitle%
	If (ErrorLevel != "FAIL") {
		lResult := ErrorLevel, VarSetCapacity(GUID, 16, 0)
		If (DllCall("ole32\CLSIDFromString", "wstr", "{332C4425-26CB-11D0-B483-00C04FD90119}", "ptr", &GUID) >= 0) {
			DllCall("oleacc\ObjectFromLresult", "ptr", lResult, "ptr", &GUID, "ptr", 0, "ptr*", pdoc)
			Return ComObj(9, ComObjQuery(pdoc, IID, IID), 1), ObjRelease(pdoc)
		}
	}
	PWB_Error("Unable to obtain browser object (PWB) from window:`n`n" WinTitle, A_ThisFunc)
}

; === PWB_Set() ===
;
; Same as above but doesn't let the browser object reset

PWB_Set(WinTitle="A", Svr#=1)
{
	PWB_Clear("Off")
	Return PWB_Get(WinTitle, Svr#)
}

; === PWB_Clear() ===
;
; Controls the behavior of whether the variable %pwb% is reset to empty after a few seconds

PWB_Clear(Set=True)
{
	PWB_DefaultTimeout = 1500
	;------------------------------------------------------------------------------------------------------------------------
	Global Element, PWB, PWB_Timeout
	Static Enabled, Initialized
	If !Initialized {
		If (PWB_Timeout = "")
			PWB_Timeout := PWB_DefaultTimeout
		Initialized := True
	}
	If (Set = "Off")
		Enabled := False
	Else If (Set = "On") or (Enabled = "")
		Enabled := True
	If PWB_Timeout and Enabled
		If Set
			SetTimer, %A_ThisFunc%, %PWB_Timeout%
		Else
			SetTimer, %A_ThisFunc%, Off
	Return
	PWB_Clear:
	Element := PWB := ""
	Return
}

; === PWB_Error() ===
;
; Displays errors

PWB_Error(Message, Function="")
{
	ErrorDialogs := True
	;------------------------------------------------------------------------------------------------------------------------
	If ErrorDialogs
		MsgBox, 262160, % A_ScriptName ": Error" (Function = "" ? "" : " with " Function "()"), %Message%`n`nTo disable these messages, change `%ErrorDialogs`% in %A_ThisFunc%() to `%false`%.
}

; === PWB_MatchTitle_Compare() ===
;
; Helper function. See http://www.autohotkey.com/board/topic/70202-string-compare-function-nonstandard-method/

PWB_MatchTitle_Compare(StringA, StringB, CaseSense=False, Digits=8)
{
	Loop %Digits%
		Max .= 9, Zeros .= 0
	If (CaseSense and StringA == StringB) or (!CaseSense and StringA = StringB)
		Return Max
	Score := 0, SearchLength := 0, LengthA := StrLen(StringA), LengthB := StrLen(StringB)
	Loop % (LengthA < LengthB ? LengthA : LengthB) * 2 {
		If (A_Index & 1)
			SearchLength += 1, Needle := "A", Haystack := "B"
		Else
			Needle := "B", Haystack := "A"
		StartAtHaystack := 1, StartAtNeedle := 1
		While (StartAtNeedle + SearchLength <= Length%Needle% + 1)
			If (Pos := InStr(String%Haystack%, SubStr(String%Needle%, StartAtNeedle, SearchLength), CaseSense, StartAtHaystack)) {
				StartAtHaystack := Pos + SearchLength, StartAtNeedle += SearchLength, Score += SearchLength ** 2
				If (StartAtHaystack + SearchLength > Length%Haystack% + 1)
					Break
			} Else
				StartAtNeedle += 1
	}
	Return (Score := Round(Score * 10 ** (Digits // 2) / (LengthA > LengthB ? LengthA : LengthB))) >= Max ? Max - 1 : SubStr(Zeros Score, 1 - Digits)
}
More examples:

Code: Select all

; Log in to some website
eGet("input name=email").value := "[email protected]"
eGet("input name=password").value := "1234"
eGet("input type=submit").click()

;------------------------------------------------------------------------------------------------------

; Clicks search in the google window which is not currently active
pwb := PWB_Get("Google ahk_class IEFrame")
eGet("input value=""Google Search""").Click()

;------------------------------------------------------------------------------------------------------

; Shows the addresses of all the images on the current page
images := eGet("img all")
For n, element in images
	output .= element.src "`n"
MsgBox, % Output

;------------------------------------------------------------------------------------------------------

; search for Joe Schmoe's name and clicks on the button to the right of it
eGet("input type=submit", "", "div", "Joe Schmoe").click()

;------------------------------------------------------------------------------------------------------

; displays the text of the first element of any kind with at least 30 characters that comes after a h2 element containing the text "News"
MsgBox, % eGet("*", ".{30,}", "h2", ".*News.*").innerText

;------------------------------------------------------------------------------------------------------

; Sends focus to first text input box, which is usually the search bar at the top of the page. Try google, amazon, or AutoHotkey forums.
^b::
If eGet("input type=text|search readonly=0 disabled=0") { ; This returns true if such an element exists. Note that 0 is used instead of false (%False% would work too).
	ControlFocus, Internet Explorer_Server1, A ; Make sure keyboard focus is in the webpage control
	Element.Focus() ; Send keyboard focus to that element
	Sleep 100 ; Short sleep
	Send ^a ; Select all within that element
}
Return
Summary:

This script might seem pretty messy but it really can be useful for quick and dirty internet explorer macros, or for longer more complicated ones. Almost any element can be fetched with a single line of code, which is a huge improvement over the normal unwieldy COM navigation. I suggest you give it a quick try if you are trying to make a macro with a webpage using Internet Explorer.
Last edited by berban on 22 May 2019, 12:05, edited 5 times in total.
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: eGet() - Grab Internet Explorer Elements Easily

04 Jul 2016, 09:29

Thanks a lot! I tested Jethrow's PWB_Get() form your compilation and it works like a charm!
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: eGet() - Grab Internet Explorer Elements Easily

09 Jul 2016, 06:35

Your compilation seems to lack PWB_MatchTitle() and PWB_Error() functions. So commenting them out together with their conditioning steatements it all starts to make sense, even if some examples are site specific, despite the effort to be universal.
Could you provide those functions?
Special thanks for:
... this function ... allows you to grab elements that don't have an ID or Name attribute
User avatar
berban
Posts: 97
Joined: 14 Apr 2014, 03:20

Re: eGet() - Grab Internet Explorer Elements Easily

09 Jul 2016, 14:51

Sorry bout that! I had a bunch of other functions that I made before (including those two) as part of my "library" but decided to just include these main ones in the forum post. I removed their references from the code just to simplify things (I never use them anyway) but you can download the whole library here if you are interested: https://1drv.ms/u/s!AuB7nFoI4yR4hpZqvfE-MWOpAEZnVg.

Did you have some specific question about the examples or the usage?
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: eGet() - Grab Internet Explorer Elements Easily

10 Jul 2016, 17:28

Thanks for carrying, but I manage to test all examples successfully. I stated:
some examples are site specific
I guess they are, but probably specific to version of search engine too (google), so e.g. eGet("*", "Next.*|(.* )?\>+").Click() doesn't work for me (or, now I see, asterisk was just a typo?), while eGet("TagName=A", "Next.*|(.* )?\>+").Click() and even eGet("tagname=SPAN", "Next.*|(.* )?\>+").Click() work.
Thanks again!
User avatar
berban
Posts: 97
Joined: 14 Apr 2014, 03:20

Re: eGet() - Grab Internet Explorer Elements Easily

10 Jul 2016, 18:08

So the first part of the first parameter is the tag name as you seem to understand (note, you don't need "TagName=" even though it seems to work for you.) So putting a "*" instead of "a" which I have in the example will look at all tags. But for this example at least this isn't necessarily desirable. For instance, in Google.com this returns a <td> element:

Code: Select all

---------------------------
; With an "*" instead of an "a"
MsgBox, % eGet("*", "Next.*|(.* )?\>+").outerHTML

; Displays the following
<td class="b navend"><a class="pn" id="pnnext" style="text-align: left;" href="/search?q=test&biw=1920&bih=995&ei=z9OCV9rfCJGGevytsLAM&start=10&sa=N"><span class="csb ch" style='background: url("/images/nav_logo242.png") no-repeat -96px 0px; width: 71px;'></span><span style="margin-left: 53px; display: block;">Next</span></a></td>
In this case the td element doesn't have any sort of onclick behavior, so clicking on it does nothing. But as you can see from the html above, there is also a <span> and an <a> element in there. I use <a> for this particular scriptlet because it seems to work the best, and <a> will always have some action when it's clicked.

Also note that using "*" will noticeably reduce performance, because the script has to check hundreds more elements (all elements instead of just the <a> ones)

Also, only this example and the very last one are "real"' examples - the others are just hypotheticals to help understand how the code works.
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: eGet() - Grab Internet Explorer Elements Easily

12 Jul 2016, 02:09

I was pretty bad in IE COM till recently. But now, trough your publication (not necessary only trough your function) I managed to replace almost all my old automatizations (sending plain keystrokes) with those based on COM. - Faster and above all, more reliable! Thanks!

Questions I have many more, but I normally prefer to solve them alone (I'm not always successful). Nevertheless, this one could be of interest to other members.
The site address is e.g.: https://minimalsearch.com/search?q=belu ... le&lang=en
Task: Navigate to next page!

Code: Select all

#Include eGet.ahk ; whole compilation
WinActivate ahk_class IEFrame
ControlFocus, Internet Explorer_Server1, ahk_class IEFrame
wb := PWB_Init(WinTitle) ; replaces WinGetTitle and PWB_Get()

; how would you do next line with eGet()?
nextPage := wb.document.querySelector("DIV.gsc-cursor-page.gsc-cursor-current-page").innerText ;\/ min search - can't do it using eGet()
; nextPage := wb.document.querySelector("TD.cur").innerText  ;\/ google - can't do it using eGet()
; nextPage := eGet("<span>\d+", "\d+").innerText ;\/ ahk forum - is this right usage (anyway it works)
nextPage++ ; why for google won't work NextPage:=NextPage+1 ?
eGet("DIV", nextPage).Click() ;\/ min search
; eGet("A", nextPage).Click()  ;\/ ahk forum & google
analogues, as you see, I did this to excercise, for google and AutoHotkey forum, but both have Next or > Button-Label.

P.s.:[quote]you don't need "TagName=" even though it seems to work for you[/quote]Technically you're right, it's redundant! However very early I learned, AutoHotkey allows assigning the value to a variable, as you know, in two ways: TagName=A and TagName:="A". Now passing only a variable to the function would be "legal", wouldn't be! Later some day I noticed, AutoHotkey allows assigning to variable "just in time", so passing "TagName=A" or TagName:="A", works too. (The name of the variable is not important, could be whatever!, but I use appropriate name to make the script easier to read!) And that's not all at all! AutoHotkey allows, you know better then I do, nesting!, so on the same principle, passing "TagName:=""A""" works too, except redundancy is still more obvious and readability rather impaired. - This all is my personal view.
User avatar
berban
Posts: 97
Joined: 14 Apr 2014, 03:20

Re: eGet() - Grab Internet Explorer Elements Easily

17 Jul 2016, 13:51

Hey rommmcek, sorry I've been on vacation for a bit.


Question 1: How to navigate to the next page

This site is a bit unusual because there's no next button, which to be honest I'm not sure if I've ever seen. However, never fear, it can still be done in one line:

Code: Select all

eGet("div", "", "div className=""gsc-cursor-page gsc-cursor-current-page""").click()
Parameters 1 and 2 say "Return any DIV, with any inner text value..."
Parameters 2 and 4 say "...that follows a DIV with className (class) of 'gsc-cursor-page gsc-cursor-current-page'." Note the double quotes because the class has a space in it. You could also do className=.*gsc-cursor-current-page, or any analogous regular expression that would only match with the "current page" div.
(By the way I didn't know about document.querySelector() - I'm hopelessly ignorant about most things HTML. But that will be handy in the future, thanks!)
(Edit: document.querySelector() might make a lot of what this function does irrelevant haha. Oh well)


Question 2: About using "TagName="

To be honest I don't 100% follow your statement. I agree that using appropriate variable names and consistent = or := throughout your script makes it easier to read. However, the text you pass to eGet() is NOT AutoHotkey code, it's just a string that the script interprets based on the rules I made. Going back into the code, I realize that your way only works because the variable I used to denote which tag is queried just happens to be the same variable used by the DOM to denote tag name. If I used some other variable name it wouldn't work. So moral of the story is, doing it your way is a little bit less efficient (the script originally assumes TagName=* then overwrites with whatever value you put in) but if you prefer it that way then go for it.
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: eGet() - Grab Internet Explorer Elements Easily

18 Jul 2016, 04:24

Thanks, you're 100% right, I think I understand both subjects better now.
P.s.: I know about querySelector() since https://autohotkey.com/boards/viewtopic ... it=rewrite (if you missed the tool) and I learned to use it through your examples. Thanks again!
iamwyf
Posts: 7
Joined: 02 May 2016, 20:38

Re: eGet() - Grab Internet Explorer Elements Easily

26 Apr 2017, 20:41

Thank you! u made an excellent work!
saves me a lot of time!
magusneo
Posts: 45
Joined: 30 Sep 2013, 06:34

Re: eGet() - Grab Internet Explorer Elements Easily

03 Feb 2019, 07:35

How about adding "BeforeTag","BeforeText" arguments?
SOTE
Posts: 1426
Joined: 15 Jun 2015, 06:21

Re: eGet() - Grab Internet Explorer Elements Easily

05 Feb 2019, 03:55

Nice script. Don't know why I didn't see it before.
User avatar
berban
Posts: 97
Joined: 14 Apr 2014, 03:20

Re: eGet() - Grab Internet Explorer Elements Easily

05 Feb 2019, 17:32

magusneo wrote:
03 Feb 2019, 07:35
How about adding "BeforeTag","BeforeText" arguments?
Hey magusneo,
Sorry but I haven't used this function in ages so I haven't kept it updated. But if you can show me the webpage you are trying to use it on maybe I can help you find an alternate way to do whatever you're attempting.
magusneo
Posts: 45
Joined: 30 Sep 2013, 06:34

Re: eGet() - Grab Internet Explorer Elements Easily

06 Feb 2019, 05:49

berban wrote:
05 Feb 2019, 17:32
Hey magusneo,
Sorry but I haven't used this function in ages so I haven't kept it updated. But if you can show me the webpage you are trying to use it on maybe I can help you find an alternate way to do whatever you're attempting.
Thanks reply.
There are some treeview like controls in our intranet webpage.I need click the '+' or '-' in front of some text.
Last edited by magusneo on 12 Mar 2019, 00:47, edited 1 time in total.
User avatar
berban
Posts: 97
Joined: 14 Apr 2014, 03:20

Re: eGet() - Grab Internet Explorer Elements Easily

06 Feb 2019, 10:09

magusneo wrote:
06 Feb 2019, 05:49
There are some treeview like controls in our intranet webpage.I need click the '+' or '-' in front of some text. Like this.
Could you show me the HTML for that part of the page?

To do that, right-click on the area and select "Inspect Element". Then right-click on one of the parent elements and choose "Copy". This will copy the HTML, which you can then paste into a text document and upload here or to a pastebin. Don't just copy the element you want, copy a few levels up so I can see how the whole treeview area of the page looks.

Image

Feel free to send me a private message to continue the conversation if you don't want to do it publicly here.
magusneo
Posts: 45
Joined: 30 Sep 2013, 06:34

Re: eGet() - Grab Internet Explorer Elements Easily

09 Mar 2019, 00:50

For some Internet Explorer_TridentDlgFrame windows,I found the IID in PWB_GET() should be IID := "{332C4427-26CB-11D0-B483-00C04FD90119}" ; IID_IHTMLWindow2
default IID := "{0002DF05-0000-0000-C000-000000000046}" ; IID_IWebBrowserApp can't work.
User avatar
berban
Posts: 97
Joined: 14 Apr 2014, 03:20

Re: eGet() - Grab Internet Explorer Elements Easily

11 Mar 2019, 05:11

Thanks magusneo! I don't really know what to make of that but thanks for posting, someone else may be able to use it.
magusneo
Posts: 45
Joined: 30 Sep 2013, 06:34

Re: eGet() - Grab Internet Explorer Elements Easily

12 Mar 2019, 00:40

berban wrote:
11 Mar 2019, 05:11
Thanks magusneo! I don't really know what to make of that but thanks for posting, someone else may be able to use it.
Thank you for your brilliant script.It help me very much in working.I have given up Selenium because your script is easier to use for IE automation.
Now I just wonder is there any similar script for chrome automation :) .
User avatar
berban
Posts: 97
Joined: 14 Apr 2014, 03:20

Re: eGet() - Grab Internet Explorer Elements Easily

12 Mar 2019, 10:04

GeekDude has this fantastic library for working with chrome that you can find here:
https://www.autohotkey.com/boards/viewtopic.php?f=6&t=42890

Unfortunately because the integration isn’t native like with COM each command takes longer. So I think it wouldn’t be feasible to loop through hundreds of elements like I do in this script - it would take far too long. You have to be more direct, using Document.querySelector() for instance
magusneo
Posts: 45
Joined: 30 Sep 2013, 06:34

Re: eGet() - Grab Internet Explorer Elements Easily

16 Mar 2019, 19:50

It seems hard to use.
Element direct locating is difficult sometimes,relative locating(like afterTag,afterText in your script) is a clever and easy way.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: metallizer and 107 guests