• Login
sketchucation logo sketchucation
  • Login
🤑 SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

Javascript problem

Scheduled Pinned Locked Moved Developers' Forum
8 Posts 4 Posters 332 Views 4 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.
  • T Offline
    T.M
    last edited by 2 Nov 2011, 16:47

    Hello,

    I've been training myself to get used to creating Webdialogs with javascript and I have recently encountered a problem. I've been trying to code something that gets the materials of each face of a pre-drawn cube (except the bottom face) and simply show these in a webdialog.

    My ruby code is the following:

    $wd = UI;;WebDialog.new "Dialog"
    path = Sketchup.find_support_file "Code/Document.html", "Plugins"
    $wd.set_file path
    
    vect = Geom;;Vector3d.new(0, 0, -1) 
    f_count = 1
    		
    Sketchup.active_model.active_entities.each{|j|
    if j.class == Sketchup;;Face && vect.samedirection?(j.normal) == false
    	arg = "'" + j.material.name + "'"
    	$wd.execute_script("defMat" + f_count.to_s + "(" + arg + ")")
    	f_count = f_count + 1
    end #if
    }
    					
    $wd.show
    
    

    And this is my Javascript code:

    <html>
    	<head>
    		<script type="text/javascript">
    		function defMat1(mat)
    		{
    			document.getElementById("mt1").innerHTML = mat
    		}
    
    		function defMat2(mat)
    		{
    			document.getElementById("mt2").innerHTML = mat
    		}
    
    		function defMat3(mat)
    		{
    			document.getElementById("mt3").innerHTML = mat
    		}
    
    		function defMat4(mat)
    		{
    			document.getElementById("mt4").innerHTML = mat
    		}
    
    		function defMat5(mat)
    		{
    			document.getElementById("mt5").innerHTML = mat
    		}
    		</script>
    	</head>
    
    
    <body>
    Material 1; 
    	<b id="mt1">Material</b>
    	<br />
    Material 2; 
    	<b id="mt2">Material</b>
    	<br />
    Material 3; 
    	<b id="mt3">Material</b>
    	<br />
    Material 4; 
    	<b id="mt4">Material</b>
    	<br />
    Material 5; 
    	<b id="mt5">Material</b>
    	<br />
    </body>
    </html>
    

    It seems that the functions of my javascript code are note called because the Webdialog does diplay, but the bold "Material" strings do not get replaced by the proper material names. I know people often get tricked while passing strings from ruby to javascript but in my case I cannot figure out where my error is.

    Any ideas?

    1 Reply Last reply Reply Quote 0
    • T Offline
      thomthom
      last edited by 2 Nov 2011, 17:54

      You're using execute_string before you have displayed the webdialog. You must wait until the dialog has openend and the HTML DOM loaded before you can make the webdialog accept commands.

      Thomas Thomassen — SketchUp Monkey & Coding addict
      List of my plugins and link to the CookieWare fund

      1 Reply Last reply Reply Quote 0
      • T Offline
        T.M
        last edited by 2 Nov 2011, 18:08

        I guess it's not just a question of putting the $wd.show on top, so how can I be sure in my code that execute_script is executed when the HTML DOM is loaded? Do you have any suggestions of correction for my code (even global) that could lead me?

        1 Reply Last reply Reply Quote 0
        • T Offline
          thomthom
          last edited by 2 Nov 2011, 18:38

          Have a look at these notes about WebDialog: http://forums.sketchucation.com/viewtopic.php?f=180&t=23445

          Thomas Thomassen — SketchUp Monkey & Coding addict
          List of my plugins and link to the CookieWare fund

          1 Reply Last reply Reply Quote 0
          • D Offline
            Dan Rathbun
            last edited by 3 Nov 2011, 00:38

            The show() method of the UI::WebDialog class, is actually an optional block method.

            However there is a bug, in that the block does not work on the Mac.

            If you care only for PC, then you can do:

            module TM
              module MatlDlg
                @@wd = UI;;WebDialog.new( "Dialog" )
                @@dialog_path = Sketchup.find_support_file( "Code/Document.html", "Plugins" )
                @@wd.set_file( @@dialog_path )
                  
                @@wd.show {
                  vect = Geom;;Vector3d.new(0, 0, -1)
                  f_count = 1
                  Sketchup.active_model.active_entities.each{|j|
                    if j.class == Sketchup;;Face && vect.samedirection?(j.normal) == false
                      arg = "'" + j.material.name + "'"
                      @@wd.execute_script("defMat" + f_count.to_s + "(" + arg + ")")
                      f_count = f_count + 1
                    end #if
                  }
                }
              end #module MatlDlg
            end #module TM
            
            

            I also suggest strongly that you organize your "filespace" by having all YOUR code within a "user/author" subfolder that identifies YOU. "TM" or whatever instead of a generic foldername like "Code".
            Beneath your author folder you make a subdir for each plugin or project.
            So the example above, would be in "Plugins/TM/MatlDlg" subdir or similar.

            I'm not here much anymore.

            1 Reply Last reply Reply Quote 0
            • D Offline
              draftomatic
              last edited by 8 Nov 2011, 00:02

              @dan rathbun said:

              I also suggest strongly that you organize your "filespace" by having all YOUR code within a "user/author" subfolder that identifies YOU. "TM" or whatever instead of a generic foldername like "Code".
              Beneath your author folder you make a subdir for each plugin or project.
              So the example above, would be in "Plugins/TM/MatlDlg" subdir or similar.

              Globals are also dangerous, so $wd should not be used. I worked out a system for my plugin where I wrap all WebDialogs inside their own class and set the WebDialog as an instance variable. You should then wrap said class in your own module to be extra safe no other plugins will clash with it. Give your module a (hopefully) unique name.

              Most scripters are not full-blown software engineers, so software architecture issues like this can be difficult. I could post a sample wrapped WebDialog class if you're interested.

              1 Reply Last reply Reply Quote 0
              • D Offline
                Dan Rathbun
                last edited by 8 Nov 2011, 10:31

                @draftomatic said:

                Globals are also dangerous, so $wd should not be used.

                As I showed in the example above, when you wrap your plugins in their own module namespace (within your "author" toplevel module namespace,) then globals are not needed, and you can use a module var ( @@var_name,) instead, to hold the reference to the UI::WebDialog instance object. In this case there is no need to class wrap the dialog, or subclass the UI::WebDialog class (unless your doing something really fancy.)

                @draftomatic said:

                I worked out a system for my plugin where I wrap all WebDialogs inside their own class and set the WebDialog as an instance variable.

                In Ruby, class Class, is the child subclass of class Module. So a class Class instance (ie, a custom class,) has everything a module has, and in addition can be have more than one instance. (Hence instance variables.)
                The rule of thumb, is that if the code only needs 1 copy (ie, a singleton instance,) then the code should be a Module.
                Most webdialogs are singleton in nature.
                I have several times showed how to only create one instance of a webdialog. Here's one of my examples: http://forums.sketchucation.com/viewtopic.php?f=180&t=39836#p352081 (The module var @@editor would hold the reference the webdialog instance, in the example.)

                @draftomatic said:

                You should then wrap said class in your own module to be extra safe no other plugins will clash with it. Give your module a (hopefully) unique name.

                It's just easier, to create a unique toplevel "Author" namespace, and have each one of your plugins in a submodule of that namespace. Your submodules and classes will not clash with anyone else's; and it's up to you to be sure any classes within your "author" namespace don't clash with each other. Meaning.. a class that is only used by a specific one of your plugins, should be defined within a specific plugin's submodule.
                Any classes that you share with more than one of your plugins, can be defined within your "author" toplevel module. (The same holds true for constants.)

                I'm not here much anymore.

                1 Reply Last reply Reply Quote 0
                • T Offline
                  T.M
                  last edited by 10 Nov 2011, 14:39

                  Thanks for you responses!

                  And yes you are right, I need to organize my scripts better, you've been of great advice!

                  1 Reply Last reply Reply Quote 0
                  • 1 / 1
                  1 / 1
                  • First post
                    6/8
                    Last post
                  Buy SketchPlus
                  Buy SUbD
                  Buy WrapR
                  Buy eBook
                  Buy Modelur
                  Buy Vertex Tools
                  Buy SketchCuisine
                  Buy FormFonts

                  Advertisement