WebDialog on Mac (call to Google SU engineers)

WebDialog on Mac (call to Google SU engineers)

Postby fredo6 » Sun Oct 12, 2008 3:39 pm

I have been making some tests on how Web dialogs behave on Mac platform (via the kind support from Regis and Edson, as I don't have a Mac myself).

I found out that there is a big discrepancy of behavior between Windows and Mac, about the communication between Javascript and Ruby, back and forth (so execute_script and callback via window.location=skp:callback@....).

Communication Ruby <-> Javascript are Synchronous on Windows, whereas they are Asynchronous on Mac.

As a result, if on Mac you call in sequence 2 javascripts:
Code: Select all
  dlg.execute_script "document.getElementById('Field1').value = '1' ; "
  dlg.execute_script "document.getElementById('Field2').value = '2' ; "

then,
- the first Ruby statement returns even before its javascript function starts executing
- Most likely, only the second javascript function will be executed, because it will override the first one.

On Windows, it works fine. Each 'execute_script' Ruby statement will only return when the javascript function has finished execution.

The same happens in the other direction, when Javascript is calling back Ruby.
Let's say that in Ruby, you have
Code: Select all
dlg.add_action_callback("callback1") { |d, p| self.j_callback1 p }
dlg.add_action_callback("callback2") { |d, p| self.j_callback2 p }


and in the Javascript section, you have the 2 statements:
Code: Select all
window.location = 'skp:callback1@' + 'event 1'
window.location = 'skp:callback2@' + 'event 2'

then, Callback1 will never be called.

Again, all this works fine in Windows. No callback call is lost, and they are sent in the right order.

This is terribly ennoying, because it makes almost impossible to use SU Web Dialogs on Mac to built rich dialog boxes. The reason is that, to drive a rich dialog based on user actions, you'll have constantly to communicate back and forth between Javascript and Ruby, to set values of fields, or to get events (like onchange, onkeydown, ...). With nothing synchronous and many actions lost in transmission, the code will never fly.

I wanted to know:
1) if SU Developers acknowledge of this problem, or if I am not correct.
2) if there is a simple workaround or something specific to do on Mac
3) if there is a fix planned

All this is related to make sure that I can release scripts both for Windows and Mac users.

Thanks in advance

Fredo
0
User avatar
fredo6 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby RickW » Mon Oct 13, 2008 2:03 am

They have been aware of problems, but you have done a great job detailing the exact behavior. Waiting for a fix...
0

RickW 
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby ScottLininger » Wed Oct 22, 2008 8:10 pm

Hey Fredo,

As Rick said, this is a known bug to us, and a very annoying one. I wish I could say there's an easy workaround, but the behavior, I have been told via folks at Apple, is a fundamental WebKit problem. (We are still pursuing a fix.)

To answer your questions:

1. You're absolutely right.

2. There is not a simple workaround. The only way to make this work is to build your javascript code to be asynchronous. As you're probably discovering, this leads to JS code that is necessarily more complex. If you think of SU as a "server" that you're making asynchronous requests to, you can use code patterns that you might be familiar with from Ajax programming. You *can* build complex UIs this way, but it's not easy.

3. A fix for this is at the top of my personal list, but I do not expect a solution in time for SU7. No promises... but maybe we'll have a fix for an early maintenance release. Another thing we've considered is either building or working with the community to build a ruby/js bridge library that abstracts some of this, but it's just design discussions at this point.

Hope that helps. When SU7 goes live I'll be able to provide a more in depth discussion of this whole issue.

Cheers,
0
- Scott Lininger
SketchUp Software Engineer
Have you visited the Ruby API Docs?
User avatar
ScottLininger 
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby fredo6 » Wed Oct 22, 2008 9:14 pm

Scott,Welcome to the forum. It's good to hear from the SU Google team, furthermore if you are specialist of the Ruby API.For the WebDialog issue on Mac, this is because Safari (Konqueror and Webkit actually) performs all redirections in asynchonous mode (so Window.location or anchor href jumps). On Windows / IE window.location is synchronous.I am surprised however that, despite of this, SU cannot do internally what you suggest the scripters shoudl do (which will be damned complex, because Ajax works mainly with HTTP requests, meaning that I don't know too much how you can support the skp: listener ; in addition Safari is known to have major issues with Synchronous requests). I may have found a workaround which I am testing currently. If this works, I'll tell you more.Note that this is in no way for very complex web dialogs. Just think of trapping key events typed in the web dialog. With the current Mac problem, you will only receive the last event (Key Up) when you type a key, all others being swallowed.I also suggest that for SU7, even if you can't fix the problem, you explore additional verbs like ElementSetValue, because most of the execute_script are actually just to put data in HTML forms. Also, would need to have extra APIs like GetSize and GetLocation.

Again, that was a genious idea to plug Javascript and web dialog box in SU / Ruby, but the current implementation of SU6 has really so many issues that I am not sure we'll see many scripts coming with WD.Fredo
0
User avatar
fredo6 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby mocathe1st » Thu Sep 17, 2009 10:58 am

Hi All,

I've currently run into the synchronisation problem described above. The JavaScript file I have currently written is fairly simple, and only passes messages from Flash via JavaScript to Ruby. I've got a single function to take care of this. However, when I send a quick succession of messages from Flash to Ruby via JS most of the commands get lost on the Mac, this works fine on the PC.

I was just wondering if anyone found a solution to the synchronisation problem, is there a way to create a JavaScript buffer or a way of synchronising the messages?

Best Regards,
Malcolm Murray
0

mocathe1st 
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby chrisglasier » Thu Sep 17, 2009 11:42 am

mocathe1st wrote:Hi All,

I've currently run into the synchronisation problem described above. The JavaScript file I have currently written is fairly simple, and only passes messages from Flash via JavaScript to Ruby. I've got a single function to take care of this. However, when I send a quick succession of messages from Flash to Ruby via JS most of the commands get lost on the Mac, this works fine on the PC.

I was just wondering if anyone found a solution to the synchronisation problem, is there a way to create a JavaScript buffer or a way of synchronising the messages?

Best Regards,
Malcolm Murray


Please take a look at this topic which includes the following:

Also included is revisions to code to enable testing Mac compatibility, viz:

START control employed as no Sketchup.active_model with Mac when Ruby scripts are first loaded. (related post)

Code rewritten so that no window.location call is followed by any javascript statements. (related post)

Feedback from Mac users and/or coders would be much appreciated.


together with a download of an example.

I think it very important for the expansion of webdialog use to find and publish the best common solution. I don't expect the SU team has this at the top of their list.

I look forward to further discussion.

My regards

Chris
0
With JSON machines we can analyse what is to be achieved so that IT can help with automation to achieve it.
User avatar
chrisglasier 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby thomthom » Sun Nov 08, 2009 8:33 pm

chrisglasier wrote:As a result, if on Mac you call in sequence 2 javascripts:

Code: Select all
dlg.execute_script "document.getElementById('Field1').value = '1' ; "
dlg.execute_script "document.getElementById('Field2').value = '2' ; "


then,
- the first Ruby statement returns even before its javascript function starts executing
- Most likely, only the second javascript function will be executed, because it will override the first one.

On Windows, it works fine. Each 'execute_script' Ruby statement will only return when the javascript function has finished execution.

I've been doing some tests on OSX, using the console. First I create a new WebDialog object:
Code: Select all
w=UI::WebDialog.new('test', true)
w.set_html('<html><body>Hello</body><html>')
w.show

Then I try with a loop to send lots of .execute_script commands.
Code: Select all
w.execute_script('document.body.innerHTML="";')
(0..100).each{|i| w.execute_script('document.body.innerHTML="<br>Hello #{i}";') }

When I run the script, it adds all the lines "Hello 1" to "Hello 100" - not a single .execute_script is lost...
Also, the ruby method did not return until it was all done.
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby thomthom » Sun Nov 08, 2009 8:47 pm

Testing the other way - making a loop in the Javascript to do 100 window.location = 'skp:callback' and I only register the last callback. All the rest appear to have been suppressed. I only see the async going from the WebDialog to Ruby. Not the other way around.
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby thomthom » Sun Nov 08, 2009 8:52 pm

Here's a sample code I used to test:
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby thomthom » Sun Nov 08, 2009 9:22 pm

I improved the test. Now the Ruby to WebDialog method creates a new DIV element every time, and it insert the DIV into the last inserted DIV. So if the calls are synchronous - all the elements should be nested.

On both PC and OSX - the elements are nested. It still appears to me that it's just the Webdialog to Ruby path that's async. Which means it's related to window.location.
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby jeff hammond » Sun Nov 08, 2009 9:47 pm

i have no idea what you're actually talking about thomas but i'm glad you are :D :thumb:
i fear the day of a great plugin coming out only to hear this once again : "sorry, pc only"
0
dotdotdot
User avatar
jeff hammond 
Global Moderator
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby chrisglasier » Mon Nov 09, 2009 2:07 am

thomthom wrote:window.location


Yes that's the culprit as I understand what Fredo said and you have demonstrated (to yourself).
0
With JSON machines we can analyse what is to be achieved so that IT can help with automation to achieve it.
User avatar
chrisglasier 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby thomthom » Mon Nov 09, 2009 8:33 am

chrisglasier wrote:
thomthom wrote:window.location


Yes that's the culprit as I understand what Fredo said and you have demonstrated (to yourself).

No, he also described .execute_script to be async - which I can't see. From my tests it returns after the Javascript is done, not before.
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby fredo6 » Mon Nov 09, 2009 8:00 pm

thomthom wrote:
chrisglasier wrote:
thomthom wrote:window.location


Yes that's the culprit as I understand what Fredo said and you have demonstrated (to yourself).

No, he also described .execute_script to be async - which I can't see. From my tests it returns after the Javascript is done, not before.

Tom,

There are 2 issues which all boil down to the problem of windows.location being asynchronous.

1) when you execute a script that should call a Ruby call back, the script returns before the call back is executed. This is unfortunately a design problem due to Safari, which I understand the SU team cannot do anything about easily.

2) in addition, the skp protocol eats up all callbacks and keep the last one, when sent in sequence. So you simply miss some callbacks, even if they were to be recieved asynchronously. This is a problem of implementation by the SU team (it would have deserved a buffering).

I had to find workarounds for both problems in my web dialog implementation in LibFredo6, precisely by buffering the callbacks in a hidden HTML field and synchronizing the Ruby code.

If I have some time, I will check if I could isolate the code for reuse by others. No promise however.

Fredo
0
User avatar
fredo6 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby thomthom » Mon Nov 09, 2009 8:18 pm

Fredo6 wrote:1) when you execute a script that should call a Ruby call back, the script returns before the call back is executed. This is unfortunately a design problem due to Safari, which I understand the SU team cannot do anything about easily.

Ah, ok. So the .execute_script is synchronous then. It's just the Javascript to Ruby callback (the skp: protocol) that's async.

So it's then safe to call .execute_script which calls a javascript method that stores the return data in a hidden input field where you then use .get_element_value to return data, correct? This is what I see from my testing - but I just want to make sure I'm not missing some cases here.
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby fredo6 » Mon Nov 09, 2009 9:12 pm

thomthom wrote:So it's then safe to call .execute_script which calls a javascript method that stores the return data in a hidden input field where you then use .get_element_value to return data, correct? This is what I see from my testing - but I just want to make sure I'm not missing some cases here.

Correct. This is what should be done to solve problem #1.
Can you confirm however, because it's been a while since I did not work on Web dialogs, and I don't want to mislead anybody.

Fredo
0
User avatar
fredo6 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby thomthom » Mon Nov 09, 2009 9:49 pm

I've tried with loops of .execute_string followed immediately by .get_element_value where I call a Javascript function to modify an argument I pass to it and fetch the result with .get_element_value. Works fine on PC and OSX.

Code: Select all
// #bar is a hidden INPUT element
function foo(i)
{
  document.getElementById('bar').valie = i * i;
}


Code: Select all
(2..10).each { |i|
  dialog.execute_script("foo(#{i});")
  x = dialog.get_element_value('bar')0
  puts "i: #{i} - x: #{x}"
}


This seems to work fine.
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby RonB » Tue Apr 10, 2012 1:12 pm

Sorry for exhuming this thread, but is there a workaround available now?
Actually i'm facing the same problem as described here and its totally driving me nuts.

I'm hoping for good news.
0

RonB 
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby thomthom » Tue Apr 10, 2012 1:39 pm

Depends on what you are doing.

One way is to make SketchUp pump for information instead of Javascript pushing information.

Another way, if you need Javascript to push information is to set up a pump-system. You create a stack (an array) of the callbacks from JS to SU you want to perform. A function then takes the first item on the stack and send it to SketchUp. It then waits for SketchUp to send notification back that the message was received. Then the next item on the stack is sent ... and so on.

It requires you to restructure how you pass the information around.

If you give a specific usage example we could probably come up with suitable design.
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby RonB » Tue Apr 10, 2012 2:38 pm

hey thomthom, thanks for your quick response.

I do have a website providing two informations for sketchup

1) the actual needed version of the plugin (provided by hidden input field)
2) a stream (string) of informations (provided by hidden input field)

1) needs to be checked directly when the webdialog loads the site and 2) when a button is clicked (because it can be chosen which set of informations to load).

Actually it is working on a PC but not on a Mac.
The Website contains both window.location skp callbacks but the second one is only triggered by button.
0

RonB 
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby thomthom » Tue Apr 10, 2012 4:09 pm

That sounds like you are sending back before the HTML DOM is ready. If you use jQuery use the 'ready' event to wait for the HTML DOM to be ready.

How have you currently structured the loading event?
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby RonB » Wed Apr 11, 2012 7:09 am

I guess you're right... i do have the skp callback somewhere in between of the page.
I'll try to change it to jquery with the "wait for doc ready"-function and report back here.

to answer your question: I'm creating a webdialog and connect by set_url to an url.
Then i'm showing the dialog and wait for the callbacks.
I hope that's what you was asking.
0

RonB 
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby Aerilius » Sat Mar 23, 2013 3:46 pm

I again stumbled across this issue, knowing JavaScript continues before the Ruby callback ends, but I didn't think that this async nature prevents subsequent urls to reach Ruby.

Example of the Problem:
Code: Select all
w = UI::WebDialog.new("Test")
w.add_action_callback("1"){|dlg, param| puts("first callback")}
w.add_action_callback("2"){|dlg, param| puts("second callback")}
w.set_html("<html><body><script>window.location='skp:1'; window.location='skp:2';</script></body></html>")
w.show

On Windows:
> first callback
> second callback

On OSX:
> second callback

Example solution:
Doesn't make anything synchronous, but makes sure all urls reach Ruby.
Code: Select all
/* class Scheduler:
 * This class makes sure given functions are not called more frequently than a
 * certain time limit.
 * .queue(function)
 *     Adds a new function. All collected functions will be executed one by one with a time interval inbetween.
 */
Scheduler = function(dt) {
  var scheduled = []; // Array of scheduled functions.
  var t = 0; // Tracks the time of the last function call.
  dt = (dt) ? Number(dt) : 250; // Minimum time interval in milliseconds between subsequent function calls.
  this.queue = function(fn) {
    scheduled.push(fn);
    check();
  };
  var run = function() {
    var toRun = scheduled.shift();
    toRun();
  };
  var check = function() {
    var c = Number(new Date().getTime());
    // Last function call is long enough ago (or first time), execute given function immediately.
    if (c > t && scheduled.length > 0) {
      run();
      // Set timer for next possible function call.
      t = c + dt;
      window.setTimeout(check, dt);
    }
  };
};


/* An instance of the Scheduler */
var callRubyScheduler = new Scheduler(1);


/* Function to call a SketchUp Ruby action_callback. */
var callRuby = function(name, data) {
  if (!data) { data = ''; }
  var url = 'skp:' + name + '@' + encodeURIComponent(data);
  callRubyScheduler.queue(function(){ window.location.href = url; });
};

On Windows:
> first callback
> second callback

On OSX:
> first callback
> second callback
0

Aerilius 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby thomthom » Sun Mar 24, 2013 11:15 am

Another way, that doesn't involve timing is to stack up messages in JS that call a receiving ruby method which takes care of forwarding to the correct ruby method and then send a ping back to JS which can then send the next message in the queue.

I made a version like that which also gives JS a return value from ruby.

Sent from my LT25i using Tapatalk 2
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: WebDialog on Mac (call to Google SU engineers)

Postby jolran » Sat Mar 30, 2013 9:40 am

Ahh, missed this addition to this rather old topic. Interesting reading.

Might be relative to Didier's recent topic.
viewtopic.php?f=180&t=51350

I wonder if I could get some clarification about this:
For ex, let say you have a dozen buttons that each is hooked up to it's own callback to Ruby with "window.location.href" for the callback.

Even if the Ruby script is permitted to "finish" it's doing before pushing the next buttons, will there be a sync problem ?

I'm having a hard time understanding how this issue behave since I don't have a Mac for testing it out myself.

It seams like Arielius has a clever solution, but what if for ex one has a slider performing realtime transformation or such ?
0
User avatar
jolran 
PluginStore Author
PluginStore Author
 

SketchUcation One-Liner Adverts

by Ad Machine » 5 minutes ago



Ad Machine 
Robot
 



 

Return to Developers' Forum

Who is online

Users browsing this forum: No registered users and 5 guests

Visit our sponsors: