PDA

View Full Version : MonthPicker


JKralicky
12-06-2007, 05: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
12-10-2007, 10: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
12-11-2007, 12:33 PM
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
12-11-2007, 11:05 PM
Brilliant! You rock! I needed this for a credit card expiry field.

JKralicky
12-12-2007, 09:54 AM
Thanks! Glad you found it useful.

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

shenliu
12-17-2007, 08:57 AM
how to use it? thanks

JKralicky
12-18-2007, 09: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
12-19-2007, 07:57 AM
thank you JKralicky! you are nice. i will try..

vtswingkid
12-19-2007, 10:39 AM
Thanks a bunch I am using this as a menu item.

Post this in the user extension!

Rob.

cariad
01-04-2008, 06: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
03-12-2008, 02:03 PM
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
04-30-2008, 10: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
06-06-2008, 11: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
06-06-2008, 12:42 PM
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
06-06-2008, 09:15 PM
Live example or screenshots please!!!

Thanks in advance,

bishoco
07-31-2008, 07: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
08-27-2008, 05: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
08-27-2008, 06: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
08-27-2008, 08: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
08-28-2008, 10: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-12-2008, 12:18 AM
zipped files are corrupt.

rednix
11-12-2008, 04: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
12-10-2008, 12:57 PM
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
12-17-2008, 06: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
12-22-2008, 06: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
01-05-2009, 09:26 PM
THANKS

sekaijin
01-07-2009, 06: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
03-31-2009, 11: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
03-31-2009, 02:14 PM
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
06-11-2009, 05: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
07-08-2009, 09:54 AM
I am with you ... am looking into it now.

vtswingkid
07-10-2009, 12:34 PM
[3.x] version here.

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

keypoint
07-13-2009, 02:01 AM
Another way of doing this: http://extjs.com/forum/showthread.php?p=356860#post356860

johnkpaul
08-06-2009, 09: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.