sproutcore 1.6.0.1-java → 1.7.1.beta-java
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.
- data/CHANGELOG +21 -0
- data/Gemfile +5 -0
- data/Rakefile +26 -13
- data/VERSION.yml +2 -2
- data/lib/Buildfile +43 -4
- data/lib/buildtasks/build.rake +10 -0
- data/lib/buildtasks/helpers/file_rule.rb +22 -0
- data/lib/buildtasks/helpers/file_rule_list.rb +137 -0
- data/lib/buildtasks/manifest.rake +133 -122
- data/lib/frameworks/sproutcore/CHANGELOG.md +69 -2
- data/lib/frameworks/sproutcore/apps/tests/english.lproj/strings.js +1 -0
- data/lib/frameworks/sproutcore/frameworks/bootstrap/system/browser.js +28 -22
- data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/array.js +9 -5
- data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/controller.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/controls/button.js +18 -13
- data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/handlebars/bind.js +5 -3
- data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/handlebars/collection.js +2 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/action_support.js +80 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/template_helpers/text_field_support.js +84 -116
- data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +8 -5
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +157 -157
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/platform.js +5 -3
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +6 -6
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/sparse_array.js +10 -7
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/action_support.js +106 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/collection.js +18 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/handlebars.js +71 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/attribute_bindings_test.js +38 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/class_name_bindings_test.js +47 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutChildViews.js +18 -18
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutStyle.js +42 -10
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +158 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/keyboard.js +26 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout_style.js +14 -8
- data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +15 -2
- data/lib/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +108 -108
- data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/datastore/system/record_array.js +2 -4
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/error_methods.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/single_attribute.js +26 -0
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/query/builders.js +7 -0
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/record_array/error_methods.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/system/datetime.js +4 -1
- data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/tests/system/datetime.js +6 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/panes/menu.js +26 -5
- data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +97 -96
- data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +4 -3
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/ui.js +17 -4
- data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +7 -7
- data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +7 -5
- data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +12 -3
- data/lib/frameworks/sproutcore/frameworks/desktop/views/web.js +23 -14
- data/lib/frameworks/sproutcore/frameworks/experimental/Buildfile +5 -1
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/render_delegates/menu_scroller.js +28 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/tests/menu/scroll.js +235 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroll.js +363 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroller.js +250 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/desktop_scroller.js +92 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/native_scroll.js +25 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/scroll.js +33 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/touch_scroller.js +76 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/integration.js +50 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/methods.js +143 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/ui.js +258 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroll.js +1164 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroller.js +332 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroll.js +236 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroller.js +347 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroll.js +15 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroller.js +10 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroll.js +804 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroller.js +133 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/resources/text_field.css +3 -3
- data/lib/frameworks/sproutcore/frameworks/foundation/validators/number.js +3 -1
- data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +3 -3
- data/lib/frameworks/sproutcore/frameworks/media/views/audio.js +2 -1
- data/lib/frameworks/sproutcore/frameworks/media/views/controls.js +2 -1
- data/lib/frameworks/sproutcore/frameworks/media/views/media_slider.js +2 -4
- data/lib/frameworks/sproutcore/frameworks/media/views/mini_controls.js +2 -4
- data/lib/frameworks/sproutcore/frameworks/media/views/simple_controls.js +2 -4
- data/lib/frameworks/sproutcore/frameworks/media/views/video.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/routing/system/routes.js +29 -3
- data/lib/frameworks/sproutcore/frameworks/runtime/core.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/replace.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/private/property_chain.js +2 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +3 -3
- data/lib/frameworks/sproutcore/frameworks/runtime/system/index_set.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +1 -1
- data/lib/frameworks/sproutcore/themes/ace/resources/collection/normal/list_item.css +2 -2
- data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/segmented.css +1 -1
- data/lib/gen/app/templates/apps/@target_name@/Buildfile +3 -5
- data/lib/gen/app/templates/apps/@target_name@/resources/_theme.css +18 -0
- data/lib/gen/project/templates/@filename@/Buildfile +2 -2
- data/lib/sproutcore.rb +30 -5
- data/lib/sproutcore/builders.rb +1 -0
- data/lib/sproutcore/builders/chance_file.rb +9 -16
- data/lib/sproutcore/builders/html.rb +2 -1
- data/lib/sproutcore/builders/minify.rb +4 -35
- data/lib/sproutcore/builders/module.rb +38 -1
- data/lib/sproutcore/builders/split.rb +63 -0
- data/lib/sproutcore/builders/strings.rb +7 -1
- data/lib/sproutcore/helpers.rb +1 -1
- data/lib/sproutcore/helpers/css_split.rb +190 -0
- data/lib/sproutcore/helpers/entry_sorter.rb +2 -0
- data/lib/sproutcore/helpers/minifier.rb +40 -16
- data/lib/sproutcore/helpers/static_helper.rb +35 -17
- data/lib/sproutcore/models/manifest.rb +26 -0
- data/lib/sproutcore/models/target.rb +12 -1
- data/lib/sproutcore/rack.rb +1 -0
- data/lib/sproutcore/rack/proxy.rb +244 -225
- data/lib/sproutcore/rack/restrict_ip.rb +67 -0
- data/lib/sproutcore/rack/service.rb +8 -2
- data/lib/sproutcore/tools.rb +102 -46
- data/lib/sproutcore/tools/build.rb +91 -43
- data/lib/sproutcore/tools/gen.rb +2 -3
- data/lib/sproutcore/tools/manifest.rb +22 -16
- data/lib/sproutcore/tools/server.rb +21 -0
- data/spec/buildtasks/helpers/accept_list +22 -0
- data/spec/buildtasks/helpers/accept_list.rb +128 -0
- data/spec/buildtasks/helpers/list.json +11 -0
- data/spec/buildtasks/manifest/prepare_build_tasks/chance_2x_spec.rb +1 -39
- data/spec/buildtasks/manifest/prepare_build_tasks/chance_spec.rb +0 -38
- data/spec/buildtasks/manifest/prepare_build_tasks/combine_spec.rb +4 -4
- data/spec/buildtasks/manifest/prepare_build_tasks/module_spec.rb +2 -2
- data/spec/buildtasks/manifest/prepare_build_tasks/packed_2x_indirect_spec.rb +7 -16
- data/spec/buildtasks/manifest/prepare_build_tasks/packed_2x_spec.rb +7 -17
- data/spec/buildtasks/manifest/prepare_build_tasks/packed_spec.rb +11 -6
- data/spec/fixtures/builder_tests/Buildfile +2 -1
- data/spec/fixtures/builder_tests/apps/module_test/modules/required_module/core.js +0 -0
- data/spec/lib/builders/module_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- data/sproutcore.gemspec +4 -9
- data/vendor/chance/lib/chance.rb +25 -6
- data/vendor/chance/lib/chance/factory.rb +45 -0
- data/vendor/chance/lib/chance/instance.rb +173 -28
- data/vendor/chance/lib/chance/instance/data_url.rb +0 -29
- data/vendor/chance/lib/chance/instance/slicing.rb +57 -4
- data/vendor/chance/lib/chance/instance/spriting.rb +112 -21
- data/vendor/chance/lib/chance/parser.rb +80 -52
- data/vendor/sproutcore/SCCompiler.jar +0 -0
- data/vendor/sproutcore/lib/args4j-2.0.12.jar +0 -0
- data/vendor/sproutcore/lib/yuicompressor-2.4.2.jar +0 -0
- metadata +84 -25
@@ -10,9 +10,15 @@
|
|
10
10
|
|
11
11
|
/*globals module test ok same equals */
|
12
12
|
|
13
|
+
|
13
14
|
/* These unit tests verify: layout(), frame(), styleLayout() and clippingFrame(). */
|
14
15
|
(function() {
|
15
|
-
var parent, child;
|
16
|
+
var parent, child, frameKeys, layoutKeys;
|
17
|
+
|
18
|
+
frameKeys = 'x y width height'.w();
|
19
|
+
layoutKeys = ['width','height','top','bottom','marginLeft','marginTop','left','right','zIndex',
|
20
|
+
'minWidth','maxWidth','minHeight','maxHeight','borderTopWidth','borderBottomWidth',
|
21
|
+
'borderLeftWidth','borderRightWidth'];
|
16
22
|
|
17
23
|
/*
|
18
24
|
helper method to test the layout of a view. Applies the passed layout to a
|
@@ -31,19 +37,16 @@
|
|
31
37
|
@returns {void}
|
32
38
|
*/
|
33
39
|
function performLayoutTest(layout, no_f, no_s, with_f, with_s, isFixedShouldBe) {
|
34
|
-
// make sure we add null properties and convert numbers to 'XXpx' to style layout.
|
35
|
-
var layoutKeys = ('width height top bottom marginLeft marginTop left right zIndex minWidth maxWidth minHeight maxHeight ' +
|
36
|
-
'borderTopWidth borderBottomWidth borderLeftWidth borderRightWidth').w();
|
37
40
|
if (SC.platform.supportsCSSTransforms) { layoutKeys.push('transform'); }
|
38
41
|
|
39
|
-
|
40
|
-
|
42
|
+
// make sure we add null properties and convert numbers to 'XXpx' to style layout.
|
41
43
|
layoutKeys.forEach(function(key) {
|
42
44
|
if (no_s[key]===undefined) { no_s[key] = null; }
|
43
45
|
if (with_s[key]===undefined) { with_s[key] = null; }
|
44
46
|
|
47
|
+
|
45
48
|
if (typeof no_s[key] === 'number') { no_s[key] = no_s[key].toString() + 'px'; }
|
46
|
-
if (typeof with_s[key] === 'number') { with_s[key] =
|
49
|
+
if (typeof with_s[key] === 'number') { with_s[key] = with_s[key].toString() + 'px'; }
|
47
50
|
});
|
48
51
|
|
49
52
|
// set layout
|
@@ -85,9 +88,13 @@
|
|
85
88
|
});
|
86
89
|
|
87
90
|
if (with_f !== undefined) {
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
+
if (frame && with_f) {
|
92
|
+
frameKeys.forEach(function(key){
|
93
|
+
equals(frame[key], with_f[key], "FRAME W/ PARENT %@".fmt(key));
|
94
|
+
});
|
95
|
+
} else {
|
96
|
+
equals(frame, with_f, "FRAME W/ PARENT");
|
97
|
+
}
|
91
98
|
}
|
92
99
|
|
93
100
|
// check if isFixedLayout is correct
|
@@ -723,7 +730,32 @@
|
|
723
730
|
test("for proper null variables");
|
724
731
|
// nothing should get passed through as undefined, instead we want null in certain cases
|
725
732
|
|
733
|
+
module('STATIC LAYOUT VARIATIONS', commonSetup);
|
734
|
+
|
735
|
+
test("no layout", function() {
|
736
|
+
|
737
|
+
var no_f = null,
|
738
|
+
no_s = {},
|
739
|
+
with_f = null,
|
740
|
+
with_s = {};
|
741
|
+
|
742
|
+
child.set('useStaticLayout', true);
|
743
|
+
|
744
|
+
performLayoutTest(SC.View.prototype.layout, no_f, no_s, with_f, with_s, NO);
|
745
|
+
});
|
746
|
+
|
747
|
+
test("with layout", function() {
|
748
|
+
|
749
|
+
var layout = { top: 10, left: 10, width: 50, height: 50 },
|
750
|
+
no_f = null,
|
751
|
+
no_s = { top: 10, left: 10, width: 50, height: 50 },
|
752
|
+
with_f = null,
|
753
|
+
with_s = { top: 10, left: 10, width: 50, height: 50 };
|
726
754
|
|
755
|
+
child.set('useStaticLayout', true);
|
756
|
+
|
757
|
+
performLayoutTest(layout, no_f, no_s, with_f, with_s, YES);
|
758
|
+
});
|
727
759
|
|
728
760
|
// test("frame size shifts with top/left/bottom/right", function(){
|
729
761
|
// var error=null;
|
@@ -42,7 +42,7 @@ SC.EMPTY_CHILD_VIEWS_ARRAY.needsClone = YES;
|
|
42
42
|
SC.CoreView.reopen(
|
43
43
|
/** @scope SC.View.prototype */ {
|
44
44
|
|
45
|
-
concatenatedProperties: ['outlets', 'displayProperties', 'classNames', 'renderMixin', 'didCreateLayerMixin', 'willDestroyLayerMixin'],
|
45
|
+
concatenatedProperties: ['outlets', 'displayProperties', 'classNames', 'renderMixin', 'didCreateLayerMixin', 'willDestroyLayerMixin', 'classNameBindings', 'attributeBindings'],
|
46
46
|
|
47
47
|
/**
|
48
48
|
The current pane.
|
@@ -670,6 +670,11 @@ SC.CoreView.reopen(
|
|
670
670
|
},
|
671
671
|
|
672
672
|
applyAttributesToContext: function(context) {
|
673
|
+
if (!this.get('layer')) {
|
674
|
+
this._applyClassNameBindings();
|
675
|
+
this._applyAttributeBindings(context);
|
676
|
+
}
|
677
|
+
|
673
678
|
context.addClass(this.get('classNames'));
|
674
679
|
|
675
680
|
if (this.get('isTextSelectable')) { context.addClass('allow-select'); }
|
@@ -685,6 +690,155 @@ SC.CoreView.reopen(
|
|
685
690
|
context.attr('role', this.get('ariaRole'));
|
686
691
|
},
|
687
692
|
|
693
|
+
/**
|
694
|
+
@private
|
695
|
+
|
696
|
+
Iterates over the view's `classNameBindings` array, inserts the value
|
697
|
+
of the specified property into the `classNames` array, then creates an
|
698
|
+
observer to update the view's element if the bound property ever changes
|
699
|
+
in the future.
|
700
|
+
*/
|
701
|
+
_applyClassNameBindings: function() {
|
702
|
+
var classBindings = this.get('classNameBindings'),
|
703
|
+
classNames = this.get('classNames'),
|
704
|
+
elem, newClass, dasherizedClass;
|
705
|
+
|
706
|
+
if (!classBindings) { return; }
|
707
|
+
|
708
|
+
// Loop through all of the configured bindings. These will be either
|
709
|
+
// property names ('isUrgent') or property paths relative to the view
|
710
|
+
// ('content.isUrgent')
|
711
|
+
classBindings.forEach(function(property) {
|
712
|
+
|
713
|
+
// Variable in which the old class value is saved. The observer function
|
714
|
+
// closes over this variable, so it knows which string to remove when
|
715
|
+
// the property changes.
|
716
|
+
var oldClass;
|
717
|
+
|
718
|
+
// Set up an observer on the context. If the property changes, toggle the
|
719
|
+
// class name.
|
720
|
+
observer = function() {
|
721
|
+
// Get the current value of the property
|
722
|
+
newClass = this._classStringForProperty(property);
|
723
|
+
elem = this.$();
|
724
|
+
|
725
|
+
// If we had previously added a class to the element, remove it.
|
726
|
+
if (oldClass) {
|
727
|
+
elem.removeClass(oldClass);
|
728
|
+
}
|
729
|
+
|
730
|
+
// If necessary, add a new class. Make sure we keep track of it so
|
731
|
+
// it can be removed in the future.
|
732
|
+
if (newClass) {
|
733
|
+
elem.addClass(newClass);
|
734
|
+
oldClass = newClass;
|
735
|
+
} else {
|
736
|
+
oldClass = null;
|
737
|
+
}
|
738
|
+
};
|
739
|
+
|
740
|
+
this.addObserver(property, this, observer);
|
741
|
+
|
742
|
+
// Get the class name for the property at its current value
|
743
|
+
dasherizedClass = this._classStringForProperty(property);
|
744
|
+
|
745
|
+
if (dasherizedClass) {
|
746
|
+
// Ensure that it gets into the classNames array
|
747
|
+
// so it is displayed when we render.
|
748
|
+
classNames.push(dasherizedClass);
|
749
|
+
|
750
|
+
// Save a reference to the class name so we can remove it
|
751
|
+
// if the observer fires. Remember that this variable has
|
752
|
+
// been closed over by the observer.
|
753
|
+
oldClass = dasherizedClass;
|
754
|
+
}
|
755
|
+
}, this);
|
756
|
+
},
|
757
|
+
|
758
|
+
/**
|
759
|
+
Iterates through the view's attribute bindings, sets up observers for each,
|
760
|
+
then applies the current value of the attributes to the passed render buffer.
|
761
|
+
|
762
|
+
@param {SC.RenderBuffer} buffer
|
763
|
+
*/
|
764
|
+
_applyAttributeBindings: function(context) {
|
765
|
+
var attributeBindings = this.get('attributeBindings'),
|
766
|
+
attributeValue, elem, type;
|
767
|
+
|
768
|
+
if (!attributeBindings) { return; }
|
769
|
+
|
770
|
+
attributeBindings.forEach(function(attribute) {
|
771
|
+
// Create an observer to add/remove/change the attribute if the
|
772
|
+
// JavaScript property changes.
|
773
|
+
var observer = function() {
|
774
|
+
elem = this.$();
|
775
|
+
var currentValue = elem.attr(attribute);
|
776
|
+
attributeValue = this.get(attribute);
|
777
|
+
|
778
|
+
type = typeof attributeValue;
|
779
|
+
|
780
|
+
if ((type === 'string' || type === 'number') && attributeValue !== currentValue) {
|
781
|
+
elem.attr(attribute, attributeValue);
|
782
|
+
} else if (attributeValue && type === 'boolean') {
|
783
|
+
elem.attr(attribute, attribute);
|
784
|
+
} else if (attributeValue === NO) {
|
785
|
+
elem.removeAttr(attribute);
|
786
|
+
}
|
787
|
+
};
|
788
|
+
|
789
|
+
this.addObserver(attribute, this, observer);
|
790
|
+
|
791
|
+
// Determine the current value and add it to the render buffer
|
792
|
+
// if necessary.
|
793
|
+
attributeValue = this.get(attribute);
|
794
|
+
type = typeof attributeValue;
|
795
|
+
|
796
|
+
if (type === 'string' || type === 'number') {
|
797
|
+
context.attr(attribute, attributeValue);
|
798
|
+
} else if (attributeValue && type === 'boolean') {
|
799
|
+
// Apply boolean attributes in the form attribute="attribute"
|
800
|
+
context.attr(attribute, attribute);
|
801
|
+
}
|
802
|
+
}, this);
|
803
|
+
},
|
804
|
+
|
805
|
+
/**
|
806
|
+
@private
|
807
|
+
|
808
|
+
Given a property name, returns a dasherized version of that
|
809
|
+
property name if the property evaluates to a non-falsy value.
|
810
|
+
|
811
|
+
For example, if the view has property `isUrgent` that evaluates to true,
|
812
|
+
passing `isUrgent` to this method will return `"is-urgent"`.
|
813
|
+
*/
|
814
|
+
_classStringForProperty: function(property) {
|
815
|
+
var split = property.split(':'), className = split[1];
|
816
|
+
property = split[0];
|
817
|
+
|
818
|
+
var val = SC.getPath(this, property);
|
819
|
+
|
820
|
+
// If value is a Boolean and true, return the dasherized property
|
821
|
+
// name.
|
822
|
+
if (val === YES) {
|
823
|
+
if (className) { return className; }
|
824
|
+
|
825
|
+
// Normalize property path to be suitable for use
|
826
|
+
// as a class name. For exaple, content.foo.barBaz
|
827
|
+
// becomes bar-baz.
|
828
|
+
return SC.String.dasherize(property.split('.').get('lastObject'));
|
829
|
+
|
830
|
+
// If the value is not NO, undefined, or null, return the current
|
831
|
+
// value of the property.
|
832
|
+
} else if (val !== NO && val !== undefined && val !== null) {
|
833
|
+
return val;
|
834
|
+
|
835
|
+
// Nothing to display. Return null so that the old class is removed
|
836
|
+
// but no new class is added.
|
837
|
+
} else {
|
838
|
+
return null;
|
839
|
+
}
|
840
|
+
},
|
841
|
+
|
688
842
|
/**
|
689
843
|
@private
|
690
844
|
|
@@ -904,6 +1058,9 @@ SC.CoreView.reopen(
|
|
904
1058
|
// SC.RootResponder to dispatch incoming events.
|
905
1059
|
SC.View.views[this.get('layerId')] = this;
|
906
1060
|
|
1061
|
+
// setup classNames
|
1062
|
+
this.classNames = this.get('classNames').slice();
|
1063
|
+
|
907
1064
|
// setup child views. be sure to clone the child views array first
|
908
1065
|
this.childViews = this.get('childViews').slice() ;
|
909
1066
|
this.createChildViews() ; // setup child Views
|
@@ -51,7 +51,32 @@ SC.View.reopen(
|
|
51
51
|
@param {SC.Responder} responder
|
52
52
|
*/
|
53
53
|
didBecomeKeyResponderFrom: function(responder) {
|
54
|
-
|
54
|
+
|
55
|
+
// Hack!!!
|
56
|
+
// If we try to execute the focus code right now, the iPad will take this as an opportunity to break
|
57
|
+
// execution of the current Run Loop (if that Run Loop was started by a timer expiring) to execute
|
58
|
+
// any touch event code that is waiting at this time.
|
59
|
+
//
|
60
|
+
// This becomes a problem in particular for ScrollView's that use a timer to pass touches to their content,
|
61
|
+
// because the touchend event can come in while the timer code is executing and pause here to complete
|
62
|
+
// the touchend code and then continue the timer code afterward. However, the timer code's
|
63
|
+
// execution context will then be out-of-date and will cause a crash in RootResponder's assignTouch().
|
64
|
+
//
|
65
|
+
// To verify this, use the branch sproutcore/timer_touch_debug in any SproutCore project. Then visit
|
66
|
+
// the app launcher http://my.local.machine.ip:4020 on an iPad 1 and simply press one of the app's
|
67
|
+
// in the list. The app should crash on the first touch (depending slightly on the speed at which you
|
68
|
+
// touch the selection; presses will crash it, taps generally won't). It should occur on the first
|
69
|
+
// touch or else try reloading the app until you get the proper touch speed figured out.
|
70
|
+
//
|
71
|
+
// Using the debug branch, when it crashes, notice how the console statements aren't in order according
|
72
|
+
// to the timestamps and notice how there is a big gap in timestamps around this.$().focus() where the
|
73
|
+
// touchend block of code runs.
|
74
|
+
//
|
75
|
+
// -Tyler Keating : tyler@sproutcore.com
|
76
|
+
|
77
|
+
this.invokeLater(function() {
|
78
|
+
this.$().focus();
|
79
|
+
});
|
55
80
|
},
|
56
81
|
|
57
82
|
/**
|
@@ -402,6 +402,7 @@ SC.View.LayoutStyleCalculator = SC.Object.extend({
|
|
402
402
|
|
403
403
|
calculate: function() {
|
404
404
|
var layout = this.get('layout'), pdim = null,
|
405
|
+
staticLayout = this.get('staticLayout'),
|
405
406
|
translateTop = null,
|
406
407
|
translateLeft = null,
|
407
408
|
turbo = this.get('turbo'),
|
@@ -413,6 +414,11 @@ SC.View.LayoutStyleCalculator = SC.Object.extend({
|
|
413
414
|
|
414
415
|
this._handleMistakes(layout);
|
415
416
|
|
417
|
+
// If the developer sets useStaticLayout and doesn't provide a unique `layout` property, we
|
418
|
+
// should not insert the styles "left: 0px; right: 0px; top: 0px; bottom: 0px" as they could
|
419
|
+
// conflict with the developer's intention. However, if they do provide a unique `layout`,
|
420
|
+
// use it.
|
421
|
+
if (staticLayout && layout === SC.View.prototype.layout) return {};
|
416
422
|
|
417
423
|
// X DIRECTION
|
418
424
|
|
@@ -473,21 +479,21 @@ SC.View.LayoutStyleCalculator = SC.Object.extend({
|
|
473
479
|
|
474
480
|
if (pendingAnimations) {
|
475
481
|
if (!activeAnimations) activeAnimations = {};
|
476
|
-
|
482
|
+
|
477
483
|
for (key in pendingAnimations) {
|
478
484
|
if (!pendingAnimations.hasOwnProperty(key)) continue;
|
479
|
-
|
485
|
+
|
480
486
|
pendingAnimation = pendingAnimations[key];
|
481
487
|
activeAnimation = activeAnimations[key];
|
482
488
|
shouldCancel = NO;
|
483
|
-
|
489
|
+
|
484
490
|
if (newStyle[key] !== (currentStyle ? currentStyle[key] : null)) shouldCancel = YES;
|
485
|
-
|
491
|
+
|
486
492
|
// if we have a new animation (an animation property has changed), cancel current
|
487
493
|
if (activeAnimation && (activeAnimation.duration !== pendingAnimation.duration || activeAnimation.timing !== pendingAnimation.timing)) {
|
488
494
|
shouldCancel = YES;
|
489
495
|
}
|
490
|
-
|
496
|
+
|
491
497
|
if (shouldCancel && activeAnimation) {
|
492
498
|
if (callback = activeAnimation.callback) {
|
493
499
|
if (transformsLength > 0) {
|
@@ -499,14 +505,14 @@ SC.View.LayoutStyleCalculator = SC.Object.extend({
|
|
499
505
|
this.runAnimationCallback(callback, null, key, YES);
|
500
506
|
}
|
501
507
|
}
|
502
|
-
|
508
|
+
|
503
509
|
this.removeAnimationFromLayout(key, YES);
|
504
510
|
}
|
505
|
-
|
511
|
+
|
506
512
|
activeAnimations[key] = pendingAnimation;
|
507
513
|
}
|
508
514
|
}
|
509
|
-
|
515
|
+
|
510
516
|
this._activeAnimations = activeAnimations;
|
511
517
|
this._pendingAnimations = null;
|
512
518
|
}
|
@@ -729,7 +729,7 @@ SC.Record = SC.Object.extend(
|
|
729
729
|
@dependsOn status
|
730
730
|
*/
|
731
731
|
isError: function() {
|
732
|
-
return this.get('status') & SC.Record.ERROR;
|
732
|
+
return !!(this.get('status') & SC.Record.ERROR);
|
733
733
|
}.property('status').cacheable(),
|
734
734
|
|
735
735
|
/**
|
@@ -1336,6 +1336,9 @@ SC.Record.mixin( /** @scope SC.Record */ {
|
|
1336
1336
|
opts = opts || {};
|
1337
1337
|
var isNested = opts.nested || opts.isNested;
|
1338
1338
|
var attr;
|
1339
|
+
|
1340
|
+
this._throwUnlessRecordTypeDefined(recordType, 'toMany');
|
1341
|
+
|
1339
1342
|
if(isNested){
|
1340
1343
|
attr = SC.ChildrenAttribute.attr(recordType, opts);
|
1341
1344
|
}
|
@@ -1362,6 +1365,9 @@ SC.Record.mixin( /** @scope SC.Record */ {
|
|
1362
1365
|
opts = opts || {};
|
1363
1366
|
var isNested = opts.nested || opts.isNested;
|
1364
1367
|
var attr;
|
1368
|
+
|
1369
|
+
this._throwUnlessRecordTypeDefined(recordType, 'toOne');
|
1370
|
+
|
1365
1371
|
if(isNested){
|
1366
1372
|
attr = SC.ChildAttribute.attr(recordType, opts);
|
1367
1373
|
}
|
@@ -1370,6 +1376,13 @@ SC.Record.mixin( /** @scope SC.Record */ {
|
|
1370
1376
|
}
|
1371
1377
|
return attr;
|
1372
1378
|
},
|
1379
|
+
|
1380
|
+
_throwUnlessRecordTypeDefined: function(recordType, relationshipType) {
|
1381
|
+
if (!recordType) {
|
1382
|
+
throw "Attempted to create " + relationshipType + " attribute with " +
|
1383
|
+
"undefined recordType. Did you forget to sc_require a dependency?";
|
1384
|
+
}
|
1385
|
+
},
|
1373
1386
|
|
1374
1387
|
/**
|
1375
1388
|
Returns all storeKeys mapped by Id for this record type. This method is
|
@@ -1439,7 +1452,7 @@ SC.Record.mixin( /** @scope SC.Record */ {
|
|
1439
1452
|
/** @private - enhance extend to notify SC.Query as well. */
|
1440
1453
|
extend: function() {
|
1441
1454
|
var ret = SC.Object.extend.apply(this, arguments);
|
1442
|
-
SC.Query._scq_didDefineRecordType(ret);
|
1455
|
+
if(SC.Query) SC.Query._scq_didDefineRecordType(ret);
|
1443
1456
|
return ret ;
|
1444
1457
|
}
|
1445
1458
|
}) ;
|
@@ -12,33 +12,33 @@ sc_require('models/record');
|
|
12
12
|
A RecordAttribute describes a single attribute on a record. It is used to
|
13
13
|
generate computed properties on records that can automatically convert data
|
14
14
|
types and verify data.
|
15
|
-
|
16
|
-
When defining an attribute on an SC.Record, you can configure it this way:
|
17
|
-
|
18
|
-
title: SC.Record.attr(String, {
|
15
|
+
|
16
|
+
When defining an attribute on an SC.Record, you can configure it this way:
|
17
|
+
|
18
|
+
title: SC.Record.attr(String, {
|
19
19
|
defaultValue: 'Untitled',
|
20
20
|
isRequired: YES|NO
|
21
21
|
})
|
22
|
-
|
23
|
-
In addition to having predefined transform types, there is also a way to
|
22
|
+
|
23
|
+
In addition to having predefined transform types, there is also a way to
|
24
24
|
set a computed relationship on an attribute. A typical example of this would
|
25
|
-
be if you have record with a parentGuid attribute, but are not able to
|
25
|
+
be if you have record with a parentGuid attribute, but are not able to
|
26
26
|
determine which record type to map to before looking at the guid (or any
|
27
|
-
other attributes). To set up such a computed property, you can attach a
|
27
|
+
other attributes). To set up such a computed property, you can attach a
|
28
28
|
function in the attribute definition of the SC.Record subclass:
|
29
|
-
|
29
|
+
|
30
30
|
relatedToComputed: SC.Record.toOne(function() {
|
31
31
|
return (this.readAttribute('relatedToComputed').indexOf("foo")==0) ? MyApp.Foo : MyApp.Bar;
|
32
32
|
})
|
33
|
-
|
34
|
-
Notice that we are not using .get() to avoid another transform which would
|
33
|
+
|
34
|
+
Notice that we are not using .get() to avoid another transform which would
|
35
35
|
trigger an infinite loop.
|
36
|
-
|
36
|
+
|
37
37
|
You usually will not work with RecordAttribute objects directly, though you
|
38
38
|
may extend the class in any way that you like to create a custom attribute.
|
39
39
|
|
40
40
|
A number of default RecordAttribute types are defined on the SC.Record.
|
41
|
-
|
41
|
+
|
42
42
|
@extends SC.Object
|
43
43
|
@see SC.Record
|
44
44
|
@see SC.ManyAttribute
|
@@ -60,75 +60,75 @@ SC.RecordAttribute = SC.Object.extend(
|
|
60
60
|
value will be substituted instead. Note that `defaultValue`s are not
|
61
61
|
converted, so the value should be in the output type expected by the
|
62
62
|
attribute.
|
63
|
-
|
63
|
+
|
64
64
|
If you use a `defaultValue` function, the arguments given to it are the
|
65
65
|
record instance and the key.
|
66
|
-
|
66
|
+
|
67
67
|
@type Object|function
|
68
68
|
@default null
|
69
69
|
*/
|
70
70
|
defaultValue: null,
|
71
|
-
|
71
|
+
|
72
72
|
/**
|
73
73
|
The attribute type. Must be either an object class or a property path
|
74
|
-
naming a class. The built in handler allows all native types to pass
|
74
|
+
naming a class. The built in handler allows all native types to pass
|
75
75
|
through, converts records to ids and dates to UTF strings.
|
76
|
-
|
76
|
+
|
77
77
|
If you use the `attr()` helper method to create a RecordAttribute instance,
|
78
78
|
it will set this property to the first parameter you pass.
|
79
|
-
|
79
|
+
|
80
80
|
@type Object|String
|
81
81
|
@default String
|
82
82
|
*/
|
83
83
|
type: String,
|
84
|
-
|
84
|
+
|
85
85
|
/**
|
86
86
|
The underlying attribute key name this attribute should manage. If this
|
87
87
|
property is left empty, then the key will be whatever property name this
|
88
88
|
attribute assigned to on the record. If you need to provide some kind
|
89
89
|
of alternate mapping, this provides you a way to override it.
|
90
|
-
|
90
|
+
|
91
91
|
@type String
|
92
92
|
@default null
|
93
93
|
*/
|
94
94
|
key: null,
|
95
|
-
|
95
|
+
|
96
96
|
/**
|
97
97
|
If `YES`, then the attribute is required and will fail validation unless
|
98
98
|
the property is set to a non-null or undefined value.
|
99
|
-
|
99
|
+
|
100
100
|
@type Boolean
|
101
101
|
@default NO
|
102
102
|
*/
|
103
103
|
isRequired: NO,
|
104
|
-
|
104
|
+
|
105
105
|
/**
|
106
106
|
If `NO` then attempts to edit the attribute will be ignored.
|
107
|
-
|
107
|
+
|
108
108
|
@type Boolean
|
109
109
|
@default YES
|
110
110
|
*/
|
111
|
-
isEditable: YES,
|
112
|
-
|
111
|
+
isEditable: YES,
|
112
|
+
|
113
113
|
/**
|
114
|
-
If set when using the Date format, expect the ISO8601 date format.
|
114
|
+
If set when using the Date format, expect the ISO8601 date format.
|
115
115
|
This is the default.
|
116
|
-
|
116
|
+
|
117
117
|
@type Boolean
|
118
118
|
@default YES
|
119
119
|
*/
|
120
120
|
useIsoDate: YES,
|
121
|
-
|
121
|
+
|
122
122
|
/**
|
123
123
|
Can only be used for toOne or toMany relationship attributes. If YES,
|
124
124
|
this flag will ensure that any related objects will also be marked
|
125
|
-
dirty when this record dirtied.
|
126
|
-
|
127
|
-
Useful when you might have multiple related objects that you want to
|
125
|
+
dirty when this record dirtied.
|
126
|
+
|
127
|
+
Useful when you might have multiple related objects that you want to
|
128
128
|
consider in an 'aggregated' state. For instance, by changing a child
|
129
|
-
object (image) you might also want to automatically mark the parent
|
129
|
+
object (image) you might also want to automatically mark the parent
|
130
130
|
(album) dirty as well.
|
131
|
-
|
131
|
+
|
132
132
|
@type Boolean
|
133
133
|
@default NO
|
134
134
|
*/
|
@@ -154,16 +154,16 @@ SC.RecordAttribute = SC.Object.extend(
|
|
154
154
|
@default NO
|
155
155
|
*/
|
156
156
|
lazilyInstantiate: NO,
|
157
|
-
|
157
|
+
|
158
158
|
// ..........................................................
|
159
159
|
// HELPER PROPERTIES
|
160
|
-
//
|
161
|
-
|
160
|
+
//
|
161
|
+
|
162
162
|
/**
|
163
163
|
Returns the type, resolved to a class. If the type property is a regular
|
164
|
-
class, returns the type unchanged. Otherwise attempts to lookup the
|
164
|
+
class, returns the type unchanged. Otherwise attempts to lookup the
|
165
165
|
type as a property path.
|
166
|
-
|
166
|
+
|
167
167
|
@property
|
168
168
|
@type Object
|
169
169
|
@default String
|
@@ -173,12 +173,12 @@ SC.RecordAttribute = SC.Object.extend(
|
|
173
173
|
if (SC.typeOf(ret) === SC.T_STRING) ret = SC.requiredObjectForPropertyPath(ret);
|
174
174
|
return ret ;
|
175
175
|
}.property('type').cacheable(),
|
176
|
-
|
176
|
+
|
177
177
|
/**
|
178
178
|
Finds the transform handler. Attempts to find a transform that you
|
179
179
|
registered using registerTransform for this attribute's type, otherwise
|
180
180
|
defaults to using the default transform for String.
|
181
|
-
|
181
|
+
|
182
182
|
@property
|
183
183
|
@type Transform
|
184
184
|
*/
|
@@ -186,7 +186,7 @@ SC.RecordAttribute = SC.Object.extend(
|
|
186
186
|
var klass = this.get('typeClass') || String,
|
187
187
|
transforms = SC.RecordAttribute.transforms,
|
188
188
|
ret ;
|
189
|
-
|
189
|
+
|
190
190
|
// walk up class hierarchy looking for a transform handler
|
191
191
|
while(klass && !(ret = transforms[SC.guidFor(klass)])) {
|
192
192
|
// check if super has create property to detect SC.Object's
|
@@ -194,20 +194,20 @@ SC.RecordAttribute = SC.Object.extend(
|
|
194
194
|
// otherwise return the function transform handler
|
195
195
|
else klass = SC.T_FUNCTION ;
|
196
196
|
}
|
197
|
-
|
197
|
+
|
198
198
|
return ret ;
|
199
199
|
}.property('typeClass').cacheable(),
|
200
|
-
|
200
|
+
|
201
201
|
// ..........................................................
|
202
202
|
// LOW-LEVEL METHODS
|
203
|
-
//
|
204
|
-
|
205
|
-
/**
|
206
|
-
Converts the passed value into the core attribute value. This will apply
|
203
|
+
//
|
204
|
+
|
205
|
+
/**
|
206
|
+
Converts the passed value into the core attribute value. This will apply
|
207
207
|
any format transforms. You can install standard transforms by adding to
|
208
|
-
the `SC.RecordAttribute.transforms` hash. See
|
208
|
+
the `SC.RecordAttribute.transforms` hash. See
|
209
209
|
SC.RecordAttribute.registerTransform() for more.
|
210
|
-
|
210
|
+
|
211
211
|
@param {SC.Record} record The record instance
|
212
212
|
@param {String} key The key used to access this attribute on the record
|
213
213
|
@param {Object} value The property value before being transformed
|
@@ -217,10 +217,10 @@ SC.RecordAttribute = SC.Object.extend(
|
|
217
217
|
var transform = this.get('transform'),
|
218
218
|
type = this.get('typeClass'),
|
219
219
|
children;
|
220
|
-
|
220
|
+
|
221
221
|
if (transform && transform.to) {
|
222
222
|
value = transform.to(value, this, type, record, key) ;
|
223
|
-
|
223
|
+
|
224
224
|
// if the transform needs to do something when its children change, we need to set up an observer for it
|
225
225
|
if(!SC.none(value) && (children = transform.observesChildren)) {
|
226
226
|
var i, len = children.length,
|
@@ -229,27 +229,27 @@ SC.RecordAttribute = SC.Object.extend(
|
|
229
229
|
record: record,
|
230
230
|
key: key
|
231
231
|
};
|
232
|
-
|
232
|
+
|
233
233
|
for(i = 0; i < len; i++) value.addObserver(children[i], this, this._SCRA_childObserver, context);
|
234
234
|
}
|
235
235
|
}
|
236
|
-
|
236
|
+
|
237
237
|
return value ;
|
238
238
|
},
|
239
|
-
|
239
|
+
|
240
240
|
/**
|
241
241
|
@private
|
242
|
-
|
242
|
+
|
243
243
|
Shared observer used by any attribute whose transform creates a seperate
|
244
244
|
object that needs to write back to the datahash when it changes. For
|
245
245
|
example, when enumerable content changes on a `SC.Set` attribute, it
|
246
246
|
writes back automatically instead of forcing you to call `.set` manually.
|
247
|
-
|
247
|
+
|
248
248
|
This functionality can be used by setting an array named
|
249
249
|
observesChildren on your transform containing the names of keys to
|
250
250
|
observe. When one of them triggers it will call childDidChange on your
|
251
251
|
transform with the same arguments as to and from.
|
252
|
-
|
252
|
+
|
253
253
|
@param {Object} obj The transformed value that is being observed
|
254
254
|
@param {String} key The key used to access this attribute on the record
|
255
255
|
@param {Object} prev Previous value (not used)
|
@@ -258,15 +258,15 @@ SC.RecordAttribute = SC.Object.extend(
|
|
258
258
|
_SCRA_childObserver: function(obj, key, prev, context) {
|
259
259
|
// write the new value back to the record
|
260
260
|
this.call(context.record, context.key, obj);
|
261
|
-
|
261
|
+
|
262
262
|
// mark the attribute as dirty
|
263
263
|
context.record.notifyPropertyChange(context.key);
|
264
264
|
},
|
265
265
|
|
266
|
-
/**
|
267
|
-
Converts the passed value from the core attribute value. This will apply
|
266
|
+
/**
|
267
|
+
Converts the passed value from the core attribute value. This will apply
|
268
268
|
any format transforms. You can install standard transforms by adding to
|
269
|
-
the `SC.RecordAttribute.transforms` hash. See
|
269
|
+
the `SC.RecordAttribute.transforms` hash. See
|
270
270
|
`SC.RecordAttribute.registerTransform()` for more.
|
271
271
|
|
272
272
|
@param {SC.Record} record The record instance
|
@@ -277,7 +277,7 @@ SC.RecordAttribute = SC.Object.extend(
|
|
277
277
|
fromType: function(record, key, value) {
|
278
278
|
var transform = this.get('transform'),
|
279
279
|
type = this.get('typeClass');
|
280
|
-
|
280
|
+
|
281
281
|
if (transform && transform.from) {
|
282
282
|
value = transform.from(value, this, type, record, key);
|
283
283
|
}
|
@@ -289,7 +289,7 @@ SC.RecordAttribute = SC.Object.extend(
|
|
289
289
|
parent record, since `SC.RecordAttribute` uses `isProperty` to masquerade
|
290
290
|
as a computed property. Get expects a property be a function, thus we
|
291
291
|
need to implement call.
|
292
|
-
|
292
|
+
|
293
293
|
@param {SC.Record} record The record instance
|
294
294
|
@param {String} key The key used to access this attribute on the record
|
295
295
|
@param {Object} value The property value if called as a setter
|
@@ -297,13 +297,13 @@ SC.RecordAttribute = SC.Object.extend(
|
|
297
297
|
*/
|
298
298
|
call: function(record, key, value) {
|
299
299
|
var attrKey = this.get('key') || key, nvalue;
|
300
|
-
|
300
|
+
|
301
301
|
if ((value !== undefined) && this.get('isEditable')) {
|
302
|
-
// careful: don't overwrite value here. we want the return value to
|
302
|
+
// careful: don't overwrite value here. we want the return value to
|
303
303
|
// cache.
|
304
304
|
nvalue = this.fromType(record, key, value) ; // convert to attribute.
|
305
|
-
record.writeAttribute(attrKey, nvalue);
|
306
|
-
}
|
305
|
+
record.writeAttribute(attrKey, nvalue);
|
306
|
+
}
|
307
307
|
|
308
308
|
nvalue = value = record.readAttribute(attrKey);
|
309
309
|
if (SC.none(value) && (value = this.get('defaultValue'))) {
|
@@ -315,40 +315,40 @@ SC.RecordAttribute = SC.Object.extend(
|
|
315
315
|
}
|
316
316
|
}
|
317
317
|
} else value = this.toType(record, key, value);
|
318
|
-
|
318
|
+
|
319
319
|
return value ;
|
320
320
|
},
|
321
321
|
|
322
322
|
// ..........................................................
|
323
323
|
// INTERNAL SUPPORT
|
324
|
-
//
|
325
|
-
|
324
|
+
//
|
325
|
+
|
326
326
|
/** @private - Make this look like a property so that `get()` will call it. */
|
327
327
|
isProperty: YES,
|
328
|
-
|
328
|
+
|
329
329
|
/** @private - Make this look cacheable */
|
330
330
|
isCacheable: YES,
|
331
|
-
|
331
|
+
|
332
332
|
/** @private - needed for KVO `property()` support */
|
333
333
|
dependentKeys: [],
|
334
|
-
|
334
|
+
|
335
335
|
/** @private */
|
336
336
|
init: function() {
|
337
337
|
sc_super();
|
338
338
|
// setup some internal properties needed for KVO - faking 'cacheable'
|
339
|
-
this.cacheKey = "
|
340
|
-
this.lastSetValueKey = "
|
339
|
+
this.cacheKey = "__cache__recattr__" + SC.guidFor(this) ;
|
340
|
+
this.lastSetValueKey = "__lastValue__recattr__" + SC.guidFor(this) ;
|
341
341
|
}
|
342
342
|
}) ;
|
343
343
|
|
344
344
|
// ..........................................................
|
345
345
|
// CLASS METHODS
|
346
|
-
//
|
346
|
+
//
|
347
347
|
|
348
348
|
SC.RecordAttribute.mixin(
|
349
349
|
/** @scope SC.RecordAttribute.prototype */{
|
350
350
|
/**
|
351
|
-
The default method used to create a record attribute instance. Unlike
|
351
|
+
The default method used to create a record attribute instance. Unlike
|
352
352
|
`create()`, takes an `attributeType` as the first parameter which will be
|
353
353
|
set on the attribute itself. You can pass a string naming a class or a
|
354
354
|
class itself.
|
@@ -365,7 +365,7 @@ SC.RecordAttribute.mixin(
|
|
365
365
|
},
|
366
366
|
|
367
367
|
/** @private
|
368
|
-
Hash of registered transforms by class guid.
|
368
|
+
Hash of registered transforms by class guid.
|
369
369
|
*/
|
370
370
|
transforms: {},
|
371
371
|
|
@@ -373,13 +373,13 @@ SC.RecordAttribute.mixin(
|
|
373
373
|
Call to register a transform handler for a specific type of object. The
|
374
374
|
object you pass can be of any type as long as it responds to the following
|
375
375
|
methods
|
376
|
-
|
376
|
+
|
377
377
|
- `to(value, attr, klass, record, key)` converts the passed value
|
378
378
|
(which will be of the class expected by the attribute) into the
|
379
379
|
underlying attribute value
|
380
380
|
- `from(value, attr, klass, record, key)` converts the underyling
|
381
381
|
attribute value into a value of the class
|
382
|
-
|
382
|
+
|
383
383
|
You can also provide an array of keys to observer on the return value.
|
384
384
|
When any of these change, your from method will be called to write the
|
385
385
|
changed object back to the record. For example:
|
@@ -409,7 +409,7 @@ SC.RecordAttribute.mixin(
|
|
409
409
|
|
410
410
|
// ..........................................................
|
411
411
|
// STANDARD ATTRIBUTE TRANSFORMS
|
412
|
-
//
|
412
|
+
//
|
413
413
|
|
414
414
|
// Object, String, Number just pass through.
|
415
415
|
|
@@ -431,8 +431,8 @@ SC.RecordAttribute.registerTransform(Number, {
|
|
431
431
|
|
432
432
|
/** @private - generic converter for Strings */
|
433
433
|
SC.RecordAttribute.registerTransform(String, {
|
434
|
-
/** @private -
|
435
|
-
convert an arbitrary object value to a String
|
434
|
+
/** @private -
|
435
|
+
convert an arbitrary object value to a String
|
436
436
|
allow null through as that will be checked separately
|
437
437
|
*/
|
438
438
|
to: function(obj) {
|
@@ -453,7 +453,7 @@ SC.RecordAttribute.registerTransform(Array, {
|
|
453
453
|
}
|
454
454
|
return obj;
|
455
455
|
},
|
456
|
-
|
456
|
+
|
457
457
|
observesChildren: ['[]']
|
458
458
|
});
|
459
459
|
|
@@ -477,7 +477,7 @@ SC.RecordAttribute.registerTransform(SC.Record, {
|
|
477
477
|
if (SC.none(id) || (id==="")) return null;
|
478
478
|
else return store.find(recordType, id);
|
479
479
|
},
|
480
|
-
|
480
|
+
|
481
481
|
/** @private - convert a record instance to a record id */
|
482
482
|
from: function(record) { return record ? record.get('id') : null; }
|
483
483
|
});
|
@@ -491,7 +491,7 @@ SC.RecordAttribute.registerTransform(SC.T_FUNCTION, {
|
|
491
491
|
var store = parentRecord.get('store');
|
492
492
|
return store.find(recordType, id);
|
493
493
|
},
|
494
|
-
|
494
|
+
|
495
495
|
/** @private - convert a record instance to a record id */
|
496
496
|
from: function(record) { return record.get('id'); }
|
497
497
|
});
|
@@ -508,7 +508,7 @@ SC.RecordAttribute.registerTransform(Date, {
|
|
508
508
|
|
509
509
|
var ret ;
|
510
510
|
str = str.toString() || '';
|
511
|
-
|
511
|
+
|
512
512
|
if (attr.get('useIsoDate')) {
|
513
513
|
var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
|
514
514
|
"(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\\.([0-9]+))?)?" +
|
@@ -531,34 +531,34 @@ SC.RecordAttribute.registerTransform(Date, {
|
|
531
531
|
|
532
532
|
offset -= date.getTimezoneOffset();
|
533
533
|
time = (Number(date) + (offset * 60 * 1000));
|
534
|
-
|
534
|
+
|
535
535
|
ret = new Date();
|
536
536
|
ret.setTime(Number(time));
|
537
537
|
} else ret = new Date(Date.parse(str));
|
538
538
|
return ret ;
|
539
539
|
},
|
540
|
-
|
540
|
+
|
541
541
|
_dates: {},
|
542
|
-
|
542
|
+
|
543
543
|
/** @private - pad with leading zeroes */
|
544
|
-
_zeropad: function(num) {
|
545
|
-
return ((num<0) ? '-' : '') + ((num<10) ? '0' : '') + Math.abs(num);
|
544
|
+
_zeropad: function(num) {
|
545
|
+
return ((num<0) ? '-' : '') + ((num<10) ? '0' : '') + Math.abs(num);
|
546
546
|
},
|
547
|
-
|
547
|
+
|
548
548
|
/** @private - convert a date to a string */
|
549
|
-
from: function(date) {
|
549
|
+
from: function(date) {
|
550
550
|
|
551
551
|
if (SC.none(date)) { return null; }
|
552
552
|
|
553
553
|
var ret = this._dates[date.getTime()];
|
554
|
-
if (ret) return ret ;
|
555
|
-
|
554
|
+
if (ret) return ret ;
|
555
|
+
|
556
556
|
// figure timezone
|
557
557
|
var zp = this._zeropad,
|
558
558
|
tz = 0-date.getTimezoneOffset()/60;
|
559
|
-
|
559
|
+
|
560
560
|
tz = (tz === 0) ? 'Z' : '%@:00'.fmt(zp(tz));
|
561
|
-
|
561
|
+
|
562
562
|
this._dates[date.getTime()] = ret = "%@-%@-%@T%@:%@:%@%@".fmt(
|
563
563
|
zp(date.getFullYear()),
|
564
564
|
zp(date.getMonth()+1),
|
@@ -567,7 +567,7 @@ SC.RecordAttribute.registerTransform(Date, {
|
|
567
567
|
zp(date.getMinutes()),
|
568
568
|
zp(date.getSeconds()),
|
569
569
|
tz) ;
|
570
|
-
|
570
|
+
|
571
571
|
return ret ;
|
572
572
|
}
|
573
573
|
});
|
@@ -576,18 +576,18 @@ if (SC.DateTime && !SC.RecordAttribute.transforms[SC.guidFor(SC.DateTime)]) {
|
|
576
576
|
/**
|
577
577
|
Registers a transform to allow `SC.DateTime` to be used as a record
|
578
578
|
attribute, ie `SC.Record.attr(SC.DateTime);`
|
579
|
-
|
579
|
+
|
580
580
|
Because `SC.RecordAttribute` is in the datastore framework and
|
581
581
|
`SC.DateTime` in the foundation framework, and we don't know which
|
582
582
|
framework is being loaded first, this chunck of code is duplicated in
|
583
583
|
both frameworks.
|
584
|
-
|
584
|
+
|
585
585
|
IF YOU EDIT THIS CODE MAKE SURE YOU COPY YOUR CHANGES to
|
586
586
|
`record_attribute.js.`
|
587
587
|
*/
|
588
588
|
|
589
589
|
SC.RecordAttribute.registerTransform(SC.DateTime, {
|
590
|
-
|
590
|
+
|
591
591
|
/** @private
|
592
592
|
Convert a String to a DateTime
|
593
593
|
*/
|
@@ -597,7 +597,7 @@ if (SC.DateTime && !SC.RecordAttribute.transforms[SC.guidFor(SC.DateTime)]) {
|
|
597
597
|
var format = attr.get('format');
|
598
598
|
return SC.DateTime.parse(str, format ? format : SC.DateTime.recordFormat);
|
599
599
|
},
|
600
|
-
|
600
|
+
|
601
601
|
/** @private
|
602
602
|
Convert a DateTime to a String
|
603
603
|
*/
|
@@ -607,7 +607,7 @@ if (SC.DateTime && !SC.RecordAttribute.transforms[SC.guidFor(SC.DateTime)]) {
|
|
607
607
|
return dt.toFormattedString(format ? format : SC.DateTime.recordFormat);
|
608
608
|
}
|
609
609
|
});
|
610
|
-
|
610
|
+
|
611
611
|
}
|
612
612
|
|
613
613
|
/**
|
@@ -617,10 +617,10 @@ SC.RecordAttribute.registerTransform(SC.Set, {
|
|
617
617
|
to: function(value, attr, type, record, key) {
|
618
618
|
return SC.Set.create(value);
|
619
619
|
},
|
620
|
-
|
620
|
+
|
621
621
|
from: function(value, attr, type, record, key) {
|
622
622
|
return value.toArray();
|
623
623
|
},
|
624
|
-
|
624
|
+
|
625
625
|
observesChildren: ['[]']
|
626
626
|
});
|