PDA

View Full Version : Ext Datetime control



soreport
31 Dec 2007, 7:23 PM
Can select Date and time.

CSS


.minutecss{
padding:4px;
height:100%;
border-top: 1px solid #a3bad9;
background: #dfecfb url(../../resources//images/default/shared/glass-bg.gif) repeat-x left top;
}
.y-hour-middle,.y-hour-left,.y-hour-right {
font:bold 11px "sans serif", tahoma, verdana, helvetica;
overflow:hidden;
}

.y-hour-right, .y-hour-left {
width:18px;
}
.y-hour-right{
text-align:right;
}
.y-hour-middle {
padding-top:2px;
padding-bottom:2px;
color:#0000ff;
}
.y-hour-right a, .y-hour-left a{
display:block;
width:16px;
height:16px;
background-position: center;
background-repeat: no-repeat;
cursor:pointer;
}

.y-hour-right a {
background-image: url(images/arrowRight.gif);
margin-right:2px;
}
.y-hour-left a{
background-image: url(images/arrowLeft.gif);
margin-left:2px;
}
.y-minute-middle,.y-minute-left,.y-minute-right {
font:bold 11px "sans serif", tahoma, verdana, helvetica;
overflow:hidden;
}

.y-minute-right, .y-minute-left {
width:18px;
}
.y-minute-right{
text-align:right;
}
.y-minute-middle {
padding-top:2px;
padding-bottom:2px;
color:#0000ff;
}
.y-minute-right a, .y-minute-left a{
display:block;
width:16px;
height:16px;
background-position: center;
background-repeat: no-repeat;
cursor:pointer;
}

.y-minute-right a {
background-image: url(images/arrowRight.gif);
margin-right:2px;
}
.y-minute-left a{
background-image: url(images/arrowLeft.gif);
margin-left:2px;
}

JS



DatetimePicker = function(config){
DatetimePicker.superclass.constructor.call(this, config);
};

Ext.extend(DatetimePicker, Ext.DatePicker, {

selectToday : function(){
this.setValue(new Date().clearTime());
var val1 = this.value;
val1.setHours(this.theHours);
val1.setMinutes(this.theMinutes);
this.fireEvent("select", this, val1);
},
handleDateClick : function(e, t){
e.stopEvent();
if(t.dateValue && !Ext.fly(t.parentNode).hasClass("x-date-disabled")){
this.setValue(new Date(t.dateValue));
var val1 = this.value;
val1.setHours(this.theHours);
val1.setMinutes(this.theMinutes);
this.fireEvent("select", this, val1);
}
},
onRender : function(container, position){
var m = [
'<table cellspacing="0">',
'<tr><td colspan="3"><table cellspacing="0" width="100%"><tr><td class="x-date-left"><a href="#" title="', this.prevText ,'">*</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'">*</a></td></tr></table></td></tr>',
'<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'];
var dn = this.dayNames;
for(var i = 0; i < 7; i++){
var d = this.startDay+i;
if(d > 6){
d = d-7;
}
m.push("<th><span>", dn[d].substr(0,1), "</span></th>");
}
m[m.length] = "</tr></thead><tbody><tr>";
for(i = 0; i < 42; i++) {
if(i % 7 === 0 && i !== 0){
m[m.length] = "</tr><tr>";
}
m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
}

m[m.length] = '</tr></tbody></table></td></tr><tr><td class="minutecss"><table cellspacing="0" ><tr>';
m[m.length] = '<td class="y-hour-left"><a href="#" title="down"> </a></td><td class="y-hour-middle" align="center"></td><td class="y-hour-right"><a href="#" title="up"> </a></td>';
m[m.length] = '<td class="y-minute-left"><a href="#" title="down"> </a></td><td class="y-minute-middle" align="center"></td><td class="y-minute-right"><a href="#" title="up"> </a></td>';
m[m.length] = '</tr></table></td><td colspan="2" class="x-date-bottom" align="center"></td></tr></table><div class="x-date-mp"></div>';

var el = document.createElement("div");
el.className = "x-date-picker";
el.innerHTML = m.join("");

container.dom.insertBefore(el, position);

this.el = Ext.get(el);
this.eventEl = Ext.get(el.firstChild);

new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"), {
handler: this.showPrevMonth,
scope: this,
preventDefault:true,
stopDefault:true
});

new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"), {
handler: this.showNextMonth,
scope: this,
preventDefault:true,
stopDefault:true
});
new Ext.util.ClickRepeater(this.el.child("td.y-hour-left a"), {
handler: function(){
if(this.theHours>0){
this.theHours--;
this.theHours = this.theHours %24;
var txt = '';
if(this.theHours<10){
txt='0'+this.theHours;
}
else{
txt= this.theHours;
}
this.hourLabel.update(txt+'时');

}
}.createDelegate(this),
scope: this
});
new Ext.util.ClickRepeater(this.el.child("td.y-hour-right a"), {
handler: function(){
this.theHours++;
this.theHours = this.theHours % 24;
var txt = '';
if(this.theHours<10){
txt='0'+this.theHours;
}
else{
txt= this.theHours;
}
this.hourLabel.update(txt+'时');
}.createDelegate(this),
scope: this
});
new Ext.util.ClickRepeater(this.el.child("td.y-minute-left a"), {
handler: function(){
if(this.theMinutes>0){
this.theMinutes--;
this.theMinutes = this.theMinutes % 60;
var txt = '';
if(this.theMinutes<10){
txt='0'+this.theMinutes;
}
else{
txt= this.theMinutes;
}
this.minuteLabel.update(txt+'分');

}
}.createDelegate(this),
scope: this
});
new Ext.util.ClickRepeater(this.el.child("td.y-minute-right a"), {
handler: function(){
this.theMinutes++;
this.theMinutes = this.theMinutes % 60;
var txt = '';
if(this.theMinutes<10){
txt='0'+this.theMinutes;
}
else{
txt= this.theMinutes;
}
this.minuteLabel.update(txt+'分');
}.createDelegate(this),
scope: this
});

this.eventEl.on("mousewheel", this.handleMouseWheel, this);

this.monthPicker = this.el.down('div.x-date-mp');
this.monthPicker.enableDisplayMode('block');

var kn = new Ext.KeyNav(this.eventEl, {
"left" : function(e){
e.ctrlKey ?
this.showPrevMonth() :
this.update(this.activeDate.add("d", -1));
},

"right" : function(e){
e.ctrlKey ?
this.showNextMonth() :
this.update(this.activeDate.add("d", 1));
},

"up" : function(e){
e.ctrlKey ?
this.showNextYear() :
this.update(this.activeDate.add("d", -7));
},

"down" : function(e){
e.ctrlKey ?
this.showPrevYear() :
this.update(this.activeDate.add("d", 7));
},

"pageUp" : function(e){
this.showNextMonth();
},

"pageDown" : function(e){
this.showPrevMonth();
},

"enter" : function(e){
e.stopPropagation();
return true;
},

scope : this
});

this.eventEl.on("click", this.handleDateClick, this, {delegate: "a.x-date-date"});

this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday, this);

this.el.unselectable();

this.cells = this.el.select("table.x-date-inner tbody td");
this.textNodes = this.el.query("table.x-date-inner tbody span");

this.mbtn = new Ext.Button({
text: "*",
tooltip: this.monthYearText,
renderTo: this.el.child("td.x-date-middle", true)
});

this.mbtn.on('click', this.showMonthPicker, this);
this.mbtn.el.child(this.mbtn.menuClassTarget).addClass("x-btn-with-menu");

var dt1 = new Date();
var txt = '';
this.hourLabel = this.el.child("td.y-hour-middle");
this.theHours = dt1.getHours();
if(this.theHours<10){
txt='0'+this.theHours;
}
else{
txt= this.theHours;
}
this.hourLabel.update(txt+'时');

this.minuteLabel = this.el.child("td.y-minute-middle");
this.theMinutes = dt1.getMinutes();
if(this.theMinutes<10){
txt='0'+this.theMinutes;
}
else{
txt= this.theMinutes;
}
this.minuteLabel.update(txt+'分');

var today = (new Date()).dateFormat(this.format);
var todayBtn = new Ext.Button({
renderTo: this.el.child("td.x-date-bottom", true),
text: String.format(this.todayText, today),
tooltip: String.format(this.todayTip, today),
handler: this.selectToday,
scope: this
});

if(Ext.isIE){
this.el.repaint();
}
this.update(this.value);
},

/**
* Method Name: update
*/
update : function(date){
var vd = this.activeDate;
this.activeDate = date;
if(vd && this.el){
var t = date.getTime();
if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
this.cells.removeClass("x-date-selected");
this.cells.each(function(c){
if(c.dom.firstChild.dateValue == t){
c.addClass("x-date-selected");
setTimeout(function(){
try{c.dom.firstChild.focus();}catch(e){}
}, 50);
return false;
}
});
return;
}
}
var days = date.getDaysInMonth();
var firstOfMonth = date.getFirstDateOfMonth();
var startingPos = firstOfMonth.getDay()-this.startDay;

if(startingPos <= this.startDay){
startingPos += 7;
}

var pm = date.add("mo", -1);
var prevStart = pm.getDaysInMonth()-startingPos;

var cells = this.cells.elements;
var textEls = this.textNodes;
days += startingPos;

// convert everything to numbers so it's fast
var day = 86400000;
var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
var today = new Date().clearTime().getTime();
var sel = date.clearTime().getTime();
var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
var ddMatch = this.disabledDatesRE;
var ddText = this.disabledDatesText;
var ddays = this.disabledDays ? this.disabledDays.join("") : false;
var ddaysText = this.disabledDaysText;
var format = this.format;

var setCellClass = function(cal, cell){
cell.title = "";
var t = d.getTime();
cell.firstChild.dateValue = t;
if(t == today){
cell.className += " x-date-today";
cell.title = cal.todayText;
}
if(t == sel){
cell.className += " x-date-selected";
setTimeout(function(){
try{cell.firstChild.focus();}catch(e){}
}, 50);
}
// disabling
if(t < min) {
cell.className = " x-date-disabled";
cell.title = cal.minText;
return;
}
if(t > max) {
cell.className = " x-date-disabled";
cell.title = cal.maxText;
return;
}
if(ddays){
if(ddays.indexOf(d.getDay()) != -1){
cell.title = ddaysText;
cell.className = " x-date-disabled";
}
}
if(ddMatch && format){
var fvalue = d.dateFormat(format);
if(ddMatch.test(fvalue)){
cell.title = ddText.replace("%0", fvalue);
cell.className = " x-date-disabled";
}
}
};

var i = 0;
for(; i < startingPos; i++) {
textEls[i].innerHTML = (++prevStart);
d.setDate(d.getDate()+1);
cells[i].className = "x-date-prevday";
setCellClass(this, cells[i]);
}
for(; i < days; i++){
intDay = i - startingPos + 1;
textEls[i].innerHTML = (intDay);
d.setDate(d.getDate()+1);
cells[i].className = "x-date-active";
setCellClass(this, cells[i]);
}
var extraDays = 0;
for(; i < 42; i++) {
textEls[i].innerHTML = (++extraDays);
d.setDate(d.getDate()+1);
cells[i].className = "x-date-nextday";
setCellClass(this, cells[i]);
}

this.mbtn.setText(this.monthNames[date.getMonth()] + " " + date.getFullYear());

if(this.theHours<10){
txt='0'+this.theHours;
}
else{
txt= this.theHours;
}
this.hourLabel.update(txt+'时');

if(this.theMinutes<10){
txt='0'+this.theMinutes;
}
else{
txt= this.theMinutes;
}
this.minuteLabel.update(txt+'分');

if(!this.internalRender){
var main = this.el.dom.firstChild;
var w = main.offsetWidth;
this.el.setWidth(w + this.el.getBorderWidth("lr"));
Ext.fly(main).setWidth(w);
this.internalRender = true;
// opera does not respect the auto grow header center column
// then, after it gets a width opera refuses to recalculate
// without a second pass
if(Ext.isOpera && !this.secondPass){
main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";
this.secondPass = true;
this.update.defer(10, this, [date]);
}
}
},

/***** Public Instance Variables *****/

/**
* Variable Name: nextYearText, prevYearText
* Description: Hover text for the previous year and next year arrow changers
* Default: as shown
* Type: string
*/
nextYearText: 'Next Year (Control+Up)',
prevYearText: 'Previous Year (Control+Down)'
});


/** Class Name: DatetimeItem
* Inherits From: Ext.menu.Adapter
*/
DatetimeItem = function(config){
DatetimeItem.superclass.constructor.call(this, new DatetimePicker(config), config);
this.picker = this.component;
this.addEvents({select: true});

this.picker.on("render", function(picker){
picker.getEl().swallowEvent("click");
picker.container.addClass("x-menu-date-item");
});

this.picker.on("select", this.onSelect, this);
};

Ext.extend(DatetimeItem, Ext.menu.Adapter, {
onSelect : function(picker, date){
this.fireEvent("select", this, date, picker);
DatetimeItem.superclass.handleClick.call(this);
}
});


/** Class Name: DatetimeMenu
* Inherits From: Ext.menu.Menu
*/
DatetimeMenu = function(config){
DatetimeMenu.superclass.constructor.call(this, config);
this.plain = true;
var di = new DatetimeItem(config);
this.add(di);
this.picker = di.picker;
this.relayEvents(di, ["select"]);
};
Ext.extend(DatetimeMenu, Ext.menu.Menu);

examples:

new Ext.form.DateField({
fieldLabel: 'datetime',
name: 'begintime',
format:'Y-m-d H:i',
menu:new DatetimeMenu()
})

soreport
1 Jan 2008, 6:52 PM
no one reply,
ComboTree,ComboGrid,Resizable ColumnTree,seems no need to submit!!!:)

galdaka
1 Jan 2008, 9:58 PM
Hi,

Thanks. Aparently good work!! Is posible live demo?

Thanks in advance,

krycek
3 Jan 2008, 12:28 AM
soreport, have you created a ComboTree indeed?

I'm very interesting on this. Could you please post it?

and I'm definitely going to test the date time field.

Thank you for sharing.

alexey.smolyakov
12 Mar 2008, 12:15 PM
Good control!!

LedrickLeron
15 Mar 2008, 10:13 PM
This is not displaying correctly in Firefox (see first image attached)

Also in IE7 I have tried to change the background color to the xtheme-dark theme and I am still getting a blue background for the date selector (see second attachment)

Please help, I have done everything to your example:



...
}, new Ext.form.DateField({
fieldLabel: 'Start Date/Time',
name: 'beginTime',
format: 'Y-m-d H:i',
menu: new DatetimeMenu()
}), new Ext.form.DateField({
fieldLabel: 'End Date/Time',
name: 'endTime',
format: 'Y-m-d H:i',
menu: new DatetimeMenu()
})]





/* datetime css */
.minutecss{ padding:4px; height:100%; border-top: 1px solid #777777; background: #888888 url(../images/default/shared/glass-bg.gif) repeat-x left top; }.y-hour-middle,.y-hour-left,.y-hour-right { font:bold 11px "sans serif", tahoma, verdana, helvetica; overflow:hidden; }

.y-hour-right, .y-hour-left { width:18px; }
.y-hour-right{ text-align:right; }
.y-hour-middle { padding-top:2px; padding-bottom:2px; color:#0000ff; }
.y-hour-right a, .y-hour-left a{ display:block; width:16px; height:16px; background-position: center; background-repeat: no-repeat; cursor:pointer; }

.y-hour-right a { background-image: url(../images/arrowRight.gif); margin-right:2px; }
.y-hour-left a{ background-image: url(../images/arrowLeft.gif); margin-left:2px; }
.y-minute-middle,.y-minute-left,.y-minute-right { font:bold 11px "sans serif", tahoma, verdana, helvetica; overflow:hidden; }

.y-minute-right, .y-minute-left { width:18px; }
.y-minute-right{ text-align:right; }
.y-minute-middle { padding-top:2px; padding-bottom:2px; color:#0000ff; }
.y-minute-right a, .y-minute-left a{ display:block; width:16px; height:16px; background-position: center; background-repeat: no-repeat; cursor:pointer; }

.y-minute-right a { background-image: url(../images/arrowRight.gif); margin-right:2px; }
.y-minute-left a{ background-image: url(../images/arrowLeft.gif); margin-left:2px; }

fionn
20 May 2008, 5:14 AM
Thank you, this works very nice!

Although, in Firefox3 it does not display correctly at all. (unusable)

ChWild
10 Jun 2008, 1:13 AM
Hello, nice work.
That's exactly what i need. But i've a problem with the time.

Id the time is changed manually in the datefield, it's not shown correctly in the menu.
There is still shown the actuall or when already set in the menu the old time. The date is shown correctly :-?

Please help.

ChWild
17 Sep 2008, 4:30 AM
Hello,
has nobody any ideas? Is there a fix for FF3?

jdurrell
11 Dec 2008, 12:32 PM
Try adding:el.style.width = '10px';

It goes in onRender(), just after el.className = "x-date-picker".

ChWild
15 Dec 2008, 4:34 AM
Thank you very much. :)


Just any idea about the problem when time is changed in the DateField?

If the time is changed manually in the datefield, it's not shown correctly in the menu.
There is still shown the actuall or when already set in the menu the old time. The date is shown correctly :-?

jdurrell
15 Dec 2008, 4:44 AM
I've made a bunch of tweaks to the code, bug fixes as well as support to make the minutes field optional (i.e. just show whole hours). Somewhere in there, yes, I fixed the update problem. It's worked well for me since, but our QA person hasn't tested it yet so YMMV. :-)

The javascript:


DatetimePicker = function(config){
DatetimePicker.superclass.constructor.call(this, config);
};

Ext.extend(DatetimePicker, Ext.DatePicker, {

handleDateClick : function(e, t){
e.stopEvent();
if(t.dateValue && !Ext.fly(t.parentNode).hasClass("x-date-disabled")){
var newDate = new Date(t.dateValue);
newDate.setHours(this.theHours);
newDate.setMinutes(this.theMinutes);
this.setValue(newDate);
this.fireEvent("select", this, newDate);
}
},
focus : function() {
this.activeDate.setHours(this.theHours);
this.activeDate.setMinutes(this.theMinutes);
Ext.DatePicker.prototype.focus.call(this);
},
setValue: function(t) {
this.value = t;
this.updateTimeFields(this.value);
if (this.el) {
this.update(this.value);
}
},
setHours: function(hours) {
this.theHours = Math.max(Math.min(hours, 23), 0);
if (this.el) {
var txt = (this.theHours % 12 == 0 ? "12" : this.theHours % 12);
this.hourLabel.update(txt);
this.ampmLabel.update(this.theHours >= 12 ? "pm" : "am");
}
},
setMinutes: function(minutes) {
this.theMinutes = Math.max(Math.min(minutes, 59, 0));
if (this.el && this.showMinutes) {
var txt = (this.theMinutes < 10 ? '0'+this.theMinutes : this.theMinutes);
this.minuteLabel.update(txt);
}
},
onRender : function(container, position){
var m = [
'<table cellspacing="0">',
'<tr><td colspan="3"><table cellspacing="0" width="100%"><tr><td class="x-date-left"><a href="#" title="', this.prevText ,'">*</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'">*</a></td></tr></table></td></tr>',
'<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'];
var dn = this.dayNames;
for(var i = 0; i < 7; i++){
var d = this.startDay+i;
if(d > 6){
d = d-7;
}
m.push("<th><span>", dn[d].substr(0,1), "</span></th>");
}
m[m.length] = "</tr></thead><tbody><tr>";
for(i = 0; i < 42; i++) {
if(i % 7 === 0 && i !== 0){
m[m.length] = "</tr><tr>";
}
m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
}

m[m.length] = '</tr></tbody></table></td></tr><tr><td class="minutecss"><table cellspacing="0" ><tr>';
m[m.length] = '<td class="y-hour-left"><a href="#" title="down"> </a></td><td class="y-hour-middle" align="center"></td>';
if (!this.showMinutes) {
m[m.length] = '<td class="y-minute-middle">:00</td>';
m[m.length] = '<td class="y-ampm">am</td>';
}
m[m.length] = '<td class="y-hour-right"><a href="#" title="up"> </a></td>';
if (this.showMinutes) {
m[m.length] = '<td class="y-minute-left"><a href="#" title="down"> </a></td><td class="y-minute-middle" align="center"></td><td class="y-minute-right"><a href="#" title="up"> </a></td>';
m[m.length] = '<td class="y-ampm">am</td>';
}
m[m.length] = '</tr></table></td><td colspan="2" class="x-date-bottom" align="center"></td></tr></table><div class="x-date-mp"></div>';

var el = document.createElement("div");
el.className = "x-date-picker";
el.style.width = '10px';
el.innerHTML = m.join("");

container.dom.insertBefore(el, position);

this.el = Ext.get(el);
this.eventEl = Ext.get(el.firstChild);

new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"), {
handler: this.showPrevMonth,
scope: this,
preventDefault:true,
stopDefault:true
});

new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"), {
handler: this.showNextMonth,
scope: this,
preventDefault:true,
stopDefault:true
});
new Ext.util.ClickRepeater(this.el.child("td.y-hour-left a"), {
handler: function(){ this.setHours(--this.theHours); }.createDelegate(this),
scope: this
});
new Ext.util.ClickRepeater(this.el.child("td.y-hour-right a"), {
handler: function(){ this.setHours(++this.theHours); }.createDelegate(this),
scope: this
});
if (this.showMinutes) {
new Ext.util.ClickRepeater(this.el.child("td.y-minute-left a"), {
handler: function() { this.setMinutes(--this.theMinutes); }.createDelegate(this),
scope: this
});
new Ext.util.ClickRepeater(this.el.child("td.y-minute-right a"), {
handler: function() { this.setMinutes(++this.theMinutes); }.createDelegate(this),
scope: this
});
}

this.eventEl.on("mousewheel", this.handleMouseWheel, this);

this.monthPicker = this.el.down('div.x-date-mp');
this.monthPicker.enableDisplayMode('block');

var kn = new Ext.KeyNav(this.eventEl, {
"left" : function(e){
e.ctrlKey ?
this.showPrevMonth() :
this.update(this.activeDate.add("d", -1));
},

"right" : function(e){
e.ctrlKey ?
this.showNextMonth() :
this.update(this.activeDate.add("d", 1));
},

"up" : function(e){
e.ctrlKey ?
this.showNextYear() :
this.update(this.activeDate.add("d", -7));
},

"down" : function(e){
e.ctrlKey ?
this.showPrevYear() :
this.update(this.activeDate.add("d", 7));
},

"pageUp" : function(e){
this.showNextMonth();
},

"pageDown" : function(e){
this.showPrevMonth();
},

"enter" : function(e){
e.stopPropagation();
return true;
},

scope : this
});

this.eventEl.on("click", this.handleDateClick, this, {delegate: "a.x-date-date"});

this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday, this);

this.el.unselectable();

this.cells = this.el.select("table.x-date-inner tbody td");
this.textNodes = this.el.query("table.x-date-inner tbody span");

this.mbtn = new Ext.Button({
text: "*",
tooltip: this.monthYearText,
renderTo: this.el.child("td.x-date-middle", true)
});

this.mbtn.on('click', this.showMonthPicker, this);
this.mbtn.el.child(this.mbtn.menuClassTarget).addClass("x-btn-with-menu");

var dt1 = new Date();
this.ampmLabel = this.el.child("td.y-ampm");
this.hourLabel = this.el.child("td.y-hour-middle");
this.setHours(dt1.getHours());
this.minuteLabel = this.el.child("td.y-minute-middle");
this.setMinutes(dt1.getMinutes());

if(this.showToday){
this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday, this);
var today = (new Date()).dateFormat(this.format);
this.todayBtn = new Ext.Button({
renderTo: this.el.child("td.x-date-bottom", true),
text: String.format(this.todayText, today),
tooltip: String.format(this.todayTip, today),
handler: this.selectToday,
scope: this
});
}
if(Ext.isIE){
this.el.repaint();
}
this.update(this.value);
},
updateTimeFields: function(d) {
this.theHours = d.getHours();
this.theMinutes = d.getMinutes();
this.setHours(this.theHours);
this.setMinutes(this.theMinutes);
},
update: function(date, forceRefresh) {
// Copy maxDate because update munges the maxDate and its a shared reference
this.maxDate = new Date(this.maxDate.getTime());
var dateCopy = new Date(date.getTime());
dateCopy.clearTime();
Ext.DatePicker.prototype.update.call(this, dateCopy, forceRefresh);
},
showMinutes: true,
nextYearText: 'Next Year (Control+Up)',
prevYearText: 'Previous Year (Control+Down)'
});

DatetimeItem = function(config){
DatetimeItem.superclass.constructor.call(this, new DatetimePicker(config), config);
this.picker = this.component;
this.addEvents({select: true});
this.picker.on("render", function(picker){
picker.getEl().swallowEvent("click");
picker.container.addClass("x-menu-date-item");
});
this.picker.on("select", this.onSelect, this);
};

Ext.extend(DatetimeItem, Ext.menu.Adapter, {
onSelect : function(picker, date){
this.fireEvent("select", this, date, picker);
DatetimeItem.superclass.handleClick.call(this);
}
});


/** Class Name: DatetimeMenu
* Inherits From: Ext.menu.Menu
*/
DatetimeMenu = function(config){
DatetimeMenu.superclass.constructor.call(this, config);
this.plain = true;
var di = new DatetimeItem(config);
this.add(di);
this.picker = di.picker;
this.relayEvents(di, ["select"]);
};
Ext.extend(DatetimeMenu, Ext.menu.Menu);
The CSS:


.minutecss{
padding:4px;
height:100%;
border-top: 1px solid #a3bad9;
}
.y-hour-middle,.y-hour-left,.y-hour-right {
font:11px "sans serif", tahoma, verdana, helvetica;
overflow:hidden;
}
.y-hour-right, .y-hour-left {
width:18px;
}
.y-hour-right{
text-align:right;
}
.y-hour-middle {
padding-top:2px;
padding-bottom:2px;
color:#444;
}
.y-hour-right a, .y-hour-left a{
display:block;
width:16px;
height:16px;
background-position: center;
background-repeat: no-repeat;
cursor:pointer;
}
.y-hour-right a {
background-image: url("../images/up2.gif");
margin-right:2px;
margin-left:2px;
}
.y-hour-left a{
background-image: url("../images/down2.gif");
margin-left:2px;
margin-right:2px;
}
.y-minute-middle,.y-minute-left,.y-minute-right {
font:11px "sans serif", tahoma, verdana, helvetica;
overflow:hidden;
}
.y-minute-right, .y-minute-left {
width:18px;
}
.y-minute-right{
text-align:right;
}
.y-minute-middle {
padding-top:2px;
padding-bottom:2px;
color:#444;
}
.y-minute-right a, .y-minute-left a{
display:block;
width:16px;
height:16px;
background-position: center;
background-repeat: no-repeat;
cursor:pointer;
}
.y-minute-right a {
background-image: url("../images/right2.gif");
margin-right:2px;
}
.y-minute-left a{
background-image: url("../images/left2.gif");
margin-left:2px;
}


Cheers!

ChWild
17 Dec 2008, 6:36 AM
Well, looks good. :D Thank You.

I "mixed" your code with mine and it look's to work. Only the first time the menu is opened the time is not correct. But i'll try to fix it.

sukebegaptek
9 Jan 2009, 1:24 AM
how to use this plugin?
i'm newbie :"> please help... thx.

dearsina
31 Jan 2009, 5:26 AM
I personally found this datetime picker to be better/more flexible:

http://extjs.com/forum/showthread.php?t=22661

But if you're hell-bent on using the one in this thread, implement soreport's original code, then add the IE fix suggested by jdurrell and you're flying.