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.
Files changed (42) hide show
  1. data/CHANGELOG +10 -0
  2. data/Manifest +12 -16
  3. data/Rakefile +1 -1
  4. data/TODO +3 -1
  5. data/autotest/discover.rb +3 -0
  6. data/javascripts/basepack.js +680 -52
  7. data/lib/app/models/netzke_hash_record.rb +180 -0
  8. data/lib/app/models/netzke_layout_item.rb +11 -0
  9. data/lib/netzke/ar_ext.rb +57 -34
  10. data/lib/netzke/border_layout_panel.rb +0 -1
  11. data/lib/netzke/db_fields.rb +4 -0
  12. data/lib/netzke/field_model.rb +131 -0
  13. data/lib/netzke/fields_configurator.rb +13 -5
  14. data/lib/netzke/fields_configurator_old.rb +62 -0
  15. data/lib/netzke/form_panel.rb +18 -24
  16. data/lib/netzke/form_panel_extras/interface.rb +20 -13
  17. data/lib/netzke/form_panel_extras/js_builder.rb +4 -1
  18. data/lib/netzke/grid_panel.rb +37 -40
  19. data/lib/netzke/grid_panel_extras/interface.rb +22 -18
  20. data/lib/netzke/grid_panel_extras/js_builder.rb +42 -13
  21. data/lib/netzke/property_editor_extras/helper_model.rb +2 -1
  22. data/lib/netzke/tab_panel.rb +15 -11
  23. data/netzke-basepack.gemspec +10 -10
  24. data/test/{accordion_panel_test.rb → unit/accordion_panel_test.rb} +0 -0
  25. data/test/{ar_ext_test.rb → unit/ar_ext_test.rb} +3 -9
  26. data/test/{grid_panel_test.rb → unit/grid_panel_test.rb} +0 -5
  27. data/test/{netzke_basepack_test.rb → unit/netzke_basepack_test.rb} +0 -0
  28. data/test/unit/netzke_hash_record_test.rb +52 -0
  29. data/test/unit/netzke_layout_item_test.rb +28 -0
  30. data/test/{tab_panel_test.rb → unit/tab_panel_test.rb} +0 -0
  31. metadata +30 -30
  32. data/generators/netzke_basepack/USAGE +0 -8
  33. data/generators/netzke_basepack/netzke_basepack_generator.rb +0 -8
  34. data/generators/netzke_form_panel/netzke_form_panel_generator.rb +0 -7
  35. data/generators/netzke_form_panel/templates/create_netzke_form_panel_fields.rb +0 -21
  36. data/generators/netzke_grid_panel/netzke_grid_panel_generator.rb +0 -7
  37. data/generators/netzke_grid_panel/templates/create_netzke_grid_panel_columns.rb +0 -24
  38. data/lib/app/models/netzke_form_panel_field.rb +0 -51
  39. data/lib/app/models/netzke_grid_panel_column.rb +0 -56
  40. data/lib/netzke/form_panel_extras/javascripts/xdatetime.js +0 -634
  41. data/test/app_root/db/migrate/20090102223811_create_netzke_grid_panel_columns.rb +0 -23
  42. 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/netzke_form_panel_field.rb
12
- lib/app/models/netzke_grid_panel_column.rb
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.2.11"]
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
@@ -0,0 +1,3 @@
1
+ Autotest.add_discovery do
2
+ "rails"
3
+ end
@@ -1,61 +1,46 @@
1
1
  Ext.apply(Ext.History, new Ext.util.Observable());
2
2
 
3
- // Editors for grid cells and form fields
4
- Ext.netzke.editors = {
5
- combo_box: function(c, config){
6
- var row = Ext.data.Record.create([{name:'id'}])
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:config.interface.getCbChoices, jsonData:{column:c.name}}),
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
- var comboBox = new Ext.form.ComboBox({
13
- mode : 'remote',
14
- displayField : 'id',
15
- valueField : 'id',
16
- triggerAction : 'all',
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
- // let user enter values that are not in the store
23
- comboBox.on('blur', function(cb){
32
+ this.on('blur', function(cb){
24
33
  cb.setValue(cb.getRawValue());
25
34
  });
26
- comboBox.on('specialkey', function(cb, event){
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
- number_field:'Numeric',
83
- text_field:'String',
84
- datetime:'String',
67
+ numberfield:'Numeric',
68
+ textfield:'String',
69
+ xdatetime:'String',
85
70
  checkbox:'Boolean',
86
- combo_box:'String',
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