Generate HTML link from text

 

Very often I have been asked if it is possible to enter a simple HTML link in a text field and generate a callable hyperlink from it in the display webview.

To create an HTML link for a webview you have to convert the entered web address into a hyperlink which then calls a Filemaker script.
The script then opens this link in the web browser (or if it is e.g. an email address, the mail program with this email address).

Opening the link directly as a hyperlink in the web browser is not a good idea, because then the website will be opened directly in the webview

The general format of an HTML link looks like this:

<a href=”url”>display text</a>

With example data

<a href=”http://iconiccoding.com”>Visit me</a>

For a Filemaker Script call we need the form:

<a href=”fmp19://$/databasename?script=scriptname&param=parameter“>display text</a>

With example data

<a href=”fmp19://$/HTML link?script=Return_Function&param=http||||http://iconiccoding.com“>
http://iconiccoding.com</a>

The script parameter “http||||http://iconiccoding.com” is used by the Filemaker script to create a parameter list by

Substitute ( parameter ; “||||” ; ¶ )

, so that the first parameter tells the script what function to execute (call HTML link, create email…) and the second parameter provides the argument.

For this conversion a custom function is useful, which extracts the entered link from the text and extends it by the parts for the hyperlink in the webview.
We have to recognize the beginning and the end of the HTML address, so that you leave the text before and after the link and only expand the link itself.

My approach in this case is a printout in the following form:

[http://iconiccoding.com]

The beginning “[http” tells us that it is an HTML link and the end we find by the next “]” character in the text.

So we pass 4 parameters to our custom function:
– The entire text
– The start text of the link
– The end text of the link
– The HMTL part to be added to the text

So the custom function searches for the text between “[http” and “]” and adds there
“<a href=”fmp19://$/HTML link?script=Return_Function&param=http||||http” + the extracted link (without the leading “http”) + “>” + the extracted link (extended with the leading “http”) + “</a>”
in.

If this function now recursively works through the entire text, all HTML links for the webview will be rearranged.

/*
httpCall ( Text ; beginString ; endString ; replaceString )

e.g.
httpCall ( "Please click this link [http://iconiccoding.com]" ; "[http" ; "]" ; 
"<a href='fmp19://$/HTML link?script=Return_Function&param=http||||" )
*/

Let ([
lenBegin = Length(beginString);
lenEnd = Length(endString);
ptBegin = Position(text; beginString; 1; 1);
ptEnd = Position(text; endString; ptBegin + lenBegin; 1) + lenEnd;
modText = Left(text; ptBegin - 1);
remainText = Middle(text; ptEnd; 9999999);
replace = Middle ( text ; ptBegin + Length (beginString ) ; ptEnd - 1 - ptBegin - Length (beginString ) );
replaceClean = Substitute ( replace ;
[ "%" ; "%25" ] ; [ "¶" ; "%0D" ] ; [ " " ; "%20" ] ; [ "!" ; "%21" ] ; [ "\"" ; "%22" ] ; [ "#" ; "%23" ] ; [ "$" ; "%24" ] ;
[ "&" ; "%26" ] ; [ "'" ; "%27" ] ; [ "(" ; "%28" ] ; [ ")" ; "%29" ] ; [ "*" ; "%2A" ] ; [ "+" ; "%2B" ] ; [ "," ; "%2C" ] ;
[ "-" ; "%2D" ] ; [ "." ; "%2E" ] ; [ "/" ; "%2F" ] ; [ ":" ; "%3A" ] ; [ ";" ; "%3B" ] ; [ "<" ; "%3C" ] ; [ "=" ; "%3D" ] ;
[ ">" ; "%3E" ] ; [ "?" ; "%3F" ] ; [ "@" ; "%40" ] ; [ "[" ; "%5B" ] ; [ "\\" ; "%5C" ] ; [ "]" ; "%5D" ] ; [ "^" ; "%5E" ] ;
[ "`" ; "%60" ] ; [ "{" ; "%7B" ] ; [ "|" ; "%7C" ] ; [ "}" ; "%7D" ]
)
];

Case(
lenBegin > 0 and lenEnd > 0 and
ptBegin > 0 and ptEnd > lenEnd;

modText & replaceString & "http" & replaceClean & "'>http" & replace & "</a>" & 
httpCall(remainText; beginString; endString; replaceString)

; text)

)

 

The function is deliberately designed so that you can change the parameters yourself and from this function you can easily derive other links:

/*
mailCall ( Text ; beginString ; endString ; replaceString )

e.g.
mailCall ( "Please drop me a line [Email:stephan@iconiccoding.com] ; "[Email" ; "]" ;
"<a href='fmp19://$/HTML link?script=Return_Function&param=Email||||" )
*/

Let ([
lenBegin = Length(beginString);
lenEnd = Length(endString);
ptBegin = Position(text; beginString; 1; 1);
ptEnd = Position(text; endString; ptBegin + lenBegin; 1) + lenEnd;
modText = Left(text; ptBegin - 1);
remainText = Middle(text; ptEnd; 9999999);
replace = Middle ( text ; ptBegin + Length (beginString ) ; ptEnd - 1 - ptBegin - Length (beginString ) );
textDisplay = "Email"
];

Case(
lenBegin > 0 and lenEnd > 0 and
ptBegin > 0 and ptEnd > lenEnd;

modText & replaceString & replace & "'>" & replace & "" & 
mailCall(remainText; beginString; endString; replaceString)

; text)

)

If you now call all your link functions from a master call, various link types can be replaced from the text.

The result of our custom functions looks like this:

Bildschirmfoto 2021 03 07 um 12 21 38

At the bottom left of the screenshot you can see a simple popup that displays the created link records from a separate table.
In this table I also generate the finished replaceString with which I later call the master custom function:

Bildschirmfoto 2021 03 07 um 12 30 51

If we now call the following cf masterCall we can pass the prefabricated replace strings from this table as a list.

/*
masterCall ( Text ; theList ; counter )
counter must be set initial to 1

masterCall ( "Long Text with Links [Email:stephan@iconiccoding.com] [http://iconiccoding.com] ;
"[http••••]••••<a href='fmp18://$/HTML link?script=Return_Function&param=http||||¶
[Email:••••]••••<a href='fmp18://$/HTML link?script=Return_Function&param=Email||||¶
[Phone:••••]••••<a href='fmp18://$/HTML link?script=Return_Function&param=Phone||||" ; 1 )
*/

Let (
[
max = ValueCount ( theList ) ;
counter = If (counter = 0 or counter = "" ; 1 ; counter ) ;
valueList = Substitute ( GetValue ( theList; counter ) ; "••••" ; ¶ ) ;
beginString = GetValue ( valueList ; 1 ) ;
endString = GetValue ( valueList ; 2 ) ;
replaceString = GetValue ( valueList ; 3 ) ;
newText = Case (
beginString = "[http" ; httpCall ( Text ; beginString ; endString ; replaceString ) ;
beginString = "[Message:" ; messageCall ( Text ; beginString ; endString ; replaceString ) ;
beginString = "[Email:" ; mailCall ( Text ; beginString ; endString ; replaceString ) ;
fmpCall ( Text ; beginString ; endString ; replaceString )
)
] ;

Case (
counter < max ; masterCall (newText; theList; counter + 1 ) ;
counter = max ; newText
)

)

The script for inserting the predefined links from the popup looks like this.

Set Variable [ $p ; Value: GetValue ( Get ( ScriptParameter ) ; 1 ) ] 
If [ $p = "http" ]
Set Variable [ $no ; Value: "http://iconiccoding.com" ]
Set Variable [ $start ; Value: Length ( html link::text & "[" ) + 1 ]
Set Variable [ $end ; Value: $start + Length ( $no ) -1 ]
Set Field [ html link::text ; html link::text & "[" & $no & "]" ]
Set Selection [ html link::text ; Start Position: $start ; End Position: $end ]
Else If [ $p = "Email" ]
Set Variable [ $no ; Value: "stephan@iconiccoding.com" ]
Set Variable [ $start ; Value: Length ( html link::text & "[" & $p & ":" ) + 1 ]
Set Variable [ $end ; Value: $start + Length ( $no ) -1 ]
Set Field [ html link::text ; html link::text & "[" & $p & ":" & $no & "]" ]
Set Selection [ html link::text ; Start Position: $start ; End Position: $end ]
Else If [ $p = "Message" ]
Set Variable [ $no ; Value: "Message-Id" ]
Set Variable [ $start ; Value: Length ( html link::text & "[" & $p & ":" ) + 1 ]
Set Variable [ $end ; Value: $start + Length ( $no ) -1 ]
Set Field [ html link::text ; html link::text & "[" & $p & ":" & $no & "]" ]
Set Selection [ html link::text ; Start Position: $start ; End Position: $end ]
Else
Set Variable [ $no ; Value: "Value" ]
Set Variable [ $start ; Value: Length ( html link::text & "[" & $p & ":" ) + 1 ]
Set Variable [ $end ; Value: $start + Length ( $no ) -1 ]
Set Field [ html link::text ; html link::text & "[" & $p & ":" & $no & "]" ]
Set Selection [ html link::text ; Start Position: $start ; End Position: $end ]
End If
Close Popover

And finally, when a link is clicked in the webview, this script is called, which then recognizes the link and reacts accordingly.

Set Variable [ $ReturnValue ; Value: Get ( ScriptParameter ) ] 
Set Variable [ $ReturnValue ; Value: FMScriptEscape ( $ReturnValue ) ]
Set Variable [ $fmp ; Value: Let ( [ sc_appVersion =
Floor ( GetAsNumber ( Substitute ( Get ( ApplicationVersion ) ; "." ; "," ) ) ) ;
sc_fmpProtocol = Case ( sc_appVersion ≥ 18 ; "fmp" & sc_appVersion & "://" ; "fmp://" ) ] ; sc_fmpProtocol ) ]
#
Freeze Window
Set Error Capture [ On ]
If [ $ReturnValue = "" ]
Exit Script [ Text Result: ]
End If
#
Set Variable [ $ParameterList ; Value: Substitute ( $ReturnValue ; "||||" ; ¶ ) ]
Set Variable [ $function ; Value: GetValue ( $ParameterList ; 1 ) ]
#
#
Set Variable [ $p1 ; Value: GetValue ( $ParameterList ; 2 ) ]
If [ $function = "http" ]
Open URL [ With dialog: Off ; $p1 ]
Else If [ $function = "message" ]
Open URL [ With dialog: Off ; "message://" & Substitute ( $p1 ; ["<" ; "%3c"] ; [">" ; "%3e"] ) ]
Else If [ $function = "email" ]
Send Mail [ Send via E-mail Client ; With dialog: On ; To: $p1 ]
Else If [ $function = "telefon" or $function = "phone" ]
Set Variable [ $telNo ; Value:
Let (
tel = Filter ( $p1 ; "0123456789+" );
Case ( tel = "" ; "" ;
Left ( tel ; 1 ) = "+" ;
Substitute ( tel ; "(0)" ; "0" );
Left ( tel ; 2 ) = "00" ;
Substitute ( "§%" & tel ; [ "§%00" ; "+49" ] ; [ "(0)" ; "0" ] ) ;
Left ( tel ; 1 ) = "0" ;
Substitute ( "§%" & tel ; "§%0" ; "+49" ) ;
)
)
Open URL [ With dialog: Off ; "tel://" & $telNo ]
Else
# fmpProtocol & "$/" & Parameter~Links#Var_Text::filename & "?script=" & Parameter~Links#Var_Text::scriptname

Commit Records/Requests [ With dialog: Off ]
Set Variable [ $sql ; Value:
ExecuteSQL ( "SELECT filename, scriptname FROM Parameter WHERE function = ?" ; ¶ ; ¶ ; $function ) ]
Open URL [ With dialog: Off ; $fmp & "$/" & GetValue ($sql ; 1) &
"?script=" & GetValue ($sql ; 2) & "&param=" & $function & "||||" & $p1 ]
End If
If [ Get (LastError) ≠ 0 ]
Show Custom Dialog [ "Error" ; ErrorDescription ( Get (LastError ) ) ]
End If

 

If you like to have an open version of the this file, just send me an email.

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