Another way for Htmldialog get_element_value. Need Help

:warning: Changed the name of get_element_value() to request_element_value()
because there is no way to receive synchronous values from JS in the UI::HtmlDialog class.

This is example code. No copyright intended nor warranty implied.

# Ruby
module MyTopLevelNamespaceModule::MyExtensionModule

  class ChromeDialog < ::UI::HtmlDialog

    def initialize(*args)
      super
      @values = {}
      set_on_closed() # no block argument uses default block !
      self
    end

    def attach_callbacks
      add_action_callback('receiveValue') do |not_used,id,val|
        receive_value(id,val)
      end
      # ... Add more callbacks here as needed ...
    end

    def request_element_value(id)
      return unless id.is_a?(String) || id.respond_to?(:to_s)
      execute_script("sendValue('#{id}');")
    end

    def receive_value(id,val)
      @values[id]= val
      process_value(id)
    end

    def process_value(id)
      # Do something with @values[id]
    end

    def process_values
      @values.keys.each { |id| process_value(id) }
      @values
    end

    def set_file(*args)
      super
      self # allows chaining
    end

    def set_html(*args)
      super
      self # allows chaining
    end

    def close(*args)
      super # call close() in UI::HtmlDialog superclass
        # If a set_can_close() block is defined and returns true then ...
          # Any set_on_closed() block would run here ...
          # The CEF window would close here ...
      unless @internal_reference.nil?
        # Wait a bit for the window to close
        sleep(0.5)
        # Release the internal reference if the window was closed:
        @internal_reference = nil unless self.visible?
        # If the instance is not externally referenced then Ruby GC
        # can destroy the unreferenced object next time it runs.
      end
      self # allows chaining
    end

    def set_on_closed(&block)
      if block_given?
        super Proc::new {
          block.call
          @internal_reference = nil
        }
      else # default block to release internal reference:
        super { @internal_reference = nil }
      end
    end

    def show(*args)
      if self.visible?
        self.bring_to_front
      else
        attach_callbacks()
        @internal_reference = self # backup reference whilst dialog is open
        super
      end
      self # allows chaining
    end

    def show_modal(*args)
      return self if self.visible?
      attach_callbacks()
      @internal_reference = self # backup reference whilst dialog is open
      super # this is a modal call !
      self # allows chaining
    end

  end # dialog subclass
end # extension module
// JavaScript:
function sendValue(id) {
  sketchup.receiveValue( id, document.getElementById(id).value );
}

EDIT: Added process_values iterator method.

2 Likes