sproutcore 1.10.2 → 1.10.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG +11 -0
- data/VERSION.yml +1 -1
- data/lib/frameworks/sproutcore/CHANGELOG.md +34 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/horizontal_stack_layout.js +3 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/child_view_layouts/vertical_stack_layout.js +3 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/platform.js +79 -80
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +115 -22
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/animation.js +54 -17
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/statechart.js +76 -34
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/select/methods.js +18 -5
- data/lib/frameworks/sproutcore/frameworks/desktop/views/grid.js +14 -5
- data/lib/frameworks/sproutcore/frameworks/desktop/views/select.js +42 -18
- data/lib/frameworks/sproutcore/frameworks/foundation/mixins/editable.js +41 -41
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/transitions/view_transitions_test.js +235 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/transitions/bounce_transition.js +8 -4
- data/lib/frameworks/sproutcore/frameworks/foundation/transitions/fade_transition.js +6 -2
- data/lib/frameworks/sproutcore/frameworks/foundation/transitions/pop_transition.js +8 -4
- data/lib/frameworks/sproutcore/frameworks/foundation/transitions/scale_transition.js +6 -2
- data/lib/frameworks/sproutcore/frameworks/foundation/transitions/slide_transition.js +6 -2
- data/lib/frameworks/sproutcore/frameworks/foundation/transitions/spring_transition.js +8 -4
- data/lib/frameworks/sproutcore/frameworks/foundation/views/inline_text_field.js +5 -4
- data/lib/frameworks/sproutcore/frameworks/runtime/core.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +124 -80
- data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/binding.js +134 -0
- data/lib/sproutcore.rb +1 -1
- data/lib/sproutcore/models/manifest.rb +12 -6
- data/lib/sproutcore/rack/builder.rb +20 -12
- data/lib/sproutcore/tools.rb +3 -3
- data/lib/sproutcore/tools/build.rb +22 -22
- data/sproutcore.gemspec +2 -5
- data/vendor/sproutcore/lib/yuicompressor-2.4.8.jar +0 -0
- metadata +10 -23
- data/vendor/sproutcore/lib/yuicompressor-2.4.6.jar +0 -0
@@ -105,8 +105,10 @@ SC.mixin(SC.View,
|
|
105
105
|
{ value: value, duration: duration, timing: 'ease-in-out' }
|
106
106
|
];
|
107
107
|
|
108
|
-
var callback = function () {
|
109
|
-
|
108
|
+
var callback = function (data) {
|
109
|
+
if (!data.isCancelled) {
|
110
|
+
view.didTransitionIn();
|
111
|
+
}
|
110
112
|
};
|
111
113
|
|
112
114
|
// Animate through the frames.
|
@@ -198,8 +200,10 @@ SC.mixin(SC.View,
|
|
198
200
|
{ value: finalValue, duration: duration, timing: 'ease-in' }
|
199
201
|
];
|
200
202
|
|
201
|
-
var callback = function () {
|
202
|
-
|
203
|
+
var callback = function (data) {
|
204
|
+
if (!data.isCancelled) {
|
205
|
+
view.didTransitionOut();
|
206
|
+
}
|
203
207
|
};
|
204
208
|
|
205
209
|
// Animate through the frames.
|
@@ -28,7 +28,9 @@ SC.mixin(SC.View,
|
|
28
28
|
duration: options.duration || 0.4,
|
29
29
|
timing: options.timing || 'ease'
|
30
30
|
}, function (data) {
|
31
|
-
|
31
|
+
if (!data.isCancelled) {
|
32
|
+
this.didTransitionIn();
|
33
|
+
}
|
32
34
|
});
|
33
35
|
}
|
34
36
|
},
|
@@ -48,7 +50,9 @@ SC.mixin(SC.View,
|
|
48
50
|
duration: options.duration || 0.4,
|
49
51
|
timing: options.timing || 'ease'
|
50
52
|
}, function (data) {
|
51
|
-
|
53
|
+
if (!data.isCancelled) {
|
54
|
+
this.didTransitionOut();
|
55
|
+
}
|
52
56
|
});
|
53
57
|
}
|
54
58
|
|
@@ -37,8 +37,10 @@ SC.mixin(SC.View,
|
|
37
37
|
{ value: { scale: scale }, duration: duration * 0.4, timing: 'ease-in-out' }
|
38
38
|
];
|
39
39
|
|
40
|
-
var callback = function () {
|
41
|
-
|
40
|
+
var callback = function (data) {
|
41
|
+
if (!data.isCancelled) {
|
42
|
+
view.didTransitionIn();
|
43
|
+
}
|
42
44
|
};
|
43
45
|
|
44
46
|
// Animate through the frames.
|
@@ -71,8 +73,10 @@ SC.mixin(SC.View,
|
|
71
73
|
{ value: { scale: 0 }, duration: duration * 0.6, timing: 'ease-in-out' }
|
72
74
|
];
|
73
75
|
|
74
|
-
var callback = function () {
|
75
|
-
|
76
|
+
var callback = function (data) {
|
77
|
+
if (!data.isCancelled) {
|
78
|
+
view.didTransitionOut();
|
79
|
+
}
|
76
80
|
};
|
77
81
|
|
78
82
|
// Animate through the frames.
|
@@ -27,7 +27,9 @@ SC.mixin(SC.View,
|
|
27
27
|
duration: options.duration || 0.4,
|
28
28
|
timing: options.timing || 'ease'
|
29
29
|
}, function (data) {
|
30
|
-
|
30
|
+
if (!data.isCancelled) {
|
31
|
+
this.didTransitionIn();
|
32
|
+
}
|
31
33
|
});
|
32
34
|
}
|
33
35
|
},
|
@@ -46,7 +48,9 @@ SC.mixin(SC.View,
|
|
46
48
|
duration: options.duration || 0.4,
|
47
49
|
timing: options.timing || 'ease'
|
48
50
|
}, function (data) {
|
49
|
-
|
51
|
+
if (!data.isCancelled) {
|
52
|
+
this.didTransitionOut();
|
53
|
+
}
|
50
54
|
});
|
51
55
|
}
|
52
56
|
|
@@ -71,7 +71,9 @@ SC.mixin(SC.View,
|
|
71
71
|
duration: options.duration || 0.4,
|
72
72
|
timing: options.timing || 'ease'
|
73
73
|
}, function (data) {
|
74
|
-
|
74
|
+
if (!data.isCancelled) {
|
75
|
+
this.didTransitionIn();
|
76
|
+
}
|
75
77
|
});
|
76
78
|
}
|
77
79
|
},
|
@@ -132,7 +134,9 @@ SC.mixin(SC.View,
|
|
132
134
|
duration: options.duration || 0.4,
|
133
135
|
timing: options.timing || 'ease'
|
134
136
|
}, function (data) {
|
135
|
-
|
137
|
+
if (!data.isCancelled) {
|
138
|
+
this.didTransitionOut();
|
139
|
+
}
|
136
140
|
});
|
137
141
|
}
|
138
142
|
}
|
@@ -108,8 +108,10 @@ SC.mixin(SC.View,
|
|
108
108
|
{ value: value, duration: duration, timing: 'ease-in-out' } // Hit target.
|
109
109
|
];
|
110
110
|
|
111
|
-
var callback = function () {
|
112
|
-
|
111
|
+
var callback = function (data) {
|
112
|
+
if (!data.isCancelled) {
|
113
|
+
view.didTransitionIn();
|
114
|
+
}
|
113
115
|
};
|
114
116
|
|
115
117
|
// Animate through the frames.
|
@@ -192,8 +194,10 @@ SC.mixin(SC.View,
|
|
192
194
|
{ value: finalValue, duration: duration, timing: 'ease-in' }
|
193
195
|
];
|
194
196
|
|
195
|
-
var callback = function () {
|
196
|
-
|
197
|
+
var callback = function (data) {
|
198
|
+
if (!data.isCancelled) {
|
199
|
+
view.didTransitionOut();
|
200
|
+
}
|
197
201
|
};
|
198
202
|
|
199
203
|
// Animate through the frames.
|
@@ -335,8 +335,11 @@ SC.InlineTextFieldView = SC.TextFieldView.extend(SC.InlineEditor,
|
|
335
335
|
*/
|
336
336
|
// TODO: this seems to do almost the same thing as fieldDidBlur
|
337
337
|
blurEditor: function(evt) {
|
338
|
-
if (
|
339
|
-
|
338
|
+
if (this.get('isEditing')) {
|
339
|
+
return this.commitOnBlur ? this.commitEditing() : this.discardEditing();
|
340
|
+
} else {
|
341
|
+
return true;
|
342
|
+
}
|
340
343
|
},
|
341
344
|
|
342
345
|
/**
|
@@ -436,7 +439,6 @@ SC.InlineTextFieldView = SC.TextFieldView.extend(SC.InlineEditor,
|
|
436
439
|
insertTab: function(evt) {
|
437
440
|
var target = this.target; // removed by commitEditing()
|
438
441
|
this.resignFirstResponder();
|
439
|
-
this.commitEditing() ;
|
440
442
|
if(target){
|
441
443
|
var next = target.get('nextValidKeyView');
|
442
444
|
if(next && next.beginEditing) next.beginEditing();
|
@@ -448,7 +450,6 @@ SC.InlineTextFieldView = SC.TextFieldView.extend(SC.InlineEditor,
|
|
448
450
|
insertBacktab: function(evt) {
|
449
451
|
var target = this.target; // removed by commitEditing()
|
450
452
|
this.resignFirstResponder();
|
451
|
-
this.commitEditing() ;
|
452
453
|
if(target){
|
453
454
|
var prev = target.get('previousValidKeyView');
|
454
455
|
if(prev && prev.beginEditing) prev.beginEditing();
|
@@ -1179,7 +1179,7 @@ SC.Observable = /** @scope SC.Observable.prototype */{
|
|
1179
1179
|
// observer during that round of notification. Similarly, if you're
|
1180
1180
|
// added as an observer during the notification round by another
|
1181
1181
|
// observer, you will not be notified until the next time.)
|
1182
|
-
members =
|
1182
|
+
members = observers.getMembers();
|
1183
1183
|
membersLength = members.length;
|
1184
1184
|
for (memberLoc = 0; memberLoc < membersLength; memberLoc++) {
|
1185
1185
|
member = members[memberLoc];
|
@@ -1224,7 +1224,7 @@ SC.Observable = /** @scope SC.Observable.prototype */{
|
|
1224
1224
|
if (starObservers && key !== '*') {
|
1225
1225
|
// We clone the structure per the justification, above, for regular
|
1226
1226
|
// observers.
|
1227
|
-
members =
|
1227
|
+
members = starObservers.getMembers();
|
1228
1228
|
membersLength = members.length;
|
1229
1229
|
for (memberLoc = 0; memberLoc < membersLength; memberLoc++) {
|
1230
1230
|
member = members[memberLoc];
|
@@ -267,6 +267,12 @@ SC.Binding = /** @scope SC.Binding.prototype */{
|
|
267
267
|
beget: function (fromPath) {
|
268
268
|
var ret = SC.beget(this);
|
269
269
|
ret.parentBinding = this;
|
270
|
+
// Logic gates must be recreated on beget.
|
271
|
+
if (ret._LogicGate) {
|
272
|
+
ret._logicGate = ret._LogicGate.create(ret._logicGateHash);
|
273
|
+
ret = ret.from('logicProperty', ret._logicGate).oneWay();
|
274
|
+
}
|
275
|
+
// Enables duplicate API calls for SC.Binding.beget and SC.Binding.from
|
270
276
|
if (fromPath !== undefined) ret = ret.from(fromPath);
|
271
277
|
return ret;
|
272
278
|
},
|
@@ -471,8 +477,13 @@ SC.Binding = /** @scope SC.Binding.prototype */{
|
|
471
477
|
// Mark it destroyed.
|
472
478
|
this.isDestroyed = YES;
|
473
479
|
|
474
|
-
//
|
475
|
-
if (this._logicGate)
|
480
|
+
// Clean up the logic gate, if any. (See logic gate methods.)
|
481
|
+
if (this._logicGate) {
|
482
|
+
this._logicGate.destroy();
|
483
|
+
this._logicGate = null;
|
484
|
+
this._LogicGate = null;
|
485
|
+
this._logicGateHash = null;
|
486
|
+
}
|
476
487
|
|
477
488
|
// Disconnect the binding.
|
478
489
|
this.disconnect();
|
@@ -494,6 +505,20 @@ SC.Binding = /** @scope SC.Binding.prototype */{
|
|
494
505
|
fromPropertyDidChange: function (target, key) {
|
495
506
|
var v = target ? target.get(key) : null;
|
496
507
|
|
508
|
+
// In rare circumstances, getting a property can result in observers firing,
|
509
|
+
// which may in turn run code that disconnects the binding. The cause of
|
510
|
+
// this pattern has been difficult to determine and so until a concrete test
|
511
|
+
// scenario and a lower level fix can be found, show a warning and ignore
|
512
|
+
// the update.
|
513
|
+
if (!this.isConnected) {
|
514
|
+
//@if(debug)
|
515
|
+
SC.Logger.warn("Developer Warning: A binding attempted to update after it was disconnected. The update will be ignored for binding: %@".fmt(this._fromPropertyPath, this._fromTarget, this));
|
516
|
+
//@endif
|
517
|
+
|
518
|
+
// Break early.
|
519
|
+
return;
|
520
|
+
}
|
521
|
+
|
497
522
|
// if the new value is different from the current binding value, then
|
498
523
|
// schedule to register an update.
|
499
524
|
if (v !== this._bindingValue || key === '[]') {
|
@@ -523,6 +548,20 @@ SC.Binding = /** @scope SC.Binding.prototype */{
|
|
523
548
|
|
524
549
|
var v = target.get(key);
|
525
550
|
|
551
|
+
// In rare circumstances, getting a property can result in observers firing,
|
552
|
+
// which may in turn run code that disconnects the binding. The cause of
|
553
|
+
// this pattern has been difficult to determine and so until a concrete test
|
554
|
+
// scenario and a lower level fix can be found, show a warning and ignore
|
555
|
+
// the update.
|
556
|
+
if (!this.isConnected) {
|
557
|
+
//@if(debug)
|
558
|
+
SC.Logger.warn("Developer Warning: A binding attempted to update after it was disconnected. The update will be ignored for binding: %@".fmt(this));
|
559
|
+
//@endif
|
560
|
+
|
561
|
+
// Break early.
|
562
|
+
return;
|
563
|
+
}
|
564
|
+
|
526
565
|
// if the new value is different from the current binding value, then
|
527
566
|
// schedule to register an update.
|
528
567
|
if (v !== this._transformedBindingValue) {
|
@@ -773,7 +812,7 @@ SC.Binding = /** @scope SC.Binding.prototype */{
|
|
773
812
|
if (tuple) {
|
774
813
|
this._toTarget = tuple[0];
|
775
814
|
this._toPropertyKey = tuple[1];
|
776
|
-
// Hook up _logicGate if needed (see
|
815
|
+
// Hook up _logicGate if needed (see logic gate methods).
|
777
816
|
if (this._logicGate) {
|
778
817
|
this._logicGate.set('localObject', this._toTarget);
|
779
818
|
}
|
@@ -978,112 +1017,117 @@ SC.Binding = /** @scope SC.Binding.prototype */{
|
|
978
1017
|
},
|
979
1018
|
|
980
1019
|
/**
|
981
|
-
Adds a transform
|
982
|
-
|
983
|
-
as a one-way binding, working only in the direction
|
984
|
-
|
985
|
-
'pathA' AND 'pathB' --> value (value returned is the result of ('pathA' && 'pathB'))
|
1020
|
+
Adds a transform to convert the value to the inverse of a bool value. This
|
1021
|
+
uses the same transform as bool() but inverts it.
|
986
1022
|
|
987
|
-
|
988
|
-
|
1023
|
+
@param {String} [fromPath]
|
1024
|
+
@returns {SC.Binding} this
|
1025
|
+
*/
|
1026
|
+
not: function (fromPath) {
|
1027
|
+
return this.from(fromPath).transform(function (v) {
|
1028
|
+
var t = SC.typeOf(v);
|
1029
|
+
if (t === SC.T_ERROR) return v;
|
1030
|
+
return !((t == SC.T_ARRAY) ? (v.length > 0) : (v === '') ? NO : !!v);
|
1031
|
+
});
|
1032
|
+
},
|
989
1033
|
|
990
|
-
|
991
|
-
|
992
|
-
})
|
1034
|
+
/**
|
1035
|
+
Adds a transform that will return YES if the value is null or undefined, NO otherwise.
|
993
1036
|
|
994
|
-
@param {String}
|
995
|
-
@
|
1037
|
+
@param {String} [fromPath]
|
1038
|
+
@returns {SC.Binding} this
|
996
1039
|
*/
|
997
|
-
|
1040
|
+
isNull: function (fromPath) {
|
1041
|
+
return this.from(fromPath).transform(function (v) {
|
1042
|
+
var t = SC.typeOf(v);
|
1043
|
+
return (t === SC.T_ERROR) ? v : SC.none(v);
|
1044
|
+
});
|
1045
|
+
},
|
998
1046
|
|
999
|
-
|
1047
|
+
/* @private Used with the logic gate bindings. */
|
1048
|
+
_LogicGateAnd: SC.Object.extend({
|
1049
|
+
logicProperty: function() {
|
1050
|
+
return (this.get('valueA') && this.get('valueB'));
|
1051
|
+
}.property('valueA', 'valueB').cacheable()
|
1052
|
+
}),
|
1053
|
+
/* @private Used with the logic gate bindings. */
|
1054
|
+
_LogicGateOr: SC.Object.extend({
|
1055
|
+
logicProperty: function() {
|
1056
|
+
return (this.get('valueA') || this.get('valueB'));
|
1057
|
+
}.property('valueA', 'valueB').cacheable()
|
1058
|
+
}),
|
1059
|
+
/* @private Used by logic gate bindings. */
|
1060
|
+
_logicGateBinding: function (gateClass, pathA, pathB) {
|
1061
|
+
// If either path is local, remove any * chains and append the localObject path to it.
|
1000
1062
|
if (pathA.indexOf('*') === 0 || pathA.indexOf('.') === 0) {
|
1001
|
-
pathA =
|
1063
|
+
pathA = pathA.slice(1).replace(/\*/g, '.');
|
1064
|
+
pathA = '*localObject.' + pathA;
|
1002
1065
|
}
|
1003
1066
|
if (pathB.indexOf('*') === 0 || pathB.indexOf('.') === 0) {
|
1004
|
-
pathB =
|
1067
|
+
pathB = pathB.slice(1).replace(/\*/g, '.');
|
1068
|
+
pathB = '*localObject.' + pathB;
|
1005
1069
|
}
|
1006
1070
|
|
1007
|
-
//
|
1008
|
-
var
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1071
|
+
// Gets the gate class and instantiates a nice copy.
|
1072
|
+
var gateHash = {
|
1073
|
+
localObject: null,
|
1074
|
+
valueABinding: SC.Binding.oneWay(pathA),
|
1075
|
+
valueBBinding: SC.Binding.oneWay(pathB)
|
1076
|
+
},
|
1077
|
+
gate = gateClass.create(gateHash);
|
1078
|
+
|
1079
|
+
// Creates and populates the return binding.
|
1080
|
+
var ret = this.from('logicProperty', gate).oneWay();
|
1081
|
+
// This is all needed later on by beget, which must create a new logic gate instance
|
1082
|
+
// or risk bad behavior.
|
1083
|
+
ret._LogicGate = gateClass;
|
1084
|
+
ret._logicGateHash = gateHash;
|
1021
1085
|
ret._logicGate = gate;
|
1086
|
+
|
1087
|
+
// On our way.
|
1022
1088
|
return ret;
|
1023
1089
|
},
|
1024
1090
|
|
1025
1091
|
/**
|
1026
|
-
Adds a transform that forwards the '
|
1092
|
+
Adds a transform that forwards the logical 'AND' of values at 'pathA' and
|
1027
1093
|
'pathB' whenever either source changes. Note that the transform acts strictly
|
1028
1094
|
as a one-way binding, working only in the direction
|
1029
1095
|
|
1030
|
-
'pathA' AND 'pathB' --> value (value returned is the result of ('pathA'
|
1096
|
+
'pathA' AND 'pathB' --> value (value returned is the result of ('pathA' && 'pathB'))
|
1097
|
+
|
1098
|
+
Usage example where a delete button's 'isEnabled' value is determined by whether
|
1099
|
+
something is selected in a list and whether the current user is allowed to delete:
|
1100
|
+
|
1101
|
+
deleteButton: SC.ButtonView.design({
|
1102
|
+
isEnabledBinding: SC.Binding.and('MyApp.itemsController.hasSelection', 'MyApp.userController.canDelete')
|
1103
|
+
})
|
1031
1104
|
|
1032
1105
|
@param {String} pathA The first part of the conditional
|
1033
1106
|
@param {String} pathB The second part of the conditional
|
1034
1107
|
*/
|
1035
|
-
|
1036
|
-
|
1037
|
-
if (pathA.indexOf('*') === 0 || pathA.indexOf('.') === 0) {
|
1038
|
-
pathA = '*localObject.' + pathA.slice(1);
|
1039
|
-
}
|
1040
|
-
if (pathB.indexOf('*') === 0 || pathB.indexOf('.') === 0) {
|
1041
|
-
pathB = '*localObject.' + pathB.slice(1);
|
1042
|
-
}
|
1043
|
-
|
1044
|
-
// create an object to the logical computation
|
1045
|
-
var gate = SC.Object.create({
|
1046
|
-
localObject: null,
|
1047
|
-
|
1048
|
-
valueABinding: pathA,
|
1049
|
-
valueBBinding: pathB,
|
1050
|
-
|
1051
|
-
or: function () {
|
1052
|
-
return (this.get('valueA') || this.get('valueB'));
|
1053
|
-
}.property('valueA', 'valueB').cacheable()
|
1054
|
-
});
|
1055
|
-
|
1056
|
-
var ret = this.from('or', gate).oneWay();
|
1057
|
-
ret._logicGate = gate;
|
1058
|
-
return ret;
|
1108
|
+
and: function (pathA, pathB) {
|
1109
|
+
return this._logicGateBinding(this._LogicGateAnd, pathA, pathB);
|
1059
1110
|
},
|
1060
1111
|
|
1061
1112
|
/**
|
1062
|
-
Adds a transform
|
1063
|
-
|
1113
|
+
Adds a transform that forwards the 'OR' of values at 'pathA' and
|
1114
|
+
'pathB' whenever either source changes. Note that the transform acts strictly
|
1115
|
+
as a one-way binding, working only in the direction
|
1064
1116
|
|
1065
|
-
|
1066
|
-
@returns {SC.Binding} this
|
1067
|
-
*/
|
1068
|
-
not: function (fromPath) {
|
1069
|
-
return this.from(fromPath).transform(function (v) {
|
1070
|
-
var t = SC.typeOf(v);
|
1071
|
-
if (t === SC.T_ERROR) return v;
|
1072
|
-
return !((t == SC.T_ARRAY) ? (v.length > 0) : (v === '') ? NO : !!v);
|
1073
|
-
});
|
1074
|
-
},
|
1117
|
+
'pathA' OR 'pathB' --> value (value returned is the result of ('pathA' || 'pathB'))
|
1075
1118
|
|
1076
|
-
|
1077
|
-
|
1119
|
+
Usage example where a delete button's 'isEnabled' value is determined by if the
|
1120
|
+
content is editable, or if the user has admin rights:
|
1078
1121
|
|
1079
|
-
|
1080
|
-
|
1122
|
+
deleteButton: SC.ButtonView.design({
|
1123
|
+
isEnabledBinding: SC.Binding.or('*content.isEditable', 'MyApp.userController.isAdmin')
|
1124
|
+
})
|
1125
|
+
|
1126
|
+
@param {String} pathA The first part of the conditional
|
1127
|
+
@param {String} pathB The second part of the conditional
|
1081
1128
|
*/
|
1082
|
-
|
1083
|
-
return this.
|
1084
|
-
var t = SC.typeOf(v);
|
1085
|
-
return (t === SC.T_ERROR) ? v : SC.none(v);
|
1086
|
-
});
|
1129
|
+
or: function (pathA, pathB) {
|
1130
|
+
return this._logicGateBinding(this._LogicGateOr, pathA, pathB);
|
1087
1131
|
},
|
1088
1132
|
|
1089
1133
|
toString: function () {
|