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.
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/extjs-mvc.rb +0 -14
- data/lib/extjs-mvc/api.rb +14 -27
- data/lib/extjs-mvc/src/App.js +219 -0
- data/lib/extjs-mvc/src/MVC.js +260 -0
- data/lib/extjs-mvc/src/Presenter.js +52 -0
- data/lib/extjs-mvc/src/README.rdoc +69 -0
- data/lib/extjs-mvc/src/controller/Controller.js +278 -0
- data/lib/extjs-mvc/src/controller/CrudController.js +460 -0
- data/lib/extjs-mvc/src/lib/Array.js +26 -0
- data/lib/extjs-mvc/src/lib/Booter.js +417 -0
- data/lib/extjs-mvc/src/lib/ClassManager.js +191 -0
- data/lib/extjs-mvc/src/lib/ControllerClassManager.js +95 -0
- data/lib/extjs-mvc/src/lib/Dependencies.js +44 -0
- data/lib/extjs-mvc/src/lib/DispatchMatcher.js +98 -0
- data/lib/extjs-mvc/src/lib/Dispatcher.js +129 -0
- data/lib/extjs-mvc/src/lib/Environment.js +43 -0
- data/lib/extjs-mvc/src/lib/Inflector.js +155 -0
- data/lib/extjs-mvc/src/lib/ModelClassManager.js +19 -0
- data/lib/extjs-mvc/src/lib/Route.js +139 -0
- data/lib/extjs-mvc/src/lib/Router.js +282 -0
- data/lib/extjs-mvc/src/lib/String.js +94 -0
- data/lib/extjs-mvc/src/lib/ViewClassManager.js +229 -0
- data/lib/extjs-mvc/src/lib/notes.txt +32 -0
- data/lib/extjs-mvc/src/model/AdapterManager.js +30 -0
- data/lib/extjs-mvc/src/model/Association.js +26 -0
- data/lib/extjs-mvc/src/model/Base.js +63 -0
- data/lib/extjs-mvc/src/model/BelongsToAssociation.js +116 -0
- data/lib/extjs-mvc/src/model/Cache.js +131 -0
- data/lib/extjs-mvc/src/model/HasManyAssociation.js +160 -0
- data/lib/extjs-mvc/src/model/Model.js +331 -0
- data/lib/extjs-mvc/src/model/UrlBuilder.js +106 -0
- data/lib/extjs-mvc/src/model/adapters/AbstractAdapter.js +296 -0
- data/lib/extjs-mvc/src/model/adapters/MemoryAdapter.js +103 -0
- data/lib/extjs-mvc/src/model/adapters/RESTAdapter.js +345 -0
- data/lib/extjs-mvc/src/model/adapters/RESTJSONAdapter.js +68 -0
- data/lib/extjs-mvc/src/model/adapters/notes.txt +42 -0
- data/lib/extjs-mvc/src/model/associations/Association.js +192 -0
- data/lib/extjs-mvc/src/model/associations/notes.txt +87 -0
- data/lib/extjs-mvc/src/model/validations/Errors.js +136 -0
- data/lib/extjs-mvc/src/model/validations/Plugin.js +139 -0
- data/lib/extjs-mvc/src/model/validations/Validations.js +276 -0
- data/lib/extjs-mvc/src/notes/Charts.graffle +0 -0
- data/lib/extjs-mvc/src/overrides/Ext.Component.js +21 -0
- data/lib/extjs-mvc/src/overrides/Ext.extend.js +142 -0
- data/lib/extjs-mvc/src/spec/Array.spec.js +15 -0
- data/lib/extjs-mvc/src/spec/ExtMVC.spec.js +65 -0
- data/lib/extjs-mvc/src/spec/Model.spec.js +370 -0
- data/lib/extjs-mvc/src/spec/OS.spec.js +83 -0
- data/lib/extjs-mvc/src/spec/Router.spec.js +99 -0
- data/lib/extjs-mvc/src/spec/SpecHelper.js +106 -0
- data/lib/extjs-mvc/src/spec/String.spec.js +83 -0
- data/lib/extjs-mvc/src/spec/model/AbstractAdapter.spec.js +49 -0
- data/lib/extjs-mvc/src/spec/model/Associations.spec.js +99 -0
- data/lib/extjs-mvc/src/spec/model/Cache.spec.js +5 -0
- data/lib/extjs-mvc/src/spec/model/RESTAdapter.spec.js +19 -0
- data/lib/extjs-mvc/src/spec/model/ValidationErrors.spec.js +64 -0
- data/lib/extjs-mvc/src/spec/model/Validations.spec.js +166 -0
- data/lib/extjs-mvc/src/spec/model/ValidationsPlugin.spec.js +108 -0
- data/lib/extjs-mvc/src/spec/suite.html +60 -0
- data/lib/extjs-mvc/src/specs-old/JSSpec.css +216 -0
- data/lib/extjs-mvc/src/specs-old/JSSpec.js +1512 -0
- data/lib/extjs-mvc/src/specs-old/all.html +66 -0
- data/lib/extjs-mvc/src/specs-old/base.js +14 -0
- data/lib/extjs-mvc/src/specs-old/controller.js +17 -0
- data/lib/extjs-mvc/src/specs-old/diff_match_patch.js +1 -0
- data/lib/extjs-mvc/src/specs-old/model.js +70 -0
- data/lib/extjs-mvc/src/specs-old/route.js +38 -0
- data/lib/extjs-mvc/src/specs-old/router.js +59 -0
- data/lib/extjs-mvc/src/specs-old/string.js +22 -0
- data/lib/extjs-mvc/src/testrunner/JSpecFormatter.js +111 -0
- data/lib/extjs-mvc/src/testrunner/TestClient.js +181 -0
- data/lib/extjs-mvc/src/testrunner/TestGrid.js +351 -0
- data/lib/extjs-mvc/src/testrunner/TestRunner.js +110 -0
- data/lib/extjs-mvc/src/testrunner/TestViewport.js +94 -0
- data/lib/extjs-mvc/src/vendor.yml +30 -0
- data/lib/extjs-mvc/src/vendor/ext-3.1.1/vendor.yml +16 -0
- data/lib/extjs-mvc/src/view/FormWindow.js +184 -0
- data/lib/extjs-mvc/src/view/HasManyEditorGridPanel.js +211 -0
- data/lib/extjs-mvc/src/view/scaffold/Edit.js +46 -0
- data/lib/extjs-mvc/src/view/scaffold/Index.js +561 -0
- data/lib/extjs-mvc/src/view/scaffold/New.js +20 -0
- data/lib/extjs-mvc/src/view/scaffold/ScaffoldFormPanel.js +255 -0
- data/lib/{vendor.yml → extjs-mvc/vendor.yml} +0 -0
- data/test/app/vendor/extjs-mvc/App.js +219 -0
- data/test/app/vendor/extjs-mvc/MVC.js +260 -0
- data/test/app/vendor/extjs-mvc/Presenter.js +52 -0
- data/test/app/vendor/extjs-mvc/README.rdoc +69 -0
- data/test/app/vendor/extjs-mvc/controller/Controller.js +278 -0
- data/test/app/vendor/extjs-mvc/controller/CrudController.js +460 -0
- data/test/app/vendor/extjs-mvc/lib/Array.js +26 -0
- data/test/app/vendor/extjs-mvc/lib/Booter.js +417 -0
- data/test/app/vendor/extjs-mvc/lib/ClassManager.js +191 -0
- data/test/app/vendor/extjs-mvc/lib/ControllerClassManager.js +95 -0
- data/test/app/vendor/extjs-mvc/lib/Dependencies.js +44 -0
- data/test/app/vendor/extjs-mvc/lib/DispatchMatcher.js +98 -0
- data/test/app/vendor/extjs-mvc/lib/Dispatcher.js +129 -0
- data/test/app/vendor/extjs-mvc/lib/Environment.js +43 -0
- data/test/app/vendor/extjs-mvc/lib/Inflector.js +155 -0
- data/test/app/vendor/extjs-mvc/lib/ModelClassManager.js +19 -0
- data/test/app/vendor/extjs-mvc/lib/Route.js +139 -0
- data/test/app/vendor/extjs-mvc/lib/Router.js +282 -0
- data/test/app/vendor/extjs-mvc/lib/String.js +94 -0
- data/test/app/vendor/extjs-mvc/lib/ViewClassManager.js +229 -0
- data/test/app/vendor/extjs-mvc/lib/notes.txt +32 -0
- data/test/app/vendor/extjs-mvc/model/AdapterManager.js +30 -0
- data/test/app/vendor/extjs-mvc/model/Association.js +26 -0
- data/test/app/vendor/extjs-mvc/model/Base.js +63 -0
- data/test/app/vendor/extjs-mvc/model/BelongsToAssociation.js +116 -0
- data/test/app/vendor/extjs-mvc/model/Cache.js +131 -0
- data/test/app/vendor/extjs-mvc/model/HasManyAssociation.js +160 -0
- data/test/app/vendor/extjs-mvc/model/Model.js +331 -0
- data/test/app/vendor/extjs-mvc/model/UrlBuilder.js +106 -0
- data/test/app/vendor/extjs-mvc/model/adapters/AbstractAdapter.js +296 -0
- data/test/app/vendor/extjs-mvc/model/adapters/MemoryAdapter.js +103 -0
- data/test/app/vendor/extjs-mvc/model/adapters/RESTAdapter.js +345 -0
- data/test/app/vendor/extjs-mvc/model/adapters/RESTJSONAdapter.js +68 -0
- data/test/app/vendor/extjs-mvc/model/adapters/notes.txt +42 -0
- data/test/app/vendor/extjs-mvc/model/associations/Association.js +192 -0
- data/test/app/vendor/extjs-mvc/model/associations/notes.txt +87 -0
- data/test/app/vendor/extjs-mvc/model/validations/Errors.js +136 -0
- data/test/app/vendor/extjs-mvc/model/validations/Plugin.js +139 -0
- data/test/app/vendor/extjs-mvc/model/validations/Validations.js +276 -0
- data/test/app/vendor/extjs-mvc/notes/Charts.graffle +0 -0
- data/test/app/vendor/extjs-mvc/overrides/Ext.Component.js +21 -0
- data/test/app/vendor/extjs-mvc/overrides/Ext.extend.js +142 -0
- data/test/app/vendor/extjs-mvc/spec/Array.spec.js +15 -0
- data/test/app/vendor/extjs-mvc/spec/ExtMVC.spec.js +65 -0
- data/test/app/vendor/extjs-mvc/spec/Model.spec.js +370 -0
- data/test/app/vendor/extjs-mvc/spec/OS.spec.js +83 -0
- data/test/app/vendor/extjs-mvc/spec/Router.spec.js +99 -0
- data/test/app/vendor/extjs-mvc/spec/SpecHelper.js +106 -0
- data/test/app/vendor/extjs-mvc/spec/String.spec.js +83 -0
- data/test/app/vendor/extjs-mvc/spec/model/AbstractAdapter.spec.js +49 -0
- data/test/app/vendor/extjs-mvc/spec/model/Associations.spec.js +99 -0
- data/test/app/vendor/extjs-mvc/spec/model/Cache.spec.js +5 -0
- data/test/app/vendor/extjs-mvc/spec/model/RESTAdapter.spec.js +19 -0
- data/test/app/vendor/extjs-mvc/spec/model/ValidationErrors.spec.js +64 -0
- data/test/app/vendor/extjs-mvc/spec/model/Validations.spec.js +166 -0
- data/test/app/vendor/extjs-mvc/spec/model/ValidationsPlugin.spec.js +108 -0
- data/test/app/vendor/extjs-mvc/spec/suite.html +60 -0
- data/test/app/vendor/extjs-mvc/specs-old/JSSpec.css +216 -0
- data/test/app/vendor/extjs-mvc/specs-old/JSSpec.js +1512 -0
- data/test/app/vendor/extjs-mvc/specs-old/all.html +66 -0
- data/test/app/vendor/extjs-mvc/specs-old/base.js +14 -0
- data/test/app/vendor/extjs-mvc/specs-old/controller.js +17 -0
- data/test/app/vendor/extjs-mvc/specs-old/diff_match_patch.js +1 -0
- data/test/app/vendor/extjs-mvc/specs-old/model.js +70 -0
- data/test/app/vendor/extjs-mvc/specs-old/route.js +38 -0
- data/test/app/vendor/extjs-mvc/specs-old/router.js +59 -0
- data/test/app/vendor/extjs-mvc/specs-old/string.js +22 -0
- data/test/app/vendor/extjs-mvc/testrunner/JSpecFormatter.js +111 -0
- data/test/app/vendor/extjs-mvc/testrunner/TestClient.js +181 -0
- data/test/app/vendor/extjs-mvc/testrunner/TestGrid.js +351 -0
- data/test/app/vendor/extjs-mvc/testrunner/TestRunner.js +110 -0
- data/test/app/vendor/extjs-mvc/testrunner/TestViewport.js +94 -0
- data/test/app/vendor/extjs-mvc/vendor.yml +30 -0
- data/test/app/vendor/extjs-mvc/vendor/ext-3.1.1/vendor.yml +16 -0
- data/test/app/vendor/extjs-mvc/view/FormWindow.js +184 -0
- data/test/app/vendor/extjs-mvc/view/HasManyEditorGridPanel.js +211 -0
- data/test/app/vendor/extjs-mvc/view/scaffold/Edit.js +46 -0
- data/test/app/vendor/extjs-mvc/view/scaffold/Index.js +561 -0
- data/test/app/vendor/extjs-mvc/view/scaffold/New.js +20 -0
- data/test/app/vendor/extjs-mvc/view/scaffold/ScaffoldFormPanel.js +255 -0
- data/test/helper.rb +7 -1
- data/test/test_extjs-mvc.rb +46 -0
- metadata +167 -7
- data/test/test_extjs-mvc-gem.rb +0 -7
@@ -0,0 +1,46 @@
|
|
1
|
+
/**
|
2
|
+
* @class ExtMVC.view.scaffold.Edit
|
3
|
+
* @extends ExtMVC.view.scaffold.ScaffoldFormPanel
|
4
|
+
* Shows a generic edit form for a given model
|
5
|
+
*/
|
6
|
+
ExtMVC.registerView('scaffold', 'edit', {
|
7
|
+
xtype : 'scaffold_form',
|
8
|
+
registerXType: 'scaffold_edit',
|
9
|
+
|
10
|
+
/**
|
11
|
+
* Sets the panel's title, if not already set
|
12
|
+
*/
|
13
|
+
initComponent: function() {
|
14
|
+
Ext.applyIf(this, {
|
15
|
+
title: 'Edit ' + this.model.prototype.singularHumanName
|
16
|
+
});
|
17
|
+
|
18
|
+
ExtMVC.getView('scaffold', 'form').prototype.initComponent.apply(this, arguments);
|
19
|
+
},
|
20
|
+
|
21
|
+
/**
|
22
|
+
* Loads the given record into the form and maintains a reference to it so that it can be returned
|
23
|
+
* when the 'save' event is fired
|
24
|
+
* @param {ExtMVC.Model.Base} instance The model instance to load into this form
|
25
|
+
*/
|
26
|
+
loadRecord: function(instance) {
|
27
|
+
this.instance = instance;
|
28
|
+
this.getForm().loadRecord(instance);
|
29
|
+
},
|
30
|
+
|
31
|
+
/**
|
32
|
+
* Called when the save button is clicked or CTRL + s pressed. By default this simply fires
|
33
|
+
* the 'save' event, passing this.getForm().getValues() as the sole argument
|
34
|
+
*/
|
35
|
+
onSave: function() {
|
36
|
+
this.fireEvent('save', this.instance, this.getFormValues(), this);
|
37
|
+
}
|
38
|
+
|
39
|
+
/**
|
40
|
+
* @event save
|
41
|
+
* Fired when the user clicks the save button, or presses ctrl + s
|
42
|
+
* @param {ExtMVC.model.Base} instance The existing instance that is to be updated
|
43
|
+
* @param {Object} values The values entered into the form
|
44
|
+
* @param {ExtMVC.view.scaffold.ScaffoldFormPanel} this The form panel
|
45
|
+
*/
|
46
|
+
});
|
@@ -0,0 +1,561 @@
|
|
1
|
+
/**
|
2
|
+
* @class ExtMVC.view.scaffold.Index
|
3
|
+
* @extends Ext.grid.GridPanel
|
4
|
+
* A default index view for a scaffold (a paging grid with double-click to edit)
|
5
|
+
*/
|
6
|
+
// ExtMVC.view.scaffold.Index = Ext.extend(Ext.grid.GridPanel, {
|
7
|
+
ExtMVC.registerView('scaffold', 'index', {
|
8
|
+
xtype : 'grid',
|
9
|
+
registerXType: 'scaffold_grid',
|
10
|
+
|
11
|
+
constructor: function(config) {
|
12
|
+
config = config || {};
|
13
|
+
|
14
|
+
this.model = config.model;
|
15
|
+
|
16
|
+
if (this.model == undefined) throw new Error("No model supplied to scaffold Index view");
|
17
|
+
|
18
|
+
this.controller = this.controller || config.controller;
|
19
|
+
|
20
|
+
//we can't put these in applyIf block below as the functions are executed immediately
|
21
|
+
if (config.columns == undefined && config.colModel == undefined && config.cm == undefined) {
|
22
|
+
config.columns = this.buildColumns(this.model);
|
23
|
+
}
|
24
|
+
config.store = config.store || this.model.find();
|
25
|
+
|
26
|
+
Ext.applyIf(config, {
|
27
|
+
viewConfig: { forceFit: true },
|
28
|
+
id: String.format("{0}_index", this.model.prototype.tableName),
|
29
|
+
|
30
|
+
loadMask: true,
|
31
|
+
|
32
|
+
/**
|
33
|
+
* @property dblClickToEdit
|
34
|
+
* @type Boolean
|
35
|
+
* True to edit a record when it is double clicked (defaults to true)
|
36
|
+
*/
|
37
|
+
dblClickToEdit: true
|
38
|
+
});
|
39
|
+
|
40
|
+
Ext.grid.GridPanel.prototype.constructor.call(this, config);
|
41
|
+
|
42
|
+
this.initListeners();
|
43
|
+
},
|
44
|
+
|
45
|
+
initComponent: function() {
|
46
|
+
var tbarConfig = this.hasTopToolbar ? this.buildTopToolbar() : null;
|
47
|
+
var bbar = this.hasBottomToolbar ? this.buildBottomToolbar(this.store) : null;
|
48
|
+
|
49
|
+
Ext.applyIf(this, {
|
50
|
+
title: this.getTitle(),
|
51
|
+
tbar: tbarConfig,
|
52
|
+
bbar: bbar,
|
53
|
+
|
54
|
+
keys: [
|
55
|
+
{
|
56
|
+
key: 'a',
|
57
|
+
scope: this,
|
58
|
+
handler: this.onAdd
|
59
|
+
},
|
60
|
+
{
|
61
|
+
key: 'e',
|
62
|
+
scope: this,
|
63
|
+
handler: this.onEdit
|
64
|
+
},
|
65
|
+
{
|
66
|
+
key: Ext.EventObject.DELETE,
|
67
|
+
scope: this,
|
68
|
+
handler: this.onDelete
|
69
|
+
}
|
70
|
+
]
|
71
|
+
});
|
72
|
+
|
73
|
+
Ext.grid.GridPanel.prototype.initComponent.apply(this, arguments);
|
74
|
+
},
|
75
|
+
|
76
|
+
/**
|
77
|
+
* Sets up events emitted by the grid panel
|
78
|
+
*/
|
79
|
+
initEvents: function() {
|
80
|
+
this.addEvents(
|
81
|
+
/**
|
82
|
+
* @event edit
|
83
|
+
* Fired when the user wishes to edit a particular record
|
84
|
+
* @param {ExtMVC.Model.Base} instance The instance of the model the user wishes to edit
|
85
|
+
*/
|
86
|
+
'edit',
|
87
|
+
|
88
|
+
/**
|
89
|
+
* @event new
|
90
|
+
* Fired when the user wishes to add a new record
|
91
|
+
*/
|
92
|
+
'new',
|
93
|
+
|
94
|
+
/**
|
95
|
+
* @event delete
|
96
|
+
* Fired when the user wishes to destroy a particular record
|
97
|
+
* @param {ExtMVC.Model.Base} instance The instance fo the model the user wishes to destroy
|
98
|
+
*/
|
99
|
+
'delete'
|
100
|
+
);
|
101
|
+
|
102
|
+
Ext.grid.GridPanel.prototype.initEvents.apply(this, arguments);
|
103
|
+
},
|
104
|
+
|
105
|
+
/**
|
106
|
+
* Listens to clicks in the grid and contained components and takes action accordingly.
|
107
|
+
* Mostly, this is simply a case of capturing events received and re-emitting normalized events
|
108
|
+
*/
|
109
|
+
initListeners: function() {
|
110
|
+
if (this.dblClickToEdit === true) {
|
111
|
+
this.on({
|
112
|
+
scope : this,
|
113
|
+
'rowdblclick': this.onEdit
|
114
|
+
});
|
115
|
+
}
|
116
|
+
|
117
|
+
if (this.controller != undefined) {
|
118
|
+
this.controller.on('delete', this.refreshStore, this);
|
119
|
+
}
|
120
|
+
},
|
121
|
+
|
122
|
+
//removes any controller listeners added by initListeners
|
123
|
+
destroy: function() {
|
124
|
+
if (this.controller != undefined) {
|
125
|
+
this.controller.un('delete', this.refreshStore, this);
|
126
|
+
}
|
127
|
+
|
128
|
+
Ext.grid.GridPanel.prototype.destroy.apply(this, arguments);
|
129
|
+
},
|
130
|
+
|
131
|
+
/**
|
132
|
+
* Calls reload on the grid's store
|
133
|
+
*/
|
134
|
+
refreshStore: function() {
|
135
|
+
//NOTE: For some reason this.store is undefined here, but getCmp on this.id works :/
|
136
|
+
var store = Ext.getCmp(this.id).store;
|
137
|
+
store.reload();
|
138
|
+
},
|
139
|
+
|
140
|
+
/**
|
141
|
+
* Returns the title to give to this grid. If this view is currently representing a model called User,
|
142
|
+
* this will return "All Users". Override to set your own grid title
|
143
|
+
* @return {String} The title to give the grid
|
144
|
+
*/
|
145
|
+
getTitle: function() {
|
146
|
+
return String.format("All {0}", this.model.prototype.pluralHumanName);
|
147
|
+
},
|
148
|
+
|
149
|
+
/**
|
150
|
+
* @property preferredColumns
|
151
|
+
* @type Array
|
152
|
+
* An array of columns to show first in the grid, if they exist
|
153
|
+
* Overwrite ExtMVC.view.scaffold.Index.preferredColumns if required
|
154
|
+
*/
|
155
|
+
preferredColumns: ['id', 'title', 'name', 'first_name', 'last_name', 'login', 'username', 'email', 'email_address', 'content', 'message', 'body'],
|
156
|
+
|
157
|
+
/**
|
158
|
+
* @property ignoreColumns
|
159
|
+
* @type Array
|
160
|
+
* An array of columns not to show in the grid (defaults to empty)
|
161
|
+
*/
|
162
|
+
ignoreColumns: ['password', 'password_confirmation'],
|
163
|
+
|
164
|
+
/**
|
165
|
+
* @property useColumns
|
166
|
+
* @type Array
|
167
|
+
* An array of fields to use to generate the column model. This defaults to undefined, but if added in a
|
168
|
+
* subclass then these fields are used to make the column model.
|
169
|
+
*/
|
170
|
+
useColumns: undefined,
|
171
|
+
|
172
|
+
/**
|
173
|
+
* @property narrowColumns
|
174
|
+
* @type Array
|
175
|
+
* An array of columns to render at half the average width
|
176
|
+
*/
|
177
|
+
narrowColumns: ['id'],
|
178
|
+
|
179
|
+
/**
|
180
|
+
* @property wideColumns
|
181
|
+
* @type Array
|
182
|
+
* An array of columns to render at double the average width
|
183
|
+
*/
|
184
|
+
wideColumns: ['message', 'content', 'description', 'bio', 'body'],
|
185
|
+
|
186
|
+
/**
|
187
|
+
* @property narrowColumnWidth
|
188
|
+
* @type Number
|
189
|
+
* The width to make columns in the narrowColumns array (defaults to 30)
|
190
|
+
*/
|
191
|
+
narrowColumnWidth: 30,
|
192
|
+
|
193
|
+
/**
|
194
|
+
* @property normalColumnWidth
|
195
|
+
* @type Number
|
196
|
+
* The width to make columns not marked as narrow or wide (defaults to 100)
|
197
|
+
*/
|
198
|
+
normalColumnWidth: 100,
|
199
|
+
|
200
|
+
/**
|
201
|
+
* @property wideColumnWidth
|
202
|
+
* @type Number
|
203
|
+
* The width to make wide columns (defaults to 200)
|
204
|
+
*/
|
205
|
+
wideColumnWidth: 200,
|
206
|
+
|
207
|
+
/**
|
208
|
+
* @property hasTopToolbar
|
209
|
+
* @type Boolean
|
210
|
+
* True to automatically include a default top toolbar (defaults to true)
|
211
|
+
*/
|
212
|
+
hasTopToolbar: true,
|
213
|
+
|
214
|
+
/**
|
215
|
+
* @property hasBottomToolbar
|
216
|
+
* @type Boolean
|
217
|
+
* True to automatically include a paging bottom toolbar (defaults to true)
|
218
|
+
*/
|
219
|
+
hasBottomToolbar: true,
|
220
|
+
|
221
|
+
/**
|
222
|
+
* Takes a model definition and returns a column array to use for a columnModel
|
223
|
+
*/
|
224
|
+
buildColumns: function(model) {
|
225
|
+
//check to see if GridColumns have been created for this model
|
226
|
+
//e.g. for a MyApp.models.User model, checks for existence of MyApp.views.users.GridColumns
|
227
|
+
if (this.viewsPackage && this.viewsPackage.GridColumns) {
|
228
|
+
var columns = this.viewsPackage.GridColumns;
|
229
|
+
} else {
|
230
|
+
var fields = this.getFields(),
|
231
|
+
columns = [];
|
232
|
+
wideColumns = [];
|
233
|
+
|
234
|
+
//put any preferred columns at the front
|
235
|
+
Ext.each(fields, function(field) {
|
236
|
+
if (this.preferredColumns.indexOf(field.name) > -1) {
|
237
|
+
columns.push(this.buildColumn(field.name));
|
238
|
+
}
|
239
|
+
}, this);
|
240
|
+
|
241
|
+
//add the rest of the columns to the end
|
242
|
+
Ext.each(fields, function(field) {
|
243
|
+
if (this.preferredColumns.indexOf(field.name) == -1 && this.ignoreColumns.indexOf(field.name) == -1) {
|
244
|
+
columns.push(this.buildColumn(field.name));
|
245
|
+
};
|
246
|
+
|
247
|
+
//if it's been declared as a wide column, add it to the wideColumns array
|
248
|
+
if (this.wideColumns.indexOf(field.name)) {
|
249
|
+
wideColumns.push(field.name);
|
250
|
+
}
|
251
|
+
}, this);
|
252
|
+
|
253
|
+
//add default widths to each
|
254
|
+
for (var i = columns.length - 1; i >= 0; i--){
|
255
|
+
var col = columns[i];
|
256
|
+
|
257
|
+
if (this.narrowColumns.indexOf(col.id) > -1) {
|
258
|
+
//id col is extra short
|
259
|
+
Ext.applyIf(col, { width: this.narrowColumnWidth });
|
260
|
+
} else if(this.wideColumns.indexOf(col.id) > -1) {
|
261
|
+
//we have a wide column
|
262
|
+
Ext.applyIf(col, { width: this.wideColumnWidth });
|
263
|
+
} else {
|
264
|
+
//we have a normal column
|
265
|
+
Ext.applyIf(col, { width: this.normalColumnWidth });
|
266
|
+
}
|
267
|
+
};
|
268
|
+
}
|
269
|
+
|
270
|
+
return columns;
|
271
|
+
},
|
272
|
+
|
273
|
+
/**
|
274
|
+
* Returns the array of field names the buildColumns() should use to generate the column model.
|
275
|
+
* This will return this.useColumns if defined, otherwise it will return all fields
|
276
|
+
* @return {Array} The array of field names to use to generate the column model
|
277
|
+
*/
|
278
|
+
getFields: function() {
|
279
|
+
if (this.useColumns === undefined) {
|
280
|
+
return this.model.prototype.fields.items;
|
281
|
+
} else {
|
282
|
+
var fields = [];
|
283
|
+
Ext.each(this.useColumns, function(column) {
|
284
|
+
fields.push({name: column});
|
285
|
+
}, this);
|
286
|
+
|
287
|
+
return fields;
|
288
|
+
}
|
289
|
+
},
|
290
|
+
|
291
|
+
/**
|
292
|
+
* Build a single column object based on a name, adds default properties
|
293
|
+
* @param {Object/String} cfg Column config object (can just include a 'name' property). Also accepts a string, which is translated into the name property
|
294
|
+
* @return {Object} A fully-formed column config with default properties set
|
295
|
+
*/
|
296
|
+
buildColumn: function(cfg) {
|
297
|
+
var cfg = cfg || {};
|
298
|
+
if (typeof(cfg) == 'string') {cfg = {name: cfg};}
|
299
|
+
|
300
|
+
return Ext.applyIf(cfg, {
|
301
|
+
id : cfg.name,
|
302
|
+
header : cfg.name.replace(/_/g, " ").titleize(),
|
303
|
+
sortable : true,
|
304
|
+
dataIndex: cfg.name
|
305
|
+
});
|
306
|
+
},
|
307
|
+
|
308
|
+
/**
|
309
|
+
* @property hasAddButton
|
310
|
+
* @type Boolean
|
311
|
+
* Defines whether or not there should be an 'Add' button on the top toolbar (defaults to true)
|
312
|
+
*/
|
313
|
+
hasAddButton: true,
|
314
|
+
|
315
|
+
/**
|
316
|
+
* @property hasEditButton
|
317
|
+
* @type Boolean
|
318
|
+
* Defines whether or not there should be a 'Edit' button on the top toolbar (defaults to true)
|
319
|
+
*/
|
320
|
+
hasEditButton: true,
|
321
|
+
|
322
|
+
/**
|
323
|
+
* @property hasDeleteButton
|
324
|
+
* @type Boolean
|
325
|
+
* Defines whether or not there should be a 'Delete' button on the top toolbar (defaults to true)
|
326
|
+
*/
|
327
|
+
hasDeleteButton: true,
|
328
|
+
|
329
|
+
/**
|
330
|
+
* Builds the Add button for the top toolbar. Override to create your own
|
331
|
+
* @param {Object} config An optional config object used to customise the button
|
332
|
+
* @return {Ext.Button} The Add Button
|
333
|
+
*/
|
334
|
+
buildAddButton: function(config) {
|
335
|
+
return new Ext.Button(
|
336
|
+
Ext.applyIf(config || {}, {
|
337
|
+
text: 'New ' + this.model.prototype.singularHumanName,
|
338
|
+
scope: this,
|
339
|
+
iconCls: 'add',
|
340
|
+
handler: this.onAdd
|
341
|
+
}
|
342
|
+
));
|
343
|
+
},
|
344
|
+
|
345
|
+
/**
|
346
|
+
* Builds the Edit button for the top toolbar. Override to create your own
|
347
|
+
* @param {Object} config An optional config object used to customise the button
|
348
|
+
* @return {Ext.Button} The Edit button
|
349
|
+
*/
|
350
|
+
buildEditButton: function(config) {
|
351
|
+
return new Ext.Button(
|
352
|
+
Ext.applyIf(config || {}, {
|
353
|
+
text: 'Edit selected',
|
354
|
+
scope: this,
|
355
|
+
iconCls: 'edit',
|
356
|
+
disabled: true,
|
357
|
+
handler: this.onEdit
|
358
|
+
}
|
359
|
+
));
|
360
|
+
},
|
361
|
+
|
362
|
+
/**
|
363
|
+
* Builds the Delete button for the top toolbar. Override to create your own
|
364
|
+
* @param {Object} config An optional config object used to customise the button
|
365
|
+
* @return {Ext.Button} The Delete button
|
366
|
+
*/
|
367
|
+
buildDeleteButton: function(config) {
|
368
|
+
return new Ext.Button(
|
369
|
+
Ext.applyIf(config || {}, {
|
370
|
+
text: 'Delete selected',
|
371
|
+
disabled: true,
|
372
|
+
scope: this,
|
373
|
+
iconCls: 'delete',
|
374
|
+
handler: this.onDelete
|
375
|
+
}
|
376
|
+
));
|
377
|
+
},
|
378
|
+
|
379
|
+
/**
|
380
|
+
* Creates Add, Edit and Delete buttons for the top toolbar and sets up listeners to
|
381
|
+
* activate/deactivate them as appropriate
|
382
|
+
* @return {Array} An array of buttons
|
383
|
+
*/
|
384
|
+
buildTopToolbar: function() {
|
385
|
+
var items = [];
|
386
|
+
|
387
|
+
if (this.hasAddButton === true) {
|
388
|
+
this.addButton = this.buildAddButton();
|
389
|
+
items.push(this.addButton, '-');
|
390
|
+
}
|
391
|
+
|
392
|
+
if (this.hasEditButton === true) {
|
393
|
+
this.editButton = this.buildEditButton();
|
394
|
+
items.push(this.editButton, '-');
|
395
|
+
}
|
396
|
+
|
397
|
+
if (this.hasDeleteButton === true) {
|
398
|
+
this.deleteButton = this.buildDeleteButton();
|
399
|
+
items.push(this.deleteButton, '-');
|
400
|
+
}
|
401
|
+
|
402
|
+
if (this.hasSearchField === true) {
|
403
|
+
this.searchField = this.buildSearchField();
|
404
|
+
items.push(this.searchField, '-');
|
405
|
+
}
|
406
|
+
|
407
|
+
this.getSelectionModel().on('selectionchange', function(selModel) {
|
408
|
+
if (selModel.getCount() > 0) {
|
409
|
+
if (this.deleteButton != undefined) this.deleteButton.enable();
|
410
|
+
if (this.editButton != undefined) this.editButton.enable();
|
411
|
+
} else {
|
412
|
+
if (this.deleteButton != undefined) this.deleteButton.disable();
|
413
|
+
if (this.editButton != undefined) this.editButton.disable();
|
414
|
+
};
|
415
|
+
}, this);
|
416
|
+
|
417
|
+
return items;
|
418
|
+
},
|
419
|
+
|
420
|
+
/**
|
421
|
+
* @property pageSize
|
422
|
+
* @type Number
|
423
|
+
* The pageSize to use in the PagingToolbar bottom Toolbar (defaults to 25)
|
424
|
+
*/
|
425
|
+
pageSize: 25,
|
426
|
+
|
427
|
+
/**
|
428
|
+
* Creates a paging toolbar to be placed at the bottom of this grid
|
429
|
+
* @param {Ext.data.Store} store The store to bind to this paging toolbar (should be the same as for the main grid)
|
430
|
+
* @return {Ext.PagingToolbar} The Paging Toolbar
|
431
|
+
*/
|
432
|
+
buildBottomToolbar: function(store) {
|
433
|
+
return new Ext.PagingToolbar({
|
434
|
+
store: store,
|
435
|
+
displayInfo: true,
|
436
|
+
pageSize: this.pageSize,
|
437
|
+
emptyMsg: String.format("No {0} to display", this.model.prototype.pluralHumanName)
|
438
|
+
});
|
439
|
+
},
|
440
|
+
|
441
|
+
/**
|
442
|
+
* @property hasSearchField
|
443
|
+
* @type Boolean
|
444
|
+
* True to add a search input box to the end of the top toolbar (defaults to false)
|
445
|
+
*/
|
446
|
+
hasSearchField: false,
|
447
|
+
|
448
|
+
/**
|
449
|
+
* @property searchParamName
|
450
|
+
* @type String
|
451
|
+
* The name of the param to send as the search variable in the GET request (defaults to 'q')
|
452
|
+
*/
|
453
|
+
searchParamName: 'q',
|
454
|
+
|
455
|
+
/**
|
456
|
+
* Builds the search field component which can be added to the top toolbar of a grid
|
457
|
+
* @return {Ext.form.TwinTriggerField} The search field object
|
458
|
+
*/
|
459
|
+
buildSearchField: function() {
|
460
|
+
/**
|
461
|
+
* @property searchField
|
462
|
+
* @type Ext.form.TwinTriggerField
|
463
|
+
* The search field that is added to the top toolbar
|
464
|
+
*/
|
465
|
+
this.searchField = new Ext.form.TwinTriggerField({
|
466
|
+
width : 200,
|
467
|
+
validationEvent : false,
|
468
|
+
validateOnBlur : false,
|
469
|
+
hideTrigger1 : true,
|
470
|
+
onTrigger1Click : this.clearSearchField.createDelegate(this, []),
|
471
|
+
onTrigger2Click : this.onSearch.createDelegate(this, []),
|
472
|
+
|
473
|
+
trigger1Class :'x-form-clear-trigger',
|
474
|
+
trigger2Class :'x-form-search-trigger'
|
475
|
+
});
|
476
|
+
|
477
|
+
this.searchField.on('specialkey', function(field, e) {
|
478
|
+
if (e.getKey() === e.ESC) this.clearSearchField(); e.stopEvent();
|
479
|
+
if (e.getKey() === e.ENTER) this.onSearch();
|
480
|
+
}, this);
|
481
|
+
|
482
|
+
return this.searchField;
|
483
|
+
},
|
484
|
+
|
485
|
+
/**
|
486
|
+
* Clears the search field in the top toolbar and hides the clear button
|
487
|
+
*/
|
488
|
+
clearSearchField: function() {
|
489
|
+
var f = this.searchField;
|
490
|
+
|
491
|
+
f.el.dom.value = '';
|
492
|
+
f.triggers[0].hide();
|
493
|
+
this.doSearch();
|
494
|
+
},
|
495
|
+
|
496
|
+
/**
|
497
|
+
* Attached to the search fields trigger2Click and Enter key events. Calls doSearch if the
|
498
|
+
* user has actually entered anything.
|
499
|
+
*/
|
500
|
+
onSearch: function() {
|
501
|
+
var f = this.searchField,
|
502
|
+
v = f.getRawValue();
|
503
|
+
|
504
|
+
if (v.length < 1) {
|
505
|
+
this.clearSearchField();
|
506
|
+
} else {
|
507
|
+
f.triggers[0].show();
|
508
|
+
this.doSearch(v);
|
509
|
+
}
|
510
|
+
},
|
511
|
+
|
512
|
+
/**
|
513
|
+
* Performs the actual search operation by updating the store bound to this grid
|
514
|
+
* TODO: Move this to the controller if possible (might not be...)
|
515
|
+
* @param {String} value The string to search for
|
516
|
+
*/
|
517
|
+
doSearch: function(value) {
|
518
|
+
value = value || this.searchField.getRawValue() || "";
|
519
|
+
|
520
|
+
var o = {start: 0};
|
521
|
+
this.store.baseParams = this.store.baseParams || {};
|
522
|
+
this.store.baseParams[this.searchParamName] = value;
|
523
|
+
this.store.reload({params:o});
|
524
|
+
},
|
525
|
+
|
526
|
+
/**
|
527
|
+
* Called when the add button is pressed, or when the 'a' key is pressed. By default this will simply fire the 'add' event
|
528
|
+
*/
|
529
|
+
onAdd: function() {
|
530
|
+
this.fireEvent('new');
|
531
|
+
},
|
532
|
+
|
533
|
+
/**
|
534
|
+
* Called when a row in this grid panel is double clicked. By default this will find the associated
|
535
|
+
* record and fire the 'edit' event. Override to provide your own logic
|
536
|
+
* @param {Ext.EventObject} e The Event object
|
537
|
+
*/
|
538
|
+
onEdit: function(e) {
|
539
|
+
var obj = this.getSelectionModel().getSelected();
|
540
|
+
|
541
|
+
if (obj) this.fireEvent('edit', obj);
|
542
|
+
},
|
543
|
+
|
544
|
+
/**
|
545
|
+
* Called when the delete button is pressed, or the delete key is pressed. By default this will ask the user to confirm,
|
546
|
+
* then fire the delete action with the selected record as the sole argument
|
547
|
+
*/
|
548
|
+
onDelete: function() {
|
549
|
+
Ext.Msg.confirm(
|
550
|
+
'Are you sure?',
|
551
|
+
String.format("Are you sure you want to delete this {0}? This cannot be undone.", this.model.prototype.modelName.humanize()),
|
552
|
+
function(btn) {
|
553
|
+
if (btn == 'yes') {
|
554
|
+
var selected = this.getSelectionModel().getSelected();
|
555
|
+
if (selected) this.fireEvent('delete', selected);
|
556
|
+
};
|
557
|
+
},
|
558
|
+
this
|
559
|
+
);
|
560
|
+
}
|
561
|
+
});
|