DateField & TimeField from ExtJs/Ext.net arsenal are two really useful controls for entering date/time into forms. However, one of my clients complained that these fields can sometime take too much time in filling out, e.g. when the Date to be entered was months/years behind or ahead of the current date. Moreover, if you fill a partial value in these fields (e.g. 2 for timefield), the fields do not validate, and clear out the content.

I was asked to ensure that the user should be able to use the Datefield calendar and the TimeField drop-down items in case he/she wanted to, but simultaneously, I should do something to speed up data entry, and allow these fields to accept partial values and automatically complete them with logical values.

So, I came up with a plugin each for DateField and TimeField which you can see in action below:

 

The plugins allow you to choose date/time for the corresponding fields normally. Plus they enable you to enter partial values like 1, 1 Apr etc. for DateField, and 2, 2p etc. for TimeField which are automatically converted into correct values for the corresponding field.

The DateField plugin uses current date for the filling out the date portions not specified directly (e.g. year in 1Apr).
However, Timefield fills the minutes with zeros  in case they are not specified (e.g. 2 gets converted to 2:00 am, but 2:5p gets converted to 2:05 pm).

I chose the above rules as dictated by the project requirements, for which these plugins were created. It should not be too difficult to tweak the rules according to your needs in case you want them to be different.

The complete source for the plugins is available in the attached file. I am also reproducing the plugin code below:

 

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }Ext.ns(‘Ext.ux’);
// Date Field Corrector
Ext.ux.DateFieldCorrector = function(config) {
Ext.apply(this, config);
};

Ext.extend(Ext.ux.DateFieldCorrector, Object, {
init: function(el) {
el.on(‘blur’, this.correctDate);
el.on(‘specialkey’, function(el, e) { if (e.keyCode == e.TAB) this.correctDate(el); }, this);
}, // end of function init

correctDate: function(el) {
if (el.isValid())
return;

var val = el.getRawValue();
var corrected;

if (typeof (val) == ‘date’) {
return;
}

val = !Ext.isEmpty(val) ? val.toString() : null;
if (val == null) {
corrected = ”;
}

var nums = val.match(/[0-9]+/g);
var alpha = val.match(/[a-zA-Z]+/);
var cur = new Date();

var d = nums && nums[0] ? nums[0] : cur.getDate();
var y = nums && nums[1] ? nums[1] : cur.getFullYear();
var m = alpha && alpha[0] ? alpha[0] : cur.format(‘M’);
var milli = Date.parse(d + ‘ ‘ + m + ‘ ‘ + y);
if (!isNaN(milli)) {
corrected = new Date(milli);
}
else {
corrected = new Date();
}

el.setValue(corrected);
}
});

// Time Field Corrector
Ext.ux.TimeFieldCorrector = function(config) {
Ext.apply(this, config);
};

Ext.extend(Ext.ux.TimeFieldCorrector, Object, {
init: function(el) {
var plugin = this;
plugin.lastText = ”;

el.on(‘render’, function(el) {
el.el.on(‘keypress’, function(e, t, o) {
if (!e.isSpecialKey()) {
var key = String.fromCharCode(e.keyCode);
plugin.lastText = t.value + key;
}
});
});
el.on(‘blur’, this.correctTime, this);
el.on(‘specialkey’, function(el, e) { if (e.keyCode == e.TAB) this.correctTime(el); }, this);
}, // end of function init

correctTime: function(el) {
var val = this.lastText;

if (Ext.isEmpty(val)) {
return;
} else {
val = val.toString();
}

var nums = val.match(/[0-9]+/g);
var alpha = val.match(/[a-zA-Z]+/);

var h = nums && nums[0] ? nums[0] : ’12’; if (h.length > 2) h = h.substring(0, 2);
var m = nums && nums[1] ? nums[1] : ’00’; if (m.length > 2) { m = m.substring(0, 2) } else { if (m.length == 1) m = ‘0’ + m };
var a = alpha && alpha[0] ? alpha[0].toLowerCase() : ‘am’;

if (a == ‘a’ || a == ‘p’) a = a + ‘m’;
if (a != ‘am’ && a != ‘pm’) a = ‘am’;

if (h > 12) {
h = h % 12;
a = ‘pm’;
}
if (m > 59) m = m % 60;

var time = h + ‘:’ + m + ‘ ‘ + a;
if (time.charAt(0) == ‘0’) {
time = time.substring(1);
}

el.setValue(time);
}
});{/syntaxhighlighter}