sproutcore 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +269 -0
- data/README.txt +67 -0
- data/Rakefile +4 -0
- data/app_generators/sproutcore/USAGE +5 -0
- data/app_generators/sproutcore/sproutcore_generator.rb +66 -0
- data/app_generators/sproutcore/templates/README +77 -0
- data/app_generators/sproutcore/templates/environment.yml +4 -0
- data/bin/sc-build +145 -0
- data/bin/sc-gen +24 -0
- data/bin/sc-server +63 -0
- data/bin/sproutcore +21 -0
- data/clients/sc_docs/controllers/docs.js +118 -0
- data/clients/sc_docs/core.js +19 -0
- data/clients/sc_docs/english.lproj/body.css +159 -0
- data/clients/sc_docs/english.lproj/body.rhtml +33 -0
- data/clients/sc_docs/english.lproj/controls.css +0 -0
- data/clients/sc_docs/english.lproj/icons/small/next.png +0 -0
- data/clients/sc_docs/english.lproj/icons/small/reset.png +0 -0
- data/clients/sc_docs/english.lproj/images/gradients.png +0 -0
- data/clients/sc_docs/english.lproj/images/indicator.gif +0 -0
- data/clients/sc_docs/english.lproj/images/toolbar.png +0 -0
- data/clients/sc_docs/english.lproj/no_docs.rhtml +7 -0
- data/clients/sc_docs/english.lproj/strings.js +14 -0
- data/clients/sc_docs/english.lproj/warning.rhtml +6 -0
- data/clients/sc_docs/fixtures/doc.js +11 -0
- data/clients/sc_docs/main.js +21 -0
- data/clients/sc_docs/models/doc.js +9 -0
- data/clients/sc_docs/tests/controllers/docs.rhtml +21 -0
- data/clients/sc_docs/tests/models/doc.rhtml +21 -0
- data/clients/sc_docs/tests/views/doc_frame.rhtml +21 -0
- data/clients/sc_docs/tests/views/doc_label_view.rhtml +21 -0
- data/clients/sc_docs/views/doc_frame.js +33 -0
- data/clients/sc_docs/views/doc_label.js +20 -0
- data/clients/sc_test_runner/controllers/runner.js +175 -0
- data/clients/sc_test_runner/core.js +19 -0
- data/clients/sc_test_runner/english.lproj/body.css +151 -0
- data/clients/sc_test_runner/english.lproj/body.rhtml +35 -0
- data/clients/sc_test_runner/english.lproj/controls.css +0 -0
- data/clients/sc_test_runner/english.lproj/icons/small/next.png +0 -0
- data/clients/sc_test_runner/english.lproj/icons/small/reset.png +0 -0
- data/clients/sc_test_runner/english.lproj/images/gradients.png +0 -0
- data/clients/sc_test_runner/english.lproj/images/indicator.gif +0 -0
- data/clients/sc_test_runner/english.lproj/images/toolbar.png +0 -0
- data/clients/sc_test_runner/english.lproj/no_tests.rhtml +6 -0
- data/clients/sc_test_runner/english.lproj/strings.js +14 -0
- data/clients/sc_test_runner/english.lproj/warning.rhtml +6 -0
- data/clients/sc_test_runner/fixtures/test.js +12 -0
- data/clients/sc_test_runner/main.js +26 -0
- data/clients/sc_test_runner/models/test.js +11 -0
- data/clients/sc_test_runner/views/runner_frame.js +72 -0
- data/clients/sc_test_runner/views/test_label.js +20 -0
- data/config/hoe.rb +70 -0
- data/config/requirements.rb +17 -0
- data/environment.yml +9 -0
- data/frameworks/prototype/prototype.js +4186 -0
- data/frameworks/sproutcore/Core.js +378 -0
- data/frameworks/sproutcore/README +3 -0
- data/frameworks/sproutcore/controllers/array.js +236 -0
- data/frameworks/sproutcore/controllers/collection.js +305 -0
- data/frameworks/sproutcore/controllers/controller.js +323 -0
- data/frameworks/sproutcore/controllers/object.js +372 -0
- data/frameworks/sproutcore/drag/drag.js +549 -0
- data/frameworks/sproutcore/drag/drag_data_source.js +32 -0
- data/frameworks/sproutcore/drag/drag_source.js +64 -0
- data/frameworks/sproutcore/drag/drop_target.js +153 -0
- data/frameworks/sproutcore/english.lproj/blank.gif +0 -0
- data/frameworks/sproutcore/english.lproj/buttons.css +589 -0
- data/frameworks/sproutcore/english.lproj/buttons.png +0 -0
- data/frameworks/sproutcore/english.lproj/inline_text_editor.css +21 -0
- data/frameworks/sproutcore/english.lproj/menu.css +121 -0
- data/frameworks/sproutcore/english.lproj/panels/background-fat.jpg +0 -0
- data/frameworks/sproutcore/english.lproj/panels/background-thin.jpg +0 -0
- data/frameworks/sproutcore/english.lproj/panels/bottom-edge.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/bottom-left-corner.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/bottom-right-corner.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/left-edge.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/overlay.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/right-edge.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/top-edge.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/top-left-corner.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/top-right-corner.png +0 -0
- data/frameworks/sproutcore/english.lproj/panes.css +155 -0
- data/frameworks/sproutcore/english.lproj/picker.css +22 -0
- data/frameworks/sproutcore/english.lproj/strings.js +15 -0
- data/frameworks/sproutcore/english.lproj/tab.css +23 -0
- data/frameworks/sproutcore/english.lproj/tests.css +67 -0
- data/frameworks/sproutcore/english.lproj/theme.css +77 -0
- data/frameworks/sproutcore/foundation/animator.js +670 -0
- data/frameworks/sproutcore/foundation/application.js +199 -0
- data/frameworks/sproutcore/foundation/array.js +348 -0
- data/frameworks/sproutcore/foundation/benchmark.js +211 -0
- data/frameworks/sproutcore/foundation/binding.js +384 -0
- data/frameworks/sproutcore/foundation/date.js +357 -0
- data/frameworks/sproutcore/foundation/error.js +39 -0
- data/frameworks/sproutcore/foundation/input_manager.js +153 -0
- data/frameworks/sproutcore/foundation/json.js +296 -0
- data/frameworks/sproutcore/foundation/mock.js +42 -0
- data/frameworks/sproutcore/foundation/node_descriptor.js +56 -0
- data/frameworks/sproutcore/foundation/object.js +777 -0
- data/frameworks/sproutcore/foundation/observable.js +451 -0
- data/frameworks/sproutcore/foundation/page.js +63 -0
- data/frameworks/sproutcore/foundation/path_module.js +413 -0
- data/frameworks/sproutcore/foundation/responder.js +310 -0
- data/frameworks/sproutcore/foundation/routes.js +371 -0
- data/frameworks/sproutcore/foundation/run_loop.js +21 -0
- data/frameworks/sproutcore/foundation/server.js +491 -0
- data/frameworks/sproutcore/foundation/set.js +96 -0
- data/frameworks/sproutcore/foundation/string.js +149 -0
- data/frameworks/sproutcore/foundation/undo_manager.js +186 -0
- data/frameworks/sproutcore/foundation/unittest.js +622 -0
- data/frameworks/sproutcore/foundation/utils.js +61 -0
- data/frameworks/sproutcore/globals/panels.js +182 -0
- data/frameworks/sproutcore/globals/popups.js +60 -0
- data/frameworks/sproutcore/globals/window.js +381 -0
- data/frameworks/sproutcore/lib/index.rhtml +66 -0
- data/frameworks/sproutcore/models/collection.js +395 -0
- data/frameworks/sproutcore/models/record.js +622 -0
- data/frameworks/sproutcore/models/store.js +295 -0
- data/frameworks/sproutcore/panes/dialog.js +16 -0
- data/frameworks/sproutcore/panes/manager.js +164 -0
- data/frameworks/sproutcore/panes/menu.js +45 -0
- data/frameworks/sproutcore/panes/overlay.js +231 -0
- data/frameworks/sproutcore/panes/pane.js +90 -0
- data/frameworks/sproutcore/panes/panel.js +19 -0
- data/frameworks/sproutcore/panes/picker.js +45 -0
- data/frameworks/sproutcore/tests/controllers/array.rhtml +86 -0
- data/frameworks/sproutcore/tests/controllers/controller.rhtml +273 -0
- data/frameworks/sproutcore/tests/controllers/object.rhtml +327 -0
- data/frameworks/sproutcore/tests/foundation/application.rhtml +125 -0
- data/frameworks/sproutcore/tests/foundation/array.rhtml +221 -0
- data/frameworks/sproutcore/tests/foundation/object.rhtml +69 -0
- data/frameworks/sproutcore/tests/globals/window.rhtml +45 -0
- data/frameworks/sproutcore/tests/panes/pane.rhtml +88 -0
- data/frameworks/sproutcore/tests/views/collection.rhtml +137 -0
- data/frameworks/sproutcore/tests/views/popup_button.rhtml +115 -0
- data/frameworks/sproutcore/tests/views/text_field.rhtml +37 -0
- data/frameworks/sproutcore/validators/credit_card.js +92 -0
- data/frameworks/sproutcore/validators/date.js +36 -0
- data/frameworks/sproutcore/validators/email.js +29 -0
- data/frameworks/sproutcore/validators/not_empty.js +24 -0
- data/frameworks/sproutcore/validators/number.js +55 -0
- data/frameworks/sproutcore/validators/password.js +78 -0
- data/frameworks/sproutcore/validators/validator.js +304 -0
- data/frameworks/sproutcore/views/button.js +425 -0
- data/frameworks/sproutcore/views/checkbox_field.js +30 -0
- data/frameworks/sproutcore/views/collection.js +1521 -0
- data/frameworks/sproutcore/views/container.js +62 -0
- data/frameworks/sproutcore/views/error_explanation.js +45 -0
- data/frameworks/sproutcore/views/field.js +214 -0
- data/frameworks/sproutcore/views/filter_button.js +29 -0
- data/frameworks/sproutcore/views/form.js +591 -0
- data/frameworks/sproutcore/views/image.js +141 -0
- data/frameworks/sproutcore/views/inline_text_editor.js +96 -0
- data/frameworks/sproutcore/views/label.js +176 -0
- data/frameworks/sproutcore/views/menu_item.js +90 -0
- data/frameworks/sproutcore/views/pagination.js +54 -0
- data/frameworks/sproutcore/views/popup_button.js +86 -0
- data/frameworks/sproutcore/views/popup_menu.js +137 -0
- data/frameworks/sproutcore/views/progress.js +100 -0
- data/frameworks/sproutcore/views/radio_field.js +107 -0
- data/frameworks/sproutcore/views/radio_group.js +48 -0
- data/frameworks/sproutcore/views/segmented.js +80 -0
- data/frameworks/sproutcore/views/select_field.js +272 -0
- data/frameworks/sproutcore/views/spinner.js +11 -0
- data/frameworks/sproutcore/views/tab.js +126 -0
- data/frameworks/sproutcore/views/text_field.js +179 -0
- data/frameworks/sproutcore/views/textarea_field.js +14 -0
- data/frameworks/sproutcore/views/toolbar.js +29 -0
- data/frameworks/sproutcore/views/view.js +1389 -0
- data/frameworks/sproutcore/views/workspace.js +170 -0
- data/generators/client/README +3 -0
- data/generators/client/USAGE +12 -0
- data/generators/client/client_generator.rb +53 -0
- data/generators/client/templates/core.js +19 -0
- data/generators/client/templates/english.lproj/body.css +0 -0
- data/generators/client/templates/english.lproj/body.rhtml +3 -0
- data/generators/client/templates/english.lproj/controls.css +0 -0
- data/generators/client/templates/english.lproj/strings.js +14 -0
- data/generators/client/templates/main.js +37 -0
- data/generators/controller/USAGE +16 -0
- data/generators/controller/controller_generator.rb +51 -0
- data/generators/controller/templates/controller.js +21 -0
- data/generators/controller/templates/test.rhtml +21 -0
- data/generators/framework/README +7 -0
- data/generators/framework/USAGE +12 -0
- data/generators/framework/framework_generator.rb +53 -0
- data/generators/framework/templates/core.js +20 -0
- data/generators/framework/templates/english.lproj/body.css +0 -0
- data/generators/framework/templates/english.lproj/body.rhtml +3 -0
- data/generators/framework/templates/english.lproj/controls.css +0 -0
- data/generators/framework/templates/english.lproj/strings.js +14 -0
- data/generators/language/USAGE +16 -0
- data/generators/language/language_generator.rb +47 -0
- data/generators/language/templates/strings.js +10 -0
- data/generators/model/USAGE +24 -0
- data/generators/model/model_generator.rb +55 -0
- data/generators/model/templates/fixture.js +11 -0
- data/generators/model/templates/model.js +20 -0
- data/generators/model/templates/test.rhtml +21 -0
- data/generators/test/USAGE +16 -0
- data/generators/test/templates/test.rhtml +21 -0
- data/generators/test/test_generator.rb +47 -0
- data/generators/view/USAGE +16 -0
- data/generators/view/templates/test.rhtml +21 -0
- data/generators/view/templates/view.js +20 -0
- data/generators/view/view_generator.rb +51 -0
- data/jsdoc/README.txt +119 -0
- data/jsdoc/app/DocFile.js +137 -0
- data/jsdoc/app/DocTag.js +110 -0
- data/jsdoc/app/Doclet.js +63 -0
- data/jsdoc/app/Dumper.js +143 -0
- data/jsdoc/app/JsDoc.js +103 -0
- data/jsdoc/app/JsHilite.js +45 -0
- data/jsdoc/app/JsIO.js +163 -0
- data/jsdoc/app/JsParse.js +385 -0
- data/jsdoc/app/JsPlate.js +130 -0
- data/jsdoc/app/JsTestrun.js +129 -0
- data/jsdoc/app/JsToke.js +564 -0
- data/jsdoc/app/Symbol.js +298 -0
- data/jsdoc/app/Transformer.js +14 -0
- data/jsdoc/app/Util.js +97 -0
- data/jsdoc/app/js.jar +0 -0
- data/jsdoc/app/run.js +144 -0
- data/jsdoc/plugins/min.js +316 -0
- data/jsdoc/plugins/strip.js +20 -0
- data/jsdoc/templates/sproutcore/class.tmpl +438 -0
- data/jsdoc/templates/sproutcore/default.css +241 -0
- data/jsdoc/templates/sproutcore/index.html +13 -0
- data/jsdoc/templates/sproutcore/index.tmpl +21 -0
- data/jsdoc/templates/sproutcore/prototype.js +4186 -0
- data/jsdoc/templates/sproutcore/publish.js +236 -0
- data/jsdoc/templates/sproutcore/splash.html +7 -0
- data/lib/sproutcore/build_tools/html_builder.rb +88 -0
- data/lib/sproutcore/build_tools/resource_builder.rb +194 -0
- data/lib/sproutcore/build_tools.rb +44 -0
- data/lib/sproutcore/bundle.rb +517 -0
- data/lib/sproutcore/bundle_manifest.rb +397 -0
- data/lib/sproutcore/generator_helper.rb +170 -0
- data/lib/sproutcore/helpers/capture_helper.rb +42 -0
- data/lib/sproutcore/helpers/static_helper.rb +80 -0
- data/lib/sproutcore/helpers/tag_helper.rb +110 -0
- data/lib/sproutcore/helpers/text_helper.rb +336 -0
- data/lib/sproutcore/helpers.rb +3 -0
- data/lib/sproutcore/jsdoc.rb +40 -0
- data/lib/sproutcore/jsmin.rb +247 -0
- data/lib/sproutcore/library.rb +258 -0
- data/lib/sproutcore/merb/bundle_controller.rb +179 -0
- data/lib/sproutcore/merb/router.rb +43 -0
- data/lib/sproutcore/merb.rb +27 -0
- data/lib/sproutcore/version.rb +9 -0
- data/lib/sproutcore/view_helpers/button_views.rb +302 -0
- data/lib/sproutcore/view_helpers/core_views.rb +284 -0
- data/lib/sproutcore/view_helpers/form_views.rb +258 -0
- data/lib/sproutcore/view_helpers/menu_views.rb +94 -0
- data/lib/sproutcore/view_helpers.rb +628 -0
- data/lib/sproutcore.rb +30 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +74 -0
- data/setup.rb +1585 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/sproutcore_spec.rb +11 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/website.rake +17 -0
- metadata +365 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
// ========================================================================
|
|
2
|
+
// SproutCore
|
|
3
|
+
// copyright 2006-2007 Sprout Systems, Inc.
|
|
4
|
+
// ========================================================================
|
|
5
|
+
|
|
6
|
+
require('Core') ;
|
|
7
|
+
require('foundation/date');
|
|
8
|
+
require('foundation/string') ;
|
|
9
|
+
|
|
10
|
+
/** @namespace SC.Benchmark
|
|
11
|
+
|
|
12
|
+
This bit of meta-programming magic can install a benchmark handler on any
|
|
13
|
+
object method. When a benchmark is installed, the time required to execute
|
|
14
|
+
the method will be printed to the console log everytime the method is
|
|
15
|
+
called.
|
|
16
|
+
|
|
17
|
+
This class can be used to implement benchmarking. To use this object, just
|
|
18
|
+
call start() with a key name and end() with a keyname. The benchmark will
|
|
19
|
+
be logged. If you set verbose = true, then benchmark will log everytime it
|
|
20
|
+
saves a bench. Otherwise, it just keeps stats. You can get the stats by
|
|
21
|
+
calling report().
|
|
22
|
+
|
|
23
|
+
Benchmark does not require anything other than the date.js class. It also
|
|
24
|
+
does not rely on SC.Object so that you can benchmark code in that area as
|
|
25
|
+
well.
|
|
26
|
+
|
|
27
|
+
*/
|
|
28
|
+
SC.Benchmark = {
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
If true, then benchmarks will be logged to the console as they are
|
|
32
|
+
recorded.
|
|
33
|
+
|
|
34
|
+
@type bool
|
|
35
|
+
*/
|
|
36
|
+
verbose: NO,
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
If false, benchmarking will be disabled. You might want to disable this
|
|
40
|
+
during production to maximize performance.
|
|
41
|
+
|
|
42
|
+
@type bool
|
|
43
|
+
*/
|
|
44
|
+
enabled: YES,
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
This hash stores collected stats. It contains key value pairs. The value
|
|
48
|
+
will be a hash with the following properties:
|
|
49
|
+
|
|
50
|
+
* * *runs*: the number of times this stat has run
|
|
51
|
+
* * *amt*: the total time consumed by this (divide by runs to get avg)
|
|
52
|
+
* * *name*: an optional longer name you assigned to the stat key. Set this using name().
|
|
53
|
+
* * *_starts*: this array is used internally.
|
|
54
|
+
*/
|
|
55
|
+
stats: {},
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
Call this method at the start of whatever you want to collect.
|
|
59
|
+
if topLevelOnly is passed, then recursive calls to the start will be
|
|
60
|
+
ignored and only the top level call will be benchmarked.
|
|
61
|
+
*/
|
|
62
|
+
start: function(key, topLevelOnly) {
|
|
63
|
+
if (!this.enabled) return ;
|
|
64
|
+
var stat = this._statFor(key) ;
|
|
65
|
+
|
|
66
|
+
if (topLevelOnly && stat._starts.length > 0) {
|
|
67
|
+
stat._starts.push('ignore') ;
|
|
68
|
+
} else {
|
|
69
|
+
stat._starts.push(Date.now()) ;
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
Call this method at the end of whatever you want to collect. This will
|
|
75
|
+
save the collected benchmark.
|
|
76
|
+
*/
|
|
77
|
+
end: function(key) {
|
|
78
|
+
if (!this.enabled) return ;
|
|
79
|
+
var stat = this._statFor(key) ;
|
|
80
|
+
var start = stat._starts.pop() ;
|
|
81
|
+
if (!start) {
|
|
82
|
+
console.log('WARNING: SC.Benchmark "%@" ended without a matching start. No information was saved.'.fmt(key));
|
|
83
|
+
return ;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// top level only.
|
|
87
|
+
if (start == 'ignore') return ;
|
|
88
|
+
|
|
89
|
+
stat.amt += Date.now() - start ;
|
|
90
|
+
stat.runs++ ;
|
|
91
|
+
|
|
92
|
+
if (this.verbose) this.log(key) ;
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
This is a simple way to benchmark a function. The function will be
|
|
97
|
+
run with the name you provide the number of times you indicate. Only the
|
|
98
|
+
function is a required param.
|
|
99
|
+
*/
|
|
100
|
+
bench: function(func, key, reps) {
|
|
101
|
+
if (!key) key = "bench%@".fmt(this._benchCount++) ;
|
|
102
|
+
if (!reps) reps = 1 ;
|
|
103
|
+
var ret ;
|
|
104
|
+
|
|
105
|
+
while(--reps >= 0) {
|
|
106
|
+
SC.Benchmark.start(key) ;
|
|
107
|
+
ret = func();
|
|
108
|
+
SC.Benchmark.end(key) ;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return ret ;
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
This bit of metaprogramming magic install a wrapper around a method and
|
|
116
|
+
benchmark it whenever it is run.
|
|
117
|
+
*/
|
|
118
|
+
install: function(object,method, topLevelOnly) {
|
|
119
|
+
|
|
120
|
+
// vae the original method.
|
|
121
|
+
var __func = object['b__' + method] = object[method] ;
|
|
122
|
+
|
|
123
|
+
// replace with this helper.
|
|
124
|
+
object[method] = function() {
|
|
125
|
+
var key = '%@(%@)'.fmt(method, $A(arguments).join(', ')) ;
|
|
126
|
+
SC.Benchmark.start(key, topLevelOnly) ;
|
|
127
|
+
var ret = __func.apply(this, arguments) ;
|
|
128
|
+
SC.Benchmark.end(key) ;
|
|
129
|
+
return ret ;
|
|
130
|
+
} ;
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
Restore the original method, deactivating the benchmark.
|
|
135
|
+
|
|
136
|
+
@param {object} object the object to change
|
|
137
|
+
@param {string} method the method name as a string.
|
|
138
|
+
|
|
139
|
+
*/
|
|
140
|
+
restore: function(object,method) {
|
|
141
|
+
object[method] = object['b__' + method] ;
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
This method will return a string containing a report of the stats
|
|
146
|
+
collected so far. If you pass a key, only the stats for that key will
|
|
147
|
+
be returned. Otherwise, all keys will be used.
|
|
148
|
+
*/
|
|
149
|
+
report: function(key) {
|
|
150
|
+
if (key) return this._genReport(key) ;
|
|
151
|
+
var ret = [] ;
|
|
152
|
+
for(var key in this.stats) {
|
|
153
|
+
if (!this.stats.hasOwnProperty(key)) continue ;
|
|
154
|
+
ret.push(this._genReport(key)) ;
|
|
155
|
+
}
|
|
156
|
+
return ret.join("\n") ;
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
This method is just like report() except that it will log the results to
|
|
161
|
+
the console.
|
|
162
|
+
*/
|
|
163
|
+
log: function(key) {
|
|
164
|
+
console.log(this.report(key)) ;
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
This will activate profiling if you have Firebug installed. Otherwise
|
|
169
|
+
does nothing.
|
|
170
|
+
*/
|
|
171
|
+
startProfile: function(key) {
|
|
172
|
+
if (!this.enabled) return ;
|
|
173
|
+
if (console && console.profile) console.profile(key) ;
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
endProfile: function(key) {
|
|
177
|
+
if (!this.enabled) return ;
|
|
178
|
+
if (console && console.profileEnd) console.profileEnd(key) ;
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
// PRIVATE METHODS
|
|
182
|
+
|
|
183
|
+
_genReport: function(key) {
|
|
184
|
+
var stat = this._statFor(key) ;
|
|
185
|
+
var avg = (stat.runs > 0) ? (Math.floor(stat.amt * 1000 / stat.runs) / 1000) : 0 ;
|
|
186
|
+
|
|
187
|
+
return 'BENCH %@ msec: %@ (%@x)'.fmt(avg, (stat.name || key), stat.runs) ;
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
// @private
|
|
191
|
+
// returns a stats hash for the named key. If the hash does not exist yet,
|
|
192
|
+
// creates it.
|
|
193
|
+
_statFor: function(key) {
|
|
194
|
+
var ret = this.stats[key] ;
|
|
195
|
+
if (!ret) ret = this.stats[key] = {
|
|
196
|
+
runs: 0, amt: 0, name: key, _starts: []
|
|
197
|
+
};
|
|
198
|
+
return ret ;
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
reset: function() { this.stats = {} ; },
|
|
202
|
+
|
|
203
|
+
// This is private, but it is used in some places, so we are keeping this for
|
|
204
|
+
// compatibility.
|
|
205
|
+
_bench: function(func, name) {
|
|
206
|
+
SC.Benchmark.bench(func, name, 1) ;
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
_benchCount: 1
|
|
210
|
+
|
|
211
|
+
} ;
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
// ========================================================================
|
|
2
|
+
// SproutCore
|
|
3
|
+
// copyright 2006-2007 Sprout Systems, Inc.
|
|
4
|
+
// ========================================================================
|
|
5
|
+
|
|
6
|
+
require('foundation/object') ;
|
|
7
|
+
|
|
8
|
+
// A relay simply allows you to connect the properties of two objects.
|
|
9
|
+
// Whenever the value of one property changes, the value of the other
|
|
10
|
+
// property will change also. This allows you to design your system more
|
|
11
|
+
// modular.
|
|
12
|
+
//
|
|
13
|
+
// You can also configure a relay to be one way so only the from -> to path
|
|
14
|
+
// changes are permitted. We will also allow transforms and placeholder values
|
|
15
|
+
// eventually.
|
|
16
|
+
|
|
17
|
+
SC.Binding = SC.Object.extend({
|
|
18
|
+
|
|
19
|
+
// ......................................
|
|
20
|
+
// PROPERTIES
|
|
21
|
+
// Configure these on setup. They should be either tuples or property
|
|
22
|
+
// paths. The relay will try to observe both of them.
|
|
23
|
+
from: '', to: '',
|
|
24
|
+
|
|
25
|
+
// set to true if you don't want changes to -> from to relay.
|
|
26
|
+
oneWay: false,
|
|
27
|
+
|
|
28
|
+
// set this to some value if you want a placeholder when the source
|
|
29
|
+
// value is an empty array or null (if you don't also set a nullPlaceholder)
|
|
30
|
+
emptyPlaceholder: null,
|
|
31
|
+
|
|
32
|
+
// set this to some value if you want a placeholder value when the source
|
|
33
|
+
// value is null. If you don't set this but you do set an emptyPlaceholder
|
|
34
|
+
// then the emptyPlaceholder will be used instead.
|
|
35
|
+
nullPlaceholder: null,
|
|
36
|
+
|
|
37
|
+
// set this to some value if you want a placeholder when the value is
|
|
38
|
+
// an array with multiple values. If you set this, arrays with single
|
|
39
|
+
// values will be converted to indivdual objects. If this is set ot null,
|
|
40
|
+
// multiple values will be allowed to pass untouched.
|
|
41
|
+
multiplePlaceholder: null,
|
|
42
|
+
|
|
43
|
+
// set this to a function if you want a transform performed on an input
|
|
44
|
+
// value. This transform is performed both ways and before placeholder
|
|
45
|
+
// values are applied.
|
|
46
|
+
transform: null,
|
|
47
|
+
|
|
48
|
+
// ......................................
|
|
49
|
+
// METHODS
|
|
50
|
+
|
|
51
|
+
// This will connect the relay so that properties can be forwarded. If
|
|
52
|
+
// the items are already connected, this has no effect.
|
|
53
|
+
connect: function() {
|
|
54
|
+
if (this._connected) return ;
|
|
55
|
+
var funcs = this._boundObservers() ;
|
|
56
|
+
|
|
57
|
+
SC.Observers.addObserver(this.get('from'),funcs.from) ;
|
|
58
|
+
SC.Observers.addObserver(this.get('to'),funcs.to) ;
|
|
59
|
+
this._connected = true ;
|
|
60
|
+
return this ;
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
// this will disconnect the relay from its observing. Call this if you
|
|
64
|
+
// want to destroy the relay. This returns null so you can use it in
|
|
65
|
+
// assignment.
|
|
66
|
+
disconnect: function() {
|
|
67
|
+
if (!this._connected) return ;
|
|
68
|
+
var funcs = this._boundObservers() ;
|
|
69
|
+
SC.Observers.removeObserver(this.get('from'),funcs.from) ;
|
|
70
|
+
SC.Observers.removeObserver(this.get('to'),funcs.to) ;
|
|
71
|
+
this._connected = false ;
|
|
72
|
+
return this ;
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
// simulate a from -> to relay.
|
|
76
|
+
relay: function() {
|
|
77
|
+
var tuple = SC.Object.tupleForPropertyPath(this.get('from')) ;
|
|
78
|
+
if (tuple) tuple = this._walkTuple(tuple) ;
|
|
79
|
+
if (tuple) this._fromObserver(tuple[0],tuple[1],tuple[0].get(tuple[1]));
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
// ......................................
|
|
83
|
+
// INTERNAL METHODS
|
|
84
|
+
|
|
85
|
+
init: function() {
|
|
86
|
+
arguments.callee.base.call(this) ;
|
|
87
|
+
this.connect() ;
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
_boundObservers: function() {
|
|
91
|
+
var ret = this._boundObserverFuncs ;
|
|
92
|
+
if (!ret) {
|
|
93
|
+
this._boundObserverFuncs = ret = {
|
|
94
|
+
from: this._fromObserver.bind(this),
|
|
95
|
+
to: this._toObserver.bind(this)
|
|
96
|
+
} ;
|
|
97
|
+
}
|
|
98
|
+
return ret ;
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
_fromObserver: function(target,key,value, propertyRevision) {
|
|
102
|
+
// to avoid echos, check against last toProperty revision.
|
|
103
|
+
if (propertyRevision <= this._lastFromPropertyRevision) return ;
|
|
104
|
+
this._lastFromPropertyRevision = propertyRevision ;
|
|
105
|
+
|
|
106
|
+
// no need to forward values if they haven't actually changed.
|
|
107
|
+
if (!this._didChange(this._lastFromValue,value)) return ;
|
|
108
|
+
this._lastFromValue = value ;
|
|
109
|
+
|
|
110
|
+
// try to get the to object.
|
|
111
|
+
var tuple = SC.Object.tupleForPropertyPath(this.get('to')) ;
|
|
112
|
+
if (tuple) tuple = this._walkTuple(tuple) ;
|
|
113
|
+
if (tuple) {
|
|
114
|
+
|
|
115
|
+
// transform the value
|
|
116
|
+
var transformFunc = this.transform ;
|
|
117
|
+
if (transformFunc) value = transformFunc('to', key, value) ;
|
|
118
|
+
this._lastToValue = value ;
|
|
119
|
+
|
|
120
|
+
// apply placeholder settings.
|
|
121
|
+
var pholder ;
|
|
122
|
+
|
|
123
|
+
// handle empty placeholder.
|
|
124
|
+
if (value && (value == []) && (pholder = this.get('emptyPlaceholder'))) {
|
|
125
|
+
value = pholder ;
|
|
126
|
+
|
|
127
|
+
// handle multiple value placeholder
|
|
128
|
+
} else if (value && (value instanceof Array) && (pholder = this.get('multiplePlaceholder'))) {
|
|
129
|
+
value = (value.length == 1) ? value[0] : pholder ;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// now handle null placeholder. This is used if one of these other
|
|
133
|
+
// transforms results in a null value.
|
|
134
|
+
if ((value == null) && (pholder = this.get('nullPlaceholder') || this.get('emptyPlaceholder'))) {
|
|
135
|
+
value = pholder ;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
tuple[0].set(tuple[1],value) ;
|
|
139
|
+
this._lastToPropertyRevision = tuple[0].propertyRevision ;
|
|
140
|
+
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
_toObserver: function(target,key,value, propertyRevision) {
|
|
145
|
+
// try to get the to object.
|
|
146
|
+
if (this.get('oneWay')) return ; // block.
|
|
147
|
+
|
|
148
|
+
// to avoid echos, check against last toProperty revision.
|
|
149
|
+
if (propertyRevision <= this._lastToPropertyRevision) return ;
|
|
150
|
+
this._lastToPropertyRevision = propertyRevision ;
|
|
151
|
+
|
|
152
|
+
// no need to forward values if they haven't actually changed.
|
|
153
|
+
if (!this._didChange(this._lastToValue,value)) return ;
|
|
154
|
+
this._lastToValue = value ;
|
|
155
|
+
|
|
156
|
+
var tuple = SC.Object.tupleForPropertyPath(this.get('from')) ;
|
|
157
|
+
if (tuple) tuple = this._walkTuple(tuple) ;
|
|
158
|
+
if (tuple) {
|
|
159
|
+
// transform the value
|
|
160
|
+
var transformFunc = this.get('transform') ;
|
|
161
|
+
if (transformFunc) value = transformFunc('from', key, value) ;
|
|
162
|
+
this._lastFromValue = value ;
|
|
163
|
+
|
|
164
|
+
// send along to the 'from' source.
|
|
165
|
+
var result = tuple[0].set(tuple[1],value) ;
|
|
166
|
+
if (result) this._lastFromPropertyRevision = result.propertyRevision ;
|
|
167
|
+
|
|
168
|
+
// now that it has been set, the FROM object might not allow some
|
|
169
|
+
// changes. If that is the case, then we need to set this back on the
|
|
170
|
+
// sender.
|
|
171
|
+
if (result != value) {
|
|
172
|
+
target.set(key,result) ;
|
|
173
|
+
this._lastToPropertyRevision = target.propertyRevision ;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
_didChange: function(lastValue, newValue) {
|
|
180
|
+
if (newValue && lastValue) {
|
|
181
|
+
if (typeof(newValue) == typeof(lastValue)) {
|
|
182
|
+
if (lastValue == newValue) return false ;
|
|
183
|
+
}
|
|
184
|
+
} else if (((newValue === null) && (lastValue === null)) || ((newValue === undefined) && (lastValue === undefined))) return false ;
|
|
185
|
+
return true ;
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
_lastToPropertyRevision: 0,
|
|
189
|
+
_lastFromPropertyRevision: 0,
|
|
190
|
+
|
|
191
|
+
_walkTuple: function(tuple) {
|
|
192
|
+
var parts = tuple[1].split('.') ;
|
|
193
|
+
if (parts.length > 1) {
|
|
194
|
+
tuple = tuple.slice() ; // duplicate to avoid an error.
|
|
195
|
+
var obj = tuple[0] ;
|
|
196
|
+
tuple[1] = parts.pop() ;
|
|
197
|
+
for(var loc=0;(obj && (loc<parts.length));loc++) {
|
|
198
|
+
obj = obj.get(parts[loc]) ;
|
|
199
|
+
}
|
|
200
|
+
tuple[0] = obj ;
|
|
201
|
+
}
|
|
202
|
+
return (tuple[0] && tuple[1]) ? tuple : null ;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
}) ;
|
|
206
|
+
|
|
207
|
+
SC.Binding.mixin({
|
|
208
|
+
// Constant values for placeholders
|
|
209
|
+
MULTIPLE_PLACEHOLDER: '@@MULT@@',
|
|
210
|
+
NULL_PLACEHOLDER: '@@NULL@@',
|
|
211
|
+
EMPTY_PLACEHOLDER: '@@EMPTY@@'
|
|
212
|
+
}) ;
|
|
213
|
+
|
|
214
|
+
// This is the basic method you can use to create a builder function for
|
|
215
|
+
// different types of relays. The first param is either a string or a set
|
|
216
|
+
// of properties. The second param is a set of properties. Both are opt.
|
|
217
|
+
SC.Binding.From = function(from,opts) {
|
|
218
|
+
if (!opts) opts = {} ;
|
|
219
|
+
if ((typeof(from) == "string") || (from instanceof Array)) {
|
|
220
|
+
opts.from = from ;
|
|
221
|
+
} else Object.extend(opts,from) ;
|
|
222
|
+
var ret = SC.Binding.extend(opts) ;
|
|
223
|
+
return ret ;
|
|
224
|
+
} ;
|
|
225
|
+
|
|
226
|
+
SC.Binding.build = function(tr) {
|
|
227
|
+
return function(from) {
|
|
228
|
+
return SC.Binding.From(from,{ transform: tr }) ;
|
|
229
|
+
} ;
|
|
230
|
+
} ;
|
|
231
|
+
|
|
232
|
+
SC.Binding.NoChange = SC.Binding.From;
|
|
233
|
+
|
|
234
|
+
// This binding will return errors as null.
|
|
235
|
+
SC.Binding.NoError = SC.Binding.build(function(dir, key, value) {
|
|
236
|
+
return ($type(value) == T_ERROR) ? null : value ;
|
|
237
|
+
}) ;
|
|
238
|
+
|
|
239
|
+
SC.Binding.NoError.ext = function(bindFunc) {
|
|
240
|
+
return function(d,k,v) {
|
|
241
|
+
return ($type(value) == T_ERROR) ? null : bindFunc(d,k,v) ;
|
|
242
|
+
} ;
|
|
243
|
+
} ;
|
|
244
|
+
|
|
245
|
+
// This binding only allows single, null, or error values. If an array is
|
|
246
|
+
// passed, it will be mapped like so:
|
|
247
|
+
//
|
|
248
|
+
// [] => null
|
|
249
|
+
// [x] => x
|
|
250
|
+
// [x,x,x] => MULTIPLE_PLACEHOLDER
|
|
251
|
+
//
|
|
252
|
+
SC.Binding.Single = SC.Binding.build(function(d,k,v) {
|
|
253
|
+
if ($type(v) == T_ARRAY) {
|
|
254
|
+
switch(v.length) {
|
|
255
|
+
case 0:
|
|
256
|
+
v = null ;
|
|
257
|
+
break ;
|
|
258
|
+
case 1:
|
|
259
|
+
v = v[0] ;
|
|
260
|
+
break ;
|
|
261
|
+
default:
|
|
262
|
+
v = SC.Binding.MULTIPLE_PLACEHOLDER ;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return v;
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// This binding works just like Single except if you pass a multiple value
|
|
269
|
+
// it will be converted to NULL.
|
|
270
|
+
SC.Binding.SingleNull = SC.Binding.build(function(d,k,v) {
|
|
271
|
+
if ($type(v) == T_ARRAY) {
|
|
272
|
+
switch(v.length) {
|
|
273
|
+
case 0:
|
|
274
|
+
v = null ;
|
|
275
|
+
break ;
|
|
276
|
+
case 1:
|
|
277
|
+
v = v[0] ;
|
|
278
|
+
break ;
|
|
279
|
+
default:
|
|
280
|
+
v = null ;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return v;
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// NoError versions.
|
|
287
|
+
SC.Binding.SingleNoError = SC.Binding.NoError.ext(SC.Binding.Single);
|
|
288
|
+
SC.Binding.SingleNullNoError = SC.Binding.NoError.ext(SC.Binding.SingleNull);
|
|
289
|
+
|
|
290
|
+
// This requires the value to be a multiple. null => [], x => [x]
|
|
291
|
+
SC.Binding.Multiple = SC.Binding.build(function(d,k,v) {
|
|
292
|
+
var t = $type(v) ;
|
|
293
|
+
if (t != T_ARRAY) {
|
|
294
|
+
if (t == null) {
|
|
295
|
+
v = [] ;
|
|
296
|
+
} else if (t != T_ERROR) {
|
|
297
|
+
v = [v] ;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return v ;
|
|
301
|
+
}) ;
|
|
302
|
+
|
|
303
|
+
SC.Binding.MultipleNoError = SC.Binding.NoError.ext(SC.Binding.Multiple);
|
|
304
|
+
|
|
305
|
+
// Converts value to a bool. true if: not null, not empty array, not 0, '',
|
|
306
|
+
// etc.
|
|
307
|
+
SC.Binding.Bool = SC.Binding.build(function(d,k,v) {
|
|
308
|
+
return ($type(v) == T_ARRAY) ? (t.length > 0) : !!v ;
|
|
309
|
+
}) ;
|
|
310
|
+
|
|
311
|
+
// Converts value to a bool, but its only true if not null
|
|
312
|
+
SC.Binding.NotNull = SC.Binding.build(function(d,k,v) {
|
|
313
|
+
return (v != null) ;
|
|
314
|
+
}) ;
|
|
315
|
+
|
|
316
|
+
// Converts inverse of bool.
|
|
317
|
+
SC.Binding.Not = SC.Binding.build(function(d,k,v) {
|
|
318
|
+
return !(($type(v) == T_ARRAY) ? (t.length > 0) : !!v) ;
|
|
319
|
+
}) ;
|
|
320
|
+
|
|
321
|
+
// Converts value to a bool, but its only true if not null
|
|
322
|
+
SC.Binding.IsNull = SC.Binding.build(function(d,k,v) {
|
|
323
|
+
return (v == null) ;
|
|
324
|
+
}) ;
|
|
325
|
+
|
|
326
|
+
// No Error versions.
|
|
327
|
+
SC.Binding.BoolNoError = SC.Binding.NoError.ext(SC.Binding.Bool) ;
|
|
328
|
+
SC.Binding.NotNullNoError = SC.Binding.NoError.ext(SC.Binding.NotNull) ;
|
|
329
|
+
SC.Binding.NotNoError = SC.Binding.NoError.ext(SC.Binding.Not) ;
|
|
330
|
+
SC.Binding.IsNullNoError = SC.Binding.NoError.ext(SC.Binding.IsNull) ;
|
|
331
|
+
|
|
332
|
+
// .........................................................
|
|
333
|
+
// DEPRECATED
|
|
334
|
+
|
|
335
|
+
// This relay forces all values to be multiple values
|
|
336
|
+
SC.Binding.Multiple = function(from) {
|
|
337
|
+
return SC.Binding.From(from,{
|
|
338
|
+
transform: function(dir,key,value) {
|
|
339
|
+
return (value) ? (SC.isArray(value) ? value : [value]) : value;
|
|
340
|
+
}
|
|
341
|
+
}) ;
|
|
342
|
+
} ;
|
|
343
|
+
|
|
344
|
+
// This relay forces all values to be multiple values, null values are not
|
|
345
|
+
// allowed.
|
|
346
|
+
SC.Binding.MultipleNotEmpty = function(from) {
|
|
347
|
+
return SC.Binding.From(from,{
|
|
348
|
+
transform: function(dir,key,value) {
|
|
349
|
+
return (value) ? (SC.isArray(value) ? value : [value]) : [];
|
|
350
|
+
}
|
|
351
|
+
}) ;
|
|
352
|
+
} ;
|
|
353
|
+
|
|
354
|
+
// This relay allows single values and no null/empty values.
|
|
355
|
+
SC.Binding.SingleNotEmpty = function(from) {
|
|
356
|
+
return SC.Binding.From(from,{
|
|
357
|
+
multiplePlaceholder: SC.Binding.MULTIPLE_PLACEHOLDER,
|
|
358
|
+
emptyPlaceholder: SC.Binding.EMPTY_PLACEHOLDER,
|
|
359
|
+
nullPlaceholder: SC.Binding.NULL_PLACEHOLDER
|
|
360
|
+
}) ;
|
|
361
|
+
} ;
|
|
362
|
+
|
|
363
|
+
// This relay allows any values, but only one way flow.
|
|
364
|
+
SC.Binding.OneWay = function(from) {
|
|
365
|
+
return SC.Binding.From(from, { oneWay: true }) ;
|
|
366
|
+
} ;
|
|
367
|
+
|
|
368
|
+
// This relay forces the value to be true or false. Empty and null values
|
|
369
|
+
// represent false.
|
|
370
|
+
SC.Binding.Flag = function(from) {
|
|
371
|
+
return SC.Binding.From(from, {
|
|
372
|
+
transform: function(dir,key,value) {
|
|
373
|
+
return (value && (value instanceof Array)) ? (value.length == 0) : !!value ;
|
|
374
|
+
}
|
|
375
|
+
}) ;
|
|
376
|
+
} ;
|
|
377
|
+
|
|
378
|
+
SC.Binding.OneWayFlag = function(from) {
|
|
379
|
+
var ret = SC.Binding.Flag(from) ;
|
|
380
|
+
ret.oneWay = true ;
|
|
381
|
+
return ret ;
|
|
382
|
+
} ;
|
|
383
|
+
|
|
384
|
+
|