@breakside/jskit 2021.52.0 → 2022.6.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 (79) 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/JSColor.js +9 -0
  7. package/Frameworks/Foundation.jsframework/JS/JSColorSpace.js +106 -20
  8. package/Frameworks/Foundation.jsframework/JS/JSMediaType.js +1 -1
  9. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  10. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  11. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  12. package/Info.json +2 -2
  13. package/Node/io.breakside.jskit-bundle.js +2 -2
  14. package/Root/Frameworks/APIKit/APIRequest.js +99 -0
  15. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  16. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  17. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  18. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  19. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  20. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  21. package/Root/Frameworks/DBKit/DBMongoStore.js +1 -0
  22. package/Root/Frameworks/DBKit/DBRedisStore.js +136 -117
  23. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  24. package/Root/Frameworks/DOM/Info.yaml +1 -1
  25. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  26. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  27. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  28. package/Root/Frameworks/Foundation/JSColor.js +9 -0
  29. package/Root/Frameworks/Foundation/JSColorSpace.js +106 -20
  30. package/Root/Frameworks/Foundation/JSMediaType.js +1 -1
  31. package/Root/Frameworks/ImageKit/IKColorProfile.js +1091 -0
  32. package/Root/Frameworks/ImageKit/IKColorSpace.js +49 -198
  33. package/Root/Frameworks/ImageKit/IKMatrix.js +124 -0
  34. package/Root/Frameworks/ImageKit/ImageKit.js +2 -0
  35. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  36. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  37. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  38. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  39. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  40. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  41. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  42. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  43. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  44. package/Root/Frameworks/ServerKit/SKHTTPRequest.js +44 -0
  45. package/Root/Frameworks/ServerKit/SKJobQueue.js +1 -1
  46. package/Root/Frameworks/ServerKit/SKRedisJobQueue.js +7 -3
  47. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  48. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  49. package/Root/Frameworks/TestKit/TKMock.js +1 -1
  50. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  51. package/Root/Frameworks/UIKit/UIBrowserViewController.js +2 -6
  52. package/Root/Frameworks/UIKit/UICollectionReusableView.js +91 -0
  53. package/Root/Frameworks/UIKit/UICollectionView.js +1254 -0
  54. package/Root/Frameworks/UIKit/UICollectionViewCell.js +121 -0
  55. package/Root/Frameworks/UIKit/UICollectionViewGridLayout.js +425 -0
  56. package/Root/Frameworks/UIKit/UICollectionViewLayout.js +82 -0
  57. package/Root/Frameworks/UIKit/UIColorWell.js +12 -1
  58. package/Root/Frameworks/UIKit/UIDisplayServer.js +5 -1
  59. package/Root/Frameworks/UIKit/UIKit.js +7 -0
  60. package/Root/Frameworks/UIKit/UILayer.js +3 -0
  61. package/Root/Frameworks/UIKit/UIListView.js +8 -9
  62. package/Root/Frameworks/UIKit/UIMenu.js +1 -1
  63. package/Root/Frameworks/UIKit/UIMenuView.js +5 -1
  64. package/Root/Frameworks/UIKit/UINavigationBar.js +9 -3
  65. package/Root/Frameworks/UIKit/UINavigationController.js +228 -112
  66. package/Root/Frameworks/UIKit/UINavigationItem.js +4 -0
  67. package/Root/Frameworks/UIKit/UIPopupButton.js +39 -3
  68. package/Root/Frameworks/UIKit/UIScrollView.js +2 -0
  69. package/Root/Frameworks/UIKit/UISplitViewController.js +215 -73
  70. package/Root/Frameworks/UIKit/UITabViewController.js +4 -10
  71. package/Root/Frameworks/UIKit/UITextField.js +3 -0
  72. package/Root/Frameworks/UIKit/UIView.js +3 -0
  73. package/Root/Frameworks/UIKit/UIViewController.js +141 -50
  74. package/Root/Frameworks/UIKit/UIWindow.js +4 -15
  75. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  76. package/Root/Frameworks/UIKitTesting/UIMockApplication.js +6 -0
  77. package/Root/Templates/http/${PROJECT_NAME}/Dockerfile +1 -1
  78. package/Root/Templates/node/${PROJECT_NAME}/Dockerfile +4 -2
  79. package/package.json +1 -1
@@ -467,18 +467,21 @@ JSClass("UIPopupButtonStyler", UIControlStyler, {
467
467
 
468
468
  JSClass("UIPopupButtonCustomStyler", UIPopupButtonStyler, {
469
469
 
470
- showsOverState: false,
471
470
  titleInsets: null,
472
471
  normalBackgroundColor: null,
473
472
  disabledBackgroundColor: null,
473
+ overBackgroundColor: null,
474
474
  activeBackgroundColor: null,
475
475
  normalBackgroundGradient: null,
476
+ overBackgroundGradient: null,
476
477
  disabledBackgroundGradient: null,
477
478
  activeBackgroundGradient: null,
478
479
  normalBorderColor: null,
479
480
  disabledBorderColor: null,
481
+ overBorderColor: null,
480
482
  activeBorderColor: null,
481
483
  normalTitleColor: null,
484
+ overTitleColor: null,
482
485
  disabledTitleColor: null,
483
486
  activeTitleColor: null,
484
487
  borderWidth: 0,
@@ -508,7 +511,7 @@ JSClass("UIPopupButtonCustomStyler", UIPopupButtonStyler, {
508
511
  },
509
512
 
510
513
  initWithSpec: function(spec){
511
- UIPopupButtonCustomStyler.$super.initWithSpec(spec);
514
+ UIPopupButtonCustomStyler.$super.initWithSpec.call(this, spec);
512
515
 
513
516
  this._populateDefaults();
514
517
 
@@ -518,6 +521,9 @@ JSClass("UIPopupButtonCustomStyler", UIPopupButtonStyler, {
518
521
  if (spec.containsKey("normalBackgroundColor")){
519
522
  this.normalBackgroundColor = spec.valueForKey("normalBackgroundColor", JSColor);
520
523
  }
524
+ if (spec.containsKey("overBackgroundColor")){
525
+ this.overBackgroundColor = spec.valueForKey("overBackgroundColor", JSColor);
526
+ }
521
527
  if (spec.containsKey("disabledBackgroundColor")){
522
528
  this.disabledBackgroundColor = spec.valueForKey("disabledBackgroundColor", JSColor);
523
529
  }
@@ -527,6 +533,9 @@ JSClass("UIPopupButtonCustomStyler", UIPopupButtonStyler, {
527
533
  if (spec.containsKey("normalBackgroundGradient")){
528
534
  this.normalBackgroundGradient = spec.valueForKey("normalBackgroundGradient", JSGradient);
529
535
  }
536
+ if (spec.containsKey("overBackgroundGradient")){
537
+ this.overBackgroundGradient = spec.valueForKey("overBackgroundGradient", JSGradient);
538
+ }
530
539
  if (spec.containsKey("disabledBackgroundGradient")){
531
540
  this.disabledBackgroundGradient = spec.valueForKey("disabledBackgroundGradient", JSGradient);
532
541
  }
@@ -536,6 +545,9 @@ JSClass("UIPopupButtonCustomStyler", UIPopupButtonStyler, {
536
545
  if (spec.containsKey("normalBorderColor")){
537
546
  this.normalBorderColor = spec.valueForKey("normalBorderColor", JSColor);
538
547
  }
548
+ if (spec.containsKey("overBorderColor")){
549
+ this.overBorderColor = spec.valueForKey("overBorderColor", JSColor);
550
+ }
539
551
  if (spec.containsKey("disabledBorderColor")){
540
552
  this.disabledBorderColor = spec.valueForKey("disabledBorderColor", JSColor);
541
553
  }
@@ -545,6 +557,9 @@ JSClass("UIPopupButtonCustomStyler", UIPopupButtonStyler, {
545
557
  if (spec.containsKey("normalTitleColor")){
546
558
  this.normalTitleColor = spec.valueForKey("normalTitleColor", JSColor);
547
559
  }
560
+ if (spec.containsKey("overTitleColor")){
561
+ this.overTitleColor = spec.valueForKey("overTitleColor", JSColor);
562
+ }
548
563
  if (spec.containsKey("disabledTitleColor")){
549
564
  this.disabledTitleColor = spec.valueForKey("disabledTitleColor", JSColor);
550
565
  }
@@ -595,6 +610,9 @@ JSClass("UIPopupButtonCustomStyler", UIPopupButtonStyler, {
595
610
  if (this.activeBorderColor === null){
596
611
  this.activeBorderColor = this.normalBorderColor.colorDarkenedByPercentage(0.2);
597
612
  }
613
+ if (this.overBorderColor === null){
614
+ this.overBorderColor = this.normalBorderColor.colorDarkenedByPercentage(0.2);
615
+ }
598
616
  if (this.disabledBorderColor === null){
599
617
  this.disabledBorderColor = this.normalBorderColor.colorWithAlpha(0.5);
600
618
  }
@@ -602,6 +620,9 @@ JSClass("UIPopupButtonCustomStyler", UIPopupButtonStyler, {
602
620
  if (this.normalTitleColor === null){
603
621
  this.normalTitleColor = JSColor.text;
604
622
  }
623
+ if (this.overTitleColor === null){
624
+ this.overTitleColor = this.normalTitleColor.colorDarkenedByPercentage(0.2);
625
+ }
605
626
  if (this.activeTitleColor === null){
606
627
  this.activeTitleColor = this.normalTitleColor.colorDarkenedByPercentage(0.2);
607
628
  }
@@ -628,6 +649,13 @@ JSClass("UIPopupButtonCustomStyler", UIPopupButtonStyler, {
628
649
  button._titleLabel.textColor = this.disabledTitleColor;
629
650
  button._imageView.templateColor = this.disabledTitleColor;
630
651
  button._indicatorView.templateColor = this.disabledTitleColor;
652
+ }else if (button.over){
653
+ button.layer.backgroundColor = this.overBackgroundColor;
654
+ button.layer.backgroundGradient = this.overBackgroundGradient;
655
+ button.layer.borderColor = this.overBorderColor;
656
+ button._titleLabel.textColor = this.overTitleColor;
657
+ button._imageView.templateColor = this.overTitleColor;
658
+ button._indicatorView.templateColor = this.overTitleColor;
631
659
  }else if (button.active){
632
660
  button.layer.backgroundColor = this.activeBackgroundColor;
633
661
  button.layer.backgroundGradient = this.activeBackgroundGradient;
@@ -754,6 +782,7 @@ JSClass("UIPopupButtonImageStyler", UIPopupButtonStyler, {
754
782
  activeBackgroundColor: null,
755
783
  overBackgroundColor: null,
756
784
  cornerRadius: 0,
785
+ titleInsets: null,
757
786
 
758
787
  init: function(){
759
788
  this.initWithColor(JSColor.text);
@@ -766,7 +795,7 @@ JSClass("UIPopupButtonImageStyler", UIPopupButtonStyler, {
766
795
  },
767
796
 
768
797
  initWithSpec: function(spec){
769
- UIPopupButtonCustomStyler.$super.initWithSpec(spec);
798
+ UIPopupButtonCustomStyler.$super.initWithSpec.call(this, spec);
770
799
  if (spec.containsKey("normalColor")){
771
800
  this.normalColor = spec.valueForKey("normalColor", JSColor);
772
801
  }
@@ -786,6 +815,9 @@ JSClass("UIPopupButtonImageStyler", UIPopupButtonStyler, {
786
815
  if (spec.containsKey("cornerRadius")){
787
816
  this.cornerRadius = spec.valueForKey("cornerRadius");
788
817
  }
818
+ if (spec.containsKey("titleInsets")){
819
+ this.titleInsets = spec.valueForKey("titleInsets", JSInsets);
820
+ }
789
821
  this._fillInMissingColors();
790
822
  },
791
823
 
@@ -796,6 +828,9 @@ JSClass("UIPopupButtonImageStyler", UIPopupButtonStyler, {
796
828
  if (this.disabledColor === null){
797
829
  this.disabledColor = this.normalColor.colorWithAlpha(0.5);
798
830
  }
831
+ if (this.titleInsets === null){
832
+ this.titleInsets = JSInsets.Zero;
833
+ }
799
834
  },
800
835
 
801
836
  initializeControl: function(button){
@@ -807,6 +842,7 @@ JSClass("UIPopupButtonImageStyler", UIPopupButtonStyler, {
807
842
  button._indicatorView.frame = JSRect.Zero;
808
843
  button._imageView.hidden = false;
809
844
  button.cornerRadius = this.cornerRadius;
845
+ button.titleInsets = this.titleInsets;
810
846
  this.updateControl(button);
811
847
  },
812
848
 
@@ -276,6 +276,8 @@ JSClass('UIScrollView', UIView, {
276
276
 
277
277
  _sanitizedOffset: function(offset){
278
278
  offset = JSPoint(offset);
279
+ offset.x = Math.round(offset.x);
280
+ offset.y = Math.round(offset.y);
279
281
  if (!this.scrollsHorizontally){
280
282
  offset.x = this._contentOffset.x;
281
283
  }else if (offset.x < this._minContentOffset.x){
@@ -56,7 +56,7 @@ JSClass("UISplitViewController", UIViewController, {
56
56
  viewDidLoad: function(){
57
57
  UISplitViewController.$super.viewDidLoad.call(this);
58
58
  this._view.delegate = this;
59
- if (this._mainViewController !== null && this._view.mainView === null){
59
+ if (this._mainViewController !== null && this._view.mainView === null && !this._view.mainHidden){
60
60
  this._view.mainView = this._mainViewController.view;
61
61
  }
62
62
  if (this._leadingViewController !== null && this._view.leadingView === null){
@@ -72,7 +72,7 @@ JSClass("UISplitViewController", UIViewController, {
72
72
  if (this._leadingViewController !== null && this.leadingViewOpen){
73
73
  this._leadingViewController.viewWillAppear(animated);
74
74
  }
75
- if (this._mainViewController !== null){
75
+ if (this._mainViewController !== null && !this._view.mainHidden){
76
76
  this._mainViewController.viewWillAppear(animated);
77
77
  }
78
78
  if (this._trailingViewController !== null && this.trailingViewOpen){
@@ -85,7 +85,7 @@ JSClass("UISplitViewController", UIViewController, {
85
85
  if (this._leadingViewController !== null && this.leadingViewOpen){
86
86
  this._leadingViewController.viewDidAppear(animated);
87
87
  }
88
- if (this._mainViewController !== null){
88
+ if (this._mainViewController !== null && !this._view.mainHidden){
89
89
  this._mainViewController.viewDidAppear(animated);
90
90
  }
91
91
  if (this._trailingViewController !== null && this.trailingViewOpen){
@@ -98,7 +98,7 @@ JSClass("UISplitViewController", UIViewController, {
98
98
  if (this._leadingViewController !== null && this.leadingViewOpen){
99
99
  this._leadingViewController.viewWillDisappear(animated);
100
100
  }
101
- if (this._mainViewController !== null){
101
+ if (this._mainViewController !== null && !this._view.mainHidden){
102
102
  this._mainViewController.viewWillDisappear(animated);
103
103
  }
104
104
  if (this._trailingViewController !== null && this.trailingViewOpen){
@@ -111,7 +111,7 @@ JSClass("UISplitViewController", UIViewController, {
111
111
  if (this._leadingViewController !== null && this.leadingViewOpen){
112
112
  this._leadingViewController.viewDidDisappear(animated);
113
113
  }
114
- if (this._mainViewController !== null){
114
+ if (this._mainViewController !== null && !this._view.mainHidden){
115
115
  this._mainViewController.viewDidDisappear(animated);
116
116
  }
117
117
  if (this._trailingViewController !== null && this.trailingViewOpen){
@@ -138,8 +138,14 @@ JSClass("UISplitViewController", UIViewController, {
138
138
  setMainViewController: function(mainViewController){
139
139
  if (this.isViewLoaded && this.view.mainHidden){
140
140
  this._setMainViewControllerCollapsed(mainViewController);
141
- return;
141
+ }else{
142
+ this._setMainViewControllerFull(mainViewController);
142
143
  }
144
+ },
145
+
146
+ _mainNavigationRootViewController: null,
147
+
148
+ _setMainViewControllerFull: function(mainViewController){
143
149
  this.replaceChildViewController(this._mainViewController, mainViewController);
144
150
  this._mainViewController = mainViewController;
145
151
  if (this.isViewLoaded){
@@ -148,21 +154,195 @@ JSClass("UISplitViewController", UIViewController, {
148
154
  },
149
155
 
150
156
  _setMainViewControllerCollapsed: function(mainViewController){
157
+ if (this._leadingViewController.isKindOfClass(UINavigationController)){
158
+ this._setMainViewControllerOnLeadingNavigationController(mainViewController, this._leadingViewController);
159
+ }else{
160
+ this._setMainViewControllerOnLeadingViewController(mainViewController, this._leadingViewController);
161
+ }
162
+ },
163
+
164
+ _setMainViewControllerOnLeadingNavigationController: function(mainViewController, navigationController){
165
+ // 1. Determine if we need to pop off any view controllers to remove the current mainViewController
166
+ var i;
167
+ var viewControllers = null;
151
168
  if (this._mainViewController !== null){
152
- if (this._leadingViewController.isKindOfClass(UINavigationController)){
153
- if (this._mainViewController === this._leadingViewController.topViewController){
154
- this._leadingViewController.popViewController(false);
169
+ if (this._mainViewController instanceof UINavigationController){
170
+ i = navigationController.viewControllers.indexOf(this._mainNavigationRootViewController);
171
+ }else{
172
+ i = navigationController.viewControllers.indexOf(this._mainViewController);
173
+ }
174
+ if (i > 0){
175
+ if (mainViewController === this._mainViewController){
176
+ // Bail if we're being asked to show the same view controller that's already shown
177
+ // NOTE: this check only comes after finding that the view controller
178
+ // is indeed part of the presentation tree becuase without a notification
179
+ // from the navigation controller when views are popped by the user,
180
+ // we may be in a situation where this._mainViewController is set, but
181
+ // is not part of the navigation stack
182
+ return;
183
+ }
184
+ viewControllers = navigationController.viewControllers.slice(0, i);
185
+ }
186
+ }
187
+ // 2. Update the nav controller
188
+ if (mainViewController !== null){
189
+ if (mainViewController instanceof UINavigationController){
190
+ // When the new main view controller is a nav controller itself,
191
+ // move it's view controller to the leading nav controller
192
+ var mainNavigationController = mainViewController;
193
+ this._mainNavigationRootViewController = mainNavigationController.viewControllers[0];
194
+ if (viewControllers === null && mainNavigationController.viewControllers.length === 1){
195
+ // In a typical case, the main nav controller has just one view controller,
196
+ // which we'll move to the leading nav controller with a push animation
197
+ mainNavigationController.setViewControllers([UIViewController.init()]);
198
+ navigationController.pushViewController(this._mainNavigationRootViewController, true);
199
+ }else{
200
+ // If the main nav controller has more than one view controller, or we're replacing some
201
+ // there's not a meaningful animation we can show, so we'll just
202
+ // update the leading nav without animation
203
+ if (viewControllers === null){
204
+ viewControllers = JSCopy(navigationController.viewControllers);
205
+ }
206
+ var l;
207
+ for (i = 0, l = mainNavigationController.viewControllers.length; i < l; ++i){
208
+ viewControllers.push(mainNavigationController.viewControllers[i]);
209
+ }
210
+ mainNavigationController.viewControllers = [UIViewController.init()];
211
+ navigationController.viewControllers = viewControllers;
155
212
  }
156
213
  }else{
157
- if (this._mainViewController === this._leadingViewController.presentedViewController){
158
- this._leadingViewController.dismiss(false);
214
+ // When the new main view controller is NOT a nav controller,
215
+ // we'll just push it unless we have other updates to do
216
+ if (viewControllers === null){
217
+ navigationController.pushViewController(mainViewController, true);
218
+ }else{
219
+ viewControllers.push(mainViewController);
220
+ navigationController.viewControllers = viewControllers;
159
221
  }
160
222
  }
161
- this._leadingViewController.view.layoutIfNeeded();
223
+ }else{
224
+ if (viewControllers !== null){
225
+ navigationController.popToViewController(viewControllers[viewControllers.length - 1], true);
226
+ }
162
227
  }
163
228
  this._mainViewController = mainViewController;
229
+ },
230
+
231
+ _setMainViewControllerOnLeadingViewController: function(mainViewController, viewController){
232
+ // Bail if we're being asked to show the same view controller that's already shown
233
+ if (mainViewController === this._mainViewController){
234
+ return;
235
+ }
236
+ // 1. Dismiss the current mainViewController
164
237
  if (this._mainViewController !== null){
165
- this._leadingViewController.show(this._mainViewController, this);
238
+ if (this._mainViewController === viewController.presentedViewController){
239
+ viewController.dismiss();
240
+ }
241
+ }
242
+ // 2. Present the new mainViewController
243
+ if (mainViewController !== null){
244
+ viewController.presentViewController(mainViewController);
245
+ }
246
+ this._mainViewController = mainViewController;
247
+ },
248
+
249
+ _moveMainViewControllerToLeading: function(){
250
+ if (this._mainViewController === null){
251
+ return;
252
+ }
253
+ if (this._leadingViewController instanceof UINavigationController){
254
+ this._moveMainViewControllerToLeadingNavigationController(this._leadingViewController);
255
+ }else{
256
+ this._moveMainViewControllerToLeadingViewController(this._leadingViewController);
257
+ }
258
+ },
259
+
260
+ _moveMainViewControllerToLeadingNavigationController: function(navigationController){
261
+ var viewControllers = JSCopy(navigationController.viewControllers);
262
+ if (this._mainViewController instanceof UINavigationController){
263
+ var mainNavigationController = this._mainViewController;
264
+ this._mainNavigationRootViewController = mainNavigationController.viewControllers[0];
265
+ var i, l;
266
+ for (i = 0, l = mainNavigationController.viewControllers.length; i < l; ++i){
267
+ viewControllers.push(mainNavigationController.viewControllers[i]);
268
+ }
269
+ mainNavigationController.viewControllers = [UIViewController.init()];
270
+ if (this.isViewVisible){
271
+ mainNavigationController.scheduleDisappearance();
272
+ }
273
+ }else{
274
+ this.view.mainView = null;
275
+ viewControllers.push(this._mainViewController);
276
+ }
277
+ navigationController.viewControllers = viewControllers;
278
+ },
279
+
280
+ _moveMainViewControllerToLeadingViewController: function(viewController){
281
+ this.view.mainView = null;
282
+ viewController.presentViewController(this._mainViewController, false);
283
+ },
284
+
285
+ _moveMainViewControllerFromLeading: function(){
286
+ if (this._mainViewController === null){
287
+ return;
288
+ }
289
+ var initialMainViewController = this._mainViewController;
290
+ if (this._leadingViewController instanceof UINavigationController){
291
+ this._moveMainViewControllerFromLeadingNavigationController(this._leadingViewController);
292
+ }else{
293
+ this._moveMainViewControllerFromLeadingViewController(this._leadingViewController);
294
+ }
295
+ },
296
+
297
+ _moveMainViewControllerFromLeadingNavigationController: function(navigationController){
298
+ if (this._mainViewController instanceof UINavigationController){
299
+ var mainNavigationController = this._mainViewController;
300
+ var i = navigationController.viewControllers.indexOf(this._mainNavigationRootViewController);
301
+ if (i > 0){
302
+ if (mainNavigationController.view.superview === null){
303
+ this.view.mainView = mainNavigationController.view;
304
+ }
305
+ mainNavigationController.scheduleAppearance();
306
+ var viewControllers = navigationController.viewControllers.slice(i);
307
+ navigationController.popToViewController(navigationController.viewControllers[i - 1], false);
308
+ viewControllers[viewControllers.length - 1].scheduleAppearance();
309
+ mainNavigationController.viewControllers = viewControllers;
310
+ }else{
311
+ this._mainViewController = null;
312
+ if (this.isViewLoaded){
313
+ this.view.mainView = null;
314
+ }
315
+ }
316
+ this._mainNavigationRootViewController = null;
317
+ }else{
318
+ navigationController.popToViewController(this._mainViewController, false);
319
+ if (navigationController.topViewController === this._mainViewController){
320
+ navigationController.popViewController(false);
321
+ if (this.isViewLoaded){
322
+ this._mainViewController.scheduleAppearance();
323
+ this.view.mainView = this._mainViewController.view;
324
+ }
325
+ }else{
326
+ this._mainViewController = null;
327
+ if (this.isViewLoaded){
328
+ this.view.mainView = null;
329
+ }
330
+ }
331
+ }
332
+ },
333
+
334
+ _moveMainViewControllerFromLeadingViewController: function(viewController){
335
+ if (viewController.presentedViewController === this._mainViewController){
336
+ viewController.dismiss(false);
337
+ if (this.isViewLoaded){
338
+ this._mainViewController.scheduleAppearance();
339
+ this.view.mainView = this._mainViewController.view;
340
+ }
341
+ }else{
342
+ this._mainViewController = null;
343
+ if (this.isViewLoaded){
344
+ this.view.mainView = null;
345
+ }
166
346
  }
167
347
  },
168
348
 
@@ -207,37 +387,24 @@ JSClass("UISplitViewController", UIViewController, {
207
387
  percentRemaining = this._leadingAnimator.percentComplete;
208
388
  this._leadingAnimator = null;
209
389
  }
210
- var willAppear = !this.splitView.leadingViewOpen;
211
- if (willAppear){
212
- this._leadingViewController.viewWillAppear(animated);
213
- }else{
214
- this._leadingViewController.viewWillDisappear(animated);
215
- }
390
+ var opening = !this.splitView.leadingViewOpen;
391
+ this._leadingViewController.beginAppearanceTransition(opening, animated);
216
392
  if (!animated){
217
- this.splitView.leadingViewOpen = !this.splitView.leadingViewOpen;
218
- if (willAppear){
219
- this._leadingViewController.enqueueDidAppear();
220
- }else{
221
- this._leadingViewController.enqueueDidDisappear();
222
- }
393
+ this.splitView.leadingViewOpen = opening;
394
+ this._leadingViewController.endAppearanceTransition();
223
395
  }else{
224
396
  // make sure to apply any pending layouts before doing the animation,
225
397
  // otherwise the pending layouts will get caught up in the animation
226
398
  this.splitView.layoutIfNeeded();
227
399
  var animator = UIViewPropertyAnimator.initWithDuration(0.15 * percentRemaining);
228
- var self = this;
229
- this.splitView.leadingViewOpen = !this.splitView.leadingViewOpen;
400
+ this.splitView.leadingViewOpen = opening;
230
401
  animator.addAnimations(function(){
231
- self.splitView.layoutIfNeeded();
232
- });
402
+ this.splitView.layoutIfNeeded();
403
+ }, this);
233
404
  animator.addCompletion(function(){
234
- self._leadingAnimator = null;
235
- if (willAppear){
236
- self._leadingViewController.viewDidAppear(animated);
237
- }else{
238
- self._leadingViewController.viewDidDisappear(animated);
239
- }
240
- });
405
+ this._leadingAnimator = null;
406
+ this._leadingViewController.endAppearanceTransition();
407
+ }, this);
241
408
  this._leadingAnimator = animator;
242
409
  animator.start();
243
410
  }
@@ -272,37 +439,24 @@ JSClass("UISplitViewController", UIViewController, {
272
439
  percentRemaining = this._trailingAnimator.percentComplete;
273
440
  this._trailingAnimator = null;
274
441
  }
275
- var willAppear = !this.splitView.leadingViewOpen;
276
- if (willAppear){
277
- this._trailingViewController.viewWillAppear(animated);
278
- }else{
279
- this._trailingViewController.viewWillDisappear(animated);
280
- }
442
+ var opening = !this.splitView.trailingViewOpen;
443
+ this._trailingViewController.beginAppearanceTransition(opening, animated);
281
444
  if (!animated){
282
445
  this.splitView.trailingViewOpen = !this.splitView.trailingViewOpen;
283
- if (willAppear){
284
- this._trailingViewController.enqueueDidAppear();
285
- }else{
286
- this._trailingViewController.enqueueDidDisappear();
287
- }
446
+ this._trailingViewController.endAppearanceTransition();
288
447
  }else{
289
448
  // make sure to apply any pending layouts before doing the animation,
290
449
  // otherwise the pending layouts will get caught up in the animation
291
450
  this.splitView.layoutIfNeeded();
292
451
  var animator = UIViewPropertyAnimator.initWithDuration(0.15 * percentRemaining);
293
- var self = this;
294
452
  this.splitView.trailingViewOpen = !this.splitView.trailingViewOpen;
295
453
  animator.addAnimations(function(){
296
- self.splitView.layoutIfNeeded();
297
- });
454
+ this.splitView.layoutIfNeeded();
455
+ }, this);
298
456
  animator.addCompletion(function(){
299
- self._trailingAnimator = null;
300
- if (willAppear){
301
- self._trailingViewController.viewDidAppear(animated);
302
- }else{
303
- self._trailingViewController.viewDidDisappear(animated);
304
- }
305
- });
457
+ this._trailingAnimator = null;
458
+ this._trailingViewController.endAppearanceTransition();
459
+ }, this);
306
460
  this._trailingAnimator = animator;
307
461
  animator.start();
308
462
  }
@@ -311,27 +465,15 @@ JSClass("UISplitViewController", UIViewController, {
311
465
  splitViewDidToggleView: function(splitView, toggledView){
312
466
  },
313
467
 
314
- isChangingTraits: false,
315
-
316
468
  traitCollectionDidChange: function(previous){
317
469
  UISplitViewController.$super.traitCollectionDidChange.call(this);
318
470
  if (this.view.canHideMain && previous.horizontalSizeClass != this.traitCollection.horizontalSizeClass){
319
471
  if (previous.horizontalSizeClass === UIUserInterface.SizeClass.compact){
320
- if (this._leadingViewController.isKindOfClass(UINavigationController)){
321
- if (this._mainViewController === this._leadingViewController.topViewController){
322
- this._leadingViewController.popViewController(false);
323
- }
324
- }else{
325
- if (this._leadingViewController.presentedViewController === this._mainViewController){
326
- this._leadingViewController.dismiss(false);
327
- }
328
- }
472
+ this._moveMainViewControllerFromLeading();
473
+ }else{
474
+ this._moveMainViewControllerToLeading();
475
+
329
476
  }
330
- this.isChangingTraits = true;
331
- var vc = this._mainViewController;
332
- this.mainViewController = null;
333
- this.mainViewController = vc;
334
- this.isChangingTraits = false;
335
477
  }
336
478
  },
337
479
 
@@ -139,10 +139,10 @@ JSClass("UITabViewController", UIViewController, {
139
139
 
140
140
  tabViewWillSelectItemAtIndex: function(tabView, index){
141
141
  if (this.isViewVisible && this._previouslySelectedViewController !== null){
142
- this._previouslySelectedViewController.viewWillDisappear();
142
+ this._previouslySelectedViewController.scheduleDisappearance();
143
143
  }
144
144
  var viewController = null;
145
- if (index < this._viewControllers.length){
145
+ if (index >= 0 && index < this._viewControllers.length){
146
146
  viewController = this._viewControllers[index];
147
147
  }
148
148
  if (viewController !== null){
@@ -150,23 +150,17 @@ JSClass("UITabViewController", UIViewController, {
150
150
  // is selected
151
151
  viewController.tabViewItem.view = viewController.view;
152
152
  if (this.isViewVisible){
153
- viewController.viewWillAppear();
153
+ viewController.scheduleAppearance();
154
154
  }
155
155
  }
156
156
  },
157
157
 
158
158
  tabViewDidSelectItemAtIndex: function(tabView, index){
159
159
  var viewController = null;
160
- if (index < this._viewControllers.length){
160
+ if (index >= 0 && index < this._viewControllers.length){
161
161
  viewController = this._viewControllers[index];
162
162
  }
163
- if (this.isViewVisible && this._previouslySelectedViewController !== null){
164
- this._previouslySelectedViewController.viewDidDisappear();
165
- }
166
163
  this._previouslySelectedViewController = viewController;
167
- if (this.isViewVisible && viewController !== null){
168
- viewController.viewDidAppear();
169
- }
170
164
  }
171
165
 
172
166
  });
@@ -788,6 +788,9 @@ JSClass("UITextField", UIControl, {
788
788
  this.delegate.textFieldDidChange(this);
789
789
  }
790
790
  this._didChange = true;
791
+ if (this._textLayer.textAlignment !== JSTextAlignment.left){
792
+ this.setNeedsLayout();
793
+ }
791
794
  },
792
795
 
793
796
  _adjustCursorPositionToCenterIfNeeded: function(){
@@ -145,6 +145,9 @@ JSClass('UIView', UIResponder, {
145
145
  this.addSubview(subview);
146
146
  }
147
147
  }
148
+ if (spec.containsKey("clipsToBounds")){
149
+ this.clipsToBounds = spec.valueForKey("clipsToBounds");
150
+ }
148
151
  // NOTE: constraints are still and work in progress, and aren't actually
149
152
  // used yet during layout
150
153
  if (spec.containsKey("constraints")){