# Update webdialog without user interaction

**URL:** <https://forums.sketchup.com/t/update-webdialog-without-user-interaction/8478>\
**Category:** Ruby API\
**Created:** [March 14, 2015, 7:10am UTC](https://forums.sketchup.com/t/update-webdialog-without-user-interaction/8478 "2015-03-14T07:10:22Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![prz87](https://avatars.discourse-cdn.com/v4/letter/p/5e9695/32.png) [@prz87](https://forums.sketchup.com/u/prz87)\
**Post date:** [March 14, 2015, 7:10am UTC](https://forums.sketchup.com/t/update-webdialog-without-user-interaction/8478/1 "2015-03-14T07:10:22Z")

</div>

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.

Thanks you for your valuable time

---

<div class="post-metadata">

**Author:** ![Aerilius](https://avatars.discourse-cdn.com/v4/letter/a/e19b73/32.png) [@Aerilius](https://forums.sketchup.com/u/Aerilius)\
**Post date:** [March 14, 2015, 12:16pm UTC](https://forums.sketchup.com/t/update-webdialog-without-user-interaction/8478/2 "2015-03-14T12:16:10Z")

</div>

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.

```auto
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

```

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [March 14, 2015, 7:31pm UTC](https://forums.sketchup.com/t/update-webdialog-without-user-interaction/8478/3 "2015-03-14T19:31:49Z")

</div>

Even more simple, just rewrite the html with the new values.  
It happens so fast the user will never see the blanking.)

```ruby
  def update_html(dims)
    @html = %Q{
      <html>
        <head>
        </head>
        <body>
          <br/>
          Thickness: #{dims[0].to_s}<br/>
          Width: #{dims[1].to_s}<br/>
          Length: #{dims[2].to_s}<br/>
          <br/>
        </body>
      </html>
    }
  end # update_html()

  def show_html(dims)
    update_html(dims.sort)
    @dlg = UI::WebDialog.new("Dims")
    @dlg.set_html(@html)
    RUBY_PLATFORM !~ /darwin/ @dlg.show : @dlg.show_modal
  end

  def update_dims(dims)
    update_html(dims.sort)
    @dlg.set_html(@html)
  end

```

Call `show_html(dims)` to initially show the dialog.  
Then reset the dialog’s html with new values by calling the `update_dims(dims)` method.

---

<div class="post-metadata">

**Author:** ![prz87](https://avatars.discourse-cdn.com/v4/letter/p/5e9695/32.png) [@prz87](https://forums.sketchup.com/u/prz87)\
**Post date:** [March 17, 2015, 1:42am UTC](https://forums.sketchup.com/t/update-webdialog-without-user-interaction/8478/4 "2015-03-17T01:42:18Z")

</div>

Hi @Aerilius Thanks for the quick response! Just a quick question though,

I am getting the

> Error:#NoMethodError: undefined method `execute\_script’ for nil:NilClass

when I call the

> …  
> js\_command = “passedFromRuby(‘#{dimensions[0]}’,‘#{dimensions[1]}’,‘#{dimensions[2]}’)”

> @dashboardDialog.execute\_script(js\_command)

Also where do I specify the location with the skp query? onload of html body?

```
  query = 'skp:get_data@' + actionName;
  window.location.href = query;

```

Do I even need it?

Thanks for your help!

---

<div class="post-metadata">

**Author:** ![Aerilius](https://avatars.discourse-cdn.com/v4/letter/a/e19b73/32.png) [@Aerilius](https://forums.sketchup.com/u/Aerilius)\
**Post date:** [March 17, 2015, 11:39am UTC](https://forums.sketchup.com/t/update-webdialog-without-user-interaction/8478/5 "2015-03-17T11:39:14Z")

</div>

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`.

> [@prz87](#):
>
> Do I even need it?

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:

```auto
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.

```auto
# JavaScript
AE.Bridge.callRuby('callbackName', 'some arguments', 81, 
  function(returnValue) { 
    /* callback */
})
# Ruby:
@dialog.call_function('functionName', ['stringArgument', 42], {'key' => 'value'})

```

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.
