Access JavaScript functions in WebGadget on Linux

Share your advanced PureBasic knowledge/code with the community.
StanDan
User
User
Posts: 57
Joined: Sun Feb 26, 2006 3:43 am
Location: Missouri, United States

Access JavaScript functions in WebGadget on Linux

Post by StanDan »

After many hours digging through XPCOM, C++ function mangling and blasphemously undocumented Mozilla functions - I finally have a working ExecuteJavaScript() hack for the Linux WebGadget. Although it doesn't use XPCOM or any magic, or for that matter even play with the gtk_moz_embed_*_() API functions. In theory it could be completely cross platform, in practice the win32 IWebBrowser2 object doesn't get the change to the document title until after a return to the programs event loop. Somebody let me know if it works on Mac?
Identical interface as Freak's win32 library, except this one adds an optional timeout value in case the function never returns. This is necessary to prevent lock-ups if an unforseen error occurs and the title never changes.

Code: Select all

; Linux PB 4.30
; Tested on Slackware 11

Prototype.s ProtoExecuteJavaScript(gadget, Function$, Arguments$, Separator$, timeout=5000) 

JSMutex = CreateMutex()

Procedure.s JavaScriptQuote(code.s)
  code = ReplaceString(code, "\", "\\")
  code = ReplaceString(code, Chr(34), "\"+Chr(34))
  ProcedureReturn Chr(34)+code+Chr(34)
EndProcedure

Procedure.l JavaScriptResetTitle(gadget.l)
	Shared JSMutex
	LockMutex(JSMutex)
	SetGadgetText(gadget, "javascript:void(function(){document.title='';})();")
	UnlockMutex(JSMutex)
EndProcedure

Procedure JavaScriptExamineThread(gadget.l)
	title.s = ""
  Repeat
    title = GetGadgetItemText(gadget, #PB_Web_PageTitle)
    If title = ""
      Delay(100)
    EndIf
  Until title > ""
EndProcedure

Procedure.s ProcExecuteJavaScript(gadget, Function$, Arguments$, Separator$, timeout) 
  Shared JSMutex
  If GadgetType(gadget) <> #PB_GadgetType_Web
    ProcedureReturn ""
  EndIf
  code.s = ""
  If Trim(Arguments$) = "" 
    code = ""
  ElseIf Seperator$ = ""
    code = JavaScriptQuote(Arguments$)
  Else            
    Count = CountString(Arguments$, Separator$)+1 
    For i = 1 To Count            
      code = code + JavaScriptQuote(StringField(Arguments$, i, Separator$))
      If i <> Count
        code = code + ","
      EndIf
    Next i 
  EndIf 
  code = Function$+"("+code+");"
  
  JavaScriptResetTitle(gadget)
  LockMutex(JSMutex)
  code = JavaScriptQuote(code)
  js.s = "javascript:void(function(){document.title='';try{var ret = eval("+code
  js = js + ");document.title=ret;}catch(e){document.title='exception: '+e;}})();"
  SetGadgetText(gadget, js)
	thread = CreateThread(@JavaScriptExamineThread(), gadget)
	If thread <> 0
		WaitThread(thread, timeout)
	EndIf
  UnlockMutex(JSMutex)
  title.s = GetGadgetItemText(gadget, #PB_Web_PageTitle)
  ProcedureReturn title
EndProcedure

ExecuteJavaScript.ProtoExecuteJavaScript = @ProcExecuteJavaScript()

#URL = "file:////somewhere.html"

Enumeration
  #Gadget_Web
  #Gadget_Command
  #Gadget_Args
  #Gadget_Text
  #Gadget_Button
EndEnumeration

Procedure Resize()
  Width = WindowWidth(0)
  Height = WindowHeight(0)
  ResizeGadget(#Gadget_Web, 5, 5, Width-10, Height-60)
  ResizeGadget(#Gadget_Command, 5, Height-50, (Width-105)/4, 20)
  ResizeGadget(#Gadget_Args, 10+(Width-105)/4, Height-50, ((Width-105)*3)/4, 20)
  ResizeGadget(#Gadget_Text, 5, Height-25, Width-10, 20)
  ResizeGadget(#Gadget_Button, Width-90, Height-50, 85, 20)
EndProcedure

If OpenWindow(0, 0, 0, 800, 600, "Javascript test", #PB_Window_ScreenCentered|#PB_Window_SizeGadget|#PB_Window_MaximizeGadget|#PB_Window_MinimizeGadget)
    WebGadget(#Gadget_Web, 0, 0, 0, 0, #URL)
    StringGadget(#Gadget_Command, 0, 0, 0, 0, "prompt")
    StringGadget(#Gadget_Args, 0, 0, 0, 0, "So what will it be?,2 Beers")
    TextGadget(#Gadget_Text, 0, 0, 0, 0, "Type commandname into the first, and arguments into the second box. Do not include ()", #PB_Text_Border)
    ButtonGadget(#Gadget_Button, 0, 0, 0, 0, "Execute")
    Resize()
   
    Repeat
      Event = WaitWindowEvent()
      If Event = #PB_Event_SizeWindow
        Resize()
      ElseIf Event = #PB_Event_Gadget And EventGadget() = #Gadget_Button
        Command$ = GetGadgetText(#Gadget_Command)
        Arguments$ = GetGadgetText(#Gadget_Args)
        Result$ = ExecuteJavaScript(#Gadget_Web, Command$, Arguments$, ",")           
        SetGadgetText(#Gadget_Text, "Result: "+Result$)         
      EndIf
    Until Event = #PB_Event_CloseWindow
EndIf

End
Actually, the example given is a prompt() function, which happens to be one of the only things that doesn't work well (modal dialogs.)

Cheers.
Seymour Clufley
Addict
Addict
Posts: 1264
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Post by Seymour Clufley »

Thankyou very much for this. At present I don't have a Linux computer and have never coded for Linux, but I'm sure that in the future this code will be very useful for me.

Thanks again!

Seymour.
dige
Addict
Addict
Posts: 1391
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: Access JavaScript functions in WebGadget on Linux

Post by dige »

hi guys,

I had previously used the WebGadget (iE) to control a Google map. Add pins, centre the map etc.

The whole thing using COMate:
viewtopic.php?p=277466#p277466

Now there is the Edge Webgadget and a WebViewGadget for which there is even a WebViewExecuteScript().

While searching for an implementation for PB6.12, I also found this code above.

With the new Edge WebGadget(): can this also be controlled via COMate? Or should I reprogramme everything to the WebViewGadget?

Any help is appreciated. Thx.
"Daddy, I'll run faster, then it is not so far..."
User avatar
mk-soft
Always Here
Always Here
Posts: 6209
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Access JavaScript functions in WebGadget on Linux

Post by mk-soft »

For the Linux WebGadget I have written extensions with which you can execute java scripts. This also works for the WebViewGadget.

Link: WebGadget Extensions
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
dige
Addict
Addict
Posts: 1391
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: Access JavaScript functions in WebGadget on Linux

Post by dige »

Thank you mk-soft. But that seems to be for Linux only - I forgot to mention, I need that for Windows..
"Daddy, I'll run faster, then it is not so far..."
User avatar
mk-soft
Always Here
Always Here
Posts: 6209
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Access JavaScript functions in WebGadget on Linux

Post by mk-soft »

After I had sent it, I noticed it too. For Windows

So on WebViewGadget
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Post Reply