Page 1 of 1

Calling a PB procedure from Javascript

Posted: Sun Mar 01, 2020 10:01 am
by firace
Is there any way of having the HTML button in this webgadget trigger a PB procedure?

EDIT: Perhaps by adapting this code: viewtopic.php?f=3&t=54007&hilit=NavigationCallback

I will play around with it and see if I can get anywhere.

Code: Select all

OpenWindow(0, 0, 0, 600, 300, "WebGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

WebGadget(0, 10, 10, 580, 240, "")
SetGadgetItemText(0, #PB_Web_HtmlCode, "<html><body>Hello <form><button onclick='document.body.innerText=1234;'>Test</button></form></body></html>")

Repeat
  EventID = WaitWindowEvent()  
Until EventID = #PB_Event_CloseWindow

Re: Calling a PB procedure from Javascript

Posted: Sun Mar 01, 2020 12:58 pm
by Sicro

Code: Select all

OpenWindow(0, 0, 0, 600, 300, "WebGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

WebGadget(0, 10, 10, 580, 240, "")
SetGadgetItemText(0, #PB_Web_HtmlCode, ~"<html><body>Hello <form><button onclick='document.body.innerText=1234; window.location.href = \"#click\"; return false'>Test</button></form></body></html>")

Repeat
  EventID = WaitWindowEvent()
  
  If url$ <> GetGadgetText(0)
    url$ = GetGadgetText(0)
    If StringField(url$, 2, "#") = "click"
      Debug "Button was clicked!"
    EndIf
  EndIf
  
Until EventID = #PB_Event_CloseWindow

Re: Calling a PB procedure from Javascript

Posted: Sun Mar 01, 2020 4:20 pm
by firace
Nice approach! I couldn't try it on a Mac yet, but it seems to work fine on Windows :)

Re: Calling a PB procedure from Javascript

Posted: Sun Mar 01, 2020 6:04 pm
by mk-soft
With the Link: viewtopic.php?f=3&t=54007 :wink:

Code: Select all

EnableExplicit

ImportC ""
  sel_registerName(str.p-ascii)
  class_addMethod(class, selector, imp, types.p-ascii)
EndImport

Global appDelegate = CocoaMessage(0, CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
Global delegateClass = CocoaMessage(0, appDelegate, "class")

ProcedureC PolicyDecisionMaker(obj, sel, webView, actionInformation, request, frameName, listener)
  Protected URL = CocoaMessage(0, request, "URL")
  Protected URLString.s = PeekS(CocoaMessage(0, CocoaMessage(0, URL, "absoluteString"), "UTF8String"), -1, #PB_UTF8)

  If URLString = "#click" 
    MessageRequester("", "Button clicked!")
  Else
    CocoaMessage(0, listener, "use")
  EndIf
EndProcedure

class_addMethod(delegateClass, sel_registerName("webView:decidePolicyForNavigationAction:request:frame:decisionListener:"), @PolicyDecisionMaker(), "v@:@@@@@")

If OpenWindow(0, 270, 100, 600, 300, "WebGadget")
  WebGadget(0, 10, 10, 580, 280, "")
  SetGadgetItemText(0, #PB_Web_HtmlCode, ~"<html><body>Hello <form><button onclick='document.body.innerText=1234; window.location.href = \"#click\"; return false'>Test</button></form></body></html>")

  CocoaMessage(0, GadgetID(0), "setPolicyDelegate:", appDelegate)
 
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Re: Calling a PB procedure from Javascript

Posted: Sun Mar 01, 2020 6:54 pm
by Shardik
I have tried Sicro's example on these operating systems with PB 5.71 x64:
  • Linux 19.3 'Tricia' x64: the contents of the root directory are displayed in the WebGadget; the debug message "Button was clicked!" is not displayed!
  • MacOS 10.14.6 'Mojave': the debug message "Button was clicked!" is not displayed!
  • Windows 10 x64 V1809: the debug message "Button was clicked!" is correctly displayed.
mk-soft's example is working fine on MacOS (it utilizes MacOS API functions)!

If you want to detect on MacOS when a button in a HTML form is clicked, you may also try this example from the German forum.

Re: Calling a PB procedure from Javascript

Posted: Tue Mar 03, 2020 7:55 pm
by Sicro
Shardik wrote:Linux 19.3 'Tricia' x64: the contents of the root directory are displayed in the WebGadget; the debug message "Button was clicked!" is not displayed!
Before I posted my above code here, I tested it on Linux and Windows XP.
Under Linux additional code was needed for the WebGadget because JavaScript is not enabled by default and SetGadgetItemText() is not supported. I omitted this additional code here because I assumed that only a macOS solution is requested and not a cross-platform solution.
Here the above code with the additional code for Linux:

Code: Select all

ImportC "-lwebkitgtk-3.0"
  webkit_web_settings_new()
  webkit_web_view_set_settings(*webkitWebView, *webkitSettings)
  webkit_web_view_load_string(*webView, content.p-utf8, *mimeType, *encoding, *baseURI)
EndImport

OpenWindow(0, 0, 0, 600, 300, "WebGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

WebGadget(0, 10, 10, 580, 240, "")
; Enable Javascript
*webKitSettings = webkit_web_settings_new()
webkit_web_view_set_settings(GadgetID(webGadget), *webkitSettings)
; Set HTML code
webkit_web_view_load_string(GadgetID(0), ~"<html><body>Hello <form><button onclick='document.body.innerText=1234; window.location.href = \"#click\"; return false'>Test</button></form></body></html>", 0, 0, 0)

Repeat
  EventID = WaitWindowEvent()
  
  If url$ <> GetGadgetText(0)
    url$ = GetGadgetText(0)
    If StringField(url$, 2, "#") = "click"
      Debug "Button was clicked!"
    EndIf
  EndIf
Until EventID = #PB_Event_CloseWindow
Shardik wrote:MacOS 10.14.6 'Mojave': the debug message "Button was clicked!" is not displayed!
Pity. I just saw in the PB help that SetGadgetItemText() is also not supported on macOS.
And if you use this instead of SetGadgetItemText():

Code: Select all

Procedure SetHTMLCode(webGadget, htmlCode$)
  Protected filePath$ = GetTemporaryDirectory() + "temp.html"
  Protected file = CreateFile(#PB_Any, filePath$)
  If file
    WriteString(file, htmlCode$)
    CloseFile(file)
    SetGadgetText(webGadget, "file:///" + filePath$)
  EndIf
EndProcedure

SetHTMLCode(0, ~"<html><body>Hello <form><button onclick='document.body.innerText=1234; window.location.href = \"#click\"; return false'>Test</button></form></body></html>")

Re: Calling a PB procedure from Javascript

Posted: Wed Mar 04, 2020 3:25 pm
by firace
OK, I had a chance to try Sicro's first code on a Mac last weekend (I don't personally have a Mac at home), and in fact it did work for me: the "Button is clicked" debug statement was triggered, but with a caveat: it was triggered when the mouse button was released too. In case that matters, OS X version was pretty old (10.11.6).

Didn't have a chance to try the other codes yet.

Re: Calling a PB procedure from Javascript

Posted: Wed Mar 04, 2020 4:12 pm
by Derren
Sicro wrote:

Code: Select all

OpenWindow(0, 0, 0, 600, 300, "WebGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

WebGadget(0, 10, 10, 580, 240, "")
SetGadgetItemText(0, #PB_Web_HtmlCode, ~"<html><body>Hello <form><button onclick='document.body.innerText=1234; window.location.href = \"#click\"; return false'>Test</button></form></body></html>")

Repeat
  EventID = WaitWindowEvent()
  
  If url$ <> GetGadgetText(0)
    url$ = GetGadgetText(0)
    If StringField(url$, 2, "#") = "click"
      Debug "Button was clicked!"
    EndIf
  EndIf
  
Until EventID = #PB_Event_CloseWindow
Interesting idea, but a second or third click won't be recognized.
You would need to set the URL back to "withouth #click". But I haven't tested if this can be done without the whole website refreshing (perhaps set it to thisisthebaseURL#null" instead

Code: Select all

If StringField(url$, 2, "#") = "click"
    Debug "Button was clicked!"
    SetGadgetText(0, "#null_or_really_anything_else_that_is_not_click")
EndIf


edit: nvm. in this code the Button disappears, so it's not an issue, but generally speaking, it is

Re: Calling a PB procedure from Javascript

Posted: Thu Mar 05, 2020 6:46 pm
by Sicro
@Derren:

Code: Select all

OpenWindow(0, 0, 0, 600, 300, "WebGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

WebGadget(0, 10, 10, 580, 240, "")
SetGadgetItemText(0, #PB_Web_HtmlCode, ~"<html><body>Hello <form><button onclick='window.location.href = \"#click_\" + Date.now(); return false'>Test</button></form></body></html>", 0, 0, 0)

Repeat
  EventID = WaitWindowEvent()
 
  If url$ <> GetGadgetText(0)
    url$ = GetGadgetText(0)
    If StringField(StringField(url$, 2, "#"), 1, "_") = "click"
      Debug "Button was clicked!"
    EndIf
  EndIf
 
Until EventID = #PB_Event_CloseWindow

Re: Calling a PB procedure from Javascript

Posted: Thu Mar 05, 2020 9:41 pm
by Shardik
Sicro wrote:
Shardik wrote:MacOS 10.14.6 'Mojave': the debug message "Button was clicked!" is not displayed!
Pity. I just saw in the PB help that SetGadgetItemText() is also not supported on macOS.
And if you use this instead of SetGadgetItemText():

Code: Select all

Procedure SetHTMLCode(webGadget, htmlCode$)
  Protected filePath$ = GetTemporaryDirectory() + "temp.html"
  Protected file = CreateFile(#PB_Any, filePath$)
  If file
    WriteString(file, htmlCode$)
    CloseFile(file)
    SetGadgetText(webGadget, "file:///" + filePath$)
  EndIf
EndProcedure

SetHTMLCode(0, ~"<html><body>Hello <form><button onclick='document.body.innerText=1234; window.location.href = \"#click\"; return false'>Test</button></form></body></html>")
On MacOS 10.14.6 'Mojave' your first example with the added procedure SetHTMLCode() is displaying the debug message "Button was clicked!" correctly!

Re: Calling a PB procedure from Javascript

Posted: Fri Mar 06, 2020 8:50 pm
by Sicro
Shardik wrote:On MacOS 10.14.6 'Mojave' your first example with the added procedure SetHTMLCode() is displaying the debug message "Button was clicked!" correctly!
Glad to hear it. Thanks for testing.