extjs-mvc 0.4.0.j → 0.4.0.k

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.
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,20 @@
1
+ /**
2
+ * @class ExtMVC.view.scaffold.New
3
+ * @extends ExtMVC.view.scaffold.ScaffoldFormPanel
4
+ * Shows a generic new form for a given model
5
+ */
6
+ ExtMVC.registerView('scaffold', 'new', {
7
+ xtype : 'scaffold_form',
8
+ registerXType: 'scaffold_new',
9
+
10
+ /**
11
+ * Sets this panel's title, if not already set. Also specifies the save handler to use
12
+ */
13
+ initComponent: function() {
14
+ Ext.applyIf(this, {
15
+ title: 'New ' + this.model.prototype.singularHumanName
16
+ });
17
+
18
+ ExtMVC.getView('scaffold', 'form').prototype.initComponent.apply(this, arguments);
19
+ }
20
+ });
@@ -0,0 +1,255 @@
1
+ /**
2
+ * @class ExtMVC.view.scaffold.ScaffoldFormPanel
3
+ * @extends Ext.form.FormPanel
4
+ * Base class for any scaffold form panel (e.g. new and edit forms)
5
+ */
6
+ ExtMVC.registerView('scaffold', 'form', {
7
+ xtype : 'form',
8
+ registerXType: 'scaffold_form',
9
+
10
+ autoScroll: true,
11
+
12
+ /**
13
+ * Sets up the FormPanel, adds default configuration and items
14
+ */
15
+ constructor: function(config) {
16
+ var config = config || {};
17
+
18
+ this.model = config.model;
19
+
20
+ if (this.model == undefined) {
21
+ throw new Ext.Error(String.format("No model supplied to scaffold Form {0}", config.title), config);
22
+ }
23
+
24
+ Ext.form.FormPanel.prototype.constructor.call(this, config);
25
+ },
26
+
27
+ /**
28
+ * Adds default items, keys and buttons to the form
29
+ */
30
+ initComponent: function() {
31
+ Ext.applyIf(this, {
32
+ items : this.buildItems(),
33
+ monitorPoll : 500,
34
+ keys : [
35
+ {
36
+ key: Ext.EventObject.ESC,
37
+ scope: this,
38
+ handler: this.onCancel
39
+ },
40
+ {
41
+ key: 's',
42
+ ctrl: true,
43
+ scope: this,
44
+ stopEvent: true,
45
+ handler: this.onSave
46
+ }
47
+ ],
48
+
49
+ /**
50
+ * @property hasSaveButton
51
+ * @type Boolean
52
+ * True to include a save button (defaults to true)
53
+ */
54
+ hasSaveButton: true,
55
+
56
+ /**
57
+ * @property hasCancelButton
58
+ * @type Boolean
59
+ * True to include a cancel button (defaults to true)
60
+ */
61
+ hasCancelButton: true
62
+ });
63
+
64
+ //applyIf applies when buttons: [] is passed, which meant there was no way to
65
+ //specify any empty set of buttons before
66
+ if (!Ext.isArray(this.buttons)) {
67
+ Ext.apply(this, {
68
+ buttons: this.buildButtons()
69
+ });
70
+ }
71
+
72
+ Ext.form.FormPanel.prototype.initComponent.apply(this, arguments);
73
+
74
+ this.initEvents();
75
+ this.initListeners();
76
+ },
77
+
78
+ /**
79
+ * Sets up any listeners on related objects. By default this just listens to update-failed and create-failed
80
+ * events on the related controller and marks fields as invalid as appropriate
81
+ */
82
+ initListeners: function() {
83
+ if (this.controller) {
84
+ this.controller.on({
85
+ scope : this,
86
+ 'create-failed': this.showErrorsFromInstance,
87
+ 'update-failed': this.showErrorsFromInstance
88
+ });
89
+ }
90
+ },
91
+
92
+ /**
93
+ * Reads errors from a model instance and marks the relevant fields as invalid
94
+ * @param {ExtMVC.Model.Base} instance The model instance
95
+ */
96
+ showErrorsFromInstance: function(instance) {
97
+ this.getForm().markInvalid(instance.errors.forForm());
98
+ },
99
+
100
+ /**
101
+ * Sets up events emitted by this component
102
+ */
103
+ initEvents: function() {
104
+ this.addEvents(
105
+ /**
106
+ * @event save
107
+ * Fired when the user clicks the save button, or presses ctrl + s
108
+ * @param {Object} values The values entered into the form
109
+ * @param {ExtMVC.view.scaffold.ScaffoldFormPanel} this The form panel
110
+ */
111
+ 'save',
112
+
113
+ /**
114
+ * @event cancel
115
+ * Fired when the user clicks the cancel button, or presses the esc key
116
+ * @param {ExtMVC.Model.Base|Null} instance If editing an existing instance, this is a reference to that instance
117
+ */
118
+ 'cancel'
119
+ );
120
+
121
+ //taken from default Ext.FormPanel.initEvents - used to listen to the current validation of the form
122
+ //and fire off events
123
+ if (this.monitorValid) this.startMonitoring();
124
+ },
125
+
126
+ /**
127
+ * @property formItemConfig
128
+ * @type Object
129
+ * Default config which will be passed to all form items
130
+ */
131
+ formItemConfig: {
132
+ anchor: '-40',
133
+ xtype: 'textfield'
134
+ },
135
+
136
+ /**
137
+ * @property ignoreFields
138
+ * @type Array
139
+ * An array of fields not to show in the form (defaults to empty)
140
+ */
141
+ ignoreFields: ['id', 'created_at', 'updated_at'],
142
+
143
+ /**
144
+ * Builds the buttons added to this form. By default this returns an array containing
145
+ * a Save button and a Cancel button, which fire the 'save' and 'cancel' events respectively
146
+ * @return {Array} An array of Ext.Button objects or configs
147
+ */
148
+ buildButtons: function() {
149
+ var buttons = [];
150
+
151
+ if (this.hasSaveButton === true) buttons.push(this.buildSaveButton());
152
+ if (this.hasCancelButton === true) buttons.push(this.buildCancelButton());
153
+
154
+ return buttons;
155
+ },
156
+
157
+ /**
158
+ * Builds the Save button config. Override this to provide your own
159
+ * @return {Object/Ext.Button} The button config or object
160
+ */
161
+ buildSaveButton: function() {
162
+ return {
163
+ text: 'Save',
164
+ scope: this,
165
+ iconCls: 'save',
166
+ handler: this.onSave,
167
+ formBind: (this.monitorValid) ? true : false
168
+ };
169
+ },
170
+
171
+ /**
172
+ * Builds the Cancel button config. Override this to provide your own
173
+ * @return {Object/Ext.Button} The button config or object
174
+ */
175
+ buildCancelButton: function() {
176
+ return {
177
+ text: 'Cancel',
178
+ scope: this,
179
+ iconCls: 'cancel',
180
+ handler: this.onCancel
181
+ };
182
+ },
183
+
184
+ /**
185
+ * Builds an array of form items for the given model
186
+ * @param {ExtMVC.Model} model The model to build form items for
187
+ * @return {Array} An array of auto-generated form items
188
+ */
189
+ buildItems: function() {
190
+ items = [];
191
+
192
+ //check to see if FormFields have been created for this model
193
+ //e.g. for a MyApp.models.User model, checks for existence of MyApp.views.users.FormFields
194
+ if (this.viewsPackage && this.viewsPackage.FormFields) {
195
+ items = this.viewsPackage.FormFields;
196
+ } else {
197
+ //no user defined form fields, generate them automatically
198
+ var model = this.model,
199
+ proto = model.prototype,
200
+ fields = proto.fields;
201
+
202
+ fields.each(function(field) {
203
+
204
+ //add if it's not a field to be ignored
205
+ if (this.ignoreFields.indexOf(field.name) == -1) {
206
+ items.push(Ext.applyIf({
207
+ name: field.name,
208
+ fieldLabel: (field.name.replace(/_/g, " ")).capitalize()
209
+ }));
210
+ }
211
+ }, this);
212
+ }
213
+
214
+ //apply defaults to each item
215
+ for (var i=0; i < items.length; i++) {
216
+ if (items[i].layout === undefined) Ext.applyIf(items[i], this.formItemConfig);
217
+ }
218
+
219
+ return items;
220
+ },
221
+
222
+ /**
223
+ * Called when the save button is clicked or CTRL + s pressed. By default this simply fires
224
+ * the 'save' event, passing this.getForm().getValues() as the sole argument
225
+ */
226
+ onSave: function() {
227
+ this.fireEvent('save', this.getFormValues(), this);
228
+ },
229
+
230
+ /**
231
+ * Gets form values in a nicer way than getForm.getValues() does - calls getValue on each field.
232
+ * See http://www.diloc.de/blog/2008/03/05/how-to-submit-ext-forms-the-right-way/
233
+ * @return {Object} key: value pairings of form values
234
+ */
235
+ getFormValues: function() {
236
+ var form = this.getForm(),
237
+ values = {};
238
+
239
+ form.items.each(function(item) {
240
+ var func = (typeof item.getSubmitValue == "function") ? 'getSubmitValue' : 'getValue';
241
+
242
+ values[item.getName()] = item[func]();
243
+ }, this);
244
+
245
+ return values;
246
+ },
247
+
248
+ /**
249
+ * Called when the cancel button is clicked or ESC pressed. Fires the 'cancel' event. If this is
250
+ * an edit form the cancel event will be called with a single argument - the current instance
251
+ */
252
+ onCancel: function() {
253
+ this.fireEvent('cancel', this.instance, this);
254
+ }
255
+ });
File without changes
@@ -0,0 +1,219 @@
1
+ /**
2
+ * @class ExtMVC.App
3
+ * @extends Ext.util.Observable
4
+ * @cfg {Boolean} usesHistory True to automatically create required DOM elements for Ext.History,
5
+ * sets up a listener on Ext.History's change event to fire this.onHistoryChange. False by default
6
+ */
7
+ ExtMVC.App = Ext.extend(Ext.util.Observable, {
8
+ /**
9
+ * @constructor
10
+ * Sets up the Application - adds events, sets up namespaces, optionally sets up history.
11
+ * Fires the 'before-launch' event before initializing router, viewport and history.
12
+ * Calls this.launch() once everything else is set up (override the 'launch' method to provide your own logic).
13
+ * Fires the 'launched' event after calling this.launch()
14
+ */
15
+ constructor: function(config) {
16
+ ExtMVC.App.superclass.constructor.apply(this, arguments);
17
+
18
+ //apply configuration object and set up namespaces
19
+ Ext.apply(this, config || {});
20
+ window[this.name] = this;
21
+
22
+ this.initializeNamespaces();
23
+
24
+ // Ext.onReady(this.onReady, this);
25
+
26
+ this.on('launched', function() {
27
+ /**
28
+ * TODO: This used to reside in initializeHistory but this.launch() needs to be
29
+ * called before this dispatches so it is temporarily here... ugly though
30
+ */
31
+ if (this.usesHistory) {
32
+ if (this.dispatchHistoryOnLoad === true) {
33
+ Ext.History.init(function(history) {
34
+ var hash = document.location.hash.replace("#", "");
35
+ var params = this.router.recognise(hash);
36
+
37
+ if (params) {this.dispatch(params);}
38
+ }, this);
39
+ } else {
40
+ Ext.History.init();
41
+ }
42
+ }
43
+ }, this);
44
+ },
45
+
46
+ /**
47
+ * @private
48
+ * Called when Ext.onReady fires
49
+ */
50
+ onReady: function() {
51
+ if (this.fireEvent('before-launch', this)) {
52
+ this.initializeRouter();
53
+ // this.initializeViewport();
54
+ this.initializeEvents();
55
+
56
+ if (this.usesHistory === true) this.initializeHistory();
57
+
58
+ this.launch();
59
+ }
60
+ },
61
+
62
+ /**
63
+ * @property name
64
+ * @type String
65
+ * The application's name. This is used when creating namespaces for models, views and controllers,
66
+ * and automatically set up as a global variable reference to this application. Read only.
67
+ */
68
+ name: 'MyApp',
69
+
70
+ /**
71
+ * @property usesHistory
72
+ * @type Boolean
73
+ * True to automatically create required DOM elements for Ext.History,
74
+ * sets up a listener on Ext.History's change event to fire this.onHistoryChange.
75
+ * False by default
76
+ */
77
+ usesHistory: false,
78
+
79
+ /**
80
+ * @prop dispatchHistoryOnLoad
81
+ * @type Boolean
82
+ * If usesHistory is true and dispatchHistoryOnLoad is also true, the OS will attempt to match
83
+ * any string currently after the # in the url and dispatch to it
84
+ */
85
+ dispatchHistoryOnLoad: true,
86
+
87
+ /**
88
+ * Called when the application is booted up. Override this to provide your own startup logic (defaults to Ext.emptyFn)
89
+ */
90
+ launch: function() {
91
+ this.fireEvent('launched', this);
92
+ },
93
+
94
+ /**
95
+ * @property params
96
+ * @type Object
97
+ * An object containing the most current parameters (usually decoded from a url using this.router)
98
+ * e.g. {controller: 'index', action: 'welcome', id: 10}
99
+ */
100
+ params: {},
101
+
102
+ /**
103
+ * Dispatches a request to a registered controller.
104
+ * @param {Object} dispatchConfig A config object which should look something like this:
105
+ * {controller: 'MyController', action: 'index'}, where 'MyController' is the key for a controller
106
+ * which has been registered to the controller. If action is not specified, it defaults to 'index'
107
+ * @param {Object} scope The scope in which to fire the event (defaults to the controller)
108
+ * @param {Array} args An array of arguments which are passed to the controller action.
109
+ */
110
+ dispatch: function dispatch(dispatchConfig, scope, args) {
111
+ var dispatchConfig = dispatchConfig || {};
112
+ Ext.applyIf(dispatchConfig, {
113
+ action: 'index'
114
+ });
115
+
116
+ this.params = dispatchConfig;
117
+
118
+ var c = ExtMVC.getController(dispatchConfig.controller);
119
+ if (c != undefined) {
120
+ var action = c[dispatchConfig.action];
121
+
122
+ if (typeof action == "function") action.apply(scope || c, args || []);
123
+ else throw new Error(String.format("Action '{0}' not found on Controller '{1}'", dispatchConfig.action, dispatchConfig.controller));
124
+ }
125
+ },
126
+
127
+ /**
128
+ * Sets up a Router instance. This is called automatically before onLaunch()
129
+ * Add routes using this.router.connect
130
+ */
131
+ initializeRouter: function() {
132
+ if (this.router == undefined) {
133
+ this.router = new ExtMVC.router.Router();
134
+ ExtMVC.router.Router.defineRoutes(this.router);
135
+ }
136
+ },
137
+
138
+ /**
139
+ * Uses Ext.namespace to create packages view controllers, models and views
140
+ * E.g. if name = 'Blog' or this.name = 'Blog', this is the same as:
141
+ * Ext.ns('Blog', 'Blog.controllers', 'Blog.models', 'Blog.views')
142
+ */
143
+ initializeNamespaces: function initializeNamespaces(name) {
144
+ var name = name || this.name;
145
+ if (name) {
146
+ Ext.ns(name, name + '.controllers', name + '.models', name + '.views');
147
+ };
148
+ },
149
+
150
+ /**
151
+ * Creates the necessary DOM elements required for Ext.History to manage state
152
+ * Sets up listeners on Ext.History's change event to fire the dispatch() action in the normal way.
153
+ * This is not called automatically as not all applications will need it
154
+ */
155
+ initializeHistory: function initializeHistory() {
156
+ this.historyForm = Ext.getBody().createChild({
157
+ tag: 'form',
158
+ action: '#',
159
+ cls: 'x-hidden',
160
+ id: 'history-form',
161
+ children: [
162
+ {
163
+ tag: 'div',
164
+ children: [
165
+ {
166
+ tag: 'input',
167
+ id: 'x-history-field',
168
+ type: 'hidden'
169
+ },
170
+ {
171
+ tag: 'iframe',
172
+ id: 'x-history-frame'
173
+ }
174
+ ]
175
+ }
176
+ ]
177
+ });
178
+
179
+ Ext.History.on('change', this.onHistoryChange, this);
180
+ },
181
+
182
+ /**
183
+ * Takes a history token (anything after the # in the url), consults the router and dispatches
184
+ * to the appropriate controller and action if a match was found
185
+ * @param {String} token The url token (e.g. the token would be cont/act/id for a url like mydomain.com/#cont/act/id)
186
+ */
187
+ onHistoryChange: function onHistoryChange(token) {
188
+ var match = this.router.recognise(token);
189
+
190
+ if (match) {
191
+ this.dispatch(match, null, [{url: token}]);
192
+ };
193
+ },
194
+
195
+ /**
196
+ * Sets up events emitted by the Application
197
+ */
198
+ initializeEvents: function initializeEvents() {
199
+ this.addEvents(
200
+ /**
201
+ * @event before-launch
202
+ * Fires before this application launches
203
+ * @param {ExtMVC.App} this The application about to be launched
204
+ */
205
+ 'before-launch',
206
+
207
+ /**
208
+ * @event launched
209
+ * Fires once the application has been launched
210
+ * @param {ExtMVC.App} this The application which has been launched
211
+ */
212
+ 'launched'
213
+ );
214
+ }
215
+ });
216
+
217
+ ExtMVC.App.define = function(config) {
218
+ ExtMVC.app = new ExtMVC.App(config);
219
+ };