Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 10 of 10 total
Thread Calling a EWB procedure from HTML inside TBrowser in Compressed mode
Sat, Mar 18 2017 2:11 PMPermanent Link

A.Kyr

Hi
I am using a TBrowser inside a TForm in order to display a list of records found after a search in DB.
The reason i use a TBrowser is that it permits beautifully formatted rows with variable size, displayable fields etc. all coming ready from the webserver (custom made).
the format is like this:
-------------
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "" name="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">">http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="" name="http://www.w3.org/1999/xhtml">">http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Untitled 1</title>
<link href="DataPage.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
...
function OnMyDblClick() { window.parent.unit1_myproc(arguments[0]); }  // <===== CALL of EWB procedure
...
</script>
</head>
<body>
<table id="MYTABLE" class="BaseStyle" style="width: 100%" >
   <tr id="R001_1421"  onmouseover="OnMouseOverBox(id)"  onmouseout="OnMouseOutBox(id)" onclick="OnMyClick(id)" ondblclick="OnMyDblClick(id)" class="NormStyle1" >
   <td>
   <input type="checkbox"></td><td> 1st Returned Rec Data</td>
   </tr>
   <tr id="R002_4521" onmouseover="OnMouseOverBox(id)" onmouseout="OnMouseOutBox(id)" onclick="OnMyClick(id)" ondblclick="OnMyDblClick(id)" class="NormStyle2">
       <td><input type="checkbox"></td><td>2nd Returned Rec Data</td>
   </tr>
   <tr id="R0003_4521" onmouseover="OnMouseOverBox(id)" onmouseout="OnMouseOutBox(id)" onclick="OnMyClick(id)" ondblclick="OnMyDblClick(id)" class="NormStyle1">
       <td><input type="checkbox"></td><td>3rd Returned Rec Data</td>
   </tr>
   </table>
</table>
</body>
</html>
-----------
The containing form is defined in unit1 where a procedure MyProc(Aparam:string); is implemented and also declared in interface part.
So when the EWB application runs, when the user doubleclicks a row, OnMyDblClick is called which call the proc. MyProc (named in exported js as unit1_proc) and
pass to the EWB appl. the ROW and ID Record to be displayed.
Everything works as a charm, and i was too happy combining the formatting of HTML and Application control of EWB, BUT..
when the EWB appl. is compressed the name that my procedure is exposed is unpredictable, so i haven't the possibility to call it from the HTML inside TBrowser.

Is there any way that specific function names dont be changed when the output is compressed?
Or, otherwise, is there any better way to call a EWB appl's procedure from a HTML inside a Tbrowser?

I hope i managed to explain the question, enough well Smile
EWB used is version 2.05 with custom made WEB server.

Thanks  in advance for any hint.
Mon, Mar 20 2017 2:54 AMPermanent Link

Michael Dreher

A.Kyr wrote:

 // Is there any way that specific function names dont be changed when the output is compressed?
 // Or, otherwise, is there any better way to call a EWB appl's procedure from a HTML inside a Tbrowser?

I had to solve the same problem, but calling a JS-function from outside the TBrowser(the IFRAME). As far as I know you cannot control JS-function names in compressed mode. I use the TBrowser.ClientID property to assign a "tag" and later search the html document to find it and execute JS-code.

Michael Dreher
Mon, Mar 20 2017 7:57 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com


<< Is there any way that specific function names dont be changed when the output is compressed? >>

The only way is to turn off compression.

<< Or, otherwise, is there any better way to call a EWB appl's procedure from a HTML inside a Tbrowser?  >>

You can do so, but it requires a lot of back-and-forth in terms of external JS functions and callbacks, and isn't particularly easy to do.

In general, what you're trying to do is fighting against the design of EWB, so it's never going to be particularly easy to do.  If you want a better formatted display of rows, then you should create a custom control in EWB that handles displaying such data in the way that you wish.

Tim Young
Elevate Software
www.elevatesoft.com
Wed, Mar 22 2017 4:31 AMPermanent Link

A.Kyr

First of all, thanks for the replies

<<In general, what you're trying to do is fighting against the design of EWB, so it's never going to be particularly easy to do.  If you want a better formatted display of rows, then you should create a custom control in EWB that handles displaying such data in the way that you wish.>>

Why? EWB offers by design this feature even if it wasn’t in development’s strict definitions. It is the implementation of feature of compressing the output that invalidates it.  Is also said by you that you evaluate to expand EWB use in more “document-oriented” solutions.
Any application needs to display a list of items simply and attractively. Some times what is to be displayed, is based of many different parameters, fields etc. Isn’t practical to transfer anything to client in order to produce the display of every item using dozen of objects and without capability to calculate the size of every item. And, when you need to produce a report, write again new code -server side this time- to produce a printable PDF or HTML.
What I succeeded to do calling from html inside Tbrowser, EWB procedures/functions seems to be a real life saver where not editable tables are needed. So much, that for the moment I will even stay with uncompressed code to keep this functionality ( I use Winx and I hope that this will cope with the uncompressed output size)

**** Ask of feature:******
Please consider the possibility that specific functions keep their name even with compression. An exotic prefix could be used for them. I know that this also affects the name of unit where these functions are declared, but the user – if decides that needs this – could declare all functions needed to be externally callable in a single only unit
like this (keeping the real implementation in other units):
unit publunit;
uses ….;
procedure EWBPUBL_dosomething(astr:string);
begin
   procedure proc_dosomething(astr);
end;

so the procedure publunit_ EWBPUBL_dosomething cound be called externally.

I can’t be sure of course, but programmatically it seems to be trivial and it will unlock a serious functionality

<<You can do so, but it requires a lot of back-and-forth in terms of external JS functions and callbacks, and isn't particularly easy to do.>>
I would be grateful for an example, or at least some links for reading

Thanks in advance
Wed, Mar 22 2017 4:51 AMPermanent Link

Matthew Jones

A.Kyr wrote:

> Please consider the possibility that specific functions keep their name even with compression.

I know nothing of the compiler implementation of course, but my thinking is that it would be done using an attribute on the function definition like "override" and "virtual". Stick in "publish" and that tells the compiler not to mangle that particular name. Or rather, to allocate the name it already has as the mangled name, and then everything else is the same.

It's a technical request, but operating with other systems is going to be important. I can imagine that a graphing tool (which I know can be embedded) might want to call back to something, and it would be important to facilitate this, while not losing the protection of the compression.

--

Matthew Jones
Wed, Mar 22 2017 9:24 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com


<< Why? >>

Because EWB goes to great lengths to "fix" issues with using straight JS code against the browser DOM, and as soon as you start "working around" that you start bumping up against the issues that EWB was designed to fix.  Things like global event management, layout management, etc.  In this particular case it's not so bad because the iframe (TBrowser) keeps things separated so that the content of the iframe doesn't interfere with EWB. But, in any other context, your code would have issues with EWB.

<< EWB offers by design this feature even if it wasn’t in development’s strict definitions. It is the implementation of feature of compressing the output that invalidates it. >>

Yes, but you're over-simplifying the issue to your one particular case.  There are all sorts of problems with doing this, including restricting our ability to change the way that the emitted JS is structured.  There is already a mismatch between the class/method/property names in the emitted JS and what the Object Pascal uses, so you can't call them without knowing the internals of how the compiler emits the JS.  This means that we could break your code without you or us knowing that it was broken.  Functions and procedures are simpler, for sure, but I still wouldn't want to commit to a promise of never, ever changing how they are emitted.  Add in the fact that WASM is coming on strong, and you start to get an idea of why this is a bad idea.

<< Is also said by you that you evaluate to expand EWB use in more “document-oriented” solutions. >>

That is a completely different thing from what you're trying to do.

<< Any application needs to display a list of items simply and attractively. Some times what is to be displayed, is based of many different parameters, fields etc. Isn’t practical to transfer anything to client in order to produce the display of every item using dozen of objects and without capability to calculate the size of every item. And, when you need to produce a report, write again new code -server side this time- to produce a printable PDF or HTML.
What I succeeded to do calling from html inside Tbrowser, EWB procedures/functions seems to be a real life saver where not editable tables are needed. >>

I understand, I really do.  But, there are better solutions that don't involve calling directly into the EWB code.  2.06 has a new THTMLLabel control, and I think that something like a new OnLinkClick event might be something that can work for you.

<< I would be grateful for an example, or at least some links for reading >>

I've prepared a test project, but there are some issues with the compiler emitting callback references that I need to fix first (it has a problem when passing a callback reference as a parameter to a callback call).  I will post here with a 2.06 beta example when it's working.

Tim Young
Elevate Software
www.elevatesoft.com
Wed, Mar 22 2017 9:27 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Matthew,

<< It's a technical request, but operating with other systems is going to be important. I can imagine that a graphing tool (which I know can be embedded) might want to call back to something, and it would be important to facilitate this, while not losing the protection of the compression. >>

It has nothing to do with interoperability.

You never want to get into calling functions/procedures by name, period.  Ask anyone that's used AngularJS and they'll tell you why it's a bad idea.  Functions/procedures can be referenced via live pointers/references, and that's how they should be called.

Tim Young
Elevate Software
www.elevatesoft.com
Wed, Mar 22 2017 12:42 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Okay, you will find the example attached.  You'll need the 2.06 B8 beta in order to compile/run it properly, which I just uploaded (let me know if you need beta access).

The "meat" of the functionality is here in the example project's main unit:

  external TCallbackProc = procedure(const Msg: String);
  external TRegisterCallbackProc = procedure(callback: TCallbackProc);
  external TTestProc = procedure();

  external function getframeregistercallbackFunc(const frameId: String): TRegisterCallbackProc;
  external function getframetestFunc(const frameId: String): TTestProc;

var
  Form1: TForm1;

implementation

procedure ShowMessageCallback(const Msg: String);
begin
  ShowMessage(Msg);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  { This is the callback registration procedure reference }
  TempRegisterCallbackProc: TRegisterCallbackProc;
  { This is the procedure reference that we're going to call to trigger the callback }
  TempTestProc: TTestProc;
begin
  { Make sure to assign an ID, otherwise the rest won't work }
  Browser1.ClientID:='TestBrowser';
  { Obtain the callback registration procedure reference }
  TempRegisterCallbackProc:=getframeregistercallbackFunc(Browser1.ClientID);
  { Call the callback registration procedure with the callback }
  TempRegisterCallbackProc(ShowMessageCallback);
  { Obtain the procedure reference for the function that will trigger the callback }
  TempTestProc:=getframetestFunc(Browser1.ClientID);
  { Call the procedure to trigger the callback }
  TempTestProc;
end;

Please see the getcallback.js external JS source to see how the helper functions are declared in JS, as well as the test.html for the JS functions declared for use in the HTML that will be displayed in the TBrowser control.  EWB requires the JS helper functions because there's no way for EWB to declare an external interface for window-level, global JS methods that it doesn't know about in advance, and that's exactly what is going on when you have global functions declared in HTML that is being loaded in an iframe (TBrowser).

The TCallbackProc declaration will need to be modified to match what you want to pass back to the EWB application when the callback is triggered.  I just used a string to help show that it's working when the proper string is displayed in the EWB application.

The TestProc code would all be absent from your actual implementation.  It's only purpose is to simulate what would happen when your JS onclick event handlers trigger the callback function.

You can also do this with methods instead of functions/procedures, but it's a little more complicated and requires that you use some internal methods in EWB to create the methods with the proper instance scoping.

If you have any questions, post them here and I'll follow up.

Tim Young
Elevate Software
www.elevatesoft.com



Attachments: browsercallback.zip
Thu, Mar 30 2017 4:36 PMPermanent Link

A.Kyr

Hi Tim.
Sorry for the delayed answer but I has been out of office for a week.
Thanks very much for your extensive reply and help with the given paradeigm.
I was hesitant to ask for this, knowing it could be considered in conflict with a strict EWB way of coding.
Thanks again for your time spent for the example.
And, yes, I would like accessibility for downloading beta versions.

Best Regards

A.Kyriakos
Fri, Mar 31 2017 10:19 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com


<< And, yes, I would like accessibility for downloading beta versions. >>

You're all set now and can download the beta from the EWB Downloads page:

http://www.elevatesoft.com/download?category=ewb

Tim Young
Elevate Software
www.elevatesoft.com
Image