[Code] Material.names to Webdialog.
-
@jolran said:
Also if I understood it correctly there is only maximum message limit FROM webdialog to Ruby?? For me that won't be a problem if thats true...
True that there is a limit going back to Ruby because the data is sent via the URI string using
%(#8000BF)[window.location.href]
-
Ah, you're using a hidden input field because you're worried about a max size?
There is a limit for sure when you call from WebDialog to Ruby, because it uses an URI to pass the data.
But I'm not so sure if there's a limit by using WebDialog.execute_script... What I do know is that for every time you call WebDialog.execute_script a <SCRIPT> element is inserted into the <BODY> element containing the argument to the method. This is evaluated into JS. Not sure exactly how that <SCRIPT> element is injected, but if you're worried about the size then you can run some tests with dummy data.
-
@jolran said:
Took like forever to figure out one has to convert the JSON when extracting it from an inputfield or such. With something like:
var containr = eval('(' + $('#container').val() + ')') ;
(1) Get in habit of using the javascritpt function:
%(#8000BF)[JSON.parse( *string* )]
as it has some built-in safeguards against running code that malicious persons can hide inside strings. If you use%(#8000BF)[eval()]
, hidden malicious code can be executed.There is a saying in the javascript world: "eval is evil" because it is an attack vector.
(2) Regarding a hidden input field. I do not not think you actually need to use one. This is usually done when sending data to a webpage via the URI (like how a search engine's form page, sends the search string using
%(#8000BF)[?search=someword]
.)You should be able to send the data directly to a javascript object, thus:
dialog.execute_script( %q{dataObject = JSON.parse('} + json_string + %q{')} )
(3) JSOs can be nested, as well as containing nested Arrays, etc., so JSON strings allow the nesting of JSOs and Arrays. ... and so forth. The nested Arrays could wrap more nested JSOs and / or Arrays, etc. (There is a limit to the nesting level but it is huge, and you'll never likely run into the limit.)
-
There is another topic where we discuss the limit on the number of
%(#8000BF)[<SCRIPT>]
elements that Microsoft Internet Explorer imposes... and Jim posted a JS cleanup function that removes these%(#8000BF)[<SCRIPT>]
elements that SketchUp appends to the%(#8000BF)[<BODY>]
element. (They have no ID attribute, so that can serve as a filter if there are%(#8000BF)[<SCRIPT>]
elements that you do not want removed.) -
<span class="syntaxdefault"><br />w</span><span class="syntaxkeyword">=</span><span class="syntaxdefault">UI</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">WebDialog</span><span class="syntaxkeyword">.new<br /></span><span class="syntaxcomment">#<UI;;WebDialog;0xed46184><br /><br /></span><span class="syntaxdefault">w</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">set_html</span><span class="syntaxkeyword">(</span><span class="syntaxstring">'Hello'</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">nil<br /><br />w</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">show<br />true<br /><br />w</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">execute_script</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">%{</span><span class="syntaxdefault">alert</span><span class="syntaxkeyword">(</span><span class="syntaxstring">'#{'</span><span class="syntaxdefault">X</span><span class="syntaxstring">'*1_000_000_00}'</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length</span><span class="syntaxkeyword">);}</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">true<br /><br />w</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">execute_script</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">%{</span><span class="syntaxdefault">alert</span><span class="syntaxkeyword">(</span><span class="syntaxstring">'#{'</span><span class="syntaxdefault">X</span><span class="syntaxstring">'*1_000_000_000}'</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length</span><span class="syntaxkeyword">);}</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">Error</span><span class="syntaxkeyword">;</span><span class="syntaxdefault"> </span><span class="syntaxcomment">#<TypeError; can't modify frozen string><br /></span><span class="syntaxkeyword">(eval);</span><span class="syntaxdefault">155<br /></span>
In the case of sending a string generated by
'X'*1_000_000_00
I got this alert - as expected:
When I tried to increase it more you see Ruby spat out an error. That's not an issue with the Ruby -> WebDialog communication, but Ruby struggling to generate such a big string. It's a bit odd it talks about frozen string... Not quite sure what's going on.
But we're talking about nearly a 1GB string here... :s
It worked up until nearly 100MB!When I tried to run
'X'*1_000_000_00
again after the previous failure I got this from the WebDialog:
So, unless you are sending crazy amount of data, hundreds of hundreds of megabyte then there should be no need to send the data via a hidden INPUT field. The INPUT field is only required when you send data from the WebDialog to Ruby.
-
@dan rathbun said:
There is another topic where we discuss the limit on the number of
%(#8000BF)[<SCRIPT>]
elements that Microsoft Internet Explorer imposes...?
Limit to the number of SCRIPT elements? I've not heard of that. Got a link to that thread?(Mind you, I clean them up anyway as I don't want them filling up the DOM space.)
-
@dan rathbun said:
JSON.parse( string )
Support chart: http://caniuse.com/json
All the way back to IE8. (I'd not worry about older IE versions any more - no unless you're doing commercial development and know a significant share of your potential users are stuck with the damned filth.) -
@thomthom said:
So, unless you are sending crazy amount of data, hundreds of hundreds of megabyte then there should be no need to send the data via a hidden INPUT field. The INPUT field is only required when you send data from the WebDialog to Ruby.
Just adding that ... technically... you do not actually send this large data to Ruby, instead you notify the Ruby-side that the data is ready, ... and then you read it from the Ruby-side using the
dialog.get_element_value()
method. -
@thomthom said:
Support chart: http://caniuse.com/json
All the way back to IE8. (I'd not worry about older IE versions any more - no unless you're doing commercial development and know a significant share of your potential users are stuck with the damned filth.)OH! Nice page to bookmark!
@unknownuser said:
Note: Requires document to be in IE8+ standards mode to work in IE8.
Lesson always use a
%(#8000BF)[<DOCTYPE>]
tag!If a customer must use IE7, you can always supply the JSON code. (There is an old topic where ThomThom and I discussed this JSON compatibility issue in detail.)
-
@dan rathbun said:
@thomthom said:
So, unless you are sending crazy amount of data, hundreds of hundreds of megabyte then there should be no need to send the data via a hidden INPUT field. The INPUT field is only required when you send data from the WebDialog to Ruby.
Just adding that ... technically... you do not actually send this large data to Ruby, instead you notify the Ruby-side that the data is ready, ... and then you read it from the Ruby-side using the
dialog.get_element_value()
method.Yes, though what I was testing now was sending data from Ruby to WebDialog. I wasn't sure if there was a size limit there.
-
@dan rathbun said:
Lesson always use a
%(#8000BF)[<DOCTYPE>]
tag!And META tag to trigger IE "edge" mode.
-
@thomthom said:
Limit to the number of SCRIPT elements? I've not heard of that. Got a link to that thread?
I cannot find it anymore as MS overhauled MSDN (and alot of content disappeared!)
I may be confused with those loaded as resources via
%(#8000BF)[<LINK>]
tags:
http://technullogy.wordpress.com/2010/03/05/internet-explorer-limits-css-and-script-resources-to-30/But I thought I saw a message at the bottom of one of the pages, that had to do with dynamically adding elements. I checked the
%(#8000BF)[appendChild()]
and%(#8000BF)[createElement()]
pages, but there is little there now. (They cleaned house!)Anyway.. we are going off topic... if you clean them up, you'll never hit any limit if there is one.
-
Just a note on the original topic, it reminded me of once when a user sent me a problem scene that was screwing up my webdialog. The problem turned out being that one of his material names had a leading control character -- unit separator, which is not printable, but which you can enter into a SU material name by hitting ALT+031. I don't recall precisely in what way that was tripping things up, but thought I'd mention it anyway.
-
OK! a lot of new stuff to digest. This forum is great.
It seems like I do a lot of things in almost the right way, or the wrong way.
I wasent sure in wich direction there was a message size limit. So to defend against that I interpreted from some topic that you could insert arrays or such in hidden inputfields.
Sending layers, materials and component names it can easily become over 2000 characters. But in reality I won't reach that large amounts like during some tests here from Thomthom.Dan.
JSON.parse( string ) sound like a better solution then. As long as I accept the user has IE8 +. For Mac that will not be an issue?
I believe that the user is probably working with SU on his or her major workstation which should be up do date.
Still have to figure out how to nest JSON or rather "hashes ready" for JSON in ruby first. Maybe use the method Thomthom already provided if it will work for that purpose.
There is bunch of info regarding " require 'json' ". But that module is not avilable in Sketchup I suppose..Regarding "code cleanup after script" I saw that thread, and put Thomthoms JQ body-detach script in the "$doc.ready" function. Don't know if theres the right place to put it, but I sure did
Maybe it should be done in a callbackSo just to make clear, I can forget about hidden inputfields and just send the data from SU exect.script to a global array in JS then? Like Thomthoms in this topic provided" materials.rb" do.
JD Hill. Thanks.
Sounds a bit like the issue I had before, I was also conserned about the end user going heywild on the keybord with names and such.
I suppose you havent had a look at Thomthoms script? Or maybe you are already doing something similar.
Well anyway, it's cleverly using 1 string stored as .text for display in webdialog and keeping the original SUmaterial.name stored as value. So one send the value to SU from JS.
In case of materials in SU, display.name is used, but I dont think there is nothing stopping you from doing some escaping on that string either, cause it wont affect the value. If one can put anything one like as value or not I havent got a clue.. -
@jolran said:
Regarding "code cleanup after script" I saw that thread, and put Thomthoms JQ body-detach script in the "$doc.ready" function. Don't know if theres the right place to put it, but I sure did
Maybe it should be done in a callbackWhat I did to simplify communication was to set up wrappers. I wrote a method that would allow me to send the function name and then a set of arbitrary arguments which would be automatically formatted into a string for execute_script.
http://www.thomthom.net/software/sketchup/tt_lib2/doc/TT/GUI/Window.html#call_script-instance_method
I can callwebdialog.call_script( 'foobar', 'Hello', 5, [1,2,3] );
That takes care of formatting and escaping the string.
I even extended it a bit further so I'm actually calling a JS proxy function that calls the desired function and returns the return value back to Ruby. So I can do stuff like this:JavaScript
<span class="syntaxdefault"><br /></span><span class="syntaxkeyword">function </span><span class="syntaxdefault">multiply</span><span class="syntaxkeyword">( </span><span class="syntaxdefault">a</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">b </span><span class="syntaxkeyword">)<br />{<br /> return </span><span class="syntaxdefault">a </span><span class="syntaxkeyword">* </span><span class="syntaxdefault">b</span><span class="syntaxkeyword">;<br />}<br /> </span><span class="syntaxdefault"></span>
Ruby
<span class="syntaxdefault"><br />result </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">webdialog</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">call_script</span><span class="syntaxkeyword">( </span><span class="syntaxstring">'multiply'</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">3</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">5 </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">puts result<br /></span><span class="syntaxcomment"># => 15<br /> </span><span class="syntaxdefault"></span>
@jolran said:
So just to make clear, I can forget about hidden inputfields and just send the data from SU exect.script to a global array in JS then? Like Thomthoms in this topic provided" materials.rb" do.
The proxy JS function I mentioned in the previous example also cleans up the SCRIPT elements. I automated all the common things you do into wrapper functions and made it a convention to call JS functions from Ruby.
-
Thomthom, thanks.
I have been poking around in TTlib. But sometimes the picture is so big I can't see the details
Also I totally forgot to check out your thomthom.net docs. Bunch of info there.
With your explanations here I might understand the code better.
Will give it a try. -
@jolran said:
I have been poking around in TTlib. But sometimes the picture is so big I can't see the details
Also I totally forgot to check out your thomthom.net docs. Bunch of info there.
With your explanations here I might understand the code better.
Will give it a try.Yea, the library is quite big. And I haven't commented it well enough. True that. But hopefully you can make use of the concept.
My library is built around populating the webdialog with Ruby classes - letting me develop UIs using just Ruby. But along with that blog entry I might see if I can decouple my bridge framework.
-
@unknownuser said:
My library is built around populating the webdialog with Ruby classes - letting me develop UIs using just Ruby.
I see, must be convenient doing like that in the long run.
For me just now I only need to send in some lists and values to my dialog and hit an OK buttons and start Ruby.So the strategy right now is to nest a hash=>json object with list of material, layers, components and default values for inputboxes. And send through a function like you do in materials.rb.
@unknownuser said:
But along with that blog entry I might see if I can decouple my bridge framework.
Do you mean a bridge light? Sounds interrseting.
It seems there is no easy way to get around that webdialogs have to be complicated. Looks like there are many things that can go wrong. And the step from SU's inputbox is quite large.http://sketchucation.com/forums/viewtopic.php?f=180&t=35969#p316774
This topic covers alot about JSON in Sketchup, BTW. Might mention it if someone enters here looking for info bout the subject. -
Untested, but should let you nest Hash objects.
<span class="syntaxdefault"><br /> </span><span class="syntaxcomment"># Very simplified method just for this example's purpose.<br /> </span><span class="syntaxdefault">def self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">hash_to_json</span><span class="syntaxkeyword">( </span><span class="syntaxdefault">hash</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">pretty_print </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">false </span><span class="syntaxkeyword">)<br /> if </span><span class="syntaxdefault">pretty_print<br /> nl </span><span class="syntaxkeyword">= </span><span class="syntaxstring">"\n"<br /> </span><span class="syntaxdefault">tab </span><span class="syntaxkeyword">= </span><span class="syntaxstring">" "<br /> </span><span class="syntaxkeyword">else<br /> </span><span class="syntaxdefault">nl </span><span class="syntaxkeyword">= </span><span class="syntaxstring">""<br /> </span><span class="syntaxdefault">tab </span><span class="syntaxkeyword">= </span><span class="syntaxstring">""<br /> </span><span class="syntaxdefault">end<br /> <br /> json </span><span class="syntaxkeyword">= </span><span class="syntaxstring">"{#{nl}"<br /> </span><span class="syntaxdefault">items </span><span class="syntaxkeyword">= []<br /> for </span><span class="syntaxdefault">key</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">value in hash<br /> </span><span class="syntaxkeyword">if </span><span class="syntaxdefault">value</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">is_a</span><span class="syntaxkeyword">?( </span><span class="syntaxdefault">Hash </span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">value_hash </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">hash_to_json</span><span class="syntaxkeyword">( </span><span class="syntaxdefault">value</span><span class="syntaxkeyword">, </span><span class="syntaxdefault">pretty_print </span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">items </span><span class="syntaxkeyword"><< </span><span class="syntaxstring">"#{tab}#{key.inspect}; #{value_hash}"<br /> </span><span class="syntaxkeyword">else<br /> </span><span class="syntaxdefault">items </span><span class="syntaxkeyword"><< </span><span class="syntaxstring">"#{tab}#{key.inspect}; #{value.inspect}"<br /> </span><span class="syntaxdefault">end<br /> json </span><span class="syntaxkeyword"><< </span><span class="syntaxdefault">items</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">join</span><span class="syntaxkeyword">(</span><span class="syntaxstring">",#{nl}"</span><span class="syntaxkeyword">)<br /> </span><span class="syntaxdefault">json </span><span class="syntaxkeyword"><< </span><span class="syntaxstring">"#{nl}}#{nl}"<br /> </span><span class="syntaxdefault">json<br /> end<br /></span>
-
@dan rathbun said:
You can sort the arrays before you convert the data hash to JSON:
data["materials"].sort!
I'd sort it in the WebDialog - as per my example - because SketchUp Ruby only knows ASCII while the WebDialog can handle UTF-8.
Advertisement