I have a requirement wherein I need to update a WebDialog , using the onSelectionBulkChange listener. basically it just needs to print out the selected entity’s dimensions.
Currently I need to manually click an ‘update’ button on the web-dialog to show any change in a entity’s dimensions since it’s required to provide a callback.
Can someone please point me a way to update the dialog, without having to click on the update button. i.e. update the dialog in realtime.
Think less complicated…
To update a webdialog you don’t use callbacks but WebDialog#execute_script(String). Previously you have been triggering this method by a callback from the button, but you don’t need to. Here, you want to trigger execute_script from the observer.
class MySelectionObserver < Sketchup::SelectionObserver
# Give the observer a contact so it knows where to send callbacks to!
def initialize(tool)
@tool = tool
end
def onSelectionBulkChange(selection)
# Just tell your tool about the change. Keep the implementation datails
# on how to process this data in your tool's class.
@tool.refresh(selection.to_a)
end
end
class MyTool
def initialize(model)
@model = model
# Pass to the observer the instance of this tool,
# so that the observer can call methods of this tool.
observer = MySelectionObserver.new(self)
@model.selection.add_observer(observer)
# Create the dialog.
@dialog = UI::WebDialog.new()
# …
end
def refresh(entities)
# Call a JavaScript method on the webdialog to accept the new data.
# just some example data (array of strings)
entity_types = entities.map{ |e| e.typename }.uniq
@dialog.execute_script('MyTool.refresh(#{entity_types.inspect})')
end
end
The NoMethodError says that execute_script was called on a variable that has the value nil. Check your source code to ensure WebDialog has already been instantiated and assigned to @dashboard_dialog.
Depends on for what you need it… If you don’t know for what you need it for this task, you probably don’t need it. If you follow Dan’s suggestion and rewrite and set the html, or if you pass all the new data via execute_script, you don’t need it.
It is not a good idea to use bare-bone window.location.href = 'skp:… because that low-level “API” is cumbersome (ugly) and achieves only that these couple of lines of low-level code are repeatedly spread over your source code, and it becomes hard to maintain.
Everyone is building their own solutions over and over again. Instead it would be better to re-use existing libraries (see thomthom’s and my extensions). Maybe we should again start efforts to either get a proper API from SketchUp or an officially endorsed and library that is promoted over the ‘skp’ way.
What you can do is at least to abstract the exact implementation it into a function, like:
function callRuby (callbackName, parameter) {
var query = 'skp:' + callbackName + '@' + parameter;
window.location.href = query;
}
…and then callRuby('get_data', 'something'). The existing libraries simplify this even more by handling conversion of arguments and serialization to a string query, allowing any amount of arguments, and optional direct callback mechanisms.
Also take care of variable scope in JavaScript: Everything variable that you forgot to initilize with var is global and not limited to the function scope in which it is used.