extjs-mvc 0.4.0.j → 0.4.0.k

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. data/Rakefile +1 -1
  2. data/VERSION +1 -1
  3. data/lib/extjs-mvc.rb +0 -14
  4. data/lib/extjs-mvc/api.rb +14 -27
  5. data/lib/extjs-mvc/src/App.js +219 -0
  6. data/lib/extjs-mvc/src/MVC.js +260 -0
  7. data/lib/extjs-mvc/src/Presenter.js +52 -0
  8. data/lib/extjs-mvc/src/README.rdoc +69 -0
  9. data/lib/extjs-mvc/src/controller/Controller.js +278 -0
  10. data/lib/extjs-mvc/src/controller/CrudController.js +460 -0
  11. data/lib/extjs-mvc/src/lib/Array.js +26 -0
  12. data/lib/extjs-mvc/src/lib/Booter.js +417 -0
  13. data/lib/extjs-mvc/src/lib/ClassManager.js +191 -0
  14. data/lib/extjs-mvc/src/lib/ControllerClassManager.js +95 -0
  15. data/lib/extjs-mvc/src/lib/Dependencies.js +44 -0
  16. data/lib/extjs-mvc/src/lib/DispatchMatcher.js +98 -0
  17. data/lib/extjs-mvc/src/lib/Dispatcher.js +129 -0
  18. data/lib/extjs-mvc/src/lib/Environment.js +43 -0
  19. data/lib/extjs-mvc/src/lib/Inflector.js +155 -0
  20. data/lib/extjs-mvc/src/lib/ModelClassManager.js +19 -0
  21. data/lib/extjs-mvc/src/lib/Route.js +139 -0
  22. data/lib/extjs-mvc/src/lib/Router.js +282 -0
  23. data/lib/extjs-mvc/src/lib/String.js +94 -0
  24. data/lib/extjs-mvc/src/lib/ViewClassManager.js +229 -0
  25. data/lib/extjs-mvc/src/lib/notes.txt +32 -0
  26. data/lib/extjs-mvc/src/model/AdapterManager.js +30 -0
  27. data/lib/extjs-mvc/src/model/Association.js +26 -0
  28. data/lib/extjs-mvc/src/model/Base.js +63 -0
  29. data/lib/extjs-mvc/src/model/BelongsToAssociation.js +116 -0
  30. data/lib/extjs-mvc/src/model/Cache.js +131 -0
  31. data/lib/extjs-mvc/src/model/HasManyAssociation.js +160 -0
  32. data/lib/extjs-mvc/src/model/Model.js +331 -0
  33. data/lib/extjs-mvc/src/model/UrlBuilder.js +106 -0
  34. data/lib/extjs-mvc/src/model/adapters/AbstractAdapter.js +296 -0
  35. data/lib/extjs-mvc/src/model/adapters/MemoryAdapter.js +103 -0
  36. data/lib/extjs-mvc/src/model/adapters/RESTAdapter.js +345 -0
  37. data/lib/extjs-mvc/src/model/adapters/RESTJSONAdapter.js +68 -0
  38. data/lib/extjs-mvc/src/model/adapters/notes.txt +42 -0
  39. data/lib/extjs-mvc/src/model/associations/Association.js +192 -0
  40. data/lib/extjs-mvc/src/model/associations/notes.txt +87 -0
  41. data/lib/extjs-mvc/src/model/validations/Errors.js +136 -0
  42. data/lib/extjs-mvc/src/model/validations/Plugin.js +139 -0
  43. data/lib/extjs-mvc/src/model/validations/Validations.js +276 -0
  44. data/lib/extjs-mvc/src/notes/Charts.graffle +0 -0
  45. data/lib/extjs-mvc/src/overrides/Ext.Component.js +21 -0
  46. data/lib/extjs-mvc/src/overrides/Ext.extend.js +142 -0
  47. data/lib/extjs-mvc/src/spec/Array.spec.js +15 -0
  48. data/lib/extjs-mvc/src/spec/ExtMVC.spec.js +65 -0
  49. data/lib/extjs-mvc/src/spec/Model.spec.js +370 -0
  50. data/lib/extjs-mvc/src/spec/OS.spec.js +83 -0
  51. data/lib/extjs-mvc/src/spec/Router.spec.js +99 -0
  52. data/lib/extjs-mvc/src/spec/SpecHelper.js +106 -0
  53. data/lib/extjs-mvc/src/spec/String.spec.js +83 -0
  54. data/lib/extjs-mvc/src/spec/model/AbstractAdapter.spec.js +49 -0
  55. data/lib/extjs-mvc/src/spec/model/Associations.spec.js +99 -0
  56. data/lib/extjs-mvc/src/spec/model/Cache.spec.js +5 -0
  57. data/lib/extjs-mvc/src/spec/model/RESTAdapter.spec.js +19 -0
  58. data/lib/extjs-mvc/src/spec/model/ValidationErrors.spec.js +64 -0
  59. data/lib/extjs-mvc/src/spec/model/Validations.spec.js +166 -0
  60. data/lib/extjs-mvc/src/spec/model/ValidationsPlugin.spec.js +108 -0
  61. data/lib/extjs-mvc/src/spec/suite.html +60 -0
  62. data/lib/extjs-mvc/src/specs-old/JSSpec.css +216 -0
  63. data/lib/extjs-mvc/src/specs-old/JSSpec.js +1512 -0
  64. data/lib/extjs-mvc/src/specs-old/all.html +66 -0
  65. data/lib/extjs-mvc/src/specs-old/base.js +14 -0
  66. data/lib/extjs-mvc/src/specs-old/controller.js +17 -0
  67. data/lib/extjs-mvc/src/specs-old/diff_match_patch.js +1 -0
  68. data/lib/extjs-mvc/src/specs-old/model.js +70 -0
  69. data/lib/extjs-mvc/src/specs-old/route.js +38 -0
  70. data/lib/extjs-mvc/src/specs-old/router.js +59 -0
  71. data/lib/extjs-mvc/src/specs-old/string.js +22 -0
  72. data/lib/extjs-mvc/src/testrunner/JSpecFormatter.js +111 -0
  73. data/lib/extjs-mvc/src/testrunner/TestClient.js +181 -0
  74. data/lib/extjs-mvc/src/testrunner/TestGrid.js +351 -0
  75. data/lib/extjs-mvc/src/testrunner/TestRunner.js +110 -0
  76. data/lib/extjs-mvc/src/testrunner/TestViewport.js +94 -0
  77. data/lib/extjs-mvc/src/vendor.yml +30 -0
  78. data/lib/extjs-mvc/src/vendor/ext-3.1.1/vendor.yml +16 -0
  79. data/lib/extjs-mvc/src/view/FormWindow.js +184 -0
  80. data/lib/extjs-mvc/src/view/HasManyEditorGridPanel.js +211 -0
  81. data/lib/extjs-mvc/src/view/scaffold/Edit.js +46 -0
  82. data/lib/extjs-mvc/src/view/scaffold/Index.js +561 -0
  83. data/lib/extjs-mvc/src/view/scaffold/New.js +20 -0
  84. data/lib/extjs-mvc/src/view/scaffold/ScaffoldFormPanel.js +255 -0
  85. data/lib/{vendor.yml → extjs-mvc/vendor.yml} +0 -0
  86. data/test/app/vendor/extjs-mvc/App.js +219 -0
  87. data/test/app/vendor/extjs-mvc/MVC.js +260 -0
  88. data/test/app/vendor/extjs-mvc/Presenter.js +52 -0
  89. data/test/app/vendor/extjs-mvc/README.rdoc +69 -0
  90. data/test/app/vendor/extjs-mvc/controller/Controller.js +278 -0
  91. data/test/app/vendor/extjs-mvc/controller/CrudController.js +460 -0
  92. data/test/app/vendor/extjs-mvc/lib/Array.js +26 -0
  93. data/test/app/vendor/extjs-mvc/lib/Booter.js +417 -0
  94. data/test/app/vendor/extjs-mvc/lib/ClassManager.js +191 -0
  95. data/test/app/vendor/extjs-mvc/lib/ControllerClassManager.js +95 -0
  96. data/test/app/vendor/extjs-mvc/lib/Dependencies.js +44 -0
  97. data/test/app/vendor/extjs-mvc/lib/DispatchMatcher.js +98 -0
  98. data/test/app/vendor/extjs-mvc/lib/Dispatcher.js +129 -0
  99. data/test/app/vendor/extjs-mvc/lib/Environment.js +43 -0
  100. data/test/app/vendor/extjs-mvc/lib/Inflector.js +155 -0
  101. data/test/app/vendor/extjs-mvc/lib/ModelClassManager.js +19 -0
  102. data/test/app/vendor/extjs-mvc/lib/Route.js +139 -0
  103. data/test/app/vendor/extjs-mvc/lib/Router.js +282 -0
  104. data/test/app/vendor/extjs-mvc/lib/String.js +94 -0
  105. data/test/app/vendor/extjs-mvc/lib/ViewClassManager.js +229 -0
  106. data/test/app/vendor/extjs-mvc/lib/notes.txt +32 -0
  107. data/test/app/vendor/extjs-mvc/model/AdapterManager.js +30 -0
  108. data/test/app/vendor/extjs-mvc/model/Association.js +26 -0
  109. data/test/app/vendor/extjs-mvc/model/Base.js +63 -0
  110. data/test/app/vendor/extjs-mvc/model/BelongsToAssociation.js +116 -0
  111. data/test/app/vendor/extjs-mvc/model/Cache.js +131 -0
  112. data/test/app/vendor/extjs-mvc/model/HasManyAssociation.js +160 -0
  113. data/test/app/vendor/extjs-mvc/model/Model.js +331 -0
  114. data/test/app/vendor/extjs-mvc/model/UrlBuilder.js +106 -0
  115. data/test/app/vendor/extjs-mvc/model/adapters/AbstractAdapter.js +296 -0
  116. data/test/app/vendor/extjs-mvc/model/adapters/MemoryAdapter.js +103 -0
  117. data/test/app/vendor/extjs-mvc/model/adapters/RESTAdapter.js +345 -0
  118. data/test/app/vendor/extjs-mvc/model/adapters/RESTJSONAdapter.js +68 -0
  119. data/test/app/vendor/extjs-mvc/model/adapters/notes.txt +42 -0
  120. data/test/app/vendor/extjs-mvc/model/associations/Association.js +192 -0
  121. data/test/app/vendor/extjs-mvc/model/associations/notes.txt +87 -0
  122. data/test/app/vendor/extjs-mvc/model/validations/Errors.js +136 -0
  123. data/test/app/vendor/extjs-mvc/model/validations/Plugin.js +139 -0
  124. data/test/app/vendor/extjs-mvc/model/validations/Validations.js +276 -0
  125. data/test/app/vendor/extjs-mvc/notes/Charts.graffle +0 -0
  126. data/test/app/vendor/extjs-mvc/overrides/Ext.Component.js +21 -0
  127. data/test/app/vendor/extjs-mvc/overrides/Ext.extend.js +142 -0
  128. data/test/app/vendor/extjs-mvc/spec/Array.spec.js +15 -0
  129. data/test/app/vendor/extjs-mvc/spec/ExtMVC.spec.js +65 -0
  130. data/test/app/vendor/extjs-mvc/spec/Model.spec.js +370 -0
  131. data/test/app/vendor/extjs-mvc/spec/OS.spec.js +83 -0
  132. data/test/app/vendor/extjs-mvc/spec/Router.spec.js +99 -0
  133. data/test/app/vendor/extjs-mvc/spec/SpecHelper.js +106 -0
  134. data/test/app/vendor/extjs-mvc/spec/String.spec.js +83 -0
  135. data/test/app/vendor/extjs-mvc/spec/model/AbstractAdapter.spec.js +49 -0
  136. data/test/app/vendor/extjs-mvc/spec/model/Associations.spec.js +99 -0
  137. data/test/app/vendor/extjs-mvc/spec/model/Cache.spec.js +5 -0
  138. data/test/app/vendor/extjs-mvc/spec/model/RESTAdapter.spec.js +19 -0
  139. data/test/app/vendor/extjs-mvc/spec/model/ValidationErrors.spec.js +64 -0
  140. data/test/app/vendor/extjs-mvc/spec/model/Validations.spec.js +166 -0
  141. data/test/app/vendor/extjs-mvc/spec/model/ValidationsPlugin.spec.js +108 -0
  142. data/test/app/vendor/extjs-mvc/spec/suite.html +60 -0
  143. data/test/app/vendor/extjs-mvc/specs-old/JSSpec.css +216 -0
  144. data/test/app/vendor/extjs-mvc/specs-old/JSSpec.js +1512 -0
  145. data/test/app/vendor/extjs-mvc/specs-old/all.html +66 -0
  146. data/test/app/vendor/extjs-mvc/specs-old/base.js +14 -0
  147. data/test/app/vendor/extjs-mvc/specs-old/controller.js +17 -0
  148. data/test/app/vendor/extjs-mvc/specs-old/diff_match_patch.js +1 -0
  149. data/test/app/vendor/extjs-mvc/specs-old/model.js +70 -0
  150. data/test/app/vendor/extjs-mvc/specs-old/route.js +38 -0
  151. data/test/app/vendor/extjs-mvc/specs-old/router.js +59 -0
  152. data/test/app/vendor/extjs-mvc/specs-old/string.js +22 -0
  153. data/test/app/vendor/extjs-mvc/testrunner/JSpecFormatter.js +111 -0
  154. data/test/app/vendor/extjs-mvc/testrunner/TestClient.js +181 -0
  155. data/test/app/vendor/extjs-mvc/testrunner/TestGrid.js +351 -0
  156. data/test/app/vendor/extjs-mvc/testrunner/TestRunner.js +110 -0
  157. data/test/app/vendor/extjs-mvc/testrunner/TestViewport.js +94 -0
  158. data/test/app/vendor/extjs-mvc/vendor.yml +30 -0
  159. data/test/app/vendor/extjs-mvc/vendor/ext-3.1.1/vendor.yml +16 -0
  160. data/test/app/vendor/extjs-mvc/view/FormWindow.js +184 -0
  161. data/test/app/vendor/extjs-mvc/view/HasManyEditorGridPanel.js +211 -0
  162. data/test/app/vendor/extjs-mvc/view/scaffold/Edit.js +46 -0
  163. data/test/app/vendor/extjs-mvc/view/scaffold/Index.js +561 -0
  164. data/test/app/vendor/extjs-mvc/view/scaffold/New.js +20 -0
  165. data/test/app/vendor/extjs-mvc/view/scaffold/ScaffoldFormPanel.js +255 -0
  166. data/test/helper.rb +7 -1
  167. data/test/test_extjs-mvc.rb +46 -0
  168. metadata +167 -7
  169. data/test/test_extjs-mvc-gem.rb +0 -7
@@ -0,0 +1,260 @@
1
+ /**
2
+ * @class ExtMVC
3
+ * ExtMVC
4
+ * @singleton
5
+ */
6
+ ExtMVC = Ext.extend(Ext.util.Observable, {
7
+ version: "0.7a",
8
+
9
+ constructor: function() {
10
+ ExtMVC.superclass.constructor.apply(this, arguments);
11
+
12
+ /**
13
+ * @property dispatcher
14
+ * @type Ext.lib.Dispatcher
15
+ * The dispatcher object which finds the right controller and action when ExtMVC.dispatch is called
16
+ */
17
+ // this.dispatcher = new Ext.lib.Dispatcher({
18
+ //
19
+ // });
20
+ },
21
+
22
+ dispatch: function() {
23
+ var dispatcher = this.dispatcher;
24
+
25
+ return dispatcher.dispatch.apply(dispatcher, arguments);
26
+ },
27
+
28
+ /**
29
+ * Sets the Ext.Application instance currently in use. This is currently required :/
30
+ * @param {Ext.Application} app The application currently in use
31
+ */
32
+ setApplication: function(app) {
33
+ this.app = app;
34
+ this.name = app.name;
35
+
36
+ ExtMVC.model.modelNamespace = window[app.name].models;
37
+ },
38
+
39
+ fields: {
40
+
41
+ },
42
+
43
+ registerFields: function(name, fields) {
44
+ this.fields[name] = fields;
45
+ },
46
+
47
+ getFields: function(name) {
48
+ return this.fields[name];
49
+ },
50
+
51
+
52
+
53
+ /**
54
+ * Registers a model class with Ext MVC
55
+ * @param {String} name The name to give this model
56
+ * @param {Object} config Model definition configuration
57
+ */
58
+ registerModel: function(name, config) {
59
+ this.registerClass('model', arguments);
60
+ },
61
+
62
+ /**
63
+ * Registers a controller class with Ext MVC
64
+ * @param {String} name The name to give this controller
65
+ * @param {Object} config Controller definition configuration
66
+ */
67
+ registerController: function(name, config) {
68
+ this.registerClass('controller', arguments);
69
+ },
70
+
71
+ /**
72
+ * Registers a view class with Ext MVC.
73
+ * @param {String} namesapce The namespace to add this view to
74
+ * @param {String} name The name to give this view
75
+ * @param {Object} config View definition configuration
76
+ */
77
+ registerView: function(namespace, name, config) {
78
+ this.registerClass('view', arguments);
79
+ },
80
+
81
+ /**
82
+ * Abstraction for registering views, models and controllers
83
+ * @param {String} managerName The name of the class manager to register with
84
+ * @param {Array} args The args to pass to the manager's register method
85
+ */
86
+ registerClass: function(managerName, args) {
87
+ var manager = this.getClassManager(managerName);
88
+
89
+ manager.register.apply(manager, args);
90
+ },
91
+
92
+ /**
93
+ * @property classManagers
94
+ * @type Object
95
+ * {name: classManager} mappings used by this.getClassManager and this.registerClassManager
96
+ */
97
+ classManagers: {},
98
+
99
+ /**
100
+ * @private
101
+ * Sets up model, view and controller class managers
102
+ */
103
+ initializeClassManagers: function() {
104
+ this.registerClassManager('model', new ExtMVC.lib.ModelClassManager());
105
+ this.registerClassManager('view', new ExtMVC.lib.ViewClassManager());
106
+ this.registerClassManager('controller', new ExtMVC.lib.ControllerClassManager());
107
+ },
108
+
109
+ /**
110
+ * Returns the class manager for the given name
111
+ * @param {String} name The name of the manager (model, view or controller)
112
+ * @return {ExtMVC.lib.ClassManager} The class manager instance
113
+ */
114
+ getClassManager: function(name) {
115
+ return this.classManagers[name];
116
+ },
117
+
118
+ /**
119
+ * Registers a class manager instance under a given name
120
+ * @param {String} name The name of the class manager
121
+ * @param {ExtMVC.lib.ClassManager} manager The ClassManager instance to register
122
+ */
123
+ registerClassManager: function(name, manager) {
124
+ this.classManagers[name] = manager;
125
+ },
126
+
127
+ /**
128
+ * Returns the canonical controller instance for the given controller name
129
+ * @return {ExtMVC.Controller} The controller instance
130
+ */
131
+ getController: function(name) {
132
+ return this.getClassManager('controller').getInstance(name);
133
+ },
134
+
135
+ /**
136
+ * Returns the constructor for a given model name
137
+ * @param {String} name The name of the model
138
+ * @return {Function} The model constructor
139
+ */
140
+ getModel: function(name) {
141
+ return this.getClassManager('model').getConstructor(name);
142
+ },
143
+
144
+ /**
145
+ * Instantiates a model of the given name with the data supplied
146
+ * @param {String} modelName The name of the model to instantiate
147
+ * @param {Object} data Data object to instantiate the instance with
148
+ * @return {ExtMVC.Model} The new model instance
149
+ */
150
+ buildModel: function(modelName, data) {
151
+ return new (this.getModel(modelName))(data);
152
+ },
153
+
154
+ /**
155
+ * Returns the constructor for a given view namespace/name combination
156
+ * @param {String} namespace The view namespace to look in
157
+ * @param {String} name The name of the view within the view namespace
158
+ * @return {Function} The view constructor
159
+ */
160
+ getView: function getView(namespace, name) {
161
+ return this.getClassManager('view').getConstructor(namespace, name);
162
+ },
163
+
164
+ /**
165
+ * Returns a new view instance for the given namespace/name combo, using the supplied config
166
+ * @param {String} namespace The namespace to find the view from
167
+ * @param {String} name The view name
168
+ * @param {Object} config Optional config object
169
+ * @return {Ext.Component} The new view instance
170
+ */
171
+ buildView: function buildView(namespace, name, config) {
172
+ var constructor = this.getView(namespace, name);
173
+
174
+ return new (constructor)(config);
175
+ },
176
+
177
+ /**
178
+ * Loads packaged classes from a given url, calling a callback when they have been registered. Sample return:
179
+ <pre>
180
+ {
181
+ controllers: [
182
+ {
183
+ name: 'comments',
184
+ superclass: 'crud',
185
+ config: {
186
+ index: function() {
187
+ this.render('index', {
188
+ title: "Loaded on demand!"
189
+ });
190
+ }
191
+ }
192
+ }
193
+ ],
194
+ views: [
195
+ {
196
+ name: 'new',
197
+ namespace: 'comments',
198
+ config: {
199
+ xtype: 'scaffoldnew',
200
+ title: "New Comment"
201
+ }
202
+ }
203
+ ],
204
+ models: [
205
+ {
206
+ name : 'Comment',
207
+ config: {
208
+ fields: [
209
+ {name: 'id', type: 'int'},
210
+ {name: 'title', type: 'string'},
211
+ {name: 'message', type: 'string'}
212
+ ]
213
+ }
214
+ }
215
+ ]
216
+ }
217
+ </pre>
218
+ * @param {String} url The url to retrieve the package from
219
+ * @param {Function} callback Optional callback function, called after the package has been read and registered
220
+ * @param {Object} scope The scope to execute the callback function in
221
+ */
222
+ loadOnDemand: function(url, callback, scope) {
223
+ Ext.Ajax.request({
224
+ url : url,
225
+ scope : scope || this,
226
+ success: function(response) {
227
+ var pkg = Ext.decode(response.responseText);
228
+
229
+ Ext.each(pkg.controllers || [], function(config) {
230
+ this.registerController(config.name, config);
231
+ }, this);
232
+
233
+ Ext.each(pkg.models || [], function(config) {
234
+ this.registerModel(config.name, config);
235
+ }, this);
236
+
237
+ Ext.each(pkg.views || [], function(config) {
238
+ this.registerView(config.namespace, config.name, config);
239
+ }, this);
240
+
241
+ if (Ext.isFunction(callback)) callback.call(scope, pkg);
242
+ }
243
+ });
244
+ }
245
+ });
246
+
247
+ ExtMVC = new ExtMVC();
248
+
249
+ // ExtMVC.initializeClassManagers();
250
+
251
+ Ext.onReady(function() {
252
+ /**
253
+ * @property dispatcher
254
+ * @type Ext.lib.Dispatcher
255
+ * The dispatcher object which finds the right controller and action when ExtMVC.dispatch is called
256
+ */
257
+ ExtMVC.dispatcher = new ExtMVC.lib.Dispatcher();
258
+ });
259
+
260
+ Ext.ns('ExtMVC.router', 'ExtMVC.plugin', 'ExtMVC.controller', 'ExtMVC.view', 'ExtMVC.view.scaffold', 'ExtMVC.lib', 'ExtMVC.test');
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @class ExtMVC.Presenter
3
+ * @extends Ext.util.Observable
4
+ * Used as an interface between a controller and its views
5
+ */
6
+ ExtMVC.Presenter = Ext.extend(Ext.util.Observable, {
7
+
8
+ constructor: function(config) {
9
+ ExtMVC.Presenter.superclass.constructor.apply(this, arguments);
10
+
11
+ this.addEvents(
12
+ /**
13
+ * @event load
14
+ * Fires when all items in the Presenter have been loaded
15
+ */
16
+ 'load'
17
+ );
18
+
19
+ /**
20
+ * @property loaded
21
+ * @type Boolean
22
+ * True if all items that must be loaded before rendering have been
23
+ */
24
+ this.loaded = false;
25
+
26
+ /**
27
+ * @property loading
28
+ * @type Boolean
29
+ * True while the loader is loading
30
+ */
31
+ this.loading = false;
32
+ },
33
+
34
+ load: function() {
35
+ if (this.loaded || this.loading) return;
36
+
37
+ this.each(function(item, index, length) {
38
+ var callback = function(index) {
39
+ return function() {
40
+ if (index == length) {
41
+ this.loaded = true;
42
+ this.loading = false;
43
+
44
+ this.fireEvent('load');
45
+ }
46
+ };
47
+ }(index);
48
+
49
+ item.on('load', callback, this, {single: true});
50
+ }, this);
51
+ }
52
+ });
@@ -0,0 +1,69 @@
1
+ = Ext MVC
2
+
3
+ EXT MVC is a complete MVC stack on top of Ext JS (http://extjs.com).
4
+
5
+ == Base App
6
+
7
+ You are advised to use the base app to get up and running with Ext MVC as it sets everything up for you.
8
+
9
+ If you're comfortable with git:
10
+
11
+ 1. git clone git://github.com/extmvc/baseapp.git myapp
12
+ 2. cd myapp
13
+ 3. rm -rf .git/
14
+ 4. git init
15
+
16
+ If not:
17
+
18
+ 1. Download the latest zip file from Github at http://github.com/extmvc/baseapp/zipball/master and unzip.
19
+
20
+ == Getting started
21
+
22
+ Read the readme file inside the base app and refer to http://extmvc.com
23
+
24
+ == Building
25
+
26
+ Ext MVC comes with a set of build tools for itself and your applications, written in Ruby. You need to be using
27
+ the Baseapp or a structure similar to it for these to work effectively.
28
+
29
+ === Building your Ext MVC application
30
+
31
+ Build any app started from the base app by running this from the app's root directory:
32
+
33
+ ruby script/build all
34
+
35
+ This will examine the contents of index.html, pull out all of the javascript includes and concatenate them into
36
+ public/application-all.js. If you have the yui-compressor in your vendor directory (this is included by default)
37
+ and you have java installed, the build process will also minify your application-all.js into application-all-min.js.
38
+
39
+ Building your app also concatenates any CSS includes in index.html into public/application-all.css.
40
+
41
+ *NOTE*: Building looks at your index.html, NOT public/index.html. index.html is your development version,
42
+ public/index.html should simply include those concatenated/minified files.
43
+
44
+ === Autobuild
45
+
46
+ If you need your app to be built every time you change any of the source files for whatever reason, use:
47
+
48
+ ruby script/build auto
49
+
50
+ This will again look at index.html and will force a rebuild any time any of those files are changed.
51
+
52
+ === Other app build options
53
+
54
+ There are several other build commands, most of which are used by the two above:
55
+
56
+ - ruby script/build css - only build CSS files, no JS concatenation or minification
57
+ - ruby script/build js - only builds JS files, not CSS
58
+ - ruby script/build concatenate_js - concatenates but does not attempt to minify your JS
59
+ - ruby script/build minify_js - minifies an already concatenated public/application-all.js file
60
+
61
+ === Building Ext MVC
62
+
63
+ If you are changing Ext MVC files and need to build Ext MVC itself, use:
64
+
65
+ - ruby script/build mvc
66
+ - ruby script/build mvc_auto
67
+
68
+ Again run from the app root directory. Like with ruby script/build auto, mvc_auto automatically rebuilds whenever
69
+ any Ext MVC file is changed.
@@ -0,0 +1,278 @@
1
+ /**
2
+ * @class ExtMVC.controller.Controller
3
+ * @extends Ext.util.Observable
4
+ * <h1>Controllers in Ext MVC</h1>
5
+ * <p>Controllers are the glue that stick applications together. They listen to events emitted by the UI as the user
6
+ * clicks interface elements, and take actions as appropriate. The relevant action may be to create or save a model
7
+ * instance, to render another view, to perform AJAX requests, or any other action.</p>
8
+ *
9
+ * <p>Controllers should be kept skinny as far as possible - receive an event, then hand any processing off to the
10
+ * appropriate model. This ensures we can keep the code as DRY as possible and makes refactoring easier.</p>
11
+ *
12
+ * <h2>Example Controller</h2>
13
+ * Here is a simple example controller which renders a couple of views and listens to events:
14
+ <pre><code>
15
+ //simple controller which manages the Page model within our application
16
+ MyApp.controllers.PagesController = Ext.extend(ExtMVC.controller.Controller, {
17
+ name: 'pages',
18
+
19
+ //renders the 'Index' template and sets up listeners
20
+ index: function() {
21
+ this.render('Index', {
22
+ listeners: {
23
+ scope : this,
24
+ 'edit' : this.edit,
25
+ 'delete': this.destroy
26
+ }
27
+ });
28
+ },
29
+
30
+ //renders the 'Edit' template (let's say it's a FormPanel), and loads the instance
31
+ edit: function(instance) {
32
+ this.render('Edit', {
33
+ listeners: {
34
+ scope : this,
35
+ save : this.update,
36
+ cancel : function() {
37
+ alert("You cancelled the update!");
38
+ }
39
+ }
40
+ }).loadRecord(instance);
41
+ },
42
+
43
+ //when the 'delete' event is fired by our 'Index' template (see the index action), this method is called.
44
+ //In this fictional example, we assume that the templates 'delete' event was called with the single argument
45
+ //of the Page instance the user wishes to destroy
46
+ destroy: function(instance) {
47
+ instance.destroy({
48
+ success: function() {
49
+ alert("The Page was deleted");
50
+ //at this point we might render another page for the user to look at
51
+ },
52
+ failure: function() {
53
+ alert('Curses! The Page could not be deleted');
54
+ }
55
+ });
56
+ },
57
+
58
+ //when the 'save' event is fired by our 'Edit' template, this method is called.
59
+ //Again, we assume that our template fired the event with the Page instance, and also an object with updates
60
+ update: function(instance, updates) {
61
+ //this applies the updates to the model instance and saves
62
+ instance.update(updates, {
63
+ success: function(updatedInstance) {
64
+ alert('Success! It saved');
65
+ //at this point we might render another page for the user to look at
66
+ },
67
+ failure: function(updatedInstance) {
68
+ alert('Darn it. Did not save');
69
+
70
+ //here we're firing the controller's update-failed event, which the view can pick up on
71
+ //The view can simply listen to our Pages controller and add errors from this instance to the form
72
+ //using form.markInvalid(instance.errors.forForm())
73
+ this.fireEvent('update-failed', instance);
74
+ };
75
+ });
76
+ },
77
+
78
+ //Sets up events emitted by this controller. Controllers are expected to fire events, so this method is called
79
+ //automatically when a controller is instantiated. Don't forget to call super here
80
+ initEvents: function() {
81
+ this.addEvents(
82
+ //this event will be fired when the controller can't update a Page instance
83
+ 'update-failed'
84
+ );
85
+
86
+ MyApp.controllers.PagesController.superclass.initEvents.apply(this, arguments);
87
+ }
88
+ })
89
+ </code></pre>
90
+ * Note that many of the methods above are provided by the {@link ExtMVC.controller.CrudController CrudController}
91
+ *
92
+ * <h2>Rendering Views</h2>
93
+ * Each controller can automatically render view classes inside its views package. In the Pages controller above the
94
+ * views package is MyApp.views.pages - the application itself is called MyApp, and the 'pages' segment comes from the
95
+ * controller's 'name' property
96
+ * <br />
97
+ * <br />
98
+ * In the example above, the line: <pre><code>this.render('Edit', {})</code></pre> will automatically find the
99
+ * MyApp.views.pages.Edit class, with the second argument to this.render being a config argument passed to the view's constructor.
100
+ *
101
+ * <br />
102
+ * <h4>Rendering strategies</h4>
103
+ * Not all applications will render views in the same way
104
+ */
105
+ // ExtMVC.controller.Controller = Ext.extend(Ext.util.Observable,
106
+ ExtMVC.registerController('controller', {
107
+
108
+ constructor: function(config) {
109
+ Ext.util.Observable.prototype.constructor.apply(this, arguments);
110
+
111
+ Ext.apply(this, {
112
+ /**
113
+ * @property renderStrategies
114
+ * @type Object
115
+ * An object of the form {xtype: function} which keys a container's xtype to the function to use
116
+ * when rendering a view to that container (see registerRenderStrategy)
117
+ */
118
+ renderStrategies: {}
119
+ }, config || {});
120
+
121
+ this.registerDefaultRenderStrategies();
122
+
123
+ this.initEvents();
124
+ this.initListeners();
125
+ },
126
+
127
+ /**
128
+ * Registers a rendering function for a given container xtype. When a view is rendered via this.render,
129
+ * the xtype of the container it is being rendered to is compared to the registered strategy xtypes, and
130
+ * the most specific match will be used to perform the rendering.
131
+ * @param {String} xtype The container xtype to register
132
+ * @param {Function} strategy The function to call when rendering to a container of the given xtype
133
+ */
134
+ registerRenderStrategy: function(xtype, strategy) {
135
+ this.renderStrategies[xtype] = strategy;
136
+ },
137
+
138
+ /**
139
+ * Returns the strategy function to use when rendering to the given container instance.
140
+ * @param {Ext.Container} container The container to add to
141
+ * @return {Function} The rendering strategy to use
142
+ */
143
+ getRenderStrategy: function(container) {
144
+ var xtypes = container.getXTypes().split("/");
145
+
146
+ for (var i = xtypes.length - 1; i >= 0; i--){
147
+ var strategy = this.renderStrategies[xtypes[i]];
148
+
149
+ if (strategy != undefined) return strategy;
150
+ };
151
+
152
+ throw new Ext.Error("No render strategy could be found for the container you specified");
153
+ },
154
+
155
+ /**
156
+ * @private
157
+ * Adds the default strategies for panel and tabpanel
158
+ */
159
+ registerDefaultRenderStrategies: function() {
160
+ this.registerRenderStrategy('panel', this.panelRenderStrategy);
161
+ this.registerRenderStrategy('tabpanel', this.tabPanelRenderStrategy);
162
+ },
163
+
164
+ /**
165
+ * Sets up events emitted by this controller. This defaults to an empty function and is
166
+ * called automatically when the controller is constructed so can simply be overridden
167
+ */
168
+ initEvents: function() {},
169
+
170
+ /**
171
+ * Sets up events this controller listens to, and the actions the controller should take
172
+ * when each event is received. This defaults to an empty function and is called when
173
+ * the controller is constructed so can simply be overridden
174
+ */
175
+ initListeners: function() {},
176
+
177
+ /**
178
+ * Shows the user a notification message. Usually used to inform user of a successful save, deletion, etc
179
+ * This is an empty function which you must implement yourself
180
+ * @param {String} notice The string notice to display
181
+ */
182
+ showNotice: function(notice) {},
183
+
184
+ /**
185
+ * @property addTo
186
+ * @type Ext.Container
187
+ * The container to add views to using the 'add' renderMethod. Usually set to an Ext.TabPanel instance or similar
188
+ */
189
+ addTo: null,
190
+
191
+ /**
192
+ * Renders a given view name in the way set up by the controller. For this to work you must have passed a
193
+ * 'name' property when creating the controller, which is automatically used to find the view namespace for
194
+ * this controller. For example, in an application called MyApp, and a controller with a name of 'users',
195
+ * the view namespace would be MyApp.views.users, and render('Index') would search for a class called
196
+ * MyApp.views.users.Index and instantiate it with the passed config.
197
+ * An error is thrown if the view could not be found.
198
+ * @param {String} viewName The name of the view class within the view namespace used by this controller
199
+ * @param {Object} config Configuration options passed through to the view class' constructor
200
+ * @return {Ext.Component} The view object that was just created
201
+ */
202
+ render: function render() {
203
+ //handle both method signatures
204
+ switch(arguments.length) {
205
+ case 1:
206
+ //this just falls through into case 2, which provides a config {} if one is not supplied
207
+ case 2:
208
+ var namespace = this.name,
209
+ viewName = arguments[0],
210
+ config = arguments[1] || {};
211
+ break;
212
+ case 3:
213
+ var namespace = arguments[0],
214
+ viewName = arguments[1],
215
+ config = arguments[2] || {};
216
+ break;
217
+ }
218
+
219
+ //we also use this constructor object to define whether or not the view should be added to the default
220
+ //container or not
221
+ Ext.applyIf(config, {
222
+ autoAdd: true,
223
+ addTo : ExtMVC.app.main
224
+ });
225
+
226
+ //NOTE: ExtMVC.getView will throw an error if the view hasn't been defined anywhere yet. At the moment this
227
+ //error will just propagate up as it's probably pretty clear, but we could provide a custom Error message here instead
228
+ var view = new (this.getView(namespace, viewName))(config);
229
+
230
+ if (config.autoAdd === true) {
231
+ if (view.isXType('window')) {
232
+ view.show();
233
+ } else {
234
+ this.getRenderStrategy(config.addTo)(config.addTo, view);
235
+ }
236
+ }
237
+
238
+ return view;
239
+ },
240
+
241
+ /**
242
+ * Just calls ExtMVC.getView and returns. This is here because we override it in Crud Controller
243
+ * @param {String} namespace The view namespace
244
+ * @param {String} name The view name
245
+ * @return {Function} The view constructor function
246
+ */
247
+ getView: function(namespace, name) {
248
+ return ExtMVC.getView(namespace, name);
249
+ },
250
+
251
+ /**
252
+ * @private
253
+ * The tabpanel render strategy
254
+ */
255
+ tabPanelRenderStrategy: function(container, view) {
256
+ var existing = container.getItem(view.id);
257
+
258
+ //don't add a tab with the same id as an existing one
259
+ if (existing == undefined) {
260
+ container.add(view);
261
+ container.doLayout();
262
+ container.activate(view);
263
+ } else {
264
+ container.setActiveTab(view.id);
265
+ view.destroy();
266
+ }
267
+ },
268
+
269
+ /**
270
+ * @private
271
+ * The panel render strategy
272
+ */
273
+ panelRenderStrategy: function(container, view) {
274
+ container.removeAll();
275
+ container.add(view);
276
+ container.doLayout();
277
+ }
278
+ });