Jump to content

Clicking on a selected button causing its container element to be click


Recommended Posts

Go create a quick account in Zapier and go to https://zapier.com/app/dashboard and make some Zaps!
Just need to click the specific instance of an .open-menu button and then click its a.run (anchor) element.
Doing this IE.au3 script just causing to click its container element:

$target = 1; Target the first instance


#include <IE.au3>
$oIE = _IEAttach("Dashboard - Zapier")

$count = 0;
$tags = _IETagNameGetCollection($oIE, "div")
For $tag in $tags
    $class_value = $tag.GetAttribute("class")
    If $class_value = "open-menu" Then
        $count += 1
        
        if $count = $target Then
            MsgBox(0, "Instance: ", $count)
;           $tag.fireEvent("onmousedown")
;           _IEAction($tag, "click")
;           $tag.fireEvent("onmouseup")

;           Or this but not working
;           $tag.Click
        EndIf
    EndIf
Next

I also tried to do it using FF.au3

$target = 1; Target the first instance


#Include <Array.au3>
#Include <FF.au3>

$count = 0;
If _FFConnect(Default, Default, 3000) Then
    $aArray = _FFXPath( "//div[@class='open-menu']", "", 7 )
;   _ArrayDisplay($aArray)

    For $tag in $aArray
        $count += 1

        if $count = $target Then
            MsgBox(0, "Instance: ", $count)
            _FFClick($tag)
        EndIf
    Next
EndIf

Error: _FFClick ==> No match: $sElement: [number]

Could some help me how to click such buttons on such kind of a dynamic page?

Edited by 5ervant
Link to post
Share on other sites

You have to examine the underlying event code to be able to figure out how to trigger the menu. In this case, there's a single event on the main container that is used for each of the objects within that container. The event looks at the position of the click to determine which element to actually trigger.

Here's some code that will cause the menu to appear --

#Include <FF.au3>

If _FFConnect(Default, Default, 3000) Then
    _FFXPath( "//div[@class='open-menu']")

    If @error = $_FF_ERROR_Success Then
        $pos = _FFCmd('FFau3.xpath.getBoundingClientRect().x') + 1
        $cmd = "d=FFau3.WCD.createEvent('MouseEvent');d.initMouseEvent('click',true,true,window,0,0,0," & $pos & ",0,0,0,0,0,0,null);FFau3.xpath.parentNode.parentNode.parentNode.dispatchEvent(d);"
        _FFCmd($cmd)
    EndIf
EndIf

It creates a click event with the proper positioning value and then passes it to the container element to be processed.

Link to post
Share on other sites
7 hours ago, Danp2 said:

You have to examine the underlying event code to be able to figure out how to trigger the menu. In this case, there's a single event on the main container that is used for each of the objects within that container. The event looks at the position of the click to determine which element to actually trigger.

Here's some code that will cause the menu to appear --

#Include <FF.au3>

If _FFConnect(Default, Default, 3000) Then
    _FFXPath( "//div[@class='open-menu']")

    If @error = $_FF_ERROR_Success Then
        $pos = _FFCmd('FFau3.xpath.getBoundingClientRect().x') + 1
        $cmd = "d=FFau3.WCD.createEvent('MouseEvent');d.initMouseEvent('click',true,true,window,0,0,0," & $pos & ",0,0,0,0,0,0,null);FFau3.xpath.parentNode.parentNode.parentNode.dispatchEvent(d);"
        _FFCmd($cmd)
    EndIf
EndIf

It creates a click event with the proper positioning value and then passes it to the container element to be processed.

Thanks, it would be great if you can show a IE.au3 version of that 'cause that FF.au3 version is hard to understand, just for educational purpose..

Link to post
Share on other sites
2 hours ago, 5ervant said:

Thanks, it would be great if you can show a IE.au3 version of that 'cause that FF.au3 version is hard to understand, just for educational purpose..

Sorry, but your on your own there. :-)

Suggest that you search to forum for a solution. IIRC, there's a post by DaleHolm that addresses a similar issue.

Link to post
Share on other sites

Could try:

#RequireAdmin
#include <IE.au3>

$oIE = _IECreate("https://zapier.com/app/dashboard", 1)
$oDivs = _IETagNameGetCollection($oIE, "div")
For $oDiv in $oDivs
    If $oDiv.ClassName = "open-menu" Then
        $hWnd = _IEPropertyGet($oIE, "hWnd")
        ControlClick($hWnd, "", "", "left", 1, _IEPropertyGet($oDiv, "browserx") + 2, _IEPropertyGet($oDiv, "browsery") + 2)
        ExitLoop
    EndIf
Next

 

Link to post
Share on other sites
On 5/5/2017 at 8:34 AM, Danp2 said:

You have to examine the underlying event code to be able to figure out how to trigger the menu. In this case, there's a single event on the main container that is used for each of the objects within that container. The event looks at the position of the click to determine which element to actually trigger.

Here's some code that will cause the menu to appear --

#Include <FF.au3>

If _FFConnect(Default, Default, 3000) Then
    _FFXPath( "//div[@class='open-menu']")

    If @error = $_FF_ERROR_Success Then
        $pos = _FFCmd('FFau3.xpath.getBoundingClientRect().x') + 1
        $cmd = "d=FFau3.WCD.createEvent('MouseEvent');d.initMouseEvent('click',true,true,window,0,0,0," & $pos & ",0,0,0,0,0,0,null);FFau3.xpath.parentNode.parentNode.parentNode.dispatchEvent(d);"
        _FFCmd($cmd)
    EndIf
EndIf

It creates a click event with the proper positioning value and then passes it to the container element to be processed.

Can you give me another twick of that, that will click let say, the second button?

'Cause @Subz solution isn't that nice, will require you to activate the window before working..
And upon a quick testing, no @DaleHohm solution work and still, a ControlClick() .

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By noellarkin
      This is for those pages that seem to load when you use _FFOpenURL(), but they have a text saying "please wait while we load your page..." but according to _FFOpenURL() the page has loaded.  An example seen in popular sites is the Cloudflare page saying "Checking your browser before...". It's the opposite of pausing a script until an element is visible on a page. It takes Elements in the form of id, xpath or text search.
      Global $BrowserPort = 4242 Global $TimeOut = 60000 Global $LocalHost = "127.0.0.1" Func _FFWaitWhileElement($thiselement, $elementtype = "xpath", $timeoutms = 60000) _FFConnect($LocalHost, $BrowserPort, $TimeOut) Local $Element Local $ElementFound = 1 Local $TimeoutCountdown = 0 While $ElementFound <> 0 And $TimeoutCountdown < $timeoutms If $elementtype = "xpath" Then $Element = _FFXPath($thiselement) EndIf If $elementtype = "id" Then Local $ConstructXPath = ".//*[@id='" & $thiselement & "']" $Element = _FFXPath($ConstructXPath) EndIf ; MsgBox(0, "", $Element) Local $ElementXPathTextContent = _FFCmd("FFau3.xpath.textContent") ; MsgBox(0, "", $ElementXPathTextContent) Local $ElementXPathInnerHTML = _FFCmd("FFau3.xpath.innerHTML") ; MsgBox(0, "", $ElementXPathInnerHTML) If $ElementXPathTextContent = "_FFCmd_Err" Or $ElementXPathInnerHTML = "_FFCmd_Err" Then $ElementFound = 0 Else $ElementFound = 1 EndIf If $elementtype = "text" Then $ElementFound = _FFSearch($thiselement) ; MsgBox(0, "", $ElementFound) EndIf $TimeoutCountdown += 1000 _FFDisConnect() _FFConnect($LocalHost, $BrowserPort, $TimeOut) WEnd Return $ElementFound EndFunc _FFConnect($LocalHost, $BrowserPort, $TimeOut) _FFOpenURL("https://www.site.com/page", True) _FFWaitForElement("Please Wait...","text", 60000) MsgBox(0,"","Page finished loading") It's pretty simple, hope it helps some of you who are working with FF.au3 :)
    • By noellarkin
      So I was trying to write a function that can find a button (or any other XPath Element) and scroll the page + move the mouse to the location of the button.
      My logic for this was:
      1. get position of button using _FFGetPosition
      2. get inner dimensions of browser window and total dimensions of page
      3. divide total dimensions by inner dimensions to get number of page down operations
      4. use Mod() to get remaining pixels offset
      5. MouseMove() and add requisite offsets for Titlebar etc (what the +5 and +54 is for in the last line)
      Example Code:
      _FFConnect($LocalHost, $BrowserPort, $TimeOut) Local $Button = _FFXPath(".//*[@id='thisbutton']") Local $ButtonPosition = _FFGetPosition($Button) Local $ElementWidth = $ButtonPosition[0] Local $ElementHeight = $ButtonPosition[1] Local $InnerWidth = _FFCmd("window.content.innerWidth") Local $InnerHeight = _FFCmd("window.content.innerHeight") Local $PageWidth = _FFCmd(".body.offsetWidth") Local $PageHeight = _FFCmd(".body.offsetHeight") Local $PGDNNo = Int($ElementHeight/$InnerHeight) Local $PGDNMod = Mod($ElementHeight, $InnerHeight) ; MsgBox(0,"","$ElementX: " & $ElementWidth & @CRLF & "$ElementY: " & $ElementHeight) ; MsgBox(0,"","$InnerWidth: " & $InnerWidth & @CRLF & "$InnerHeight: " & $InnerHeight) ; MsgBox(0,"","$PageWidth: " & $PageWidth & @CRLF & "$PageHeight: " & $PageHeight) ; MsgBox(0,"",$PGDNNo) ; MsgBox(0,"",$PGDNMod) Local $iter = 1 While $iter <= $PGDNNo WinActivate($BrowserWindowClass,"") _FFCmd("window.content.scrollByPages(1)") $iter += 1 WEnd MouseMove($ElementWidth + 5, $PGDNMod + 54) This isn't working. In some cases, it's not doing the page down operation the number of times needed, or not accurately pinpointing the location. I think there may be something wrong with the logic I'm using. What am I doing wrong?
      Thanks.
       
    • By mLipok
      Anybody could help with using QueryInterface in AutoIt to embed Microsoft Edge using WebView2 Interface ?
      Here are links to information/documentation:

      Image comes from: https://docs.microsoft.com/en-us/microsoft-edge/webview2/media/webview2/whatwebview.png
      Introduction to Microsoft Edge WebView2
      https://docs.microsoft.com/en-us/microsoft-edge/webview2/

      Understand WebView2 SDK versions
      https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/versioning
      Download:
      https://developer.microsoft.com/en-US/microsoft-edge/webview2/
      https://developer.microsoft.com/en-US/microsoft-edge/webview2/#download-section
      https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution
      API Reference:
      https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/?view=webview2-1.0.622.22

      HowTo/Concepts:
      https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/versioning
      https://docs.microsoft.com/en-us/microsoft-edge/webview2/gettingstarted/win32
      https://docs.microsoft.com/en-us/microsoft-edge/webview2/howto/debug?tabs=devtools
      https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/security
      https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/userdatafolder
      https://mybuild.microsoft.com/sessions/9198aeac-0c8e-4d32-96d1-cbb99a390aa6
      Example:
      https://github.com/MicrosoftEdge/WebView2Samples
      Related:
      https://www.essentialobjects.com/Products/WebBrowser/Default.aspx?gclid=CjwKCAiA17P9BRB2EiwAMvwNyMe6UI9VHej-JYDBUoyGDFz40KaaJ_RidY-75Fhr-PHz65sSVC0XlxoC5loQAvD_BwE
      https://docs.microsoft.com/en-us/microsoft-edge/webview2/howto/webdriver
       
      btw.
      I'm not WindowsApi expert (QueryInterface, C++, DllCall).
      What I trying to say is:     It means that I do not done anything in this regards .... as so far.
       
       
      TIMELINE/ChangeLog:
       
      2020-11-12 - Project propsed by @mLipok 2021-02-03 - First version provided by @LarsJ
    • By Pured
      I am looking to create a script which refreshes/reads a webpage every few seconds. My goal is to see if the page has changed, then I will send myself a notification that the webpage has been updated.
       
      However, rather than downloading the entire webpage every single time, is there a way to check when the webpage last updated?
       
      If not, is there away to partially download/read html source until a specific tag is hit?
       
      Goal: I would like to increase my poll rate and not excessively waste data.
    • By mLipok
      In the past there was many questions about how to: "Automatic file upload using without user interaction"

      https://www.autoitscript.com/forum/topic/92907-ie-8-input-namenomfic-typefile-idnomfic/
      https://www.autoitscript.com/forum/topic/116899-cant-automate-input-typefile-tag-in-ie/?tab=comments#comment-815478
      https://www.autoitscript.com/forum/topic/14883-input-typefile/
      https://www.autoitscript.com/forum/topic/188708-how-to-set-the-value-of-an-input-typefile-element/
      https://www.autoitscript.com/forum/topic/91513-how-can-i-auto-set-file-path-for-input-file-in-ie/
      https://www.autoitscript.com/forum/topic/116899-cant-automate-input-typefile-tag-in-ie/
      https://www.autoitscript.com/forum/topic/169190-how-to-script-file-upload-button/
      https://www.autoitscript.com/forum/topic/145327-how-to-deal-with-ie-window-for-upload-a-fileinput-typefile/
      https://www.autoitscript.com/forum/topic/140482-internet-explorer-input-file-problem/
       
      I found solution here: 
      https://stackoverflow.com/questions/33253517/upload-a-file-via-input-input-in-html-form-with-vba
      and:
      https://www.motobit.com/tips/detpg_uploadvbsie/
      And I translate this code to AutoIt3 code:
      ; Upload file using http protocol And multipart/form-data ; v1.01 ; 2001 Antonin Foller, PSTRUH Software Global $oErrorHandler = ObjEvent("AutoIt.Error", _ErrFunc) do_vbsUpload() Func do_vbsUpload() #cs ; We need at least two arguments (File & URL) ConsoleWrite('- ' & @ScriptLineNumber & @CRLF) If $CmdLine[0] < 2 Then InfoEcho() ConsoleWrite('- ' & @ScriptLineNumber & @CRLF) ; Are some required objects missing? If StringInStr(CheckRequirements(), "Error") > 0 Then InfoEcho() ConsoleWrite('- ' & @ScriptLineNumber & @CRLF) Local $s_FileName, $s_DestURL, $s_FieldName $s_FieldName = "FileField" ; Default field name For $i_argCounter = 1 To $CmdLine[0] ConsoleWrite('+ '& $i_argCounter& ' >> ' & $CmdLine[$i_argCounter] & @CRLF) Select Case $i_argCounter = 1 ;~ $s_FileName = $CmdLine[$i_argCounter] $s_FileName = @ScriptFullPath Case $i_argCounter = 2 $s_DestURL = $CmdLine[$i_argCounter] Case $i_argCounter = 3 $s_FieldName = $CmdLine[$i_argCounter] EndSelect Next UploadFile($s_DestURL, $s_FileName, $s_FieldName) #ce UploadFile('http://www.dobeash.com/test.html', @ScriptFullPath, 'fileExample') EndFunc ;==>do_vbsUpload ; ******************* upload - begin ; Upload file using input type=file Func UploadFile($s_DestURL, $s_FileName, $s_FieldName) ; Boundary of fields. ; Be sure this string is Not In the source file Const $Boundary = "---------------------------0123456789012" ; Get source file As a binary data. Local $d_FileContents = GetFile($s_FileName) ; Build multipart/form-data document Local $s_FormData = BuildFormData($d_FileContents, $Boundary, $s_FileName, $s_FieldName) ; Post the data To the destination URL IEPostBinaryRequest($s_DestURL, $s_FormData, $Boundary) EndFunc ;==>UploadFile ; Build multipart/form-data document with file contents And header info Func BuildFormData($d_FileContents, $Boundary, $s_FileName, $s_FieldName) Const $s_ContentType = "application/upload" ; The two parts around file contents In the multipart-form data. Local $s_Pre = "--" & $Boundary & @CRLF & mpFields($s_FieldName, $s_FileName, $s_ContentType) Local $s_Po = @CRLF & "--" & $Boundary & "--" & @CRLF ; Build form data using recordset binary field Const $i_adLongVarBinary = 205 Local $oRS = ObjCreate("ADODB.Recordset") ; https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/append-method-ado?view=sql-server-ver15 $oRS.Fields.Append("b", $i_adLongVarBinary, StringLen($s_Pre) + BinaryLen($d_FileContents) + StringLen($s_Po)) $oRS.Open() $oRS.AddNew() ; Convert Pre string value To a binary data Local $i_LenData = StringLen($s_Pre) $oRS("b").AppendChunk(StringToMB($s_Pre) & StringToBinary(Chr(0))) $s_Pre = $oRS("b").GetChunk($i_LenData) $oRS("b") = "" ; Convert Po string value To a binary data $i_LenData = StringLen($s_Po) $oRS("b").AppendChunk(StringToMB($s_Po) & StringToBinary(Chr(0))) $s_Po = $oRS("b").GetChunk($i_LenData) $oRS("b") = "" ; Join Pre & $d_FileContents & Po binary data $oRS("b").AppendChunk($s_Pre) $oRS("b").AppendChunk($d_FileContents) $oRS("b").AppendChunk($s_Po) $oRS.Update() Local $s_FormData = $oRS("b") $oRS.Close() Return $s_FormData EndFunc ;==>BuildFormData ; sends multipart/form-data To the URL using IE Func IEPostBinaryRequest($s_URL, $s_FormData, $Boundary) ; Create InternetExplorer Local $oIE = ObjCreate("InternetExplorer.Application") ; You can uncoment Next line To see form results $oIE.Visible = True ; Send the form data To $s_URL As POST multipart/form-data request $oIE.Navigate($s_URL, '', '', $s_FormData, _ "Content-Type: multipart/form-data; boundary=" & $Boundary & @CRLF) While $oIE.Busy Wait(1, "Upload To " & $s_URL) WEnd ; Get a result of the script which has received upload ;~ On Error Resume Next Local $s_IE_InnerHTML = $oIE.Document.body.innerHTML MsgBox(0, 'TEST #' & @CRLF & @ScriptLineNumber, $s_IE_InnerHTML) $oIE.Quit() Return $s_IE_InnerHTML EndFunc ;==>IEPostBinaryRequest ; Infrormations In form field header. Func mpFields($s_FieldName, $s_FileName, $s_ContentType) Local $s_MPTemplate = _ ; template For multipart header 'Content-Disposition: form-data; name="{field}";' & _ 'FileName="{file}"' & @CRLF & _ 'Content-Type: {ct}' & @CRLF & @CRLF & _ '' Local $s_Out $s_Out = StringReplace($s_MPTemplate, "{field}", $s_FieldName) $s_Out = StringReplace($s_Out, "{file}", $s_FileName) $s_Out = StringReplace($s_Out, "{ct}", $s_ContentType) Return $s_Out EndFunc ;==>mpFields Func Wait($i_Seconds, $s_Message) MsgBox(64, '', $s_Message, $i_Seconds) EndFunc ;==>Wait ; Returns file contents As a binary data Func GetFile($s_FileName) Local $oStream = ObjCreate("ADODB.Stream") $oStream.Type = 1 ; Binary $oStream.Open() $oStream.LoadFromFile($s_FileName) Local $d_GetFile = $oStream.Read() $oStream.Close() Return $d_GetFile EndFunc ;==>GetFile ; Converts OLE string To multibyte string Func StringToMB($S) Local $I, $B For $I = 1 To StringLen($S) $B &= StringToBinary(Asc(StringMid($S, $I, 1))) Next Return $B EndFunc ;==>StringToMB ; ******************* upload - end ; ******************* Support ; Basic script info Func InfoEcho() Local $sMsg = _ "Upload file using http And multipart/form-data" & @CRLF & _ "Copyright (C) 2001 Antonin Foller, PSTRUH Software" & @CRLF & _ "use" & @CRLF & _ "[cscript|wscript] fupload.vbs file $s_URL [fieldname]" & @CRLF & _ " file ... Local file To upload" & @CRLF & _ " $s_URL ... $s_URL which can accept uploaded data" & @CRLF & _ " fieldname ... Name of the source form field." & @CRLF & _ @CRLF & CheckRequirements() & @CRLF & _ "" ConsoleWrite('! ' & $sMsg & @CRLF) EndFunc ;==>InfoEcho ; Checks If all of required objects are installed Func CheckRequirements() Local $sMsg = _ "This script requires some objects installed To run properly." & @CRLF & _ CheckOneObject("ADODB.Recordset") & @CRLF & _ CheckOneObject("ADODB.Stream") & @CRLF & _ CheckOneObject("InternetExplorer.Application") & @CRLF & _ "" Return $sMsg ; $sMsgBox $sMsg EndFunc ;==>CheckRequirements ; Checks If the one object is installed. Func CheckOneObject($sClassName) Local $sMsg ObjCreate($sClassName) If @error = 0 Then $sMsg = "OK" Else $sMsg = "Error:" & @error EndIf Return $sClassName & " - " & $sMsg EndFunc ;==>CheckOneObject ; ******************* Support - end ; User's COM error function. Will be called if COM error occurs Func _ErrFunc(ByRef $oError) ; Do anything here. ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _ @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _ @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _ @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _ @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _ @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _ @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _ @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _ @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _ @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF) EndFunc ;==>_ErrFunc  
      But I miss something and the code not works as intendend.
      Please join and contribute, in solving this issue, as this will be handy for entire community.
      @mLipok
       
      btw.
      I think that this may be realated to ChrB() which I simply translate to StringToBinary()
      Especialy this :
      StringToBinary(Chr(0))) could be the main issue.
      But for now I'm tired and going to sleep.
      Hope maybe tomorrow somebody solve this issue.
       
×
×
  • Create New...