netzke-basepack 0.3.10 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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