sproutcore 1.11.0.rc2 → 1.11.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG +10 -0
  3. data/VERSION.yml +1 -1
  4. data/lib/frameworks/sproutcore/CHANGELOG.md +114 -1
  5. data/lib/frameworks/sproutcore/apps/showcase/views/views_item_view.js +1 -7
  6. data/lib/frameworks/sproutcore/apps/showcase/views/views_list_view.js +9 -9
  7. data/lib/frameworks/sproutcore/frameworks/ajax/system/request.js +167 -5
  8. data/lib/frameworks/sproutcore/frameworks/ajax/system/response.js +24 -8
  9. data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/stack_layout.js +737 -0
  10. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/layout.js +0 -6
  11. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +11 -7
  12. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane_statechart.js +7 -11
  13. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/child_view_layout_protocol.js +8 -3
  14. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/observable_protocol.js +9 -6
  15. data/lib/frameworks/sproutcore/frameworks/{desktop/protocols/responder.js → core_foundation/protocols/responder_protocol.js} +83 -17
  16. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/{sparse_array_delegate.js → sparse_array_delegate_protocol.js} +11 -7
  17. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/view_transition_protocol.js +11 -6
  18. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/color.js +2 -2
  19. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/page.js +0 -22
  20. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +61 -56
  21. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/main_pane.js +2 -2
  22. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/pane/append_remove.js +3 -3
  23. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/animation.js +63 -39
  24. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/border_frame_test.js +28 -28
  25. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/createLayer.js +10 -4
  26. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layout.js +102 -1
  27. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutDidChange.js +4 -4
  28. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutStyle.js +103 -103
  29. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/replaceAllChildren_test.js +1 -1
  30. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/view.js +77 -1
  31. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/view_states_test.js +18 -17
  32. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +42 -49
  33. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/animation.js +5 -6
  34. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/enabled.js +16 -5
  35. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout.js +241 -102
  36. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout_style.js +1 -4
  37. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/manipulation.js +0 -11
  38. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/statechart.js +993 -610
  39. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/theming.js +3 -2
  40. data/lib/frameworks/sproutcore/frameworks/datastore/data_sources/data_source.js +6 -11
  41. data/lib/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +94 -27
  42. data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +133 -53
  43. data/lib/frameworks/sproutcore/frameworks/datastore/system/store.js +30 -35
  44. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/writeAttribute.js +3 -2
  45. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/writeDataHash.js +73 -29
  46. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/conflictedStoreKeys_test.js +156 -0
  47. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/dataSourceCallbacks.js +61 -37
  48. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/find.js +2 -2
  49. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/system/datetime.js +68 -39
  50. data/lib/frameworks/sproutcore/frameworks/designer/tests/coders/page.js +1 -2
  51. data/lib/frameworks/sproutcore/frameworks/desktop/panes/panel.js +8 -6
  52. data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +80 -14
  53. data/lib/frameworks/sproutcore/frameworks/desktop/panes/sheet.js +2 -2
  54. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/{drag_data_source.js → drag_data_source_protocol.js} +16 -10
  55. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/{drag_source.js → drag_source_protocol.js} +28 -26
  56. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/{drop_target.js → drop_target_protocol.js} +73 -75
  57. data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +4 -4
  58. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/panel/ui.js +39 -23
  59. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/mouse.js +120 -97
  60. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/rowSizeForContentIndex.js +26 -25
  61. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/ui.js +3 -3
  62. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/segmented/ui.js +5 -0
  63. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/split/{dividers.js → dividers_test.js} +38 -38
  64. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +29 -14
  65. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_scroll.js +2 -1
  66. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll_view.js +13 -18
  67. data/lib/frameworks/sproutcore/frameworks/desktop/views/segmented.js +41 -35
  68. data/lib/frameworks/sproutcore/frameworks/desktop/views/slider.js +14 -14
  69. data/lib/frameworks/sproutcore/frameworks/desktop/views/split.js +41 -26
  70. data/lib/frameworks/sproutcore/frameworks/desktop/views/static_content.js +2 -12
  71. data/lib/frameworks/sproutcore/frameworks/foundation/gestures/tap.js +2 -2
  72. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_resize.js +14 -10
  73. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/gesturable.js +104 -63
  74. data/lib/frameworks/sproutcore/frameworks/foundation/protocols/swap_transition_protocol.js +9 -4
  75. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/auto_mixin_tests.js +1 -2
  76. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/auto_resize_test.js +33 -33
  77. data/lib/frameworks/sproutcore/frameworks/foundation/tests/transitions/view_transitions_test.js +5 -5
  78. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/methods.js +0 -4
  79. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/transition_test.js +0 -4
  80. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/ui.js +0 -2
  81. data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +12 -8
  82. data/lib/frameworks/sproutcore/frameworks/media/resources/silence.mp3 +0 -0
  83. data/lib/frameworks/sproutcore/frameworks/media/tests/audio.js +69 -0
  84. data/lib/frameworks/sproutcore/frameworks/media/views/audio.js +1 -0
  85. data/lib/frameworks/sproutcore/frameworks/runtime/core.js +2 -2
  86. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +11 -4
  87. data/lib/frameworks/sproutcore/frameworks/runtime/protocols/mixin_protocol.js +150 -0
  88. data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +447 -137
  89. data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +9 -15
  90. data/lib/frameworks/sproutcore/frameworks/runtime/system/set.js +19 -17
  91. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/binding.js +188 -16
  92. data/lib/frameworks/sproutcore/frameworks/statechart/system/state.js +1 -1
  93. data/lib/frameworks/sproutcore/frameworks/template_view/panes/template.js +0 -3
  94. data/lib/frameworks/sproutcore/frameworks/template_view/tests/panes/template.js +0 -17
  95. data/lib/frameworks/sproutcore/frameworks/template_view/tests/views/template/collection.js +43 -26
  96. data/lib/frameworks/sproutcore/frameworks/template_view/views/bindable_span.js +9 -2
  97. data/lib/frameworks/sproutcore/themes/ace/resources/collection/normal/list.css +0 -1
  98. data/lib/frameworks/sproutcore/themes/ace/resources/scroll/scroll.css +3 -0
  99. data/sproutcore.gemspec +3 -3
  100. metadata +19 -17
  101. data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/horizontal_stack_layout.js +0 -465
  102. data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/vertical_stack_layout.js +0 -472
  103. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/build.js +0 -87
  104. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/build_children.js +0 -89
@@ -653,12 +653,16 @@ SC.Object.prototype = {
653
653
  value is ignored.
654
654
  */
655
655
  init: function () {
656
+ //@if(debug)
657
+ // Provide some developer support for the deprecation of `awake`.
658
+ if (this.awake !== SC.Object.prototype.awake) SC.warn("Developer Warning: `awake` has been deprecated and will not be called. Override `init` and call sc_super(); instead.");
659
+ //@endif
656
660
  this.initObservable();
657
661
  return this;
658
662
  },
659
663
 
660
664
  /**
661
- Set to YES once this object has been destroyed.
665
+ This is set to YES once this object has been destroyed.
662
666
 
663
667
  @type Boolean
664
668
  */
@@ -828,22 +832,12 @@ SC.Object.prototype = {
828
832
  return this._object_toString;
829
833
  },
830
834
 
831
- /**
832
- Activates any outlet connections in object and syncs any bindings. This
833
- method is called automatically for view classes but may be used for any
834
- object.
835
-
836
-
837
- */
835
+ /** @deprecated v1.11 - use init instead. */
836
+ //@if(debug)
838
837
  awake: function () {
839
- var outlets = this.outlets,
840
- i, len, outlet;
841
- for (i = 0, len = outlets.length; i < len; ++i) {
842
- outlet = outlets[i];
843
- this.get(outlet);
844
- }
845
- this.bindings.invoke('sync');
838
+ SC.warn('Developer Warning: The `awake` method has been deprecated. Use `init` instead. (Be sure to call sc_super().)');
846
839
  },
840
+ //@endif
847
841
 
848
842
  /**
849
843
  Invokes the passed method or method name one time during the runloop. You
@@ -12,13 +12,13 @@ sc_require('mixins/copyable');
12
12
 
13
13
  // IMPORTANT NOTE: This file actually defines two classes:
14
14
  // SC.Set is a fully observable set class documented below.
15
- // SC._CoreSet is just like SC.Set but is not observable. This is required
15
+ // SC.CoreSet is just like SC.Set but is not observable. This is required
16
16
  // because SC.Observable is built on using sets and requires sets without
17
17
  // observability.
18
18
  //
19
19
  // We use pointer swizzling below to swap around the actual definitions so
20
20
  // that the documentation will turn out right. (The docs should only
21
- // define SC.Set - not SC._CoreSet)
21
+ // define SC.Set - not SC.CoreSet)
22
22
 
23
23
  /**
24
24
  @class
@@ -197,7 +197,8 @@ SC.Set = SC.mixin({},
197
197
  clear: function() {
198
198
  if (this.isFrozen) throw SC.FROZEN_ERROR;
199
199
  this.length = 0;
200
- return this ;
200
+
201
+ return this;
201
202
  },
202
203
 
203
204
  /**
@@ -374,6 +375,7 @@ SC.Set = SC.mixin({},
374
375
 
375
376
  if (this.isObservable) this.enumerableContentDidChange();
376
377
  if (this.setObservers) this.didRemoveItem(obj);
378
+
377
379
  return this ;
378
380
  },
379
381
 
@@ -431,8 +433,10 @@ SC.Set = SC.mixin({},
431
433
  @returns {SC.Set} receiver
432
434
  */
433
435
  destroy: function() {
434
- this.isFrozen = NO ; // unfreeze to return to pool
436
+ this.isFrozen = NO; // unfreeze to return to pool
437
+
435
438
  if (!this.isObservable) SC.Set._pool.push(this.clear());
439
+
436
440
  return this;
437
441
  },
438
442
 
@@ -443,15 +447,16 @@ SC.Set = SC.mixin({},
443
447
  /** @private - optimized */
444
448
  forEach: function(iterator, target) {
445
449
  var len = this.length;
446
- if (!target) target = this ;
447
- for(var idx=0;idx<len;idx++) iterator.call(target, this[idx], idx, this);
450
+
451
+ if (!target) target = this;
452
+ for (var idx = 0; idx < len; idx++) iterator.call(target, this[idx], idx, this);
448
453
  return this ;
449
454
  },
450
455
 
451
456
  /** @private */
452
457
  toString: function() {
453
458
  var len = this.length, idx, ary = [];
454
- for(idx=0;idx<len;idx++) ary[idx] = this[idx];
459
+ for (idx = 0; idx < len; idx++) ary[idx] = this[idx];
455
460
  return "SC.Set<%@>".fmt(ary.join(',')) ;
456
461
  },
457
462
 
@@ -487,31 +492,28 @@ SC.Set = SC.mixin({},
487
492
  for (idx = 0; idx < len; idx++) o[idx].didRemoveItem(this, item);
488
493
  },
489
494
 
490
- // the pool used for non-observable sets
491
- _pool: [],
492
-
493
495
  /** @private */
494
496
  isObservable: YES
495
497
 
496
- }) ;
498
+ });
497
499
 
498
500
  SC.Set.constructor = SC.Set;
499
501
 
500
502
  // Make SC.Set look a bit more like other enumerables
501
503
 
502
504
  /** @private */
503
- SC.Set.clone = SC.Set.copy ;
505
+ SC.Set.clone = SC.Set.copy;
504
506
 
505
507
  /** @private */
506
- SC.Set.push = SC.Set.unshift = SC.Set.add ;
508
+ SC.Set.push = SC.Set.unshift = SC.Set.add;
507
509
 
508
510
  /** @private */
509
- SC.Set.shift = SC.Set.pop ;
511
+ SC.Set.shift = SC.Set.pop;
510
512
 
511
513
  // add generic add/remove enumerable support
512
514
 
513
515
  /** @private */
514
- SC.Set.addObject = SC.Set.add ;
516
+ SC.Set.addObject = SC.Set.add;
515
517
 
516
518
  /** @private */
517
519
  SC.Set.removeObject = SC.Set.remove;
@@ -524,7 +526,7 @@ SC.Set._pool = [];
524
526
 
525
527
  /** @class
526
528
 
527
- CoreSet is just like set but not observable. If you want to use the set
529
+ CoreSet is just like Set but not observable. If you want to use the set
528
530
  as a simple data structure with no observing, CoreSet is slightly faster
529
531
  and more memory efficient.
530
532
 
@@ -534,7 +536,7 @@ SC.Set._pool = [];
534
536
  SC.CoreSet = SC.beget(SC.Set);
535
537
 
536
538
  /** @private */
537
- SC.CoreSet.isObservable = NO ;
539
+ SC.CoreSet.isObservable = NO;
538
540
 
539
541
  /** @private */
540
542
  SC.CoreSet.constructor = SC.CoreSet;
@@ -7,7 +7,7 @@
7
7
  // ========================================================================
8
8
  // SC.Binding Tests
9
9
  // ========================================================================
10
- /*globals module, test, ok, isObj, equals, expects */
10
+ /*globals module, test, ok, equals */
11
11
 
12
12
  var FromObject, fromObject, midObject, toObject, binding, Bon1, bon2, first, second, third, binding1, binding2;
13
13
 
@@ -366,6 +366,7 @@ test("two bindings to the same value should sync in the order they are initializ
366
366
 
367
367
  });
368
368
 
369
+ var BindableObject;
369
370
  module("Binding transforms", {
370
371
  setup: function () {
371
372
  BindableObject = SC.Object.extend({
@@ -373,7 +374,8 @@ module("Binding transforms", {
373
374
  numericValue: 42,
374
375
  stringValue: 'forty-two',
375
376
  arrayValue: [4, 2],
376
- undefinedValue: undefined
377
+ undefinedValue: undefined,
378
+ nullValue: null
377
379
  });
378
380
  // temporarily set up two source objects in the SC namespace so we can
379
381
  // use property paths to access them
@@ -407,9 +409,112 @@ test('Binding sync when only transformed value has changed', function () {
407
409
  equals(toObject.get('transformedValue'), 'VALUE IS UNDEFINED', 'value is undefined, so bound value should be');
408
410
  });
409
411
 
410
- test("ALL THE OTHER BINDING TRANSFORMS.");
412
+ test("the integer transform", function() {
413
+ var toObject;
414
+
415
+ SC.run(function () {
416
+ toObject = SC.Object.create({
417
+ aNumber: null,
418
+ aNumberBinding: SC.Binding.oneWay('SC.testControllerA.nullValue').integer(10)
419
+ });
420
+ });
421
+
422
+ equals(toObject.get('aNumber'), 0, "Value is null, so bound value should should be");
423
+
424
+ SC.run(function () {
425
+ SC.testControllerA.set('nullValue', '123abc');
426
+ });
427
+
428
+ equals(toObject.get('aNumber'), window.parseInt('123abc', 10), "Value is String, so bound value should be");
429
+
430
+ SC.run(function () {
431
+ SC.testControllerA.set('nullValue', 'abc123');
432
+ });
433
+
434
+ equals(toObject.get('aNumber'), 0, "Value is non-parseable String, so bound value should be");
435
+
436
+ SC.run(function () {
437
+ SC.testControllerA.set('nullValue', NaN);
438
+ });
439
+
440
+ equals(toObject.get('aNumber'), 0, "Value is NaN, so bound value should be");
441
+
442
+ SC.run(function () {
443
+ SC.testControllerA.set('nullValue', Infinity);
444
+ });
445
+
446
+ equals(toObject.get('aNumber'), Infinity, "Value is Infinity, so bound value should be");
447
+
448
+ SC.run(function () {
449
+ SC.testControllerA.set('nullValue', true);
450
+ });
411
451
 
412
- test("equalTo", function() {
452
+ equals(toObject.get('aNumber'), 1, "Value is Boolean true, so bound value should be");
453
+
454
+ SC.run(function () {
455
+ SC.testControllerA.set('nullValue', false);
456
+ });
457
+
458
+ equals(toObject.get('aNumber'), 0, "Value is Boolean false, so bound value should be");
459
+
460
+ SC.run(function () {
461
+ SC.testControllerA.set('nullValue', {});
462
+ });
463
+
464
+ equals(toObject.get('aNumber'), 0, "Value is Object, so bound value should be");
465
+
466
+ SC.run(function () {
467
+ SC.testControllerA.set('nullValue', SC.Object.create({}));
468
+ });
469
+
470
+ equals(toObject.get('aNumber'), 0, "Value is SC.Object instance, so bound value should be");
471
+ });
472
+
473
+
474
+ test("the string transform", function() {
475
+ var toObject;
476
+
477
+ SC.run(function () {
478
+ toObject = SC.Object.create({
479
+ aString: null,
480
+ aStringBinding: SC.Binding.oneWay('SC.testControllerA.nullValue').string()
481
+ });
482
+ });
483
+
484
+ equals(toObject.get('aString'), '', "Value is null, so bound value should should be");
485
+
486
+ SC.run(function () {
487
+ SC.testControllerA.set('nullValue', 1);
488
+ });
489
+
490
+ equals(toObject.get('aString'), '1', "Value is Number, so bound value should be");
491
+
492
+ SC.run(function () {
493
+ SC.testControllerA.set('nullValue', true);
494
+ });
495
+
496
+ equals(toObject.get('aString'), 'true', "Value is Boolean true, so bound value should be");
497
+
498
+ SC.run(function () {
499
+ SC.testControllerA.set('nullValue', false);
500
+ });
501
+
502
+ equals(toObject.get('aString'), 'false', "Value is Boolean false, so bound value should be");
503
+
504
+ SC.run(function () {
505
+ SC.testControllerA.set('nullValue', {});
506
+ });
507
+
508
+ equals(toObject.get('aString'), {}.toString(), "Value is Object, so bound value should be");
509
+
510
+ SC.run(function () {
511
+ SC.testControllerA.set('nullValue', SC.Object.create({ toString: function () { return 'An SC.Object'; }}));
512
+ });
513
+
514
+ equals(toObject.get('aString'), 'An SC.Object', "Value is SC.Object instance, so bound value should be");
515
+ });
516
+
517
+ test("the equalTo transform", function() {
413
518
  SC.RunLoop.begin();
414
519
  var toObject = SC.Object.create({
415
520
  isFortyTwo: null,
@@ -433,14 +538,16 @@ module("Binding transform: `and`", {
433
538
  // use property paths to access them
434
539
  SC.testControllerA = SC.Object.create({ value: NO });
435
540
  SC.testControllerB = SC.Object.create({ value: NO });
541
+ SC.testControllerC = SC.Object.create({ value: NO });
436
542
 
437
543
  toObject = SC.Object.create({
438
544
  value: null,
439
- valueBinding: SC.Binding.and('SC.testControllerA.value', 'SC.testControllerB.value'),
545
+ valueBinding: SC.Binding.and('SC.testControllerA.value', 'SC.testControllerB.value', 'SC.testControllerC.value'),
440
546
  localValue1: NO,
441
547
  localValue2: NO,
548
+ localValue3: NO,
442
549
  boundLocalValue: NO,
443
- boundLocalValueBinding: SC.Binding.and('.localValue1', '.localValue2')
550
+ boundLocalValueBinding: SC.Binding.and('.localValue1', '.localValue2', '.localValue3')
444
551
  });
445
552
  },
446
553
 
@@ -449,13 +556,16 @@ module("Binding transform: `and`", {
449
556
  delete SC.testControllerA;
450
557
  SC.testControllerB.destroy();
451
558
  delete SC.testControllerB;
559
+ SC.testControllerC.destroy();
560
+ delete SC.testControllerC;
452
561
  }
453
562
  });
454
563
 
455
- test("bound value should be YES if both sources are YES", function () {
564
+ test("bound value should be YES if all sources are YES", function () {
456
565
  SC.RunLoop.begin();
457
566
  SC.testControllerA.set('value', YES);
458
567
  SC.testControllerB.set('value', YES);
568
+ SC.testControllerC.set('value', YES);
459
569
  SC.RunLoop.end();
460
570
 
461
571
  SC.Binding.flushPendingChanges();
@@ -464,6 +574,7 @@ test("bound value should be YES if both sources are YES", function () {
464
574
  SC.RunLoop.begin();
465
575
  toObject.set('localValue1', YES);
466
576
  toObject.set('localValue2', YES);
577
+ toObject.set('localValue3', YES);
467
578
  SC.RunLoop.end();
468
579
 
469
580
  SC.Binding.flushPendingChanges();
@@ -474,50 +585,56 @@ test("toObject.value should be NO if either source is NO", function () {
474
585
  SC.RunLoop.begin();
475
586
  SC.testControllerA.set('value', YES);
476
587
  SC.testControllerB.set('value', NO);
588
+ SC.testControllerC.set('value', YES);
477
589
  SC.RunLoop.end();
478
590
 
479
591
  SC.Binding.flushPendingChanges();
480
- equals(toObject.get('value'), NO, 'Bound value on YES/NO');
592
+ equals(toObject.get('value'), NO, 'Bound value on YES/NO/YES');
481
593
 
482
594
  SC.RunLoop.begin();
483
595
  SC.testControllerA.set('value', YES);
484
596
  SC.testControllerB.set('value', YES);
597
+ SC.testControllerC.set('value', YES);
485
598
  SC.RunLoop.end();
486
599
 
487
600
  SC.Binding.flushPendingChanges();
488
- equals(toObject.get('value'), YES, 'Bound value on YES/YES');
601
+ equals(toObject.get('value'), YES, 'Bound value on YES/YES/YES');
489
602
 
490
603
  SC.RunLoop.begin();
491
604
  SC.testControllerA.set('value', NO);
492
605
  SC.testControllerB.set('value', YES);
606
+ SC.testControllerC.set('value', NO);
493
607
  SC.RunLoop.end();
494
608
 
495
609
  SC.Binding.flushPendingChanges();
496
- equals(toObject.get('value'), NO, 'Bound value on NO/YES');
610
+ equals(toObject.get('value'), NO, 'Bound value on NO/YES/NO');
497
611
 
498
612
  SC.RunLoop.begin();
499
613
  toObject.set('localValue1', YES);
500
614
  toObject.set('localValue2', NO);
615
+ toObject.set('localValue3', YES);
501
616
  SC.RunLoop.end();
502
617
 
503
618
  SC.Binding.flushPendingChanges();
504
- equals(toObject.get('boundLocalValue'), NO, 'Local bound value on YES/NO');
619
+ equals(toObject.get('boundLocalValue'), NO, 'Local bound value on YES/NO/YES');
505
620
 
506
621
  SC.RunLoop.begin();
507
622
  toObject.set('localValue1', YES);
508
623
  toObject.set('localValue2', YES);
624
+ toObject.set('localValue3', YES);
509
625
  SC.RunLoop.end();
510
626
 
511
627
  SC.Binding.flushPendingChanges();
512
- equals(toObject.get('boundLocalValue'), YES, 'Local bound value on YES/YES');
628
+ equals(toObject.get('boundLocalValue'), YES, 'Local bound value on YES/YES/YES');
513
629
 
514
630
  SC.RunLoop.begin();
515
631
  toObject.set('localValue1', NO);
516
632
  toObject.set('localValue2', YES);
633
+ toObject.set('localValue2', NO);
517
634
  SC.RunLoop.end();
518
635
 
519
636
  SC.Binding.flushPendingChanges();
520
- equals(toObject.get('boundLocalValue'), NO, 'Local bound value on NO/YES');
637
+ equals(toObject.get('boundLocalValue'), NO, 'Local bound value on NO/YES/NO');
521
638
  });
522
639
 
523
640
  test("remote paths work when binding is defined on a class", function() {
@@ -718,6 +835,62 @@ test("local paths work when binding is defined on a class", function() {
718
835
 
719
836
  });
720
837
 
838
+ module("Binding transform: `mix`", {
839
+
840
+ setup: function () {
841
+ // temporarily set up two source objects in the SC namespace so we can
842
+ // use property paths to access them
843
+ SC.testControllerA = SC.Object.create({ value: 0 });
844
+ SC.testControllerB = SC.Object.create({ value: 1 });
845
+ SC.testControllerC = SC.Object.create({ value: 2 });
846
+
847
+ toObject = SC.Object.create({
848
+ value: null,
849
+ valueBinding: SC.Binding.mix('SC.testControllerA.value', 'SC.testControllerB.value', 'SC.testControllerC.value',
850
+ function(v1,v2,v3) {
851
+ return v1+'-'+v2+'-'+v3;
852
+ } ),
853
+ localValue1: 1,
854
+ localValue2: 2,
855
+ localValue3: 3,
856
+ boundLocalValue: NO,
857
+ boundLocalValueBinding: SC.Binding.mix('.localValue1', '.localValue2', '.localValue3',
858
+ function(v1,v2,v3) {
859
+ return v1+'+'+v2+'+'+v3;
860
+ } )
861
+ });
862
+ },
863
+
864
+ teardown: function () {
865
+ SC.testControllerA.destroy();
866
+ delete SC.testControllerA;
867
+ SC.testControllerB.destroy();
868
+ delete SC.testControllerB;
869
+ SC.testControllerC.destroy();
870
+ delete SC.testControllerC;
871
+ }
872
+ });
873
+
874
+ test("bound value should be calculated correctly", function () {
875
+ SC.RunLoop.begin();
876
+ SC.testControllerA.set('value', 0);
877
+ SC.testControllerB.set('value', 10);
878
+ SC.testControllerC.set('value', 20);
879
+ SC.RunLoop.end();
880
+
881
+ SC.Binding.flushPendingChanges();
882
+ equals(toObject.get('value'), '0-10-20', 'Bound value');
883
+
884
+ SC.RunLoop.begin();
885
+ toObject.set('localValue1', 0);
886
+ toObject.set('localValue2', 10);
887
+ toObject.set('localValue3', 20);
888
+ SC.RunLoop.end();
889
+
890
+ SC.Binding.flushPendingChanges();
891
+ equals(toObject.get('boundLocalValue'), '0+10+20', 'Local bound value');
892
+ });
893
+
721
894
  module("Binding with '[]'", {
722
895
  setup: function () {
723
896
  fromObject = SC.Object.create({ value: [] });
@@ -751,8 +924,7 @@ module("propertyNameBinding with longhand", {
751
924
  teardown: function () {
752
925
  TestNamespace.fromObject.destroy();
753
926
  TestNamespace.toObject.destroy();
754
- delete TestNamespace.fromObject;
755
- delete TestNamespace.toObject;
927
+ TestNamespace = null;
756
928
  }
757
929
  });
758
930
 
@@ -815,7 +987,7 @@ test("Bindings override in subclasses.", function() {
815
987
  });
816
988
  SC.RunLoop.end();
817
989
 
818
- ok(fromObject._bindings.length === 1, "Duplicate bindings are not created.")
990
+ ok(fromObject._bindings.length === 1, "Duplicate bindings are not created.");
819
991
 
820
992
  equals(fromObject.get('value'), 'world', "Superclass binding should have been overridden in the subclass, giving value a value of");
821
993