Webview intergration Part 2

In the first part of the series, we discussed a lot of information briefly.

However, my goal was to have a small, functional plugin integrated into a web view by the end of the first part.

In this part, I will delve into the actual hooks since they are essential for the communication between
a web view and Filemaker.

As mentioned in the first part, there are two ways to pass a call to Filemaker:

Until Filemaker 19, the only way to execute scripts in Filemaker was through an fmp protocol call.

Firstly, I will explain the “old” method using an fmp protocol link that then calls a Filemaker script.
This method still works from Filemaker 19 onwards (the link just needs to contain the version number).
The fmp protocol link offers an advantage that we will learn about during the course, and without it,
for example, my Kanban would not be possible.

To avoid covering the entire topic here, I recommend reading this article from Claris, even though it is older:
https://help.claris.com/archive/help/14/fmp/en/html/sharing_data.17.6.html

So, you generate a link that addresses a Filemaker file and executes a script, possibly passing parameters:

fmp{FMVersion}://$/mydatabaseName?script=myScriptName&param=myParameter

Until Filemaker 19, no version number was specified. Since Filemaker 19, such a link should look like this:

fmp19://$/mydatabaseName?script=myScriptName&param=myParameter

To generate such a link, you can simply use the following calculation and store it as a custom function:

generateFmpLink ( database ; script ; parameterList ; parameterListSeparator ) = 
Let (
[
getAppVersion = Floor ( GetAsNumber ( Substitute ( Get ( ApplicationVersion ) ; "." ; "," ) ) ) ;
fmp = Case ( getAppVersion ≥ 18 ; "fmp" & getAppVersion & "://" ; "fmp://" )
] ; fmp & "$/" & database & "?script=" & script & If ( ValueCount ( parameterList ) > 0 ;
"&param=" & Substitute ( parameterList ; ¶ ; parameterListSeparator ) ; "" )
)

I use the separator to create a valid URL, which should not contain line breaks. Therefore, I replace them in the parameterList
with the separator.

I again use a text field “HTML” with a placeholder “__Link” in an attached parameter table via an X-relationship:

html
Parameter::HTML=
<!doctype html>
<html lang='en'>
<head>
<meta charset='utf-8'>
</head>
<body>
<style>
body {font-family: 'Lucida Grande', 'sans-serif';font-size: 8pt; line-height: 300%;
background-color:#FFFFFF;}
</style>
__Link
</body>
</html>

To create the actual links, I use an unstored calculation with the display values of the links and the
URL to be called (fmp protocol):

Webview FM =
While (
[
ListeLink = "First Button¶Second Button" ;
ListeValue = "Button1¶Button2";
Script = "Click on Link" ;
max = ValueCount ( ListeLink ) ;
lines = "" ;
i = 1
] ;
i ≤ max ;
[
lines = List ( lines ; "<a href='" & generateFmpLink ( Get ( FileName ) ; Script ;
GetValue ( ListeValue ; i ) ; "||||" ) & "'>" & GetValue ( ListeLink ; i ) & "</a></br>" ) ;
i = i + 1
] ;
Substitute ( Parameter::HTML ; "__Link" ; lines )
)

Within the While function, a line with an fmp protocol link is generated for each entry in the
“ListeLink.” In the end, the “__Link” placeholder in Parameter::HTML is replaced with this list.

<a href='fmp19://$/HTML Click?script=Click on Link&param=Button1'>First Button</a>
<a href='fmp19://$/HTML Click?script=Click on Link&param=Button2'>Second Button</a>

Clicking one of the links will execute the “Click on Link” script with the “Button1” or “Button2” parameter in the “HTML Click” file.

The entire HTML code looks like this:

HTML=
<!doctype html>
<html lang='en'>
<head>
<meta charset='utf-8'>
</head>
<body>
<style>
body {font-family: 'Lucida Grande', 'sans-serif';font-size: 8pt; line-height: 300%;
background-color:#FFFFFF; }
</style>
<a href='fmp19://$/HTML Click?script=Click on Link&param=Button1'>First Button</br>
<a href='fmp19://$/HTML Click?script=Click on Link&param=Button2'>Second Button</br>
</body>
</html>

To display this HTML code in a web view, we need to prepend the formula with the text “data:text/html”:

"data:text/html," & Webview FM

The link can be replaced with the JavaScript command
“FileMaker.PerformScript(script, parameter);” from FileMaker 19 onwards.

Here’s the adjusted calculation for Webview FM:

Webview FM=
While (
[
ListeLink = „First Button¶Second Button" ;
ListeValue = "Button1¶Button2";
Script = "Click on Link" ;
max = ValueCount ( ListeLink ) ;
lines = "" ;
i = 1
] ;
i ≤ max ;
[
lines = List ( lines ; "<a onClick='FileMaker.PerformScript ( \"" & Script & "\",\"" &
GetValue ( ListeValue ; i ) & "\" );’ style='cursor: pointer; cursor: hand;'>" &
GetValue ( ListeLink ; i ) & "</a></br>" ) ;
i = i + 1
] ;
Substitute ( Parameter::HTML ; "__Link" ; lines )
)

The HTML “<a>” tag looks a bit different but has the same functionality.

<a onClick='FileMaker.PerformScript ("Click","Button1“);'style='cursor: pointer; cursor: hand;‘>First Button</a>
<a onClick='FileMaker.PerformScript ("Click","Button2“);'style='cursor: pointer; cursor: hand;‘>Second Button</a>

At this point, I would like to point out a peculiar thing I encountered during the adaptation to FileMaker.Perform Script.
Initially, I used only single quotes in the calculation, but the web view always interpreted the last single quotes as double quotes,
causing the FM script call not to work.
It was only when I used double quotes (\”) at this point that I could trigger the script by clicking.
I haven’t found an explanation for why this happens.

That concludes the simple example of how to generate a hook yourself. This can be very useful if you want to use
a list in Filemaker where clicking triggers a script.

For my own projects, I usually look for plugins that already offer such methods. If we look at the fantastic site https://jqueryui.com/demos/,
all widgets/plugins here are very well-equipped with events and methods and are thoroughly documented.

In the next part of the series, we will take a closer look at the JQUERY part of our slider example from the last part,
as it is not as easy for Filemaker developers to understand the JQUERY syntax.

The JQUERY Slider is a widget, essentially its own object with properties that can be configured. To interact
with this widget, we need to address the Slider Widget and be able to change its properties.

If we examine the actual part of the Slider Init function from the last part, the slider itself is created in the
HTML part <body> through
<div id=”slider-range-max” style=”width:95%;”></div>.
So, it has received an id (“slider-range-max”). This id is arbitrarily assigned and logically should be unique in the
HTML code so that we can always address the correct element.

To speak to this element, we can use “$( “#slider-range-max” )” in JQUERY, selecting the element and using dot notation to address individual sub-elements within the element:
“$( “#slider-range-max” ).slider”.

In addition to the id selector “#” in JQUERY, there are other operators for addressing HTML elements – https://www.w3schools.com/jquery/jquery_ref_selectors.asp

We can then give options to the “Slider” element (as seen in the JQUERYUI documentation
at https://api.jqueryui.com/slider/, use methods, or utilize events.

In our example:

$( "#slider-range-max" ).slider({
range: "max", // We give the Slider a max value as the Range endpoint -> here max: 10
min: 1, // The minimum value of the Slider
max: 10, // The maximum value of the Slider
value: 2, // The current value of the Slider (In the example,
this was a placeholder to be replaced by a Filemaker field value)
slide: function( event, ui ) { // An event of the Slider triggered ALWAYS DURING
the Slider is being changed
$( "#amount" ).val( ui.value ); // Again, an HTML element with the id "amount" is
addressed to enter the value from the Slider into the <Label> "Minimum number of bedrooms:"
};
});

Our hook from the last part is also an event of the Slider Widget. We used the “Change” event to pass the current value to our Filemaker script at the moment when the value of the Slider has changed (after the user has changed it):

change: function(event, ui) {
event.preventDefault(); // Prevents a link from directly opening a URL
(see https://www.w3schools.com/jsref/event_preventdefault.asp)
Here, we actually prevent the default action of the "change" method from being executed
var str = $("#slider-range-max").slider( "value" ); // We define a variable "str" and retrieve the value
from the Slider by querying its "value" property
(see [https://api.jqueryui.com/slider/#option-value](https://api.jqueryui.com/slider/#option-value))
FileMaker.PerformScript ( 'ReturnSlider', str ); // Then, the Filemaker script "ReturnSlider"
is called with the variable "str"
}

 

$( "#amount" ).val( $( "#slider-range-max" ).slider( "value" ) ); // Here, the HTML element with id=amount 
is described with the value of the Slider

So, you can take an existing method (like “change”) from a widget and attach our hook to it. Many plugins already offer these methods, making it easy to perform a Filemaker call.

In my own projects, I usually look for plugins that already offer such methods. If we look at the fantastic site https://jqueryui.com/demos/, all widgets/plugins here are very
well-equipped with events and methods and are thoroughly documented.

To conclude this part, I would like to give a preview of the next part of the article series and how we can create a hook without the “<a href>” link. It involves the JQUERY command
“$( self.location = “fmp19://$/DatabaseName?script=ScriptName&param=ParameterString );” This method performs a redirect to a new URL
see https://www.w3schools.com/js/js_window_location.asp

The hook is built into the code within an event – here, it’s the Click event of a JQUERYUI Portlet:

$( ".portlet-content" ).on( "click", function( e ) {
var id = $(this).closest('.portlet').attr('id');
$( self.location = '__script&param=selectItem||||' + id );
});

In the next episode, we will discuss this method in more detail and use it for the JQUERY Portlets https://jqueryui.com/sortable/#portlets.

I hope that I have presented the information in a reasonably straightforward manner and look forward to the next part of the series where we will bring together
everything learned in a practical example.

Do you have any questions? Feel free to send me an email; I’ll try to answer as soon as possible.