PDA

View Full Version : MonthPicker



JKralicky
6 Dec 2007, 2:21 PM
Hi folks,
I'm trying to implement a MonthPicker by extracting the month picking code out of the DatePicker. I'm also trying to make a MonthMenu like the DateMenu - that's my eventual goal. I've started with this code, but I'm running into problems left and right, so it's probably due to my lack of understanding of how to make extensions. Can anyone help please?!
Thanks so much!
Joe

** UPDATE **
I've got it working nicely on Firefox but I'm having some trouble on IE:
What I have is an icon on the screen that I launch the MonthMenu from.
The code here is updated and should work with Firefox. What happens with IE is:
1. the width of the menu never changes, and is too small. Whatever I try, I can't get the menu to fit the MonthPicker.
2. The first time opening the menu, the MonthPicker flashes then goes away leaving a white blank menu (which is to narrow - see #1).

** Update #2 **
I've got it working on both Firefox and IE. Enjoy!


Here's the code I have so far:



Ext.namespace('Ext.ux');

/**
* @class Ext.ux.MonthPicker
* @extends Ext.Component
* A picker that allows you to select a month and year
* @constructor
* @param {Object} config Configuration options
* @author Joseph Kralicky
* @version 0.1
*/




Ext.ux.MonthPicker = Ext.extend(Ext.Component, {

format : "M, Y",

okText : " OK ",

cancelText : "Cancel",

constrainToViewport : true,

monthNames : Date.monthNames,

startDay : 0,

value : 0,

noPastYears: true, // only use the current year and future years

initComponent: function(){
Ext.ux.MonthPicker.superclass.initComponent.call(this);

this.value = this.value ?
this.value.clearTime() : new Date().clearTime();

this.addEvents(

'select'
);

if(this.handler){
this.on("select", this.handler, this.scope || this);
}
},

focus : function(){
if(this.el){
this.update(this.activeDate);
}
},

onRender : function(container, position){
var m = [ '<div style="width: 175px; height:175px;"></div>' ]
m[m.length] = '<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.monthPicker = this.el.down('div.x-date-mp');
this.monthPicker.enableDisplayMode('block');

this.el.unselectable();

this.showMonthPicker();

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

this.update(this.value);

},

createMonthPicker : function(){
if(!this.monthPicker.dom.firstChild){
var buf = ['<table border="0" cellspacing="0">'];
for(var i = 0; i < 6; i++){
buf.push(
'<tr><td class="x-date-mp-month"><a href="#">', this.monthNames[i].substr(0, 3), '</a></td>',
'<td class="x-date-mp-month x-date-mp-sep"><a href="#">', this.monthNames[i+6].substr(0, 3), '</a></td>',
i == 0 ?
'<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
'<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
);
}
buf.push(
'<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
this.okText,
'</button><button type="button" class="x-date-mp-cancel">',
this.cancelText,
'</button></td></tr>',
'</table>'
);
this.monthPicker.update(buf.join(''));
this.monthPicker.on('click', this.onMonthClick, this);
this.monthPicker.on('dblclick', this.onMonthDblClick, this);

this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
this.mpYears = this.monthPicker.select('td.x-date-mp-year');

this.mpMonths.each(function(m, a, i){
i += 1;
if((i%2) == 0){
m.dom.xmonth = 5 + Math.round(i * .5);
}else{
m.dom.xmonth = Math.round((i-1) * .5);
}
});
}
},

showMonthPicker : function(){
this.createMonthPicker();
var size = this.el.getSize();
this.monthPicker.setSize(size);
this.monthPicker.child('table').setSize(size);

this.mpSelMonth = (this.activeDate || this.value).getMonth();
this.updateMPMonth(this.mpSelMonth);
this.mpSelYear = (this.activeDate || this.value).getFullYear();
this.updateMPYear(this.mpSelYear);

this.monthPicker.show();
//this.monthPicker.slideIn('t', {duration:.2});
},

updateMPYear : function(y){

if ( this.noPastYears ) {
var minYear = new Date().getFullYear();
if ( y < (minYear+4) ) {
y = minYear+4;
}
}

this.mpyear = y;
var ys = this.mpYears.elements;
for(var i = 1; i <= 10; i++){
var td = ys[i-1], y2;
if((i%2) == 0){
y2 = y + Math.round(i * .5);
td.firstChild.innerHTML = y2;
td.xyear = y2;
}else{
y2 = y - (5-Math.round(i * .5));
td.firstChild.innerHTML = y2;
td.xyear = y2;
}
this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
}
},

updateMPMonth : function(sm){
this.mpMonths.each(function(m, a, i){
m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
});
},

selectMPMonth: function(m){

},

onMonthClick : function(e, t){
e.stopEvent();
var el = new Ext.Element(t), pn;
if(el.is('button.x-date-mp-cancel')){
this.hideMonthPicker();
//this.fireEvent("select", this, this.value);
}
else if(el.is('button.x-date-mp-ok')){
this.update(new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
//this.hideMonthPicker();
this.fireEvent("select", this, this.value);
}
else if(pn = el.up('td.x-date-mp-month', 2)){
this.mpMonths.removeClass('x-date-mp-sel');
pn.addClass('x-date-mp-sel');
this.mpSelMonth = pn.dom.xmonth;
}
else if(pn = el.up('td.x-date-mp-year', 2)){
this.mpYears.removeClass('x-date-mp-sel');
pn.addClass('x-date-mp-sel');
this.mpSelYear = pn.dom.xyear;
}
else if(el.is('a.x-date-mp-prev')){
this.updateMPYear(this.mpyear-10);
}
else if(el.is('a.x-date-mp-next')){
this.updateMPYear(this.mpyear+10);
}
},

onMonthDblClick : function(e, t){
e.stopEvent();
var el = new Ext.Element(t), pn;
if(pn = el.up('td.x-date-mp-month', 2)){
this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
//this.hideMonthPicker();
this.fireEvent("select", this, this.value);
}
else if(pn = el.up('td.x-date-mp-year', 2)){
this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
//this.hideMonthPicker();
this.fireEvent("select", this, this.value);
}
},

hideMonthPicker : function(disableAnim){
Ext.menu.MenuMgr.hideAll();
},


showPrevMonth : function(e){
this.update(this.activeDate.add("mo", -1));
},


showNextMonth : function(e){
this.update(this.activeDate.add("mo", 1));
},


showPrevYear : function(){
this.update(this.activeDate.add("y", -1));
},


showNextYear : function(){
this.update(this.activeDate.add("y", 1));
},

update : function( date ) {
this.activeDate = date;
this.value = date;

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;

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]);
}
}
}

});

Ext.reg('monthpicker', Ext.ux.MonthPicker);

Ext.ux.MonthItem = function(config){
Ext.ux.MonthItem.superclass.constructor.call(this, new Ext.ux.MonthPicker(config), config);

this.picker = this.component;
this.addEvents('select');

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(Ext.ux.MonthItem, Ext.menu.Adapter, {
onSelect : function(picker, date){
this.fireEvent("select", this, date, picker);
Ext.ux.MonthItem.superclass.handleClick.call(this);
}
});

Ext.ux.MonthMenu = function(config){
Ext.ux.MonthMenu.superclass.constructor.call(this, config);
this.plain = true;
var mi = new Ext.ux.MonthItem(config);
this.add(mi);

this.picker = mi.picker;

this.relayEvents(mi, ["select"]);
};

Ext.extend(Ext.ux.MonthMenu, Ext.menu.Menu, {
cls:'x-date-menu'
});

JKralicky
10 Dec 2007, 7:18 AM
I updated the code which now works on Firefox but not IE. See the updated post above.
Thanks for any help!

Joe

JKralicky
11 Dec 2007, 9:33 AM
Hi folks,
I've got the MonthPicker working on IE and Firefox now! Enjoy and let me know if it works for you (or not)!
See the first post for the file.

Thanks!
Joe

ElliotS
11 Dec 2007, 8:05 PM
Brilliant! You rock! I needed this for a credit card expiry field.

JKralicky
12 Dec 2007, 6:54 AM
Thanks! Glad you found it useful.

Thanks also (mostly) go to the Ext team for writing this great framework!

shenliu
17 Dec 2007, 5:57 AM
how to use it? thanks

JKralicky
18 Dec 2007, 6:04 AM
Hi Shenliu,

If you want to use this as a menu item, use MonthMenu like DateMenu. If you want to use it as a standalone component, use MonthPicker like DatePicker. See the Ext 2.0 Documentation (http://extjs.com/deploy/dev/docs/) for how to use DateMenu and DatePicker.
Also, for my own purposes, I added a configuration item: "noPastYears = true" which does not show years in the past by default. You can set this to false if you want to be able to select years past.

Good luck!
Joe

shenliu
19 Dec 2007, 4:57 AM
thank you JKralicky! you are nice. i will try..

vtswingkid
19 Dec 2007, 7:39 AM
Thanks a bunch I am using this as a menu item.

Post this in the user extension!

Rob.

cariad
4 Jan 2008, 3:32 AM
Thanks for this nice extension!

I've tried it with Ext 1.1 and it works with just one mod: remove the following line:

Ext.reg('monthpicker', Ext.ux.MonthPicker);

Actually, I've made some further extensions to it, and added a MonthField based on DateField. One new config attribute has been added (useDayDate), that allows you to specify a specific day of the month that should be used to construct the resulting Date().
Set this to null to keep the old functionality.
If this value is set to 31 and the selected month only has 28 days, the minimum value will be used.

Example usage:
new Ext.ux.MonthMenu({
handler : function(dp, date){
alert(date.format('M j, Y'));
}
});
new Ext.ux.MonthField({
format : 'Y-m-d',
useDayDate : 31
});

Extension:
Ext.namespace('Ext.ux');

/**
* @class Ext.ux.MonthPicker
* @extends Ext.Component
* A picker that allows you to select a month and year
* @constructor
* @param {Object} config Configuration options
* @author Joseph Kralicky
* @version 0.1
*/




Ext.ux.MonthPicker = Ext.extend(Ext.Component, {

format : "M, Y",
okText : Ext.MessageBox.buttonText.ok,
cancelText : Ext.MessageBox.buttonText.cancel,
constrainToViewport : true,
monthNames : Date.monthNames,
value : 0,
noPastYears : true, // only use the current year and future years
useDayDate : null, // set to a number between 1-31 to use this day when creating the resulting date object (or null to use todays date or keep existing)

initComponent: function(){
Ext.ux.MonthPicker.superclass.initComponent.call(this);

this.value = this.value ?
this.value.clearTime() : new Date().clearTime();

this.addEvents(
'select'
);

if(this.handler){
this.on("select", this.handler, this.scope || this);
}
},

focus : function(){
if(this.el){
this.update(this.activeDate);
}
},

onRender : function(container, position){
var m = [ '<div style="width: 175px; height:175px;"></div>' ]
m[m.length] = '<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.monthPicker = this.el.down('div.x-date-mp');
this.monthPicker.enableDisplayMode('block');

this.el.unselectable();

this.showMonthPicker();

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

this.update(this.value);

},

createMonthPicker : function(){
if(!this.monthPicker.dom.firstChild){
var buf = ['<table border="0" cellspacing="0">'];
for(var i = 0; i < 6; i++){
buf.push(
'<tr><td class="x-date-mp-month"><a href="#">', this.monthNames[i].substr(0, 3), '</a></td>',
'<td class="x-date-mp-month x-date-mp-sep"><a href="#">', this.monthNames[i+6].substr(0, 3), '</a></td>',
i == 0 ?
'<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
'<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
);
}
buf.push(
'<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
this.okText,
'</button><button type="button" class="x-date-mp-cancel">',
this.cancelText,
'</button></td></tr>',
'</table>'
);
this.monthPicker.update(buf.join(''));
this.monthPicker.on('click', this.onMonthClick, this);
this.monthPicker.on('dblclick', this.onMonthDblClick, this);

this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
this.mpYears = this.monthPicker.select('td.x-date-mp-year');

this.mpMonths.each(function(m, a, i){
i += 1;
if((i%2) == 0){
m.dom.xmonth = 5 + Math.round(i * .5);
}else{
m.dom.xmonth = Math.round((i-1) * .5);
}
});
}
},

showMonthPicker : function(){
this.createMonthPicker();
var size = this.el.getSize();
this.monthPicker.setSize(size);
this.monthPicker.child('table').setSize(size);

this.mpSelMonth = (this.activeDate || this.value).getMonth();
this.updateMPMonth(this.mpSelMonth);
this.mpSelYear = (this.activeDate || this.value).getFullYear();
this.updateMPYear(this.mpSelYear);

this.monthPicker.show();
//this.monthPicker.slideIn('t', {duration:.2});
},

updateMPYear : function(y){

if ( this.noPastYears ) {
var minYear = new Date().getFullYear();
if ( y < (minYear+4) ) {
y = minYear+4;
}
}

this.mpyear = y;
var ys = this.mpYears.elements;
for(var i = 1; i <= 10; i++){
var td = ys[i-1], y2;
if((i%2) == 0){
y2 = y + Math.round(i * .5);
td.firstChild.innerHTML = y2;
td.xyear = y2;
}else{
y2 = y - (5-Math.round(i * .5));
td.firstChild.innerHTML = y2;
td.xyear = y2;
}
this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
}
},

updateMPMonth : function(sm){
this.mpMonths.each(function(m, a, i){
m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
});
},

selectMPMonth: function(m){

},

getAdjustedDate : function (year,month){
return new Date(
year,
month,
this.useDayDate ? // use a specific day date?
(Math.min(this.useDayDate, (new Date(year, month, 1)).getDaysInMonth())) // yes, cap it to month max
:
(this.activeDate || this.value).getDate() // keep existing
);
},

onMonthClick : function(e, t){
e.stopEvent();
var el = new Ext.Element(t), pn;
if(el.is('button.x-date-mp-cancel')){
this.hideMonthPicker();
//this.fireEvent("select", this, this.value);
}
else if(el.is('button.x-date-mp-ok')){
this.update(this.getAdjustedDate(this.mpSelYear, this.mpSelMonth));
//this.hideMonthPicker();
this.fireEvent("select", this, this.value);
}
else if(pn = el.up('td.x-date-mp-month', 2)){
this.mpMonths.removeClass('x-date-mp-sel');
pn.addClass('x-date-mp-sel');
this.mpSelMonth = pn.dom.xmonth;
}
else if(pn = el.up('td.x-date-mp-year', 2)){
this.mpYears.removeClass('x-date-mp-sel');
pn.addClass('x-date-mp-sel');
this.mpSelYear = pn.dom.xyear;
}
else if(el.is('a.x-date-mp-prev')){
this.updateMPYear(this.mpyear-10);
}
else if(el.is('a.x-date-mp-next')){
this.updateMPYear(this.mpyear+10);
}
},

onMonthDblClick : function(e, t){
e.stopEvent();
var el = new Ext.Element(t), pn;
if(pn = el.up('td.x-date-mp-month', 2)){
this.update(this.getAdjustedDate(this.mpSelYear, pn.dom.xmonth));
//this.hideMonthPicker();
this.fireEvent("select", this, this.value);
}
else if(pn = el.up('td.x-date-mp-year', 2)){
this.update(this.getAdjustedDate(pn.dom.xyear, this.mpSelMonth));
//this.hideMonthPicker();
this.fireEvent("select", this, this.value);
}
},

hideMonthPicker : function(disableAnim){
Ext.menu.MenuMgr.hideAll();
},


showPrevMonth : function(e){
this.update(this.activeDate.add("mo", -1));
},


showNextMonth : function(e){
this.update(this.activeDate.add("mo", 1));
},


showPrevYear : function(){
this.update(this.activeDate.add("y", -1));
},


showNextYear : function(){
this.update(this.activeDate.add("y", 1));
},

update : function( date ) {
this.activeDate = date;
this.value = date;

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;

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]);
}
}
},

setValue : function( date ) {
this.activeDate = date;
this.value = date;
}

});

//Ext.reg('monthpicker', Ext.ux.MonthPicker);

Ext.ux.MonthItem = function(config){
Ext.ux.MonthItem.superclass.constructor.call(this, new Ext.ux.MonthPicker(config), config);

this.picker = this.component;
this.addEvents('select');

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(Ext.ux.MonthItem, Ext.menu.Adapter, {
onSelect : function(picker, date){
this.fireEvent("select", this, date, picker);
Ext.ux.MonthItem.superclass.handleClick.call(this);
}
});

Ext.ux.MonthMenu = function(config){
Ext.ux.MonthMenu.superclass.constructor.call(this, config);
this.plain = true;
var mi = new Ext.ux.MonthItem(config);
this.add(mi);

this.picker = mi.picker;

this.relayEvents(mi, ["select"]);
};

Ext.extend(Ext.ux.MonthMenu, Ext.menu.Menu, {
cls:'x-date-menu'
});

Ext.ux.MonthField = function(config){
Ext.ux.MonthField.superclass.constructor.call(this, config);
}

Ext.extend(Ext.ux.MonthField, Ext.form.DateField, {
format : Ext.ux.MonthPicker.prototype.format,
noPastYears: Ext.ux.MonthPicker.prototype.noPastYears,
useDayDate: Ext.ux.MonthPicker.prototype.useDayDate,
onTriggerClick : function(){
if(this.disabled){
return;
}
if(this.menu == null){
this.menu = new Ext.ux.MonthMenu();
}
Ext.apply(this.menu.picker, {
format : this.format,
noPastYears : this.noPastYears,
useDayDate : this.useDayDate
});
this.menu.on(Ext.apply({}, this.menuListeners, {
scope:this
}));
this.menu.picker.setValue(this.getValue() || new Date());
this.menu.show(this.el, "tl-bl?");
}
});

BlackTheMad
12 Mar 2008, 10:03 AM
That's great extension.
But i got one trouble with it.
When i create several monthFields, they all show the same menu.
field.getValue() gives me different values, but menu is the same.
It should redraw, or something =)
Probably, there is a quick workaround?

Ext 2.0.2, cariad's edition of monthField.

vizcano
30 Apr 2008, 6:33 AM
Hi!

I'm trying to use this extension and what I get is what is shown in the screenshot attached, I can see the monthpicker but it's not collapsible and I'd like it to be collapsible, like a DataField, and I do not know how to do it, has anyone an example to show me?

luisparada
6 Jun 2008, 7:08 AM
Can you please post the final version without bugs?
I need to use this class but in your first post it says is not working on ie. but in firefox is working properly, so please can you upload the final version ?
thanks-

JKralicky
6 Jun 2008, 8:42 AM
The version in my post works in both browsers - see "Update #2" in the first post. You can use my code or the one updated by Cariad in post #10.

Joe


Can you please post the final version without bugs?
I need to use this class but in your first post it says is not working on ie. but in firefox is working properly, so please can you upload the final version ?
thanks-

galdaka
6 Jun 2008, 5:15 PM
Live example or screenshots please!!!

Thanks in advance,

bishoco
31 Jul 2008, 3:36 PM
I have been using this extension for a while and discovered a really strange bug. When selecting a month that doesn't have a 31st day, on the 31st, it won't let you select that month.

For example, today is 7/31/2008. Using monthpicker I try to select June 2008 and hit okay. The field now says 06/2008. When field loses focus, the date turns into 07/2008. I even set the useDayDate to 01 and it is doing this. If try to set any month that doesn't have 31 days, February, April, etc. it does the same thing. For months with 31 days, it works correctly.

I'm guessing that somewhere it is checking if it is a valid date, and when it does, it uses the current date for the day and it breaks. I'm not sure where that happens in the code, though.

zentropy
27 Aug 2008, 1:19 PM
Hi,

I am using Cariad's second version of this nifty MonthField. Thanks for posting the code!

I have a question and an issue:

1) I want to make the text input portion read-only, but not disabled (i.e. not grayed-out), and also that the user is still able to (forced to) click the attached button and pop open the month picker. (See #1 below in red)

2) I can't seem to properly register a "click" event handler for the OK button on the picker popup. (See #2 below in red)

Here is my code:



// in the .html
<span id="curMonthDiv">&nbsp;</span>


// in the .js
myApp.app = function() {
var monthPicker = null;

return {
init: function() {

monthPicker = new Ext.ux.MonthField({
format: 'M, Y',
useDayDate: 1,
noPastYears: true,
renderTo: 'curMonthDiv',
monthNames: [ /* month names... */ ]
});
// #1: This works, but still turns the text input gray/doesn't look good
monthPicker.el.dom.readOnly = true;

// add listener for when the OK button is clicked (go to new month)
// #2: doesn't work
monthPicker.on("select", function(picker, selDate) {
// go to the new month - contact server...
// When I select the month and hit the OK btn, this code is not reached
});

monthPicker.setValue(new Date()); // today
} // end init()
}; // end return
}(); // end myApp.app



Your help is greatly appreciated! Thanks in advance!

-Frank

rednix
27 Aug 2008, 2:15 PM
For 1) have a look at the Ext.ux.FieldReadOnlyPlugin (http://extjs.com/forum/showthread.php?t=40842) - this might do the trick.

I'm using a slightly customized version of Cariad's one - but not in combination with a field. I'm just using a button and attach a MonthMenu on it. The MonthMenu has a handler attached passing newValue and oldValue and doing some further actions when the value has been changed. The button has a handler on the menushow listener which ensures that the passed text of the button is selected in the MonthMenu. So the selected date is shown in the button's text label (so I don't need to tackle with "read-only" and styling - its just fine by default).
I don't know if you need a field for your case. If you just need a function to execute after the user has changed the date - the button/menu combination might be an option for you as well.

I vaguely remember that while customizing the MonthMenu it was somewhat tricky to catch the "changed date event". I started with the field variant and ended with the mentioned button/menu solution.

If you are further interested in my approach I will try to post some more details on it. Just let me know.

Regards,
rednix

zentropy
27 Aug 2008, 4:40 PM
The button with the attached month picker menu sounds fabulous. Can you please post more details? Yes, as you suspected, the text field is simply used to display the current month and year, and nothing more.

Best,

-Frank

rednix
28 Aug 2008, 6:43 AM
Ok - I set up a drop-in example (just extract the folder in the archive to your <ext-root>/examples folder). It includes my further enhanced version 0.2 of Ext.ux.MonthPicker.
It's currently not tested extensively so feel free to report bugs.

http://img155.imageshack.us/img155/7442/extuxmonthpickerv02hd7.png

bharatsehgal
11 Nov 2008, 9:18 PM
zipped files are corrupt.

rednix
12 Nov 2008, 1:13 PM
~100 peeps before you complained not.
I tried it again using Firefox 3 and everything was OK.

If you are using Internet Explorer - try Condor's second suggestion noted in this thread (http://extjs.com/forum/showthread.php?t=51197).

johnkpaul
10 Dec 2008, 9:57 AM
Is anyone else finding that the "select" event is being fired three times when you click on "OK"?


var monthMenu = new Ext.ux.MonthMenu({
noPastYears:false,
id:"test",
shadow:"drop",
listeners:{"select":function(menu,val){console.log(val)}}
});
monthMenu.showAt([0,0]);

I get three lines in the console log when I click on "OK" Any Idea what I'm doing wrong?

g13013
17 Dec 2008, 3:22 AM
when we select a date and the field lose focus the value changes to Jan,1970 so i think it's the same bug that "@bishoco" posted, i tested and see that when we select a month that ahave 31 days the value is changed when blur!!

g13013
22 Dec 2008, 3:08 AM
i found a small bug that set a different value after blur the Monthfield, i corrected it by overriding the beforeBlur function by an empty one in the original DateField

Ext.extend(Ext.ux.MonthField, Ext.form.DateField, {
format : Ext.ux.MonthPicker.prototype.format,
noPastYears: Ext.ux.MonthPicker.prototype.noPastYears,
noPastMonths: Ext.ux.MonthPicker.prototype.noPastMonths,
useDayDate: Ext.ux.MonthPicker.prototype.useDayDate,

beforeBlur : Ext.emptyFn,

onTriggerClick : function(){
if(this.disabled){
return;
}
if(this.menu == null){
this.menu = new Ext.ux.MonthMenu();
}
Ext.apply(this.menu.picker, {
format : this.format,
noPastYears : this.noPastYears,
noPastMonths : this.noPastMonths,
useDayDate : this.useDayDate
});
this.menu.on(Ext.apply({}, this.menuListeners, {
scope:this
}));
this.menu.picker.setValue(this.getValue() || new Date());
this.menu.show(this.el, "tl-bl?");
}
});

jinrey
5 Jan 2009, 6:26 PM
THANKS

sekaijin
7 Jan 2009, 3:33 AM
Hi
I don't have seen your plugin and I've devolopped this
http://extjs.com/forum/showthread.php?t=51208

I'm think is same approche
Bye
JYT

sdrew
31 Mar 2009, 7:58 AM
I have same issue as below. Seems that when the control looses focus, the date is parsed and the 'useDayDate' is ignored. For example today on the 31 March trying to select Feb month results in the underlying date values set to 3-March. This happens whether you trigger the monthpicker widget or not, so its really the underlying datefield that needs to also handle the Y/M format and append the 'useDayDate'.

Any ideas how to fix?


I have been using this extension for a while and discovered a really strange bug. When selecting a month that doesn't have a 31st day, on the 31st, it won't let you select that month.

For example, today is 7/31/2008. Using monthpicker I try to select June 2008 and hit okay. The field now says 06/2008. When field loses focus, the date turns into 07/2008. I even set the useDayDate to 01 and it is doing this. If try to set any month that doesn't have 31 days, February, April, etc. it does the same thing. For months with 31 days, it works correctly.

I'm guessing that somewhere it is checking if it is a valid date, and when it does, it uses the current date for the day and it breaks. I'm not sure where that happens in the code, though.

achu_vlr
31 Mar 2009, 10:14 AM
Even i am facing the same issue mentioned by sdrew..
Any help would be appreciated..

though i have a workaround...i am using field.value instead of field.getValue() which gives me the selected month irrespective of the date.

puttefnasker
11 Jun 2009, 1:03 PM
Hi

I'm trying to upgrade to Extj JS 3.0 RC2 but the monthMenu now throws an error - "Ext.ux.MonthMenu is not a constructor". Firebug tells me it is on line 281 in the monthMenu.js file at this point


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

I have read that Ext JS 3.0 has made some changes to Ext.Menu as I have read in this post (http://extjs.com/forum/showthread.php?t=70352)
Could this affect the monthMenu extension?

Does anyone else have this problem or is it just me?

Thanks!

vtswingkid
8 Jul 2009, 5:54 AM
I am with you ... am looking into it now.

vtswingkid
10 Jul 2009, 8:34 AM
[3.x] version here.

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

keypoint
12 Jul 2009, 10:01 PM
Another way of doing this: http://extjs.com/forum/showthread.php?p=356860#post356860

johnkpaul
6 Aug 2009, 5:19 AM
The check for opera around line 266 is no longer necessary. It causes an error in Opera 9.64 and everything works perfectly once I remove those three lines.