-
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
- 34,107
- Vote Rating
- 453
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
-
30 May 2013 3:02 AM #8
Works well with 4.2.0 but unfortunately not with the 4.2.1
some fix?
thank you very much
-
30 May 2013 3:12 AM #9
For my part, I'm really sorry but, going in production right now, I don't plan to upgrade my ExtJs version soon (I'm indeed still at 4.1) even though I plan to do it ... later.
If some kind hacker find a solution, please publish it (note: cross-version upgrade are rarely complex logical bugs but just configuration changes, and I would have to re-analyse and re-discover the code like most other user)
-
10 Jun 2013 7:17 AM #10
It seems that the problem is in the trigger time of the field.
But unfortunately the resolution of the problem is far outside of my ability ...
Someone?
Thank you very much.


Reply With Quote