netzke-basepack 0.3.10 → 0.4.0
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.
- data/CHANGELOG +10 -0
- data/Manifest +12 -16
- data/Rakefile +1 -1
- data/TODO +3 -1
- data/autotest/discover.rb +3 -0
- data/javascripts/basepack.js +680 -52
- data/lib/app/models/netzke_hash_record.rb +180 -0
- data/lib/app/models/netzke_layout_item.rb +11 -0
- data/lib/netzke/ar_ext.rb +57 -34
- data/lib/netzke/border_layout_panel.rb +0 -1
- data/lib/netzke/db_fields.rb +4 -0
- data/lib/netzke/field_model.rb +131 -0
- data/lib/netzke/fields_configurator.rb +13 -5
- data/lib/netzke/fields_configurator_old.rb +62 -0
- data/lib/netzke/form_panel.rb +18 -24
- data/lib/netzke/form_panel_extras/interface.rb +20 -13
- data/lib/netzke/form_panel_extras/js_builder.rb +4 -1
- data/lib/netzke/grid_panel.rb +37 -40
- data/lib/netzke/grid_panel_extras/interface.rb +22 -18
- data/lib/netzke/grid_panel_extras/js_builder.rb +42 -13
- data/lib/netzke/property_editor_extras/helper_model.rb +2 -1
- data/lib/netzke/tab_panel.rb +15 -11
- data/netzke-basepack.gemspec +10 -10
- data/test/{accordion_panel_test.rb → unit/accordion_panel_test.rb} +0 -0
- data/test/{ar_ext_test.rb → unit/ar_ext_test.rb} +3 -9
- data/test/{grid_panel_test.rb → unit/grid_panel_test.rb} +0 -5
- data/test/{netzke_basepack_test.rb → unit/netzke_basepack_test.rb} +0 -0
- data/test/unit/netzke_hash_record_test.rb +52 -0
- data/test/unit/netzke_layout_item_test.rb +28 -0
- data/test/{tab_panel_test.rb → unit/tab_panel_test.rb} +0 -0
- metadata +30 -30
- data/generators/netzke_basepack/USAGE +0 -8
- data/generators/netzke_basepack/netzke_basepack_generator.rb +0 -8
- data/generators/netzke_form_panel/netzke_form_panel_generator.rb +0 -7
- data/generators/netzke_form_panel/templates/create_netzke_form_panel_fields.rb +0 -21
- data/generators/netzke_grid_panel/netzke_grid_panel_generator.rb +0 -7
- data/generators/netzke_grid_panel/templates/create_netzke_grid_panel_columns.rb +0 -24
- data/lib/app/models/netzke_form_panel_field.rb +0 -51
- data/lib/app/models/netzke_grid_panel_column.rb +0 -56
- data/lib/netzke/form_panel_extras/javascripts/xdatetime.js +0 -634
- data/test/app_root/db/migrate/20090102223811_create_netzke_grid_panel_columns.rb +0 -23
- data/test/border_layout_panel_test.rb +0 -25
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
v0.4.0
|
2
|
+
Rework: got rid of NetzkeFormPanelField and NetzkeGridPanelColumn classes along with their tables. The layout is now stored in netzke_preferences.
|
3
|
+
New: dynamic hiding of columns from column menu in GridPanel.
|
4
|
+
New: FormPanel now supports combo boxes.
|
5
|
+
Fix: config[:bbar] set to 'false' now works in grids with pagination
|
6
|
+
New: you can specify :preloaded => true in a tab config in TabPanel to preload the widget in that tab along with the TabPanel itself
|
7
|
+
New: hideBusy added to Ext.StatusBar
|
8
|
+
Fix: assigning association (a Boss to a Clerk) by virtual column (like boss__name) works now
|
9
|
+
Fix: an old bug that made GridPanel misbehave after reordering the columns
|
10
|
+
|
1
11
|
v0.3.10
|
2
12
|
BasicApp-based widgets can now introduce arbitrary layout, following the convention of defining "main-panel" and "main-toolbar" panels with layout 'fit'.
|
3
13
|
|
data/Manifest
CHANGED
@@ -1,15 +1,10 @@
|
|
1
|
+
autotest/discover.rb
|
1
2
|
CHANGELOG
|
2
|
-
generators/netzke_basepack/netzke_basepack_generator.rb
|
3
|
-
generators/netzke_basepack/USAGE
|
4
|
-
generators/netzke_form_panel/netzke_form_panel_generator.rb
|
5
|
-
generators/netzke_form_panel/templates/create_netzke_form_panel_fields.rb
|
6
|
-
generators/netzke_grid_panel/netzke_grid_panel_generator.rb
|
7
|
-
generators/netzke_grid_panel/templates/create_netzke_grid_panel_columns.rb
|
8
3
|
init.rb
|
9
4
|
install.rb
|
10
5
|
javascripts/basepack.js
|
11
|
-
lib/app/models/
|
12
|
-
lib/app/models/
|
6
|
+
lib/app/models/netzke_hash_record.rb
|
7
|
+
lib/app/models/netzke_layout_item.rb
|
13
8
|
lib/netzke/accordion_panel.rb
|
14
9
|
lib/netzke/ar_ext.rb
|
15
10
|
lib/netzke/basic_app.rb
|
@@ -17,11 +12,12 @@ lib/netzke/border_layout_panel.rb
|
|
17
12
|
lib/netzke/configuration_tool.rb
|
18
13
|
lib/netzke/container.rb
|
19
14
|
lib/netzke/db_fields.rb
|
15
|
+
lib/netzke/field_model.rb
|
20
16
|
lib/netzke/fields_configurator.rb
|
17
|
+
lib/netzke/fields_configurator_old.rb
|
21
18
|
lib/netzke/form_panel.rb
|
22
19
|
lib/netzke/form_panel_extras/interface.rb
|
23
20
|
lib/netzke/form_panel_extras/javascripts/xcheckbox.js
|
24
|
-
lib/netzke/form_panel_extras/javascripts/xdatetime.js
|
25
21
|
lib/netzke/form_panel_extras/js_builder.rb
|
26
22
|
lib/netzke/grid_panel.rb
|
27
23
|
lib/netzke/grid_panel_extras/interface.rb
|
@@ -42,7 +38,6 @@ Rakefile
|
|
42
38
|
README.rdoc
|
43
39
|
stylesheets/basepack.css
|
44
40
|
tasks/netzke_basepack_tasks.rake
|
45
|
-
test/accordion_panel_test.rb
|
46
41
|
test/app_root/app/controllers/application.rb
|
47
42
|
test/app_root/app/models/book.rb
|
48
43
|
test/app_root/app/models/category.rb
|
@@ -67,13 +62,10 @@ test/app_root/db/migrate/20081223025635_create_countries.rb
|
|
67
62
|
test/app_root/db/migrate/20081223025653_create_continents.rb
|
68
63
|
test/app_root/db/migrate/20081223025732_create_cities.rb
|
69
64
|
test/app_root/db/migrate/20090102223630_create_netzke_layouts.rb
|
70
|
-
test/app_root/db/migrate/20090102223811_create_netzke_grid_panel_columns.rb
|
71
65
|
test/app_root/script/console
|
72
66
|
test/app_root/vendor/plugins/acts_as_list/init.rb
|
73
67
|
test/app_root/vendor/plugins/acts_as_list/lib/active_record/acts/list.rb
|
74
68
|
test/app_root/vendor/plugins/acts_as_list/README
|
75
|
-
test/ar_ext_test.rb
|
76
|
-
test/border_layout_panel_test.rb
|
77
69
|
test/console_with_fixtures.rb
|
78
70
|
test/fixtures/books.yml
|
79
71
|
test/fixtures/categories.yml
|
@@ -81,10 +73,14 @@ test/fixtures/cities.yml
|
|
81
73
|
test/fixtures/continents.yml
|
82
74
|
test/fixtures/countries.yml
|
83
75
|
test/fixtures/genres.yml
|
84
|
-
test/grid_panel_test.rb
|
85
|
-
test/netzke_basepack_test.rb
|
86
76
|
test/schema.rb
|
87
|
-
test/tab_panel_test.rb
|
88
77
|
test/test_helper.rb
|
78
|
+
test/unit/accordion_panel_test.rb
|
79
|
+
test/unit/ar_ext_test.rb
|
80
|
+
test/unit/grid_panel_test.rb
|
81
|
+
test/unit/netzke_basepack_test.rb
|
82
|
+
test/unit/netzke_hash_record_test.rb
|
83
|
+
test/unit/netzke_layout_item_test.rb
|
84
|
+
test/unit/tab_panel_test.rb
|
89
85
|
TODO
|
90
86
|
uninstall.rb
|
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ Echoe.new("netzke-basepack") do |p|
|
|
5
5
|
p.email = "sergei@writelesscode.com"
|
6
6
|
p.summary = "Base Netzke widgets - grid, form, tree, and more"
|
7
7
|
p.url = "http://writelesscode.com"
|
8
|
-
p.runtime_dependencies = ["searchlogic >=1.6.2", "netzke-core >= 0.
|
8
|
+
p.runtime_dependencies = ["searchlogic >=1.6.2", "netzke-core >= 0.3.0"]
|
9
9
|
p.development_dependencies = []
|
10
10
|
p.test_pattern = 'test/**/*_test.rb'
|
11
11
|
|
data/TODO
CHANGED
@@ -1 +1,3 @@
|
|
1
|
-
* GridPanel. Reordering of grid columns may lead to unpredictable results when data from an "outdated" table (e.g. open in another browser) gets submitted. A mechanism is needed to submit updated data along with the field names - as hash (as done is FormPanel), *not* as array.
|
1
|
+
* GridPanel. Reordering of grid columns may lead to unpredictable results when data from an "outdated" table (e.g. open in another browser) gets submitted. A mechanism is needed to submit updated data along with the field names - as hash (as done is FormPanel), *not* as array.
|
2
|
+
|
3
|
+
* Add status bar to BasicApp
|
data/javascripts/basepack.js
CHANGED
@@ -1,61 +1,46 @@
|
|
1
1
|
Ext.apply(Ext.History, new Ext.util.Observable());
|
2
2
|
|
3
|
-
//
|
4
|
-
Ext.netzke.
|
5
|
-
|
6
|
-
|
3
|
+
// A convenient passfield
|
4
|
+
Ext.netzke.PassField = Ext.extend(Ext.form.TextField, {
|
5
|
+
inputType: 'password'
|
6
|
+
});
|
7
|
+
Ext.reg('passfield', Ext.netzke.PassField);
|
8
|
+
|
9
|
+
// Combobox that knows to talk to the server side (used in both grids and panels)
|
10
|
+
Ext.netzke.ComboBox = Ext.extend(Ext.form.ComboBox, {
|
11
|
+
mode : 'remote',
|
12
|
+
displayField : 'id',
|
13
|
+
valueField : 'id',
|
14
|
+
triggerAction : 'all',
|
15
|
+
typeAhead : true,
|
16
|
+
selectOnFocus : true,
|
17
|
+
|
18
|
+
initComponent : function(){
|
19
|
+
var row = Ext.data.Record.create([{name:'id'}]);
|
20
|
+
// console.info(this.parentWidget);
|
7
21
|
var store = new Ext.data.Store({
|
8
|
-
proxy : new Ext.data.HttpProxy({url:
|
22
|
+
proxy : new Ext.data.HttpProxy({url:this.parentConfig.interface.getCbChoices, jsonData:{column:this.fieldConfig.name}}),
|
9
23
|
reader : new Ext.data.ArrayReader({root:'data', id:0}, row)
|
10
|
-
})
|
24
|
+
});
|
11
25
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
typeAhead : true,
|
18
|
-
selectOnFocus : true,
|
19
|
-
store : store
|
20
|
-
})
|
26
|
+
Ext.apply(this, {
|
27
|
+
store : store
|
28
|
+
});
|
29
|
+
|
30
|
+
Ext.netzke.ComboBox.superclass.initComponent.apply(this, arguments);
|
21
31
|
|
22
|
-
|
23
|
-
comboBox.on('blur', function(cb){
|
32
|
+
this.on('blur', function(cb){
|
24
33
|
cb.setValue(cb.getRawValue());
|
25
34
|
});
|
26
|
-
|
35
|
+
|
36
|
+
this.on('specialkey', function(cb, event){
|
27
37
|
if (event.getKey() == 9 || event.getKey() == 13) {cb.setValue(cb.getRawValue());}
|
28
38
|
});
|
29
|
-
|
30
|
-
return comboBox;
|
31
|
-
},
|
32
|
-
|
33
|
-
text_field: function(c, config){
|
34
|
-
return new Ext.form.TextField({
|
35
|
-
selectOnFocus:true
|
36
|
-
})
|
37
|
-
},
|
38
|
-
|
39
|
-
checkbox: function(c, config){
|
40
|
-
return new Ext.form.TextField({
|
41
|
-
selectOnFocus:true
|
42
|
-
})
|
43
|
-
},
|
44
|
-
|
45
|
-
number_field: function(c, config){
|
46
|
-
return new Ext.form.NumberField({
|
47
|
-
selectOnFocus:true
|
48
|
-
})
|
49
|
-
},
|
50
|
-
|
51
|
-
// TODO: it's simply a text field for now
|
52
|
-
datetime: function(c, config){
|
53
|
-
return new Ext.form.TextField({
|
54
|
-
selectOnFocus:true
|
55
|
-
})
|
56
39
|
}
|
57
|
-
};
|
40
|
+
});
|
41
|
+
Ext.reg('combobox', Ext.netzke.ComboBox);
|
58
42
|
|
43
|
+
// TODO: rethink
|
59
44
|
Ext.netzke.renderer = function(renderer, c, config){
|
60
45
|
res = null; // null-renderer means "no renderer"
|
61
46
|
|
@@ -75,17 +60,26 @@ Ext.netzke.renderer = function(renderer, c, config){
|
|
75
60
|
}
|
76
61
|
|
77
62
|
return res
|
78
|
-
}
|
63
|
+
};
|
79
64
|
|
80
65
|
// Mapping of editor field to grid filters
|
81
66
|
Ext.netzke.filterMap = {
|
82
|
-
|
83
|
-
|
84
|
-
|
67
|
+
numberfield:'Numeric',
|
68
|
+
textfield:'String',
|
69
|
+
xdatetime:'String',
|
85
70
|
checkbox:'Boolean',
|
86
|
-
|
71
|
+
combobox:'String',
|
87
72
|
date:'Date'
|
88
|
-
}
|
73
|
+
};
|
74
|
+
|
75
|
+
Ext.override(Ext.StatusBar, {
|
76
|
+
hideBusy : function(){
|
77
|
+
return this.setStatus({
|
78
|
+
text: this.defaultText,
|
79
|
+
iconCls: this.defaultIconCls
|
80
|
+
});
|
81
|
+
}
|
82
|
+
});
|
89
83
|
|
90
84
|
Ext.data.RecordArrayReader = Ext.extend(Ext.data.JsonReader, {
|
91
85
|
/**
|
@@ -114,3 +108,637 @@ Ext.data.RecordArrayReader = Ext.extend(Ext.data.JsonReader, {
|
|
114
108
|
return record;
|
115
109
|
}
|
116
110
|
});
|
111
|
+
|
112
|
+
/**
|
113
|
+
* @class Ext.ux.form.DateTime
|
114
|
+
* @extends Ext.form.Field
|
115
|
+
*
|
116
|
+
* DateTime field, combination of DateField and TimeField
|
117
|
+
*
|
118
|
+
* @author Ing. Jozef Sak�lo�
|
119
|
+
* @copyright (c) 2008, Ing. Jozef Sak�lo�
|
120
|
+
* @version 2.0
|
121
|
+
* @revision $Id: Ext.ux.form.DateTime.js 513 2009-01-29 19:59:22Z jozo $
|
122
|
+
*
|
123
|
+
* @license Ext.ux.form.DateTime is licensed under the terms of
|
124
|
+
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
|
125
|
+
* that the code/component(s) do NOT become part of another Open Source or Commercially
|
126
|
+
* licensed development library or toolkit without explicit permission.
|
127
|
+
*
|
128
|
+
* <p>License details: <a href="http://www.gnu.org/licenses/lgpl.html"
|
129
|
+
* target="_blank">http://www.gnu.org/licenses/lgpl.html</a></p>
|
130
|
+
*
|
131
|
+
* @forum 22661
|
132
|
+
*/
|
133
|
+
|
134
|
+
Ext.ns('Ext.ux.form');
|
135
|
+
|
136
|
+
/**
|
137
|
+
* @constructor
|
138
|
+
* Creates new DateTime
|
139
|
+
* @param {Object} config The config object
|
140
|
+
*/
|
141
|
+
Ext.ux.form.DateTime = Ext.extend(Ext.form.Field, {
|
142
|
+
/**
|
143
|
+
* @cfg {String/Object} defaultAutoCreate DomHelper element spec
|
144
|
+
* Let superclass to create hidden field instead of textbox. Hidden will be submittend to server
|
145
|
+
*/
|
146
|
+
defaultAutoCreate:{tag:'input', type:'hidden'}
|
147
|
+
/**
|
148
|
+
* @cfg {Number} timeWidth Width of time field in pixels (defaults to 100)
|
149
|
+
*/
|
150
|
+
,timeWidth:80
|
151
|
+
/**
|
152
|
+
* @cfg {String} dtSeparator Date - Time separator. Used to split date and time (defaults to ' ' (space))
|
153
|
+
*/
|
154
|
+
,dtSeparator:' '
|
155
|
+
/**
|
156
|
+
* @cfg {String} hiddenFormat Format of datetime used to store value in hidden field
|
157
|
+
* and submitted to server (defaults to 'Y-m-d H:i:s' that is mysql format)
|
158
|
+
*/
|
159
|
+
,hiddenFormat:'Y-m-d H:i:s'
|
160
|
+
/**
|
161
|
+
* @cfg {Boolean} otherToNow Set other field to now() if not explicly filled in (defaults to true)
|
162
|
+
*/
|
163
|
+
,otherToNow:true
|
164
|
+
/**
|
165
|
+
* @cfg {Boolean} emptyToNow Set field value to now on attempt to set empty value.
|
166
|
+
* If it is true then setValue() sets value of field to current date and time (defaults to false)
|
167
|
+
*/
|
168
|
+
/**
|
169
|
+
* @cfg {String} timePosition Where the time field should be rendered. 'right' is suitable for forms
|
170
|
+
* and 'below' is suitable if the field is used as the grid editor (defaults to 'right')
|
171
|
+
*/
|
172
|
+
,timePosition:'right' // valid values:'below', 'right'
|
173
|
+
/**
|
174
|
+
* @cfg {String} dateFormat Format of DateField. Can be localized. (defaults to 'm/y/d')
|
175
|
+
*/
|
176
|
+
,dateFormat:'m/d/y'
|
177
|
+
/**
|
178
|
+
* @cfg {String} timeFormat Format of TimeField. Can be localized. (defaults to 'g:i A')
|
179
|
+
*/
|
180
|
+
,timeFormat:'g:i A'
|
181
|
+
/**
|
182
|
+
* @cfg {Object} dateConfig Config for DateField constructor.
|
183
|
+
*/
|
184
|
+
/**
|
185
|
+
* @cfg {Object} timeConfig Config for TimeField constructor.
|
186
|
+
*/
|
187
|
+
|
188
|
+
// {{{
|
189
|
+
/**
|
190
|
+
* @private
|
191
|
+
* creates DateField and TimeField and installs the necessary event handlers
|
192
|
+
*/
|
193
|
+
,initComponent:function() {
|
194
|
+
// call parent initComponent
|
195
|
+
Ext.ux.form.DateTime.superclass.initComponent.call(this);
|
196
|
+
|
197
|
+
// create DateField
|
198
|
+
var dateConfig = Ext.apply({}, {
|
199
|
+
id:this.id + '-date'
|
200
|
+
,format:this.dateFormat || Ext.form.DateField.prototype.format
|
201
|
+
,width:this.timeWidth
|
202
|
+
,selectOnFocus:this.selectOnFocus
|
203
|
+
,listeners:{
|
204
|
+
blur:{scope:this, fn:this.onBlur}
|
205
|
+
,focus:{scope:this, fn:this.onFocus}
|
206
|
+
}
|
207
|
+
}, this.dateConfig);
|
208
|
+
this.df = new Ext.form.DateField(dateConfig);
|
209
|
+
this.df.ownerCt = this;
|
210
|
+
delete(this.dateFormat);
|
211
|
+
|
212
|
+
|
213
|
+
// create TimeField
|
214
|
+
var timeConfig = Ext.apply({}, {
|
215
|
+
id:this.id + '-time'
|
216
|
+
,format:this.timeFormat || Ext.form.TimeField.prototype.format
|
217
|
+
,width:this.timeWidth
|
218
|
+
,selectOnFocus:this.selectOnFocus
|
219
|
+
,listeners:{
|
220
|
+
blur:{scope:this, fn:this.onBlur}
|
221
|
+
,focus:{scope:this, fn:this.onFocus}
|
222
|
+
}
|
223
|
+
}, this.timeConfig);
|
224
|
+
this.tf = new Ext.form.TimeField(timeConfig);
|
225
|
+
this.tf.ownerCt = this;
|
226
|
+
delete(this.timeFormat);
|
227
|
+
|
228
|
+
// relay events
|
229
|
+
this.relayEvents(this.df, ['focus', 'specialkey', 'invalid', 'valid']);
|
230
|
+
this.relayEvents(this.tf, ['focus', 'specialkey', 'invalid', 'valid']);
|
231
|
+
|
232
|
+
} // eo function initComponent
|
233
|
+
// }}}
|
234
|
+
// {{{
|
235
|
+
/**
|
236
|
+
* @private
|
237
|
+
* Renders underlying DateField and TimeField and provides a workaround for side error icon bug
|
238
|
+
*/
|
239
|
+
,onRender:function(ct, position) {
|
240
|
+
// don't run more than once
|
241
|
+
if(this.isRendered) {
|
242
|
+
return;
|
243
|
+
}
|
244
|
+
|
245
|
+
// render underlying hidden field
|
246
|
+
Ext.ux.form.DateTime.superclass.onRender.call(this, ct, position);
|
247
|
+
|
248
|
+
// render DateField and TimeField
|
249
|
+
// create bounding table
|
250
|
+
var t;
|
251
|
+
if('below' === this.timePosition || 'bellow' === this.timePosition) {
|
252
|
+
t = Ext.DomHelper.append(ct, {tag:'table',style:'border-collapse:collapse',children:[
|
253
|
+
{tag:'tr',children:[{tag:'td', style:'padding-bottom:1px', cls:'ux-datetime-date'}]}
|
254
|
+
,{tag:'tr',children:[{tag:'td', cls:'ux-datetime-time'}]}
|
255
|
+
]}, true);
|
256
|
+
}
|
257
|
+
else {
|
258
|
+
t = Ext.DomHelper.append(ct, {tag:'table',style:'border-collapse:collapse',children:[
|
259
|
+
{tag:'tr',children:[
|
260
|
+
{tag:'td',style:'padding-right:4px', cls:'ux-datetime-date'},{tag:'td', cls:'ux-datetime-time'}
|
261
|
+
]}
|
262
|
+
]}, true);
|
263
|
+
}
|
264
|
+
|
265
|
+
this.tableEl = t;
|
266
|
+
// this.wrap = t.wrap({cls:'x-form-field-wrap'});
|
267
|
+
this.wrap = t.wrap();
|
268
|
+
this.wrap.on("mousedown", this.onMouseDown, this, {delay:10});
|
269
|
+
|
270
|
+
// render DateField & TimeField
|
271
|
+
this.df.render(t.child('td.ux-datetime-date'));
|
272
|
+
this.tf.render(t.child('td.ux-datetime-time'));
|
273
|
+
|
274
|
+
// workaround for IE trigger misalignment bug
|
275
|
+
if(Ext.isIE && Ext.isStrict) {
|
276
|
+
t.select('input').applyStyles({top:0});
|
277
|
+
}
|
278
|
+
|
279
|
+
this.on('specialkey', this.onSpecialKey, this);
|
280
|
+
this.df.el.swallowEvent(['keydown', 'keypress']);
|
281
|
+
this.tf.el.swallowEvent(['keydown', 'keypress']);
|
282
|
+
|
283
|
+
// create icon for side invalid errorIcon
|
284
|
+
if('side' === this.msgTarget) {
|
285
|
+
var elp = this.el.findParent('.x-form-element', 10, true);
|
286
|
+
this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
|
287
|
+
|
288
|
+
this.df.errorIcon = this.errorIcon;
|
289
|
+
this.tf.errorIcon = this.errorIcon;
|
290
|
+
}
|
291
|
+
|
292
|
+
// setup name for submit
|
293
|
+
this.el.dom.name = this.hiddenName || this.name || this.id;
|
294
|
+
|
295
|
+
// prevent helper fields from being submitted
|
296
|
+
this.df.el.dom.removeAttribute("name");
|
297
|
+
this.tf.el.dom.removeAttribute("name");
|
298
|
+
|
299
|
+
// we're rendered flag
|
300
|
+
this.isRendered = true;
|
301
|
+
|
302
|
+
// update hidden field
|
303
|
+
this.updateHidden();
|
304
|
+
|
305
|
+
} // eo function onRender
|
306
|
+
// }}}
|
307
|
+
// {{{
|
308
|
+
/**
|
309
|
+
* @private
|
310
|
+
*/
|
311
|
+
,adjustSize:Ext.BoxComponent.prototype.adjustSize
|
312
|
+
// }}}
|
313
|
+
// {{{
|
314
|
+
/**
|
315
|
+
* @private
|
316
|
+
*/
|
317
|
+
,alignErrorIcon:function() {
|
318
|
+
this.errorIcon.alignTo(this.tableEl, 'tl-tr', [2, 0]);
|
319
|
+
}
|
320
|
+
// }}}
|
321
|
+
// {{{
|
322
|
+
/**
|
323
|
+
* @private initializes internal dateValue
|
324
|
+
*/
|
325
|
+
,initDateValue:function() {
|
326
|
+
this.dateValue = this.otherToNow ? new Date() : new Date(1970, 0, 1, 0, 0, 0);
|
327
|
+
}
|
328
|
+
// }}}
|
329
|
+
// {{{
|
330
|
+
/**
|
331
|
+
* Calls clearInvalid on the DateField and TimeField
|
332
|
+
*/
|
333
|
+
,clearInvalid:function(){
|
334
|
+
this.df.clearInvalid();
|
335
|
+
this.tf.clearInvalid();
|
336
|
+
} // eo function clearInvalid
|
337
|
+
// }}}
|
338
|
+
// {{{
|
339
|
+
/**
|
340
|
+
* @private
|
341
|
+
* called from Component::destroy.
|
342
|
+
* Destroys all elements and removes all listeners we've created.
|
343
|
+
*/
|
344
|
+
,beforeDestroy:function() {
|
345
|
+
if(this.isRendered) {
|
346
|
+
// this.removeAllListeners();
|
347
|
+
this.wrap.removeAllListeners();
|
348
|
+
this.wrap.remove();
|
349
|
+
this.tableEl.remove();
|
350
|
+
this.df.destroy();
|
351
|
+
this.tf.destroy();
|
352
|
+
}
|
353
|
+
} // eo function beforeDestroy
|
354
|
+
// }}}
|
355
|
+
// {{{
|
356
|
+
/**
|
357
|
+
* Disable this component.
|
358
|
+
* @return {Ext.Component} this
|
359
|
+
*/
|
360
|
+
,disable:function() {
|
361
|
+
if(this.isRendered) {
|
362
|
+
this.df.disabled = this.disabled;
|
363
|
+
this.df.onDisable();
|
364
|
+
this.tf.onDisable();
|
365
|
+
}
|
366
|
+
this.disabled = true;
|
367
|
+
this.df.disabled = true;
|
368
|
+
this.tf.disabled = true;
|
369
|
+
this.fireEvent("disable", this);
|
370
|
+
return this;
|
371
|
+
} // eo function disable
|
372
|
+
// }}}
|
373
|
+
// {{{
|
374
|
+
/**
|
375
|
+
* Enable this component.
|
376
|
+
* @return {Ext.Component} this
|
377
|
+
*/
|
378
|
+
,enable:function() {
|
379
|
+
if(this.rendered){
|
380
|
+
this.df.onEnable();
|
381
|
+
this.tf.onEnable();
|
382
|
+
}
|
383
|
+
this.disabled = false;
|
384
|
+
this.df.disabled = false;
|
385
|
+
this.tf.disabled = false;
|
386
|
+
this.fireEvent("enable", this);
|
387
|
+
return this;
|
388
|
+
} // eo function enable
|
389
|
+
// }}}
|
390
|
+
// {{{
|
391
|
+
/**
|
392
|
+
* @private Focus date filed
|
393
|
+
*/
|
394
|
+
,focus:function() {
|
395
|
+
this.df.focus();
|
396
|
+
} // eo function focus
|
397
|
+
// }}}
|
398
|
+
// {{{
|
399
|
+
/**
|
400
|
+
* @private
|
401
|
+
*/
|
402
|
+
,getPositionEl:function() {
|
403
|
+
return this.wrap;
|
404
|
+
}
|
405
|
+
// }}}
|
406
|
+
// {{{
|
407
|
+
/**
|
408
|
+
* @private
|
409
|
+
*/
|
410
|
+
,getResizeEl:function() {
|
411
|
+
return this.wrap;
|
412
|
+
}
|
413
|
+
// }}}
|
414
|
+
// {{{
|
415
|
+
/**
|
416
|
+
* @return {Date/String} Returns value of this field
|
417
|
+
*/
|
418
|
+
,getValue:function() {
|
419
|
+
// create new instance of date
|
420
|
+
return this.dateValue ? new Date(this.dateValue) : '';
|
421
|
+
} // eo function getValue
|
422
|
+
// }}}
|
423
|
+
// {{{
|
424
|
+
/**
|
425
|
+
* @return {Boolean} true = valid, false = invalid
|
426
|
+
* @private Calls isValid methods of underlying DateField and TimeField and returns the result
|
427
|
+
*/
|
428
|
+
,isValid:function() {
|
429
|
+
return this.df.isValid() && this.tf.isValid();
|
430
|
+
} // eo function isValid
|
431
|
+
// }}}
|
432
|
+
// {{{
|
433
|
+
/**
|
434
|
+
* Returns true if this component is visible
|
435
|
+
* @return {boolean}
|
436
|
+
*/
|
437
|
+
,isVisible : function(){
|
438
|
+
return this.df.rendered && this.df.getActionEl().isVisible();
|
439
|
+
} // eo function isVisible
|
440
|
+
// }}}
|
441
|
+
// {{{
|
442
|
+
/**
|
443
|
+
* @private Handles blur event
|
444
|
+
*/
|
445
|
+
,onBlur:function(f) {
|
446
|
+
// called by both DateField and TimeField blur events
|
447
|
+
|
448
|
+
// revert focus to previous field if clicked in between
|
449
|
+
if(this.wrapClick) {
|
450
|
+
f.focus();
|
451
|
+
this.wrapClick = false;
|
452
|
+
}
|
453
|
+
|
454
|
+
// update underlying value
|
455
|
+
if(f === this.df) {
|
456
|
+
this.updateDate();
|
457
|
+
}
|
458
|
+
else {
|
459
|
+
this.updateTime();
|
460
|
+
}
|
461
|
+
this.updateHidden();
|
462
|
+
|
463
|
+
// fire events later
|
464
|
+
(function() {
|
465
|
+
if(!this.df.hasFocus && !this.tf.hasFocus) {
|
466
|
+
var v = this.getValue();
|
467
|
+
if(String(v) !== String(this.startValue)) {
|
468
|
+
this.fireEvent("change", this, v, this.startValue);
|
469
|
+
}
|
470
|
+
this.hasFocus = false;
|
471
|
+
this.fireEvent('blur', this);
|
472
|
+
}
|
473
|
+
}).defer(100, this);
|
474
|
+
|
475
|
+
} // eo function onBlur
|
476
|
+
// }}}
|
477
|
+
// {{{
|
478
|
+
/**
|
479
|
+
* @private Handles focus event
|
480
|
+
*/
|
481
|
+
,onFocus:function() {
|
482
|
+
if(!this.hasFocus){
|
483
|
+
this.hasFocus = true;
|
484
|
+
this.startValue = this.getValue();
|
485
|
+
this.fireEvent("focus", this);
|
486
|
+
}
|
487
|
+
}
|
488
|
+
// }}}
|
489
|
+
// {{{
|
490
|
+
/**
|
491
|
+
* @private Just to prevent blur event when clicked in the middle of fields
|
492
|
+
*/
|
493
|
+
,onMouseDown:function(e) {
|
494
|
+
if(!this.disabled) {
|
495
|
+
this.wrapClick = 'td' === e.target.nodeName.toLowerCase();
|
496
|
+
}
|
497
|
+
}
|
498
|
+
// }}}
|
499
|
+
// {{{
|
500
|
+
/**
|
501
|
+
* @private
|
502
|
+
* Handles Tab and Shift-Tab events
|
503
|
+
*/
|
504
|
+
,onSpecialKey:function(t, e) {
|
505
|
+
var key = e.getKey();
|
506
|
+
if(key === e.TAB) {
|
507
|
+
if(t === this.df && !e.shiftKey) {
|
508
|
+
e.stopEvent();
|
509
|
+
this.tf.focus();
|
510
|
+
}
|
511
|
+
if(t === this.tf && e.shiftKey) {
|
512
|
+
e.stopEvent();
|
513
|
+
this.df.focus();
|
514
|
+
}
|
515
|
+
}
|
516
|
+
// otherwise it misbehaves in editor grid
|
517
|
+
if(key === e.ENTER) {
|
518
|
+
this.updateValue();
|
519
|
+
}
|
520
|
+
|
521
|
+
} // eo function onSpecialKey
|
522
|
+
// }}}
|
523
|
+
// {{{
|
524
|
+
/**
|
525
|
+
* @private Sets the value of DateField
|
526
|
+
*/
|
527
|
+
,setDate:function(date) {
|
528
|
+
this.df.setValue(date);
|
529
|
+
} // eo function setDate
|
530
|
+
// }}}
|
531
|
+
// {{{
|
532
|
+
/**
|
533
|
+
* @private Sets the value of TimeField
|
534
|
+
*/
|
535
|
+
,setTime:function(date) {
|
536
|
+
this.tf.setValue(date);
|
537
|
+
} // eo function setTime
|
538
|
+
// }}}
|
539
|
+
// {{{
|
540
|
+
/**
|
541
|
+
* @private
|
542
|
+
* Sets correct sizes of underlying DateField and TimeField
|
543
|
+
* With workarounds for IE bugs
|
544
|
+
*/
|
545
|
+
,setSize:function(w, h) {
|
546
|
+
if(!w) {
|
547
|
+
return;
|
548
|
+
}
|
549
|
+
if('below' === this.timePosition) {
|
550
|
+
this.df.setSize(w, h);
|
551
|
+
this.tf.setSize(w, h);
|
552
|
+
if(Ext.isIE) {
|
553
|
+
this.df.el.up('td').setWidth(w);
|
554
|
+
this.tf.el.up('td').setWidth(w);
|
555
|
+
}
|
556
|
+
}
|
557
|
+
else {
|
558
|
+
this.df.setSize(w - this.timeWidth - 4, h);
|
559
|
+
this.tf.setSize(this.timeWidth, h);
|
560
|
+
|
561
|
+
if(Ext.isIE) {
|
562
|
+
this.df.el.up('td').setWidth(w - this.timeWidth - 4);
|
563
|
+
this.tf.el.up('td').setWidth(this.timeWidth);
|
564
|
+
}
|
565
|
+
}
|
566
|
+
} // eo function setSize
|
567
|
+
// }}}
|
568
|
+
// {{{
|
569
|
+
/**
|
570
|
+
* @param {Mixed} val Value to set
|
571
|
+
* Sets the value of this field
|
572
|
+
*/
|
573
|
+
,setValue:function(val) {
|
574
|
+
if(!val && true === this.emptyToNow) {
|
575
|
+
this.setValue(new Date());
|
576
|
+
return;
|
577
|
+
}
|
578
|
+
else if(!val) {
|
579
|
+
this.setDate('');
|
580
|
+
this.setTime('');
|
581
|
+
this.updateValue();
|
582
|
+
return;
|
583
|
+
}
|
584
|
+
if ('number' === typeof val) {
|
585
|
+
val = new Date(val);
|
586
|
+
}
|
587
|
+
else if('string' === typeof val && this.hiddenFormat) {
|
588
|
+
val = Date.parseDate(val, this.hiddenFormat)
|
589
|
+
}
|
590
|
+
val = val ? val : new Date(1970, 0 ,1, 0, 0, 0);
|
591
|
+
var da, time;
|
592
|
+
if(val instanceof Date) {
|
593
|
+
this.setDate(val);
|
594
|
+
this.setTime(val);
|
595
|
+
this.dateValue = new Date(val);
|
596
|
+
}
|
597
|
+
else {
|
598
|
+
da = val.split(this.dtSeparator);
|
599
|
+
this.setDate(da[0]);
|
600
|
+
if(da[1]) {
|
601
|
+
if(da[2]) {
|
602
|
+
// add am/pm part back to time
|
603
|
+
da[1] += da[2];
|
604
|
+
}
|
605
|
+
this.setTime(da[1]);
|
606
|
+
}
|
607
|
+
}
|
608
|
+
this.updateValue();
|
609
|
+
} // eo function setValue
|
610
|
+
// }}}
|
611
|
+
// {{{
|
612
|
+
/**
|
613
|
+
* Hide or show this component by boolean
|
614
|
+
* @return {Ext.Component} this
|
615
|
+
*/
|
616
|
+
,setVisible: function(visible){
|
617
|
+
if(visible) {
|
618
|
+
this.df.show();
|
619
|
+
this.tf.show();
|
620
|
+
}else{
|
621
|
+
this.df.hide();
|
622
|
+
this.tf.hide();
|
623
|
+
}
|
624
|
+
return this;
|
625
|
+
} // eo function setVisible
|
626
|
+
// }}}
|
627
|
+
//{{{
|
628
|
+
,show:function() {
|
629
|
+
return this.setVisible(true);
|
630
|
+
} // eo function show
|
631
|
+
//}}}
|
632
|
+
//{{{
|
633
|
+
,hide:function() {
|
634
|
+
return this.setVisible(false);
|
635
|
+
} // eo function hide
|
636
|
+
//}}}
|
637
|
+
// {{{
|
638
|
+
/**
|
639
|
+
* @private Updates the date part
|
640
|
+
*/
|
641
|
+
,updateDate:function() {
|
642
|
+
|
643
|
+
var d = this.df.getValue();
|
644
|
+
if(d) {
|
645
|
+
if(!(this.dateValue instanceof Date)) {
|
646
|
+
this.initDateValue();
|
647
|
+
if(!this.tf.getValue()) {
|
648
|
+
this.setTime(this.dateValue);
|
649
|
+
}
|
650
|
+
}
|
651
|
+
this.dateValue.setMonth(0); // because of leap years
|
652
|
+
this.dateValue.setFullYear(d.getFullYear());
|
653
|
+
this.dateValue.setMonth(d.getMonth(), d.getDate());
|
654
|
+
// this.dateValue.setDate(d.getDate());
|
655
|
+
}
|
656
|
+
else {
|
657
|
+
this.dateValue = '';
|
658
|
+
this.setTime('');
|
659
|
+
}
|
660
|
+
} // eo function updateDate
|
661
|
+
// }}}
|
662
|
+
// {{{
|
663
|
+
/**
|
664
|
+
* @private
|
665
|
+
* Updates the time part
|
666
|
+
*/
|
667
|
+
,updateTime:function() {
|
668
|
+
var t = this.tf.getValue();
|
669
|
+
if(t && !(t instanceof Date)) {
|
670
|
+
t = Date.parseDate(t, this.tf.format);
|
671
|
+
}
|
672
|
+
if(t && !this.df.getValue()) {
|
673
|
+
this.initDateValue();
|
674
|
+
this.setDate(this.dateValue);
|
675
|
+
}
|
676
|
+
if(this.dateValue instanceof Date) {
|
677
|
+
if(t) {
|
678
|
+
this.dateValue.setHours(t.getHours());
|
679
|
+
this.dateValue.setMinutes(t.getMinutes());
|
680
|
+
this.dateValue.setSeconds(t.getSeconds());
|
681
|
+
}
|
682
|
+
else {
|
683
|
+
this.dateValue.setHours(0);
|
684
|
+
this.dateValue.setMinutes(0);
|
685
|
+
this.dateValue.setSeconds(0);
|
686
|
+
}
|
687
|
+
}
|
688
|
+
} // eo function updateTime
|
689
|
+
// }}}
|
690
|
+
// {{{
|
691
|
+
/**
|
692
|
+
* @private Updates the underlying hidden field value
|
693
|
+
*/
|
694
|
+
,updateHidden:function() {
|
695
|
+
if(this.isRendered) {
|
696
|
+
var value = this.dateValue instanceof Date ? this.dateValue.format(this.hiddenFormat) : '';
|
697
|
+
this.el.dom.value = value;
|
698
|
+
}
|
699
|
+
}
|
700
|
+
// }}}
|
701
|
+
// {{{
|
702
|
+
/**
|
703
|
+
* @private Updates all of Date, Time and Hidden
|
704
|
+
*/
|
705
|
+
,updateValue:function() {
|
706
|
+
|
707
|
+
this.updateDate();
|
708
|
+
this.updateTime();
|
709
|
+
this.updateHidden();
|
710
|
+
|
711
|
+
return;
|
712
|
+
} // eo function updateValue
|
713
|
+
// }}}
|
714
|
+
// {{{
|
715
|
+
/**
|
716
|
+
* @return {Boolean} true = valid, false = invalid
|
717
|
+
* calls validate methods of DateField and TimeField
|
718
|
+
*/
|
719
|
+
,validate:function() {
|
720
|
+
return this.df.validate() && this.tf.validate();
|
721
|
+
} // eo function validate
|
722
|
+
// }}}
|
723
|
+
// {{{
|
724
|
+
/**
|
725
|
+
* Returns renderer suitable to render this field
|
726
|
+
* @param {Object} Column model config
|
727
|
+
*/
|
728
|
+
,renderer: function(field) {
|
729
|
+
var format = field.editor.dateFormat || Ext.ux.form.DateTime.prototype.dateFormat;
|
730
|
+
format += ' ' + (field.editor.timeFormat || Ext.ux.form.DateTime.prototype.timeFormat);
|
731
|
+
var renderer = function(val) {
|
732
|
+
var retval = Ext.util.Format.date(val, format);
|
733
|
+
return retval;
|
734
|
+
};
|
735
|
+
return renderer;
|
736
|
+
} // eo function renderer
|
737
|
+
// }}}
|
738
|
+
|
739
|
+
}); // eo extend
|
740
|
+
|
741
|
+
// register xtype
|
742
|
+
Ext.reg('xdatetime', Ext.ux.form.DateTime);
|
743
|
+
|
744
|
+
// eof
|