@breakside/jskit 2022.7.1 → 2022.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/Frameworks/DOM.jsframework/Info.json +2 -2
  2. package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
  3. package/Frameworks/FontKit.jsframework/Info.json +2 -2
  4. package/Frameworks/FontKit.jsframework/JS/FNTFontDescriptor.js +9 -6
  5. package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
  6. package/Frameworks/Foundation.jsframework/Info.json +2 -2
  7. package/Frameworks/Foundation.jsframework/JS/JSEnvironment.js +5 -0
  8. package/Frameworks/Foundation.jsframework/JS/JSHTMLHTTPClient.js +9 -1
  9. package/Frameworks/Foundation.jsframework/JS/JSImage.js +12 -5
  10. package/Frameworks/Foundation.jsframework/JS/JSURLResponse.js +10 -0
  11. package/Frameworks/Foundation.jsframework/JS/JSXMLParser.js +81 -8
  12. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  13. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  14. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  15. package/Info.json +2 -2
  16. package/Node/io.breakside.jskit-bundle.js +2 -2
  17. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  18. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  19. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  20. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  21. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  22. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  23. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  24. package/Root/Frameworks/DOM/Info.yaml +1 -1
  25. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  26. package/Root/Frameworks/Dispatch/JSHTMLDispatchQueue.js +4 -2
  27. package/Root/Frameworks/FontKit/FNTFontDescriptor.js +9 -6
  28. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  29. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  30. package/Root/Frameworks/Foundation/JSEnvironment.js +5 -0
  31. package/Root/Frameworks/Foundation/JSHTMLHTTPClient.js +9 -1
  32. package/Root/Frameworks/Foundation/JSImage.js +12 -5
  33. package/Root/Frameworks/Foundation/JSURLResponse.js +10 -0
  34. package/Root/Frameworks/Foundation/JSXMLParser.js +81 -8
  35. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  36. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  37. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  38. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  39. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  40. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  41. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  42. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  43. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  44. package/Root/Frameworks/ServerKit/SKHTTPServer+Node.js +8 -0
  45. package/Root/Frameworks/ServerKit/SKNodeHTTPRequest.js +3 -0
  46. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  47. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  48. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  49. package/Root/Frameworks/UIKit/UIApplication.js +15 -1
  50. package/Root/Frameworks/UIKit/UICollectionView.js +93 -34
  51. package/Root/Frameworks/UIKit/UICollectionViewCell.js +11 -1
  52. package/Root/Frameworks/UIKit/UICollectionViewLayout.js +1 -1
  53. package/Root/Frameworks/UIKit/UIDraggingSession.js +7 -0
  54. package/Root/Frameworks/UIKit/UIHTMLWindowServer.js +13 -1
  55. package/Root/Frameworks/UIKit/UIScrollView.js +15 -12
  56. package/Root/Frameworks/UIKit/UISegmentedControl.js +15 -0
  57. package/Root/Frameworks/UIKit/UITabView.js +5 -6
  58. package/Root/Frameworks/UIKit/UIWindow.js +21 -0
  59. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  60. package/package.json +1 -1
@@ -163,6 +163,16 @@ JSURLResponse.StatusClass = {
163
163
  serverError: 5
164
164
  };
165
165
 
166
+ JSURLResponse.error = function(statusCode, object){
167
+ var response = JSURLResponse.init();
168
+ response.statusCode = statusCode;
169
+ if (object !== undefined){
170
+ response.data = JSON.stringify(object).utf8();
171
+ response.headerMap.add("Content-Type", response.jsonMime);
172
+ }
173
+ return new JSURLResponseError(response);
174
+ };
175
+
166
176
  JSGlobalObject.JSURLResponseError = function(response){
167
177
  if (this === undefined){
168
178
  return new JSURLResponseError();
@@ -36,6 +36,7 @@ JSClass("JSXMLParser", JSObject, {
36
36
  var c;
37
37
  var lineNumber = 1;
38
38
  var lineOffset;
39
+ var entityMap = JSCopy(defaultEntityMap);
39
40
  var readToken = function(){
40
41
  if (offset >= length){
41
42
  return null;
@@ -131,8 +132,77 @@ JSClass("JSXMLParser", JSObject, {
131
132
  return {kind: 'PI', name: name, value: readUntil('?>')};
132
133
  }
133
134
  if (token == '<!DOCTYPE'){
134
- var parts = readUntil('>').trim().split(' ');
135
- return {kind: 'Doctype', name: parts[0], publicId: parts[1], systemId: parts[2]};
135
+ readWhitespace();
136
+ name = readName();
137
+ readWhitespace();
138
+ var doctype = {kind: 'Doctype', name: name, publicId: null, systemId: null, entities: {}};
139
+ if (offset < length && input[offset] !== '>'){
140
+ if (input[offset] != '['){
141
+ name = readName();
142
+ readWhitespace();
143
+ if (name == "SYSTEM"){
144
+ if (offset < length && (input[offset] == "'" || input[offset] == '"')){
145
+ doctype.systemId = readAttributeValue();
146
+ readWhitespace();
147
+ }else{
148
+ throw new Error("Expecting quote at " + lineNumber + ':' + (offset - lineOffset));
149
+ }
150
+ }else if (name === "PUBLIC"){
151
+ if (offset < length && (input[offset] == "'" || input[offset] == '"')){
152
+ doctype.publicId = readAttributeValue();
153
+ readWhitespace();
154
+ if (offset < length && (input[offset] == "'" || input[offset] == '"')){
155
+ doctype.systemId = readAttributeValue();
156
+ readWhitespace();
157
+ }else{
158
+ throw new Error("Expecting quote at " + lineNumber + ':' + (offset - lineOffset));
159
+ }
160
+ }else{
161
+ throw new Error("Expecting quote at " + lineNumber + ':' + (offset - lineOffset));
162
+ }
163
+ }else{
164
+ throw new Error("Expecting SYSTEM or PUBLIC at " + lineNumber + ':' + (offset - lineOffset));
165
+ }
166
+ }
167
+ if (offset < length && input[offset] == '['){
168
+ ++offset;
169
+ readWhitespace();
170
+ while (offset < length && input[offset] !== ']'){
171
+ token = readToken();
172
+ if (token == '<!'){
173
+ name = readName();
174
+ if (name === "ENTITY"){
175
+ readWhitespace();
176
+ if (offset >= length){
177
+ throw new Error("Expecting ENTITY name at " + lineNumber + ':' + (offset - lineOffset));
178
+ }
179
+ name = readName();
180
+ readWhitespace();
181
+ if (offset >= length){
182
+ throw new Error("Expecting ENTITY value at " + lineNumber + ':' + (offset - lineOffset));
183
+ }
184
+ entityMap[name] = readAttributeValue();
185
+ }
186
+ readUntil('>');
187
+ }else if (token == '<?'){
188
+ readUntil('?>');
189
+ }else if (token == '<!--'){
190
+ readUntil('-->');
191
+ }
192
+ readWhitespace();
193
+ }
194
+ if (offset >= length || input[offset] !== ']'){
195
+ throw new Error("Expecting ] at end of DOCTYPE at " + lineNumber + ':' + (offset - lineOffset));
196
+ }
197
+ ++offset;
198
+ readWhitespace();
199
+ }
200
+ }
201
+ if (offset >= length || input[offset] !== '>'){
202
+ throw new Error("Expecting > at end of DOCTYPE at " + lineNumber + ':' + (offset - lineOffset));
203
+ }
204
+ ++offset;
205
+ return doctype;
136
206
  }
137
207
  if (token == '<![CDATA['){
138
208
  return {kind: 'CDATA', value: readUntil(']]>')};
@@ -154,7 +224,7 @@ JSClass("JSXMLParser", JSObject, {
154
224
  if (offset < length && input[offset] == '='){
155
225
  ++offset;
156
226
  readWhitespace();
157
- attributes.push({name: attrName, value: textByDecodingEntities(readAttributeValue())});
227
+ attributes.push({name: attrName, value: textByDecodingEntities(readAttributeValue(), entityMap)});
158
228
  }else{
159
229
  attributes.push({name: attrName, value: null});
160
230
  }
@@ -189,7 +259,7 @@ JSClass("JSXMLParser", JSObject, {
189
259
  ++offset;
190
260
  return {kind: 'ElementEnd', name: name};
191
261
  }
192
- return {kind: 'Text', value: textByDecodingEntities(token)};
262
+ return {kind: 'Text', value: textByDecodingEntities(token, entityMap)};
193
263
  };
194
264
  var readUntil = function(token){
195
265
  var index = input.indexOf(token, offset);
@@ -267,7 +337,10 @@ JSClass("JSXMLParser", JSObject, {
267
337
  }
268
338
  obj = readObject();
269
339
  var elementNameStack = [];
270
- var namespaces = {':default:': null};
340
+ var namespaces = {
341
+ ':default:': null,
342
+ 'xml': 'http://www.w3.org/XML/1998/namespace'
343
+ };
271
344
  var namespacesStack = [];
272
345
  var hasDocumentElement = false;
273
346
  var hasSentDoctype = false;
@@ -361,7 +434,7 @@ JSClass("JSXMLParser", JSObject, {
361
434
 
362
435
  });
363
436
 
364
- var textByDecodingEntities = function(text){
437
+ var textByDecodingEntities = function(text, map){
365
438
  var index = text.indexOf('&');
366
439
  var length = text.length;
367
440
  var end;
@@ -390,7 +463,7 @@ var textByDecodingEntities = function(text){
390
463
  value = String.fromCharCode(code);
391
464
  }
392
465
  }else{
393
- value = entityMap[entity] || null;
466
+ value = map[entity] || null;
394
467
  if (value === null){
395
468
  throw new Error("Cannot lookup entity: &" + entity + ';');
396
469
  }
@@ -404,7 +477,7 @@ var textByDecodingEntities = function(text){
404
477
  return text;
405
478
  };
406
479
 
407
- var entityMap = {
480
+ var defaultEntityMap = {
408
481
  'lt': '<',
409
482
  'LT': '<',
410
483
  'gt': '>',
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ImageKit
3
- JSBundleVersion: 2022.7.1
3
+ JSBundleVersion: 2022.20.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: 2022.7.1
3
+ JSBundleVersion: 2022.20.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: 2022.7.1
3
+ JSBundleVersion: 2022.20.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: 2022.7.1
3
+ JSBundleVersion: 2022.20.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: 2022.7.1
3
+ JSBundleVersion: 2022.20.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: 2022.7.1
3
+ JSBundleVersion: 2022.20.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: 2022.7.1
3
+ JSBundleVersion: 2022.20.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: 2022.7.1
3
+ JSBundleVersion: 2022.20.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: 2022.7.1
3
+ JSBundleVersion: 2022.20.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -85,6 +85,10 @@ SKHTTPServer.definePropertiesFromExtensions({
85
85
  _handleNodeRequest: function(nodeRequest, nodeResponse){
86
86
  try{
87
87
  var request = SKNodeHTTPRequest.initWithNodeRequest(nodeRequest, nodeResponse);
88
+ if (request === null){
89
+ nodeRequest.socket.destroy();
90
+ return;
91
+ }
88
92
  if (this.tlsCertificate && this.tlsPrivateKey){
89
93
  request.url.scheme = "https";
90
94
  }
@@ -98,6 +102,10 @@ SKHTTPServer.definePropertiesFromExtensions({
98
102
  _handleNodeUpgrade: function(nodeRequest, socket, headPacket){
99
103
  try{
100
104
  var request = SKNodeHTTPRequest.initWithNodeRequest(nodeRequest, null);
105
+ if (request === null){
106
+ nodeRequest.socket.destroy();
107
+ return;
108
+ }
101
109
  this.handleUpgrade(request);
102
110
  }catch(e){
103
111
  nodeRequest.socket.destroy();
@@ -25,6 +25,9 @@ JSClass("SKNodeHTTPRequest", SKHTTPRequest, {
25
25
 
26
26
  initWithNodeRequest: function(nodeRequest, nodeResponse){
27
27
  var url = JSURL.initWithString(nodeRequest.url);
28
+ if (url === null){
29
+ return null;
30
+ }
28
31
  if (url.pathComponents.length === 0){
29
32
  url.path = "/";
30
33
  }
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ServerKitTesting
3
- JSBundleVersion: 2022.7.1
3
+ JSBundleVersion: 2022.20.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: 2022.7.1
3
+ JSBundleVersion: 2022.20.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: 2022.7.1
3
+ JSBundleVersion: 2022.20.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -126,7 +126,7 @@ JSClass('UIApplication', UIResponder, {
126
126
  JSFont.Size[size] = Math.round(JSFont.Size[size] * 1.2);
127
127
  }
128
128
  }
129
- this.windowServer.displayServer.registerFontDescriptors(descriptors, function(error){
129
+ this.registerFontDescriptors(descriptors, function(error){
130
130
  completion.call(target, error);
131
131
  }, this);
132
132
  },
@@ -427,9 +427,23 @@ JSClass('UIApplication', UIResponder, {
427
427
  this.windowServer.createMouseEvent(UIEvent.Type.leftMouseUp, event.timestamp, location);
428
428
  },
429
429
 
430
+ // MARK: - Fonts
431
+
432
+ registerFontDescriptor: function(descriptor, completion, target){
433
+ return this.registerFontDescriptors([descriptor], completion, target);
434
+ },
435
+
436
+ registerFontDescriptors: function(descriptors, completion, target){
437
+ return this.windowServer.displayServer.registerFontDescriptors(descriptors, completion, target);
438
+ },
439
+
440
+ // MARK: - URLs
441
+
430
442
  openURL: function(url, options){
431
443
  },
432
444
 
445
+ // MARK: - Environment
446
+
433
447
  getenv: function(name, defaultValue){
434
448
  return this.environment.get(name, defaultValue);
435
449
  },
@@ -19,6 +19,8 @@
19
19
  // #import "UICollectionViewLayout.js"
20
20
  "use strict";
21
21
 
22
+ (function(){
23
+
22
24
  JSProtocol("UICollectionViewDelegate", JSProtocol, {
23
25
 
24
26
  // Selection
@@ -34,7 +36,13 @@ JSProtocol("UICollectionViewDelegate", JSProtocol, {
34
36
  // Dragging cells
35
37
  collectionViewShouldDragCellAtIndexPath: function(collectionView, indexPath){},
36
38
  pasteboardItemsForCollectionViewAtIndexPath: function(collectionView, indexPath){},
37
- collectionViewWillBeginDraggingSession: function(collectionView, session){}
39
+ collectionViewWillBeginDraggingSession: function(collectionView, session){},
40
+
41
+ // Dragging destination
42
+ collectionViewDraggingSessionDidEnter: function(collectionView, sesssion){},
43
+ collectionViewDraggingSessionDidUpdate: function(collectionView, sesssion, indexPath){},
44
+ collectionViewDraggingSessionDidExit: function(collectionView, sesssion){},
45
+ collectionViewPerformDragOperation: function(collectionView, sesssion, operation, indexPath){}
38
46
 
39
47
  });
40
48
 
@@ -286,12 +294,12 @@ JSClass("UICollectionView", UIScrollView, {
286
294
  },
287
295
 
288
296
  reloadCellsAtIndexPaths: function(indexPaths, animator){
297
+ if (this._needsReload){
298
+ return;
299
+ }
289
300
  if (this._visibleElements.length === 0){
290
301
  return;
291
302
  }
292
- var firstVisibleElement = this._visibleElements[0];
293
- var lastVisibleElement = this._visibleElements[this._visibleElements.length - 1];
294
- var searcher = JSBinarySearcher(this._visibleElements, VisibleElement.indexPathCompare);
295
303
 
296
304
  indexPaths = JSCopy(indexPaths);
297
305
  indexPaths.sort(function(a, b){
@@ -301,28 +309,25 @@ JSClass("UICollectionView", UIScrollView, {
301
309
  var i, l;
302
310
  var indexPath;
303
311
  var comparison;
304
- var elementIndex;
312
+ var elementIndex = 0;
313
+ var elementCount = this._visibleElements.length;
305
314
  var cell;
306
315
  var element;
307
316
 
308
317
  for (i = 0, l = indexPaths.length; i < l; ++i){
309
318
  indexPath = indexPaths[i];
310
- comparison = VisibleElement.indexPathCompare(indexPath, lastVisibleElement);
311
- if (comparison <= 0){
312
- comparison = VisibleElement.indexPathCompare(indexPath, firstVisibleElement);
313
- if (comparison >= 0){
314
- elementIndex = searcher.indexMatchingValue(indexPath);
315
- if (elementIndex !== null){
316
- element = this._visibleElements[elementIndex];
317
- cell = element.view;
318
- this._enqueueReusableCell(cell);
319
- cell = this._createCellWithAttributes(element.attributes);
320
- if (cell !== element.view){
321
- this._elementsContainerView.insertSubviewBelowSibling(cell, element.view);
322
- element.view.removeFromSuperview();
323
- element.view = cell;
324
- }
325
- }
319
+ while (elementIndex < elementCount && !this._visibleElements[elementIndex].indexPath.isEqual(indexPath)){
320
+ ++elementIndex;
321
+ }
322
+ if (elementIndex < elementCount){
323
+ element = this._visibleElements[elementIndex];
324
+ cell = element.view;
325
+ this._enqueueReusableCell(cell);
326
+ cell = this._createCellWithAttributes(element.attributes);
327
+ if (cell !== element.view){
328
+ this._elementsContainerView.insertSubviewBelowSibling(cell, element.view);
329
+ element.view.removeFromSuperview();
330
+ element.view = cell;
326
331
  }
327
332
  }
328
333
  }
@@ -345,6 +350,9 @@ JSClass("UICollectionView", UIScrollView, {
345
350
  },
346
351
 
347
352
  deleteCellsAtIndexPaths: function(indexPaths, animation){
353
+ if (this.selectedIndexPaths.length > 0){
354
+ this._setSelectedIndexPaths([], {notifyDelegate: true});
355
+ }
348
356
  // TODO:
349
357
  this.reloadData();
350
358
  },
@@ -838,11 +846,13 @@ JSClass("UICollectionView", UIScrollView, {
838
846
  this._updateVisibleCellStates();
839
847
  },
840
848
 
849
+
841
850
  mouseDragged: function(event){
842
851
  var location = event.locationInView(this);
843
852
  var cell = this._cellHitTest(location);
844
853
  if (this._shouldDrag){
845
854
  var dragItems = [];
855
+ var indexPaths = [];
846
856
  if (cell !== null){
847
857
  var cellItems = [];
848
858
  if (this.allowsMultipleSelection && this._selectionContainsIndexPath(cell.indexPath)){
@@ -854,6 +864,7 @@ JSClass("UICollectionView", UIScrollView, {
854
864
  if (cellItems !== null){
855
865
  dragItems = dragItems.concat(cellItems);
856
866
  }
867
+ indexPaths.push(indexPath);
857
868
  }
858
869
  }
859
870
  }else{
@@ -862,13 +873,14 @@ JSClass("UICollectionView", UIScrollView, {
862
873
  if (cellItems !== null){
863
874
  dragItems = cellItems;
864
875
  }
876
+ indexPaths.push(cell.indexPath);
865
877
  }
866
878
  }
867
879
  }
868
880
  if (dragItems.length > 0){
869
881
  var session = this.beginDraggingSessionWithItems(dragItems, event);
870
882
  if (this.delegate && this.delegate.collectionViewWillBeginDraggingSession){
871
- this.delegate.collectionViewWillBeginDraggingSession(this, session);
883
+ this.delegate.collectionViewWillBeginDraggingSession(this, session, indexPaths, location);
872
884
  }
873
885
  }
874
886
  }else{
@@ -1019,6 +1031,62 @@ JSClass("UICollectionView", UIScrollView, {
1019
1031
  this._cancelTouchSelection();
1020
1032
  },
1021
1033
 
1034
+ // ----------------------------------------------------------------------
1035
+ // MARK: - Drag Destination
1036
+
1037
+ draggingEntered: function(session){
1038
+ if (this.delegate && this.delegate.collectionViewDraggingSessionDidEnter){
1039
+ this.delegate.collectionViewDraggingSessionDidEnter(this, session);
1040
+ }
1041
+ return UIDragOperation.none;
1042
+ },
1043
+
1044
+ draggingUpdated: function(session){
1045
+ var location = this.convertPointFromScreen(session.screenLocation);
1046
+ var indexPath = null;
1047
+ var cell = this._cellHitTest(location);
1048
+ if (cell !== null){
1049
+ indexPath = cell.indexPath;
1050
+ }
1051
+ var operation = UIDragOperation.none;
1052
+ if (this.delegate && this.delegate.collectionViewDraggingSessionDidUpdate){
1053
+ operation = this.delegate.collectionViewDraggingSessionDidUpdate(this, session, indexPath);
1054
+ }
1055
+ if (operation === UIDragOperation.none){
1056
+ this._updateDropTarget(null);
1057
+ }else{
1058
+ this._updateDropTarget(cell);
1059
+ }
1060
+ return operation;
1061
+ },
1062
+
1063
+ draggingExited: function(session){
1064
+ this._updateDropTarget(null);
1065
+ if (this.delegate && this.delegate.collectionViewDraggingSessionDidExit){
1066
+ this.delegate.collectionViewDraggingSessionDidExit(this, session);
1067
+ }
1068
+ },
1069
+
1070
+ performDragOperation: function(session, operation){
1071
+ var location = this.convertPointFromScreen(session.screenLocation);
1072
+ var cell = this._cellHitTest(location);
1073
+ this._updateDropTarget(null);
1074
+ if (cell && this.delegate && this.delegate.collectionViewPerformDragOperation){
1075
+ this.delegate.collectionViewPerformDragOperation(this, session, operation, cell.indexPath);
1076
+ }
1077
+ },
1078
+
1079
+ _updateDropTarget: function(cell){
1080
+ var i, l;
1081
+ var item;
1082
+ for (i = 0, l = this._visibleElements.length; i < l; ++i){
1083
+ item = this._visibleElements[i];
1084
+ if (item.attributes.elementCategory === UICollectionView.ElementCategory.cell){
1085
+ item.view.dropTarget = item.view === cell;
1086
+ }
1087
+ }
1088
+ },
1089
+
1022
1090
  // --------------------------------------------------------------------
1023
1091
  // MARK: - Finding Cells by Location
1024
1092
 
@@ -1118,6 +1186,7 @@ JSClass("UICollectionView", UIScrollView, {
1118
1186
  // MARK: - Scrolling
1119
1187
 
1120
1188
  scrollToCellAtIndexPath: function(indexPath, position){
1189
+ this.layoutIfNeeded();
1121
1190
  if (position === undefined){
1122
1191
  position = UICollectionView.ScrollPosition.auto;
1123
1192
  }
@@ -1226,15 +1295,7 @@ VisibleElement.prototype = Object.create(Function.prototype, {
1226
1295
  indexPath: { value: null, writable: true },
1227
1296
  rect: { value: null, writable: true, configurable: true },
1228
1297
  kind: { value: null, writable: true },
1229
- view: {
1230
- configurable: true,
1231
- set: function(view){
1232
- Object.defineProperty(this, 'view', {value: view});
1233
- },
1234
- get: function(){
1235
- return null;
1236
- }
1237
- },
1298
+ view: { value: null, writable: true },
1238
1299
  state: { value: null, writable: true },
1239
1300
  animation: { value: null, writable: true },
1240
1301
 
@@ -1249,6 +1310,4 @@ VisibleElement.prototype = Object.create(Function.prototype, {
1249
1310
 
1250
1311
  });
1251
1312
 
1252
- VisibleElement.indexPathCompare = function VisibleElement_indexPathCompare(indexPath, element){
1253
- return indexPath.compare(element.indexPath);
1254
- };
1313
+ })();
@@ -36,6 +36,7 @@ JSClass("UICollectionViewCell", UICollectionReusableView, {
36
36
  active: JSDynamicProperty(null, null, 'isActive'),
37
37
  selected: JSDynamicProperty(null, null, 'isSelected'),
38
38
  contextSelected: JSDynamicProperty(null, null, 'isContextSelected'),
39
+ dropTarget: JSDynamicProperty(null, null, 'isDropTarget'),
39
40
 
40
41
  _updateState: function(newState){
41
42
  if (newState != this._state){
@@ -94,6 +95,14 @@ JSClass("UICollectionViewCell", UICollectionReusableView, {
94
95
  this._toggleState(UICollectionViewCell.State.contextSelected, isContextSelected);
95
96
  },
96
97
 
98
+ isDropTarget: function(){
99
+ return (this._state & UICollectionViewCell.State.dropTarget) === UICollectionViewCell.State.dropTarget;
100
+ },
101
+
102
+ setDropTarget: function(isDropTarget){
103
+ this._toggleState(UICollectionViewCell.State.dropTarget, isDropTarget);
104
+ },
105
+
97
106
  // --------------------------------------------------------------------
98
107
  // MARK: - Accessibility
99
108
 
@@ -117,5 +126,6 @@ UICollectionViewCell.State = {
117
126
  active: 1 << 1,
118
127
  selected: 1 << 2,
119
128
  contextSelected: 1 << 3,
120
- firstUserState: 1 << 4
129
+ dropTarget: 1 << 4,
130
+ firstUserState: 1 << 5
121
131
  };
@@ -35,7 +35,7 @@ JSClass("UICollectionViewLayout", JSObject, {
35
35
  layoutAttributesForCellAtIndexPath: function(indexPath){
36
36
  },
37
37
 
38
- layoutAttributesForSupplimentaryViewAtIndexPath: function(indexPath){
38
+ layoutAttributesForSupplimentaryViewAtIndexPath: function(indexPath, kind){
39
39
  },
40
40
 
41
41
  shouldInvalidateLayoutForBounds: function(bounds){
@@ -83,6 +83,9 @@ JSClass("UIDraggingSession", JSObject, {
83
83
  },
84
84
 
85
85
  cancel: function(){
86
+ if (this.destination){
87
+ this.destination.draggingExited(this);
88
+ }
86
89
  },
87
90
 
88
91
  isValidDestination: function(destination){
@@ -95,6 +98,10 @@ JSClass("UIDraggingSession", JSObject, {
95
98
  this.imageOffset = JSPoint(offset);
96
99
  },
97
100
 
101
+ setImageFromView: function(view, offset){
102
+ this.imageOffset = JSPoint(offset);
103
+ },
104
+
98
105
  centerImageScreenLocation: JSReadOnlyProperty(),
99
106
 
100
107
  getCenterImageScreenLocation: function(){