How to pass values to HtmlDialog?

HtmlDialog doesn’t accept a block in its show method. And ‘execute_script’ doesn’t seem to be doing anything till after the dialog has been shown asynchronously (meaning, calling ‘show’ and a line after execute_script doesn’t work). So what is the best alternative? Is it to use a timer? Set up an action callback for ‘onload’?

I find the easiest way to populate both Dialog types is to use vars in the html and then use set_html

once loaded you can change things using execute_script and the same to retrieve values…

the only time I’ve needed a timer was to inject words into google translate and needed to wait for the translation before retrieving it…

but, you really need example scenario or code for people to offer better advice…

there are many options…

I try to kiss and only use vanilla JS etc…

EDIT: he’s a sample from one of mine that was previously a UI.messagebox and did;t want to rewrite it all…

      body = ''
      i = 0
      prompts.each do |prompt|
        body << %(<div class="wrap"><div class="leftcol"> #{prompt}: </div>)
        if list[i] == ''
          body << %(<div class="centcol"><input class="v4su narrowInput" type="text" id="add2array#{i}"} value="#{defaults[i]}"></div>)

        elsif list[i] =~ /\d\|\d/
          unless prompt == prompts[-2]
          body << %(<div class="centcol "><select class="v4su widerSelect" id="add2array#{i}">)
          range.split('|').each {|v| body << %(<option #{defaults[i].to_s == v ? 'selected' : ''}>#{v}</option>)}
          else
          if @castellations
            body << %(<div class="centcol "><select class="v4su widerSelect" id="add2array#{i}" >)
            range.split('|').each {|v| body << %(<option #{defaults[i].to_s == v ? 'selected' : ''}>#{v}</option>)}
          else
            body << %(<div class="centcol "><select class="v4su widerSelect" id="add2array#{i}" disabled>)
            range.split('|').each {|v| body << %(<option #{defaults[i].to_s == v ? 'selected' : ''}>#{v}</option>)}
          end
        end
          body << %(</select>&nbsp%</div>)

john

1 Like

(Moved to the Ruby API category.)

[u]Proper[/u] category search on terms “DOMContentLoaded”

HInt: IF you enter the correct category, and then use the search feature (magnifying glass icon, upper right,) the search will automatically be filtered to only that category. (You can always uncheck the box if desired.)


FYI, for those new to Ruby, John is speaking of string interpolation in double-quoted strings or HEREDOCs.

See: File: literals.rdoc [Ruby 2.0.0]

1 Like

Don’t think of it as pushing data/actions to the dialog, but rather the dialog requests actions or pulls data from SketchUp.

Exactly! This is a thought hump that WebDialog and HtmlDialog programmers need to get across: think of the dialog’s javascript as initiating everything and the SketchUp’s Ruby as sitting quietly waiting for a callback from javascript. The only time the Ruby code initiates an action is in the middle of a callback.

For which there exist also much nicer callback mechanisms, that unfortunately were not realized in HtmlDialog.

FWIW, this is how I did it (and my initial post was looking for nicer way)
In the constructor

add_action_callback("onload") do |context|
	execute_script("set_value(#{value.inspect})") 
end

And in the html

<script type="text/javascript">
		function init() {
			sketchup.onload()
		}
		
		function set_value(value) {
			// do something with the value
		}
</script>
...
<body onload="init()">

Too much boilerplate for something that I expect is very common: passing constructor arguments into the dialog. Would have been nice if there was a way to add values to the sketchup object in JS. Something like set_value(some_name, value) that would make sketchup.some_name have value. Or, if that is not possible, have show accept a block as was in WebDialog

And while we’re on the subject of improving HtmlDialog, it would be nice to have a predefined css to get a standard look and feel (beyond raw html), and maybe jquery integration built in instead of needing to pull it into the plugin or rely on external (network) URLs.

A sneak peek into the framework that I am using:

<script type="text/javascript">
    document.addListener('DOMContentLoaded', function() {

        AE.Bridge.get('settings').then(function (settings) {
            // Do initialization and stuff with settings.
        }, function (error) {
            // Handle error or display error message
        });

    }
</script>

Such a mechanism avoids having separate onload() and set_value() since they belong together. It also avoids fishing an onCompleted out of the function signature (as SketchUp does and assumes it’s intended for callback). Logic and control flow stays in JavaScript, and Ruby just answers requests without knowing about or caring about the order (no onload).
Now I have been polishing this framework for too long, and parts of it have been solved by HtmlDialog, but it could maybe be of interest for others?


It is controversial what the right “look” of an application is (and, if the main app would be HTML/JS based, it would be critisized not being “native”). Ideally it would use the system’s native styling (raw elements without CSS), but since Chromium and other web browsers transitioned to using their corporate style instead of calling the system’s theming engine, this approach is obsolete.

Should I imitate native styling with CSS (but then it would be hard-coded to look like a specific theme on a specific OS, and not match when the theme is changed)? Should I invent my own style and make it look inconsistent? Should I imitate SketchUp’s corporate style? Should I use a neutral style?

NO. it’s bloated and really unnecessary, unless you want a carbuncle that doesn’t look like it belongs in SU…

it seems a lot of people overlook that it’s not the internet, it’s a closed ruby server catering to a handful of browser for WebDialog, or a single [two flavour] browser for HtmlDialog…

you can use Ruby to serve and retrieve what you want, when you want and plain old javascript will obey…

the css for @Aerilius’s was a serious attempt at define css to look ‘native’ and the mac stuff for that looks identical in chrome as it did in safari…

the css for the snippet above is in a similar ilk…

it could be in a linked file, but why when it can be dynamically altered by the ruby serving it…

an example of this would be a dialog whose background colour was set as a complimentary colour to the current SU style background, then if someone was foolishly using a black bg the standard white would not blind them…

    head = <<-HEAD
        <!DOCTYPE html>
        <html><head>
        <title>#{@title}</title>
          <style>
            body {
              font-family: sans-serif;
              font: caption;
              font-size: 3.5mm;
              margin: 0;
              padding: 0;
              background-color: Window;
              line-height: 7mm;
            }

            .legend {
              margin: 0;
              padding: 0;
              text-align: center;
              font-weight: 700;
            }

            hr {
              margin: -.25mm 5mm -0.25mm 5mm;
    /*          border: 0;
              height: 0;
              border-top: .25mm solid rgba(0,0,0,0.4);
              border-bottom: .25mm solid rgba(255,255,255,0.5);*/
            }

            .note {
              text-align: center;
              font-style: italic;
              font-weight: lighter;
              font-size: smaller;
            }

            ::selection {
              background: inherit;
            }

            input::selection {
              background: #fff2a8;
            }

            .wrap {
              width: 100%;
              overflow: auto;
            /* background:lime; */
            }

            .leftcol {
              width: 50%;
              margin-right: 1mm;
              text-align: right;
              cursor: default;
              float: left;
              min-width: 30mm;
            /* background:pink; */
            }

            .centcol {
              float: left;
              width: 22mm;
              cursor: default;
            /* background:lightblue; */
            }

            .rightcol {
              padding: 0;
              margin: 0;
              float: right;
            /* background:yellow; */
            }

            .narrowInput {
              width: 20mm;
            }

            .widerSelect {
              width: 17.5mm;
            }

            input[type=checkbox] {
              margin-top: 1mm;
              margin-left: 6mm;
            }

            input[type=radio] {
              margin-top: 1mm;
              margin-left: 6mm;
            }

            input {
              cursor: pointer;
            }

            input[type=text] {
              cursor: text;
            }

            select {
              cursor: pointer;
            }

            .botbut {
              min-width: 18mm;
            }

            .hlpbut {
            margin-right:3mm;
            }

            .hlpclk {
              cursor: alias;
              width: 100%;
              height: 100%;
              background: InfoBackground;
            }

            .hlpimg {
              margin: 0;
              width: 50%;
              height: 150mm;
              margin-left: 50%;
            }

            img {
              margin-top: 8mm;
              width: 80mm;
              height: 80mm;
              margin-left: -40mm;
            }

            .wrap.footer {
              position: fixed;
              bottom: 3mm;
              line-height: 8mm;
            }
          </style>
        </head>
        <body>
        <div class="legend">Set parrameters for Wave</div>
       <hr/>
      HEAD

and this is how the entire dynamically served html shows in SU

<html><head>
        <title>Sine Circle Details</title>
          <style>
            body {
              font-family: sans-serif;
              font: caption;
              font-size: 3.5mm;
              margin: 0;
              padding: 0;
              background-color: Window;
              line-height: 7mm;
            }

            .legend {
              margin: 0;
              padding: 0;
              text-align: center;
              font-weight: 700;
            }

            hr {
              margin: -.25mm 5mm -0.25mm 5mm;
              border: 0;
              height: 0;
              border-top: .25mm solid rgba(0,0,0,0.2);
              border-bottom: .25mm solid rgba(255,255,255,0.5);
            }

            .note {
              text-align: center;
              font-style: italic;
              font-weight: lighter;
              font-size: smaller;
            }

            ::selection {
              background: inherit;
            }

            input::selection {
              background: #fff2a8;
            }

            .wrap {
              width: 100%;
              overflow: auto;
            /* background:lime; */
            }

            .leftcol {
              width: 50%;
              margin-right: 1mm;
              text-align: right;
              cursor: default;
              float: left;
              min-width: 30mm;
            /* background:pink; */
            }

            .centcol {
              float: left;
              width: 22mm;
              cursor: default;
            /* background:lightblue; */
            }

            .rightcol {
              padding: 0;
              margin: 0;
              float: right;
            /* background:yellow; */
            }

            .narrowInput {
              width: 20mm;
            }

            .widerSelect {
              width: 17.5mm;
            }

            input[type=checkbox] {
              margin-top: 1mm;
              margin-left: 6mm;
            }

            input[type=radio] {
              margin-top: 1mm;
              margin-left: 6mm;
            }

            input {
              cursor: pointer;
            }

            input[type=text] {
              cursor: text;
            }

            select {
              cursor: pointer;
            }

            .botbut {
              min-width: 18mm;
            }

            .hlpbut {
            margin-right:3mm;
            }

            .hlpclk {
              cursor: alias;
              width: 100%;
              height: 100%;
              background: InfoBackground;
            }

            .hlpimg {
              margin: 0;
              width: 50%;
              height: 150mm;
              margin-left: 50%;
            }

            img {
              margin-top: 8mm;
              width: 80mm;
              height: 80mm;
              margin-left: -40mm;
            }

            .wrap.footer {
              position: fixed;
              bottom: 3mm;
              line-height: 8mm;
            }
          </style>
        </head>
        <body style="overflow: hidden;">
        <div class="legend">Set parrameters for Wave</div>
       <hr>
<div class="wrap"><div class="leftcol"> Radius of Circle: </div><div class="centcol"><input class="v4su narrowInput" type="text" id="add2array0" }="" value="5000.000000"></div><div class="rightcol">
        <input title="Click for help" type="button" value="?" class="hlpbut" onclick="toggle_visibility('help0');"></div>
        <div title="Click to Close" class="hlpclk" onclick="toggle_visibility('help0');">
        <div class="hlpimg" id="help0" style="display: none;">
        <img src="/Users/johns_iMac/Library/Application Support/SketchUp 2017/SketchUp/Plugins/jcb_sine_circle/Resources/Help/help0.gif" alt="Radius of Circle Help"></div>
        </div>
        </div><div class="wrap"><div class="leftcol"> Circle Segments: </div><div class="centcol"><input class="v4su narrowInput" type="text" id="add2array1" }="" value="96"></div><div class="rightcol">
        <input title="Click for help" type="button" value="?" class="hlpbut" onclick="toggle_visibility('help1');"></div>
        <div title="Click to Close" class="hlpclk" onclick="toggle_visibility('help1');">
        <div class="hlpimg" id="help1" style="display: none;">
        <img src="/Users/johns_iMac/Library/Application Support/SketchUp 2017/SketchUp/Plugins/jcb_sine_circle/Resources/Help/help1.gif" alt="Circle Segments Help"></div>
        </div>
        </div><div class="wrap"><div class="leftcol"> Wave Count: </div><div class="centcol"><input class="v4su narrowInput" type="text" id="add2array2" }="" value="6"></div><div class="rightcol">
        <input title="Click for help" type="button" value="?" class="hlpbut" onclick="toggle_visibility('help2');"></div>
        <div title="Click to Close" class="hlpclk" onclick="toggle_visibility('help2');">
        <div class="hlpimg" id="help2" style="display: none;">
        <img src="/Users/johns_iMac/Library/Application Support/SketchUp 2017/SketchUp/Plugins/jcb_sine_circle/Resources/Help/help2.gif" alt="Wave Count Help"></div>
        </div>
        </div><div class="wrap"><div class="leftcol"> Wave Height: </div><div class="centcol "><select class="v4su widerSelect" id="add2array3"><option>1</option><option>5</option><option>10</option><option>15</option><option>20</option><option>25</option><option>30</option><option>35</option><option>40</option><option>45</option><option selected="">50</option><option>55</option><option>60</option><option>65</option><option>70</option><option>75</option><option>80</option><option>85</option><option>90</option><option>95</option></select>&nbsp;%</div><div class="rightcol">
        <input title="Click for help" type="button" value="?" class="hlpbut" onclick="toggle_visibility('help3');"></div>
        <div title="Click to Close" class="hlpclk" onclick="toggle_visibility('help3');">
        <div class="hlpimg" id="help3" style="display: none;">
        <img src="/Users/johns_iMac/Library/Application Support/SketchUp 2017/SketchUp/Plugins/jcb_sine_circle/Resources/Help/help3.gif" alt="Wave Height Help"></div>
        </div>
        </div><div class="wrap"><div class="leftcol"> Create Single Wave: </div><div class="centcol"><input class="v4su" type="radio" name="choose" checked="" value="true" id="add2array4" onclick="radio(this);">
              </div><div class="rightcol">
        <input title="Click for help" type="button" value="?" class="hlpbut" onclick="toggle_visibility('help4');"></div>
        <div title="Click to Close" class="hlpclk" onclick="toggle_visibility('help4');">
        <div class="hlpimg" id="help4" style="display: none;">
        <img src="/Users/johns_iMac/Library/Application Support/SketchUp 2017/SketchUp/Plugins/jcb_sine_circle/Resources/Help/help4.gif" alt="Create Single Wave Help"></div>
        </div>
        </div><div class="wrap"><div class="leftcol"> with Circle: </div><div class="centcol"><input class="v4su" type="radio" name="choose" value="false" id="add2array5" onclick="radio(this);">
              </div><div class="rightcol">
        <input title="Click for help" type="button" value="?" class="hlpbut" onclick="toggle_visibility('help5');"></div>
        <div title="Click to Close" class="hlpclk" onclick="toggle_visibility('help5');">
        <div class="hlpimg" id="help5" style="display: none;">
        <img src="/Users/johns_iMac/Library/Application Support/SketchUp 2017/SketchUp/Plugins/jcb_sine_circle/Resources/Help/help5.gif" alt="with Circle Help"></div>
        </div>
        </div><div class="wrap"><div class="leftcol"> with Surface: </div><div class="centcol"><input class="v4su" type="radio" name="choose" value="false" id="add2array6" onclick="radio(this);">
              </div><div class="rightcol">
        <input title="Click for help" type="button" value="?" class="hlpbut" onclick="toggle_visibility('help6');"></div>
        <div title="Click to Close" class="hlpclk" onclick="toggle_visibility('help6');">
        <div class="hlpimg" id="help6" style="display: none;">
        <img src="/Users/johns_iMac/Library/Application Support/SketchUp 2017/SketchUp/Plugins/jcb_sine_circle/Resources/Help/help6.gif" alt="with Surface Help"></div>
        </div>
        </div><div class="wrap"><div class="leftcol"> with Cylinder: </div><div class="centcol"><input class="v4su" type="radio" name="choose" value="false" id="add2array7" onclick="radio(this);">
              </div><div class="rightcol">
        <input title="Click for help" type="button" value="?" class="hlpbut" onclick="toggle_visibility('help7');"></div>
        <div title="Click to Close" class="hlpclk" onclick="toggle_visibility('help7');">
        <div class="hlpimg" id="help7" style="display: none;">
        <img src="/Users/johns_iMac/Library/Application Support/SketchUp 2017/SketchUp/Plugins/jcb_sine_circle/Resources/Help/help7.gif" alt="with Cylinder Help"></div>
        </div>
        </div><div class="wrap"><div class="leftcol"> with Castellation: </div><div class="centcol"><input class="v4su" type="radio" name="choose" value="false" id="add2array8" onclick="radio(this);">
              </div><div class="rightcol">
        <input title="Click for help" type="button" value="?" class="hlpbut" onclick="toggle_visibility('help8');"></div>
        <div title="Click to Close" class="hlpclk" onclick="toggle_visibility('help8');">
        <div class="hlpimg" id="help8" style="display: none;">
        <img src="/Users/johns_iMac/Library/Application Support/SketchUp 2017/SketchUp/Plugins/jcb_sine_circle/Resources/Help/help8.gif" alt="with Castellation Help"></div>
        </div>
        </div><div class="wrap"><div class="leftcol"> Face Thickness: </div><div class="centcol "><select class="v4su widerSelect" id="add2array9" disabled=""><option>1</option><option>5</option><option>10</option><option>15</option><option>20</option><option>25</option><option>30</option><option>35</option><option>40</option><option>45</option><option selected="">50</option><option>55</option><option>60</option><option>65</option><option>70</option><option>75</option><option>80</option><option>85</option><option>90</option><option>95</option></select>&nbsp;%</div><div class="rightcol">
        <input title="Click for help" type="button" value="?" class="hlpbut" onclick="toggle_visibility('help9');"></div>
        <div title="Click to Close" class="hlpclk" onclick="toggle_visibility('help9');">
        <div class="hlpimg" id="help9" style="display: none;">
        <img src="/Users/johns_iMac/Library/Application Support/SketchUp 2017/SketchUp/Plugins/jcb_sine_circle/Resources/Help/help9.gif" alt="Face Thickness Help"></div>
        </div>
        </div><div class="wrap"><div class="leftcol"> Explode Grouping: </div><div class="centcol"><input class="v4su" type="checkbox" value="false" id="add2array10" onclick="handleClick(this);">
          </div><div class="rightcol">
        <input title="Click for help" type="button" value="?" class="hlpbut" onclick="toggle_visibility('help10');"></div>
        <div title="Click to Close" class="hlpclk" onclick="toggle_visibility('help10');">
        <div class="hlpimg" id="help10" style="display: none;">
        <img src="/Users/johns_iMac/Library/Application Support/SketchUp 2017/SketchUp/Plugins/jcb_sine_circle/Resources/Help/help10.gif" alt="Explode Grouping Help"></div>
        </div>
        </div>        <div class="wrap footer" id="footer" style="display: block;">
        <div class="leftcol"><input type="button" class="botbut" value="Cancel" onclick="closeDlg();"></div>
        <div class="centcol"><input type="button" class="botbut" value="OK" autofocus="" onclick="js2ruby();"></div></div>

        <script>
         // help items
        function toggle_visibility(id) {
          var e = document.getElementById(id);
          var f = document.getElementById('footer')
          var h = e.style.display === 'none'
          var all = document.getElementsByClassName('hlpimg');
          for (i = 0; i < all.length; i++) {
            all[i].style.display = 'none';
          }
          h ? e.style.display = 'block' : e.style.display = 'none';
          h ? e.scrollIntoView() : document.scrollTop;
          h ? f.style.display = 'none' : f.style.display = 'block';
        }

        function radio(chk) {
          var group = chk.name;
          var t = add2array9.disabled === true;
          var all = document.getElementsByName(group);
          for (var i = 0; i < all.length; i++) {
            all[i].value = all[i].checked;
            add2array9.disabled=true;
          }
        if (chk === add2array8)
        t ? add2array9.disabled=!add2array9.disabled : add2array9.disabled=!add2array9.disabled
        }

        function handleClick(cb) {
          cb.value = cb.checked;
        }

        function closeDlg() {
          sketchup.close_dlg();
        }

        function js2ruby() {
          clicks = 1;
          timer = setTimeout(function() {
            if (clicks == 1) {
          var ary = [];
          var val = document.getElementsByClassName('v4su');
          for (var i = 0, len = val.length; i < len; i++) {

            ary[i] = val[i].value
          }
             sketchup.js2ruby(ary);
             closeDlg();
            }
        }, 500);
        }
        </script>
</body></html>

sorry there big chunks, but it would take time to write snippets to show the totality of this process…

john

Javascript is OK if the dialog is small but once you start even basic stuff it becomes a pain. So of course we can work with what Javascript offers but that is akin to saying we can write C instead of Ruby. Possible, but cumbersome. I don’t think including jquery will bloat Sketchup and not every dialog needs to load it (which would also not bloat anything too much), it can be simply a path in SU which the html can reference.

Response moved to:

I’m using jquery 1.12.4 - but I don’t include it inside with my plugins.

I use a mix of javascript and jquery since jquery does make certain things easier and more consistent between browsers.

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