Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Loop and open link in another 'window/control'
#1
Hi,

I began yesterday with my new license.

I can now browse internet, click the right buttons o links and fill the boxes i need to get into my target web page.
This web shows a list of links (let´s call them 'A' type) for getting into the individual document and - of course - another huge variety of objects types.

How should i 
     * loop between objects in browser, get properties of the element, determine if it is the 'A' class of link
     * If yes, then open the href in another 'window' or antview control
     * get the context in text or look for a new link to an xml file 

Maybe is too much content for a simple question.
Thanks In Advance.
Regards.

   

CYZ
Reply
#2
Hi,

You are correct that I am missing details in order to give you a complete answer. The screenshot does not tell me much I'm afraid, a lot depends on the actual html behind it.
Either way though, for this you're going to have to use javascript.

Please make sure you are using either AntView version 1.1.460 or AntView version 2.0.459 (or later) as they have much improved VFP examples over earlier versions.
Then in the standard example put the following code in the "Html to _cliptext" button of the AntView form.

Code:
* enumerate all links for the current page

lcCurrentHtml = ''
lnReturn = 0
lcNewLine = CHR(13)+CHR(10)
lcScript = '() => { ' + lcNewLine
lcScript = lcScript + '  let result="";' + lcNewLine
lcScript = lcScript + '  let ele = document.getElementsByTagName("a");' + lcNewLine
lcScript = lcScript + '  for (let i = 0; i < ele.length; i++) {' + lcNewLine
lcScript = lcScript + '     result=result+ele[i].href+";";' + lcNewLine
lcScript = lcScript + '     }' + lcNewLine
lcScript = lcScript + '  return result;' + lcNewLine
lcScript = lcScript + ' }' + lcNewLine
lcData = ''

lnreturn = thisform.oAntviewDocument.RunAnonymousFunctionsync(1,0,lcScript,@lcData)
MESSAGEBOX('lnreturn is '+STR(lnreturn)+' data returned is '+lcData)

This is a very basic javascript example that gets the urls from each hyperlink on the currently rendered page.
Those you can then use in a new form and navigate to them in a new AntView control.

However.. if these pages are on a protected website then there's a chance that it is protected in a way that you need to artificially "click" on the links of interest.
If that's the case then change the line:
Code:
lcScript = lcScript + '    result=result+ele[i].href+";";' + lcNewLine
into
lcScript = lcScript + '    result=result+ele[i].id+";";' + lcNewLine
or
lcScript = lcScript + '    result=result+ele[i].name+";";' + lcNewLine
depending on the actual html.
If the hyperlinks have an "id" attribute you'd use the first one, if they have a "name" attribute then you can get the last one.
Then you can use ElementClickById, respectively ElementClickByName to click on the link.
If the link is set to open a new browser you can handle the new window popup from within VFP.

As this is a bit much to explain, please have a look at the "Advanced" examples folder.
Make sure to read the "Help" page from the help button in the demo's as it has a lot of explanations on how-to do things with the AntView control in VFP.

Hope this helps and if not please send me the html of that screenshot by email.
--
Wil
Reply
#3
Thanks, Wil.
I'll take a look and come back with results.

Regards

Hi, again.
Maybe i've explained really bad or there are some problems to do that.
I've attached the html code. I think i need a reference to each link in html as an object, to review his properties and determine if is one of the links i must review.

With my old version, still working with IE and createobject("internetexplorer.application") what i do is loop between the objects in page:
Code:
m.myObject = Document.All.Item(xx)
If Type("m.myObject.href") != "U"
     if atc("enlaceExpediente", m.myObject.id) > 0
          * now i know this is a link i must use.

     endif
endif

then, i open myobject.href url in another IE object and read content.
You can test in this web:
https://contrataciondelestado.es/wps/portal/plataforma
Then click on 'publicaciones', then in 'licitaciones', then by example, just fill 'Fecha publicación entre' (publication dates between...) and press 'Buscar' (find).

You will see a list similar to mine.


.txt   WebPageWithListofLinks.txt (Size: 141.14 KB / Downloads: 2)
Reply
#4
(2024-11-25, 12:34:21)wila Wrote:
Hi,

You are correct that I am missing details in order to give you a complete answer. The screenshot does not tell me much I'm afraid, a lot depends on the actual html behind it.
Either way though, for this you're going to have to use javascript.

Please make sure you are using either AntView version 1.1.460 or AntView version 2.0.459 (or later) as they have much improved VFP examples over earlier versions.
Then in the standard example put the following code in the "Html to _cliptext" button of the AntView form.

Code:
* enumerate all links for the current page

lcCurrentHtml = ''
lnReturn = 0
lcNewLine = CHR(13)+CHR(10)
lcScript = '() => { ' + lcNewLine
lcScript = lcScript + '  let result="";' + lcNewLine
lcScript = lcScript + '  let ele = document.getElementsByTagName("a");' + lcNewLine
lcScript = lcScript + '  for (let i = 0; i < ele.length; i++) {' + lcNewLine
lcScript = lcScript + '     result=result+ele[i].href+";";' + lcNewLine
lcScript = lcScript + '     }' + lcNewLine
lcScript = lcScript + '  return result;' + lcNewLine
lcScript = lcScript + ' }' + lcNewLine
lcData = ''

lnreturn = thisform.oAntviewDocument.RunAnonymousFunctionsync(1,0,lcScript,@lcData)
MESSAGEBOX('lnreturn is '+STR(lnreturn)+' data returned is '+lcData)

This is a very basic javascript example that gets the urls from each hyperlink on the currently rendered page.
Those you can then use in a new form and navigate to them in a new AntView control.

However.. if these pages are on a protected website then there's a chance that it is protected in a way that you need to artificially "click" on the links of interest.
If that's the case then change the line:
Code:
lcScript = lcScript + '    result=result+ele[i].href+";";' + lcNewLine
into
lcScript = lcScript + '    result=result+ele[i].id+";";' + lcNewLine
or
lcScript = lcScript + '    result=result+ele[i].name+";";' + lcNewLine
depending on the actual html.
If the hyperlinks have an "id" attribute you'd use the first one, if they have a "name" attribute then you can get the last one.
Then you can use ElementClickById, respectively ElementClickByName to click on the link.
If the link is set to open a new browser you can handle the new window popup from within VFP.

As this is a bit much to explain, please have a look at the "Advanced" examples folder.
Make sure to read the "Help" page from the help button in the demo's as it has a lot of explanations on how-to do things with the AntView control in VFP.

Hope this helps and if not please send me the html of that screenshot by email.
--
Wil

Hi, Wil

did you see my last post with the attachment and more explanations?
Thanks in advance.
Reply
#5
Hi Carlos,

The attached html file does not include the string "enlaceExpediente" Smile
Either way, it's just a matter of adjusting the javascript that you're running.

For your specific question, this would change to something along the lines of:
Code:
lcCurrentHtml = ''
lnReturn = 0
lcNewLine = CHR(13)+CHR(10)
lcScript = '() => { ' + lcNewLine
lcScript = lcScript + '  let result="";' + lcNewLine
lcScript = lcScript + '  let id="";' + lcNewLine
lcScript = lcScript + '  let url="";' + lcNewLine
lcScript = lcScript + '  let ele = document.getElementsByTagName("a");' + lcNewLine
lcScript = lcScript + '  for (let i = 0; i < ele.length; i++) {' + lcNewLine
lcScript = lcScript + '     url=ele[i].href;' + lcNewLine
lcScript = lcScript + '     id=ele[i].id;' + lcNewLine
lcScript = lcScript + '     if (id.toLowerCase().includes("enlaceExpediente".toLowerCase())) {' + lcNewLine
lcScript = lcScript + '       result=result+url+";";' + lcNewLine
lcScript = lcScript + '     }' + lcNewLine
lcScript = lcScript + '  }' + lcNewLine
lcScript = lcScript + '  return result;' + lcNewLine
lcScript = lcScript + ' }' + lcNewLine

A few notes, the code above is assuming that it returns more than one url. This is why the url's are separated by a semicolumn eg. <url1>;<url2>;<url3>;

If it is only supposed to return a single url then you can simplify it like so:
Code:
lcScript = lcScript + '    if (id.toLowerCase().includes("enlaceExpediente".toLowerCase())) {' + lcNewLine
lcScript = lcScript + '      result=url;' + lcNewLine
lcScript = lcScript + '    }' + lcNewLine
So only change the line with "result=" and keep the rest.

Another note is that you can debug the script that you are sending from vfp.
See Debug Anonymous javascript functions    

PS: reposted as the correct user as it might be confusing that I posted this answer as a forum test user Smile
--
Wil
Reply
#6
Thanks, Wil.

Maybe now i got the trick. And the example 'opens' my mind to other ways of thinking web automation. We are 'forcing' browse to exec new code that is not contained on it and return for us i.e. a list of ids... then we'll work with this ids and 'ById' functions.
Now i can go ahead. I'll keep in touch.
Thanks again.
Regards

CYZ
Reply
#7
Hi,

It's pretty different from how things used to work in the old control and it does mean having to work with another language (javascript). However it also means that there are now more ways to do things and you're not limited to the exposed API. If it can be done in javascript then there most likely are ways to do it in your application.
On top of that there is a lot of javascript knowledge out there.

Having said all that, we do try to extend our API for most of the basic things of accessing the document content, so you don't have to fall back to javascript all the time.

Let me know if you have more questions.
--
Wil
Reply
#8
(2024-12-03, 08:14:48)carlos@agpsoftware.com Wrote: Thanks, Wil.

Maybe now i got the trick. And the example 'opens' my mind to other ways of thinking web automation. We are 'forcing' browse to exec new code that is not contained on it and return for us i.e. a list of ids... then we'll work with this ids and 'ById' functions.
Now i can go ahead. I'll keep in touch.
Thanks again.
Regards

i am wondering, can Javascript return an object instead of string or other type of value?
Something like:
    return document.getElementById("viewns_Z7_AVEQAI930OBRD02JPMTPG21004_:form1:button1")
I case yes, could i read attributes of this returned object?

CYZ
Reply
#9
Carlos,

There's no (shadow)DOM at ActiveX level, so you can't really do things like the old interface.
You can however return the full html of the element and parse that html on your end.

Something along the lines of:
Code:
() => {
  let obj = document.getElementById("MPFooter");
  return obj.outerHTML;
  }

would then return the full content of html element with Id "MPFooter".

Edit:
BTW, if you know the Id already and what Attribute you are looking for then you can skip all that and use a couple of AntView document functions: ElementHasAttributeById and RequestElementAttributeById 
(or there Synchronized alternatives ElementHasAttributeByIdSync and RequestElementAttributeByIdSync
--
Wil
Reply
#10
I’ve already tested those functions; thanks. Even that i see “value” seems to not be an attribute and we have to use other functions to get element value.
Thanks

CYZ
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)