@breakside/jskit 2023.22.0 → 2023.32.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 (57) hide show
  1. package/Frameworks/DOM.jsframework/Info.json +2 -2
  2. package/Frameworks/DOM.jsframework/JS/DOMElement.js +8 -0
  3. package/Frameworks/DOM.jsframework/JS/XMLSerializer.js +29 -3
  4. package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
  5. package/Frameworks/FontKit.jsframework/Info.json +2 -2
  6. package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
  7. package/Frameworks/Foundation.jsframework/Info.json +2 -2
  8. package/Frameworks/Foundation.jsframework/JS/JSAttributedString.js +1 -1
  9. package/Frameworks/Foundation.jsframework/JS/JSTextLayoutManager.js +3 -0
  10. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  11. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  12. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  13. package/Info.json +2 -2
  14. package/Node/io.breakside.jskit-bundle.js +2 -2
  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/CHPieChart.js +3 -1
  20. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  21. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  22. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  23. package/Root/Frameworks/DOM/DOMElement.js +8 -0
  24. package/Root/Frameworks/DOM/Info.yaml +1 -1
  25. package/Root/Frameworks/DOM/XMLSerializer.js +29 -3
  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/JSAttributedString.js +1 -1
  30. package/Root/Frameworks/Foundation/JSTextLayoutManager.js +3 -0
  31. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  32. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  33. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  34. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  35. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  36. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  37. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  38. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  39. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  40. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  41. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  42. package/Root/Frameworks/TestKit/TKMock.js +4 -0
  43. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  44. package/Root/Frameworks/UIKit/UIApplication.js +9 -1
  45. package/Root/Frameworks/UIKit/UIButton.js +1 -1
  46. package/Root/Frameworks/UIKit/UIHTMLApplication.js +14 -0
  47. package/Root/Frameworks/UIKit/UIHTMLContentEditableTextInputManager.js +3 -3
  48. package/Root/Frameworks/UIKit/UIHTMLDisplayServerCanvasContext.js +1 -1
  49. package/Root/Frameworks/UIKit/UIHTMLWindowServer.js +52 -0
  50. package/Root/Frameworks/UIKit/UIKeyboard.js +13 -0
  51. package/Root/Frameworks/UIKit/UIPopupWindow.js +1 -0
  52. package/Root/Frameworks/UIKit/UITextEditor.js +15 -7
  53. package/Root/Frameworks/UIKit/UITextField.js +15 -4
  54. package/Root/Frameworks/UIKit/UITextLayer.js +4 -2
  55. package/Root/Frameworks/UIKit/UITokenField.js +1 -0
  56. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  57. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.DOM",
4
- "JSBundleVersion": "2023.22.0",
4
+ "JSBundleVersion": "2023.32.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "DOM+Node.js"
10
10
  },
11
11
  "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",
12
- "GitRevision": "c5e74a677a557876be14d6e2bf15b95202dcea6e"
12
+ "GitRevision": "ac9770622bb71dffd8ec514219c86c56afecbae8"
13
13
  }
@@ -14,6 +14,7 @@
14
14
  // limitations under the License.
15
15
 
16
16
  // #import "DOMNode.js"
17
+ /* global XMLSerializer */
17
18
  'use strict';
18
19
 
19
20
  DOM.Element.prototype = Object.create(DOM.Node.prototype, {
@@ -107,6 +108,13 @@ DOM.Element.prototype = Object.create(DOM.Node.prototype, {
107
108
  delete this._attributeMap[':global:'][name];
108
109
  }
109
110
  }
111
+ },
112
+
113
+ innerHTML: {
114
+ get: function DOMElement_innerHTML(){
115
+ var serializer = new XMLSerializer();
116
+ return serializer._serializeToString(this, true);
117
+ }
110
118
  }
111
119
 
112
120
  });
@@ -21,7 +21,12 @@ JSGlobalObject.XMLSerializer = function XMLSerializer(){
21
21
 
22
22
  XMLSerializer.prototype = {
23
23
 
24
- serializeToString: function(document){
24
+ serializeToString: function(node){
25
+ return this._serializeToString(node, false);
26
+ },
27
+
28
+ _serializeToString: function(node, childrenOnly){
29
+ var document = node.ownerDocument || node;
25
30
  var doctype = document.doctype;
26
31
  var isHTML = doctype && doctype.name == "html";
27
32
  var str = "";
@@ -127,10 +132,31 @@ XMLSerializer.prototype = {
127
132
  }
128
133
  };
129
134
 
130
- if (!isHTML){
135
+ if (!isHTML && !childrenOnly){
131
136
  str += '<?xml version="1.0" encoding="utf-8"?>\n';
132
137
  }
133
- writeNode(document, {':global:': null});
138
+ if (childrenOnly){
139
+ var namespaces = {':global:': null};
140
+ if (node.nodeType === DOM.Node.ELEMENT_NODE){
141
+ if (node.namespaceURI !== null){
142
+ if (node.prefix !== null){
143
+ if (namespaces[node.prefix] != node.namespaceURI){
144
+ namespaces[node.prefix] = node.namespaceURI;
145
+ }
146
+ }else{
147
+ if (namespaces[':global:'] !== node.namespaceURI){
148
+ namespaces[':global:'] = node.namespaceURI;
149
+ }
150
+ }
151
+ }
152
+ }
153
+ var i, l;
154
+ for (i = 0, l = node.childNodes.length; i < l; ++i){
155
+ writeNode(node.childNodes[i], namespaces);
156
+ }
157
+ }else{
158
+ writeNode(node, {':global:': null});
159
+ }
134
160
 
135
161
  return str;
136
162
  }
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.DOM'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.DOM",
6
- "JSBundleVersion": "2023.22.0",
6
+ "JSBundleVersion": "2023.32.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.DOM'] = {
11
11
  "node": "DOM+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": "c5e74a677a557876be14d6e2bf15b95202dcea6e"
14
+ "GitRevision": "ac9770622bb71dffd8ec514219c86c56afecbae8"
15
15
  },
16
16
  "Resources": [],
17
17
  "ResourceLookup": {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.FontKit",
4
- "JSBundleVersion": "2023.22.0",
4
+ "JSBundleVersion": "2023.32.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
8
8
  "html": "FontKit+HTML.js"
9
9
  },
10
10
  "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",
11
- "GitRevision": "c5e74a677a557876be14d6e2bf15b95202dcea6e"
11
+ "GitRevision": "ac9770622bb71dffd8ec514219c86c56afecbae8"
12
12
  }
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.JSKit.FontKit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.FontKit",
6
- "JSBundleVersion": "2023.22.0",
6
+ "JSBundleVersion": "2023.32.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
10
10
  "html": "FontKit+HTML.js"
11
11
  },
12
12
  "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",
13
- "GitRevision": "c5e74a677a557876be14d6e2bf15b95202dcea6e"
13
+ "GitRevision": "ac9770622bb71dffd8ec514219c86c56afecbae8"
14
14
  },
15
15
  "Resources": [],
16
16
  "ResourceLookup": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.Foundation",
4
- "JSBundleVersion": "2023.22.0",
4
+ "JSBundleVersion": "2023.32.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "Foundation+Node.js"
10
10
  },
11
11
  "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",
12
- "GitRevision": "c5e74a677a557876be14d6e2bf15b95202dcea6e"
12
+ "GitRevision": "ac9770622bb71dffd8ec514219c86c56afecbae8"
13
13
  }
@@ -360,7 +360,7 @@ JSClass("JSAttributedString", JSObject, {
360
360
  var run = this._runs[runRange.location];
361
361
  run.attributes = JSCopy(attributes);
362
362
  if (runRange.length > 1){
363
- run.range.length = this._runs[runRange.end - 1].end - run.range.location;
363
+ run.range.length = this._runs[runRange.end - 1].range.end - run.range.location;
364
364
  this._runs.splice(runRange.location + 1, runRange.length - 1);
365
365
  }
366
366
  this._fixRunsInRunRange(JSRange(runRange.location, 1));
@@ -72,6 +72,9 @@ JSClass("JSTextLayoutManager", JSObject, {
72
72
 
73
73
  replaceTextStorage: function(storage){
74
74
  var originalStorage = this._textStorage;
75
+ if (storage === originalStorage){
76
+ return;
77
+ }
75
78
  if (originalStorage !== null){
76
79
  var managers = originalStorage.layoutManagers;
77
80
  originalStorage.removeAllLayoutManagers();
@@ -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": "2023.22.0",
6
+ "JSBundleVersion": "2023.32.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": "c5e74a677a557876be14d6e2bf15b95202dcea6e"
14
+ "GitRevision": "ac9770622bb71dffd8ec514219c86c56afecbae8"
15
15
  },
16
16
  "Resources": [
17
17
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.SecurityKit",
4
- "JSBundleVersion": "2023.22.0",
4
+ "JSBundleVersion": "2023.32.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "SecurityKit+Node.js"
10
10
  },
11
11
  "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",
12
- "GitRevision": "c5e74a677a557876be14d6e2bf15b95202dcea6e"
12
+ "GitRevision": "ac9770622bb71dffd8ec514219c86c56afecbae8"
13
13
  }
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.SecurityKit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.SecurityKit",
6
- "JSBundleVersion": "2023.22.0",
6
+ "JSBundleVersion": "2023.32.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.SecurityKit'] = {
11
11
  "node": "SecurityKit+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": "c5e74a677a557876be14d6e2bf15b95202dcea6e"
14
+ "GitRevision": "ac9770622bb71dffd8ec514219c86c56afecbae8"
15
15
  },
16
16
  "Resources": [],
17
17
  "ResourceLookup": {
package/Info.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "JSBundleType": "node",
3
3
  "JSBundleIdentifier": "io.breakside.jskit",
4
- "JSBundleVersion": "2023.22.0",
4
+ "JSBundleVersion": "2023.32.0",
5
5
  "JSExecutableName": "jskit",
6
6
  "NPMOrganization": "breakside",
7
7
  "JSResources": [
8
8
  "Tests/HTMLTestRunner.js",
9
9
  "Tests/NodeTestRunner.js"
10
10
  ],
11
- "GitRevision": "c5e74a677a557876be14d6e2bf15b95202dcea6e"
11
+ "GitRevision": "ac9770622bb71dffd8ec514219c86c56afecbae8"
12
12
  }
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.jskit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "node",
5
5
  "JSBundleIdentifier": "io.breakside.jskit",
6
- "JSBundleVersion": "2023.22.0",
6
+ "JSBundleVersion": "2023.32.0",
7
7
  "JSExecutableName": "jskit",
8
8
  "NPMOrganization": "breakside",
9
9
  "JSResources": [
10
10
  "Tests/HTMLTestRunner.js",
11
11
  "Tests/NodeTestRunner.js"
12
12
  ],
13
- "GitRevision": "c5e74a677a557876be14d6e2bf15b95202dcea6e"
13
+ "GitRevision": "ac9770622bb71dffd8ec514219c86c56afecbae8"
14
14
  },
15
15
  "Resources": [
16
16
  {
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.APIKit
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSIncludeDirectories:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.APIKitTesting
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.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.AuthKit
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.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.CSSOM
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -107,10 +107,12 @@ JSClass("CHPieChart", CHChart, {
107
107
  }
108
108
  this.legend.drawInContext(context, legendRect);
109
109
  }
110
- this.drawPieInContext(context, pieRect);
111
110
  },
112
111
 
113
112
  drawPieInContext: function(context, rect){
113
+ if (rect.size.width <= 0 || rect.size.height <= 0){
114
+ return;
115
+ }
114
116
  if (this.series.length < 1){
115
117
  return;
116
118
  }
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ChartKit
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.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.ConferenceKit
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.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.DBKit
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -14,6 +14,7 @@
14
14
  // limitations under the License.
15
15
 
16
16
  // #import "DOMNode.js"
17
+ /* global XMLSerializer */
17
18
  'use strict';
18
19
 
19
20
  DOM.Element.prototype = Object.create(DOM.Node.prototype, {
@@ -107,6 +108,13 @@ DOM.Element.prototype = Object.create(DOM.Node.prototype, {
107
108
  delete this._attributeMap[':global:'][name];
108
109
  }
109
110
  }
111
+ },
112
+
113
+ innerHTML: {
114
+ get: function DOMElement_innerHTML(){
115
+ var serializer = new XMLSerializer();
116
+ return serializer._serializeToString(this, true);
117
+ }
110
118
  }
111
119
 
112
120
  });
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.DOM
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -21,7 +21,12 @@ JSGlobalObject.XMLSerializer = function XMLSerializer(){
21
21
 
22
22
  XMLSerializer.prototype = {
23
23
 
24
- serializeToString: function(document){
24
+ serializeToString: function(node){
25
+ return this._serializeToString(node, false);
26
+ },
27
+
28
+ _serializeToString: function(node, childrenOnly){
29
+ var document = node.ownerDocument || node;
25
30
  var doctype = document.doctype;
26
31
  var isHTML = doctype && doctype.name == "html";
27
32
  var str = "";
@@ -127,10 +132,31 @@ XMLSerializer.prototype = {
127
132
  }
128
133
  };
129
134
 
130
- if (!isHTML){
135
+ if (!isHTML && !childrenOnly){
131
136
  str += '<?xml version="1.0" encoding="utf-8"?>\n';
132
137
  }
133
- writeNode(document, {':global:': null});
138
+ if (childrenOnly){
139
+ var namespaces = {':global:': null};
140
+ if (node.nodeType === DOM.Node.ELEMENT_NODE){
141
+ if (node.namespaceURI !== null){
142
+ if (node.prefix !== null){
143
+ if (namespaces[node.prefix] != node.namespaceURI){
144
+ namespaces[node.prefix] = node.namespaceURI;
145
+ }
146
+ }else{
147
+ if (namespaces[':global:'] !== node.namespaceURI){
148
+ namespaces[':global:'] = node.namespaceURI;
149
+ }
150
+ }
151
+ }
152
+ }
153
+ var i, l;
154
+ for (i = 0, l = node.childNodes.length; i < l; ++i){
155
+ writeNode(node.childNodes[i], namespaces);
156
+ }
157
+ }else{
158
+ writeNode(node, {':global:': null});
159
+ }
134
160
 
135
161
  return str;
136
162
  }
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.Dispatch
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.0
4
4
  JSCopyright: Copyright © 2020 Breakside Inc.
5
5
  JSBundleEnvironments:
6
6
  html: Dispatch+HTML.js
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.FontKit
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.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.Foundation
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -360,7 +360,7 @@ JSClass("JSAttributedString", JSObject, {
360
360
  var run = this._runs[runRange.location];
361
361
  run.attributes = JSCopy(attributes);
362
362
  if (runRange.length > 1){
363
- run.range.length = this._runs[runRange.end - 1].end - run.range.location;
363
+ run.range.length = this._runs[runRange.end - 1].range.end - run.range.location;
364
364
  this._runs.splice(runRange.location + 1, runRange.length - 1);
365
365
  }
366
366
  this._fixRunsInRunRange(JSRange(runRange.location, 1));
@@ -72,6 +72,9 @@ JSClass("JSTextLayoutManager", JSObject, {
72
72
 
73
73
  replaceTextStorage: function(storage){
74
74
  var originalStorage = this._textStorage;
75
+ if (storage === originalStorage){
76
+ return;
77
+ }
75
78
  if (originalStorage !== null){
76
79
  var managers = originalStorage.layoutManagers;
77
80
  originalStorage.removeAllLayoutManagers();
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ImageKit
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.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: 2023.22.0
3
+ JSBundleVersion: 2023.32.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: 2023.22.0
3
+ JSBundleVersion: 2023.32.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: 2023.22.0
3
+ JSBundleVersion: 2023.32.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: 2023.22.0
3
+ JSBundleVersion: 2023.32.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: 2023.22.0
3
+ JSBundleVersion: 2023.32.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: 2023.22.0
3
+ JSBundleVersion: 2023.32.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: 2023.22.0
3
+ JSBundleVersion: 2023.32.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: 2023.22.0
3
+ JSBundleVersion: 2023.32.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.ServerKitTesting
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.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: 2023.22.0
3
+ JSBundleVersion: 2023.32.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -75,6 +75,10 @@ JSGlobalObject.TKMock = function(methods){
75
75
  }
76
76
  mockMethod.results.push({callback: {args: args, argIndex: argIndex, targeted: true}});
77
77
  };
78
+ mockMethod.reset = function(){
79
+ mockMethod.calls = [];
80
+ mockMethod.results = [];
81
+ };
78
82
  return mockMethod;
79
83
  };
80
84
  for (var name in methods){
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.UIKit
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -229,13 +229,21 @@ JSClass('UIApplication', UIResponder, {
229
229
  }else{
230
230
  this._stopCalled = true;
231
231
  logger.info("Stopping application");
232
+ var closed = false;
232
233
  var _close = function(){
234
+ if (closed){
235
+ return;
236
+ }
237
+ closed = true;
233
238
  JSUserDefaults.shared.close(function(){
234
239
  completion.call(target);
235
240
  });
236
241
  };
237
242
  if (this.delegate && this.delegate.applicationWillTerminate){
238
- this.delegate.applicationWillTerminate(_close);
243
+ var promise = this.delegate.applicationWillTerminate(_close);
244
+ if (promise instanceof Promise){
245
+ promise.finally(_close);
246
+ }
239
247
  }else{
240
248
  _close();
241
249
  }
@@ -214,7 +214,7 @@ JSClass("UIButton", UIControl, {
214
214
  this.active = false;
215
215
  }
216
216
  var location = event.locationInView(this);
217
- this.over = this.window !== null && this.containsPoint(location);
217
+ this.over = this.enabled && this.window !== null && this.containsPoint(location);
218
218
  return;
219
219
  }
220
220
  UIButton.$super.mouseUp.call(this, event);
@@ -134,6 +134,7 @@ JSClass("UIHTMLApplication", UIApplication, {
134
134
  this.domWindow.addEventListener("hashchange", this);
135
135
  this.domWindow.addEventListener("popstate", this);
136
136
  this.domWindow.addEventListener("pageshow", this);
137
+ this.domWindow.addEventListener("visibilitychange", this);
137
138
  },
138
139
 
139
140
  removeEventListeners: function(){
@@ -143,6 +144,7 @@ JSClass("UIHTMLApplication", UIApplication, {
143
144
  this.domWindow.removeEventListener("hashchange", this);
144
145
  this.domWindow.removeEventListener("popstate", this);
145
146
  this.domWindow.removeEventListener("pageshow", this);
147
+ this.domWindow.removeEventListener("visibilitychange", this);
146
148
  },
147
149
 
148
150
  handleEvent: function(e){
@@ -244,6 +246,18 @@ JSClass("UIHTMLApplication", UIApplication, {
244
246
  }
245
247
  },
246
248
 
249
+ _event_visibilitychange: function(e){
250
+ if (this.domWindow.document.visibilityState === "hidden"){
251
+ if (this.delegate && this.delegate.applicationDidEnterBackground){
252
+ this.delegate.applicationDidEnterBackground(this);
253
+ }
254
+ }else if (this.domWindow.document.visibilityState === "visible"){
255
+ if (this.delegate && this.delegate.applicationDidEnterForeground){
256
+ this.delegate.applicationDidEnterForeground(this);
257
+ }
258
+ }
259
+ },
260
+
247
261
  _crash: function(error){
248
262
  this.removeEventListeners();
249
263
  if (this.delegate && this.delegate.applicationDidCrash){
@@ -83,7 +83,7 @@ JSClass('UIHTMLContentEditableTextInputManager', UITextInputManager, {
83
83
  setEditableElement: function(editableElement){
84
84
  if (editableElement === this._editableElement){
85
85
  if (this._editableElement !== null){
86
- this._editableElement.focus();
86
+ this._editableElement.focus({preventScroll: true});
87
87
  this.scheduleDocumentSelectionUpdate();
88
88
  }
89
89
  return;
@@ -95,7 +95,7 @@ JSClass('UIHTMLContentEditableTextInputManager', UITextInputManager, {
95
95
  this._editableElement = editableElement;
96
96
  if (this._editableElement !== null){
97
97
  this.setupEditableElement();
98
- this._editableElement.focus();
98
+ this._editableElement.focus({preventScroll: true});
99
99
  }
100
100
  this.scheduleDocumentSelectionUpdate();
101
101
  },
@@ -749,7 +749,7 @@ JSClass('UIHTMLContentEditableTextInputManager', UITextInputManager, {
749
749
 
750
750
  _ensureCorrectFocus: function(){
751
751
  if (this._editableElement !== null){
752
- this._editableElement.focus();
752
+ this._editableElement.focus({preventScroll: true});
753
753
  this.updateDocumentSelection();
754
754
  }
755
755
  },
@@ -1116,7 +1116,7 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
1116
1116
 
1117
1117
  updateAccessibilityFocus: function(accessibility){
1118
1118
  var ariaRole = ariaRoleForAccessibility(accessibility);
1119
- this.element.focus();
1119
+ this.element.focus({preventScroll: true});
1120
1120
  // if (focusedAccessibility === null || focusedAccessibility === undefined){
1121
1121
  // this.element.removeAttribute("aria-activedescendant");
1122
1122
  // }else{
@@ -22,6 +22,7 @@
22
22
  // #import "UIHTMLContentEditableTextInputManager.js"
23
23
  // #import "UIPlatform.js"
24
24
  // #import "UIOpenPanel.js"
25
+ // #import "UIKeyboard.js"
25
26
  // #feature Element.prototype.addEventListener
26
27
  // #feature 'key' in KeyboardEvent.prototype
27
28
  // #feature File
@@ -166,6 +167,9 @@ JSClass("UIHTMLWindowServer", UIWindowServer, {
166
167
  this.rootElement.addEventListener('touchend', this, {passive: false, capture: false});
167
168
  this.rootElement.addEventListener('touchcancel', this, {passive: false, capture: false});
168
169
  this.rootElement.addEventListener('touchmove', this, {passive: false, capture: false});
170
+ if (this.domWindow.visualViewport !== null){
171
+ this.domWindow.visualViewport.addEventListener('resize', this, false);
172
+ }
169
173
  },
170
174
 
171
175
  removeEventListeners: function(){
@@ -200,6 +204,9 @@ JSClass("UIHTMLWindowServer", UIWindowServer, {
200
204
  this.rootElement.removeEventListener('touchend', this, {passive: false, capture: false});
201
205
  this.rootElement.removeEventListener('touchcancel', this, {passive: false, capture: false});
202
206
  this.rootElement.removeEventListener('touchmove', this, {passive: false, capture: false});
207
+ if (this.domWindow.visualViewport !== null){
208
+ this.domWindow.visualViewport.removeEventListener('resize', this, false);
209
+ }
203
210
  },
204
211
 
205
212
  handleEvent: function(e){
@@ -721,6 +728,10 @@ JSClass("UIHTMLWindowServer", UIWindowServer, {
721
728
  // --------------------------------------------------------------------
722
729
  // MARK: - Window Events
723
730
 
731
+ virtualKeyboard: JSLazyInitProperty(function(){
732
+ return UIKeyboard.init();
733
+ }),
734
+
724
735
  resize: function(e){
725
736
  // resize event is not cancelable, so no need for preventDefault
726
737
  if (e.currentTarget === this.domWindow){
@@ -728,6 +739,47 @@ JSClass("UIHTMLWindowServer", UIWindowServer, {
728
739
  this.screen.frame = JSRect(JSPoint.Zero, this.rootElementSize());
729
740
  this.screenDidChangeFrame(oldFrame);
730
741
  this.displayServer.setScreenSize(this.screen.frame.size);
742
+ }else if (e.currentTarget === this.domWindow.visualViewport){
743
+ // using touch screen as proxy for "has virtual keyboard"
744
+ // not a perfect match, but good enough for now
745
+ if (UIDevice.shared.primaryPointerType === UIUserInterface.PointerType.touch){
746
+ var viewportFrame = JSRect(
747
+ Math.floor(this.domWindow.visualViewport.offsetLeft),
748
+ Math.floor(this.domWindow.visualViewport.offsetTop),
749
+ Math.floor(this.domWindow.visualViewport.width),
750
+ Math.floor(this.domWindow.visualViewport.height)
751
+ );
752
+ if (viewportFrame.origin.x === this.screen.frame.origin.x && viewportFrame.origin.y === this.screen.frame.origin.y && viewportFrame.size.width === this.screen.frame.size.width){
753
+ // A keyboard may not be the only thing that obstructs the bottom of the screen, but
754
+ // we'll assume that a large-ish obstruction is a keyboard
755
+ var obstructedHeight = this.screen.frame.size.height - viewportFrame.size.height;
756
+ var obstructedFrame = JSRect(0, this.screen.frame.origin.x + this.screen.frame.size.height - obstructedHeight, this.screen.frame.size.width, obstructedHeight);
757
+ if (!this.virtualKeyboard.frame.isEqual(obstructedFrame)){
758
+ var wasVisible = this.virtualKeyboard.visible;
759
+ this.virtualKeyboard.frame = obstructedFrame;
760
+ this.virtualKeyboard.visible = this.virtualKeyboard.frame.size.height > 50;
761
+ if (wasVisible){
762
+ if (this.virtualKeyboard.visible){
763
+ JSNotificationCenter.shared.post("UIKeyboardDidShow", this, {frame: this.virtualKeyboard.frame});
764
+ }else{
765
+ JSNotificationCenter.shared.post("UIKeyboardDidHide", this);
766
+ // This should only come into play on Android, where hiding the keyboard
767
+ // does NOT cause a blur event. We want to go ahead and remove first responder
768
+ // status when the keyboard is hidden.
769
+ if (this.textInputManager.textInputClient instanceof UIView){
770
+ if (this.textInputManager.textInputClient.window.firstResponder === this.textInputManager.textInputClient){
771
+ this.textInputManager.textInputClient.window.firstResponder = null;
772
+ }
773
+ }
774
+ }
775
+ }else{
776
+ if (this.virtualKeyboard.visible){
777
+ JSNotificationCenter.shared.post("UIKeyboardDidShow", this, {frame: this.virtualKeyboard.frame});
778
+ }
779
+ }
780
+ }
781
+ }
782
+ }
731
783
  }
732
784
  },
733
785
 
@@ -0,0 +1,13 @@
1
+ // #import Foundation
2
+ "use strict";
3
+
4
+ JSClass("UIKeyboard", JSObject, {
5
+
6
+ frame: null,
7
+ visible: false,
8
+
9
+ init: function(){
10
+ this.frame = JSRect.Zero;
11
+ }
12
+
13
+ });
@@ -394,6 +394,7 @@ JSClass("UIPopupWindowStyler", UIWindowStyler, {
394
394
  },
395
395
 
396
396
  layoutWindow: function(window){
397
+ UIPopupWindowStyler.$super.layoutWindow.call(this, window);
397
398
  var contentInsets = JSInsets(window.contentInsets);
398
399
  if (window._showsSourceArrow){
399
400
  var popupBacking = window.stylerProperties.popupBacking;
@@ -475,7 +475,7 @@ JSClass("UITextEditor", JSObject, {
475
475
  var selections = this._selectionsCopy();
476
476
  for (i = 0, l = selections.length; i < l; ++i){
477
477
  selection = selections[i];
478
- this._setAttributeValueForSelection(name, value, selection);
478
+ this._setAttributeValueForSelection(name, value, selection, false);
479
479
  }
480
480
  this._setSelectionsAllowingUndo(selections);
481
481
  this.undoManager.endUndoGrouping();
@@ -585,7 +585,7 @@ JSClass("UITextEditor", JSObject, {
585
585
  var selections = this._selectionsCopy();
586
586
  for (i = 0, l = selections.length; i < l; ++i){
587
587
  selection = selections[i];
588
- this._setAttributeValueForSelection(name, !currentValue, selection);
588
+ this._setAttributeValueForSelection(name, !currentValue, selection, true);
589
589
  }
590
590
  this._setSelectionsAllowingUndo(selections);
591
591
  this.undoManager.endUndoGrouping();
@@ -593,17 +593,25 @@ JSClass("UITextEditor", JSObject, {
593
593
  this._resetSelectionAffinity();
594
594
  },
595
595
 
596
- _setAttributeValueForSelection: function(name, value, selection){
596
+ _setAttributeValueForSelection: function(name, value, selection, expandingSelection){
597
597
  var textStorage = this.textLayoutManager.textStorage;
598
+ var str = textStorage.string;
599
+ var range = selection.range;
600
+ if (expandingSelection && selection.range.length === 0){
601
+ range = str.rangeForWordAtIndex(selection.range.location);
602
+ if (selection.range.location === range.location || selection.range.location === range.end){
603
+ range = selection.range;
604
+ }
605
+ }
598
606
  var replacementString;
599
- if (selection.range.length > 0){
600
- replacementString = textStorage.attributedSubstringInRange(selection.range);
607
+ if (range.length > 0){
608
+ replacementString = textStorage.attributedSubstringInRange(range);
601
609
  if (value !== null && value !== undefined){
602
610
  replacementString.addAttributeInRange(name, value, JSRange(0, replacementString.string.length));
603
611
  }else{
604
612
  replacementString.removeAttributeInRange(name, JSRange(0, replacementString.string.length));
605
613
  }
606
- this._replaceTextStorageRangeAllowingUndo(textStorage, selection.range, replacementString);
614
+ this._replaceTextStorageRangeAllowingUndo(textStorage, range, replacementString);
607
615
  }else{
608
616
  selection.attributes = this._insertAttributesForSelection(selection);
609
617
  var currentValue = selection.attributes[name];
@@ -612,7 +620,7 @@ JSClass("UITextEditor", JSObject, {
612
620
  }else{
613
621
  delete selection.attributes[name];
614
622
  }
615
- this.undoManager.registerUndo(this, this._setAttributeValueForSelection, name, currentValue, selection);
623
+ this.undoManager.registerUndo(this, this._setAttributeValueForSelection, name, currentValue, selection, expandingSelection);
616
624
  }
617
625
  },
618
626
 
@@ -1008,10 +1008,12 @@ JSClass("UITextField", UIControl, {
1008
1008
  this._localEditor.handleTouchesEnded(touches, event);
1009
1009
  return;
1010
1010
  }
1011
- var origin = this.convertPointToView(this.bounds.origin, this.window);
1012
- if (this.containsPoint(location) && this._touchOrigin.distanceToPoint(origin) < 2){
1013
- this.window.firstResponder = this;
1014
- this._localEditor.handleTouchesEndedAtLocation(this.layer.convertPointToLayer(location, this._textLayer), touches, event);
1011
+ if (this._touchOrigin !== null){
1012
+ var origin = this.convertPointToView(this.bounds.origin, this.window);
1013
+ if (this.containsPoint(location) && this._touchOrigin.distanceToPoint(origin) < 2){
1014
+ this.window.firstResponder = this;
1015
+ this._localEditor.handleTouchesEndedAtLocation(this.layer.convertPointToLayer(location, this._textLayer), touches, event);
1016
+ }
1015
1017
  }
1016
1018
  }
1017
1019
  UITextField.$super.touchesEnded.call(this, touches, event);
@@ -1407,6 +1409,7 @@ JSClass("UITextFieldCustomStyler", UITextFieldStyler, {
1407
1409
  disabledBorderColor: null,
1408
1410
  borderWidth: 0,
1409
1411
  textColor: null,
1412
+ disabledTextColor: null,
1410
1413
  placeholderColor: null,
1411
1414
  cornerRadius: 0,
1412
1415
  textInsets: null,
@@ -1442,6 +1445,11 @@ JSClass("UITextFieldCustomStyler", UITextFieldStyler, {
1442
1445
  }else{
1443
1446
  this.textColor = JSColor.text;
1444
1447
  }
1448
+ if (spec.containsKey("disabledTextColor")){
1449
+ this.disabledTextColor = spec.valueForKey("disabledTextColor", JSColor);
1450
+ }else{
1451
+ this.disabledTextColor = this.textColor;
1452
+ }
1445
1453
  if (spec.containsKey("placeholderColor")){
1446
1454
  this.placeholderColor = spec.valueForKey("placeholderColor", JSColor);
1447
1455
  }
@@ -1486,6 +1494,7 @@ JSClass("UITextFieldCustomStyler", UITextFieldStyler, {
1486
1494
  if (textField.active){
1487
1495
  textField.backgroundColor = this.activeBackgroundColor || this.backgroundColor;
1488
1496
  textField.borderColor = this.activeBorderColor || this.borderColor;
1497
+ textField.textColor = this.textColor;
1489
1498
  }else if (textField.enabled){
1490
1499
  if (textField.over){
1491
1500
  textField.backgroundColor = this.overBackgroundColor || this.backgroundColor;
@@ -1494,9 +1503,11 @@ JSClass("UITextFieldCustomStyler", UITextFieldStyler, {
1494
1503
  textField.backgroundColor = this.backgroundColor;
1495
1504
  textField.borderColor = this.borderColor;
1496
1505
  }
1506
+ textField.textColor = this.textColor;
1497
1507
  }else{
1498
1508
  textField.backgroundColor = this.disabledBackgroundColor || this.backgroundColor;
1499
1509
  textField.borderColor = this.disabledBorderColor || this.borderColor;
1510
+ textField.textColor = this.disabledTextColor;
1500
1511
  }
1501
1512
  },
1502
1513
 
@@ -167,8 +167,10 @@ JSClass("UITextLayer", UILayer, {
167
167
  if (!text.isKindOfClass(JSTextStorage)){
168
168
  text = JSTextStorage.initWithAttributedString(text);
169
169
  }
170
- this._textStorage = text;
171
- this._textLayoutManager.replaceTextStorage(this._textStorage);
170
+ if (text !== this._textStorage){
171
+ this._textStorage = text;
172
+ this._textLayoutManager.replaceTextStorage(this._textStorage);
173
+ }
172
174
  this.setNeedsDisplay();
173
175
  this._displayQueued = true;
174
176
  },
@@ -143,6 +143,7 @@ JSClass("UITokenField", UITextField, {
143
143
  this.attributedText.replaceCharactersInRangeWithAttributedString(JSRange(range.location + indexAdjustment, range.length), attachmentString);
144
144
  }
145
145
  }
146
+ this.sendActionsForEvents(UIControl.Event.primaryAction | UIControl.Event.valueChanged);
146
147
  },
147
148
 
148
149
  _convertStringToRepresentedObject: function(string, range){
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.UIKitTesting
3
- JSBundleVersion: 2023.22.0
3
+ JSBundleVersion: 2023.32.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "node": ">=10.10.0"
10
10
  },
11
11
  "name": "@breakside/jskit",
12
- "version": "2023.22.0",
12
+ "version": "2023.32.0",
13
13
  "license": "SEE LICENSE IN LICENSE.txt",
14
14
  "files": [
15
15
  "*"