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,295 @@
|
|
|
1
|
+
// ========================================================================
|
|
2
|
+
// SproutCore
|
|
3
|
+
// copyright 2006-2007 Sprout Systems, Inc.
|
|
4
|
+
// ========================================================================
|
|
5
|
+
|
|
6
|
+
require('foundation/object') ;
|
|
7
|
+
|
|
8
|
+
// The Store is where you can find all of your records. You should also
|
|
9
|
+
// use this to define your various types of records, since this will be
|
|
10
|
+
// used to automatically update from data coming from the server.
|
|
11
|
+
//
|
|
12
|
+
// You should create a store for each application. This allows the records
|
|
13
|
+
// for apps to be kept separate, even if they live in the same page.
|
|
14
|
+
//
|
|
15
|
+
SC.Store = SC.Object.create({
|
|
16
|
+
|
|
17
|
+
// This can be passed in from a Server to push updated data to all the
|
|
18
|
+
// named records. The parameter should be an array of hashes. Each hash
|
|
19
|
+
// can contain arrays or strings. Each one should also have a recordType
|
|
20
|
+
// property, which points to the record type. dataSource is the server.
|
|
21
|
+
// this will be automatically set on all the objects so that their future
|
|
22
|
+
// refreshes will come from the server.
|
|
23
|
+
updateRecords: function(dataHashes, dataSource, recordType, isLoaded) {
|
|
24
|
+
|
|
25
|
+
this.set('updateRecordsInProgress',true) ;
|
|
26
|
+
var store = this ;
|
|
27
|
+
var ret = [] ;
|
|
28
|
+
if (!recordType) recordType = SC.Record ;
|
|
29
|
+
this.beginPropertyChanges() ;
|
|
30
|
+
|
|
31
|
+
//SC.Benchmark._bench(function() {
|
|
32
|
+
dataHashes.each(function(data) {
|
|
33
|
+
var rt = data.recordType || recordType;
|
|
34
|
+
if (data.recordType !== undefined) delete data.recordType;
|
|
35
|
+
|
|
36
|
+
var pkValue = data[rt.primaryKey()] ;
|
|
37
|
+
var rec = store.getRecordFor(pkValue,rt,true) ;
|
|
38
|
+
rec.dataSource = dataSource ;
|
|
39
|
+
rec.updateAttributes(data, isLoaded, isLoaded) ;
|
|
40
|
+
if (rec.needsAddToStore) store.addRecord(rec) ;
|
|
41
|
+
ret.push(rec) ;
|
|
42
|
+
});
|
|
43
|
+
// },'dataHashes') ;
|
|
44
|
+
|
|
45
|
+
this.endPropertyChanges() ;
|
|
46
|
+
this.set('updateRecordsInProgress',false) ;
|
|
47
|
+
return ret ;
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
// ....................................
|
|
51
|
+
// Record dataSource methods
|
|
52
|
+
//
|
|
53
|
+
|
|
54
|
+
refreshRecords: function(records) {},
|
|
55
|
+
|
|
56
|
+
createRecords: function(recs) {
|
|
57
|
+
recs.invoke('set','newRecord','false') ;
|
|
58
|
+
this.commitRecords(recs);
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
commitRecords: function(recs) { recs.invoke('set','isDirty','false'); },
|
|
62
|
+
|
|
63
|
+
destroyRecords: function(recs) {
|
|
64
|
+
var store = this ;
|
|
65
|
+
recs.each(function(r) {
|
|
66
|
+
r.set('isDeleted',true); store.removeRecord(r);
|
|
67
|
+
});
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
// ....................................
|
|
71
|
+
// Record Helpers
|
|
72
|
+
//
|
|
73
|
+
|
|
74
|
+
// add a record instance to the store. The record will now be monitored for
|
|
75
|
+
// changes.
|
|
76
|
+
addRecord: function(rec) {
|
|
77
|
+
// save record in a cache
|
|
78
|
+
rec.needsAddToStore = false;
|
|
79
|
+
var guid = rec._storeKey();
|
|
80
|
+
var records = this._records[guid] || [];
|
|
81
|
+
records.push(rec);
|
|
82
|
+
this._records[guid] = records;
|
|
83
|
+
|
|
84
|
+
// global record cache
|
|
85
|
+
if (!this._quickCache) this._quickCache = {};
|
|
86
|
+
|
|
87
|
+
// records are cached by Class type
|
|
88
|
+
var records = this._quickCache[guid] || {};
|
|
89
|
+
var pkey = rec.get(rec.primaryKey);
|
|
90
|
+
records[pkey] = rec;
|
|
91
|
+
this._quickCache[guid] = records;
|
|
92
|
+
|
|
93
|
+
// and start observing it.
|
|
94
|
+
rec.addObserver('*',this._boundRecordObserver) ;
|
|
95
|
+
this.recordDidChange(rec) ;
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
// remove a record instance from the store. The record will no longer be
|
|
99
|
+
// monitored for changes and may be deleted.
|
|
100
|
+
removeRecord: function(rec) {
|
|
101
|
+
// remove from cache
|
|
102
|
+
var guid = rec._storeKey();
|
|
103
|
+
var records = this._records[guid] || [];
|
|
104
|
+
records = records.without(rec);
|
|
105
|
+
this._records[guid] = records;
|
|
106
|
+
|
|
107
|
+
// remove from quick cache
|
|
108
|
+
if (this._quickCache)
|
|
109
|
+
{
|
|
110
|
+
var records = this._quickCache[guid] || {};
|
|
111
|
+
var pkey = rec.get(rec.primaryKey);
|
|
112
|
+
delete records[pkey];
|
|
113
|
+
this._quickCache[guid] = records;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// and stop observing it.
|
|
117
|
+
rec.removeObserver('*',this._boundRecordObserver) ;
|
|
118
|
+
this.recordDidChange(rec) ; // this will remove from cols since destroyed.
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Since records are cached by primaryKey, whenever that key changes we need to re-cache it in the proper place
|
|
123
|
+
* @param {string} oldkey Previous primary key
|
|
124
|
+
* @param {string} newkey New primary key
|
|
125
|
+
* @param {SC.Record} rec The object to relocate
|
|
126
|
+
* @return {SC.Record} The record passed in
|
|
127
|
+
**/
|
|
128
|
+
relocateRecord: function( oldkey, newkey, rec )
|
|
129
|
+
{
|
|
130
|
+
if (!this._quickCache) return rec;
|
|
131
|
+
|
|
132
|
+
var classKey = rec._storeKey();
|
|
133
|
+
var records = this._quickCache[classKey] || {};
|
|
134
|
+
|
|
135
|
+
records[newkey] = rec;
|
|
136
|
+
delete records[oldkey];
|
|
137
|
+
|
|
138
|
+
this._quickCache[classKey] = records;
|
|
139
|
+
|
|
140
|
+
return rec;
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
// You can pass any number of condition hashes to this, ending with a
|
|
145
|
+
// recordType. It will AND the results of each condition hash.
|
|
146
|
+
findRecords: function() {
|
|
147
|
+
var allConditions = $A(arguments) ;
|
|
148
|
+
var recordType = allConditions.pop() ;
|
|
149
|
+
var guid = recordType._storeKey() ;
|
|
150
|
+
|
|
151
|
+
// initial set of records.
|
|
152
|
+
var records = this._records[guid] ;
|
|
153
|
+
|
|
154
|
+
while(allConditions.length > 0) {
|
|
155
|
+
var conditions = allConditions.pop() ;
|
|
156
|
+
var ret = [] ; var loc = (records) ? records.length : 0;
|
|
157
|
+
while(--loc >= 0) {
|
|
158
|
+
var rec = records[loc] ;
|
|
159
|
+
if ((rec._type == recordType) || (rec._type.coreRecordType == recordType)) {
|
|
160
|
+
if (rec.matchConditions(conditions)) ret.push(rec) ;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
records = ret ;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return records ;
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
// private method used by Record and Store. Returns null if the record does not exist.
|
|
170
|
+
_getRecordFor: function(pkValue,recordType) {
|
|
171
|
+
var guid = recordType._storeKey() ;
|
|
172
|
+
var records = (this._quickCache) ? this._quickCache[guid] : null;
|
|
173
|
+
var ret = (records) ? records[pkValue] : null ;
|
|
174
|
+
return ret ;
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
// finds the record with the primary key value. If the record does not
|
|
178
|
+
// exist, creates it.
|
|
179
|
+
getRecordFor: function(pkValue,recordType,dontAutoaddRecord) {
|
|
180
|
+
var ret = this._getRecordFor(pkValue,recordType) ;
|
|
181
|
+
if (!ret) {
|
|
182
|
+
var opts = {}; opts[recordType.primaryKey()] = pkValue;
|
|
183
|
+
ret = recordType.create(opts) ;
|
|
184
|
+
if (dontAutoaddRecord) {
|
|
185
|
+
ret.needsAddToStore = true ;
|
|
186
|
+
} else this.addRecord(ret) ;
|
|
187
|
+
}
|
|
188
|
+
return ret ;
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
// ....................................
|
|
192
|
+
// Collection Helpers
|
|
193
|
+
//
|
|
194
|
+
|
|
195
|
+
addCollection: function(collection) {
|
|
196
|
+
var guid = collection.recordType._storeKey() ;
|
|
197
|
+
var collections = this._collections[guid] || [] ;
|
|
198
|
+
collections.push(collection) ;
|
|
199
|
+
this._collections[guid] = collections ;
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
removeCollection: function(collection) {
|
|
203
|
+
var guid = collection.recordType._storeKey() ;
|
|
204
|
+
var collections = this._collections[guid] || [] ;
|
|
205
|
+
collections = collections.without(collection) ;
|
|
206
|
+
this._collections[guid] = collections ;
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
listFor: function(opts) {
|
|
210
|
+
var conditions = opts.conditions || {} ;
|
|
211
|
+
var order = opts.order || ['guid'] ;
|
|
212
|
+
var records = this.findRecords(conditions,opts.recordType) ;
|
|
213
|
+
var count = records.length ;
|
|
214
|
+
|
|
215
|
+
// sort
|
|
216
|
+
records = records.sort(function(a,b) { return a.compareTo(b,order); }) ;
|
|
217
|
+
|
|
218
|
+
// slice if needed.
|
|
219
|
+
if (opts.limit && (opts.limit > 0)) {
|
|
220
|
+
var start = (opts.offset) ? opts.offset : 0 ;
|
|
221
|
+
var end = start + opts.limit ;
|
|
222
|
+
records = records.slice(start,end) ;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// now run callback.
|
|
226
|
+
if (opts.callback) opts.callback(records,count) ;
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
// ....................................
|
|
230
|
+
// PRIVATE
|
|
231
|
+
//
|
|
232
|
+
_records: {}, _changedRecords: null, _collections: {},
|
|
233
|
+
|
|
234
|
+
// called whenever properties on a record change.
|
|
235
|
+
recordDidChange: function(rec) {
|
|
236
|
+
// add to changed records. This will eventually notify collections.
|
|
237
|
+
var guid = rec._storeKey() ;
|
|
238
|
+
changed = this.get('_changedRecords') || {};
|
|
239
|
+
records = changed[guid] || {} ;
|
|
240
|
+
records[rec._guid] = rec ;
|
|
241
|
+
|
|
242
|
+
changed[guid] = records ;
|
|
243
|
+
this.set('_changedRecords',changed) ;
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
// invoked whenever the changedRecords hash is updated. This will notify
|
|
247
|
+
// collections.
|
|
248
|
+
_changedRecordsObserver: function() {
|
|
249
|
+
// process changedRecords to notify collections.
|
|
250
|
+
for(var guid in this._changedRecords) {
|
|
251
|
+
var collections = this._collections[guid] ;
|
|
252
|
+
if (collections && collections.length>0) {
|
|
253
|
+
|
|
254
|
+
// collect records into array. Faster than using uniq.
|
|
255
|
+
var records = [] ;
|
|
256
|
+
for(var key in this._changedRecords[guid]) {
|
|
257
|
+
records.push(this._changedRecords[guid][key]) ;
|
|
258
|
+
}
|
|
259
|
+
var cloc = collections.length ;
|
|
260
|
+
while(--cloc >= 0) {
|
|
261
|
+
|
|
262
|
+
// for each collection watching this type of record, notify.
|
|
263
|
+
var col = collections[cloc] ;
|
|
264
|
+
col.beginPropertyChanges() ;
|
|
265
|
+
try {
|
|
266
|
+
// for each record...
|
|
267
|
+
var rloc = records.length ;
|
|
268
|
+
while(--rloc >= 0) {
|
|
269
|
+
var record = records[rloc] ;
|
|
270
|
+
// notify only if record type matches.
|
|
271
|
+
if (col.recordType == record._type) {
|
|
272
|
+
col.recordDidChange(record) ;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
catch (e) {
|
|
277
|
+
console.log('EXCEPTION: While notifying collection') ;
|
|
278
|
+
}
|
|
279
|
+
col.endPropertyChanges() ;
|
|
280
|
+
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// then clear changed records to start again.
|
|
286
|
+
this._changedRecords = {} ;
|
|
287
|
+
|
|
288
|
+
}.observes('_changedRecords'),
|
|
289
|
+
|
|
290
|
+
init: function() {
|
|
291
|
+
arguments.callee.base.call(this) ;
|
|
292
|
+
this._boundRecordObserver = this.recordDidChange.bind(this) ;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
}) ;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// ========================================================================
|
|
2
|
+
// SproutCore
|
|
3
|
+
// copyright 2006-2007 Sprout Systems, Inc.
|
|
4
|
+
// ========================================================================
|
|
5
|
+
|
|
6
|
+
require('panes/overlay') ;
|
|
7
|
+
|
|
8
|
+
SC.DIALOG_PANE = 'dialog';
|
|
9
|
+
SC.DialogPaneView = SC.OverlayPaneView.extend({
|
|
10
|
+
|
|
11
|
+
emptyElement: '<div class="pane dialog-pane"><div class="pane-wrapper"><div class="pane-root"></div></div>',
|
|
12
|
+
|
|
13
|
+
layer: 200
|
|
14
|
+
|
|
15
|
+
}) ;
|
|
16
|
+
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// ========================================================================
|
|
2
|
+
// SproutCore
|
|
3
|
+
// copyright 2006-2007 Sprout Systems, Inc.
|
|
4
|
+
// ========================================================================
|
|
5
|
+
|
|
6
|
+
require('views/view') ;
|
|
7
|
+
|
|
8
|
+
// The PaneManager is responsible for displaying pane that appear over your
|
|
9
|
+
// regular content. You can register your own pane types by calling
|
|
10
|
+
// PaneManager.registerPane('type',PaneClass) on app load.
|
|
11
|
+
//
|
|
12
|
+
// One instance of the PaneManager view is created the first time you try
|
|
13
|
+
// to show a pane.
|
|
14
|
+
SC.PaneManager = SC.View.extend({
|
|
15
|
+
|
|
16
|
+
emptyElement: '<div id="panes"></div>',
|
|
17
|
+
|
|
18
|
+
// this method will show a pane. Pass the content view and the paneType.
|
|
19
|
+
// if the pane is already visible, it will be hidden first. The optional
|
|
20
|
+
// event and root element will be set as properties on the wrapper pane
|
|
21
|
+
// before the pane is made visible so that it can position itself.
|
|
22
|
+
showPaneView: function(view, paneType, anchorView, triggerEvent) {
|
|
23
|
+
|
|
24
|
+
// if pane is already showing, hide the pane first...
|
|
25
|
+
this.hidePaneView(view) ;
|
|
26
|
+
|
|
27
|
+
// now get a pane instance for the specified paneType and add view to it.
|
|
28
|
+
var pane = this.getPaneFor(paneType) ;
|
|
29
|
+
pane._managedPaneType = paneType ;
|
|
30
|
+
pane.set('anchorView',anchorView) ;
|
|
31
|
+
pane.set('triggerEvent',triggerEvent) ;
|
|
32
|
+
pane.set('isVisible', false) ;
|
|
33
|
+
this._visiblePanes[view._guid] = pane ;
|
|
34
|
+
|
|
35
|
+
// look through child views (which are panes). Insert before first pane
|
|
36
|
+
// with a layer value > this pane.
|
|
37
|
+
var child= this.get('firstChild') ;
|
|
38
|
+
var layer = pane.get('layer');
|
|
39
|
+
while(child && (child.get('layer') <= layer)) {
|
|
40
|
+
child = child.get('nextSibling');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
this.insertBefore(pane, child);
|
|
44
|
+
|
|
45
|
+
// if this pane is not visible, make it visible too.
|
|
46
|
+
this.set('isVisible',true) ;
|
|
47
|
+
|
|
48
|
+
// and make target pane visible, but set visibility hidden.
|
|
49
|
+
// visibility hidden will be turned off when the view is fully configured.
|
|
50
|
+
pane.setStyle({ visibility: 'hidden' }) ;
|
|
51
|
+
pane.set('isVisible',true) ;
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
this._setApplicationKeyPane();
|
|
55
|
+
|
|
56
|
+
// set content on view.
|
|
57
|
+
pane.set('content',view);
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
// this method will hide a visible pane view. Pass the content view. If
|
|
61
|
+
// the view is not already visible, this will do nothing.
|
|
62
|
+
hidePaneView: function(view) {
|
|
63
|
+
var pane = this._visiblePanes[view._guid] ;
|
|
64
|
+
if (!pane) return ;
|
|
65
|
+
|
|
66
|
+
// make pane not visible then do the rest of the cleanup when that
|
|
67
|
+
// finishes.
|
|
68
|
+
pane.addObserver('displayIsVisible', this._boundPaneDidHide) ;
|
|
69
|
+
pane.set('isVisible', false) ;
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
// this method will return a pave view for the specified type. If no panes
|
|
73
|
+
// of the type exist in the pane cache, then a new pane will be created.
|
|
74
|
+
getPaneFor: function(paneType) {
|
|
75
|
+
var panes = this._paneCache[paneType] ;
|
|
76
|
+
var pane = (panes) ? panes.pop() : null ;
|
|
77
|
+
if (pane) return pane ;
|
|
78
|
+
|
|
79
|
+
// no pane found in cache. Build one instead. First look for class in
|
|
80
|
+
// set of registered pane types. If that doesn't work, build class name.
|
|
81
|
+
var paneClass = this._paneTypes[paneType] ;
|
|
82
|
+
if (!paneClass) paneClass = SC[paneType.classify() + 'PaneView'] ;
|
|
83
|
+
if (!paneClass) {
|
|
84
|
+
throw "no matching class found for pane type '%@'".fmt(paneType);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// now create an instance.
|
|
88
|
+
pane = paneClass.viewFor(null) ;
|
|
89
|
+
return pane ;
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
// this method will add the pane instance to the pane cache for later use.
|
|
93
|
+
returnToCache: function(pane, paneType) {
|
|
94
|
+
var panes = this._paneCache[paneType] || [] ;
|
|
95
|
+
panes.push(pane) ;
|
|
96
|
+
this._paneCache[paneType] = panes;
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
// this method is called by the pane when it finishes hiding itself.
|
|
100
|
+
_paneDidHide: function(pane) {
|
|
101
|
+
var visible = pane.get('displayIsVisible') ;
|
|
102
|
+
if (visible) return ;
|
|
103
|
+
|
|
104
|
+
// remove this observer and remove pane from parent view.
|
|
105
|
+
pane.removeObserver('displayIsVisible', this._boundPanelDidHide) ;
|
|
106
|
+
pane.removeFromParent() ;
|
|
107
|
+
|
|
108
|
+
// now remove content view from pane and return pane to cache.
|
|
109
|
+
pane.set('content', null) ;
|
|
110
|
+
this.returnToCache(pane,pane._managedPaneType) ;
|
|
111
|
+
|
|
112
|
+
// if there are no more panes left visible, hide pane manager as well.
|
|
113
|
+
if (this.get('firstChild') == null) {
|
|
114
|
+
this.set('isVisible',false) ;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
this._setApplicationKeyPane();
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @todo Need to move this (and all of the pane display/hide interface) into SC.Application
|
|
122
|
+
*/
|
|
123
|
+
_setApplicationKeyPane: function()
|
|
124
|
+
{
|
|
125
|
+
// ensure that the frontmost pane is the key pane
|
|
126
|
+
// we're making a lot of assumptions here... need to create a some unit tests that:
|
|
127
|
+
// lastChild is always a pane view
|
|
128
|
+
// calling makeKeyPane indiscriminately will have no ill effect (currently it's fine)
|
|
129
|
+
var frontMostPane = this.get('lastChild');
|
|
130
|
+
if (frontMostPane && frontMostPane.get('isVisible')) {
|
|
131
|
+
frontMostPane.makeKeyPane();
|
|
132
|
+
} else {
|
|
133
|
+
var pane = SC.app.get('mainPane');
|
|
134
|
+
if (pane) pane.makeKeyPane();
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
// on init, add to main HTML page if not already added.
|
|
139
|
+
init: function() {
|
|
140
|
+
arguments.callee.base.apply(this,arguments) ;
|
|
141
|
+
var el = this.rootElement ;
|
|
142
|
+
if (!this.parentNode) {
|
|
143
|
+
$tag('body').insertBefore(el, null) ;
|
|
144
|
+
SC.window.insertBefore(this, null) ;
|
|
145
|
+
}
|
|
146
|
+
this.set('isVisible',false) ;
|
|
147
|
+
this._boundPaneDidHide = this._paneDidHide.bind(this) ;
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
// registered panes.
|
|
151
|
+
_paneTypes: {},
|
|
152
|
+
_paneCache: {}, // unused pane instances stored by paneType.
|
|
153
|
+
_visiblePanes: {} // panes stored by views
|
|
154
|
+
}) ;
|
|
155
|
+
|
|
156
|
+
SC.PaneManager.registerPaneType = function(paneType, paneClass) {
|
|
157
|
+
SC.PaneManager.prototype._paneTypes[paneType] = paneClass ;
|
|
158
|
+
} ;
|
|
159
|
+
|
|
160
|
+
// This will create the manager instance if it does not already exist.
|
|
161
|
+
SC.PaneManager.manager = function() {
|
|
162
|
+
if (!this._manager) this._manager = SC.PaneManager.viewFor('panes') ;
|
|
163
|
+
return this._manager ;
|
|
164
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// ========================================================================
|
|
2
|
+
// SproutCore
|
|
3
|
+
// copyright 2006-2007 Sprout Systems, Inc.
|
|
4
|
+
// ========================================================================
|
|
5
|
+
|
|
6
|
+
require('panes/overlay') ;
|
|
7
|
+
|
|
8
|
+
SC.MENU_PANE = 'menu';
|
|
9
|
+
SC.MenuPaneView = SC.OverlayPaneView.extend({
|
|
10
|
+
|
|
11
|
+
emptyElement: '<div class="pane menu-pane"><div class="shadow pane-wrapper"><div class="pane-root"></div><div class="top-left-edge"></div><div class="top-edge"></div><div class="top-right-edge"></div><div class="right-edge"></div><div class="bottom-right-edge"></div><div class="bottom-edge"></div><div class="bottom-left-edge"></div><div class="left-edge"></div></div></div>',
|
|
12
|
+
|
|
13
|
+
layer: 400,
|
|
14
|
+
|
|
15
|
+
isModal: false,
|
|
16
|
+
|
|
17
|
+
// The ideal position for a picker pane is just below the anchor that
|
|
18
|
+
// triggered it. Find that ideal position, then call adjustPosition.
|
|
19
|
+
positionPane: function() {
|
|
20
|
+
var anchor = this.anchorView ;
|
|
21
|
+
var picker = this.containerView ;
|
|
22
|
+
var origin ;
|
|
23
|
+
|
|
24
|
+
// usually an anchorView will be passed. The ideal position to appear is
|
|
25
|
+
// just below the anchorView. If that is not possible, fitToScreen will
|
|
26
|
+
// take care of that.
|
|
27
|
+
if (anchor) {
|
|
28
|
+
origin = picker.convertFrameFromView(anchor.get('frame'), anchor) ;
|
|
29
|
+
origin.y += origin.height ;
|
|
30
|
+
origin = this.fitPositionToScreen(origin, picker, anchor) ;
|
|
31
|
+
|
|
32
|
+
// if no anchor view has been set for some reason, just center.
|
|
33
|
+
} else {
|
|
34
|
+
var wsize = SC.window.get('size') ;
|
|
35
|
+
var psize = picker.get('size') ;
|
|
36
|
+
origin = {} ;
|
|
37
|
+
origin.x = (wsize.width - psize.width) / 2 ;
|
|
38
|
+
origin.y = (wsize.height - psize.height) / 2 ;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
picker.set('origin',origin) ;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
}) ;
|
|
45
|
+
|