@breakside/jskit 2021.40.1 → 2021.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/Frameworks/DOM.jsframework/Info.json +2 -2
  2. package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
  3. package/Frameworks/FontKit.jsframework/Info.json +2 -2
  4. package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
  5. package/Frameworks/Foundation.jsframework/Info.json +2 -2
  6. package/Frameworks/Foundation.jsframework/JS/JSClass.js +8 -5
  7. package/Frameworks/Foundation.jsframework/JS/JSDateFormatter.js +81 -8
  8. package/Frameworks/Foundation.jsframework/JS/JSImage.js +1 -0
  9. package/Frameworks/Foundation.jsframework/JS/JSIndexPath.js +3 -0
  10. package/Frameworks/Foundation.jsframework/JS/JSLocale.js +536 -4
  11. package/Frameworks/Foundation.jsframework/JS/JSNumberFormatter.js +20 -7
  12. package/Frameworks/Foundation.jsframework/JS/JSTimeZone.js +6 -2
  13. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  14. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  15. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  16. package/Info.json +2 -2
  17. package/Node/io.breakside.jskit-bundle.js +2 -2
  18. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  19. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  20. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  21. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  22. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  23. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  24. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  25. package/Root/Frameworks/DOM/Info.yaml +1 -1
  26. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  27. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  28. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  29. package/Root/Frameworks/Foundation/JSClass.js +8 -5
  30. package/Root/Frameworks/Foundation/JSDateFormatter.js +81 -8
  31. package/Root/Frameworks/Foundation/JSImage.js +1 -0
  32. package/Root/Frameworks/Foundation/JSIndexPath.js +3 -0
  33. package/Root/Frameworks/Foundation/JSLocale.js +536 -4
  34. package/Root/Frameworks/Foundation/JSNumberFormatter.js +20 -7
  35. package/Root/Frameworks/Foundation/JSTimeZone.js +6 -2
  36. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  37. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  38. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  39. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  40. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  41. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  42. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  43. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  44. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  45. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  46. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  47. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  48. package/Root/Frameworks/UIKit/UIButton.js +8 -6
  49. package/Root/Frameworks/UIKit/UIHTMLWindowServer.js +3 -4
  50. package/Root/Frameworks/UIKit/UILayer.js +17 -0
  51. package/Root/Frameworks/UIKit/UIListView.js +44 -28
  52. package/Root/Frameworks/UIKit/UINavigationBar.js +13 -14
  53. package/Root/Frameworks/UIKit/UINavigationItem.js +4 -0
  54. package/Root/Frameworks/UIKit/UIPopupButton.js +3 -0
  55. package/Root/Frameworks/UIKit/UISplitViewController.js +37 -22
  56. package/Root/Frameworks/UIKit/UIToolbar.js +1 -1
  57. package/Root/Frameworks/UIKit/UIView.js +1 -0
  58. package/Root/Frameworks/UIKit/UIWindow.js +42 -3
  59. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  60. package/package.json +1 -1
@@ -15,8 +15,11 @@
15
15
 
16
16
  // #import "JSObject.js"
17
17
  // #import "JSCalendar.js"
18
+ /* global Intl */
18
19
  'use strict';
19
20
 
21
+ (function(){
22
+
20
23
  JSClass("JSLocale", JSObject, {
21
24
 
22
25
  identifier: JSReadOnlyProperty('_identifier', null),
@@ -25,9 +28,7 @@ JSClass("JSLocale", JSObject, {
25
28
  regionCode: JSReadOnlyProperty('_regionCode', null),
26
29
  scriptCode: JSReadOnlyProperty('_scriptCode', null),
27
30
  extensions: JSReadOnlyProperty('_extensions', null),
28
- decimalSeparator: JSReadOnlyProperty('_decimalSeparator', '.'),
29
- groupingSeparator: JSReadOnlyProperty('_decimalSeparator', ','),
30
- calendarIdentifier: JSReadOnlyProperty('_calendarIdentifier', JSCalendar.Identifier.gregorian),
31
+ _data: null,
31
32
 
32
33
  initWithIdentifier: function(identifier){
33
34
  if (identifier === null){
@@ -91,6 +92,27 @@ JSClass("JSLocale", JSObject, {
91
92
  if (this._identifier in JSLocale._localesByIdentifier){
92
93
  return JSLocale._localesByIdentifier[this._identifier];
93
94
  }
95
+ var id = this._languageCode;
96
+ if (id in JSLocale.data){
97
+ this._data = {};
98
+ overwrite(this._data, JSLocale.data[id]);
99
+ }
100
+ if (this.scriptCode !== null){
101
+ id += "-" + this.scriptCode;
102
+ }
103
+ if (id in JSLocale.data){
104
+ this._data = this._data || {};
105
+ overwrite(this._data, JSLocale.data[id]);
106
+ }
107
+ if (this.regionCode !== null){
108
+ id += "-" + this.regionCode;
109
+ }
110
+ if (id in JSLocale.data){
111
+ this._data = this._data || {};
112
+ overwrite(this._data, JSLocale.data[id]);
113
+ }
114
+ this._determineNumericFormattingOptions();
115
+ this._determineDateFormattingOptions();
94
116
  JSLocale._localesByIdentifier[this._identifier] = this;
95
117
  },
96
118
 
@@ -102,6 +124,493 @@ JSClass("JSLocale", JSObject, {
102
124
  return true;
103
125
  }
104
126
  return false;
127
+ },
128
+
129
+ // ----------------------------------------------------------------------
130
+ // MARK: - Number Formatting
131
+
132
+ decimalSeparator: JSReadOnlyProperty('_decimalSeparator', '.'),
133
+ groupingSeparator: JSReadOnlyProperty('_groupingSeparator', ','),
134
+ percentSymbol: JSReadOnlyProperty("_percentSymbol", '%'),
135
+ perMilleSymbol: JSReadOnlyProperty("_perMilleSymbol", '‰'),
136
+ minusSign: JSReadOnlyProperty("_minusSign", '-'),
137
+ plusSign: JSReadOnlyProperty("_plusSign", '+'),
138
+ zeroSymbol: JSReadOnlyProperty("_zeroSymbol", null),
139
+ notANumberSymbol: JSReadOnlyProperty("_notANumberSymbol", 'NaN'),
140
+ nullSymbol: JSReadOnlyProperty("_nullSymbol", ''),
141
+ positiveInfinitySymbol: JSReadOnlyProperty("_positiveInfinitySymbol", '+∞'),
142
+ negativeInfinitySymbol: JSReadOnlyProperty("_negativeInfinitySymbol", '-∞'),
143
+
144
+ decimalNumberFormat: JSReadOnlyProperty("_decimalNumberFormat", "#,##0.###"),
145
+ percentNumberFormat: JSReadOnlyProperty("_percentNumberFormat", "#,##0%"),
146
+ currencyNumberFormat: JSReadOnlyProperty("_currencyNumberFormat", "¤#,##0.00"),
147
+ accountingNumberFormat: JSReadOnlyProperty("_accountingNumberFormat", "¤#,##0.00;(¤#,##0.00)"),
148
+
149
+ _determineNumericFormattingOptions: function(){
150
+ if (this._identifier === "en-US"){
151
+ return;
152
+ }
153
+ if (this._determineNumericFormattingOptionsFromData()){
154
+ return;
155
+ }
156
+ this._determineNumericFormattingOptionsFromIntl();
157
+ },
158
+
159
+ _determineNumericFormattingOptionsFromData: function(){
160
+ if (this._data === null){
161
+ return false;
162
+ }
163
+ var symbols = this._data.numbers.symbols;
164
+ var formats = this._data.numbers.formats;
165
+ if (symbols.decimal !== undefined){
166
+ this._decimalSeparator = symbols.decimal;
167
+ }
168
+ if (symbols.group !== undefined){
169
+ this._groupingSeparator = symbols.group;
170
+ }
171
+ if (symbols.percent !== undefined){
172
+ this._percentSymbol = symbols.percent;
173
+ }
174
+ if (symbols.perMille !== undefined){
175
+ this._perMilleSymbol = symbols.perMille;
176
+ }
177
+ if (symbols.plus !== undefined){
178
+ this._plusSign = symbols.plus;
179
+ }
180
+ if (symbols.minus !== undefined){
181
+ this._minusSign = symbols.minus;
182
+ }
183
+ if (symbols.nan !== undefined){
184
+ this._notANumberSymbol = symbols.nan;
185
+ }
186
+ if (symbols.infinity !== undefined){
187
+ this._positiveInfinitySymbol = this._plusSign + symbols.infinity;
188
+ this._negativeInfinitySymbol = this._minusSign + symbols.infinity;
189
+ }
190
+ if (formats.decimal !== undefined){
191
+ this._decimalNumberFormat = formats.decimal;
192
+ }
193
+ if (formats.percent !== undefined){
194
+ this._percentNumberFormat = formats.percent;
195
+ }
196
+ if (formats.currency !== undefined){
197
+ this._currencyNumberFormat = formats.currency;
198
+ }
199
+ if (formats.accounting !== undefined){
200
+ this._accountingNumberFormat = formats.accounting;
201
+ }
202
+ return true;
203
+ },
204
+
205
+ _determineNumericFormattingOptionsFromIntl: function(){
206
+ if (!JSGlobalObject.Intl){
207
+ return false;
208
+ }
209
+ function repeat(c, n){
210
+ var str = "";
211
+ for (var i = 0; i < n; ++i){
212
+ str += c;
213
+ }
214
+ return str;
215
+ }
216
+ try{
217
+ // Decimal format
218
+ var formatter = new Intl.NumberFormat(this._identifier, {
219
+ signDisplay: "always"
220
+ });
221
+ this._decimalNumberFormat = formatter.unciodeFormatString;
222
+ var parts = formatter.formatToParts(1234567890.1234567);
223
+ var part;
224
+ var i, l;
225
+ this._usesGroupingSeparator = false;
226
+ var groupSize = 0;
227
+ var secondaryGroupSize = 0;
228
+ var decimalFormat = "";
229
+ var fractionSize = 0;
230
+ for (i = 0, l = parts.length; i < l; ++i){
231
+ part = parts[i];
232
+ if (part.type === "plusSign"){
233
+ this._plusSign = part.value;
234
+ }else if (part.type === "group"){
235
+ this._usesGroupingSeparator = true;
236
+ this._groupingSeparator = part.value;
237
+ }else if (part.type === "integer"){
238
+ if (this._usesGroupingSeparator){
239
+ if (part.value.length != groupSize){
240
+ secondaryGroupSize = groupSize;
241
+ groupSize = part.value.length;
242
+ }
243
+ }
244
+ }else if (part.type === "decimal"){
245
+ this._decimalSeparator = part.value;
246
+ }else if (part.type === "fraction"){
247
+ fractionSize = part.value.length;
248
+ }
249
+ }
250
+ var integerFormat = "";
251
+ if (this._usesGroupingSeparator){
252
+ if (secondaryGroupSize > 0){
253
+ integerFormat = repeat("#", secondaryGroupSize) + "," + repeat("#", groupSize - 1) + "0";
254
+ }else{
255
+ integerFormat = "#," + repeat("#", groupSize - 1) + "0";
256
+ }
257
+ }else{
258
+ integerFormat = "#0";
259
+ }
260
+ if (fractionSize > 0){
261
+ this._decimalNumberFormat = integerFormat + "." + repeat("#", fractionSize);
262
+ }else{
263
+ this._decimalNumberFormat = integerFormat;
264
+ }
265
+
266
+ // Percent format
267
+ formatter = new Intl.NumberFormat(this._identifier, {
268
+ signDisplay: "always",
269
+ style: "percent",
270
+ useGrouping: false
271
+ });
272
+ parts = formatter.formatToParts(-1.1234567);
273
+ this._percentNumberFormat = "";
274
+ for (i = 0, l = parts.length; i < l; ++i){
275
+ part = parts[i];
276
+ if (part.type == "minusSign"){
277
+ this._minusSign = part.value;
278
+ }else if (part.type === "integer"){
279
+ this._percentNumberFormat += integerFormat;
280
+ }else if (part.type === "literal"){
281
+ this._percentNumberFormat += part.value;
282
+ }else if (part.type === "decimal"){
283
+ this._percentNumberFormat += ".";
284
+ }else if (part.type === "fraction"){
285
+ this._percentNumberFormat += repeat("#", part.value.length);
286
+ }else if (part.type === "percentSign"){
287
+ this._percentSymbol = part.value;
288
+ this._percentNumberFormat += "%";
289
+ }
290
+ }
291
+
292
+ // currency format
293
+ formatter = new Intl.NumberFormat(this._identifier, {
294
+ style: "currency",
295
+ currency: "USD",
296
+ useGrouping: false
297
+ });
298
+ parts = formatter.formatToParts(1.1);
299
+ this._currencyNumberFormat = "";
300
+ for (i = 0, l = parts.length; i < l; ++i){
301
+ part = parts[i];
302
+ if (part.type == "minusSign"){
303
+ this._minusSign = part.value;
304
+ }else if (part.type === "integer"){
305
+ this._currencyNumberFormat += integerFormat;
306
+ }else if (part.type === "literal"){
307
+ this._currencyNumberFormat += part.value;
308
+ }else if (part.type === "decimal"){
309
+ this._currencyNumberFormat += ".";
310
+ }else if (part.type === "fraction"){
311
+ this._currencyNumberFormat += repeat("0", part.value.length);
312
+ }else if (part.type === "currency"){
313
+ this._percentSymbol = part.value;
314
+ this._currencyNumberFormat += "¤";
315
+ }
316
+ }
317
+
318
+ // accounting format
319
+ formatter = new Intl.NumberFormat(this._identifier, {
320
+ style: "currency",
321
+ currency: "USD",
322
+ currencySign: "accounting",
323
+ useGrouping: false
324
+ });
325
+ parts = formatter.formatToParts(1.1);
326
+ this._accountingNumberFormat = "";
327
+ for (i = 0, l = parts.length; i < l; ++i){
328
+ part = parts[i];
329
+ if (part.type == "minusSign"){
330
+ this._accountingNumberFormat += "-";
331
+ }else if (part.type === "integer"){
332
+ this._accountingNumberFormat += integerFormat;
333
+ }else if (part.type === "literal"){
334
+ this._accountingNumberFormat += part.value;
335
+ }else if (part.type === "decimal"){
336
+ this._accountingNumberFormat += ".";
337
+ }else if (part.type === "fraction"){
338
+ this._accountingNumberFormat += repeat("0", part.value.length);
339
+ }else if (part.type === "currency"){
340
+ this._percentSymbol = part.value;
341
+ this._accountingNumberFormat += "¤";
342
+ }
343
+ }
344
+ parts = formatter.formatToParts(-1.1);
345
+ this._accountingNumberFormat += ";";
346
+ for (i = 0, l = parts.length; i < l; ++i){
347
+ part = parts[i];
348
+ if (part.type == "minusSign"){
349
+ this._accountingNumberFormat += "-";
350
+ }else if (part.type === "integer"){
351
+ this._accountingNumberFormat += integerFormat;
352
+ }else if (part.type === "literal"){
353
+ this._accountingNumberFormat += part.value;
354
+ }else if (part.type === "decimal"){
355
+ this._accountingNumberFormat += ".";
356
+ }else if (part.type === "fraction"){
357
+ this._accountingNumberFormat += repeat("0", part.value.length);
358
+ }else if (part.type === "currency"){
359
+ this._percentSymbol = part.value;
360
+ this._accountingNumberFormat += "¤";
361
+ }
362
+ }
363
+ return true;
364
+ }catch (e){
365
+ return false;
366
+ }
367
+ },
368
+
369
+ // ----------------------------------------------------------------------
370
+ // MARK: - Date Formatting
371
+
372
+ calendarIdentifier: JSReadOnlyProperty('_calendarIdentifier', JSCalendar.Identifier.gregorian),
373
+
374
+ dateFormatForTemplate: function(template){
375
+ return this._dateFormatsByTemplate[template] || null;
376
+ },
377
+
378
+ shortDateFormat: JSReadOnlyProperty("_shortDateFormat", "M/d/yy"),
379
+ mediumDateFormat: JSReadOnlyProperty("_mediumDateFormat", "MMM d, y"),
380
+ longDateFormat: JSReadOnlyProperty("_longDateFormat", "MMMM d, y"),
381
+ fullDateFormat: JSReadOnlyProperty("_fullDateFormat", "EEEE, MMMM d, y"),
382
+
383
+ shortTimeFormat: JSReadOnlyProperty("_shortTimeFormat", "h:mm a"),
384
+ mediumTimeFormat: JSReadOnlyProperty("_mediumTimeFormat", "h:mm:ss a"),
385
+ longTimeFormat: JSReadOnlyProperty("_longTimeFormat", "h:mm:ss a z"),
386
+ fullTimeFormat: JSReadOnlyProperty("_fullTimeFormat", "h:mm:ss a zzzz"),
387
+
388
+ shortDateTimeFormat: JSReadOnlyProperty("_shortDateTimeFormat", "{1}, {0}"),
389
+ mediumDateTimeFormat: JSReadOnlyProperty("_mediumDateTimeFormat", "{1}, {0}"),
390
+ longDateTimeFormat: JSReadOnlyProperty("_longDateTimeFormat", "{1} 'at' {0}"),
391
+ fullDateTimeFormat: JSReadOnlyProperty("_fullDateTimeFormat", "{1} 'at' {0}"),
392
+
393
+ _dateFormatsByTemplate: null,
394
+
395
+ _determineDateFormattingOptions: function(){
396
+ this._dateFormatsByTemplate = {};
397
+ if (this._identifier === "en-US"){
398
+ this._dateFormatsByTemplate.yMEd = "EEE, M/d/y";
399
+ this._dateFormatsByTemplate.yyyyMd = "M/d/y";
400
+ this._dateFormatsByTemplate.yMd = "M/d/y";
401
+ this._dateFormatsByTemplate.yMMMd = "MMM d, y";
402
+ this._dateFormatsByTemplate.yMMMMd = "MMMM d, y";
403
+ this._dateFormatsByTemplate.yM = "M/y";
404
+ this._dateFormatsByTemplate.yMMM = "MMM y";
405
+ this._dateFormatsByTemplate.yMMMM = "MMMM y";
406
+ this._dateFormatsByTemplate.Md = "M/d";
407
+ this._dateFormatsByTemplate.MMMd = "MMM d";
408
+ this._dateFormatsByTemplate.MMMMd = "MMMM d";
409
+ this._dateFormatsByTemplate.hms = "h:mm:ss a";
410
+ this._dateFormatsByTemplate.hm = "h:mm a";
411
+ this._dateFormatsByTemplate.Hms = "HH:mm:ss";
412
+ this._dateFormatsByTemplate.Hm = "HH:mm";
413
+ return;
414
+ }
415
+ if (this._determineDateFormattingOptionsFromData()){
416
+ return;
417
+ }
418
+ this._determineDateFormattingOptionsFromIntl();
419
+ },
420
+
421
+ _determineDateFormattingOptionsFromData: function(){
422
+ if (this._data === null){
423
+ return false;
424
+ }
425
+ var calendar = this._data.calendars.gregorian;
426
+ if (!calendar){
427
+ return false;
428
+ }
429
+ if (calendar.dateFormats.short !== undefined){
430
+ this._shortDateFormat = calendar.dateFormats.short;
431
+ }
432
+ if (calendar.dateFormats.medium !== undefined){
433
+ this._mediumDateFormat = calendar.dateFormats.medium;
434
+ }
435
+ if (calendar.dateFormats.long !== undefined){
436
+ this._longDateFormat = calendar.dateFormats.long;
437
+ }
438
+ if (calendar.dateFormats.full !== undefined){
439
+ this._fullDateFormat = calendar.dateFormats.full;
440
+ }
441
+ if (calendar.timeFormats.short !== undefined){
442
+ this._shortTimeFormat = calendar.timeFormats.short;
443
+ }
444
+ if (calendar.timeFormats.medium !== undefined){
445
+ this._mediumTimeFormat = calendar.timeFormats.medium;
446
+ }
447
+ if (calendar.timeFormats.long !== undefined){
448
+ this._longTimeFormat = calendar.timeFormats.long;
449
+ }
450
+ if (calendar.timeFormats.full !== undefined){
451
+ this._fullTimeFormat = calendar.timeFormats.full;
452
+ }
453
+ if (calendar.dateTimeFormats.short !== undefined){
454
+ this._shortDateTimeFormat = calendar.dateTimeFormats.short;
455
+ }
456
+ if (calendar.dateTimeFormats.medium !== undefined){
457
+ this._mediumDateTimeFormat = calendar.dateTimeFormats.medium;
458
+ }
459
+ if (calendar.dateTimeFormats.long !== undefined){
460
+ this._longDateTimeFormat = calendar.dateTimeFormats.long;
461
+ }
462
+ if (calendar.dateTimeFormats.full !== undefined){
463
+ this._fullDateTimeFormat = calendar.dateTimeFormats.full;
464
+ }
465
+ if (calendar.templates){
466
+ this._dateFormatsByTemplate = calendar.templates;
467
+ }
468
+ return true;
469
+ },
470
+
471
+ _determineDateFormattingOptionsFromIntl: function(){
472
+ if (!JSGlobalObject.Intl){
473
+ return false;
474
+ }
475
+ var referenceDate = new Date(2021, 0, 2, 15, 45, 6);
476
+ var shortMonthName = "";
477
+ var narrowMonthName = "";
478
+ var shortWeekdayName = "";
479
+ var narrowWeekdayName = "";
480
+ var locale = this._identifier;
481
+ function escaped(literal){
482
+ var escapedLiteral = "";
483
+ var i, l, c;
484
+ var quoting = false;
485
+ for (i = 0, l = literal.length; i < l; ++i){
486
+ c = literal[i];
487
+ if (c === "'"){
488
+ escapedLiteral += "'";
489
+ }else if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')){
490
+ if (!quoting){
491
+ quoting = true;
492
+ escapedLiteral += "'";
493
+ }
494
+ }else{
495
+ if (quoting){
496
+ quoting = false;
497
+ escapedLiteral += "'";
498
+ }
499
+ }
500
+ escapedLiteral += c;
501
+ }
502
+ return escapedLiteral;
503
+ }
504
+ function unicodeFormatForOptions(options){
505
+ options.calendar = "gregory";
506
+ options.numberingSystem = "latn";
507
+ var formatter = new Intl.DateTimeFormat(locale, options);
508
+ var parts = formatter.formatToParts(referenceDate);
509
+ var part;
510
+ var i, l;
511
+ var format = "";
512
+ for (i = 0, l = parts.length; i < l; ++i){
513
+ part = parts[i];
514
+ if (part.type === "era"){
515
+ }else if (part.type === "year"){
516
+ if (part.value.length == 2){
517
+ format += "yy";
518
+ }else{
519
+ format += "y";
520
+ }
521
+ }else if (part.type === "yearName"){
522
+ format += "U";
523
+ }else if (part.type === "month"){
524
+ if (part.value === "1"){
525
+ format += "M";
526
+ }else if (part.value == "01"){
527
+ format += "MM";
528
+ }else if (part.value === narrowMonthName){
529
+ format += "MMMMM";
530
+ }else if (part.value === shortMonthName){
531
+ format += "MMM";
532
+ }else{
533
+ format += "MMMM";
534
+ }
535
+ }else if (part.type === "day"){
536
+ format += "d";
537
+ if (part.value.length > 1){
538
+ format += "d";
539
+ }
540
+ }else if (part.type === "hour"){
541
+ if (part.value === "3"){
542
+ format += "h";
543
+ }else if (part.value === "03"){
544
+ format += "hh";
545
+ }else if (part.value == "15"){
546
+ format += "HH";
547
+ }
548
+ }else if (part.type === "minute"){
549
+ format += "mm";
550
+ }else if (part.type === "second"){
551
+ format += "ss";
552
+ }else if (part.type === "fractionalSecond"){
553
+ format += "S";
554
+ }else if (part.type === "dayPeriod"){
555
+ format += "a";
556
+ }else if (part.type === "timeZoneName"){
557
+ if (part.value.length > 4){
558
+ format += "zzzz";
559
+ }else{
560
+ format += "z";
561
+ }
562
+ }else if (part.type === "literal"){
563
+ format += escaped(part.value);
564
+ }else if (part.type === "weekday"){
565
+ if (part.value === narrowWeekdayName){
566
+ format += "EEEEE";
567
+ }else if (part.value === shortWeekdayName){
568
+ format += "EEE";
569
+ }else{
570
+ format += "EEEE";
571
+ }
572
+ }
573
+ }
574
+ return format;
575
+ }
576
+ try{
577
+ shortMonthName = new Intl.DateTimeFormat(locale, {calendar: "gregory", month: "short"}).format(referenceDate);
578
+ narrowMonthName = new Intl.DateTimeFormat(locale, {calendar: "gregory", month: "narrow"}).format(referenceDate);
579
+ shortWeekdayName = new Intl.DateTimeFormat(locale, {calendar: "gregory", weekday: "short"}).format(referenceDate);
580
+ narrowWeekdayName = new Intl.DateTimeFormat(locale, {calendar: "gregory", weekday: "narrow"}).format(referenceDate);
581
+ this._shortDateFormat = unicodeFormatForOptions({dateStyle: "short"});
582
+ this._mediumDateFormat = unicodeFormatForOptions({dateStyle: "medium"});
583
+ this._longDateFormat = unicodeFormatForOptions({dateStyle: "long"});
584
+ this._fullDateFormat = unicodeFormatForOptions({dateStyle: "full"});
585
+ this._shortTimeFormat = unicodeFormatForOptions({timeStyle: "short"});
586
+ this._mediumTimeFormat = unicodeFormatForOptions({timeStyle: "medium"});
587
+ this._longTimeFormat = unicodeFormatForOptions({timeStyle: "long"});
588
+ this._fullTimeFormat = unicodeFormatForOptions({timeStyle: "full"});
589
+ this._shortDateTimeFormat = unicodeFormatForOptions({dateStyle: "short", timeStyle: "short"}).replace(this._shortDateFormat, "{1}").replace(this._shortTimeFormat, "{0}");
590
+ this._mediumDateTimeFormat = unicodeFormatForOptions({dateStyle: "medium", timeStyle: "medium"}).replace(this._mediumDateFormat, "{1}").replace(this._mediumTimeFormat, "{0}");
591
+ this._longDateTimeFormat = unicodeFormatForOptions({dateStyle: "long", timeStyle: "long"}).replace(this._longDateFormat, "{1}").replace(this._longTimeFormat, "{0}");
592
+ this._fullDateTimeFormat = unicodeFormatForOptions({dateStyle: "full", timeStyle: "full"}).replace(this._fullDateFormat, "{1}").replace(this._fullTimeFormat, "{0}");
593
+ this._dateFormatsByTemplate = {
594
+ "yMEd": unicodeFormatForOptions({year: "numeric", month: "numeric", weekday: "short", day: "numeric"}),
595
+ "yyyyMd": unicodeFormatForOptions({year: "numeric", month: "numeric", day: "numeric"}),
596
+ "yMd": unicodeFormatForOptions({year: "numeric", month: "numeric", day: "numeric"}),
597
+ "yMMMd": unicodeFormatForOptions({year: "numeric", month: "short", day: "numeric"}),
598
+ "yMMMMd": unicodeFormatForOptions({year: "numeric", month: "long", day: "numeric"}),
599
+ "yM": unicodeFormatForOptions({year: "numeric", month: "numeric"}),
600
+ "yMMM": unicodeFormatForOptions({year: "numeric", month: "short"}),
601
+ "yMMMM": unicodeFormatForOptions({year: "numeric", month: "long"}),
602
+ "Md": unicodeFormatForOptions({month: "numeric", day: "numeric"}),
603
+ "MMMd": unicodeFormatForOptions({month: "short", day: "numeric"}),
604
+ "MMMMd": unicodeFormatForOptions({month: "long", day: "numeric"}),
605
+ "hms": unicodeFormatForOptions({hour: "numeric", minute: "numeric", second: "numeric"}),
606
+ "hm": unicodeFormatForOptions({hour: "numeric", minute: "numeric"}),
607
+ "Hms": unicodeFormatForOptions({hour: "numeric", minute: "numeric", second: "numeric", hour12: false}),
608
+ "Hm": unicodeFormatForOptions({hour: "numeric", minute: "numeric", hour12: false}),
609
+ };
610
+ return true;
611
+ }catch (e){
612
+ return false;
613
+ }
105
614
  }
106
615
 
107
616
  });
@@ -115,6 +624,8 @@ JSLocale.ClearCache = function(){
115
624
  JSLocale._preferredLanguages = [];
116
625
  JSLocale.preferredLanguagesVersion = 1;
117
626
 
627
+ JSLocale.data = {};
628
+
118
629
  Object.defineProperties(JSLocale, {
119
630
 
120
631
  preferredLanguages: {
@@ -134,4 +645,25 @@ Object.defineProperties(JSLocale, {
134
645
  }
135
646
  }
136
647
 
137
- });
648
+ });
649
+
650
+ var overwrite = function(base, updates){
651
+ var k, v;
652
+ for (k in updates){
653
+ v = updates[k];
654
+ if (typeof(v) === "object"){
655
+ if (!(k in base)){
656
+ if (v instanceof Array){
657
+ base[k] = [];
658
+ }else{
659
+ base[k] = {};
660
+ }
661
+ }
662
+ overwrite(base[k], v);
663
+ }else{
664
+ base[k] = v;
665
+ }
666
+ }
667
+ };
668
+
669
+ })();
@@ -42,8 +42,17 @@ JSClass("JSNumberFormatter", JSObject, {
42
42
 
43
43
  setLocale: function(locale){
44
44
  this._locale = locale;
45
- this.groupingSeparator = locale.groupingSeparator;
46
- this.decimalSeparator = locale.decimalSeparator;
45
+ this._groupingSeparator = locale.groupingSeparator;
46
+ this._decimalSeparator = locale.decimalSeparator;
47
+ this._percentSymbol = locale.percentSymbol;
48
+ this._perMilleSymbol = locale.perMilleSymbol;
49
+ this._minusSign = locale.minusSign;
50
+ this._plusSign = locale.plusSign;
51
+ this._zeroSymbol = locale.zeroSymbol;
52
+ this._notANumberSymbol = locale.notANumberSymbol;
53
+ this._nullSymbol = locale.nullSymbol;
54
+ this._positiveInfinitySymbol = locale.positiveInfinitySymbol;
55
+ this._negativeInfinitySymbol = locale.negativeInfinitySymbol;
47
56
  },
48
57
 
49
58
  format: JSDynamicProperty(),
@@ -81,22 +90,26 @@ JSClass("JSNumberFormatter", JSObject, {
81
90
  this.format = "#";
82
91
  break;
83
92
  case JSNumberFormatter.Style.decimal:
84
- this.format = "#,##0.###";
93
+ this.format = this._locale.decimalNumberFormat;
85
94
  break;
86
95
  case JSNumberFormatter.Style.percent:
87
- this.format = "#,##0%";
96
+ this.format = this._locale.percentNumberFormat;
88
97
  break;
89
98
  case JSNumberFormatter.Style.ordinal:
90
99
  // TODO:
91
100
  break;
92
101
  case JSNumberFormatter.Style.currency:
93
- this.format = "¤#,##0.00";
102
+ this.format = this._locale.currencyNumberFormat;
94
103
  break;
95
104
  case JSNumberFormatter.Style.currencyAccounting:
96
- this.format = "¤#,##0.00;(¤#)";
105
+ this.format = this._locale.accountingNumberFormat;
97
106
  break;
98
107
  case JSNumberFormatter.Style.currencyISOCode:
99
- this.format = "¤¤ #,##0.00;¤¤ -#";
108
+ if (this._locale.currencyNumberFormat.startsWith("¤") && this._locale.currencyNumberFormat.indexOf(";") < 0){
109
+ this.format = this._locale.currencyNumberFormat.replace(/¤/g, "¤¤ ") + ";" + this._locale.currencyNumberFormat.replace(/¤/g, "¤¤ -");
110
+ }else{
111
+ this.format = this._locale.currencyNumberFormat.replace(/¤/g, "¤¤");
112
+ }
100
113
  break;
101
114
  }
102
115
  this._style = style;
@@ -536,7 +536,11 @@ var defaultLocalProperty = {
536
536
  get: function JSTimeZone_getLocal(){
537
537
  var timezone = null;
538
538
  if (localIdentifier !== null){
539
- timezone = JSTimeZone.initWithIdentifier(localIdentifier);
539
+ if (localIdentifier === "UTC"){
540
+ timezone = JSTimeZone.utc;
541
+ }else{
542
+ timezone = JSTimeZone.initWithIdentifier(localIdentifier);
543
+ }
540
544
  }
541
545
  Object.defineProperty(JSTimeZone, 'local', {configurable: true, value: timezone});
542
546
  return timezone;
@@ -557,7 +561,7 @@ Object.defineProperties(JSTimeZone, {
557
561
  systemTimeZoneIdentifier: {
558
562
  get: function JSTimeZone_getSystemTimeZoneIdentifier(){
559
563
  // FIXME: if no identifier, try to guess based on offset?
560
- return Intl.DateTimeFormat().resolvedOptions().timeZone || null;
564
+ return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
561
565
  }
562
566
  },
563
567
 
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.Foundation'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.Foundation",
6
- "JSBundleVersion": "2021.40.1",
6
+ "JSBundleVersion": "2021.43.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.Foundation'] = {
11
11
  "node": "Foundation+Node.js"
12
12
  },
13
13
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
14
- "GitRevision": "9f5d18fecb2fd5007632481cce3f830f6abcfd9c"
14
+ "GitRevision": "0773c815878b130f1dc25e6912bd72f788582577"
15
15
  },
16
16
  "Resources": [
17
17
  {