This pattern works to load the Ruby hash into the dialog JS as an object …
I think it was that the ready state callback on the Ruby-side was not getting called.
There also was a minor error down in the add()
function where it stuffed the attribute value into the body:
You were using …
new_dc_att.setAttribute('value',get_atts(key));
… which resulted in the JS error “get_atts is not a function”.
This is true. It is a JS object so either use square brackets or dot notation.
new_dc_att.setAttribute('value',get_atts[key]);
… works.
Working pattern to load the attribute data (missing the edit functions)
def go
@dialog = UI::HtmlDialog.new(
{
:dialog_title => 'dynamic form',
:scrollable => true,
:resizable => true,
:width => 600,
:height => 300,
:left => 200,
:top => 200,
:min_width => 50,
:min_height => 50,
:max_width =>600,
:style => UI::HtmlDialog::STYLE_DIALOG
})
att_hash = {
att_1: 'dc att_1 value',
att_2: 'dc att_2 value',
att_3: 'dc att_3 value'
}
@dialog.add_action_callback('ready') do |context, params|
puts "Dialog callback \"ready\" (dialog static content was loaded)"
pass_atts_in = att_hash.to_json
@dialog.execute_script( %[var get_atts = JSON.parse('#{pass_atts_in}');] )
@dialog.execute_script( %[populate_list();] )
end
html = %q[
<!DOCTYPE html>
<html>
<head>
<title>Dynamic Fields</title>
<style>
body {
width: 100%;
height: 100%;
}
.button {
border: 1px solid black;
color: black;
padding: 3px 8px;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
}
.container {
width: 100%;
}
</style>
<script>
document.addEventListener("readystatechange", function (e) {
if( document.readyState == 'complete' ) {
sketchup.ready();
}
});
</script>
</head>
<body>
<h1>DC Attributes List  <button class='button' onclick='add()'>Add</button> </h1>
<br>
<div class='container'>
<div id='dc_att_list'>
</div>
<br>
<input class='button' name='submit' type='Submit' value='Save'>
</div>
</body>
<script>
var dc_att_list = document.getElementById('dc_att_list');
function populate_list() {
// run once at start
console.log('In populate_list() function ...');
// Iterate the get_atts Object imported from Ruby hash:
Object.keys(get_atts).forEach(function(key) {
// key = att_1,2,etc get_atts[att_1] = 'dc attribute string'
console.log('Key : ' + key + ', Value : ' + get_atts[key])
// block to build initial form
add(key)
})
}
function add(key) {
//add the dc attribute feild
var input_tags = dc_att_list.getElementsByTagName('input');
var att_no = (input_tags.length/2) + 1;
var new_dc_att = document.createElement('input');
new_dc_att.setAttribute('type','text');
new_dc_att.setAttribute('name','att_text');
new_dc_att.setAttribute('id',key);
new_dc_att.setAttribute('class','text');
new_dc_att.setAttribute('value',get_atts[key]);
new_dc_att.setAttribute('size',50);
dc_att_list.appendChild(new_dc_att);
//add the remove button
var new_att_remove = document.createElement('input');
var att_nam = 'att_' + (att_no + 0.5);
new_att_remove.setAttribute('name','clear');
new_att_remove.setAttribute('type','button');
new_att_remove.setAttribute('class','button');
new_att_remove.setAttribute('onclick','clear_child(att_nam)');
//this should remove the button, how to make the att_nam variable stick?
new_att_remove.setAttribute('id',att_nam);
new_att_remove.setAttribute('value','remove ' + att_no);
dc_att_list.appendChild(new_att_remove);
}
</script>
</html>
] # end of HTML
@dialog.set_html(html)
@dialog.show
end # go()