--- /dev/null
+Ext.ns('Gilbert.lib.ui.forms');
+
+
+Gilbert.lib.ui.forms.ClearableComboBox = Ext.extend(Ext.form.ComboBox, {
+
+ initComponent: function () {
+ Gilbert.lib.ui.forms.ClearableComboBox.superclass.initComponent.call(this);
+
+ this.triggerConfig = {
+ tag: 'span',
+ cls: 'x-form-twin-triggers',
+ cn: [
+ {
+ tag: 'img',
+ src: Ext.BLANK_IMAGE_URL,
+ alt: '',
+ cls: 'x-form-trigger x-form-clear-trigger',
+ },
+ {
+ tag: 'img',
+ src: Ext.BLANK_IMAGE_URL,
+ alt: '',
+ cls: 'x-form-trigger ' + this.triggerClass,
+ },
+ ],
+ };
+ },
+
+ afterRender: function () {
+ Gilbert.lib.ui.forms.ClearableComboBox.superclass.afterRender.call(this);
+
+ if (this.value && this.allowBlank) {
+ this.triggers[0].show();
+ } else {
+ this.triggers[0].hide();
+ }
+ },
+
+ initTrigger: function () {
+ Ext.form.TwinTriggerField.prototype.initTrigger.call(this);
+ },
+
+ getTriggerWidth: function () {
+ Ext.form.TwinTriggerField.prototype.getTriggerWidth.call(this);
+ },
+
+ onTrigger2Click: function () {
+ this.onTriggerClick();
+ },
+
+ onTrigger1Click: function () {
+ this.clearValue();
+ this.triggers[0].hide();
+ },
+
+ setValue: function (v) {
+ Gilbert.lib.ui.forms.ClearableComboBox.superclass.setValue.call(this, v);
+
+ if (this.value && this.allowBlank) {
+ this.triggers[0].show();
+ } else {
+ this.triggers[0].hide();
+ }
+ },
+
+ onDestroy: function () {
+ Ext.destroy(this.triggers);
+
+ Gilbert.lib.ui.forms.ClearableComboBox.superclass.onDestroy.call(this);
+ },
+
+});
+Ext.reg('gilbertclearablecombo', Gilbert.lib.ui.forms.ClearableComboBox);
+
+
+Gilbert.lib.ui.forms.ModelChoiceField = Ext.extend(Gilbert.lib.ui.forms.ClearableComboBox, {
+
+ model_app_label: undefined,
+
+ model_name: undefined,
+
+ model_filters: {},
+
+ initComponent: function () {
+ if (!this.model) {
+ this.model = Gilbert.get_model(this.model_app_label, this.model_name);
+ }
+ if (!this.store) {
+ if (!this.model && this.backup_store) {
+ this.store = this.backup_store;
+ } else if (this.model) {
+ this.store = this.model.create_store({
+ baseParams: {
+ filters: this.model_filters,
+ },
+ });
+ this.valueField = 'pk';
+ this.displayField = '__unicode__';
+
+ this.on('beforequery', function () {
+ delete this.lastQuery;
+ }, this);
+ this.store.on('load', function (store, records, options) {
+ this.store_loaded = true;
+ }, this, {single: true});
+ this.store.load();
+
+ this.on('render', function () {
+ var outer = this;
+ this.dropTarget = new Ext.dd.DropTarget(this.el, {
+ ddGroup: outer.model.drag_drop_group,
+ notifyEnter: function (source, e, data) {
+ outer.el.highlight();
+ return Ext.dd.DropTarget.prototype.notifyEnter.call(this);
+ },
+ notifyDrop: function (source, e, data) {
+ outer.setValue(data.selections[0].id);
+ return true;
+ },
+ });
+ }, this);
+ }
+ }
+ Gilbert.lib.ui.forms.ModelChoiceField.superclass.initComponent.call(this);
+ },
+
+ setValue: function (v) {
+ if (this.model && !this.store_loaded) {
+ this.el.dom.value = this.loadingText;
+ this.store.on('load', this.setValue.createDelegate(this, [v]), null, {single: true});
+ return;
+ }
+ return Gilbert.lib.ui.forms.ModelChoiceField.superclass.setValue.call(this, v);
+ }
+
+});
+Ext.reg('gilbertmodelchoicefield', Gilbert.lib.ui.forms.ModelChoiceField);
+
+
+Gilbert.lib.ui.forms.MultipleChoiceField = Ext.extend(Ext.ux.form.SuperBoxSelect, {});
+Ext.reg('gilbertmultiplechoicefield', Gilbert.lib.ui.forms.MultipleChoiceField);
+
+
+Gilbert.lib.ui.forms.ModelMultipleChoiceField = Ext.extend(Gilbert.lib.ui.forms.MultipleChoiceField, {});
+Ext.reg('gilbertmodelmultiplechoicefield', Gilbert.lib.ui.forms.ModelMultipleChoiceField);
+
+
+/*
+Gilbert.lib.ui.DateTimeField is derived from revision 813 of Ext.ux.form.DateTime by Ing. Jozef Sakáloš as posted at http://extjs.com/forum/showthread.php?t=22661.
+It, and the original, is licensed under the GNU LGPL version 3.0 (http://www.gnu.org/licenses/lgpl.html).
+*/
+
+/**
+ * Creates new DateTimeField
+ * @constructor
+ * @param {Object} config A config object
+ */
+Gilbert.lib.ui.DateTimeField = Ext.extend(Ext.form.Field, {
+ /**
+ * @cfg {Function} dateValidator A custom validation function to be called during date field
+ * validation (defaults to null)
+ */
+ dateValidator: null
+ /**
+ * @cfg {String/Object} defaultAutoCreate DomHelper element spec
+ * Let superclass to create hidden field instead of textbox. Hidden will be submittend to server
+ */
+ ,
+ defaultAutoCreate: {
+ tag: 'input',
+ type: 'hidden'
+ }
+ /**
+ * @cfg {String} dtSeparator Date - Time separator. Used to split date and time (defaults to ' ' (space))
+ */
+ ,
+ dtSeparator: ' '
+ /**
+ * @cfg {String} hiddenFormat Format of datetime used to store value in hidden field
+ * and submitted to server (defaults to 'Y-m-d H:i:s' that is mysql format)
+ */
+ ,
+ hiddenFormat: 'Y-m-d H:i:s'
+ /**
+ * @cfg {Boolean} otherToNow Set other field to now() if not explicly filled in (defaults to true)
+ */
+ ,
+ otherToNow: true
+ /**
+ * @cfg {Boolean} emptyToNow Set field value to now on attempt to set empty value.
+ * If it is true then setValue() sets value of field to current date and time (defaults to false)
+ */
+ /**
+ * @cfg {String} timePosition Where the time field should be rendered. 'right' is suitable for forms
+ * and 'below' is suitable if the field is used as the grid editor (defaults to 'right')
+ */
+ ,
+ timePosition: 'right'
+ // valid values:'below', 'right'
+ /**
+ * @cfg {Function} timeValidator A custom validation function to be called during time field
+ * validation (defaults to null)
+ */
+ ,
+ timeValidator: null
+ /**
+ * @cfg {Number} timeWidth Width of time field in pixels (defaults to 100)
+ */
+ ,
+ timeWidth: 100
+ /**
+ * @cfg {String} dateFormat Format of DateField. Can be localized. (defaults to 'm/y/d')
+ */
+ ,
+ dateFormat: 'm/d/y'
+ /**
+ * @cfg {String} timeFormat Format of TimeField. Can be localized. (defaults to 'g:i A')
+ */
+ ,
+ timeFormat: 'g:i A'
+ /**
+ * @cfg {Object} dateConfig Config for DateField constructor.
+ */
+ /**
+ * @cfg {Object} timeConfig Config for TimeField constructor.
+ */
+
+ // {{{
+ /**
+ * @private
+ * creates DateField and TimeField and installs the necessary event handlers
+ */
+ ,
+ initComponent: function() {
+ // call parent initComponent
+ Gilbert.lib.ui.DateTimeField.superclass.initComponent.call(this);
+
+ // create DateField
+ var dateConfig = Ext.apply({},
+ {
+ id: this.id + '-date'
+ ,
+ format: this.dateFormat || Ext.form.DateField.prototype.format
+ ,
+ width: this.timeWidth
+ ,
+ selectOnFocus: this.selectOnFocus
+ ,
+ validator: this.dateValidator
+ ,
+ listeners: {
+ blur: {
+ scope: this,
+ fn: this.onBlur
+ }
+ ,
+ focus: {
+ scope: this,
+ fn: this.onFocus
+ }
+ }
+ },
+ this.dateConfig);
+ this.df = new Ext.form.DateField(dateConfig);
+ this.df.ownerCt = this;
+ delete(this.dateFormat);
+
+ // create TimeField
+ var timeConfig = Ext.apply({},
+ {
+ id: this.id + '-time'
+ ,
+ format: this.timeFormat || Ext.form.TimeField.prototype.format
+ ,
+ width: this.timeWidth
+ ,
+ selectOnFocus: this.selectOnFocus
+ ,
+ validator: this.timeValidator
+ ,
+ listeners: {
+ blur: {
+ scope: this,
+ fn: this.onBlur
+ }
+ ,
+ focus: {
+ scope: this,
+ fn: this.onFocus
+ }
+ }
+ },
+ this.timeConfig);
+ this.tf = new Ext.form.TimeField(timeConfig);
+ this.tf.ownerCt = this;
+ delete(this.timeFormat);
+
+ // relay events
+ this.relayEvents(this.df, ['focus', 'specialkey', 'invalid', 'valid']);
+ this.relayEvents(this.tf, ['focus', 'specialkey', 'invalid', 'valid']);
+
+ this.on('specialkey', this.onSpecialKey, this);
+
+ }
+ // eo function initComponent
+ // }}}
+ // {{{
+ /**
+ * @private
+ * Renders underlying DateField and TimeField and provides a workaround for side error icon bug
+ */
+ ,
+ onRender: function(ct, position) {
+ // don't run more than once
+ if (this.isRendered) {
+ return;
+ }
+
+ // render underlying hidden field
+ Gilbert.lib.ui.DateTimeField.superclass.onRender.call(this, ct, position);
+
+ // render DateField and TimeField
+ // create bounding table
+ var t;
+ if ('below' === this.timePosition || 'bellow' === this.timePosition) {
+ t = Ext.DomHelper.append(ct, {
+ tag: 'table',
+ style: 'border-collapse:collapse',
+ children: [
+ {
+ tag: 'tr',
+ children: [{
+ tag: 'td',
+ style: 'padding-bottom:1px',
+ cls: 'ux-datetime-date'
+ }]
+ }
+ ,
+ {
+ tag: 'tr',
+ children: [{
+ tag: 'td',
+ cls: 'ux-datetime-time'
+ }]
+ }
+ ]
+ },
+ true);
+ }
+ else {
+ t = Ext.DomHelper.append(ct, {
+ tag: 'table',
+ style: 'border-collapse:collapse',
+ children: [
+ {
+ tag: 'tr',
+ children: [
+ {
+ tag: 'td',
+ style: 'padding-right:4px',
+ cls: 'ux-datetime-date'
+ },
+ {
+ tag: 'td',
+ cls: 'ux-datetime-time'
+ }
+ ]
+ }
+ ]
+ },
+ true);
+ }
+
+ this.tableEl = t;
+ this.wrap = t.wrap({
+ cls: 'x-form-field-wrap'
+ });
+ // this.wrap = t.wrap();
+ this.wrap.on("mousedown", this.onMouseDown, this, {
+ delay: 10
+ });
+
+ // render DateField & TimeField
+ this.df.render(t.child('td.ux-datetime-date'));
+ this.tf.render(t.child('td.ux-datetime-time'));
+
+ // workaround for IE trigger misalignment bug
+ // see http://extjs.com/forum/showthread.php?p=341075#post341075
+ // if(Ext.isIE && Ext.isStrict) {
+ // t.select('input').applyStyles({top:0});
+ // }
+ this.df.el.swallowEvent(['keydown', 'keypress']);
+ this.tf.el.swallowEvent(['keydown', 'keypress']);
+
+ // create icon for side invalid errorIcon
+ if ('side' === this.msgTarget) {
+ var elp = this.el.findParent('.x-form-element', 10, true);
+ if (elp) {
+ this.errorIcon = elp.createChild({
+ cls: 'x-form-invalid-icon'
+ });
+ }
+
+ var o = {
+ errorIcon: this.errorIcon
+ ,
+ msgTarget: 'side'
+ ,
+ alignErrorIcon: this.alignErrorIcon.createDelegate(this)
+ };
+ Ext.apply(this.df, o);
+ Ext.apply(this.tf, o);
+ // this.df.errorIcon = this.errorIcon;
+ // this.tf.errorIcon = this.errorIcon;
+ }
+
+ // setup name for submit
+ this.el.dom.name = this.hiddenName || this.name || this.id;
+
+ // prevent helper fields from being submitted
+ this.df.el.dom.removeAttribute("name");
+ this.tf.el.dom.removeAttribute("name");
+
+ // we're rendered flag
+ this.isRendered = true;
+
+ // update hidden field
+ this.updateHidden();
+
+ }
+ // eo function onRender
+ // }}}
+ // {{{
+ /**
+ * @private
+ */
+ ,
+ adjustSize: Ext.BoxComponent.prototype.adjustSize
+ // }}}
+ // {{{
+ /**
+ * @private
+ */
+ ,
+ alignErrorIcon: function() {
+ this.errorIcon.alignTo(this.tableEl, 'tl-tr', [2, 0]);
+ }
+ // }}}
+ // {{{
+ /**
+ * @private initializes internal dateValue
+ */
+ ,
+ initDateValue: function() {
+ this.dateValue = this.otherToNow ? new Date() : new Date(1970, 0, 1, 0, 0, 0);
+ }
+ // }}}
+ // {{{
+ /**
+ * Calls clearInvalid on the DateField and TimeField
+ */
+ ,
+ clearInvalid: function() {
+ this.df.clearInvalid();
+ this.tf.clearInvalid();
+ }
+ // eo function clearInvalid
+ // }}}
+ // {{{
+ /**
+ * Calls markInvalid on both DateField and TimeField
+ * @param {String} msg Invalid message to display
+ */
+ ,
+ markInvalid: function(msg) {
+ this.df.markInvalid(msg);
+ this.tf.markInvalid(msg);
+ }
+ // eo function markInvalid
+ // }}}
+ // {{{
+ /**
+ * @private
+ * called from Component::destroy.
+ * Destroys all elements and removes all listeners we've created.
+ */
+ ,
+ beforeDestroy: function() {
+ if (this.isRendered) {
+ // this.removeAllListeners();
+ this.wrap.removeAllListeners();
+ this.wrap.remove();
+ this.tableEl.remove();
+ this.df.destroy();
+ this.tf.destroy();
+ }
+ }
+ // eo function beforeDestroy
+ // }}}
+ // {{{
+ /**
+ * Disable this component.
+ * @return {Ext.Component} this
+ */
+ ,
+ disable: function() {
+ if (this.isRendered) {
+ this.df.disabled = this.disabled;
+ this.df.onDisable();
+ this.tf.onDisable();
+ }
+ this.disabled = true;
+ this.df.disabled = true;
+ this.tf.disabled = true;
+ this.fireEvent("disable", this);
+ return this;
+ }
+ // eo function disable
+ // }}}
+ // {{{
+ /**
+ * Enable this component.
+ * @return {Ext.Component} this
+ */
+ ,
+ enable: function() {
+ if (this.rendered) {
+ this.df.onEnable();
+ this.tf.onEnable();
+ }
+ this.disabled = false;
+ this.df.disabled = false;
+ this.tf.disabled = false;
+ this.fireEvent("enable", this);
+ return this;
+ }
+ // eo function enable
+ // }}}
+ // {{{
+ /**
+ * @private Focus date filed
+ */
+ ,
+ focus: function() {
+ this.df.focus();
+ }
+ // eo function focus
+ // }}}
+ // {{{
+ /**
+ * @private
+ */
+ ,
+ getPositionEl: function() {
+ return this.wrap;
+ }
+ // }}}
+ // {{{
+ /**
+ * @private
+ */
+ ,
+ getResizeEl: function() {
+ return this.wrap;
+ }
+ // }}}
+ // {{{
+ /**
+ * @return {Date/String} Returns value of this field
+ */
+ ,
+ getValue: function() {
+ // create new instance of date
+ return this.dateValue ? new Date(this.dateValue) : '';
+ }
+ // eo function getValue
+ // }}}
+ // {{{
+ /**
+ * @return {Boolean} true = valid, false = invalid
+ * @private Calls isValid methods of underlying DateField and TimeField and returns the result
+ */
+ ,
+ isValid: function() {
+ return this.df.isValid() && this.tf.isValid();
+ }
+ // eo function isValid
+ // }}}
+ // {{{
+ /**
+ * Returns true if this component is visible
+ * @return {boolean}
+ */
+ ,
+ isVisible: function() {
+ return this.df.rendered && this.df.getActionEl().isVisible();
+ }
+ // eo function isVisible
+ // }}}
+ // {{{
+ /**
+ * @private Handles blur event
+ */
+ ,
+ onBlur: function(f) {
+ // called by both DateField and TimeField blur events
+ // revert focus to previous field if clicked in between
+ if (this.wrapClick) {
+ f.focus();
+ this.wrapClick = false;
+ }
+
+ // update underlying value
+ if (f === this.df) {
+ this.updateDate();
+ }
+ else {
+ this.updateTime();
+ }
+ this.updateHidden();
+
+ this.validate();
+
+ // fire events later
+ (function() {
+ if (!this.df.hasFocus && !this.tf.hasFocus) {
+ var v = this.getValue();
+ if (String(v) !== String(this.startValue)) {
+ this.fireEvent("change", this, v, this.startValue);
+ }
+ this.hasFocus = false;
+ this.fireEvent('blur', this);
+ }
+ }).defer(100, this);
+
+ }
+ // eo function onBlur
+ // }}}
+ // {{{
+ /**
+ * @private Handles focus event
+ */
+ ,
+ onFocus: function() {
+ if (!this.hasFocus) {
+ this.hasFocus = true;
+ this.startValue = this.getValue();
+ this.fireEvent("focus", this);
+ }
+ }
+ // }}}
+ // {{{
+ /**
+ * @private Just to prevent blur event when clicked in the middle of fields
+ */
+ ,
+ onMouseDown: function(e) {
+ if (!this.disabled) {
+ this.wrapClick = 'td' === e.target.nodeName.toLowerCase();
+ }
+ }
+ // }}}
+ // {{{
+ /**
+ * @private
+ * Handles Tab and Shift-Tab events
+ */
+ ,
+ onSpecialKey: function(t, e) {
+ var key = e.getKey();
+ if (key === e.TAB) {
+ if (t === this.df && !e.shiftKey) {
+ e.stopEvent();
+ this.tf.focus();
+ }
+ if (t === this.tf && e.shiftKey) {
+ e.stopEvent();
+ this.df.focus();
+ }
+ this.updateValue();
+ }
+ // otherwise it misbehaves in editor grid
+ if (key === e.ENTER) {
+ this.updateValue();
+ }
+
+ }
+ // eo function onSpecialKey
+ // }}}
+ // {{{
+ /**
+ * Resets the current field value to the originally loaded value
+ * and clears any validation messages. See Ext.form.BasicForm.trackResetOnLoad
+ */
+ ,
+ reset: function() {
+ this.df.setValue(this.originalValue);
+ this.tf.setValue(this.originalValue);
+ }
+ // eo function reset
+ // }}}
+ // {{{
+ /**
+ * @private Sets the value of DateField
+ */
+ ,
+ setDate: function(date) {
+ this.df.setValue(date);
+ }
+ // eo function setDate
+ // }}}
+ // {{{
+ /**
+ * @private Sets the value of TimeField
+ */
+ ,
+ setTime: function(date) {
+ this.tf.setValue(date);
+ }
+ // eo function setTime
+ // }}}
+ // {{{
+ /**
+ * @private
+ * Sets correct sizes of underlying DateField and TimeField
+ * With workarounds for IE bugs
+ */
+ ,
+ setSize: function(w, h) {
+ if (!w) {
+ return;
+ }
+ if ('below' === this.timePosition) {
+ this.df.setSize(w, h);
+ this.tf.setSize(w, h);
+ if (Ext.isIE) {
+ this.df.el.up('td').setWidth(w);
+ this.tf.el.up('td').setWidth(w);
+ }
+ }
+ else {
+ this.df.setSize(w - this.timeWidth - 4, h);
+ this.tf.setSize(this.timeWidth, h);
+
+ if (Ext.isIE) {
+ this.df.el.up('td').setWidth(w - this.timeWidth - 4);
+ this.tf.el.up('td').setWidth(this.timeWidth);
+ }
+ }
+ }
+ // eo function setSize
+ // }}}
+ // {{{
+ /**
+ * @param {Mixed} val Value to set
+ * Sets the value of this field
+ */
+ ,
+ setValue: function(val) {
+ if (!val && true === this.emptyToNow) {
+ this.setValue(new Date());
+ return;
+ }
+ else if (!val) {
+ this.setDate('');
+ this.setTime('');
+ this.updateValue();
+ return;
+ }
+ if ('number' === typeof val) {
+ val = new Date(val);
+ }
+ else if ('string' === typeof val && this.hiddenFormat) {
+ val = Date.parseDate(val, this.hiddenFormat);
+ }
+ val = val ? val: new Date(1970, 0, 1, 0, 0, 0);
+ var da;
+ if (val instanceof Date) {
+ this.setDate(val);
+ this.setTime(val);
+ this.dateValue = new Date(Ext.isIE ? val.getTime() : val);
+ }
+ else {
+ da = val.split(this.dtSeparator);
+ this.setDate(da[0]);
+ if (da[1]) {
+ if (da[2]) {
+ // add am/pm part back to time
+ da[1] += da[2];
+ }
+ this.setTime(da[1]);
+ }
+ }
+ this.updateValue();
+ }
+ // eo function setValue
+ // }}}
+ // {{{
+ /**
+ * Hide or show this component by boolean
+ * @return {Ext.Component} this
+ */
+ ,
+ setVisible: function(visible) {
+ if (visible) {
+ this.df.show();
+ this.tf.show();
+ } else {
+ this.df.hide();
+ this.tf.hide();
+ }
+ return this;
+ }
+ // eo function setVisible
+ // }}}
+ //{{{
+ ,
+ show: function() {
+ return this.setVisible(true);
+ }
+ // eo function show
+ //}}}
+ //{{{
+ ,
+ hide: function() {
+ return this.setVisible(false);
+ }
+ // eo function hide
+ //}}}
+ // {{{
+ /**
+ * @private Updates the date part
+ */
+ ,
+ updateDate: function() {
+
+ var d = this.df.getValue();
+ if (d) {
+ if (! (this.dateValue instanceof Date)) {
+ this.initDateValue();
+ if (!this.tf.getValue()) {
+ this.setTime(this.dateValue);
+ }
+ }
+ this.dateValue.setMonth(0);
+ // because of leap years
+ this.dateValue.setFullYear(d.getFullYear());
+ this.dateValue.setMonth(d.getMonth(), d.getDate());
+ // this.dateValue.setDate(d.getDate());
+ }
+ else {
+ this.dateValue = '';
+ this.setTime('');
+ }
+ }
+ // eo function updateDate
+ // }}}
+ // {{{
+ /**
+ * @private
+ * Updates the time part
+ */
+ ,
+ updateTime: function() {
+ var t = this.tf.getValue();
+ if (t && !(t instanceof Date)) {
+ t = Date.parseDate(t, this.tf.format);
+ }
+ if (t && !this.df.getValue()) {
+ this.initDateValue();
+ this.setDate(this.dateValue);
+ }
+ if (this.dateValue instanceof Date) {
+ if (t) {
+ this.dateValue.setHours(t.getHours());
+ this.dateValue.setMinutes(t.getMinutes());
+ this.dateValue.setSeconds(t.getSeconds());
+ }
+ else {
+ this.dateValue.setHours(0);
+ this.dateValue.setMinutes(0);
+ this.dateValue.setSeconds(0);
+ }
+ }
+ }
+ // eo function updateTime
+ // }}}
+ // {{{
+ /**
+ * @private Updates the underlying hidden field value
+ */
+ ,
+ updateHidden: function() {
+ if (this.isRendered) {
+ var value = this.dateValue instanceof Date ? this.dateValue.format(this.hiddenFormat) : '';
+ this.el.dom.value = value;
+ }
+ }
+ // }}}
+ // {{{
+ /**
+ * @private Updates all of Date, Time and Hidden
+ */
+ ,
+ updateValue: function() {
+
+ this.updateDate();
+ this.updateTime();
+ this.updateHidden();
+
+ return;
+ }
+ // eo function updateValue
+ // }}}
+ // {{{
+ /**
+ * @return {Boolean} true = valid, false = invalid
+ * calls validate methods of DateField and TimeField
+ */
+ ,
+ validate: function() {
+ return this.df.validate() && this.tf.validate();
+ }
+ // eo function validate
+ // }}}
+ // {{{
+ /**
+ * Returns renderer suitable to render this field
+ * @param {Object} Column model config
+ */
+ ,
+ renderer: function(field) {
+ var format = field.editor.dateFormat || Gilbert.lib.ui.DateTimeField.prototype.dateFormat;
+ format += ' ' + (field.editor.timeFormat || Gilbert.lib.ui.DateTimeField.prototype.timeFormat);
+ var renderer = function(val) {
+ var retval = Ext.util.Format.date(val, format);
+ return retval;
+ };
+ return renderer;
+ }
+ // eo function renderer
+ // }}}
+});
+// eo extend
+// register xtype
+Ext.reg('gilbertdatetimefield', Gilbert.lib.ui.DateTimeField);