HtmlDialog. User's system expects a comma delimiter. Number.to_l throws an error

(Although not the solution,) you can do an end around thus …

width = wplus_width.to_f.to_l

This is what you should do. The metric users should see numeric string values using their decimal separator.

I refer you to ThomThom’s blog article on dealing with units in SketchUp extensions …

I’ll not do the work around. I will look at Thom Thom’s blog article. Many thanks.

1 Like

The JavaScript part of the extension should not be formatting the length strings. Only Length#to_s should be used for this, and the correctly formatted string should be sent to the JS side.

1 Like

The JavaScript side gets the numbers from the Html page then calls

sketchup.getUserInput(wPlus_width, etc...}

I was just sending this data as obtained by

document.getElementById("wPlus_width").value

in the JavaScript.

Although my computer is now set up as German, the HtmlDialog is showing decimal points, not decimal commas. I really do need to read Thom Thom’s blog article.

Would be good if everyone agreed a decimal point for everywhere :slightly_smiling_face:

Perhaps you sent the original value as a numeric ? As Christina said, convert to a string on the Ruby side and send to JS as a string with the proper user decimal separator. Then the JS should send the edited string back to Ruby where your extension can convert it back to a Length object with #to_l.

document.getElementById("wPlus_width").value

converts the value to a string. This is the value which is in the parameter list of

sketchup.getUserInput(wPlus_width, etc...}

All of this is in the Html side of things. The Ruby side gets the parameter as output from the Html side. In this case a string which looks like “9.0”. A decimal number in America/British format. That produces the error in

"9.0".to_l

on a German machine.

I don’t send anything from Ruby to Html. As I understand it, the values are obtained from the HtmlDialog and then sent to my Ruby method.

On the Ruby side there is a SketchUp method called show_dialog and it calls a SketchUp HtmlDialog method called ‘add_action_callback’ on an instance variable of the class HtmlDialog. It takes the name of a function, ‘getUserInput’ of an Html object called sketchup and this seems to obtain the parameters. All of the parameters are strings but some are strings representations of numbers.

I don’t know anything about the internal workings of the Html object ‘sketchup’ nor the inner workings of SketchUp’s Ruby class HtmlDialog and I don’t think I need to.

I just need the decimal separator to be correctly displayed in my dialog (it is always point/dot even on a German machine where it should be a comma) and correctly interpreted by the SketchUp Ruby method .to_l (a point in countries where this is the norm and a comma for the rest). I guess I’ll need a javascript function which recognizes the country and sets the comma. That would probably fix the issue with ‘.to_l’. I’m not sure but I’ll try that first.

Everything seems to work fine on my machine when it is set up as American.

Where is the “9.0” string coming from? Where is this string being defined?

It is a number in the web dialog which the user can change. I assign a float to the variable which holds it. But the number seems to get converted to a string when I fetch it back from the Html. The Html doesn’t seem to automatically convert the decimal separator. It takes the number I’ve written in the Javascript and converts it to a string but retaining the decimal separator I have given the number. I thought that kind of conversion would have been automatic but it seems I’m wrong.

JavaScript has no concept of the local decimal separator. Don’t use JavaScript floats to represent lengths. Convert a Length to a String in Ruby, send the STRING to the JavaScript HTML side, and parse the STRING back to a length on the Ruby side.

1 Like

If I understood right, what the user is typing into the html dialog, you want to interpret as the current unit value.
So if the unit setting in SU is mm and the user type “9.0” you want to get 9mm lenght.
But if the unit setting in SU is inch and the user type “9.0” you want to get 9" lenght.

Lets assume the user can type “9.0” or “9,0”. This should be interpreted as same values.
This method will do that:

    def to_locale_string( string )
      string.tr(',', '.').tr('.', Sketchup::RegionalSettings::decimal_separator)
    end
    len1 = to_locale_string( "9.0" ).to_l 
    len2 = to_locale_string( "9,0" ).to_l

That is a surprising fact about JavaScript. Should have guessed it maybe. I’m working on a Windows 10 computer which is set up for Ireland, where I live. If the Extension reviewer had not brought the decimal separator thing to my attention I’d not have known it was an issue. I’ve changed my computer’s setting to German to test this.

So I’m thinking I use the ‘#execute_script’ HtmlDialog method to set the string variables in the local machine. I convert the local numbers to strings using ‘.to_l.to_s’ on the Ruby side and then send them to the Html side with something like

wPlus_width = 9.0.to_l.to_s

js_command = "document.getElementById('id').innerHTML = wPlus_width "
dialog.execute_script(js_command)

Am I on the right track?

.innerHTML= may not be the correct JS method. Prefer .value= or innerText=.

But even better would be to use %{} parameter replacement to stuff the values into the HTML file before you send it to the dialog.

Rememeber this example topic ?

You do similar with HTML text in Ruby:

# form_data is a hash of values for the HTML form
# (you can use another reference name if you like)

# Load the HTML template file into a string:
html = File.read(File.join(__dir__,"my_dialog.html"))

# Replace the %{} parameters in the HTML with data from the hash:
@dlg.set_html( html % form_data )

# Set other dialog options and show it:
@dlg.show

So you load an HTML file into a html string object.
This file is setup as a template with %{fieldname} parameters that match the keynames of your Ruby value hash.

IE in the HTML template file …

<input type="text" id="wPlus_width" name="Width" value='%{width}'>

… And in Ruby you load up a hash of values like …

form_data = {
  width: wPlus_width.to_s # Assume this is a SketchUp Length object
  # other data fields
}

Now the call to html % form_data would replace the %{width} substring in the HTML file string with the value marked with the :width key from the hash.

As Julia said, if you are using Length objects on the Ruby side, it’s class’ #to_s method will automagically use the correct decimal delimiter for the numeric string in the form_data hash.
When the string is sent back to Ruby, SketchUp’s String#to_l method automagically knows what the decimal separator is.


ADD: I also explained the above %{} replacement concept here …

… and (further down that topic) …

You are getting closer!

You need to interpolate wPlus_width into the js_command string. Otherwise JavaScript will wonder what wPlus_width is. Also you need quotation marks around it since it’s a string, not a number.

In most cases, this would work, but not if the model unit is set to inches with the unit displayed. That would cause the quotation mark used inside the string to clash with the syntax itself.

js_command = "document.getElementById('id').value= \"#{wPlus_width}\" "

Instead, use this where the JSON formatting automatically escapes special characters for you. This is a general approach that can be used for sending any string rom Ruby to JavaScript.

js_command = "document.getElementById('id').value= #{wPlus_width.to_s.to_json} "

I’m looking at this. It will take a little time to digest. Thank you for the help.

I’m going over your suggestions. It will take a little time to see where it goes. Thank you for the help!

I’ve rewritten some code from An example … to implement Dan’s suggestions. It works when I change the type of length, breadth and depth in the html form from number to text. If I leave the type as number the html won’t show the locale numbers with their comma decimal separator. The fields in the HtmlDialog form show as blank fields. I guess this is a fundamental of html that it only recognises points as decimal separators and so I must ‘type’ floating point numbers as ‘text’. When I change the type to text the HtmlDialog form fields show the locale numbers correctly and the data is correctly interpreted on the Ruby side and I get a box modeled in my SketchUp model.

The code below doesn’t work -

<form>
	length: <input id='id1' type='number' name='length' value='%{length}' required><br>
	breadth: <input id='id2' type='number' name='breadth' value='%{breadth}' required><br>
	depth: <input id='id3' type='number' name='depth' value='%{depth}' required>
</form>

but this does work

<form>
	length: <input id='id1' type='text' name='length' value='%{length}' required><br>
	breadth: <input id='id2' type='text' name='breadth' value='%{breadth}' required><br>
	depth: <input id='id3' type='text' name='depth' value='%{depth}' required>
</form>

The only drawback is that the user loses the incremental arrows on the right hand side of the input field.

I could post the entire example if the forum thought it would be useful. Just let me know.

Thank you to every one who helped with this. Cultures and their diversity make programming interesting.

1 Like

Thank you. That is a possibility. I’ve tried Dan and ene_su’s way and it works fine. It uses only .to_l and .to_s without the need of a custom method. Interesting that it can be done that way to though.

This isn’t unique to HTML. A float can’t express a specific decimal separator or other characters. 5 m, 300mm, 6' 6 1/2" etc must be expressed as strings. Going from Length to Float and then to String removes the characters and only keep numbers. You need to go from Length directly to String, without going through a Float.

That is true. I take the point. I was thinking of numbers in a much too mathematical way, and not in the way they are used in life. Currency is yet another branch of the number representation tree.

Thanks for the help.

1 Like

I’ve flushed out so many bugs in different software because I use non-US locales and non-English characters. Even in SketchUp. It’s an area that is non-trivial and many makes assumptions that doesn’t hold up in the wild.

1 Like