@breakside/jskit 2022.23.0 → 2022.25.1
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.
- package/Frameworks/DOM.jsframework/Info.json +2 -2
- package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
- package/Frameworks/FontKit.jsframework/Info.json +2 -2
- package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
- package/Frameworks/Foundation.jsframework/Info.json +2 -2
- package/Frameworks/Foundation.jsframework/JS/JSAttributedString.js +139 -10
- package/Frameworks/Foundation.jsframework/JS/JSFileManager+Node.js +2 -2
- package/Frameworks/Foundation.jsframework/JS/JSParagraphStyle.js +71 -0
- package/Frameworks/Foundation.jsframework/JS/JSTextAttachment.js +1 -1
- package/Frameworks/Foundation.jsframework/JS/JSTextContainer.js +56 -29
- package/Frameworks/Foundation.jsframework/JS/JSTextFrame.js +2 -32
- package/Frameworks/Foundation.jsframework/JS/JSTextFramesetter.js +125 -22
- package/Frameworks/Foundation.jsframework/JS/JSTextLayoutManager.js +11 -3
- package/Frameworks/Foundation.jsframework/JS/JSTextLine.js +4 -3
- package/Frameworks/Foundation.jsframework/JS/JSTextRun.js +5 -3
- package/Frameworks/Foundation.jsframework/JS/JSTextTypesetter.js +41 -25
- package/Frameworks/Foundation.jsframework/JS/JSURL.js +3 -0
- package/Frameworks/Foundation.jsframework/JS/JSZip.js +97 -76
- package/Frameworks/Foundation.jsframework/JS/String+JS.js +35 -0
- package/Frameworks/Foundation.jsframework/JS/UnicodeChar.js +8 -0
- package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
- package/Frameworks/Foundation.jsframework/sources.json +3 -0
- package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
- package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
- package/Info.json +2 -2
- package/Node/io.breakside.jskit-bundle.js +2 -2
- package/Node/jskit +1 -0
- package/Root/Frameworks/APIKit/Info.yaml +1 -1
- package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/AuthKit/Info.yaml +1 -1
- package/Root/Frameworks/CSSOM/Info.yaml +1 -1
- package/Root/Frameworks/ChartKit/CHAxis.js +5 -5
- package/Root/Frameworks/ChartKit/CHPieChart.js +1 -1
- package/Root/Frameworks/ChartKit/Info.yaml +1 -1
- package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
- package/Root/Frameworks/DBKit/Info.yaml +1 -1
- package/Root/Frameworks/DOM/Info.yaml +1 -1
- package/Root/Frameworks/Dispatch/Info.yaml +1 -1
- package/Root/Frameworks/FontKit/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/JSAttributedString.js +139 -10
- package/Root/Frameworks/Foundation/JSFileManager+Node.js +2 -2
- package/Root/Frameworks/Foundation/JSParagraphStyle.js +71 -0
- package/Root/Frameworks/Foundation/JSTextAttachment.js +1 -1
- package/Root/Frameworks/Foundation/JSTextContainer.js +56 -29
- package/Root/Frameworks/Foundation/JSTextFrame.js +2 -32
- package/Root/Frameworks/Foundation/JSTextFramesetter.js +125 -22
- package/Root/Frameworks/Foundation/JSTextLayoutManager.js +11 -3
- package/Root/Frameworks/Foundation/JSTextLine.js +4 -3
- package/Root/Frameworks/Foundation/JSTextRun.js +5 -3
- package/Root/Frameworks/Foundation/JSTextTypesetter.js +41 -25
- package/Root/Frameworks/Foundation/JSURL.js +3 -0
- package/Root/Frameworks/Foundation/JSZip.js +97 -76
- package/Root/Frameworks/Foundation/String+JS.js +35 -0
- package/Root/Frameworks/Foundation/UnicodeChar.js +8 -0
- package/Root/Frameworks/ImageKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
- package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
- package/Root/Frameworks/PDFKit/Info.yaml +1 -1
- package/Root/Frameworks/QRKit/Info.yaml +1 -1
- package/Root/Frameworks/SearchKit/Info.yaml +1 -1
- package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
- package/Root/Frameworks/ServerKit/Info.yaml +1 -1
- package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/TestKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/UIBasicAnimation.js +1 -1
- package/Root/Frameworks/UIKit/UIHTMLApplication.js +53 -15
- package/Root/Frameworks/UIKit/UIHTMLContentEditableTextInputManager.js +36 -0
- package/Root/Frameworks/UIKit/UIHTMLDisplayServer.js +1 -1
- package/Root/Frameworks/UIKit/UIHTMLTextField.js +1 -1
- package/Root/Frameworks/UIKit/UIHTMLTextFrame.js +19 -91
- package/Root/Frameworks/UIKit/UIHTMLTextFramesetter.js +52 -9
- package/Root/Frameworks/UIKit/UIHTMLTextLine.js +95 -30
- package/Root/Frameworks/UIKit/UIHTMLTextRun.js +22 -9
- package/Root/Frameworks/UIKit/UIHTMLTextTypesetter.js +334 -459
- package/Root/Frameworks/UIKit/UIHTMLWindowServer.js +16 -0
- package/Root/Frameworks/UIKit/UIImageLayer.js +14 -7
- package/Root/Frameworks/UIKit/UILabel.js +2 -0
- package/Root/Frameworks/UIKit/UIScrollView.js +12 -0
- package/Root/Frameworks/UIKit/UISegmentedControl.js +6 -6
- package/Root/Frameworks/UIKit/UIState.js +8 -1
- package/Root/Frameworks/UIKit/UITextAttachmentView.js +1 -1
- package/Root/Frameworks/UIKit/UITextEditor.js +210 -25
- package/Root/Frameworks/UIKit/UITextField.js +58 -31
- package/Root/Frameworks/UIKit/UITextInput.js +3 -1
- package/Root/Frameworks/UIKit/UITextInputManager.js +2 -2
- package/Root/Frameworks/UIKit/UITextLayer.js +39 -26
- package/Root/Frameworks/UIKit/UITokenField.js +4 -4
- package/Root/Frameworks/UIKit/UIView.js +3 -1
- package/Root/Frameworks/UIKit/UIWindow.js +16 -3
- package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// #import "JSObject.js"
|
|
2
2
|
// #import "Promise+JS.js"
|
|
3
3
|
// #import "JSCRC32.js"
|
|
4
|
+
// #import "JSDate.js"
|
|
5
|
+
// #import "JSCalendar.js"
|
|
6
|
+
// #import "Deflate.js"
|
|
4
7
|
"use strict";
|
|
5
8
|
|
|
6
9
|
JSClass("JSZip", JSObject, {
|
|
@@ -14,61 +17,89 @@ JSClass("JSZip", JSObject, {
|
|
|
14
17
|
offset: 0,
|
|
15
18
|
|
|
16
19
|
addFile: function(file, completion, target){
|
|
20
|
+
return this.addFileInDirectory(file, "", {}, completion, target);
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
addFileInDirectory: function(file, directory, attributes, completion, target){
|
|
17
24
|
if (!completion){
|
|
18
25
|
completion = Promise.completion(Promise.resolveNull);
|
|
19
26
|
}
|
|
27
|
+
if (directory.startsWith("/")){
|
|
28
|
+
directory = directory.substr(1);
|
|
29
|
+
}
|
|
30
|
+
if (directory.length > 1 && !directory.endsWith("/")){
|
|
31
|
+
directory = directory + "/";
|
|
32
|
+
}
|
|
20
33
|
file.readData(function(data){
|
|
21
34
|
if (data === null){
|
|
22
35
|
completion.call(target, new Error("Failed to read file data"));
|
|
23
36
|
return;
|
|
24
37
|
}
|
|
25
|
-
|
|
38
|
+
var error = null;
|
|
39
|
+
try{
|
|
40
|
+
this.addDataForFilename(data, directory + file.name, attributes);
|
|
41
|
+
}catch (e){
|
|
42
|
+
error = e;
|
|
43
|
+
}
|
|
44
|
+
completion.call(target, error);
|
|
26
45
|
}, this);
|
|
27
46
|
return completion.promise;
|
|
28
47
|
},
|
|
29
48
|
|
|
30
|
-
addDataForFilename: function(data, name,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
var
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
dataView.setUint16(26, encodedName.length, true);
|
|
50
|
-
dataView.setUint16(28, 0, true);
|
|
51
|
-
encodedName.copyTo(header, 30);
|
|
52
|
-
this.directory.push({
|
|
53
|
-
name: name,
|
|
54
|
-
offset: this.offset,
|
|
55
|
-
header: header
|
|
56
|
-
});
|
|
57
|
-
this.addChunk(header);
|
|
58
|
-
this.addChunk(data);
|
|
59
|
-
}catch (e){
|
|
60
|
-
error = e;
|
|
49
|
+
addDataForFilename: function(data, name, attributes, deflate){
|
|
50
|
+
var encodedName = name.utf8();
|
|
51
|
+
var header = JSData.initWithLength(30 + encodedName.length);
|
|
52
|
+
var dataView = header.dataView();
|
|
53
|
+
var crc = JSCRC32(data);
|
|
54
|
+
var dateComponents = JSCalendar.gregorian.componentsFromDate(JSCalendar.Unit.day | JSCalendar.Unit.month | JSCalendar.Unit.year | JSCalendar.Unit.hour | JSCalendar.Unit.minute | JSCalendar.Unit.second, attributes.updated !== undefined ? JSDate.initWithTimeIntervalSince1970(attributes.updated) : JSDate.now, JSTimeZone.local || JSTimeZone.utc);
|
|
55
|
+
var dosDate = ((dateComponents.year - 1980) << 9) | ((dateComponents.month) << 5) | (dateComponents.day);
|
|
56
|
+
var dosTime = ((dateComponents.hour) << 11) | ((dateComponents.minute) << 5) | (Math.floor(dateComponents.second / 2));
|
|
57
|
+
var storedData = data;
|
|
58
|
+
var method = 0;
|
|
59
|
+
if (deflate){
|
|
60
|
+
var stream = DeflateStream();
|
|
61
|
+
stream.input = data;
|
|
62
|
+
stream.output = JSData.initWithLength(data.length);
|
|
63
|
+
stream.deflate(true);
|
|
64
|
+
if (stream.state === DeflateStream.State.done){
|
|
65
|
+
storedData = stream.output.subdataInRange(JSRange(0, stream.outputOffset));
|
|
66
|
+
method = 8;
|
|
67
|
+
}
|
|
61
68
|
}
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
// Local File Header (APPNOTE.txt 4.3.7)
|
|
70
|
+
// Everything is little-endian
|
|
71
|
+
dataView.setUint32(0, 0x04034b50, true); // signtature
|
|
72
|
+
dataView.setUint16(4, 0x0014, true); // version needed to extract (2.0)
|
|
73
|
+
dataView.setUint16(6, 0, true); // general purpose flags
|
|
74
|
+
dataView.setUint16(8, method, true); // compression method (0=none, 8=deflate)
|
|
75
|
+
dataView.setUint16(10, dosTime, true); // last modified time (MS-DOS)
|
|
76
|
+
dataView.setUint16(12, dosDate, true); // last modified date (MS-DOS)
|
|
77
|
+
dataView.setUint32(14, crc, true); // crc-32 (magic number 0xdebb20e3, preconditioned to 0xffffffff, post-conditioned by one's compliment)
|
|
78
|
+
dataView.setUint32(18, storedData.length, true); // compressed size
|
|
79
|
+
dataView.setUint32(22, data.length, true); // uncompressed size
|
|
80
|
+
dataView.setUint16(26, encodedName.length, true); // name length
|
|
81
|
+
dataView.setUint16(28, 0, true); // extra field length
|
|
82
|
+
encodedName.copyTo(header, 30); // name (NOT null-terminated)
|
|
83
|
+
this.directory.push({
|
|
84
|
+
name: name,
|
|
85
|
+
offset: this.offset,
|
|
86
|
+
header: header
|
|
87
|
+
});
|
|
88
|
+
this.chunks.push(header);
|
|
89
|
+
this.chunks.push(storedData);
|
|
90
|
+
this.offset += header.length + storedData.length;
|
|
91
|
+
this._data = null;
|
|
64
92
|
},
|
|
65
93
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
94
|
+
directory: null,
|
|
95
|
+
|
|
96
|
+
chunks: null,
|
|
97
|
+
|
|
98
|
+
data: JSReadOnlyProperty("_data", null),
|
|
99
|
+
|
|
100
|
+
getData: function(){
|
|
101
|
+
if (this._data === null){
|
|
102
|
+
var chunks = JSCopy(this.chunks);
|
|
72
103
|
var i, l;
|
|
73
104
|
var centralDirectoryOffset = this.offset;
|
|
74
105
|
var centralDirectorySize = 0;
|
|
@@ -77,49 +108,39 @@ JSClass("JSZip", JSObject, {
|
|
|
77
108
|
var dataView;
|
|
78
109
|
var file;
|
|
79
110
|
for (i = 0, l = this.directory.length; i < l; ++i){
|
|
111
|
+
// Central Directory File Header (APPNOTE.txt 4.3.12)
|
|
112
|
+
// Everything is little-endian
|
|
80
113
|
file = this.directory[i];
|
|
81
114
|
header = JSData.initWithLength(46 + (file.header.length - 30));
|
|
82
115
|
dataView = header.dataView();
|
|
83
|
-
dataView.setUint32(0, 0x02014b50, true);
|
|
84
|
-
dataView.setUint16(4,
|
|
85
|
-
file.header.subdataInRange(JSRange(4, 26)).copyTo(header, 6);
|
|
86
|
-
dataView.setUint16(32, 0, true);
|
|
87
|
-
dataView.setUint16(34, 0, true);
|
|
88
|
-
dataView.setUint16(36, 0, true);
|
|
89
|
-
dataView.setUint32(38, 0, true);
|
|
90
|
-
dataView.setUint32(42, file.offset, true);
|
|
91
|
-
file.header.subdataInRange(JSRange(30, file.header.length - 30)).copyTo(header, 46);
|
|
116
|
+
dataView.setUint32(0, 0x02014b50, true); // signature
|
|
117
|
+
dataView.setUint16(4, 0x0314, true); // version made by (UNIX=3, 2.0)
|
|
118
|
+
file.header.subdataInRange(JSRange(4, 26)).copyTo(header, 6); // copy from local header
|
|
119
|
+
dataView.setUint16(32, 0, true); // commenet length
|
|
120
|
+
dataView.setUint16(34, 0, true); // disk number start
|
|
121
|
+
dataView.setUint16(36, 0, true); // internal file attributes
|
|
122
|
+
dataView.setUint32(38, 0, true); // external file attributes
|
|
123
|
+
dataView.setUint32(42, file.offset, true); // offset of local header relative to first disk
|
|
124
|
+
file.header.subdataInRange(JSRange(30, file.header.length - 30)).copyTo(header, 46); // name (ALWAYS forward slashes for directories)
|
|
92
125
|
centralDirectorySize += header.length;
|
|
93
|
-
|
|
126
|
+
chunks.push(header);
|
|
94
127
|
}
|
|
128
|
+
// End of Central Directory Record (APPNOTE.txt 4.3.16)
|
|
129
|
+
// everything is little-endian
|
|
95
130
|
var end = JSData.initWithLength(22);
|
|
96
131
|
dataView = end.dataView();
|
|
97
|
-
dataView.setUint32(0, 0x06054b50, true);
|
|
98
|
-
dataView.setUint16(4, 0, true);
|
|
99
|
-
dataView.setUint16(6, 0, true);
|
|
100
|
-
dataView.setUint16(8, this.directory.length, true);
|
|
101
|
-
dataView.setUint16(10, this.directory.length, true);
|
|
102
|
-
dataView.setUint32(12, centralDirectorySize, true);
|
|
103
|
-
dataView.setUint32(16, centralDirectoryOffset, true);
|
|
104
|
-
dataView.setUint16(20, 0, true);
|
|
105
|
-
|
|
106
|
-
this._data = JSData.initWithChunks(
|
|
107
|
-
}catch (e){
|
|
108
|
-
error = e;
|
|
132
|
+
dataView.setUint32(0, 0x06054b50, true); // signature
|
|
133
|
+
dataView.setUint16(4, 0, true); // number of this disk
|
|
134
|
+
dataView.setUint16(6, 0, true); // number of the disk with the start of central directory
|
|
135
|
+
dataView.setUint16(8, this.directory.length, true); // number of central directory items on this disk
|
|
136
|
+
dataView.setUint16(10, this.directory.length, true); // number of central directory items total
|
|
137
|
+
dataView.setUint32(12, centralDirectorySize, true); // size of central directory
|
|
138
|
+
dataView.setUint32(16, centralDirectoryOffset, true); // offset to central directory with respect to starting disk
|
|
139
|
+
dataView.setUint16(20, 0, true); // zip file comemnt length
|
|
140
|
+
chunks.push(end);
|
|
141
|
+
this._data = JSData.initWithChunks(chunks);
|
|
109
142
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
},
|
|
113
|
-
|
|
114
|
-
addChunk: function(chunk){
|
|
115
|
-
this.chunks.push(chunk);
|
|
116
|
-
this.offset += chunk.length;
|
|
117
|
-
},
|
|
118
|
-
|
|
119
|
-
directory: null,
|
|
120
|
-
|
|
121
|
-
chunks: null,
|
|
122
|
-
|
|
123
|
-
data: JSReadOnlyProperty("_data", null),
|
|
143
|
+
return this._data;
|
|
144
|
+
}
|
|
124
145
|
|
|
125
146
|
});
|
|
@@ -244,6 +244,25 @@ Object.defineProperties(String.prototype, {
|
|
|
244
244
|
}
|
|
245
245
|
},
|
|
246
246
|
|
|
247
|
+
rangeForParagraphAtIndex: {
|
|
248
|
+
enumerable: false,
|
|
249
|
+
value: function String_rangeForParagraphAtIndex(index){
|
|
250
|
+
var iterator1 = this.userPerceivedCharacterIterator(index);
|
|
251
|
+
var startIndex = iterator1.range.location;
|
|
252
|
+
var iterator2 = UserPerceivedCharacterIterator(iterator1);
|
|
253
|
+
iterator1.decrement();
|
|
254
|
+
while (!iterator1.isParagraphBreak){
|
|
255
|
+
startIndex = iterator1.range.location;
|
|
256
|
+
iterator1.decrement();
|
|
257
|
+
}
|
|
258
|
+
while (!iterator2.isParagraphBreak){
|
|
259
|
+
iterator2.increment();
|
|
260
|
+
}
|
|
261
|
+
var endIndex = iterator2.range.end;
|
|
262
|
+
return JSRange(startIndex, endIndex - startIndex);
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
|
|
247
266
|
// -------------------------------------------------------------------------
|
|
248
267
|
// MARK: - Changing a String
|
|
249
268
|
|
|
@@ -1159,6 +1178,22 @@ Object.defineProperties(UserPerceivedCharacterIterator.prototype, {
|
|
|
1159
1178
|
// can start with CR, we know the second character must be LF.
|
|
1160
1179
|
return this._unicodeIterator.character.isLineBreak;
|
|
1161
1180
|
}
|
|
1181
|
+
},
|
|
1182
|
+
|
|
1183
|
+
isParagraphBreak: {
|
|
1184
|
+
enumerable: true,
|
|
1185
|
+
configurable: false,
|
|
1186
|
+
get: function UserPerceivedCharacterIterator_isMandatoryLineBreak(){
|
|
1187
|
+
if (this._unicodeIterator.character === null){
|
|
1188
|
+
return true;
|
|
1189
|
+
}
|
|
1190
|
+
// Note that even though we're only checking the first character,
|
|
1191
|
+
// it will match the multi-char CRLF sequence, which is considered
|
|
1192
|
+
// to be a single user perceived character. In this case, only
|
|
1193
|
+
// the CR is checked, but since no other user perceived character
|
|
1194
|
+
// can start with CR, we know the second character must be LF.
|
|
1195
|
+
return this._unicodeIterator.character.isParagraphBreak;
|
|
1196
|
+
}
|
|
1162
1197
|
}
|
|
1163
1198
|
|
|
1164
1199
|
});
|
|
@@ -778,6 +778,14 @@ UnicodeChar.prototype = Object.create(Object.prototype, {
|
|
|
778
778
|
Object.defineProperty(this, 'isLineBreak', {value: this.code === UnicodeChar.LineBreaks.newLine || this.code === UnicodeChar.LineBreaks.formFeed || this.code === UnicodeChar.LineBreaks.carriageReturn || this.code === UnicodeChar.LineBreaks.nextLine || this.code === UnicodeChar.LineBreaks.lineSeparator || this.code === UnicodeChar.LineBreaks.paragraphSeparator});
|
|
779
779
|
return this.isLineBreak;
|
|
780
780
|
}
|
|
781
|
+
},
|
|
782
|
+
|
|
783
|
+
isParagraphBreak: {
|
|
784
|
+
configurable: true,
|
|
785
|
+
get: function UnicodeChar_lazy_isParagraphBreak(){
|
|
786
|
+
Object.defineProperty(this, 'isParagraphBreak', {value: this.code === UnicodeChar.LineBreaks.newLine || this.code === UnicodeChar.LineBreaks.formFeed || this.code === UnicodeChar.LineBreaks.carriageReturn || this.code === UnicodeChar.LineBreaks.nextLine || this.code === UnicodeChar.LineBreaks.paragraphSeparator});
|
|
787
|
+
return this.isParagraphBreak;
|
|
788
|
+
}
|
|
781
789
|
}
|
|
782
790
|
|
|
783
791
|
});
|
|
@@ -88,7 +88,7 @@ JSClass('UIBasicAnimation', UIPropertyAnimation, {
|
|
|
88
88
|
var progress = this.timingFunction(this._state.currentPercentage);
|
|
89
89
|
this.isComplete = this._state.isComplete();
|
|
90
90
|
this._updateContext[this._updateProperty] = this.interpolation(this._fromValue, this._toValue, progress);
|
|
91
|
-
if (this._updateContext === this._layer.presentation && this._updateProperty === "bounds"){
|
|
91
|
+
if (this._updateContext === this._layer.presentation && (this._updateProperty === "bounds" || this._updateProperty === "imageFrame")){
|
|
92
92
|
this._layer.setNeedsDisplay();
|
|
93
93
|
}
|
|
94
94
|
},
|
|
@@ -29,6 +29,7 @@ JSClass("UIHTMLApplication", UIApplication, {
|
|
|
29
29
|
initWithBundle: function(bundle, windowServer){
|
|
30
30
|
UIHTMLApplication.$super.initWithBundle.call(this, bundle, windowServer);
|
|
31
31
|
this.domWindow = this.windowServer.domWindow;
|
|
32
|
+
this.rememberStateInPath = this.bundle.info.UIHTMLUseURLPathForState === true;
|
|
32
33
|
},
|
|
33
34
|
|
|
34
35
|
setup: function(completion, target){
|
|
@@ -69,7 +70,7 @@ JSClass("UIHTMLApplication", UIApplication, {
|
|
|
69
70
|
if (options === undefined){
|
|
70
71
|
options = {};
|
|
71
72
|
}
|
|
72
|
-
if (options.replacingApplication){
|
|
73
|
+
if (options.replacingApplication || url.scheme === "mailto" || url.scheme === "tel"){
|
|
73
74
|
var application = this;
|
|
74
75
|
var open = function(){
|
|
75
76
|
application.domWindow.location.href = url.encodedString;
|
|
@@ -93,17 +94,15 @@ JSClass("UIHTMLApplication", UIApplication, {
|
|
|
93
94
|
this.stop(reload);
|
|
94
95
|
},
|
|
95
96
|
|
|
96
|
-
baseURL: JSReadOnlyProperty('_baseURL'),
|
|
97
|
+
baseURL: JSReadOnlyProperty('_baseURL', null),
|
|
98
|
+
rememberStateInPath: false,
|
|
97
99
|
|
|
98
100
|
setState: function(state){
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (!this._isHandlingHashChange){
|
|
105
|
-
var href = url.encodedString;
|
|
106
|
-
if (href != this.domWindow.location.href){
|
|
101
|
+
if (!state.isEqual(this.state)){
|
|
102
|
+
UIHTMLApplication.$super.setState.call(this, state);
|
|
103
|
+
if (!this._isHandlingBrowserStateChange){
|
|
104
|
+
var url = this.urlForState(state);
|
|
105
|
+
var href = url.encodedString;
|
|
107
106
|
this.domWindow.history.pushState(null, null, url.encodedString);
|
|
108
107
|
}
|
|
109
108
|
}
|
|
@@ -111,11 +110,20 @@ JSClass("UIHTMLApplication", UIApplication, {
|
|
|
111
110
|
|
|
112
111
|
setStateReplacingHTMLState: function(state){
|
|
113
112
|
UIHTMLApplication.$super.setState.call(this, state);
|
|
113
|
+
var url = this.urlForState(state);
|
|
114
|
+
this.domWindow.history.replaceState(null, null, url.encodedString);
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
urlForState: function(state){
|
|
114
118
|
var url = JSURL.initWithURL(this.baseURL);
|
|
115
|
-
if (state.
|
|
116
|
-
|
|
119
|
+
if (state.pathComponents.length > 1){
|
|
120
|
+
if (this.rememberStateInPath){
|
|
121
|
+
url.appendPathComponents(state.pathComponents.slice(1));
|
|
122
|
+
}else{
|
|
123
|
+
url.fragment = state.path;
|
|
124
|
+
}
|
|
117
125
|
}
|
|
118
|
-
|
|
126
|
+
return url;
|
|
119
127
|
},
|
|
120
128
|
|
|
121
129
|
addEventListeners: function(){
|
|
@@ -123,6 +131,7 @@ JSClass("UIHTMLApplication", UIApplication, {
|
|
|
123
131
|
this.domWindow.addEventListener("unhandledrejection", this);
|
|
124
132
|
this.domWindow.addEventListener("beforeunload", this);
|
|
125
133
|
this.domWindow.addEventListener("hashchange", this);
|
|
134
|
+
this.domWindow.addEventListener("popstate", this);
|
|
126
135
|
},
|
|
127
136
|
|
|
128
137
|
handleEvent: function(e){
|
|
@@ -160,7 +169,10 @@ JSClass("UIHTMLApplication", UIApplication, {
|
|
|
160
169
|
},
|
|
161
170
|
|
|
162
171
|
_event_hashchange: function(e){
|
|
163
|
-
this.
|
|
172
|
+
if (this.rememberStateInPath){
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
this._isHandlingBrowserStateChange = true;
|
|
164
176
|
try{
|
|
165
177
|
var requestedURL = JSURL.initWithString(this.domWindow.location.href);
|
|
166
178
|
var requestedFragment = requestedURL.fragment;
|
|
@@ -185,7 +197,33 @@ JSClass("UIHTMLApplication", UIApplication, {
|
|
|
185
197
|
}
|
|
186
198
|
this.setStateReplacingHTMLState(state);
|
|
187
199
|
}finally{
|
|
188
|
-
this.
|
|
200
|
+
this._isHandlingBrowserStateChange = false;
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
_event_popstate: function(e){
|
|
205
|
+
if (!this.rememberStateInPath){
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
this._isHandlingBrowserStateChange = true;
|
|
209
|
+
try{
|
|
210
|
+
var requestedURL = JSURL.initWithString(this.domWindow.location.href);
|
|
211
|
+
var relativeURL = JSURL.initWithString(requestedURL.encodedStringRelativeTo(this._baseURL));
|
|
212
|
+
var requestedState = UIState.initWithPath(relativeURL.path);
|
|
213
|
+
var state = null;
|
|
214
|
+
if (this.delegate && this.delegate.applicationDidRequestState){
|
|
215
|
+
state = this.delegate.applicationDidRequestState(this, requestedState);
|
|
216
|
+
}
|
|
217
|
+
if (state === null || state === undefined){
|
|
218
|
+
state = this.state;
|
|
219
|
+
}
|
|
220
|
+
if (state.isEqual(requestedState)){
|
|
221
|
+
UIHTMLApplication.$super.setState.call(this, state);
|
|
222
|
+
}else{
|
|
223
|
+
this.setStateReplacingHTMLState(state);
|
|
224
|
+
}
|
|
225
|
+
}finally{
|
|
226
|
+
this._isHandlingBrowserStateChange = false;
|
|
189
227
|
}
|
|
190
228
|
},
|
|
191
229
|
|
|
@@ -155,6 +155,9 @@ JSClass('UIHTMLContentEditableTextInputManager', UITextInputManager, {
|
|
|
155
155
|
var selection = this.textInputClient.textInputSelections()[0];
|
|
156
156
|
var anchor = textFrame.domSelectionPointForCharacterAtIndex(selection.startLocation);
|
|
157
157
|
var focus = textFrame.domSelectionPointForCharacterAtIndex(selection.insertionLocation);
|
|
158
|
+
if (anchor.offset < 0 || focus.offset < 0){
|
|
159
|
+
throw new Error("negative dom offset");
|
|
160
|
+
}
|
|
158
161
|
domSelection.setBaseAndExtent(anchor.node, anchor.offset, focus.node, focus.offset);
|
|
159
162
|
// logger.debug("setting dom selection: %d->%d", anchor.offset, focus.offset);
|
|
160
163
|
if (domSelection.anchorNode){
|
|
@@ -274,9 +277,41 @@ JSClass('UIHTMLContentEditableTextInputManager', UITextInputManager, {
|
|
|
274
277
|
},
|
|
275
278
|
|
|
276
279
|
focus: function(e){
|
|
280
|
+
if (UIDevice.shared && UIDevice.shared.primaryPointerType === UIUserInterface.PointerType.touch){
|
|
281
|
+
if (this.textInputClient instanceof UIView){
|
|
282
|
+
this._cancelNullFirstResponder(this.textInputClient);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
277
285
|
},
|
|
278
286
|
|
|
279
287
|
blur: function(e){
|
|
288
|
+
if (UIDevice.shared && UIDevice.shared.primaryPointerType === UIUserInterface.PointerType.touch){
|
|
289
|
+
if (this.textInputClient instanceof UIView){
|
|
290
|
+
if (this.textInputClient.window){
|
|
291
|
+
if (this.textInputClient.window.firstResponder === this.textInputClient){
|
|
292
|
+
this._scheduleNullFirstResponder(this.textInputClient);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
|
|
299
|
+
_nullFirstResponderTimer: null,
|
|
300
|
+
|
|
301
|
+
_scheduleNullFirstResponder: function(view){
|
|
302
|
+
this._nullFirstResponderTimer = JSTimer.scheduledTimerWithInterval(0.2, function(){
|
|
303
|
+
this._nullFirstResponderTimer = null;
|
|
304
|
+
if (view.window && view.window.firstResponder === view){
|
|
305
|
+
view.window.firstResponder = null;
|
|
306
|
+
}
|
|
307
|
+
}, this);
|
|
308
|
+
},
|
|
309
|
+
|
|
310
|
+
_cancelNullFirstResponder: function(responder){
|
|
311
|
+
if (this._nullFirstResponderTimer){
|
|
312
|
+
this._nullFirstResponderTimer.invalidate();
|
|
313
|
+
this._nullFirstResponderTimer = null;
|
|
314
|
+
}
|
|
280
315
|
},
|
|
281
316
|
|
|
282
317
|
select: function(e){
|
|
@@ -784,6 +819,7 @@ JSTextLayoutManager.definePropertiesFromExtensions({
|
|
|
784
819
|
container = this._textContainers[i];
|
|
785
820
|
offset += container._textFrame.recalculateRange(offset);
|
|
786
821
|
container._textFrame.recalculateSize();
|
|
822
|
+
container.framesetter._updateSizesAndPositionsOfLinesInFrame(container._textFrame);
|
|
787
823
|
}
|
|
788
824
|
}
|
|
789
825
|
|
|
@@ -477,7 +477,7 @@ JSClass("UIHTMLDisplayServer", UIDisplayServer, {
|
|
|
477
477
|
this.layerRemoved(layer);
|
|
478
478
|
}else{
|
|
479
479
|
var context = this.contextsByObjectID[attachment.objectID];
|
|
480
|
-
if (context
|
|
480
|
+
if (context){
|
|
481
481
|
context.destroy();
|
|
482
482
|
delete this.contextsByObjectID[attachment.objectID];
|
|
483
483
|
}
|
|
@@ -738,7 +738,7 @@ JSClass("UIHTMLTextField", UIControl, {
|
|
|
738
738
|
var selection;
|
|
739
739
|
for (var i = selections.length - 1; i >= 0; --i){
|
|
740
740
|
selection = selections[i];
|
|
741
|
-
this.inputElement.setRangeText(replacement, selection.location, selection.end, "end");
|
|
741
|
+
this.inputElement.setRangeText(replacement, selection.range.location, selection.range.end, "end");
|
|
742
742
|
}
|
|
743
743
|
this._text = this.inputElement.value;
|
|
744
744
|
this._sendChangeNotificaions();
|