Calling methods in javascript through ruby

Try defining the test function in the header section of your html.
Currently it’ll only return 1 when run as the document loads ?

“Show the dialog” string is not printed though dialog is shown.

Still that is not working.

You are right. It works for WebDialog. Replacing HtmlDialog with WebDialog works.
d = UI::WebDialog.new()
But the reason of using HtmlDialog was because WebDialog is deprecated.
Also there is difference in UI shown with same piece of html.

HtmlDialog is asynchronous (as WebDialog always was on Mac) and has different API than WebDialog. You can’t just substitute one for the other and expect it to work!

Both WebDialog and HtmlDialog has execute_script method mentioned in their docs.
I have not used any method that is not the part of documentation.

as I said before, this can only be used in WebDialogs not HtmlDialogs…

john

The callback syntax/params is different between the two types: see the example code…
Class: UI::HtmlDialog — SketchUp Ruby API Documentation

This works with both Web- and Htmldialogs.

The reason it is not working in this particular case, is that TS is executing the function directly after calling the show method. Ruby is not waiting untill the page is loaded, thus it’s calling something that doesn’t exist yet.

I’m pretty sure that if you first copy-paste this in the Ruby console:

d = UI::HtmlDialog.new()
d.set_html(%[<!DOCTYPE html>
<html>
   <head>
      <link rel="stylesheet" href="./../css/style.css" type="text/css" />
      <title>Test</title>
   </head>
   <body>
      <fieldset>
	       <legend>Scale</legend>
         <div id="slidecontainer">
         <input type="range" min="0.01" max="100" value="1" class="slider" id="scale_slider" step="0.01">
         </div>
         <input id="scale_input" onfocus="select_text(this.id);" size="7" value="0"/>
      </fieldset>
      <script>
        function test(value) {
          var slide_amount = document.getElementById("scale_input");
          slide_amount = value;
          window.location='skp:test@' + value;
        }
      </script>
   </body>
</html>
])
d.add_action_callback("test") do |wd, p|
    puts "Test Successful"
end
d.show

and then, when you see the dialog, copy-paste this in the console:

d.execute_script('test(1);')

you’ll get the expected result.

The reason this will work is:
By the time you have copy-pasted the second script in the console, the html page will be fully loaded and the test function will be available.

@kengey It works in console.
@TIG - instead of
window.location='skp:test@' + value;
according to doc I should use
sketchup.test(value) even then it does not work

Maybe I wasn’t clear in my response.
The solution is:
Wait for the dialog to be fully loaded prior to calling functions on it from Ruby.
How do you know a page is loaded? Well, let the page call a Ruby callback when it does.
This link might inspire you.

Thanks @kengey. It really solved my problem.
I am new to javascript and ruby. Learned a new thing.
Thanks all for helping me out

Glad it helps.
We all were new at some point.

Js

function test(value) {
   sketchup.test(value)
}

Ruby

d.add_action_callback("test") do |wd, p|
    puts "Test Successful"
end

If instead of
d.execute_script('test(1);')
i pass string or literal in test method
d.execute_script('test(a);')

then test method is not executed in js/ruby. How do pass string or literals from ruby or am i doing something funny here ?

Yes, you are telling Javascript to pass the object referenced as "a" to the js function test(), which is likely raising a JS error, but you don’t see it unless you have the debugger open.

Learn about string literals …

http://ruby-doc.org/core-2.0.0/doc/syntax/literals_rdoc.html

d.execute_script('test("a");')

or

d.execute_script("test('a');")

or

d.execute_script(%[test("a");])

or interpolate some value from a Ruby object reference …

d.execute_script(%[test("#{some_ruby_variable}");])

Thank you.

1 Like

How could I pass json string to javascript?
I tried escaping the quotes but it does not work.

str = [{"org_id"=>54, "org_name"=>"", "creator"=>"Noone", "role"=>"admin", "projects"=>[{"project_id"=>310, "name"=>"26Dec", "description"=>""}]}]

d.execute_script(%[test("#{str}");] #Does not work

This is because your str object above is defined as an Array with 1 member, which is a Hash, which has several key/value pairs, the last of which is "projects", whose value is an Array with 1 member, which is a Hash.

IT is not yet a JSON string.

To use JSON functionality, you normally need to …

require "json"

… but I think SketchUp loads it up at startup anyway,…
but you should still “require” it so as to declare a dependency.

Then to produce a JSON string that you wish to send to a HtmlDialog, to produce a JS Object (which is similar to a Ruby OpenStruct,) or a JS Array, you start on the Ruby side with a Hash or OpenStruct, or a Ruby Array

hash = {
    "org_id"=>54,
    "org_name"=>"",
    "creator"=>"Noone",
    "role"=>"admin",
    "projects"=>[
      {"project_id"=>310, "name"=>"26Dec", "description"=>""}
    ]
  }

# Create the JSON string ...
json_str = hash.to_json # uses double quotes

# Pass the JSON string to a web dialog ...
dialog.execute_script(%[set_projects('#{json_str}');] 

… then on the JS side something like … (untested)

// JavaScript global variable
var ProjectList = null;

function set_projects( json_str ) {
    ProjectList = JSON.parse(json_str);
}

function task() {
    if (ProjectList.org_id == 54) {
        // do some task
        if (ProjectList.projects[0].project_id == 310) {
            // Hey we are getting somewhere ...
        }
    }
}

So, it is important to realize that Ruby Arrays are converted to JS Arrays, …
and Ruby Hashes converted to JS Objects. (This is why is is called JavaScript Object Notation.)

Then when you get JSON strings back from a webdialog and wish to convert back to Ruby …

hash = JSON::load(json_str)

… or simply use the “smart” JSON::[] method …

hash = JSON[json_str]

RUBY REFERENCES

The JSON library module

JAVASCRIPT REFERENCES:

http://www.json.org/

The JS Object object

The JSON Object

Thanks @DanRathbun.
For converting to hash I have used JSON.parse(str) and then to_json on top of it as you suggested.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.