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,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
+ };