Webdialog data into Ruby

Hello,

I have a question about getting info out of a webdialog. I have a ruby UI menu but it’s looking a bit basic. So i want to use a webdialog. The only thing i need to know is to get data into ruby. So in this example x should be the result from myTextInput

Thanks.

@dialog = UI::WebDialog.new
path = Sketchup.find_support_file "1.html", "Plugins"
@dialog.set_file path
@dialog.get_element_value("myTextInput")
@dialog.show

#Result
x = text??
<html>
<body>

<!-- Location of the third vertex -->
Text:
<input type="text" id="myTextInput" value="hello"/>
</body>
</html>

(1) You need to pass the correct amount of arguments to the UI::WebDialog constructor method, ie, new().

(2) Your files need to be in a sub-folder of the “Plugins” folder.

(3) You cannot call functions upon a browser frame until it is shown and exists.

(4) Create a callback for the dialog on the Ruby side that is called when the <input> element is updated.

@dialog.add_action_callback("text_was_input") {|d,id|
  @text = @dialog.get_element_value(id)
}

(5) Then in your html page you need some JavaScript to signal the ruby side that input has occured:

And add a attribute to the <input> element ie: oninput="input_ready(this.id);"

So the html:

<!DOCTYPE html>
<html>
    <head>
        <script>
            function inputReady(id) {
                window.location = "skp://text_was_input@"+id
            }
        </script>
    <head>
    <body>
        <!-- Location of the third vertex -->
        <div>Text:
            <input type="text" id="myTextInput" value="hello" oninput="inputReady(this.id);"/>
        </div>
    </body>
</html>

Ok thanks.

Is this also the way with buttons? So when clicked, value is true.

That is the last thing I need to know how the communication between sketchup and html works.

ok this is what i have but no text result. Tried with some changes but nothing happens after clicking the button

Thanks

@dialog = UI::WebDialog.new()
path = Sketchup.find_support_file "Tekst/1.html", "Plugins"
@dialog.set_file path
@dialog.show

@dialog.add_action_callback("text_was_input") {|d,id|
  @text = @dialog.get_element_value(id)
}
<!DOCTYPE html>
<html>
    <head>
        <script>
            function inputReady(id) 
	    {
                window.location = "skp://text_was_input@" + id;
            }
        </script>
    <head>
    <body>
        <!-- Location of the third vertex -->
        <div>Text:
            <input type="text" id="myTextInput" value="hello" oninput="inputReady(this.id);"/>
<input type="Submit" onclick="inputReady(id);"
value="Get text" />
    </body>
</html>

First, the callback is already called everytime you change the value of the input field (oninput fires the function on every input). Second, when you added the button, you added the inputReady(id) function to the onclick event, but id is undefined. In this case, you can hardcode the input field associated with the button like this:

<input type="Submit" onclick="inputReady('myTextInput');"

You bring to my mind the fact that unless you have a debugger active or an on error handler, javascript will fail silently on this kind of error with no indication of what went wrong.

1 Like

@vanlion, You need to use "inputReady(this.id);"

In JavaScript, this refers to the current object.

2nd: <input type="Submit", this is more normally used inside a <form> element.
As Sven says, you are firing two (2) events when the text field changes.

Choose either one way or the other. Either fire a value read when individual fields change, or make the user click a “Submit” button, and read all of the input fields.

You likely need to run through a tutorial on JavaScript.

Thanks everyone.

Made some progress.

But what i was wondering how to add a datalist, found some codes but i don’t know how to use the chosen value.

What i’m looking for is a drop datalist ` that can set the value for “Kolom” see code line underneath. at the bottom the code that is already working for input box (text)

Thanks.

@defn.set_attribute( 'dynamic_attributes', '_type_formula', "#{"Kolom"}" )
      def kolom

         @mod = Sketchup.active_model
         @ent = @mod.active_entities
      
         @Length = 8000.mm unless @Length
         @Width = 10000.mm unless @Width
         @Height = 3000.mm unless @Height
         @Breedte = 4000.mm unless @Breedte
         
         @X = 0.mm unless @X
         @Y = 0.mm unless @Y
         @Z = 0.mm unless @Z

         @dlg=UI::WebDialog.new("Entresolvloer", false,"WDID",1000,1100,200,200,true)
         html = <<-HTML
         <html>
            <head>
               <meta charset="utf-8" />
            </head>
            <body>
               <form action='skp:box@'>
                  <fieldset>
                     <legend style='font-size:125%;color:blue'><b> Invoer gegevens </b></legend>
                     <table style='font-size:100%'>
                        <tr><td align='left'>Breedte vloer:</td>
                        <td><input name='Length' type='text' value='#{@Length}' size=5/></td></tr>
                        <tr><td align='left'>Diepte vloer:</td>
                        <td><input name='Width' type='text' value='#{@Width}' size=5/></td></tr>
                        <tr><td align='left'>Hoogte bovenzijde:</td>
                        <td><input name='Height' type='text' value='#{@Height}' size=5/></td><tr>
                        <tr><td align='left'>Stramienmaat in de breedte:</td>
                        <td><input name='Breedte' type='text' value='#{@Breedte}' size=5/></td><tr>
                     </table>
                     </fieldset>
                 <center><input type="image" src="C://Users/techniek/AppData/Roaming/SketchUp/SketchUp 2016/SketchUp/mp.jpg" alt="maken" width="120" height="80"/></center>
               </form>
          </body>
         </html>
         HTML

         @dlg.set_html(html)
         
         @dlg.add_action_callback("box") {|d,p|
            p.gsub!("?",""); tokens=p.split("&"); puts p
            tokens.each{|t|
               var,val = t.split("="); puts t
               case var
                  when 'Length' then @Length = val.to_l
                  when 'Width' then @Width = val.to_l
                  when 'Height' then @Height = val.to_l
                  when 'X' then @X = val.to_l
                  when 'Y' then @Y = val.to_l
                  when 'Z' then @Z = val.to_l
               end
            }

            @mod.start_operation "Place Kolom"
 
            model = Sketchup.active_model
            @def = model.definitions
            componentdefinition = @def.load ( "Z:/Algemeen 2016/Systeemvloeren/Tekeningen/Sketchup/Enkelzijdige kolom C350.skp" )
            @defn = componentdefinition 
            @defn = model.active_entities.add_instance( @defn, [@X,@Y,@Z] )  
            @defn.set_attribute( 'dynamic_attributes', '_lenz_formula', "#{@Height*2.54}" )
            @defn.set_attribute( 'dynamic_attributes', '_type_formula', "#{"Kolom"}" ) 
            dcs = $dc_observers.get_latest_class
            dcs.redraw_with_undo(@defn)
            
            @mod.commit_operation
         };
         
         RUBY_PLATFORM =~ /(darwin)/ ? @dlg.show_modal() : @dlg.show();
         
      end
kolom

You need to learn JavaScript if you are going to write WebDialogs.

There are plenty of tutorials on the Internet.

Start here: http://www.w3schools.com/

That line is of no help at all to us. We have no idea what kind of data it should be, nor what the choices in the droplist are.

In HTML this is likely a <select> element.

You mentioned a <datalist> element, which is not really necessary, and not supported by MSIE until version 10. (SketchUp by default is currently setting MSIE browser emulation in WebDialogs to v 9.)

So just use <select> with nested <option> elements.

You need to assign an ID attribute to the <select> element and have a function that fires when for it when it changes, ie:

(HTML)

<select id="this_drop_list" onchange="sendKolomChoice(this.id);">
    <option value="this.text;">200.mm</option>
    <option value="this.text;">300.mm</option>
    <option value="this.text;">400.mm</option>
    <option value="this.text;">500.mm</option>
    <option value="this.text;" selected>600.mm</option>
</select>

And in your <script> element (usually in the <head> element,) you need a function that iterates the specific options collection, of that droplist <select> element:

(JAVASCRIPT)

function getKolomChoice( list ) {

	var opts = list.options;
	
	if (opts.length>0) {
		// Iterate the options collection...
		for (i=0; i< opts.length; i++) {
			// ...searching for the 1st selected option:
			if (opts(i).selected == true) {
				return opts(i).value;
			}
		}
		// If we get here, just return the first option:
		return opts(0).value;
	} else {
		// Value to return if no options loaded:
		return "0";
	}
}

function sendKolomChoice( DropListID ) {
	
	var list = document.getElementById(DropListID);
        window.location = "skp:callback_name@"+getKolomChoice(list);
}

Thanks Dan,

I know the websites you show me, very helpfull and most part i understand.

The code you gave i also understand but not the part to get the result in a code like i said:

@defn.set_attribute( 'dynamic_attributes', '_type_formula', "#{"????"}" )

??? is result datalist

If i know that i have everything to transform the ruby menu to Webdialog

So, … what is it’s Ruby class ? … a String ?

If so, then if the reference name for it is result, then simply do:

@defn.set_attribute( 'dynamic_attributes', '_type_formula', result )

If not, then do this:

@defn.set_attribute( 'dynamic_attributes', '_type_formula', result.to_s )

… and stop farting around with String interpolation when it is not needed !

1 Like

I did everything you said but the “result” doesn’t work (column is not updated)

This is the sample code. Who can see what is wrong. Thanks.

      def kolom

         @mod = Sketchup.active_model
         @ent = @mod.active_entities
        
         @dlg=UI::WebDialog.new("Entresolvloer", false,"WDID",1000,1100,200,200,true)
         @dlg.set_background_color("white")
         html = <<-HTML
 
         <html>
            <head>
               <meta charset="utf-8" />

<form action='skp:kolom@'>

Select Column type:
<select id="this_drop_list" onchange="sendKolomChoice(this.id);">
    <option value="this.text;">200.mm</option>
    <option value="this.text;">300.mm</option>
    <option value="this.text;">400.mm</option>
    <option value="this.text;">500.mm</option>
    <option value="this.text;" selected>600.mm</option>
</select>

<script>
 function getKolomChoice( list ) {

	var opts = list.options;
	
	if (opts.length>0) {
		// Iterate the options collection...
		for (i=0; i< opts.length; i++) {
			// ...searching for the 1st selected option:
			if (opts(i).selected == true) {
				return opts(i).value;
			}
		}
		// If we get here, just return the first option:
		return opts(0).value;
	} else {
		// Value to return if no options loaded:
		return "0";
	}
}

function sendKolomChoice( DropListID ) {
	
	var list = document.getElementById(DropListID);
        window.location = "skp:callback_name@"+getKolomChoice(list);
}   

</script>
             <center><input type="image" src="C://Users/techniek/AppData/Roaming/SketchUp/SketchUp 2016/SketchUp/12.gif" alt="Vloer bouwen" width="95" height="80"/></center>
             </form>
          </body>
         </html>
         HTML

         @dlg.set_html(html)
         
         @dlg.add_action_callback("kolom") {|d,p|
         
            @mod.start_operation "Create Kolom"
            
            model = Sketchup.active_model
            @defn = model.definitions
            componentdefinition = @defn.load ( "Z:/Algemeen 2016/Systeemvloeren/Tekeningen/Sketchup/Enkelzijdige kolom C350.skp" )
            @defn = componentdefinition 
            @defn = model.active_entities.add_instance( @defn, [0,0,0] )  
            @defn.set_attribute( 'dynamic_attributes', '_type_formula', result) 
            };
                  
         RUBY_PLATFORM =~ /(darwin)/ ? @dlg.show_modal() : @dlg.show();
         
      end
kolom

It would appear that you named your Ruby callback “kolom” in add_action_callback, yet you invoke it as “skp:callback_name” in your javascript.

1 Like

Yes that was supposed to be changed to a valid callback name. It was just some example code I posted.

maybe think about adding more debug options in your scripts.

in javascript: add some alerts to visually see what kind of values you are about to send to ruby.
in ruby: add some puts to see what data you just received from javascript.

by doing so you will more easily track down problems

Hi,

Done what you said but stil no result.

it was:
“skp:callback_name@”+getKolomChoice(list);

and now i have:
“skp:callback_kolom@”+getKolomChoice(list);

also added an alert but doens’t give a result only [object]

i know i’m so close…

Just skp:kolom@…

Try value instead of id:

<select id="this_drop_list" onchange="sendKolomChoice(this.value);">

and also the callback is defined as:

@dlg.add_action_callback("kolom")...

So you need to call that explicitly in the js function:

window.location = "skp:kolom@"+getKolomChoice(list);

changed everything but stil no result:

it doesn’t recognize a value for “list” i think

def kolom

         @mod = Sketchup.active_model
         @ent = @mod.active_entities
        
         @dlg=UI::WebDialog.new("Entresolvloer", false,"WDID",1000,1100,200,200,true)
         @dlg.set_background_color("white")
         html = <<-HTML
 
         <html>
            <head>
               <meta charset="utf-8" />

<form action='skp:kolom@'>

Select Column type:
<select id="this_drop_list" onchange="sendKolomChoice(this.value);">
    <option value="200">200</option>
    <option value="300">300</option>
    <option value="400">400</option>
    <option value="500">500</option>
    <option value="600" selected>600</option>
</select>

<script>
 function getKolomChoice( list ) {

	var opts = list.options;
	
	if (opts.length>0) {
		// Iterate the options collection...
		for (i=0; i< opts.length; i++) {
			// ...searching for the 1st selected option:
			if (opts(i).selected == true) {
				return opts(i).value;
			}
		}
		// If we get here, just return the first option:
		return opts(0).value;
	} else {
		// Value to return if no options loaded:
		return "0";
	}
}

function sendKolomChoice( DropListID ) {

	var list = document.getElementById(DropListID);
        window.location = "skp:kolom@"+getKolomChoice(list);
}   

</script>
             <center><input type="image" src="C://Users/techniek/AppData/Roaming/SketchUp/SketchUp 2016/SketchUp/12.gif" alt="Vloer bouwen" width="95" height="80"/></center>
             </form>
          </body>
         </html>
         HTML

         @dlg.set_html(html)
         
         @dlg.add_action_callback("kolom") {|d,p|
         
            @mod.start_operation "Create Kolom"
            
            model = Sketchup.active_model
            @defn = model.definitions
            componentdefinition = @defn.load ( "Z:/Algemeen 2016/Systeemvloeren/Tekeningen/Sketchup/Enkelzijdige kolom C350.skp" )
            @defn = componentdefinition 
            @defn = model.active_entities.add_instance( @defn, [0,0,0] )  
            @defn.set_attribute( 'dynamic_attributes', '_type_formula', "#{list}") 
            };
                  
         RUBY_PLATFORM =~ /(darwin)/ ? @dlg.show_modal() : @dlg.show();
         
      end
kolom

Your html code is muddled.
In the <head> set up the <script>
In the <body> after that set up the form, list etc.
You neither close the head or open the body !

Try this:

function sendKolomChoice( value ) {
   window.location = "skp:kolom@"+value;
} 

You are over complicating it…
I don’t think you need getKolomChoice
If you pass the current value to the callback you can use that directly…