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,351 @@
1
+ /**
2
+ * @class ExtMVC.test.TestGrid
3
+ * @extends Ext.grid.GridPanel
4
+ * Customised GridPanel which shows the results of unit tests
5
+ */
6
+ ExtMVC.test.TestGrid = Ext.extend(Ext.grid.GridPanel, {
7
+
8
+ initComponent: function() {
9
+ var expander = new Ext.ux.grid.RowExpander({
10
+ tpl : new Ext.XTemplate(
11
+ '<tpl for="failingSpecs">',
12
+ '<div class="detail">',
13
+ '<tpl for="suite">',
14
+ '<h2>Suite: {name}</h2>',
15
+ '</tpl>',
16
+ 'Expectation: {description}',
17
+ '<ul class="assertions">',
18
+ '<tpl for="assertions">',
19
+ '<li>',
20
+ '{message}',
21
+ '</li>',
22
+ '</tpl>',
23
+ '</ul>',
24
+ '<div class="code">',
25
+ '{code}',
26
+ '</div>',
27
+ '</div>',
28
+ '</tpl>'
29
+ )
30
+ });
31
+
32
+ Ext.applyIf(this, {
33
+ plugins: expander,
34
+
35
+ store: new Ext.data.JsonStore({
36
+ data : [],
37
+ fields: [
38
+ {name: 'passes', type: 'int'},
39
+ {name: 'failures', type: 'int'},
40
+ {name: 'time', type: 'int'},
41
+ {name: 'total', type: 'int', mapping: 'specs'},
42
+ {name: 'failingSpecs'}
43
+ ]
44
+ }),
45
+
46
+ cm: new Ext.grid.ColumnModel({
47
+ defaults: {
48
+ sortable: false
49
+ },
50
+ columns: [
51
+ expander,
52
+ {
53
+ header : "Passes",
54
+ dataIndex: 'passes'
55
+ },
56
+ {
57
+ header : "Failures",
58
+ dataIndex: 'failures'
59
+ },
60
+ {
61
+ header : "Total",
62
+ dataIndex: 'total'
63
+ },
64
+ {
65
+ header : "Time (ms)",
66
+ dataIndex: 'time'
67
+ }
68
+ ]
69
+ }),
70
+
71
+ viewConfig: {
72
+ forceFit: true,
73
+ getRowClass: function(record, index) {
74
+ return record.get('failures') == 0 ? 'pass' : 'fail';
75
+ }
76
+ }
77
+ });
78
+
79
+ ExtMVC.test.TestGrid.superclass.initComponent.apply(this, arguments);
80
+
81
+ /**
82
+ * When a new row has been inserted, expand it if the tests didn't all pass
83
+ * We have to do a little hack to set the rowIndex inside here, as the RowExpander
84
+ * plugin errors otherwise :/
85
+ */
86
+ this.getView().on('rowsinserted', function(view, firstRow, lastRow) {
87
+ var record = this.store.getAt(firstRow);
88
+
89
+ if (record.get('failures') > 0) {
90
+ //first, collapse all rows
91
+ this.store.each(function(record, index) {
92
+ var row = view.getRow(index);
93
+ row.rowIndex = index;
94
+
95
+ expander.collapseRow(row);
96
+ });
97
+
98
+ //now, expand the last row as it contains errors
99
+ var row = view.getRow(firstRow);
100
+ row.rowIndex = firstRow;
101
+
102
+ expander.expandRow(row);
103
+
104
+ row.scrollIntoView(this.ownerCt);
105
+ };
106
+ }, this);
107
+ }
108
+ });
109
+
110
+
111
+ /*!
112
+ * Ext JS Library 3.0+
113
+ * Copyright(c) 2006-2009 Ext JS, LLC
114
+ * licensing@extjs.com
115
+ * http://www.extjs.com/license
116
+ */
117
+ Ext.ns('Ext.ux.grid');
118
+
119
+ /**
120
+ * @class Ext.ux.grid.RowExpander
121
+ * @extends Ext.util.Observable
122
+ * Plugin (ptype = 'rowexpander') that adds the ability to have a Column in a grid which enables
123
+ * a second row body which expands/contracts. The expand/contract behavior is configurable to react
124
+ * on clicking of the column, double click of the row, and/or hitting enter while a row is selected.
125
+ *
126
+ * @ptype rowexpander
127
+ */
128
+ Ext.ux.grid.RowExpander = Ext.extend(Ext.util.Observable, {
129
+ /**
130
+ * @cfg {Boolean} expandOnEnter
131
+ * <tt>true</tt> to toggle selected row(s) between expanded/collapsed when the enter
132
+ * key is pressed (defaults to <tt>true</tt>).
133
+ */
134
+ expandOnEnter : true,
135
+ /**
136
+ * @cfg {Boolean} expandOnDblClick
137
+ * <tt>true</tt> to toggle a row between expanded/collapsed when double clicked
138
+ * (defaults to <tt>true</tt>).
139
+ */
140
+ expandOnDblClick : true,
141
+
142
+ header : '',
143
+ width : 20,
144
+ sortable : false,
145
+ fixed : true,
146
+ menuDisabled : true,
147
+ dataIndex : '',
148
+ id : 'expander',
149
+ lazyRender : true,
150
+ enableCaching : true,
151
+
152
+ constructor: function(config){
153
+ Ext.apply(this, config);
154
+
155
+ this.addEvents({
156
+ /**
157
+ * @event beforeexpand
158
+ * Fires before the row expands. Have the listener return false to prevent the row from expanding.
159
+ * @param {Object} this RowExpander object.
160
+ * @param {Object} Ext.data.Record Record for the selected row.
161
+ * @param {Object} body body element for the secondary row.
162
+ * @param {Number} rowIndex The current row index.
163
+ */
164
+ beforeexpand: true,
165
+ /**
166
+ * @event expand
167
+ * Fires after the row expands.
168
+ * @param {Object} this RowExpander object.
169
+ * @param {Object} Ext.data.Record Record for the selected row.
170
+ * @param {Object} body body element for the secondary row.
171
+ * @param {Number} rowIndex The current row index.
172
+ */
173
+ expand: true,
174
+ /**
175
+ * @event beforecollapse
176
+ * Fires before the row collapses. Have the listener return false to prevent the row from collapsing.
177
+ * @param {Object} this RowExpander object.
178
+ * @param {Object} Ext.data.Record Record for the selected row.
179
+ * @param {Object} body body element for the secondary row.
180
+ * @param {Number} rowIndex The current row index.
181
+ */
182
+ beforecollapse: true,
183
+ /**
184
+ * @event collapse
185
+ * Fires after the row collapses.
186
+ * @param {Object} this RowExpander object.
187
+ * @param {Object} Ext.data.Record Record for the selected row.
188
+ * @param {Object} body body element for the secondary row.
189
+ * @param {Number} rowIndex The current row index.
190
+ */
191
+ collapse: true
192
+ });
193
+
194
+ Ext.ux.grid.RowExpander.superclass.constructor.call(this);
195
+
196
+ if(this.tpl){
197
+ if(typeof this.tpl == 'string'){
198
+ this.tpl = new Ext.Template(this.tpl);
199
+ }
200
+ this.tpl.compile();
201
+ }
202
+
203
+ this.state = {};
204
+ this.bodyContent = {};
205
+ },
206
+
207
+ getRowClass : function(record, rowIndex, p, ds){
208
+ p.cols = p.cols-1;
209
+ var content = this.bodyContent[record.id];
210
+ if(!content && !this.lazyRender){
211
+ content = this.getBodyContent(record, rowIndex);
212
+ }
213
+ if(content){
214
+ p.body = content;
215
+ }
216
+ return this.state[record.id] ? 'x-grid3-row-expanded' : 'x-grid3-row-collapsed';
217
+ },
218
+
219
+ init : function(grid){
220
+ this.grid = grid;
221
+
222
+ var view = grid.getView();
223
+ view.getRowClass = view.getRowClass.createSequence(this.getRowClass, this);
224
+
225
+ view.enableRowBody = true;
226
+
227
+
228
+ grid.on('render', this.onRender, this);
229
+ grid.on('destroy', this.onDestroy, this);
230
+ },
231
+
232
+ // @private
233
+ onRender: function() {
234
+ var grid = this.grid;
235
+ var mainBody = grid.getView().mainBody;
236
+ mainBody.on('mousedown', this.onMouseDown, this, {delegate: '.x-grid3-row-expander'});
237
+ if (this.expandOnEnter) {
238
+ this.keyNav = new Ext.KeyNav(this.grid.getGridEl(), {
239
+ 'enter' : this.onEnter,
240
+ scope: this
241
+ });
242
+ }
243
+ if (this.expandOnDblClick) {
244
+ grid.on('rowdblclick', this.onRowDblClick, this);
245
+ }
246
+ },
247
+
248
+ // @private
249
+ onDestroy: function() {
250
+ if(this.keyNav){
251
+ this.keyNav.disable();
252
+ delete this.keyNav;
253
+ }
254
+ /*
255
+ * A majority of the time, the plugin will be destroyed along with the grid,
256
+ * which means the mainBody won't be available. On the off chance that the plugin
257
+ * isn't destroyed with the grid, take care of removing the listener.
258
+ */
259
+ var mainBody = this.grid.getView().mainBody;
260
+ if(mainBody){
261
+ mainBody.un('mousedown', this.onMouseDown, this);
262
+ }
263
+ },
264
+ // @private
265
+ onRowDblClick: function(grid, rowIdx, e) {
266
+ this.toggleRow(rowIdx);
267
+ },
268
+
269
+ onEnter: function(e) {
270
+ var g = this.grid;
271
+ var sm = g.getSelectionModel();
272
+ var sels = sm.getSelections();
273
+ for (var i = 0, len = sels.length; i < len; i++) {
274
+ var rowIdx = g.getStore().indexOf(sels[i]);
275
+ this.toggleRow(rowIdx);
276
+ }
277
+ },
278
+
279
+ getBodyContent : function(record, index){
280
+ if(!this.enableCaching){
281
+ return this.tpl.apply(record.data);
282
+ }
283
+ var content = this.bodyContent[record.id];
284
+ if(!content){
285
+ content = this.tpl.apply(record.data);
286
+ this.bodyContent[record.id] = content;
287
+ }
288
+ return content;
289
+ },
290
+
291
+ onMouseDown : function(e, t){
292
+ e.stopEvent();
293
+ var row = e.getTarget('.x-grid3-row');
294
+ this.toggleRow(row);
295
+ },
296
+
297
+ renderer : function(v, p, record){
298
+ p.cellAttr = 'rowspan="2"';
299
+ return '<div class="x-grid3-row-expander">&#160;</div>';
300
+ },
301
+
302
+ beforeExpand : function(record, body, rowIndex){
303
+ if(this.fireEvent('beforeexpand', this, record, body, rowIndex) !== false){
304
+ if(this.tpl && this.lazyRender){
305
+ body.innerHTML = this.getBodyContent(record, rowIndex);
306
+ }
307
+ return true;
308
+ }else{
309
+ return false;
310
+ }
311
+ },
312
+
313
+ toggleRow : function(row){
314
+ if(typeof row == 'number'){
315
+ row = this.grid.view.getRow(row);
316
+ }
317
+ this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'collapseRow'](row);
318
+ },
319
+
320
+ expandRow : function(row){
321
+ if(typeof row == 'number'){
322
+ row = this.grid.view.getRow(row);
323
+ }
324
+
325
+ var record = this.grid.store.getAt(row.rowIndex);
326
+ var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row);
327
+ if(this.beforeExpand(record, body, row.rowIndex)){
328
+ this.state[record.id] = true;
329
+ Ext.fly(row).replaceClass('x-grid3-row-collapsed', 'x-grid3-row-expanded');
330
+ this.fireEvent('expand', this, record, body, row.rowIndex);
331
+ }
332
+ },
333
+
334
+ collapseRow : function(row){
335
+ if(typeof row == 'number'){
336
+ row = this.grid.view.getRow(row);
337
+ }
338
+ var record = this.grid.store.getAt(row.rowIndex);
339
+ var body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true);
340
+ if(this.fireEvent('beforecollapse', this, record, body, row.rowIndex) !== false){
341
+ this.state[record.id] = false;
342
+ Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed');
343
+ this.fireEvent('collapse', this, record, body, row.rowIndex);
344
+ }
345
+ }
346
+ });
347
+
348
+ Ext.preg('rowexpander', Ext.ux.grid.RowExpander);
349
+
350
+ //backwards compat
351
+ Ext.grid.RowExpander = Ext.ux.grid.RowExpander;
@@ -0,0 +1,110 @@
1
+ /**
2
+ * @class ExtMVC.test.TestRunner
3
+ * @extends Ext.util.Observable
4
+ * Wraps JSpec to provide normal Ext-style events
5
+ */
6
+ ExtMVC.test.TestRunner = Ext.extend(Ext.util.Observable, {
7
+
8
+ constructor: function(config) {
9
+ ExtMVC.test.TestRunner.superclass.constructor.apply(this, arguments);
10
+
11
+ Ext.apply(this, {
12
+ /**
13
+ * @property hasRecentFailures
14
+ * @type Boolean
15
+ * True if the last full suite run had failures
16
+ */
17
+ hasRecentFailures: false,
18
+
19
+ /**
20
+ * @property fullRun
21
+ * @type Boolean
22
+ * True if the last run was a full run (as opposed to only running a subset of suites)
23
+ */
24
+ fullRun: false
25
+ });
26
+
27
+ this.addEvents(
28
+ /**
29
+ * @event starting
30
+ * Fires when the runner starts running specs
31
+ */
32
+ 'starting',
33
+
34
+ /**
35
+ * @event finished
36
+ * Fires when the runner has finished running a batch of tests
37
+ * @param {Object} stats Test pass stats
38
+ */
39
+ 'finished'
40
+ );
41
+
42
+ this.tests = [];
43
+ },
44
+
45
+ onJSpecFinish: function(options) {
46
+ runner.fireEvent('finished', JSpec.stats);
47
+
48
+ if (runner.fullRun == true) {
49
+ runner.hasRecentFailures = JSpec.stats.failures > 0;
50
+ }
51
+ },
52
+
53
+ /**
54
+ * Adds an array of test suites
55
+ * @param {Array} tests Array of urls to load test suites from
56
+ */
57
+ addTests: function(tests) {
58
+ this.tests = this.tests.concat(tests);
59
+ },
60
+
61
+ /**
62
+ * Executes an array of test files and fires the 'finished' event when complete
63
+ * @param {Array} tests Optional array of test files to run (defaults to all tests)
64
+ */
65
+ runTests: function(tests) {
66
+ //we're doing a full run if a test subset array was not passed in
67
+ this.fullRun = !Ext.isArray(tests);
68
+
69
+ tests = tests || this.tests;
70
+
71
+ delete JSpec;
72
+ var filename = "../vendor/jspec/lib/jspec.js",
73
+ callback = function() {
74
+ this.fireEvent('starting');
75
+
76
+ JSpec.options.formatter = ExtMVC.test.JSpecFormatter;
77
+
78
+ Ext.each(tests, function(test) {
79
+ JSpec.exec(test);
80
+ }, this);
81
+
82
+ JSpec.include({
83
+ utilities : {
84
+ runner: this
85
+ },
86
+ reporting : this.onJSpecFinish
87
+ });
88
+
89
+ JSpec.run({ failuresOnly: false }).report();
90
+ }.createDelegate(this);
91
+
92
+ var script = document.createElement('script');
93
+ script.type = "text/javascript";
94
+ script.src = filename;
95
+
96
+ //IE has a different way of handling <script> loads, so we need to check for it here
97
+ if (script.readyState) {
98
+ script.onreadystatechange = function(){
99
+ if (script.readyState == "loaded" || script.readyState == "complete") {
100
+ script.onreadystatechange = null;
101
+ callback();
102
+ }
103
+ };
104
+ } else {
105
+ script.onload = callback;
106
+ }
107
+
108
+ document.getElementsByTagName("head")[0].appendChild(script);
109
+ }
110
+ });