diff --git a/MonthPicker.js b/MonthPicker.js
index 47638f7..a3010ea 100644
--- a/MonthPicker.js
+++ b/MonthPicker.js
@@ -1,7 +1,7 @@
/*
https://github.com/KidSysco/jquery-ui-month-picker/
-Version 2.7
+Version 2.8
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -23,7 +23,7 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
// to perform this test for every MonthPicker instance being created.
if (!$ || !$.ui || !$.ui.button || !$.ui.datepicker) {
alert(_setupErr + 'The jQuery UI button and datepicker plug-ins must be loaded.');
- return false;
+ return;
}
var _speeds = $.fx.speeds;
@@ -51,9 +51,12 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
Button: '_updateButton',
ShowOn: '_updateFieldEvents',
IsRTL: '_setRTL',
+ AltFormat: '_updateAlt',
+ AltField: '_updateAlt',
StartYear: '_setPickerYear',
MinMonth: '_setMinMonth',
- MaxMonth: '_setMaxMonth'
+ MaxMonth: '_setMaxMonth',
+ SelectedMonth: '_setSelectedMonth'
};
var $noop = $.noop;
var $proxy = $.proxy;
@@ -146,8 +149,12 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
});
}
+ function _isInline(elem) {
+ return !elem.is('input');
+ }
+
$.MonthPicker = {
- VERSION: 2.7, // Added in version 2.4;
+ VERSION: 2.8, // Added in version 2.4;
i18n: {
year: "Year",
prevYear: "Previous Year",
@@ -279,7 +286,7 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
// TLDR:
// http://www.w3.org/TR/html5/forms.html#the-input-element
// https://api.jquery.com/text-selector/
- if (!_el.is('input') || ['text', 'month', void 0].indexOf(_el.attr('type')) === -1) {
+ if (!_el.is('input,div,span') || ['text', 'month', void 0].indexOf(_el.attr('type')) === -1) {
var error = _setupErr + 'MonthPicker can only be called on text or month inputs.';
// Call alert first so that IE<10 won't trip over console.log and swallow all errors.
alert(error + ' \n\nSee (developer tools) for more details.');
@@ -315,10 +322,11 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
_el.addClass('month-year-input');
- var _menu = this._monthPickerMenu = $('
');
+ var _menu = this._monthPickerMenu = $('');
+ var isInline = _isInline(_el);
$(_markup).appendTo(_menu);
- $('body').append(_menu);
+ (_menu).appendTo( isInline ? _el : document.body );
$('.year-title', _menu).text(this._i18n('year'));
@@ -336,8 +344,9 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
this._setRTL(_opts.IsRTL); //Assigns icons to the next/prev buttons.
- $('.ui-button-icon-primary', this._nextButton).text(this._i18n('nextLabel'));
- $('.ui-button-icon-primary', this._prevButton).text(this._i18n('prevLabel'));
+ var _iconClass = '.ui-button-icon-primary';
+ $(_iconClass, this._nextButton).text(this._i18n('nextLabel'));
+ $(_iconClass, this._prevButton).text(this._i18n('prevLabel'));
var $table = $('.month-picker-month-table', _menu);
for (var i = 0; i < 12; i++) {
@@ -364,16 +373,26 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
me._setOption(type + Month, me.options[type + Month]);
});
+ var _selMonth = _opts.SelectedMonth;
+ if (_selMonth !== void 0) {
+ var month = _encodeMonth(this, _selMonth);
+ _el.val( this._formatMonth(new Date( _toYear(month), month % 12, 1)) );
+ }
+
+ this._updateAlt();
+
this._setUseInputMask();
this._setDisabledState();
this._updateFieldEvents();
this.Destroy = this.destroy;
- },
-
- /****** Misc. Utility functions ******/
-
- _i18n: function(str) {
- return this.options.i18n[str] || $.MonthPicker.i18n[str];
+
+ if (isInline) {
+ this.Open();
+ } else {
+ // Update the alt field if the user manually changes
+ // the input field.
+ _el.change($proxy(this._updateAlt, this));
+ }
},
/****** Publicly Accessible API functions ******/
@@ -433,11 +452,10 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
},
Open: function (event) {
- if (!this.options.Disabled && !this._visible) {
- var _elem = this.element, _opts = this.options;
-
+ var _elem = this.element, _opts = this.options;
+ if (!_opts.Disabled && !this._visible) {
// Allow the user to prevent opening the menu.
- event = event || new $.Event();
+ event = event || $.Event();
if (_event('OnBeforeMenuOpen', this)(event) === false || event.isDefaultPrevented()) {
return false;
}
@@ -445,47 +463,53 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
this._visible = true;
this._ajustYear(_opts);
- // If there is an open menu close it first.
- if (_openedInstance) {
- _openedInstance.Close(event);
- }
-
- _openedInstance = this;
var _menu = this._monthPickerMenu;
this._showMonths();
-
- $(document).on(click + this.uuid, $proxy(this.Close, this))
- .on('keydown' + _eventsNs + this.uuid, $proxy(this._keyDown, this));
-
- // Trun off validation so that clicking one of the months
- // won't blur the input field and trogger vlaidation
- // befroe the month was chosen (click event was triggered).
- // It is turned back on when Hide() is called.
- _elem.off('blur' + _eventsNs).focus();
-
- var _anim = _opts.ShowAnim || _opts.Animation,
- _noAnim = _anim === 'none';
-
- // jQuery UI overrides jQuery.show and dosen't
- // call the start callback.
- // see: http://api.jqueryui.com/show/
- _menu[ _noAnim ? 'fadeIn' : _anim ]({
- duration: _noAnim ? 0 : this._duration(),
- start: $proxy(this._position, this, _menu),
- complete: _event('OnAfterMenuOpen', this)
- });
+
+ if (_isInline(_elem)) {
+ _menu.css('position', 'static').show();
+ _event('OnAfterMenuOpen', this)();
+ } else {
+ // If there is an open menu close it first.
+ if (_openedInstance) {
+ _openedInstance.Close(event);
+ }
+
+ _openedInstance = this;
+
+ $(document).on(click + this.uuid, $proxy(this.Close, this))
+ .on('keydown' + _eventsNs + this.uuid, $proxy(this._keyDown, this));
+
+ // Trun off validation so that clicking one of the months
+ // won't blur the input field and trogger vlaidation
+ // befroe the month was chosen (click event was triggered).
+ // It is turned back on when Hide() is called.
+ _elem.off('blur' + _eventsNs).focus();
+
+ var _anim = _opts.ShowAnim || _opts.Animation,
+ _noAnim = _anim === 'none';
+
+ // jQuery UI overrides jQuery.show and dosen't
+ // call the start callback.
+ // see: http://api.jqueryui.com/show/
+ _menu[ _noAnim ? 'fadeIn' : _anim ]({
+ duration: _noAnim ? 0 : this._duration(),
+ start: $proxy(this._position, this, _menu),
+ complete: _event('OnAfterMenuOpen', this)
+ });
+ }
}
return false;
},
Close: function (event) {
- if (this._visible) {
+ var _elem = this.element;
+ if (!_isInline(_elem) && this._visible) {
var _menu = this._monthPickerMenu,
- _opts = this.options,
- _elem = this.element;
+ _opts = this.options;
- event = event || new $.Event();
+ event = event || $.Event();
if (_event('OnBeforeMenuClose', this)(event) === false || event.isDefaultPrevented()) {
return;
}
@@ -530,14 +554,31 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
}
},
- /****** Private functions ******/
+ /****** Private and Misc Utility functions ******/
+
+ _setSelectedMonth: function (_selMonth) {
+ var month = _encodeMonth(this, _selMonth), _el = this.element;
+
+ if (!month) {
+ _el.val( '' );
+ } else {
+ _el.val( this._formatMonth( new Date( _toYear(month), month % 12, 1)) );
+ }
+
+ this._ajustYear(this.options);
+ this._showMonths();
+ },
- _parseMonth: function (str) {
- return this.ParseMonth(str || this.element.val(), this.options.MonthFormat);
+ _i18n: function(str) {
+ return this.options.i18n[str] || $.MonthPicker.i18n[str];
},
- _formatMonth: function (date) {
- return this.FormatMonth(date || this._parseMonth(), this.options.MonthFormat);
+ _parseMonth: function (str, format) {
+ return this.ParseMonth(str || this.element.val(), format || this.options.MonthFormat);
+ },
+
+ _formatMonth: function (date, format) {
+ return this.FormatMonth(date || this._parseMonth(), format || this.options.MonthFormat);
},
_showIcon: function () {
@@ -567,15 +608,16 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
try {
_button.button('option', 'disabled', isDisabled);
} catch (e) {
- _button.filter('button, input').prop('disabled', isDisabled);
+ _button.filter('button,input').prop('disabled', isDisabled);
}
},
_createButton: function () {
- if (!this.options.ShowIcon) return;
+ var _elem = this.element;
+ if (!this.options.ShowIcon || !_elem.is('input')) return;
var _oldButton = this._monthPickerButton.off(_eventsNs);
- var _btnOpt = this.options.Button, _elem = this.element;
+ var _btnOpt = this.options.Button;
if ($.isFunction(_btnOpt)) {
_btnOpt = _btnOpt.call(_elem[0], $.extend(true, {i18n: $.MonthPicker.i18n}, this.options));
@@ -629,10 +671,10 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
switch (event.keyCode) {
case 13: // Enter.
this._chooseMonth(new Date().getMonth() + 1);
- this.Close();
+ this.Close(event);
break;
case 27: // Escape
- this.Close();
+ this.Close(event);
break;
}
},
@@ -704,13 +746,23 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
this._yearContainer.text(year || new Date().getFullYear());
},
+ _updateAlt: function (noop, date) {
+ // False means use the fields value.
+ var _field = $(this.options.AltField);
+ if (_field.length) {
+ _field.val(this._formatMonth(date, this.options.AltFormat));
+ }
+ },
+
_chooseMonth: function (month) {
var date = new Date(this._getPickerYear(), month-1);
this.element.val(this._formatMonth( date )).blur();
+ this._updateAlt(0, date);
+
_setActive( this._selectedBtn, false );
this._selectedBtn = _setActive( $(this._buttons[month-1]), true );
- _event('OnAfterChooseMonth', this)();
+ _event('OnAfterChooseMonth', this)(date);
},
_chooseYear: function (year) {
@@ -844,7 +896,7 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
_year = Math.min(_toYear(this._MaxMonth), _year);
}
- this._setPickerYear( _year );
+ this._setPickerYear( _year );
},
_decorateButtons: function() {
diff --git a/MonthPicker.min.js b/MonthPicker.min.js
index 3a6c84e..623afc7 100644
--- a/MonthPicker.min.js
+++ b/MonthPicker.min.js
@@ -1 +1 @@
-!function(a,b,c,d){"use strict";function e(a){return a.getMonth()+12*a.getFullYear()}function f(a){return Math.floor(a/12)}function g(){a(this).addClass(s)}function h(a,b){return a[b?"on":"off"]("mousenter mouseout",g).toggleClass(s,b)}function i(a,b,c){return(!b||a>=b)&&(!c||c>=a)}function j(b,c){if(null===c)return c;if(c instanceof d)return e(c);if(a.isNumeric(c))return e(new d)+parseInt(c,10);var f=b._parseMonth(c);return f?e(f):l(c)}function k(a,b){return E(b.options[a]||D,b.element[0])}function l(a,b){var c=a.trim();c=c.replace(/y/i,'":"y"'),c=c.replace(/m/i,'":"m"');try{var f=JSON.parse('{"'+c.replace(/ /g,',"')+"}"),g={};for(var h in f)g[f[h]]=h;var i=e(new d);return i+=parseInt(g.m,10)||0,i+12*(parseInt(g.y,10)||0)}catch(j){return!1}}function m(b){return a(''+b.i18n.buttonText+"").button({text:!1,icons:{primary:b.ButtonIcon}})}function n(a,b){a.button("option",{icons:{primary:"ui-icon-circle-triangle-"+(b?"w":"e")}})}if(!(a&&a.ui&&a.ui.button&&a.ui.datepicker))return alert(v+"The jQuery UI button and datepicker plug-ins must be loaded."),!1;var o=a.fx.speeds,p=".MonthPicker",q="month-picker-disabled",r="ui-state-highlight",s="ui-state-active",t={my:"left top+1",at:"left bottom"},u={my:"right top+1",at:"right bottom"},v="MonthPicker Error: ",w=v+"The jQuery UI position plug-in must be loaded.",x=v+"Unsupported % option value, supported values are: ",y=v+'"_" is not a valid %Month value.',z=null,A=!!a.ui.position,B={Animation:["slideToggle","fadeToggle","none"],ShowAnim:["fadeIn","slideDown","none"],HideAnim:["fadeOut","slideUp","none"]},C={ValidationErrorMessage:"_createValidationMessage",Disabled:"_setDisabledState",ShowIcon:"_showIcon",Button:"_updateButton",ShowOn:"_updateFieldEvents",IsRTL:"_setRTL",StartYear:"_setPickerYear",MinMonth:"_setMinMonth",MaxMonth:"_setMaxMonth"},D=a.noop,E=a.proxy,F=a.datepicker,G="click"+p;a.MonthPicker={VERSION:2.7,i18n:{year:"Year",prevYear:"Previous Year",nextYear:"Next Year",next5Years:"Jump Forward 5 Years",prev5Years:"Jump Back 5 Years",nextLabel:"Next",prevLabel:"Prev",buttonText:"Open Month Chooser",jumpYears:"Jump Years",months:["Jan.","Feb.","Mar.","Apr.","May","June","July","Aug.","Sep.","Oct.","Nov.","Dec."]}};var H='
';a.widget("KidSysco.MonthPicker",{options:{i18n:{},IsRTL:!1,Position:null,StartYear:null,ShowIcon:!0,UseInputMask:!1,ValidationErrorMessage:null,Disabled:!1,MonthFormat:"mm/yy",Animation:"fadeToggle",ShowAnim:null,HideAnim:null,ShowOn:null,MinMonth:null,MaxMonth:null,Duration:"normal",Button:m,ButtonIcon:"ui-icon-calculator"},_monthPickerButton:a(),_validationMessage:a(),_selectedBtn:a(),_destroy:function(){var b=this.element;jQuery.mask&&this.options.UseInputMask&&(b.unmask(),this.GetSelectedDate()||b.val("")),b.removeClass("month-year-input").off(p),a(c).off(G+this.uuid),this._monthPickerMenu.remove();var d=this._monthPickerButton.off(G);this._removeOldBtn&&d.remove(),this._validationMessage.remove()},_setOption:function(b,c){switch(b){case"i18n":c=a.extend({},c);break;case"Position":if(!A)return void alert(w);case"MonthFormat":var d=this.GetSelectedDate();d&&this.element.val(this.FormatMonth(d,c))}return b in B&&-1===B[b].indexOf(c)?void alert(x.replace(/%/,b)+B[b]):(this._super(b,c),void(C[b]?this[C[b]](c):0))},_create:function(){var b=this.element,c=this.options;if(!b.is("input")||-1===["text","month",void 0].indexOf(b.attr("type"))){var d=v+"MonthPicker can only be called on text or month inputs.";return alert(d+" \n\nSee (developer tools) for more details."),console.error(d+"\n Caused by:"),console.log(b[0]),!1}if(!a.mask&&c.UseInputMask)return alert(v+"The UseInputMask option requires the Input Mask Plugin. Get it from digitalbush.com"),!1;if(null!==c.Position&&!A)return alert(w),!1;for(var e in B)if(null!==c[e]&&-1===B[e].indexOf(c[e]))return alert(x.replace(/%/,e)+B[e]),!1;this._isMonthInputType="month"===b.attr("type"),this._isMonthInputType&&(this.options.MonthFormat=this.MonthInputFormat,b.css("width","auto")),b.addClass("month-year-input");var f=this._monthPickerMenu=a('');a(H).appendTo(f),a("body").append(f),a(".year-title",f).text(this._i18n("year")),this._yearContainerAll=a(".year-container-all",f).attr("title",this._i18n("jumpYears")).click(E(this._showYearsClickHandler,this)),this._createValidationMessage(),this._yearContainer=a(".year",f),this._prevButton=a(".previous-year button",f).button({text:!1}),this._nextButton=a(".next-year button",f).button({text:!1}),this._setRTL(c.IsRTL),a(".ui-button-icon-primary",this._nextButton).text(this._i18n("nextLabel")),a(".ui-button-icon-primary",this._prevButton).text(this._i18n("prevLabel"));for(var g=a(".month-picker-month-table",f),h=0;12>h;h++){var i=h%3?i:a("
").appendTo(g);i.append('
')}this._buttons=a("button",g).button(),f.on(G,function(a){return!1});var k=this,l="Month";a.each(["Min","Max"],function(a,b){k["_set"+b+l]=function(a){(k["_"+b+l]=j(k,a))===!1&&alert(y.replace(/%/,b).replace(/_/,a))},k._setOption(b+l,k.options[b+l])}),this._setUseInputMask(),this._setDisabledState(),this._updateFieldEvents(),this.Destroy=this.destroy},_i18n:function(b){return this.options.i18n[b]||a.MonthPicker.i18n[b]},GetSelectedDate:function(){return this._parseMonth()},GetSelectedYear:function(){var a=this.GetSelectedDate();return a?a.getFullYear():NaN},GetSelectedMonth:function(){var a=this.GetSelectedDate();return a?a.getMonth()+1:NaN},Validate:function(){var a=this.GetSelectedDate();return null===this.options.ValidationErrorMessage||this.options.Disabled||this._validationMessage.toggle(!a),a},GetSelectedMonthYear:function(){var a=this.Validate();return a?a.getMonth()+1+"/"+a.getFullYear():null},Disable:function(){this._setOption("Disabled",!0)},Enable:function(){this._setOption("Disabled",!1)},ClearAllCallbacks:function(){for(var a in this.options)0===a.indexOf("On")&&(this.options[a]=D)},Clear:function(){this.element.val(""),this._validationMessage.hide()},Toggle:function(a){return this._visible?this.Close(a):this.Open(a)},Open:function(b){if(!this.options.Disabled&&!this._visible){var d=this.element,e=this.options;if(b=b||new a.Event,k("OnBeforeMenuOpen",this)(b)===!1||b.isDefaultPrevented())return!1;this._visible=!0,this._ajustYear(e),z&&z.Close(b),z=this;var f=this._monthPickerMenu;this._showMonths(),a(c).on(G+this.uuid,E(this.Close,this)).on("keydown"+p+this.uuid,E(this._keyDown,this)),d.off("blur"+p).focus();var g=e.ShowAnim||e.Animation,h="none"===g;f[h?"fadeIn":g]({duration:h?0:this._duration(),start:E(this._position,this,f),complete:k("OnAfterMenuOpen",this)})}return!1},Close:function(b){if(this._visible){var d=this._monthPickerMenu,e=this.options,f=this.element;if(b=b||new a.Event,k("OnBeforeMenuClose",this)(b)===!1||b.isDefaultPrevented())return;this._visible=!1,z=null,a(c).off("keydown"+p+this.uuid).off(G+this.uuid),this.Validate(),f.on("blur"+p,E(this.Validate,this));var g=k("OnAfterMenuClose",this),h=e.HideAnim||e.Animation;"none"===h?d.hide(0,g):d[h](this._duration(),g)}},MonthInputFormat:"yy-mm",ParseMonth:function(a,b){try{return F.parseDate("dd"+b,"01"+a)}catch(c){return null}},FormatMonth:function(a,b){try{return F.formatDate(b,a)||null}catch(c){return null}},_parseMonth:function(a){return this.ParseMonth(a||this.element.val(),this.options.MonthFormat)},_formatMonth:function(a){return this.FormatMonth(a||this._parseMonth(),this.options.MonthFormat)},_showIcon:function(){var a=this._monthPickerButton;a.length?a.toggle(!!this.options.ShowIcon):this._createButton(),this._updateFieldEvents()},_updateButton:function(){var a=this.options.Disabled;this._createButton();var b=this._monthPickerButton;try{b.button("option","disabled",a)}catch(c){b.filter("button, input").prop("disabled",a)}},_createButton:function(){if(this.options.ShowIcon){var b=this._monthPickerButton.off(p),d=this.options.Button,e=this.element;a.isFunction(d)&&(d=d.call(e[0],a.extend(!0,{i18n:a.MonthPicker.i18n},this.options)));var f=!1;this._monthPickerButton=(d instanceof a?d:a(d)).each(function(){a.contains(c.body,this)||(f=!0,a(this).insertAfter(e))}).on(G,E(this.Toggle,this)),this._removeOldBtn&&b.remove(),this._removeOldBtn=f}},_updateFieldEvents:function(){this.element.off(G),"both"!==this.options.ShowOn&&this._monthPickerButton.length||this.element.on(G,E(this.Open,this))},_createValidationMessage:function(){var b=this.options.ValidationErrorMessage,c=this.element;if(-1===[null,""].indexOf(b)){var d=a(''+b+""),e=this._monthPickerButton;this._validationMessage=d.insertAfter(e.length?e:c),c.on("blur"+p,E(this.Validate,this))}else this._validationMessage.remove()},_setRTL:function(a){n(this._prevButton,!a),n(this._nextButton,a)},_keyDown:function(a){switch(a.keyCode){case 13:this._chooseMonth((new d).getMonth()+1),this.Close();break;case 27:this.Close()}},_duration:function(){var b=this.options.Duration;return a.isNumeric(b)?b:b in o?o[b]:o._default},_position:A?function(b){var c=this.options.IsRTL?u:t,d=a.extend(c,this.options.Position);return b.position(a.extend({of:this.element},d))}:function(a){var b=this.element,c={top:b.offset().top+b.height()+7+"px"};return this.options.IsRTL?c.left=b.offset().left-a.width()+b.width()+7+"px":c.left=b.offset().left+"px",a.css(c)},_setUseInputMask:function(){if(!this._isMonthInputType)try{this.options.UseInputMask?this.element.mask(this._formatMonth(new d).replace(/\d/g,9)):this.element.unmask()}catch(a){}},_setDisabledState:function(){var a=this.options.Disabled,b=this.element;b[0].disabled=a,b.toggleClass(q,a),a&&this._validationMessage.hide(),this.Close(),this._updateButton(),k("OnAfterSetDisabled",this)(a)},_getPickerYear:function(){return parseInt(this._yearContainer.text(),10)},_setPickerYear:function(a){this._yearContainer.text(a||(new d).getFullYear())},_chooseMonth:function(b){var c=new d(this._getPickerYear(),b-1);this.element.val(this._formatMonth(c)).blur(),h(this._selectedBtn,!1),this._selectedBtn=h(a(this._buttons[b-1]),!0),k("OnAfterChooseMonth",this)()},_chooseYear:function(a){this._setPickerYear(a),this._buttons.removeClass(r),this._showMonths(),k("OnAfterChooseYear",this)()},_showMonths:function(){var b=this._i18n("months");this._prevButton.attr("title",this._i18n("prevYear")).off(G).on(G,E(this._addToYear,this,-1)),this._nextButton.attr("title",this._i18n("nextYear")).off(G).on(G,E(this._addToYear,this,1)),this._yearContainerAll.css("cursor","pointer"),this._buttons.off(p);var c=this,d=E(c._onMonthClick,c);a.each(b,function(b,e){a(c._buttons[b]).on(G,{month:b+1},d).button("option","label",e)}),this._decorateButtons()},_showYearsClickHandler:function(){this._buttons.removeClass(r),this._showYears(),k("OnAfterChooseYears",this)()},_showYears:function(){var b=this._getPickerYear(),c=-4,e=b+c,g=5,j=(new d).getFullYear(),k=this._MinMonth,l=this._MaxMonth,m=k?f(k):0,n=l?f(l):0;this._prevButton.attr("title",this._i18n("prev5Years")).off(G).on(G,E(this._addToYears,this,-g)).button("option","disabled",m&&m>e-1),this._nextButton.attr("title",this._i18n("next5Years")).off(G).on(G,E(this._addToYears,this,g)).button("option","disabled",n&&e+12-1>n),this._yearContainerAll.css("cursor","default"),this._buttons.off(p),h(this._selectedBtn,!1);for(var o=this.GetSelectedYear(),q=E(this._onYearClick,this),s=i(j,m,n),t=i(o,m,n),u=0;12>u;u++){var v=b+c,w=a(this._buttons[u]).button({disabled:!i(v,m,n),label:v}).toggleClass(r,v===j&&s).on(G,{year:v},q);t&&o&&o===v&&(this._selectedBtn=h(w,!0)),c++}},_onMonthClick:function(a){this._chooseMonth(a.data.month),this.Close(a)},_onYearClick:function(a){this._chooseYear(a.data.year)},_addToYear:function(a){var b=this._yearContainer;b.text(parseInt(b.text())+a,10),this.element.focus(),this._decorateButtons(),k("OnAfter"+(a>0?"Next":"Previous")+"Year",this)()},_addToYears:function(a){var b=this._yearContainer;b.text(parseInt(b.text())+a,10),this._showYears(),this.element.focus(),k("OnAfter"+(a>0?"Next":"Previous")+"Years",this)()},_ajustYear:function(a){var b=a.StartYear||this.GetSelectedYear()||(new d).getFullYear();null!==this._MinMonth&&(b=Math.max(f(this._MinMonth),b)),null!==this._MaxMonth&&(b=Math.min(f(this._MaxMonth),b)),this._setPickerYear(b)},_decorateButtons:function(){var b=this._getPickerYear(),c=e(new d),g=this._MinMonth,j=this._MaxMonth;h(this._selectedBtn,!1);var k=this.GetSelectedDate(),l=i(k?e(k):null,g,j);k&&k.getFullYear()===b&&(this._selectedBtn=h(a(this._buttons[k.getMonth()]),l)),this._prevButton.button("option","disabled",g&&b==f(g)),this._nextButton.button("option","disabled",j&&b==f(j));for(var m=0;12>m;m++){var n=12*b+m,o=i(n,g,j);a(this._buttons[m]).button({disabled:!o}).toggleClass(r,o&&n==c)}}})}(jQuery,window,document,Date);
\ No newline at end of file
+!function(a,b,c,d){"use strict";function e(a){return a.getMonth()+12*a.getFullYear()}function f(a){return Math.floor(a/12)}function g(){a(this).addClass(t)}function h(a,b){return a[b?"on":"off"]("mousenter mouseout",g).toggleClass(t,b)}function i(a,b,c){return(!b||a>=b)&&(!c||c>=a)}function j(b,c){if(null===c)return c;if(c instanceof d)return e(c);if(a.isNumeric(c))return e(new d)+parseInt(c,10);var f=b._parseMonth(c);return f?e(f):l(c)}function k(a,b){return F(b.options[a]||E,b.element[0])}function l(a,b){var c=a.trim();c=c.replace(/y/i,'":"y"'),c=c.replace(/m/i,'":"m"');try{var f=JSON.parse('{"'+c.replace(/ /g,',"')+"}"),g={};for(var h in f)g[f[h]]=h;var i=e(new d);return i+=parseInt(g.m,10)||0,i+12*(parseInt(g.y,10)||0)}catch(j){return!1}}function m(b){return a(''+b.i18n.buttonText+"").button({text:!1,icons:{primary:b.ButtonIcon}})}function n(a,b){a.button("option",{icons:{primary:"ui-icon-circle-triangle-"+(b?"w":"e")}})}function o(a){return!a.is("input")}if(!(a&&a.ui&&a.ui.button&&a.ui.datepicker))return void alert(w+"The jQuery UI button and datepicker plug-ins must be loaded.");var p=a.fx.speeds,q=".MonthPicker",r="month-picker-disabled",s="ui-state-highlight",t="ui-state-active",u={my:"left top+1",at:"left bottom"},v={my:"right top+1",at:"right bottom"},w="MonthPicker Error: ",x=w+"The jQuery UI position plug-in must be loaded.",y=w+"Unsupported % option value, supported values are: ",z=w+'"_" is not a valid %Month value.',A=null,B=!!a.ui.position,C={Animation:["slideToggle","fadeToggle","none"],ShowAnim:["fadeIn","slideDown","none"],HideAnim:["fadeOut","slideUp","none"]},D={ValidationErrorMessage:"_createValidationMessage",Disabled:"_setDisabledState",ShowIcon:"_showIcon",Button:"_updateButton",ShowOn:"_updateFieldEvents",IsRTL:"_setRTL",AltFormat:"_updateAlt",AltField:"_updateAlt",StartYear:"_setPickerYear",MinMonth:"_setMinMonth",MaxMonth:"_setMaxMonth",SelectedMonth:"_setSelectedMonth"},E=a.noop,F=a.proxy,G=a.datepicker,H="click"+q;a.MonthPicker={VERSION:2.8,i18n:{year:"Year",prevYear:"Previous Year",nextYear:"Next Year",next5Years:"Jump Forward 5 Years",prev5Years:"Jump Back 5 Years",nextLabel:"Next",prevLabel:"Prev",buttonText:"Open Month Chooser",jumpYears:"Jump Years",months:["Jan.","Feb.","Mar.","Apr.","May","June","July","Aug.","Sep.","Oct.","Nov.","Dec."]}};var I='
';a.widget("KidSysco.MonthPicker",{options:{i18n:{},IsRTL:!1,Position:null,StartYear:null,ShowIcon:!0,UseInputMask:!1,ValidationErrorMessage:null,Disabled:!1,MonthFormat:"mm/yy",Animation:"fadeToggle",ShowAnim:null,HideAnim:null,ShowOn:null,MinMonth:null,MaxMonth:null,Duration:"normal",Button:m,ButtonIcon:"ui-icon-calculator"},_monthPickerButton:a(),_validationMessage:a(),_selectedBtn:a(),_destroy:function(){var b=this.element;jQuery.mask&&this.options.UseInputMask&&(b.unmask(),this.GetSelectedDate()||b.val("")),b.removeClass("month-year-input").off(q),a(c).off(H+this.uuid),this._monthPickerMenu.remove();var d=this._monthPickerButton.off(H);this._removeOldBtn&&d.remove(),this._validationMessage.remove()},_setOption:function(b,c){switch(b){case"i18n":c=a.extend({},c);break;case"Position":if(!B)return void alert(x);case"MonthFormat":var d=this.GetSelectedDate();d&&this.element.val(this.FormatMonth(d,c))}return b in C&&-1===C[b].indexOf(c)?void alert(y.replace(/%/,b)+C[b]):(this._super(b,c),void(D[b]?this[D[b]](c):0))},_create:function(){var b=this.element,e=this.options;if(!b.is("input,div,span")||-1===["text","month",void 0].indexOf(b.attr("type"))){var g=w+"MonthPicker can only be called on text or month inputs.";return alert(g+" \n\nSee (developer tools) for more details."),console.error(g+"\n Caused by:"),console.log(b[0]),!1}if(!a.mask&&e.UseInputMask)return alert(w+"The UseInputMask option requires the Input Mask Plugin. Get it from digitalbush.com"),!1;if(null!==e.Position&&!B)return alert(x),!1;for(var h in C)if(null!==e[h]&&-1===C[h].indexOf(e[h]))return alert(y.replace(/%/,h)+C[h]),!1;this._isMonthInputType="month"===b.attr("type"),this._isMonthInputType&&(this.options.MonthFormat=this.MonthInputFormat,b.css("width","auto")),b.addClass("month-year-input");var i=this._monthPickerMenu=a(''),k=o(b);a(I).appendTo(i),i.appendTo(k?b:c.body),a(".year-title",i).text(this._i18n("year")),this._yearContainerAll=a(".year-container-all",i).attr("title",this._i18n("jumpYears")).click(F(this._showYearsClickHandler,this)),this._createValidationMessage(),this._yearContainer=a(".year",i),this._prevButton=a(".previous-year button",i).button({text:!1}),this._nextButton=a(".next-year button",i).button({text:!1}),this._setRTL(e.IsRTL);var l=".ui-button-icon-primary";a(l,this._nextButton).text(this._i18n("nextLabel")),a(l,this._prevButton).text(this._i18n("prevLabel"));for(var m=a(".month-picker-month-table",i),n=0;12>n;n++){var p=n%3?p:a("
The jQuery UI Month Picker Plugin is designed to allow user input for only a month and year when only that input is
required. Clicking on the year, allows the user to jump ahead or back 5 years at a time. Clicking anywhere on the
page, except on the month picker menu itself, will cause the month picker to hide. The Month Picker has lots of options
@@ -45,7 +45,7 @@ $('input[type=month]').MonthPicker().css('backgroundColor', 'lightyellow');
All buttons, labels and other text can be changed out using the i18n support.
+You can create an inline month picker menu by calling the month picker function on a <div> or <span> tag, example:
+
+$('div').MonthPicker({
+ SelectedMonth: '+1y -3M', // Set the selected month.
+ AltField: '#hiddenInput' // Populate a hidden field and send to send the selected value to the server.
+
+ OnAfterChooseMonth: function(selectedDate) {
+ // Do something with selected JavaScript date.
+ // console.log(selectedDate);
+ }
+});
+
+
+
HTML 5 Month Input Support
Calling the MonthPicker on HTML 5 Month Input types is currently working. The latest version of Chrome shows some nice examples of how this plugin works with the HTML 5 Month Input Type but we still feel that our UI is better than what Chrome offers... Wow, did I just say that? The jQuery UI month picker UI allows the user to choose any month of the year in a single click, while the Chrome version requires more tinkering. The HTML 5 support in Chrome appears to make input masking and validation obsolete, so those should be turned off when using this plugin on an HTML 5 Month Input Type. The HTML 5 Month Input Type is the reccomended element to call this plugin on but it is not required.
@@ -119,7 +135,7 @@ However this is not supported and might stop working in future releases i
Destroys the month picker widget.
Theme Support
-
The MonthPicker plugin uses the jQuery UI CSS Framework to style its look and feel, including the colors of buttons and background textures. We recommend using the ThemeRoller tool to create and download custom themes that are easy to build and maintain.
+
The MonthPicker plugin uses the jQuery UI CSS Framework to style its look and feel, including the colors of buttons and background textures. We recommend using the ThemeRoller tool to create and download custom themes that are easy to build and maintain.
If a deeper level of customization is needed, there are widget-specific classes referenced within the MonthPicker.css stylesheet that can be modified. These classes are highlighed below.
.month-picker-disabled
@@ -324,6 +340,37 @@ When you change the Disabled option the button will be v
If the button is not one of the elements above then you have to disable the element yourself as shown in the example above.
+
+
SelectedMonth
+ Type: Date or Number or String
+ Default: null
+ Since: 2.8
+ Set the selected month. When set to null nothing is selected.
+
+
+
+Multiple types supported:
+
+
Date: A Date object containing the selected month.
+
Number: A number of months from today. For example 2 represents two months from today and -1 represents the last month.
+
String: A string in the format defined by the MonthFormat option option, or a relative month.
Relative months must contain value and period pairs; valid periods are "m" for months, and "y" for years. For example, "+1y +3m" represents one year and three months from today.
Type: Boolean
@@ -470,7 +517,7 @@ $('.selector').MonthPicker({ MonthFormat: 'MM, yy' });
var disabled = $('.selector').MonthPicker('option', 'MonthFormat');
//setter (Results in December, 2015)
-$('.selector').MonthPicker('option', MonthFormat: 'MM, yy' );
+$('.selector').MonthPicker('option', 'MonthFormat', 'MM, yy' );
The following example shows how to use the popular Moment.js library
@@ -520,6 +567,52 @@ $('.selector').MomentMonthPicker({
});
+
+
+
AltField
+ Type: Selector or jQuery or Element
+ Default: null.
+ Since: 2.8
+ An input element that is to be updated with the selected month from the month picker. Use the AltFormat option to change the format of the date within this field. Leave as blank for no alternate field.
+
+
+ Type: String
+ Default: null.
+ Since: 2.8
+ The MonthFormat to be used for the AltField option. This allows one month format to be shown to the user for selection purposes, while a different format is actually sent behind the scenes. For a full list of the possible formats see the $.datepicker.formatDate() function.
+
+
';a.widget("KidSysco.MonthPicker",{options:{i18n:{},IsRTL:!1,Position:null,StartYear:null,ShowIcon:!0,UseInputMask:!1,ValidationErrorMessage:null,Disabled:!1,MonthFormat:"mm/yy",Animation:"fadeToggle",ShowAnim:null,HideAnim:null,ShowOn:null,MinMonth:null,MaxMonth:null,Duration:"normal",Button:m,ButtonIcon:"ui-icon-calculator"},_monthPickerButton:a(),_validationMessage:a(),_selectedBtn:a(),_destroy:function(){var b=this.element;jQuery.mask&&this.options.UseInputMask&&(b.unmask(),this.GetSelectedDate()||b.val("")),b.removeClass("month-year-input").off(p),a(c).off(G+this.uuid),this._monthPickerMenu.remove();var d=this._monthPickerButton.off(G);this._removeOldBtn&&d.remove(),this._validationMessage.remove()},_setOption:function(b,c){switch(b){case"i18n":c=a.extend({},c);break;case"Position":if(!A)return void alert(w);case"MonthFormat":var d=this.GetSelectedDate();d&&this.element.val(this.FormatMonth(d,c))}return b in B&&-1===B[b].indexOf(c)?void alert(x.replace(/%/,b)+B[b]):(this._super(b,c),void(C[b]?this[C[b]](c):0))},_create:function(){var b=this.element,c=this.options;if(!b.is("input")||-1===["text","month",void 0].indexOf(b.attr("type"))){var d=v+"MonthPicker can only be called on text or month inputs.";return alert(d+" \n\nSee (developer tools) for more details."),console.error(d+"\n Caused by:"),console.log(b[0]),!1}if(!a.mask&&c.UseInputMask)return alert(v+"The UseInputMask option requires the Input Mask Plugin. Get it from digitalbush.com"),!1;if(null!==c.Position&&!A)return alert(w),!1;for(var e in B)if(null!==c[e]&&-1===B[e].indexOf(c[e]))return alert(x.replace(/%/,e)+B[e]),!1;this._isMonthInputType="month"===b.attr("type"),this._isMonthInputType&&(this.options.MonthFormat=this.MonthInputFormat,b.css("width","auto")),b.addClass("month-year-input");var f=this._monthPickerMenu=a('');a(H).appendTo(f),a("body").append(f),a(".year-title",f).text(this._i18n("year")),this._yearContainerAll=a(".year-container-all",f).attr("title",this._i18n("jumpYears")).click(E(this._showYearsClickHandler,this)),this._createValidationMessage(),this._yearContainer=a(".year",f),this._prevButton=a(".previous-year button",f).button({text:!1}),this._nextButton=a(".next-year button",f).button({text:!1}),this._setRTL(c.IsRTL),a(".ui-button-icon-primary",this._nextButton).text(this._i18n("nextLabel")),a(".ui-button-icon-primary",this._prevButton).text(this._i18n("prevLabel"));for(var g=a(".month-picker-month-table",f),h=0;12>h;h++){var i=h%3?i:a("
';a.widget("KidSysco.MonthPicker",{options:{i18n:{},IsRTL:!1,Position:null,StartYear:null,ShowIcon:!0,UseInputMask:!1,ValidationErrorMessage:null,Disabled:!1,MonthFormat:"mm/yy",Animation:"fadeToggle",ShowAnim:null,HideAnim:null,ShowOn:null,MinMonth:null,MaxMonth:null,Duration:"normal",Button:m,ButtonIcon:"ui-icon-calculator"},_monthPickerButton:a(),_validationMessage:a(),_selectedBtn:a(),_destroy:function(){var b=this.element;jQuery.mask&&this.options.UseInputMask&&(b.unmask(),this.GetSelectedDate()||b.val("")),b.removeClass("month-year-input").off(q),a(c).off(H+this.uuid),this._monthPickerMenu.remove();var d=this._monthPickerButton.off(H);this._removeOldBtn&&d.remove(),this._validationMessage.remove()},_setOption:function(b,c){switch(b){case"i18n":c=a.extend({},c);break;case"Position":if(!B)return void alert(x);case"MonthFormat":var d=this.GetSelectedDate();d&&this.element.val(this.FormatMonth(d,c))}return b in C&&-1===C[b].indexOf(c)?void alert(y.replace(/%/,b)+C[b]):(this._super(b,c),void(D[b]?this[D[b]](c):0))},_create:function(){var b=this.element,e=this.options;if(!b.is("input,div,span")||-1===["text","month",void 0].indexOf(b.attr("type"))){var g=w+"MonthPicker can only be called on text or month inputs.";return alert(g+" \n\nSee (developer tools) for more details."),console.error(g+"\n Caused by:"),console.log(b[0]),!1}if(!a.mask&&e.UseInputMask)return alert(w+"The UseInputMask option requires the Input Mask Plugin. Get it from digitalbush.com"),!1;if(null!==e.Position&&!B)return alert(x),!1;for(var h in C)if(null!==e[h]&&-1===C[h].indexOf(e[h]))return alert(y.replace(/%/,h)+C[h]),!1;this._isMonthInputType="month"===b.attr("type"),this._isMonthInputType&&(this.options.MonthFormat=this.MonthInputFormat,b.css("width","auto")),b.addClass("month-year-input");var i=this._monthPickerMenu=a(''),k=o(b);a(I).appendTo(i),i.appendTo(k?b:c.body),a(".year-title",i).text(this._i18n("year")),this._yearContainerAll=a(".year-container-all",i).attr("title",this._i18n("jumpYears")).click(F(this._showYearsClickHandler,this)),this._createValidationMessage(),this._yearContainer=a(".year",i),this._prevButton=a(".previous-year button",i).button({text:!1}),this._nextButton=a(".next-year button",i).button({text:!1}),this._setRTL(e.IsRTL);var l=".ui-button-icon-primary";a(l,this._nextButton).text(this._i18n("nextLabel")),a(l,this._prevButton).text(this._i18n("prevLabel"));for(var m=a(".month-picker-month-table",i),n=0;12>n;n++){var p=n%3?p:a("
Only one picker open test First picker:
diff --git a/test/test.js b/test/test.js
index 9504678..27963ed 100644
--- a/test/test.js
+++ b/test/test.js
@@ -341,12 +341,58 @@ QUnit.test('MonthFormat Option Tests', function (assert) {
assert.equal($(FormatField).val(), 'April 2012', 'The text field has the value April 2012');
});
+QUnit.test('Inline menu', function(assert) {
+ var field = $(InlineMenuDiv).MonthPicker({
+ Animation: 'none', // Disable animation to make sure opening and closing the menu is synchronous.
+ });
+
+ var menu = $(MonthPicker_InlineMenuDiv);
+
+ assert.ok(menu.is(':visible'), 'The menu is visible without having to call the Open method');
+
+
+ $(document.body).trigger('click');
+
+ assert.ok(menu.is(':visible'), 'The menu is still visible after clicking outside the menu');
+
+ //var buttons = menu.find('.month-picker-month-table button');
+ menu.find('.button-1').trigger('click');
+
+ assert.ok(menu.is(':visible'), 'The menu is still visible after choosing a month');
+
+ assert.notOk($("#MonthPicker_Button_InlineMenuDiv").length, 'The default button was not created');
+
+ field.MonthPicker('destroy');
+});
+
+QUnit.test('SelectedMonth option', function(assert) {
+ var field = $(InlineMenuDiv).MonthPicker({
+ Animation: 'none', // Disable animation to make sure opening and closing the menu is synchronous.
+
+ SelectedMonth: 0
+ });
+
+ var menu = $(MonthPicker_InlineMenuDiv);
+ var date = field.MonthPicker('GetSelectedDate');
+ assert.equal( date.getMonth(), _today.getMonth(), 'The correct month was selected');
+ assert.equal( date.getFullYear(), _today.getFullYear(), 'The correct year was selected');
+
+ assert.ok( menu.find('.button-' + (_today.getMonth()+1)).is('.ui-state-active'), 'The correct button is highlighted');
+
+ field.MonthPicker('option', 'SelectedMonth', '01/2015');
+
+ var date = field.MonthPicker('GetSelectedDate');
+ assert.ok( menu.find('.button-1').is('.ui-state-active'), 'January is selected after changing the SelectedMonth');
+
+ field.MonthPicker('Destroy');
+});
+
// Makes sure that all events are triggered as expected.
// Perhaps we should consider removing some of these events.
QUnit.test('Events and context', function (assert) { // A.k.a duplicate code test.
// Good luck figuring out which callback is causing the
// problem if this test fails.
- assert.expect(30);
+ assert.expect(31);
var field = $(EventsField).MonthPicker({
Animation: 'none', // Disable animation to make sure opening and closing the menu is synchronous.
@@ -445,7 +491,8 @@ QUnit.test('Events and context', function (assert) { // A.k.a duplicate code tes
assert.ok(OnAfterChooseYearTriggered, 'Clicking a year triggered OnAfterChooseYear');
var OnAfterChooseMonthTriggered = false;
- field.MonthPicker('option', 'OnAfterChooseMonth', function() {
+ field.MonthPicker('option', 'OnAfterChooseMonth', function(date) {
+ assert.ok(date instanceof Date, 'A date value was passed to OnAfterChooseMonth as the first argument');
OnAfterChooseMonthTriggered = true;
assert.equal( this, EventsField, 'OnAfterChooseMonth was called in the right context' );
});
@@ -498,6 +545,39 @@ QUnit.test('Events and context', function (assert) { // A.k.a duplicate code tes
field.MonthPicker('ClearAllCallbacks');
});
+QUnit.test('AltField and AltFormat tests', function( assert ) {
+ var hiddenField = $('');
+
+ var field = $(MainAltField).MonthPicker({
+ SelectedMonth: '05/2010',
+ Animation: 'none', // Disable animation to make sure opening and closing the menu is synchronous.
+ AltField: hiddenField,
+ AltFormat: 'yy-mm'
+ });
+
+ assert.equal(hiddenField.val(), '2010-05', "The secondary field has the main field's value in the alt format");
+
+ field.MonthPicker('Open');
+
+ var menu = $(MonthPicker_MainAltField);
+ menu.find('.button-1').trigger('click');
+
+ assert.equal( field.val(), '01/2010', 'The main field was populated');
+ assert.equal( hiddenField.val(), '2010-01', 'The secondary field was populated with a different format');
+
+ field.MonthPicker('option', 'AltFormat', null);
+
+ assert.equal( hiddenField.val(), '01/2010', 'Clearing AltFormat set the format to the MonthFormat');
+
+ field.MonthPicker('option', 'AltField', '#SecondaryAltField');
+
+ assert.equal( $(SecondaryAltField).val(), '01/2010', 'Changing the altField after init assigned the current value');
+
+ field.val('11/2015').trigger('change');
+
+ assert.equal( $(SecondaryAltField).val(), '11/2015', 'Triggering a change event on the main field updated the secondary field');
+});
+
QUnit.test('Right to left', function (assert) {
var field = $(RTLField).MonthPicker({
Animation: 'none', // Disable animation to make sure opening and closing the menu is synchronous.