1+ // Enum to help keep track of unit systems rather than hard-coded strings throughout the code
2+ const Units = Object . freeze ( {
3+ Metric : "mm" ,
4+ Imperial : "inches"
5+ } ) ;
6+
7+ // object to hold offsets in a spot that is easy to edit
8+ const offsets = Object . freeze ( {
9+ xrail_core : 169 ,
10+ yrail_minus_work : 255 ,
11+ ytable_minus_work : 313 ,
12+ xbelt_extra : 180 ,
13+ ybelt_extra : 200 ,
14+ xtable_extra : 110 ,
15+ xrail_cushion : 3
16+ } ) ;
17+
18+ // initialize current display unit
19+ var displayUnit = Units . Metric ;
20+
21+ // To prevent rounding error creep, we are going to keep the desired size in
22+ // variables instead of relying on the after-conversion number on display in the textboxes
23+ var xUsable = 1220 ;
24+ var yUsable = 2440 ;
25+ var xThickness = 6.5 ;
26+
27+
28+ /**
29+ * Update display.
30+ *
31+ * This updates the visual components on the page with the correct text, etc. to match the selected unit.
32+ *
33+ * @param {Units } currentUnit Current Display unit.
34+ */
35+ function setUnitDisplay ( currentUnit ) {
36+ switch ( currentUnit ) {
37+ case Units . Metric :
38+ // Find all the labels and change them to inches
39+ $ ( ".units" ) . text ( Units . Metric ) ;
40+ // Set the step attributes (you can also set other attributes here, like min, max, whatever)
41+ $ ( "input[name=xwork]" ) . attr ( {
42+ "step" : 10.0
43+ } ) ;
44+ $ ( "input[name=ywork]" ) . attr ( {
45+ "step" : 10.0
46+ } ) ;
47+ $ ( "input[name=xzplate]" ) . attr ( {
48+ "step" : 0.1
49+ } ) ;
50+ break ;
51+ case Units . Imperial :
52+ // Find all the labels and change them to inches
53+ $ ( ".units" ) . text ( Units . Imperial ) ;
54+
55+ // Set the step attributes (you can also set other attributes here, like min, max, whatever)
56+ $ ( "input[name=xwork]" ) . attr ( {
57+ "step" : 0.125
58+ } ) ;
59+ $ ( "input[name=ywork]" ) . attr ( {
60+ "step" : 0.125
61+ } ) ;
62+ $ ( "input[name=xzplate]" ) . attr ( {
63+ "step" : 0.004
64+ } ) ;
65+ break ;
66+ }
67+ }
68+
69+ /**
70+ * Switch to Metric
71+ *
72+ * This updates the inputs on the page with the correct text to match the selected unit, and updates the calculator
73+ * Should be called when the unit selector switches to mm
74+ */
75+ function to_mm ( ) {
76+ var isUnitChanging = displayUnit === Units . Imperial ;
77+ displayUnit = Units . Metric ;
78+ setUnitDisplay ( displayUnit ) ;
79+
80+ // Get the current units
81+ if ( isUnitChanging ) {
82+ // Change the units.
83+ // If we are changing from inches, round up to the next highest mm to keep display clean
84+ // Underlying values remain the same to preserve calculation and prevent rounding error creep when switching back and forth
85+ $ ( "input[name=xwork]" ) . val ( Math . ceil ( xUsable ) ) ;
86+ $ ( "input[name=ywork]" ) . val ( Math . ceil ( yUsable ) ) ;
87+
88+ // XZ plate thickness might require a little more accuracy so just display to 2 decimal places. This is more likely a mcahined part
89+ // than wood being cut with simple tools
90+ $ ( "input[name=xzplate]" ) . val ( parseFloat ( xThickness . toFixed ( 2 ) ) ) ;
91+ }
92+
93+ // Recalculate the rest of the page.
94+ calculate ( ) ;
95+ }
96+
97+ /**
98+ * Switch to Imperial
99+ *
100+ * This updates the inputs on the page with the correct text to match the selected unit, and updates the calculator
101+ * Should be called when the unit selector switches to inches
102+ */
103+ function to_inch ( ) {
104+ var isUnitChanging = displayUnit === Units . Metric ;
105+ displayUnit = Units . Imperial ;
106+ setUnitDisplay ( displayUnit ) ;
107+
108+ if ( isUnitChanging ) {
109+ // Change the units.
110+ $ ( "input[name=xwork]" ) . val ( roundToNearest ( xUsable / 25.4 ) ) ;
111+ $ ( "input[name=ywork]" ) . val ( roundToNearest ( yUsable / 25.4 ) ) ;
112+
113+ // XZ plate thickness might require a little more accuracy so just display to 3 decimal places. This is more likely a mcahined part
114+ // than wood being cut with simple tools
115+ $ ( "input[name=xzplate]" ) . val ( parseFloat ( ( xThickness / 25.4 ) . toFixed ( 3 ) ) ) ;
116+ }
117+
118+ // Recalculate the rest of the page.
119+ calculate ( ) ;
120+ }
121+
122+ /**
123+ * Round Up To Nearest 1/8".
124+ *
125+ * Round up the supplied value to the next nearest 1/8" increment. This only affects Imperial measurements as metric values
126+ * should already be rounded to the nearest whole number.
127+ *
128+ * @param {number } value value to be rounded.
129+ */
130+ function roundUpToNearest ( value ) {
131+ return Math . ceil ( value * 8 ) / 8 ; // Round to .125
132+ }
133+
134+ /**
135+ * Round To Nearest 1/8".
136+ *
137+ * Round up the supplied value to the next nearest 1/8" increment. This only affects Imperial measurements as metric values
138+ * should already be rounded to the nearest whole number.
139+ *
140+ * @param {number } value value to be rounded.
141+ */
142+ function roundToNearest ( value ) {
143+ return Math . round ( value * 8 ) / 8 ; // Round to .125
144+ }
145+
146+ /**
147+ * Reset Workspace
148+ *
149+ * Resets inputs back to initial values. Retains selected unit system
150+ */
151+ function reset_work ( ) {
152+ xUsable = 1220 ;
153+ yUsable = 2440 ;
154+ xThickness = 6.5 ;
155+
156+ switch ( displayUnit ) {
157+ case Units . Metric :
158+ $ ( "input[name=xwork]" ) . val ( xUsable ) ;
159+ $ ( "input[name=ywork]" ) . val ( yUsable ) ;
160+ $ ( "input[name=xzplate]" ) . val ( xThickness ) ;
161+ break ;
162+ case Units . Imperial :
163+ $ ( "input[name=xwork]" ) . val ( roundToNearest ( xUsable / 25.4 ) ) ;
164+ $ ( "input[name=ywork]" ) . val ( roundToNearest ( yUsable / 25.4 ) ) ;
165+
166+ // XZ plate thickness might require a little more accuracy so just display to 3 decimal places. This is more likely a mcahined part
167+ // than wood being cut with simple tools
168+ $ ( "input[name=xzplate]" ) . val ( parseFloat ( ( xThickness / 25.4 ) . toFixed ( 3 ) ) ) ;
169+ break ;
170+ }
171+
172+ calculate ( ) ;
173+ }
174+
175+ /**
176+ * X Usable Cutting Area changed
177+ *
178+ * Update calculator when X Usable changes. Should be called when the X Usable value is changed in the interface.
179+ */
180+ function xwork_changed ( ) {
181+ var xwork = parseFloat ( $ ( "input[name=xwork]" ) . val ( ) ) ;
182+ if ( ! isNaN ( xwork ) ) {
183+ switch ( displayUnit ) {
184+ case Units . Metric :
185+ xUsable = xwork ;
186+ break ;
187+ case Units . Imperial :
188+ xUsable = xwork * 25.4 ;
189+ break ;
190+ }
191+
192+ calculate ( ) ;
193+ }
194+ }
195+
196+ /**
197+ * Y Usable Cutting Area changed
198+ *
199+ * Update calculator when Y Usable changes. Should be called when the Y Usable value is changed in the interface.
200+ */
201+ function ywork_changed ( ) {
202+ var ywork = parseFloat ( $ ( "input[name=ywork]" ) . val ( ) ) ;
203+ if ( ! isNaN ( ywork ) ) {
204+ switch ( displayUnit ) {
205+ case Units . Metric :
206+ yUsable = ywork ;
207+ break ;
208+ case Units . Imperial :
209+ yUsable = ywork * 25.4 ;
210+ break ;
211+ }
212+
213+ calculate ( ) ;
214+ }
215+ }
216+
217+ /**
218+ * XZ Plate Thickness changed
219+ *
220+ * Update calculator when XZ Plate changes. Should be called when the XZ Plate Thickness value is changed in the interface.
221+ */
222+ function xthickness_changed ( ) {
223+ var xzthick = parseFloat ( $ ( "input[name=xzplate]" ) . val ( ) ) ;
224+ if ( ! isNaN ( xzthick ) ) {
225+ switch ( displayUnit ) {
226+ case Units . Metric :
227+ xThickness = xzthick ;
228+ break ;
229+ case Units . Imperial :
230+ xThickness = xzthick * 25.4 ;
231+ break ;
232+ }
233+
234+ calculate ( ) ;
235+ }
236+ }
237+
238+ /**
239+ * Convert to Display Units.
240+ *
241+ * Convert the supplied value to display units. Currently only affects Imperial display unit, as all values are held in memory in Metric
242+ *
243+ * @param {number } value value to be rounded.
244+ */
245+ function convertToDisplayUnits ( val ) {
246+ if ( displayUnit === Units . Imperial )
247+ return val / 25.4 ;
248+ else
249+ return val ;
250+ }
251+
252+ /**
253+ * Update Calculated values.
254+ *
255+ * Take the values in memory and update the calculator section of the page with calculated values in the correct display unit
256+ */
257+ function calculate ( ) {
258+ // Calculate strut plate width first, then use the strut plate dimension to calculate other values
259+ // since this value will be rounded up to the next mm
260+ var xstrut = Math . ceil ( xUsable + offsets . xrail_core ) ;
261+ var xbelts = xstrut + offsets . xbelt_extra ;
262+ var xtable = xstrut + 2 * xThickness + offsets . xtable_extra ;
263+
264+ var yrail = yUsable + offsets . yrail_minus_work ;
265+ var ybelts = yrail + offsets . ybelt_extra ;
266+ var ytable = yUsable + offsets . ytable_minus_work ;
267+
268+ var belt_total = 1 * xbelts + 2 * ybelts ;
269+
270+ // handle the xrail special case where we want a little cushion to makes sure the plates don't kick out
271+ // we do this calculation in display units to make sure rounding errors don't cause us to be 0 or 2 increments off
272+ var convertedXStrut = roundUpToNearest ( convertToDisplayUnits ( xstrut ) ) ;
273+ var xrails = convertedXStrut - roundUpToNearest ( convertToDisplayUnits ( offsets . xrail_cushion ) ) ;
274+
275+ $ ( "span[name=strut]" ) . text ( convertedXStrut ) ;
276+ $ ( "span[name=xrails]" ) . text ( xrails ) ;
277+ $ ( "span[name=yrail]" ) . text ( roundUpToNearest ( convertToDisplayUnits ( yrail ) ) ) ;
278+ $ ( "span[name=xbelts]" ) . text ( roundUpToNearest ( convertToDisplayUnits ( xbelts ) ) ) ;
279+ $ ( "span[name=ybelts]" ) . text ( roundUpToNearest ( convertToDisplayUnits ( ybelts ) ) ) ;
280+ $ ( "span[name=belt_total]" ) . text ( roundUpToNearest ( convertToDisplayUnits ( belt_total ) ) ) ;
281+ $ ( "span[name=xtable]" ) . text ( roundUpToNearest ( convertToDisplayUnits ( xtable ) ) ) ;
282+ $ ( "span[name=ytable]" ) . text ( roundUpToNearest ( convertToDisplayUnits ( ytable ) ) ) ;
283+ }
284+
285+ // Set these up the first time.
286+ $ ( window ) . on ( 'load' , function ( ) {
287+ // Get back to mm
288+ $ ( "input[value=mm]" ) . prop ( 'checked' , true ) ;
289+ $ ( "input[value=inches]" ) . prop ( 'checked' , false ) ;
290+
291+ to_mm ( ) ;
292+
293+ reset_work ( ) ;
294+ } ) ;
0 commit comments