Javascript problem
-
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?
-
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.
-
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?
-
Have a look at these notes about WebDialog: http://forums.sketchucation.com/viewtopic.php?f=180&t=23445
-
The
show()
method of theUI::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. -
@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.
-
@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 theUI::WebDialog
instance object. In this case there is no need to class wrap the dialog, or subclass theUI::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 classModule
. So a classClass
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 aModule
.
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.) -
Thanks for you responses!
And yes you are right, I need to organize my scripts better, you've been of great advice!
Advertisement