-
14 Feb 2012 7:19 AM #1
ja Ext.ux.form.DateTimeField
ja Ext.ux.form.DateTimeField
Hello,
I needed some simple and strong date-time field (found some here but still problematic here and there)
So I started with this one using only native ExtJs date and time edition abilities. It uses one input-text and has two triggers.
It is basically one dateField who has a timeField bound to the same elements and triggered by the second trigger.
dtsnap.png
Hope it might help.
Code:/* * 14Feb 2012 - DateTimeField * Francois Marie De Mey - eeddow@gmail * * Date-time field with one common input box and two trigger/picker */ (function() { var //Combine a date and a time. Doesn't modify any combine = function(me, date, time) { if('string'=== typeof date) date = me.parseDate(date); if(!date) date = new Date(); if('string'=== typeof time) time = me.parseDate(time); if(!time) time = new Date(); var rv = new Date(date); rv.setHours(time.getHours()); rv.setMinutes(time.getMinutes()); rv.setSeconds(time.getSeconds()); return rv; }, //Trick the 'format' option for some timeField functions needing only time to be used oldFormatFunction = function(methodName) { return function() { var me = this, rv, dateCtl = me.datetimeField; me.format = dateCtl.timeFormat; rv = Ext.form.TimeField.prototype[methodName].apply(me, arguments); me.format = dateCtl.format; return rv; }; }; Ext.define('Ext.ux.form.DateTimeField', { extend: 'Ext.form.DateField', alias: 'widget.datetimefield', requires: ['Ext.form.TimeField'], trigger2Cls: Ext.baseCSSPrefix + 'form-time-trigger', /** * @cfg {Number} pickerMaxHeight * The maximum height of the {@link Ext.picker.Time} dropdown. */ /** * @cfg {String} minTimeText * The error text to display when the entered time is before {@link #minTime}. */ /** * @cfg {Date/String} minTime * The minimum allowed time. Can be either a Javascript date object with a valid time value or a string time in a * valid format -- see {@link #format} and {@link #altFormats}. */ /** * @cfg {String} maxTimeText * The error text to display when the entered time is after {@link #maxTime}. */ /** * @cfg {Date/String} maxTime * The maximum allowed time. Can be either a Javascript date object with a valid time value or a string time in a * valid format -- see {@link #format} and {@link #altFormats}. */ /** * @cfg {Number} increment * The number of minutes between each time value in the list. */ /** * @cfg {String} format * The default date format string which can be overriden for localization support. The format must be valid * according to {@link Ext.Date#parse}. */ format : "m/d/Y H:i", /** * @cfg {String} format * The default time format string used to express only the time part. The format must be valid * according to {@link Ext.Date#parse}. */ timeFormat: "H:i", /** * @cfg {String} altFormats * Multiple date formats separated by "|" to try when parsing a user input value and it does not match the defined * format. */ altFormats : "m/d/Y H:i|n/j/Y H:i|n/j/y H:i|m/j/y H:i|n/d/y H:i|m/j/Y H:i|n/d/Y H:i|m-d-y H:i|m-d-Y H:i|m/d H:i|m-d H:i|md H:i|mdy H:i|mdY H:i|d H:i|Y-m-d H:i|n-j H:i|n/j H:i", initComponent: function() { var me = this, elm, config = { datetimeField: me, //share the format format: me.format, altFormats: me.altFormats, //Straight forwards minText: me.minTimeText, maxText: me.maxTimeText, //Don't set the value, juste the "time" part of the value onListSelect: function(list, recordArray) { var me = this, record = recordArray[0], val = record ? record.get('date') : null; me.datetimeField.setValue(combine(me, me.getValue(), val)); me.fireEvent('select', me, val); me.picker.clearHighlight(); me.collapse(); me.inputEl.focus(); }, //Oops... we must use the 'time' format some times createPicker: oldFormatFunction('createPicker'), setLimit: oldFormatFunction('setLimit') }, forward = { minValue: me.minTime, maxValue: me.maxTime, increment: me.increment, pickerMaxHeight: me.pickerMaxHeight }; for(elm in forward) if({}.u!== forward[elm] && forward.hasOwnProperty(elm)) config[elm] = forward[elm]; //Create the "virtual" time field me.timeField = new Ext.form.TimeField(config); this.callParent(); }, onRender: function() { var me = this, triggers; me.callParent(arguments); triggers = me.triggerEl; me.dateTrigger = triggers.item(0); me.timeTrigger = triggers.item(1); Ext.apply(me.timeField, { rendered: true, el: me.el, inputEl: me.inputEl, bodyEl: me.bodyEl, errorEl: me.errorEl }); }, mimicBlur: function(e) { var me = this, picker = me.timeField.picker; // ignore mousedown events within the picker element if (!picker || !e.within(picker.el, false, true)) { me.callParent(arguments); } }, //Suddenly, a wide trigger appears... getTriggerWidth: function() { return this.hideTrigger || this.readOnly ? 0 : this.timeTrigger.getWidth() + this.dateTrigger.getWidth() + this.triggerWrap.getFrameWidth('lr'); }, //Manually expand our "virtual" time field onTrigger2Click: function() { var me=this; me.collapse(); me.timeField.onTriggerClick(); }, onTriggerClick: function() { var me=this; me.timeField.collapse(); me.callParent(arguments); }, //Don't set the value, juste the "date" part of the value onSelect: function(m, d) { var me = this; me.setValue(combine(me, d, me.getValue())); me.fireEvent('select', me, d); me.collapse(); }, //Combinations getErrors: function(value) { var me = this, format = Ext.String.format, errors = me.callParent(arguments), minValue = me.minTime, maxValue = me.maxTime, date; value = me.formatDate(value || me.processRawValue(me.getRawValue())); if (value === null || value.length < 1) { // if it's blank and textfield didn't flag it then it's valid return errors; } date = me.parseDate(value); if (!date) { //avoid double format error return errors; } if (minValue && date < minValue) { errors.push(format(me.minText, me.formatDate(minValue))); } if (maxValue && date > maxValue) { errors.push(format(me.maxText, me.formatDate(maxValue))); } return errors; }, setValue: function() { var me = this, args = arguments, timeField = me.timeField; me.callParent(args); return timeField.setValue.apply(timeField, arguments); }, //Straight forwards setMaxTime: function() { var timeField = this.timeField; return timeField.setMaxValue.apply(timeField, arguments); }, setMinTime: function() { var timeField = this.timeField; return timeField.setMinValue.apply(timeField, arguments); } }); })();Last edited by eddow; 15 Feb 2012 at 4:17 AM. Reason: bug-fix for in-column editor
-
14 Feb 2012 8:32 AM #2Sencha - Senior Forum Manager
- Join Date
- Mar 2007
- Location
- St. Louis, MO
- Posts
- 33,641
- Vote Rating
- 434
You should change the trigger for the time to be a clock icon
Mitchell Simoens @SenchaMitch
Sencha Inc, Senior Forum Manager
________________
http://www.JSONPLint.com - Source to lint your JSONP!
Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
https://github.com/mitchellsimoens
Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/
Need more help with your app? Hire Sencha Services services@sencha.com
Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is almost in print!
When posting code, please use BBCode's CODE tags.
-
14 Feb 2012 9:19 AM #3
Indeed, I made an icon but, using paint, it sprayed my icon with rainbow pixel (GIF compression) and I was lazzy to work it out again.
It was indeed not that hard and I just set it in png. (if one is in the mood to set back the green to transparency and perhaps have it as a quality gif for consistency)
The icon is: time-trigger.png (clock icon from silk - famfamfam.com )
The result is: dtsnap.png
You have to add in any CSS :
Code:.x-form-time-trigger { background-image: url('../../resources/themes/images/default/form/time-trigger.png') !important; }
-
15 Mar 2012 7:05 AM #4
Does not work with 4.1 RC1
Some fixes?
thanks
-
1 Apr 2012 9:14 AM #5
Sorry, I forgot to post it: the changes are minor, it's due to a change in the time field.
Here is the 4.1rc1 compatible :
Code:/* * 14Feb 2012 - DateTimeField * Francois Marie De Mey - eeddow@gmail * * Date-time field with one common input box and two trigger/picker */ (function() { var //Combine a date and a time. Doesn't modify any combine = function(me, date, time) { if(Ext.isString(date)) date = me.parseDate(date); if(!date) date = new Date(); if(Ext.isString(time)) time = me.parseDate(time); if(!time) time = new Date(); var rv = new Date(date); rv.setHours(time.getHours()); rv.setMinutes(time.getMinutes()); rv.setSeconds(time.getSeconds()); return rv; }, //Trick the 'format' option for some timeField functions needing only time to be used oldFormatFunction = function(methodName) { return function() { var me = this, rv, dateCtl = me.datetimeField; me.format = dateCtl.timeFormat; rv = Ext.form.TimeField.prototype[methodName].apply(me, arguments); me.format = dateCtl.format; return rv; }; }; Ext.define('Ext.ux.form.DateTimeField', { extend: 'Ext.form.DateField', alias: 'widget.datetimefield', requires: ['Ext.form.TimeField'], trigger2Cls: Ext.baseCSSPrefix + 'form-time-trigger', /** * @cfg {Number} pickerMaxHeight * The maximum height of the {@link Ext.picker.Time} dropdown. */ /** * @cfg {String} minTimeText * The error text to display when the entered time is before {@link #minTime}. */ /** * @cfg {Date/String} minTime * The minimum allowed time. Can be either a Javascript date object with a valid time value or a string time in a * valid format -- see {@link #format} and {@link #altFormats}. */ /** * @cfg {String} maxTimeText * The error text to display when the entered time is after {@link #maxTime}. */ /** * @cfg {Date/String} maxTime * The maximum allowed time. Can be either a Javascript date object with a valid time value or a string time in a * valid format -- see {@link #format} and {@link #altFormats}. */ /** * @cfg {Number} increment * The number of minutes between each time value in the list. */ /** * @cfg {String} format * The default date format string which can be overriden for localization support. The format must be valid * according to {@link Ext.Date#parse}. */ format : "m/d/Y H:i", /** * @cfg {String} format * The default time format string used to express only the time part. The format must be valid * according to {@link Ext.Date#parse}. */ timeFormat: "H:i", /** * @cfg {String} altFormats * Multiple date formats separated by "|" to try when parsing a user input value and it does not match the defined * format. */ altFormats : "m/d/Y H:i|n/j/Y H:i|n/j/y H:i|m/j/y H:i|n/d/y H:i|m/j/Y H:i|n/d/Y H:i|m-d-y H:i|m-d-Y H:i|m/d H:i|m-d H:i|md H:i|mdy H:i|mdY H:i|d H:i|Y-m-d H:i|n-j H:i|n/j H:i", initComponent: function() { var me = this, elm, config = { datetimeField: me, //share the format format: me.format, altFormats: me.altFormats, //Straight forwards minText: me.minTimeText, maxText: me.maxTimeText, //Don't set the value, juste the "time" part of the value onListSelectionChange: function(list, recordArray) { var me = this, record = recordArray[0], val = record ? record.get('date') : null; if (!me.ignoreSelection) { me.skipSync = true; me.datetimeField.setValue(combine(me, me.getValue(), val)); me.skipSync = false; me.fireEvent('select', me, val); me.picker.clearHighlight(); me.collapse(); me.inputEl.focus(); } }, //Oops... we must use the 'time' format some times createPicker: oldFormatFunction('createPicker'), setLimit: oldFormatFunction('setLimit') }, forward = { minValue: me.minTime, maxValue: me.maxTime, increment: me.increment, pickerMaxHeight: me.pickerMaxHeight }; for(elm in forward) if(forward.hasOwnProperty(elm) && {}.u!== forward[elm]) config[elm] = forward[elm]; //Create the "virtual" time field me.timeField = new Ext.form.TimeField(config); this.callParent(); }, onRender: function() { var me = this, triggers; me.callParent(arguments); triggers = me.triggerEl; me.dateTrigger = triggers.item(0); me.timeTrigger = triggers.item(1); Ext.apply(me.timeField, { rendered: true, el: me.el, inputEl: me.inputEl, bodyEl: me.bodyEl, errorEl: me.errorEl, doc: me.doc }); }, mimicBlur: function(e) { var me = this, picker = me.timeField.picker; // ignore mousedown events within the picker element if (!picker || !e.within(picker.el, false, true)) { me.callParent(arguments); } }, //Suddenly, a wide trigger appears... getTriggerWidth: function() { return this.hideTrigger || this.readOnly ? 0 : this.timeTrigger.getWidth() + this.dateTrigger.getWidth() + this.triggerWrap.getFrameWidth('lr'); }, //Manually expand our "virtual" time field onTrigger2Click: function() { var me=this; me.collapse(); me.timeField.onTriggerClick(); }, onTriggerClick: function() { var me=this; me.timeField.collapse(); me.callParent(arguments); }, //Don't set the value, juste the "date" part of the value onSelect: function(m, d) { var me = this; me.setValue(combine(me, d, me.getValue())); me.fireEvent('select', me, d); me.collapse(); }, //Combinations getErrors: function(value) { var me = this, format = Ext.String.format, errors = me.callParent(arguments), minValue = me.minTime, maxValue = me.maxTime, date; value = me.formatDate(value || me.processRawValue(me.getRawValue())); if (value === null || value.length < 1) { // if it's blank and textfield didn't flag it then it's valid return errors; } date = me.parseDate(value); if (!date) { //avoid double format error return errors; } if (minValue && date < minValue) { errors.push(format(me.minText, me.formatDate(minValue))); } if (maxValue && date > maxValue) { errors.push(format(me.maxText, me.formatDate(maxValue))); } return errors; }, setValue: function() { var me = this, args = arguments, timeField = me.timeField; timeField.setValue.apply(timeField, arguments); return me.callParent(args); }, //Straight forwards setMaxTime: function() { var timeField = this.timeField; return timeField.setMaxValue.apply(timeField, arguments); }, setMinTime: function() { var timeField = this.timeField; return timeField.setMinValue.apply(timeField, arguments); } }); })();
-
13 Jun 2012 1:34 AM #6
I am just wondering if the extend and require is wrong?
Shouldn't it better be like this, to be analog to the naming conventions of EXT?
Code:Ext.define('Ext.ux.form.field.DateTimeField', { extend: 'Ext.form.field.Date', alias: 'widget.datetimefield', requires: ['Ext.form.field.Time'],
-
13 Jun 2012 1:44 AM #7
The aliases system makes both correct
Indeed, we should define these two aliases (any as the main name, the other as an alias) to be exact-sencha-like:
Ext.ux.form.field.DateTime
Ext.ux.form.DateTimeField


Reply With Quote