A little more about UI: HtmlDialog

Guys, I’m a beginner in Sketchup plugins, I’m looking to develop a plugin, but I have a limitation so I
can only learn with an example. That is why the site http://www.smustard.com/script/ is fantastic but
is not updated anymore and for this reason we cannot count on examples from HtlmDialog. because at https://extensions.sketchup.com/ we even found free plugins but most are encrypted.
Thomthom presented an example of an incredible dialog in vue of 2017 but that even today is very current, I can say that Aerilius also presented a dialogue with another very current topic. However, I would like to understand the basics better and then try to fly higher. Based on the Camlaman post I’m trying to develop a plugin that after selecting the element sends the data of the element’s id and length to the Htmldialog, the Dialog requested the height and depth, performs area calculations and presents it in the dialog and then returns the length, height and depth data for the selected element by changing its layer. For now I’m trying to get the id and length data but I’m not getting it, where am I going wrong?

I put some markers to indicate that I am on the right path, so I realize that I receive the id and the length correctly, but when inspecting the page I see that the values are not recognized by the script

Following code works.

require 'sketchup.rb'
require 'json'
mod = Sketchup.active_model
sel = mod.selection

sel.each do |e| # Tem que haver each para se ter o ele as caracterisitcas da entidade
if e.class == Sketchup::Edge # compara se o elemento selecionado e Edge
comp = sel.length*25400 # pega o comprimento em polegada e transforma em milimetro
id = e.entityID # pega o id do elemento
UI.messagebox(id)
my_hash={id:id,compr:comp} # cria um hash
my_hashjon = my_hash.to_json # Transforma o hash ruby em hash json
UI.messagebox( my_hashjon )
sel.clear # Limpar a seleção
end
end

dialog = UI::HtmlDialog.new({
  :dialog_title => "Definição do Material",
  :scrollable => true,
  :resizable => true,
  :width => 700,
  :height => 300,
  :left => 200,
  :top => 200,
  :min_width => 50,
  :min_height => 50,
  :max_width =>1000,
  :max_height => 500,
  :style => UI::HtmlDialog::STYLE_DIALOG
})
html = "
  <!DOCTYPE html>
  <html>
  <head>
  <title>FMS Test Dialog
  </title>
  </head>
  <h1>Draw a Box from a HtmlDialog</h1>
  <script>
  function sendDataToSketchUp() {
	var altura = document.getElementById('id1');
	var largura = document.getElementById('id2');
	var compr = document.getElementById('id3');
	sketchup.pegaentrada(altura.value, largura.value, compr.value)
}
  document.getElementById('comp').innerHTML = recebeJSON.id;     
  </script>
  <body>
  <p>O material escolhido apresenta as seguintes caracterisitcas</p>
  <form>
	Altura: <input id='id1' type='number' name='altura' value=5 required><br>
	Largura: <input id='id2' type='number' name='largura' value=10 required><br>
	comprimento: <input id='id3' type='number' name='compr' value=25 required>
  </form>
  <p id='comp'>This is a demonstration.</p>
  <button onclick='sendDataToSketchUp()'>Draw Box</button>
  </body>
  </html>
"

dialog.set_html(html)
dialog.show
#dialog.execute_script("var recebeJSON = JSON.parse('#{my_hashjon}');") ... This is your problem


dialog.add_action_callback("pegaentrada"){|action_context, altura, largura, compr|
	puts("JavaScript said user_input1 is #{altura}, user_input2 is #{largura} and user_input3 is #{compr}.")
dialog.close
	width = altura.to_f
	breadth = largura.to_f
	depth = compr.to_f
	model = Sketchup.active_model
	entities = model.active_entities
	pts = []
	pts[0] = [0, 0, 0]
	pts[1] = [width, 0, 0]
	pts[2] = [width, breadth, 0]
	pts[3] = [0, breadth, 0]
	# Add the face to the entities in the model
	face = entities.add_face(pts)
	face.pushpull depth
}

thanks majid866 for your attention. But I don’t think I was able to express myself properly. This code works was calman who posted on this forum. The fact is that I would like to make a small modification using the execute_script method of the UI class: HtmlDialog. Therefore, I would like to send the id and length information of the selected element to the open page.
However I am not able to make js implement this information in the script

I think Aerilius can answer you.
WebDialog / HtmlDialog Tutorial using sketchup-bridge

The error shown in the Chrome Dev panel … "ReferenceError: recibeJSON is not defined"
happens because the JS statement in your HTML string …

document.getElementById('comp').innerHTML = recebeJSON.id;

is evaluating BEFORE the recebeJSON object is defined.

You are defining it later on the RUBY side AFTER the dialog is shown, and AFTER the above assignment statement.

So it is a issue of timing.

(a) Put a defining statement at the top of the javascript …

var recebeJSON = {};

(b) Do not send dynamic data over to the dialog until the dialog reports that it has loaded all the HTML and JavaScript and is ready. To have the dialog report back when ready, do something like this at the bottom of the HTML file …

    </body>
    <script>
        
        // Load Event
        document.body.onload = function() {
            sketchup.report_ready();
        }

    </script>
</html>

And in your Ruby, attach an action callback named “report_ready” to the UI::HtmlDialog object that sets the initial data for the recebeJSON JS object and then calls JS function to load the from fields…

dialog.add_action_callback("report_ready"){|action_context|
  dialog.execute_script( %[recebeJSON = JSON.parse('#{my_hashjon}');] )
  dialog.execute_script( %[load_form();] )
}

Notice that we use % string delimiters with [] brackets here so as not to confuse the Ruby interpreter with the nested double quote characters that can be produced by the JSON string creation.

See the primer on String literals …
https://ruby-doc.org/core-2.7.1/doc/syntax/literals_rdoc.html#label-Strings
… for an explanation of %Q (same as %,) and %q delimited string literal expressions.

You can also set the fields individually …

dialog.add_action_callback("report_ready"){|action_context|
  dialog.execute_script( %[recebeJSON.id = '#{my_hash["id"]}');] )
  dialog.execute_script( %[recebeJSON.altura = #{my_hash["altura"]});] )
  dialog.execute_script( %[recebeJSON.largura = #{my_hash["largura"]});] )
  dialog.execute_script( %[recebeJSON.compr = #{my_hash["compr"]});] )
  dialog.execute_script( %[load_form();] )
}

The Javascript load_form() function would be similar to …

    <script>
        
        // Load Form
        load_form = function() {
           document.getElementById('id').innerHTML = recebeJSON.id;
           document.getElementById('id1').innerHTML = recebeJSON.altura;
           document.getElementById('id2').innerHTML = recebeJSON.largura;
           document.getElementById('id3').innerHTML = recebeJSON.compr;
        }

    </script>

(c) You are also not setting the altura (height) and largura (width) in the hash.

my_hash={ id:id, compr:comp, altura: e.bounds.height, largura: e.bounds.width }


Do not change the layer (tag) of geometric primitives. (Leave them on “Layer0” / “Untagged”.)

Only set complex objects to other layer/tags, such as Guides, Dimensions, Group or Component Instances, Section Planes, etc.

Also, when setting HTML form elements, some types you use .value = and others you will use .innerHTML =. So if one way does not work, then try the other. Same for getting values.