Navigating into an Iframe

Started by hdsouza, December 02, 2014, 07:00:56 PM

Previous topic - Next topic

hdsouza

Hi, I could do an msie.navigate to the iframe src (which is actually the url) and enter in the login/password fields
Although I wanted to see if there is a way to accessing and filling up the login/password fields without doing the extra step of navigating to the iframe URL
Here is the page I am referring to: http://www.investors.com

I did an "INSPECT" using FIREFOX and I am able to find the input elements in the Iframe.


I am assuming it would be somewhere along there lines. I could get the elements of the iFrame .. but how do I navigate into the iFrame

Code (winbatch) Select

GoSub Find_iFrame
Exit

;*******************************************************************************************
:Find_iFrame
forEach iFrame in msie.document.GetElementsByTagName("iFrame")
   iFrame.style.border = ".25mm solid red"
   ErrorMode(@OFF)
   aa = strtrim(iFrame.name)
   bb = strtrim(iFrame.id)
   cc = strtrim(iFrame.src)
   ErrorMode(@CANCEL) ; do not REM
   iFrame.style.border = ".25mm solid black"
next
Return
;*******************************************************************************************


td

If you search the Tech Database on 'iframe' you will find two articles on same.  They may provide some assistance.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

hdsouza

Quote from: td on December 04, 2014, 06:46:48 AM
If you search the Tech Database on 'iframe' you will find two articles on same.  They may provide some assistance.

TD, I have already been through both topics. The first one  "Automate name change in Yahoo Mail Account" was actually my code, posted to tech support, I believe by Deana back in the days
The second topic "Dealing with iFrames" does not talk about how to navigate into an iframe in a way to get a handle to the inputs/elements inside the iframe.src

hdsouza

I modified the code about and wrote out a subloop called "Get_IFrameElement" once I get a handle to the Iframe.
Unfortunately the "Get_IFrameElement" does not find the input elements on the iframe. I also replaced Input with div, head and any other tag that was relevant to the page. What am I doing wrong in the syntax

Code (winbatch) Select

GoSub GetMSIE

GoSub Find_iFrame
Exit

;*******************************************************************************************
:Find_iFrame
forEach iFrame in msie.document.GetElementsByTagName("iFrame")
   ErrorMode(@OFF)
   ;iFrame.style.border = ".25mm solid red"
   Frame_Name = strtrim(iFrame.name)
   Exist_Name = strindexnc(Frame_Name, "easyXDM_default", 1, @FWDSCAN)
   If Exist_Name == 0 then continue
   Frame_src = strtrim(iFrame.src)
   Gosub Get_IFrameElement
   ErrorMode(@CANCEL)
   Break
next
Return
;*******************************************************************************************
:Get_IFrameElement
iFrameInputCollection = iFrame.getElementsByTagName("Input")
forEach Input in iFrameInputCollection
   Input.style.border = ".5mm solid red"
   aaa= input.id
   Message("Iframe", "Element found !!!!")
next
Return
;*******************************************************************************************
:GetMSIE
   Shell = ObjectOpen("Shell.Application")
   For x = 0 To Shell.Windows.count-1
      swc = Shell.Windows.count-1
      ;ex  = x
      ErrorMode(@OFF)
      swi = Shell.Windows.item(x)
      If !swi
         ErrorMode(@CANCEL)
         Continue
      EndIf
      swif =  Shell.Windows.item(x).fullname
      If !StrIndexNC(swif, "iexplore.exe", 1, @FWDSCAN)
         ErrorMode(@CANCEL)
         Continue
      EndIf

      msie=Shell.Windows.item(x)
      URL = msie.LocationURL
      URL_Valid = StrIndexNC(URL, "investors.com", 1, @FWDSCAN)
      If !URL_Valid
         ErrorMode(@CANCEL)
         Continue
      Else
         Break
      EndIf
      ErrorMode(@CANCEL)     
   Next
Return
;*******************************************************************************************

stanl

I'm not sure about a Gosub from within a For..Next and with Errmode(@OFF) you might not know if there is a problem.

RAK

I do not believe you can manipulate fields in an iframe unless you navigate to the source page.

hdsouza

Quote from: stanl on December 04, 2014, 12:18:06 PM
I'm not sure about a Gosub from within a For..Next and with Errmode(@OFF) you might not know if there is a problem.

Stan, I tried without the errormode and I do not get an error. I also ran the script line-by-line.
I am thinking there is something wrong with my syntax of the collection in the inner gosub. Any ideas on the correct syntax

stanl

Not really sure about getting elements from an iframe (which is an element). You might try testing the attributes by inserting code like below (I use oIE for my Object, and it is oldser code using strcat rather than  :  concatentation)

Code (WINBATCH) Select

cLinks=""
cHlinks = oIE.Document.Body.GetElementsByTagName("iframe")
   If cHlinks
      For z = 0 To cHlinks.length-1
         S = cHlinks.item(z)
         cLinks = StrCat(cLinks,'oIE.Document.Body.GetElementsByTagName("iframe").Item(',z,")",@CRLF)
         If S.GetAttribute("name")<>"" Then  cLinks= StrCat(cLinks,"name:",S.name,@CRLF)
         If S.GetAttribute("id")<>"" Then  cLinks= StrCat(cLinks,S.id,"|")
         If S.GetAttribute("innerHTML")<>"" Then  cLinks= StrCat(cLinks,"   HTML:",S.innerHTML,@CRLF)
         If S.GetAttribute("innerText")<>"" Then  cLinks= StrCat(cLinks,S.innerText,"|")
         If S.GetAttribute("href")<>"" Then  cLinks= StrCat(cLinks,S.href,@CRLF)
      Next
   Endif
;write cLinks to a text file, or display as a message



td

Quote from: hdsouza on December 04, 2014, 04:50:54 PM
Stan, I tried without the errormode and I do not get an error. I also ran the script line-by-line.
I am thinking there is something wrong with my syntax of the collection in the inner gosub. Any ideas on the correct syntax

May or may not be applicable but the following link suggest using 'contentWindow'

http://stackoverflow.com/questions/14451358/how-to-pick-element-inside-iframe-using-document-getelementbyid
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

hdsouza

Hi Stan, I took your code and applied it to the Iframe on the webpage. Unfortunately, it still does not expose the items in the Iframe. I tried various combinations of the code but no luck. If you run this code you will see what I mean. Thanks for the code though
Code (winbatch) Select

GoSub Open_Site
GoSub Find_iFrame
Exit
;*******************************************************************************************
:Find_iFrame

cLinks=""
cHlinks = msie.Document.Body.GetElementsByTagName("iframe")
   If cHlinks
      For z = 0 To cHlinks.length-1
         S = cHlinks.item(z)
         cLinks = StrCat(cLinks,'msie.Document.Body.GetElementsByTagName("iframe").Item(',z,")",@CRLF)
         s.style.border = ".5mm solid red"
         S_Name      = strtrim(S.GetAttribute("name"))
         Exist_Name = strindexnc(S_Name, "easyXDM_default", 1, @FWDSCAN)
         If Exist_Name == 0 then continue
         S_id        = strtrim(S.GetAttribute("id"))
         S_innerHTML = strtrim(S.GetAttribute("innerHTML"))
         S_innerText = strtrim(S.GetAttribute("innerText"))
         S_href      = strtrim(S.GetAttribute("href"))
         If S.GetAttribute("name")<>"" Then  cLinks= StrCat(cLinks,"name:",S.name,@CRLF)
         If S.GetAttribute("id")<>"" Then  cLinks= StrCat(cLinks,S.id,"|")
         If S.GetAttribute("innerHTML")<>"" Then  cLinks= StrCat(cLinks,"   HTML:",S.innerHTML,@CRLF)
         If S.GetAttribute("innerText")<>"" Then  cLinks= StrCat(cLinks,S.innerText,"|")
         If S.GetAttribute("href")<>"" Then  cLinks= StrCat(cLinks,S.href,@CRLF)
      Next
   Endif
Return
;*******************************************************************************************
:Open_Site
msie = ObjectOpen("InternetExplorer.Application")
msie.Visible = @True
msie.Navigate("http://www.investors.com/default.aspx?fromad=1")
GoSub WaitForMSIE
Timedelay(4)
Return
;*******************************************************************************************
:WaitForMSIE
aa = msie.busy
Loop1_Count = 0
while msie.busy
    aa = msie.busy
    Loop1_Count = Loop1_Count +1
    if Loop1_Count >=20 then break
    timedelay(1)
endwhile
Return
;*******************************************************************************************

hdsouza

Quote from: td on December 05, 2014, 07:17:51 AM
May or may not be applicable but the following link suggest using 'contentWindow'

http://stackoverflow.com/questions/14451358/how-to-pick-element-inside-iframe-using-document-getelementbyid
Hi Td, I tried using the code  and it gave it error on
Code (winbatch) Select

msie.document.getElementById("easyXDM_default8793_provider").contentWindow.document.getElementById('UserName') = "test"


Although I kept reading other posts on the site and someone mentioned that while dealing with iframes one has to switch to the iframe and once complete exit the iframe.
Code (winbatch) Select

msie.switchTo().frame(msie.GetElementsByid("easyXDM_default8793_provider"))

msie.switchTo().defaultContent()

if so, after I switch to the iframe how would I be able to get to the input items in the iframe

td

Quote from: hdsouza on December 06, 2014, 07:34:59 PM

Although I kept reading other posts on the site and someone mentioned that while dealing with iframes one has to switch to the iframe and once complete exit the iframe.
Code (winbatch) Select

msie.switchTo().frame(msie.GetElementsByid("easyXDM_default8793_provider"))

msie.switchTo().defaultContent()

if so, after I switch to the iframe how would I be able to get to the input items in the iframe

'SwitchTo()' is part of the WebDriver API which is a standardized  API for testing/automating Web pages.  MSFT has an implementation of the API that can be used with IE. More information about their version of the WebDriver API including a link for downloading their dll can be found here

http://msdn.microsoft.com/en-us/library/ie/dn725045(v=vs.85).aspx

I have never used MSFT's implementation so I do not even know if it works with WinBatch COM.   
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

After a bit more reading it would appear that MSFT's WebDriver dll is more or less useless for general use. 

The "contentDocument" and "contentWindow" methods are both implemented in MSFT's DOM.  According to W3School, "Note: Internet Explorer 8 (and higher) supports the contentDocument property only if a !DOCTYPE is specified. For earlier versions of IE, use the contentWindow property."

In your case it appears you will get an 'access deny' error with the 'contentWindow' method which may be the result of the following again from W3School, "Note: Because of security reasons, the contents of a document can be accessed from another document only if the two documents are located in the same domain."

So neither of my previous suggestions appears particularly useful in this case so the direct reference to document object of the iFrame may be your only shot other than navigating to the frame's domain.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

hdsouza

Quote from: JTaylor on December 06, 2014, 08:57:59 PM
I don't see you attempting at access any objects within the iframe.   Putting the red border around it works and you are pulling the name attribute successfully.   Maybe I don't really understand how GetAttribute works (Stan knows far more than I so I may just use it in its simplest form) but I wouldn't think that code would work based on the way I use it.   Are you trying to get to the actual document within the iframe and get something from within there?   If so, maybe this will help.  I realize it doesn't do what you originally asked but my point was to demonstrate accessing an element within the iframe.
Jim

Hi Jim, The line s_id = s.document.GetElementsbyTagName("body") appears to be referencing the page itself instead the iframe. So I am not able to expose the inputs or anything inside the iframe. I put up a simple iframe for testing purposes http://www.healthnutrisystems.com/test/iframe.html. For example here I would want to fill in a first and last name.

In the code I have added a blue and a red frame so we can see what is being referenced

Code (winbatch) Select

GoSub Open_Site
;GoSub GetMSIE
GoSub Find_iFrame
Exit
;*******************************************************************************************
:Find_iFrame

cLinks=""
cHlinks = msie.Document.Body.GetElementsByTagName("iframe")
   If cHlinks
      For z = 0 To cHlinks.length-1
         S = cHlinks.item(z)
         cLinks = StrCat(cLinks,'msie.Document.Body.GetElementsByTagName("iframe").Item(',z,")",@CRLF)
         s.style.border = ".25mm solid blue"
         s_id = s.document.GetElementsbyTagName("body")
         ForEach id in s_id
             id.style.border = ".25mm solid red"
             body_txt = STRTRIM(id.OuterHTML)
             message("HI",body_txt)
         Next
      Next
   Endif
Return
;*******************************************************************************************
:Open_Site
msie = ObjectOpen("InternetExplorer.Application")
msie.Visible = @True
msie.Navigate("http://www.healthnutrisystems.com/test/iframe.html")
GoSub WaitForMSIE
Timedelay(4)
Return
;*******************************************************************************************
:WaitForMSIE
aa = msie.busy
Loop1_Count = 0
while msie.busy
    aa = msie.busy
    Loop1_Count = Loop1_Count +1
    if Loop1_Count >=20 then break
    timedelay(1)
endwhile
Return
;*******************************************************************************************
:GetMSIE
   Shell = ObjectOpen("Shell.Application")
   For x = 0 To Shell.Windows.count-1
      swc = Shell.Windows.count-1
      ;ex  = x
      ErrorMode(@OFF)
      swi = Shell.Windows.item(x)
      If !swi
         ErrorMode(@CANCEL)
         Continue
      EndIf
      swif =  Shell.Windows.item(x).fullname
      If !StrIndexNC(swif, "iexplore.exe", 1, @FWDSCAN)
         ErrorMode(@CANCEL)
         Continue
      EndIf

      msie=Shell.Windows.item(x)
      URL = msie.LocationURL
      URL_Valid = StrIndexNC(URL, "iframe", 1, @FWDSCAN)
      If !URL_Valid
         ErrorMode(@CANCEL)
         Continue
      Else
         Break
      EndIf
      ErrorMode(@CANCEL)
   Next
Return
;*******************************************************************************************


td

RAK may have had the correct answer for at least cross domain iFrames a number of forum posts ago. 
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

hdsouza

Quote from: td on December 09, 2014, 06:45:19 AM
RAK may have had the correct answer for at least cross domain iFrames a number of forum posts ago.

1) in the script above, while accessing the contents of an iframe it goes back to the main page/msie and not the frame.
I can understand if the logic was actually trying to access the iframe elements and get an error (access denied).. which is not the case here

2) window.postMessage can be used to call a function between page and iframe (cross domain or not).
See https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage
Are these function calls available in winbatch

td

Quote from: hdsouza on December 09, 2014, 08:36:43 AM

1) in the script above, while accessing the contents of an iframe it goes back to the main page/msie and not the frame.
I can understand if the logic was actually trying to access the iframe elements and get an error (access denied).. which is not the case here

Your script does not manipulate any of the input elements of the iFrame which is the point I believe RAK was trying to make.  You script dumps some HTML from the iFrame element as it resides on the first domain but does not actually pull information that resided on the second domain. 

Quote
2) window.postMessage can be used to call a function between page and iframe (cross domain or not).
See https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage
Are these function calls available in winbatch

Yes of course it is available as part of MSFT's DOM to COM implementation but it would require having scripts running on both domains.  One as a sender and one as the responder.   Unless the responding domain has an event handler already you are still left with navigating to the second domain to hook one up.   
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

hdsouza

Quote from: td on December 09, 2014, 02:04:36 PM
Your script does not manipulate any of the input elements of the iFrame which is the point I believe RAK was trying to make.  You script dumps some HTML from the iFrame element as it resides on the first domain but does not actually pull information that resided on the second domain.   

Td, I understand what you are saying about cross domain, bu then if the Iframe lies on the same domain it code should work correct.
That means the code should work for the  website I mentioned at the start of this post, because the webpage and frame exist on the same site. There is no cross domain

Thats what I have been trying to get ask every time in every post: what is correct syntax to get to the elements of an iframe

td

The iFrame is HTTPS but the page is HTTP. I believe a protocol difference is  considered cross-domain on newer versions of IE. That is why the "contentWindow" method which is the standard way to get an iframe's content gives an "Access denied" error. If you think about it,  allowing access to an HTTPS iFrame is a perfect setup for a man-in-the-middle exploit.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

hdsouza

Quote from: td on December 10, 2014, 08:54:58 AM
The iFrame is HTTPS but the page is HTTP. I believe a protocol difference is  considered cross-domain on newer versions of IE. That is why the "contentWindow" method which is the standard way to get an iframe's content gives an "Access denied" error. If you think about it,  allowing access to an HTTPS iFrame is a perfect setup for a man-in-the-middle exploit.

Yes. Thanks Td, All. We gave it our best shot