@breakside/jskit 2021.43.0 → 2021.52.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 (81) 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/Deflate.js +2 -3
  7. package/Frameworks/Foundation.jsframework/JS/Error+JS.js +10 -0
  8. package/Frameworks/Foundation.jsframework/JS/JSColor.js +15 -0
  9. package/Frameworks/Foundation.jsframework/JS/JSDate.js +6 -0
  10. package/Frameworks/Foundation.jsframework/JS/JSDateFormatter.js +2 -2
  11. package/Frameworks/Foundation.jsframework/JS/JSTimer.js +6 -0
  12. package/Frameworks/Foundation.jsframework/JS/JSURLResponse.js +60 -1
  13. package/Frameworks/Foundation.jsframework/JS/Zlib.js +2 -3
  14. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  15. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  16. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  17. package/Info.json +2 -2
  18. package/Node/HTMLBuilder.js +2 -1
  19. package/Node/JavascriptCompilation.js +1 -1
  20. package/Node/io.breakside.jskit-bundle.js +2 -2
  21. package/Root/Frameworks/APIKit/APIError.js +2 -3
  22. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  23. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  24. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  25. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  26. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  27. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  28. package/Root/Frameworks/DBKit/DBObjectDatabase.js +6 -5
  29. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  30. package/Root/Frameworks/DOM/Info.yaml +1 -1
  31. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  32. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  33. package/Root/Frameworks/Foundation/Deflate.js +2 -3
  34. package/Root/Frameworks/Foundation/Error+JS.js +10 -0
  35. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  36. package/Root/Frameworks/Foundation/JSColor.js +15 -0
  37. package/Root/Frameworks/Foundation/JSDate.js +6 -0
  38. package/Root/Frameworks/Foundation/JSDateFormatter.js +2 -2
  39. package/Root/Frameworks/Foundation/JSTimer.js +6 -0
  40. package/Root/Frameworks/Foundation/JSURLResponse.js +60 -1
  41. package/Root/Frameworks/Foundation/Zlib.js +2 -3
  42. package/Root/Frameworks/ImageKit/IKDecoderPNG.js +1 -3
  43. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  44. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  45. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  46. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  47. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  48. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  49. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  50. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  51. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  52. package/Root/Frameworks/ServerKit/SKFileJobQueue.js +3 -1
  53. package/Root/Frameworks/ServerKit/SKHTTPError.js +2 -3
  54. package/Root/Frameworks/ServerKit/SKHTTPRequest.js +7 -0
  55. package/Root/Frameworks/ServerKit/SKHTTPResponder.js +9 -2
  56. package/Root/Frameworks/ServerKit/SKUserAgent.js +130 -0
  57. package/Root/Frameworks/ServerKit/SKValidatingObject.js +1 -3
  58. package/Root/Frameworks/ServerKit/ServerKit.js +1 -0
  59. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  60. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  61. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  62. package/Root/Frameworks/UIKit/UIAnimation.js +4 -0
  63. package/Root/Frameworks/UIKit/UIContainerView.js +1 -1
  64. package/Root/Frameworks/UIKit/UIContainerViewController.js +3 -35
  65. package/Root/Frameworks/UIKit/UIHTMLDisplayServerCanvasContext.js +6 -1
  66. package/Root/Frameworks/UIKit/UIImageLayer.js +12 -14
  67. package/Root/Frameworks/UIKit/UILayer.js +3 -0
  68. package/Root/Frameworks/UIKit/UIListView.js +44 -7
  69. package/Root/Frameworks/UIKit/UIListViewHeaderFooterView.js +34 -0
  70. package/Root/Frameworks/UIKit/UINavigationBar.js +4 -2
  71. package/Root/Frameworks/UIKit/UINavigationBarItem.js +11 -0
  72. package/Root/Frameworks/UIKit/UINavigationController.js +2 -2
  73. package/Root/Frameworks/UIKit/UISplitViewController.js +9 -87
  74. package/Root/Frameworks/UIKit/UITabView.js +2 -2
  75. package/Root/Frameworks/UIKit/UITabViewController.js +6 -5
  76. package/Root/Frameworks/UIKit/UITextLayer.js +11 -10
  77. package/Root/Frameworks/UIKit/UIView.js +15 -0
  78. package/Root/Frameworks/UIKit/UIViewController.js +39 -0
  79. package/Root/Frameworks/UIKit/UIWindowServer.js +2 -2
  80. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  81. package/package.json +1 -1
@@ -453,9 +453,9 @@ JSClass("JSDateFormatter", JSObject, {
453
453
  return Math.floor(ms / 100).toString();
454
454
  }
455
455
  if (n == 2){
456
- return Math.floor(ms / 10).toString();
456
+ return Math.floor(ms / 10).toString().leftPaddedString("0", 2);
457
457
  }
458
- return Math.floor((ms * Math.pow(10, n - 3))).toString();
458
+ return Math.floor((ms * Math.pow(10, n - 3))).toString().leftPaddedString("0", n);
459
459
  },
460
460
 
461
461
  _z: function(n, date, components){
@@ -72,4 +72,10 @@ JSTimer.scheduledRepeatingTimerWithInterval = function(interval, action, target)
72
72
  var timer = JSTimer.initWithInterval(interval, true, action, target);
73
73
  timer.schedule();
74
74
  return timer;
75
+ };
76
+
77
+ JSTimer.waitInterval = function(interval){
78
+ return new Promise(function(resolve, reject){
79
+ JSTimer.scheduledTimerWithInterval(interval, resolve);
80
+ });
75
81
  };
@@ -17,6 +17,7 @@
17
17
  // #import "JSMIMEHeaderMap.js"
18
18
  // #import "JSMediaType.js"
19
19
  // #import "JSURL.js"
20
+ // #import "Error+JS.js"
20
21
  'use strict';
21
22
 
22
23
  JSClass("JSURLResponse", JSObject, {
@@ -92,6 +93,12 @@ JSClass("JSURLResponse", JSObject, {
92
93
 
93
94
  getLocation: function(){
94
95
  return JSURL.initWithString(this._headerMap.get("Location", null));
96
+ },
97
+
98
+ assertSuccess: function(){
99
+ if (this.statusClass !== JSURLResponse.StatusClass.success){
100
+ throw new JSURLResponseError(this);
101
+ }
95
102
  }
96
103
 
97
104
  });
@@ -154,4 +161,56 @@ JSURLResponse.StatusClass = {
154
161
  redirect: 3,
155
162
  clientError: 4,
156
163
  serverError: 5
157
- };
164
+ };
165
+
166
+ JSGlobalObject.JSURLResponseError = function(response){
167
+ if (this === undefined){
168
+ return new JSURLResponseError();
169
+ }
170
+ this.name = "JSURLResponseError";
171
+ if (response instanceof JSURLResponseError){
172
+ this.message = response.message;
173
+ this.response = response.response;
174
+ this.stack = response.stack;
175
+ }else{
176
+ this.response = response;
177
+ this.message = "Received %d from server".sprintf(response.statusCode);
178
+ Error.captureStackTrace(this, JSURLResponseError);
179
+ }
180
+ };
181
+
182
+ JSURLResponseError.prototype = Object.create(Error.prototype);
183
+
184
+ Object.defineProperties(JSURLResponseError.prototype, {
185
+
186
+ statusCode: {
187
+ value: function(){
188
+ return this.response.statusCode;
189
+ },
190
+ },
191
+
192
+ statusClass: {
193
+ value: function(){
194
+ return this.response.statusClass;
195
+ },
196
+ },
197
+
198
+ data: {
199
+ value: function(){
200
+ return this.response.data;
201
+ }
202
+ },
203
+
204
+ object: {
205
+ value: function(){
206
+ return this.response.object;
207
+ }
208
+ },
209
+
210
+ headerMap: {
211
+ value: function(){
212
+ return this.response.headerMap;
213
+ }
214
+ }
215
+
216
+ });
@@ -19,6 +19,7 @@
19
19
  // #import "JSLog.js"
20
20
  // #import "JSData.js"
21
21
  // #import "CoreTypes.js"
22
+ // #import "Error+JS.js"
22
23
  'use strict';
23
24
 
24
25
  (function(){
@@ -73,9 +74,7 @@ function ZlibError(msg){
73
74
  }
74
75
  this.name = "ZlibError";
75
76
  this.message = msg;
76
- if (Error.captureStackTrace){
77
- Error.captureStackTrace(this, ZlibError);
78
- }
77
+ Error.captureStackTrace(this, ZlibError);
79
78
  }
80
79
 
81
80
  ZlibError.prototype = Object.create(Error.prototype);
@@ -701,9 +701,7 @@ var IKDecoderPNGError = function(code, byteOffset, msg){
701
701
  this.code = code;
702
702
  this.byteOffset = byteOffset;
703
703
  this.msg = msg;
704
- if (Error.captureStackTrace){
705
- Error.captureStackTrace(this, IKDecoderPNGError);
706
- }
704
+ Error.captureStackTrace(this, IKDecoderPNGError);
707
705
  };
708
706
 
709
707
  IKDecoderPNGError.prototype = Object.create(Error.prototype);
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ImageKit
3
- JSBundleVersion: 2021.43.0
3
+ JSBundleVersion: 2021.52.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.MediaKit
3
- JSBundleVersion: 2021.43.0
3
+ JSBundleVersion: 2021.52.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.MediaKitUI
3
- JSBundleVersion: 2021.43.0
3
+ JSBundleVersion: 2021.52.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.NotificationKit
3
- JSBundleVersion: 2021.43.0
3
+ JSBundleVersion: 2021.52.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2021 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.PDFKit
3
- JSBundleVersion: 2021.43.0
3
+ JSBundleVersion: 2021.52.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.QRKit
3
- JSBundleVersion: 2021.43.0
3
+ JSBundleVersion: 2021.52.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.SearchKit
3
- JSBundleVersion: 2021.43.0
3
+ JSBundleVersion: 2021.52.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.SecurityKit
3
- JSBundleVersion: 2021.43.0
3
+ JSBundleVersion: 2021.52.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ServerKit
3
- JSBundleVersion: 2021.43.0
3
+ JSBundleVersion: 2021.52.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -49,7 +49,9 @@ JSClass("SKFileJobQueue", SKJobQueue, {
49
49
  },
50
50
 
51
51
  handleChange: function(eventType, filename){
52
- if (fs.existsSync(filename)){
52
+ let url = JSURL.initWithString(filename, this.queueURL);
53
+ let path = this.fileManager.pathForURL(url);
54
+ if (fs.existsSync(path)){
53
55
  this.notifyConsumer(this);
54
56
  }
55
57
  },
@@ -13,6 +13,7 @@
13
13
  // See the License for the specific language governing permissions and
14
14
  // limitations under the License.
15
15
 
16
+ // #import Foundation
16
17
  'use strict';
17
18
 
18
19
  JSGlobalObject.SKHTTPError = function(statusCode, message, object){
@@ -28,9 +29,7 @@ JSGlobalObject.SKHTTPError = function(statusCode, message, object){
28
29
  this.message = message;
29
30
  this.object = object || null;
30
31
  }
31
- if (Error.captureStackTrace){
32
- Error.captureStackTrace(this, SKHTTPError);
33
- }
32
+ Error.captureStackTrace(this, SKHTTPError);
34
33
  };
35
34
 
36
35
  JSGlobalObject.SKHTTPError.prototype = Object.create(Error.prototype);
@@ -16,6 +16,7 @@
16
16
  // #import Foundation
17
17
  // #import "SKHTTPResponse.js"
18
18
  // #import "SKValidatingObject.js"
19
+ // #import "SKUserAgent.js"
19
20
  'use strict';
20
21
 
21
22
  JSClass("SKHTTPRequest", JSObject, {
@@ -299,4 +300,10 @@ JSClass("SKHTTPRequest", JSObject, {
299
300
  return null;
300
301
  },
301
302
 
303
+ userAgent: JSReadOnlyProperty(),
304
+
305
+ getUserAgent: function(){
306
+ return SKUserAgent.initWithString(this.headerMap.get("User-Agent", null));
307
+ },
308
+
302
309
  });
@@ -197,16 +197,20 @@ JSClass("SKHTTPResponder", JSObject, {
197
197
  return Promise.reject(new Error("not implemented"));
198
198
  },
199
199
 
200
- addAllowedOrigin: function(origin, methods, headers){
200
+ addAllowedOrigin: function(origin, methods, headers, credentials){
201
201
  if (methods === undefined){
202
202
  methods = ["*"];
203
203
  }
204
204
  if (headers === undefined){
205
205
  headers = ["Authorization", "Content-Type"];
206
206
  }
207
+ if (credentials === undefined){
208
+ credentials = false;
209
+ }
207
210
  this.allowedOrigins[origin] = {
208
211
  methods: methods,
209
- headers: headers
212
+ headers: headers,
213
+ credentials: credentials
210
214
  };
211
215
  },
212
216
 
@@ -229,6 +233,9 @@ JSClass("SKHTTPResponder", JSObject, {
229
233
  if (this.request.headerMap.get('Access-Control-Request-Headers', null) !== null){
230
234
  this.response.headerMap.set("Access-Control-Allow-Headers", allowed.headers.join(", "));
231
235
  }
236
+ if (allowed.credentials){
237
+ this.response.headerMap.set("Access-Control-Allow-Credentials", "true");
238
+ }
232
239
  if (this.request.method == "OPTIONS"){
233
240
  this.response.headerMap.set("Access-Control-Max-Age", 60 * 60);
234
241
  }
@@ -0,0 +1,130 @@
1
+ // Copyright 2021 Breakside Inc.
2
+ //
3
+ // Licensed under the Breakside Public License, Version 1.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // If a copy of the License was not distributed with this file, you may
6
+ // obtain a copy at
7
+ //
8
+ // http://breakside.io/licenses/LICENSE-1.0.txt
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ // #import Foundation
17
+ "use strict";
18
+
19
+ JSClass("SKUserAgent", JSObject, {
20
+
21
+ string: null,
22
+ products: null,
23
+ productsByIdentifier: null,
24
+ comments: null,
25
+ commentSet: null,
26
+
27
+ initWithString: function(string){
28
+ if (string === null || string === undefined){
29
+ return null;
30
+ }
31
+ this.string = string;
32
+ this.products = [];
33
+ this.productsByIdentifier = new Set();
34
+ this.comments = [];
35
+ this.commentSet = new Set();
36
+ this.parse();
37
+ },
38
+
39
+ parse: function(){
40
+ var str = this.string;
41
+ var i = 0;
42
+ var l = this.string.length;
43
+ var product = "";
44
+ var version = "";
45
+ var comment = "";
46
+ while (i < l){
47
+ while (str[i] == " " || str[i] == "\t"){
48
+ ++i;
49
+ }
50
+ if (i < l){
51
+ if (str[i] == "("){
52
+ comment = "";
53
+ ++i;
54
+ while (i < l && str[i] !== ")"){
55
+ if (str[i] == ";"){
56
+ comment = comment.trim();
57
+ if (comment !== ""){
58
+ this.addComment(comment);
59
+ }
60
+ comment = "";
61
+ }else{
62
+ comment += str[i];
63
+ }
64
+ ++i;
65
+ }
66
+ comment = comment.trim();
67
+ if (comment !== ""){
68
+ this.addComment(comment);
69
+ }
70
+ if (i < l){
71
+ ++i;
72
+ }
73
+ }else{
74
+ product = "";
75
+ version = "";
76
+ while (i < l && str[i] !== "/" && str[i] !== " " && str[i] !== "\t"){
77
+ product += str[i];
78
+ ++i;
79
+ }
80
+ if (i < l && str[i] == "/"){
81
+ ++i;
82
+ while (i < l && str[i] !== "(" && str[i] !== " " && str[i] !== "\t"){
83
+ version += str[i];
84
+ ++i;
85
+ }
86
+ }
87
+ this.addProduct(product, version);
88
+ }
89
+ }
90
+ }
91
+ },
92
+
93
+ addProduct: function(name, version){
94
+ if (version === "" || version === undefined){
95
+ version = null;
96
+ }
97
+ var product = {name: name, version: version};
98
+ this.products.push(product);
99
+ this.productsByIdentifier[name] = product;
100
+ if (version !== null){
101
+ this.productsByIdentifier["%s/%s".sprintf(name, version)] = product;
102
+ }
103
+ },
104
+
105
+ addComment: function(comment){
106
+ this.comments.push(comment);
107
+ this.commentSet.add(comment);
108
+ },
109
+
110
+ containsProduct: function(name, version){
111
+ if (version === undefined || version === null || version === ""){
112
+ return name in this.productsByIdentifier;
113
+ }
114
+ return "%s/%s".sprintf(name, version) in this.productsByIdentifier;
115
+ },
116
+
117
+ versionOfProduct: function(name){
118
+ var product = this.productsByIdentifier[name];
119
+ if (product){
120
+ return product.version;
121
+ }
122
+ return null;
123
+ },
124
+
125
+ containsComment: function(comment){
126
+ return this.commentSet.has(comment);
127
+ }
128
+
129
+ });
130
+
@@ -527,9 +527,7 @@ SKValidatingObject.Error = function(info, message){
527
527
  this.message = message;
528
528
  break;
529
529
  }
530
- if (Error.captureStackTrace){
531
- Error.captureStackTrace(this, SKValidatingObject.Error);
532
- }
530
+ Error.captureStackTrace(this, SKValidatingObject.Error);
533
531
  }
534
532
  };
535
533
 
@@ -31,4 +31,5 @@
31
31
  // #import "SKSecretsEnvironmentProvider.js"
32
32
  // #import "SKHTTPRoute.js"
33
33
  // #import "SKHTTPRouteMatch.js"
34
+ // #import "SKUserAgent.js"
34
35
  'use strict';
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ServerKitTesting
3
- JSBundleVersion: 2021.43.0
3
+ JSBundleVersion: 2021.52.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.TestKit
3
- JSBundleVersion: 2021.43.0
3
+ JSBundleVersion: 2021.52.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.UIKit
3
- JSBundleVersion: 2021.43.0
3
+ JSBundleVersion: 2021.52.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -180,4 +180,8 @@ UIAnimation.interpolate4Color = function(from, to, progress){
180
180
  from.components[2] + (to.components[2] - from.components[2]) * progress,
181
181
  from.components[3] + (to.components[3] - from.components[3]) * progress
182
182
  ]);
183
+ };
184
+
185
+ UIAnimation.Duration = {
186
+ transition: 0.2
183
187
  };
@@ -71,10 +71,10 @@ JSClass("UIContainerView", UIView, {
71
71
  this._contentView.removeFromSuperview();
72
72
  }
73
73
  this._contentView = contentView;
74
+ this.setNeedsLayout();
74
75
  if (this._contentView !== null){
75
76
  this.insertSubviewAtIndex(contentView, index);
76
77
  }
77
- this.setNeedsLayout();
78
78
  },
79
79
 
80
80
  setAlignment: function(alignment){
@@ -74,42 +74,10 @@ JSClass("UIContainerViewController", UIViewController, {
74
74
  contentViewController: JSDynamicProperty("_contentViewController", null),
75
75
 
76
76
  setContentViewController: function(contentViewController){
77
- var previousViewController = this._contentViewController;
77
+ this.replaceChildViewController(this._contentViewController, contentViewController);
78
+ this._contentViewController = contentViewController;
78
79
  if (this.isViewLoaded){
79
- var contentView = null;
80
- if (contentViewController !== null){
81
- contentView = contentViewController.view;
82
- }
83
- if (this.isViewVisible){
84
- if (previousViewController !== null){
85
- previousViewController.viewWillDisappear(false);
86
- previousViewController.enqueueDidDisappear();
87
- }
88
- if (contentViewController !== null){
89
- contentViewController.viewWillAppear(false);
90
- }
91
- }
92
- if (previousViewController !== null){
93
- previousViewController.removeFromParentViewController();
94
- }
95
- this._contentViewController = contentViewController;
96
- if (contentViewController !== null){
97
- this.addChildViewController(contentViewController);
98
- }
99
- this.view.contentView = contentView;
100
- if (this.isViewVisible){
101
- if (contentViewController !== null){
102
- contentViewController.enqueueDidAppear();
103
- }
104
- }
105
- }else{
106
- if (previousViewController !== null){
107
- previousViewController.removeFromParentViewController();
108
- }
109
- this._contentViewController = contentViewController;
110
- if (contentViewController !== null){
111
- this.addChildViewController(contentViewController);
112
- }
80
+ this.view.contentView = contentViewController !== null ? contentViewController.view : null;
113
81
  }
114
82
  },
115
83
 
@@ -101,6 +101,7 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
101
101
  // MARK: - Display Lifecycle
102
102
 
103
103
  layerDidChangeProperty: function(layer, property){
104
+ var methodName = 'updateHTMLProperty_' + property;
104
105
  switch (property){
105
106
  case 'shadowColor':
106
107
  case 'shadowOffset':
@@ -120,7 +121,11 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
120
121
  }
121
122
  break;
122
123
  default:
123
- this.propertiesNeedingUpdate[property] = true;
124
+ if (methodName in this){
125
+ this.propertiesNeedingUpdate[property] = true;
126
+ }else{
127
+ this.needsCustomDisplay = true;
128
+ }
124
129
  break;
125
130
  }
126
131
  },
@@ -20,13 +20,13 @@ JSClass("UIImageLayer", UILayer, {
20
20
 
21
21
  image: JSDynamicProperty('_image', null),
22
22
  imageFrame: JSDynamicProperty('_imageFrame', null),
23
- templateColor: JSDynamicProperty('_templateColor', null),
23
+ templateColor: UILayerAnimatedProperty(),
24
24
  automaticRenderMode: JSDynamicProperty('_automaticRenderMode', JSImage.RenderMode.original),
25
25
 
26
26
  init: function(){
27
27
  UIImageLayer.$super.init.call(this);
28
28
  this._imageFrame = JSRect.Zero;
29
- this._templateColor = JSColor.black;
29
+ this.model.templateColor = JSColor.black;
30
30
  },
31
31
 
32
32
  getImage: function(){
@@ -49,7 +49,7 @@ JSClass("UIImageLayer", UILayer, {
49
49
  drawInContext: function(context){
50
50
  if (this._image !== null && this._imageFrame.size.width > 0 && this._imageFrame.size.height > 0){
51
51
  if (this._image.renderMode === JSImage.RenderMode.template || (this._image.renderMode === JSImage.RenderMode.automatic && this._automaticRenderMode === JSImage.RenderMode.template)){
52
- context.setFillColor(this._templateColor);
52
+ context.setFillColor(this.presentation.templateColor);
53
53
  context.fillMaskedRect(this._imageFrame, this._image);
54
54
  }else{
55
55
  context.drawImage(this._image, this._imageFrame);
@@ -65,21 +65,19 @@ JSClass("UIImageLayer", UILayer, {
65
65
  this.setNeedsDisplay();
66
66
  },
67
67
 
68
- setTemplateColor: function(templateColor){
69
- if (templateColor === null && this._templateColor === null){
70
- return;
71
- }
72
- if (templateColor !== null && this._templateColor !== null && templateColor.isEqual(this._templateColor)){
73
- return;
74
- }
75
- this._templateColor = templateColor;
76
- this.setNeedsDisplay();
77
- },
78
-
79
68
  sizeToFit: function(){
80
69
  if (this._image !== null){
81
70
  this.bounds = JSRect(JSPoint.Zero, this._image.size);
82
71
  }
83
72
  }
84
73
 
74
+ });
75
+
76
+ UIImageLayer.Properties = Object.create(UILayer.Properties, {
77
+
78
+ templateColor: {
79
+ writable: true,
80
+ value: null
81
+ }
82
+
85
83
  });
@@ -40,6 +40,9 @@ UILayerAnimatedProperty.prototype.define = function(C, key, extensions){
40
40
  if (value === this.model[key]){
41
41
  return;
42
42
  }
43
+ if (value !== null && this.model[key] !== null && value.isEqual && value.isEqual(this.model[key])){
44
+ return;
45
+ }
43
46
  this._addImplicitAnimationForKey(key);
44
47
  this.model[key] = value;
45
48
  this.didChangeProperty(key);