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

I just got a DENIED back from the SketchUp Extension Warehouse validation team. The main error they found was that my HtmlDialog routine passed a number with a period / point separator to my Ruby routine when their system expected a comma. This caused SketchUp’s Ruby method .to_l (converts numbers to SketchUp length objects) to throw the following error -

Error: #<ArgumentError: Cannot convert "445.7044372558594" to Length> [...]/sketchup/plugins/fms_windoorplus/make_wplus_from_html_dialog.rbe:24:in `to_l' [...]/sketchup/plugins/fms_windoorplus/make_wplus_from_html_dialog.rbe:24:in `block in windowplus_from_htmldialog' [...]/sketchup/plugins/fms_windoorplus/make_wplus_from_html_dialog.rbe:19:in `each' [...]/sketchup/plugins/fms_windoorplus/make_wplus_from_html_dialog.rbe:19:in `windowplus_from_htmldialog' [...]/sketchup/plugins/fms_windoorplus/html_dialog_start.rbe:55:in `block in show_dialog'

I’m not sure what is the best thing to do about this.

Any advice would be much appreciated.

I would use the RegionalSettings .decimal_separator class_method to convert the passed string to the right (current system locale) format.

Off topic:
:innocent: I’m pretending to be your defense attorney: :wink:
The native Scale Tool doesn’t fully work either with some regional/locale settings.

1 Like

Is that on the Ruby side or the Html side?

Ignore, I just spotted that your text is a link. Thanks very much.

1 Like

Nice trick :slightly_smiling_face:

1 Like

I wouldn’t explicitly replace anything with the local decimal separator. SketchUp has symmetrical methods for converting between Length objects and string representation. You don’t need to care what the local format is, as long as you use the right methods.

length_value= 5.m
string_output = length_value.to_s

# Show this value to the user

string_input = "5000 mm" # Or whatever the user enters
length_value = string_input.to_l

Don’t use floats when you want to represent a length (other than when serializing the value to send it outside of the Ruby world). Use Length internally and convert between Length and String for the UI layer, and units and decimal separators just works.

1 Like

The problem is that the SketchUp Length Class trips up when passed an otherwise valid string in a country where a comma is expected for the decimal separator. I would love if the Length Class could deal with this but it doesn’t seem to. Below is the error output. The value wplus_width is the String “0.9” but when I make my computer think it is German by changing its Windows 10 Region and Number settings my Extension throws this error.

wplus_width is 0.9
wplus_width.class is String
Error: #<ArgumentError: Cannot convert "0.9" to Length>
C:/SketchUp_Plugins/My_Extensions/WinDoorPlus/in_development/in_notepad_plus_plus/make_wplus_from_html_dialog.rb:12:in `to_l'
C:/SketchUp_Plugins/My_Extensions/WinDoorPlus/in_development/in_notepad_plus_plus/make_wplus_from_html_dialog.rb:12:in `windowplus_from_htmldialog'
c:/users/francis/appdata/roaming/sketchup/sketchup 2022/sketchup/plugins/fms_windoorplus/html_dialog_start.rbe:55:in `block in show_dialog'

This string should not be defined as “0.9”. If you use 0.9.m to define a Length object, and then use #to_s to format the string, you get a valid decimal separator.

Having #to_l support invalid decimal separators is not a solution here. The value should be correctly formatted before being shown to the user. Then the user can be expected to use the valid local separator.

The javascript end of my extension (it uses HtmlDialog) converted the number to a string. I will see if I can stop this happening at the Html end. My slight worry is that somehow a comma will appear as a separator in the Html side. However, that didn’t happen for the Extension reviewer and doesn’t happen on my reset as German machine either.

(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?