Webdialog callback produces inconsistent result

Hi,

to update the state of my JavaScript (ReactJs) app inside my WebDialog, I registered a function window.setState(items) that handles the update of the current state. I’ve registered a callback to reload which executes this method:

@dlg.add_action_callback('reload') do |dialog, _value|
  puts 'reload cb'
  @journal.reload
  command = 'window.setState(' + @journal.items.values.to_json + ')'
  puts command
  dialog.execute_script command
end

I also have a separate ruby method, which I use to trigger the reload from somewhere in my plugin (or console). It’s essentially the same.

def self.update
  @journal.reload
  command = 'window.setState(' + @journal.items.values.to_json + ')'
  puts command
  @dlg.execute_script command
end

Now when my callback is executed, it puts the command in the console, and calls the JS function, but it returns early, but I’m not sure what is going on (debugging the Webdialog is a pain in the ass). When I call my update method, it prints the exact same command to the console, but does everything it’s supposed to do, without an error.

Why might this happen?

Seems weird. Perhaps the block parameter dialog is not right ?
What platform Mac or PC ?
What browser version of Safari or MSIE ?
What SketchUp version ?

Does this work any better from inside the callback block (which I think gets converted to a Proc object.) ?

Ie, change the do & end, to { and }. They create blocks with different visibility.
Your do block may not “see” the @journal ?

@dlg.add_action_callback('reload') { |dialog, _value|
  puts 'reload cb'
  @journal.reload
  command = 'window.setState(' + @journal.items.values.to_json + ')'
  puts command
  dialog.execute_script command
}

IF that does not work, try:

@dlg.add_action_callback('reload') { |dialog, _value|
  puts 'reload cb'
  @journal.reload
  command = 'window.setState(' + @journal.items.values.to_json + ')'
  puts command
  @dlg.execute_script command # <---<<<< use @dlg reference
}

On a sidenote, it’s better to combine common code:

@dlg.add_action_callback('reload') do |dialog, _value|
  puts 'reload cb'
  self.update()
end

Off-Topic, FYI:

command = 'window.setState(' + @journal.items.values.to_json + ')'

… creates 5 String objects, whereas:

command = %[window.setState(#{@journal.items.values.to_json})]

… creates only 2, stuffing the json string inside the command string.

Why call upon the window object ?
Access to the window object is severely limited in the MS WebBrowser Control.

What happens if you call document.setState(json) instead ?

Or just plain setState(json) ?

Did you define the JS function under some namespace ? or is it global to the document ?

are you using Firebug Lite or Web Inspector inside SU?

if you dev on a mac, setting a global preference for Web Inspector is the easiest way…

 defaults write NSGlobalDomain WebKitDeveloperExtras -bool true

‘Inspect Element’ will then be a Right Click option in ‘most’ WebDialogs…

if your using iFrames, you may need an input field to right click in…

for Firebug Lite you add a link in the head of your html page…

john

1 Like

Bliss,

Ok, I’ve been away from plugins for a while, but I still look at the forum every so often.

Try and wrap your callbacks from js => ruby in setTimeout calls. I recall some behavior differences (between Windows and OSX) as to what blocks what and where. You may need a closure. Most of the time, the few milliseconds that a setTimeout takes isn’t an issue.

Also, re some comments in this thread, window is to js as Kernel is to Ruby. If a js function is declared globally, window.someFunction() is the same as someFunction(), assuming you’re in a ‘browser’ environment and no one has redefined window…

Greg

After countless attempts at debugging the problem, I’ve found a problem on the JavaScript side. Now all is good, sorry for the trouble.