• Login
sketchucation logo sketchucation
  • Login
⚠️ Libfredo 15.4b | Minor release with bugfixes and improvements Update

Web dialog on a Mac

Scheduled Pinned Locked Moved Developers' Forum
69 Posts 9 Posters 7.3k Views 9 Watching
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    s_k_e_t_c_h_y
    last edited by 22 Dec 2013, 19:46

    Hi,
    I have a plug-in I wrote working on Windows system, but have received feedback that is doesn't work on a Mac. I've borrowed a Mac and confirmed that the Web Dialog doesn't send the message back to the Ruby script. I tried a basic example (showing the console from a web dialog) and this also failed.

    I am new to using a Mac so I don't know if there is some option you need to set to permit web dialogs to operate? There doesn't appear to be any differentiation in the coding documentation required between the Operating Systems or their respective browsers.
    
    I assume this is a pretty basic fix, but can't seem to find the answer yet.
    

    Help appreciated. Happy Holidays.

    Paul.

    1 Reply Last reply Reply Quote 0
    • J Offline
      jolran
      last edited by 22 Dec 2013, 20:43

      Are you using dialog.set_file ?

      htmlset = File.join( File.dirname(FILE), "somehtml" )
      dialog.set_file( htmlset )

      I think that is one of the many recommendations.
      Also do a platformcheck and set dialog to modal.

      RUBY_PLATFORM =~ /(darwin)/ ? dialog.show_modal() : dialog.show

      It's difficult for anyone to tell without some code I guess.

      At least you have something to try out 😄 I have not yet done any dialogs for Mac so I couldent tell for sure if that works..

      1 Reply Last reply Reply Quote 0
      • S Offline
        slbaumgartner
        last edited by 23 Dec 2013, 00:53

        No, there is no special option you have to set. However, you do have to be careful about the fact that javascript runs asynchronously on the Mac but not on Windows. This can cause a host of problems. One of the most common is that an onload event callback from the HTML body will not work, you have to use a script element as the last thing in the body.

        Take a look at TT's writeup https://github.com/thomthom/sketchup-webdialogs-the-lost-manual first to make sure you aren't doing something known to be wrong.

        1 Reply Last reply Reply Quote 0
        • S Offline
          s_k_e_t_c_h_y
          last edited by 23 Dec 2013, 19:25

          Thanks for the feedback,
          I'll try some of your ideas. I did know about the unload, but thought I'd taken care of that with a message back to ruby to let it know the DOM was loaded.

          Paul.

          1 Reply Last reply Reply Quote 0
          • S Offline
            slbaumgartner
            last edited by 24 Dec 2013, 01:17

            @s_k_e_t_c_h_y said:

            Thanks for the feedback,
            I'll try some of your ideas. I did know about the unload, but thought I'd taken care of that with a message back to ruby to let it know the DOM was loaded.

            Paul.

            What triggers the message? It could be that due to async timing it is never delivered!

            Steve

            1 Reply Last reply Reply Quote 0
            • S Offline
              s_k_e_t_c_h_y
              last edited by 25 Dec 2013, 23:13

              All,
              I'm still having trouble despite reading the articles and trying to incorporate the advice recommended. Most of the 'examples' seem to stop at demonstrating that the behavior is different between operating systems. I just want to have a form send back it's data. I'm presuming that this is to do with the asynchronicity on the Mac. The submit button in the form doesn't run make it back to Ruby at all and the normal button works for one option, but not multiple options.

              Here is the Ruby example code:

              @d = nil
              @d = UI;;WebDialog.new("Test", true, "", 800, 800, 200, 200, true)
              
              htmlset = File.join( File.dirname(__FILE__), "test.html" )
              @d.set_file( htmlset )
              
              #set the callback for the radio buttons
              @d.add_action_callback('food') { |dialog, params|
                  puts '>> Food; ' + params
                  @d.execute_script('send_radio_data();')    #return control back to JS?
              }
              
              @d.add_action_callback('animal') { |dialog, params|
                  puts '>> Animal; ' + params
                  @d.execute_script('send_radio_data();')    #return control back to JS?
              }
              
              RUBY_PLATFORM =~ /(darwin)/ ? @d.show_modal() ; @d.show
              

              Here is the HTML example code:

              <html>
                  <body >
                      Multi-Platform WebDialog form submission test<br>
                      
                      <form name="stuff" onsubmit="submitbutton();" method="post">
                          Favorite Food;<br>
                          <input type="radio" name="food" value="Pizza">Pizza<br>
                          <input type="radio" name="food" value="Hotdogs">Hotdogs<br>
                          Favorite Animal;<br>
                          <input type="radio" name="animal" value="Cat">Cat<br>
                          <input type="radio" name="animal" value="Dog">Dog<br>
                                      
                          <input type="button" value="Submit by Button" onclick="buttonpress()">
                          <input type="submit" value="Submit by Submit">
                      </form>
                      
                      <script>
                          function call_ruby( callback_name, message ) {
                              location = 'skp;' + callback_name + '@' + message
                          }
                      
                          function send_radio_data(field) {
                              //Get the field data
                              var ps = document.getElementsByName(field);
                          
                              for (var i = 0, length = ps.length; i < length; i++) {
                                  if (ps[i].checked) {
                                      // Send the value back to SketchUp
                                      call_ruby(field, ps[i].value);
                                      // only one radio can be logically checked, don't check the rest
                                      break;
                                  }
                              }
                          }
                      
                          function sendformdata()
                          {
                              send_radio_data("food")
                              send_radio_data("animal")
                          }
                      
                          function buttonpress()
                          {
                              alert("Doing Button Press Send");
                              sendformdata();
                          }
                      
                          function submitbutton()
                          {
                              alert("Doing Submit send")
                              sendformdata()    // Never gets ran
                          }
                      
                      </script>
                  </body>
              <html>
              

              If someone could put me out of my misery and help me correct this it would be much appreciated.

              Sincerely, Paul.

              1 Reply Last reply Reply Quote 0
              • Dan RathbunD Offline
                Dan Rathbun
                last edited by 26 Dec 2013, 03:23

                (1) The button is just a button. Use onclick= instead of onsubmit=

                (2) You are missing ; at the end of some JS statements. Try using a syntax checker like JSLint to check your code.
                http://www.jslint.com

                I'm not here much anymore.

                1 Reply Last reply Reply Quote 0
                • Dan RathbunD Offline
                  Dan Rathbun
                  last edited by 26 Dec 2013, 03:31

                  Ok I see a major booboo.

                  location is an attribute of the window object.

                  ... so in your call_ruby() function, it needs to be:

                  
                              function call_ruby( callback_name, message ) {
                                  window.location = 'skp;' + callback_name + '@' + message;
                              }
                  
                  

                  I'm not here much anymore.

                  1 Reply Last reply Reply Quote 0
                  • S Offline
                    s_k_e_t_c_h_y
                    last edited by 26 Dec 2013, 07:13

                    Thanks for the replies Dan,
                    I'm still having issues, but I'll keep tinkering =P.

                    1 Reply Last reply Reply Quote 0
                    • S Offline
                      s_k_e_t_c_h_y
                      last edited by 26 Dec 2013, 17:41

                      Ok,
                      I've got it!! I made a few design decisions which should be reasonably documented in the code, but I've enclosed a fully working example below for submitting forms that works on a Mac and a Windows system.

                      The example below presents a single form with a radio buttons and checkboxes and after selecting them how you desire and hitting submit all of the settings are sent one by one. To get around the asynchronous/synchronous problem, I essentially have message passing between Ruby and JavaScript to force sending one option at a time (making both Operating Systems act asynchronously) from a options list. It should be quite easy to extend from here.
                      

                      Here is the HTML/JavaScript Code:

                      
                      <html>
                          <body >
                              Multi-Platform WebDialog form submission test<br><br>
                      
                              <form name="stuff">
                                  Favorite Food;<br>
                                  <input type="radio" name="food" value="Pizza">Pizza<br>
                                  <input type="radio" name="food" value="Hotdogs">Hotdogs<br>
                                  <br>Favorite Animals;<br>
                                  <input type="checkbox" id="a_cat" value="a_cat">Cat<br>
                                  <input type="checkbox" id="a_dog" value="a_dog">Dog<br>
                                  <input type="checkbox" id="a_squirrel" value="a_squirrel">Squirrel<br>
                                      
                                  <input type="button" value="Submit" onclick="sendformdata()">
                              </form>
                              
                              <script>
                                  var options = {};   // object that stores all of our settings
                                  
                                  //Sends a mesage to SU / Ruby
                                  function call_ruby( callback_name, message ) {
                                      window.location = 'skp;' + callback_name + '@' + message;
                                  }
                              
                                  //Add a checkbox value to the options object
                                  function add_checkbox_data(var_str) {
                                      if (document.getElementById(var_str).checked) {
                                          options[var_str] = "1";
                                      } else {
                                          options[var_str] = "0";
                                      }
                                  }
                              
                                  //Add a radio button value to the options object
                                  function add_radio_data(field) {
                                      //Get the field data
                                      var ps = document.getElementsByName(field);
                                  
                                      for (var i = 0, length = ps.length; i < length; i++) {
                                          if (ps[i].checked) {
                                              // store value in our object
                                              options[field] = ps[i].value;
                                              // only one radio can be logically checked, don't check the rest
                                              break;
                                          }
                                      }
                                  }
                              
                                  //Send a single setting to SU, callbacks will come and get the rest
                                  function send_setting()
                                  {
                                      var size = 0, key;
                                      var seting, value;
                                      
                                      for (key in options) {
                                          if (options.hasOwnProperty(key)) size++;
                                      }
                                      
                                      if (size > 0) {
                                          for (setting in options) break; // Get the first setting
                                          value = options[setting];
                                          delete options[setting];
                                          call_ruby(setting, value);
                                      } else {
                                          call_ruby("submit", 1);
                                      }
                                  }
                              
                                  function sendformdata()
                                  {
                                      add_radio_data("food");
                                      
                                      //The checkbox options all have unique names to simplify storage in 'options' receipt at the SU end (more callback handlers needed though)
                                      //Could have concatenated all check options into a string, sent them as a single submit and parsed the string at the SU end too
                                      add_checkbox_data("a_cat");
                                      add_checkbox_data("a_dog");
                                      add_checkbox_data("a_squirrel");
                                      
                                      //Send the first setting to SU, the callbacks will get the rest
                                      send_setting();
                                  }
                      
                              </script>
                          </body>
                      <html>
                      
                      

                      Here is the Ruby Code:

                      
                      @d = nil
                      @d = UI;;WebDialog.new("Test", true, "", 800, 800, 200, 200, true)
                      
                      htmlset = File.join( File.dirname(__FILE__), "test.html" )
                      @d.set_file( htmlset )
                      
                      #set the callback for the radiobuttons
                      @d.add_action_callback('food') { |dialog, params|
                          puts '>> Food; ' + params
                          @d.execute_script('send_setting();')    #check for more settings to send
                      }
                      
                      @d.add_action_callback('a_cat') { |dialog, params|
                          puts '>> Animal; Cat - ' + params
                          @d.execute_script('send_setting();')    #check for more settings to send
                      }
                      
                      @d.add_action_callback('a_dog') { |dialog, params|
                          puts '>> Animal; Dog - ' + params
                          @d.execute_script('send_setting();')    #check for more settings to send
                      }
                      
                      @d.add_action_callback('a_squirrel') { |dialog, params|
                          puts '>> Animal; Squirrel - ' + params
                          @d.execute_script('send_setting();')    #check for more settings to send
                      }
                      
                      #Make the window persistant on top of SU
                      RUBY_PLATFORM =~ /(darwin)/ ? @d.show_modal() ; @d.show
                      
                      

                      Thanks to all for the advice along the way.

                      Sincerely, Paul

                      1 Reply Last reply Reply Quote 0
                      • D Offline
                        driven
                        last edited by 27 Dec 2013, 15:41

                        Hi Paul,

                        I'll give it a run later...
                        I've been trying to tidy up my own version to see if it would be of any use, but you beat me to it...

                        I'll post it anyway, for your perusal, and maybe see if it works on a PC [I don't have one]

                        I wanted to use only ruby and the least 'vanila' js to do all the sorting. To achieve this I use a common id(+digit) for each element, then a ruby range loop collects them...

                        Let me know if it seems sensible?
                        john
                        output to UI.messagebox to show it works on mac...
                        it's a one pager for convenience of testing...

                        
                        def js_2_ruby
                        
                            dlg = UI;;WebDialog.new("optionsDialog", false, "tlDlg", 300, 250, 150, 150, false)
                        
                            # the html for structure needs values and names in specific groups for the js to work for radio buttons and or checkboxes.
                        
                            html =<<HTML
                            <html>
                            <title>Web Form in SU</title>
                            <head>
                            <script>
                            function js2ruby() {
                            window.location='skp;js2ruby';
                            }
                        
                            function radio(chk) {
                                try {
                                exists = document.getElementById(chk.name);
                                exists.id = exists.value;}
                                catch(err){}
                                finally {
                                if (chk.checked === true)
                                 chk.id = chk.name;}
                            }
                        
                            function validate(chk) {
                                if (chk.checked === true)
                                 chk.value = chk.name;
                                else chk.value = chk.title;
                            }
                            </script>
                        <style></style>
                        
                                </head>
                            <body>
                        
                            <h1>Send to ruby</h1>
                        
                            <form name="f1" id="f1">
                                A Greeting to;
                                <input type="text" name="greet" id="add2array1" placeholder=" to all fine gentlemen "><br/>
                                Your Name;
                                <input type="text " name="name " id='add2array2';" placeholder="John">
                                <br />
                                Your Order;
                                <br />
                                <input type="radio" name="add2array3" id="Pizza" value="Pizza" onclick='return radio(Pizza);'>Pizza
                                <br />
                                <input type="radio" name="add2array3" id="Hotdogs" value="Hotdogs" onclick='return radio(Hotdogs);'>Hotdogs
                                <br/>
                                <input type="checkbox" name="with sauce" id="add2array4" title="without sauce"  value="" onClick='return validate(add2array4);'>with "Tomato" Sauce?
                                <br />
                                <br />
                                Send to Ruby;
                                <input type="button" value="Submit" onClick="js2ruby();">
                            </form>
                             </body>
                            </html>[attachment=0]2013-12-27 03.35.26 pm.png[/attachment]
                        HTML
                        
                            @html = html
                        
                            # the gist; make an array
                            @tl = []
                        
                            # get 'user replys' from the webdialog,
                            dlg.add_action_callback("js2ruby") {|d,_|
                            # need to hard code number range to match html...
                            (1..4).each{ |i| tl = d.get_element_value("add2array#{i}")
                            # then add a placeholder for missing values, I like to be obvious...
                            tl = "missing value" if not tl.length > 0
                            # then push the full range into the array...
                            @tl << tl
                            }
                            # if only used once per session, you could use @tl[0..3], but just incase, user make a change...
                            UI.messagebox("    Greetings to #{@tl[-4]}\n   from #{@tl[-3]}\n  #{@tl[-2]} #{@tl[-1]}")
                            }
                            # then set_html or file/url if separate...
                            dlg.set_html html
                            if( (RUBY_PLATFORM =~ /darwin/i) )
                            dlg.show_modal
                            else
                            dlg.show
                            end #if
                        
                        end # def js_2_ruby
                        
                        # to run
                        js_2_ruby
                        
                        

                        learn from the mistakes of others, you may not live long enough to make them all yourself...

                        1 Reply Last reply Reply Quote 0
                        • Dan RathbunD Offline
                          Dan Rathbun
                          last edited by 28 Dec 2013, 01:03

                          The reference to the dialog object needs to be an instance var @dlg, or else Ruby's garbage collection will sweep up the local var inside the method when it returns.

                          Ie.. the dialog will close by itself, and be destroyed. (or you can return the dialog object at the end of the method, and let the caller have the responsibility to hold the object reference.)

                          I'm not here much anymore.

                          1 Reply Last reply Reply Quote 0
                          • D Offline
                            driven
                            last edited by 28 Dec 2013, 01:16

                            hi dan

                            it's a quick[well not so quick] lash-up of a few concepts I've had on the back-burner for far to long...

                            so there is room for improvements in the coding, so fire away...

                            I could never see the need for the hidden field to hold the js values, when ruby could collect them directly for itself?

                            I'm just adding to it to bounce back some interactive ruby, i.e. Sketchup as server, which has also been on the bb...

                            I guess that's what xmas is for...

                            BIG ?? does it run on Windows...

                            john

                            learn from the mistakes of others, you may not live long enough to make them all yourself...

                            1 Reply Last reply Reply Quote 0
                            • Dan RathbunD Offline
                              Dan Rathbun
                              last edited by 28 Dec 2013, 01:39

                              Without even trying I can tell you we will see the dialog for a second and then POOF it will be gone.

                              But if you return dlg as the last line of the method,...

                              and then call it using a reference assignment like:
                              my_dialog = js2ruby()
                              it WILL work because Ruby will hold a reference to the dialog object.

                              I'm not here much anymore.

                              1 Reply Last reply Reply Quote 0
                              • D Offline
                                driven
                                last edited by 28 Dec 2013, 01:57

                                so why does it always work on a mac...

                                never had one vanish?

                                I can even add a bunch of GC.start 's and it's stay's... just tried it...

                                just curious...

                                john

                                learn from the mistakes of others, you may not live long enough to make them all yourself...

                                1 Reply Last reply Reply Quote 0
                                • Dan RathbunD Offline
                                  Dan Rathbun
                                  last edited by 28 Dec 2013, 04:51

                                  Specifically I do not know.

                                  Generally the OSX GUI is different from the MS Windows GUI.

                                  I'm not here much anymore.

                                  1 Reply Last reply Reply Quote 0
                                  • G Offline
                                    Garry K
                                    last edited by 2 Jan 2014, 21:26

                                    I have also been experimenting with web dialogs. This works with Windows 7 and sketchup 7,8 and 2013.

                                    Hopefully someone with a MAC can try this and see if it works in Safari.

                                    I have Chrome, IE11 and Firefox installed. The code works with these Browsers but only if I rem out the line that references sk


                                    web dialog


                                    This file adds a menu Item under Plugins called "Web Dialog Test"

                                    1 Reply Last reply Reply Quote 0
                                    • D Offline
                                      driven
                                      last edited by 2 Jan 2014, 21:54

                                      looks like this in SU, and works
                                      but you do need a version of

                                          # then set_html or file/url if separate...
                                          @dlg.set_html html
                                          if( (RUBY_PLATFORM =~ /darwin/i) )
                                          @dlg.show_modal
                                          else
                                          @dlg.show
                                          end #if
                                      

                                      john

                                      learn from the mistakes of others, you may not live long enough to make them all yourself...

                                      1 Reply Last reply Reply Quote 0
                                      • G Offline
                                        Garry K
                                        last edited by 2 Jan 2014, 22:06

                                        Thanks

                                        I can easily add that.

                                        When you clicked "Ok" button did you get a list of Control Id's and values?

                                        1 Reply Last reply Reply Quote 0
                                        • D Offline
                                          driven
                                          last edited by 2 Jan 2014, 22:18

                                          you mean this?

                                          pre-setting the size [webDialog] is better as well.

                                          john

                                          learn from the mistakes of others, you may not live long enough to make them all yourself...

                                          1 Reply Last reply Reply Quote 0
                                          • 1
                                          • 2
                                          • 3
                                          • 4
                                          • 1 / 4
                                          1 / 4
                                          • First post
                                            1/69
                                            Last post
                                          Buy SketchPlus
                                          Buy SUbD
                                          Buy WrapR
                                          Buy eBook
                                          Buy Modelur
                                          Buy Vertex Tools
                                          Buy SketchCuisine
                                          Buy FormFonts

                                          Advertisement