Page 1 of 6

WebGadget: Directly insert code and catch link clicks.

Posted: Thu Sep 15, 2005 1:37 am
by freak
As some of you may have followed the thread here viewtopic.php?t=16737 ,
i have posted a lot of code to interface with the Document Object Model of IE or the WebGadget.

Since such things (catching links and writing code to it) have been
requested for quite a while, i decided to put it into some simple functions
for easy usage. As you can see from the example below, there is no
knowledge of COM or Interfaces needed.
If you want to do more specific things than these functions allow, i suggest
you have a close look on the above mentioned thread. It has examples
of how to get individual html elements and setting up various event callbacks.

Its all one includefile. You can get it here:
http://freak.purearea.net/code/WebGadgetExtras.pb

Procedure description:

WebGadget_IsLoaded(#Gadget)
Returns 1 if the page has finished loading and 0 if not. This must be
checked before setting up the links callback. (as it requires the page to be fully loaded)
This is only needed if the page is loaded from a file or from the web.
(not needed the code is directly written with the procedures below)

WebGadget_CatchLinks(#Gadget, @Callback())
This sets up a callback that will receive all link clicks in this page.
It must be called when the page is fully loaded. The link callback is set
for the currently present links only. If the page is reloaded, or the contents
are changed (new page), you have to call this again!
Currently the page may not contain frames for this to work.
The callback must look like this:

Code: Select all

Procedure LinkCallback(Gadget, Link$, Text$, ID$, Class$)

  ProcedureReturn 0
EndProcedure
Gadget : Gadget number of the WebGadget
Link$ : receives the target set by the "href" attribute.
Text$ : receives the displayed text.
ID$ : receives the ID attribute of the link.
Class$ : receives the classname for the link.

If you return 0 from the callback, the link will not be executed. If you return
a non-zero value, then the link will be executed. (the target file will be loaded.)

WebGadget_Open(#Gadget, AddHistory)
Opens the WebGadget to write new code into it. Set AddHistory to non-zero
if you want the new page to be a new entry in the history. Set it to 0
if the new content should just replace the old page.

WebGadget_Write(String$)
Writes the given string into a previously opened WebGadget.

WebGadget_Close()
Completes the writing of new code into the WebGadget.


Ok, finally a short example for the usage. Its really quite simple:

Code: Select all

XIncludeFile "WebGadgetExtras.pb"

#WebGadget = 0

Procedure LinkCallback(Gadget, Link$, Text$, ID$, Class$)

  Debug "Link: "+Link$
  Debug "Text: "+Text$
  Debug ""

  ProcedureReturn 0 ; prevent link from executing
EndProcedure

If OpenWindow(0, 0, 0, 800, 600, #PB_Window_SystemMenu|#PB_Window_ScreenCentered, "WebGadget example")
  If CreateGadgetList(WindowID())
    
    WebGadget(#WebGadget, 0, 0, 800, 600, "")    
            
    If WebGadget_Open(#WebGadget, 0)
    
      WebGadget_Write("<html><body><center><br>")
      WebGadget_Write("<a href="+Chr(34)+"http://www.purebasic.com"+Chr(34)+">PureBasic.com</a><br>")
      WebGadget_Write("<a href="+Chr(34)+"http://forums.purebasic.com"+Chr(34)+">Forum</a><br>")      
      WebGadget_Write("</center></body></html>")
    
      WebGadget_Close()
    EndIf
    
    WebGadget_CatchLinks(#WebGadget, @LinkCallback())            
    
    Repeat
    Until WaitWindowEvent() = #PB_Event_CloseWindow    
    
  EndIf
EndIf
Comments and Questions are welcome...

Posted: Thu Sep 15, 2005 1:40 am
by Brice Manuel
This is EXACTLY what I needed for a project I am working on.

Thank you :D

Posted: Thu Sep 15, 2005 1:46 am
by ricardo
Great! You are a genious and a very nice guy! :)

Posted: Thu Sep 15, 2005 1:50 am
by Dare2
Ace!

Edit:

Thank you, thank you, thank you!

Posted: Thu Sep 15, 2005 3:08 am
by Dare2
Hi, a question.

How should browsing be handled?

I'm doing this:

Code: Select all

Global flg

Procedure LinkCallback(Gadget, Link$, Text$, ID$, Class$)
  Debug "Link="+Link$+", Text="+Text$+", ID="+ID$+", class="+Class$
  SetGadgetText(Gadget,Link$)
  flg=0
  ProcedureReturn 0 ; prevent link from executing
EndProcedure
and

Code: Select all

...
    WebGadget_CatchLinks(#WebGadget, @LinkCallback())
    flg=1

    Repeat
      If WebGadget_IsLoaded(#WebGadget)<>0 And flg=0
        flg=1
        WebGadget_CatchLinks(#WebGadget, @LinkCallback())           
      EndIf
    Until WaitWindowEvent() = #PB_Event_CloseWindow

I can use this to browse the forums, but it will not browse the purebasic site: Obviously I have not understood how to use it. :?


PS: Also a right-click and open in new window does not get caught, so the page escapes from the PB browser and flees into IE.


Thanks again Freak. :)

Posted: Thu Sep 15, 2005 4:40 am
by rsts
Very useful.

Many thanks for sharing this.

Posted: Thu Sep 15, 2005 7:45 am
by Blade
It's just me?
[ERROR] Invalis memory access
(line 489)

Posted: Thu Sep 15, 2005 8:04 am
by gnozal
Thank you very much :D
Maybe these functions (and others :twisted: ) will be standard Purebasic functions in the future ?

Posted: Thu Sep 15, 2005 12:06 pm
by PB
Made sticky because this is a major tip. :)

Web functions are a big part of today's applications and this tip is a good way
to start learning about interacting with web-based projects. Thanks, Freak!

Posted: Thu Sep 15, 2005 12:37 pm
by Num3
Freak for president!!! :lol:

Posted: Thu Sep 15, 2005 1:02 pm
by Nik
Genious
thanks a lot 8)

Posted: Thu Sep 15, 2005 1:58 pm
by Kale
Great Code!!! :shock:

Posted: Thu Sep 15, 2005 2:13 pm
by dracflamloc
How can I get the html source thats been loaded?

Posted: Thu Sep 15, 2005 2:25 pm
by Num3
I seem to have some troubles...

This code doesn't work with mozilla firefox activeX :shock:

Posted: Thu Sep 15, 2005 4:28 pm
by ricardo
dracflamloc wrote:How can I get the html source thats been loaded?

Code: Select all

If Document2\get_body(@Body.IHTMLElement) = #S_OK 
    Body\get_innerHTML(@bstr_code) = #S_OK  
    Html$ = ReadBSTR(bstr_code) ;Html$ stores the code
    SysFreeString_(bstr_body)
EndIf
You can try with get_outerHTML and should work okay too.

Remember you may need to set the string size bigger or maybe best store it into a memory to avoid crashes if its bigger than 64 k.