diff --git a/MonthPicker.js b/MonthPicker.js index 459cfbc..091279a 100644 --- a/MonthPicker.js +++ b/MonthPicker.js @@ -1,7 +1,7 @@ /* https://github.com/KidSysco/jquery-ui-month-picker/ -Version 2.6.1 +Version 2.6.2 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -16,6 +16,7 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. */ ; (function ($, window, document) { + 'use strict'; var _speeds = $.fx.speeds; var _eventsNs = '.MonthPicker'; var _disabledClass = 'month-picker-disabled'; @@ -42,6 +43,14 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. MaxMonth: '_setMaxMonth' }; + function _toMonth(date) { + return date.getMonth() + (date.getFullYear() * 12); + } + + function _toYear(month) { + return Math.floor(month / 12); + } + // This test must be run before any rererence is made to jQuery. // In case the user didn't load jQuery or jQuery UI the plugin // will fail before it get's to this test + there is no reason @@ -294,7 +303,7 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. var me = this, Month = 'Month'; $.each(['Min', 'Max'], function(i, type) { me["_set" + type + Month] = function(val) { - if ((me['_' + type + Month] = this._toDate(val)) === false) { + if ((me['_' + type + Month] = this._toMonth(val)) === false) { alert(_badMinMaxVal.replace(/%/, type).replace(/_/, val)); } }; @@ -366,8 +375,8 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. this._validationMessage.hide(); }, - Toggle: function () { - return this._visible ? this.Close() : this.Open(); + Toggle: function (event) { + return this._visible ? this.Close(event) : this.Open(event); }, Open: function (event) { @@ -689,8 +698,8 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. var _minDate = this._MinMonth; var _maxDate = this._MaxMonth; - _minYear = _minDate ? _minDate.getFullYear() : 0; - _maxYear = _maxDate ? _maxDate.getFullYear() : 0; + var _minYear = _minDate ? _toYear(_minDate) : 0; + var _maxYear = _maxDate ? _toYear(_maxDate) : 0; this._prevButton .attr('title', this._i18n('prev5Years')) @@ -725,7 +734,7 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. _onMonthClick: function(event) { this._chooseMonth(event.data.month); - this.Close(); + this.Close(event); }, _onYearClick: function(event) { @@ -754,10 +763,10 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. _ajustYear: function(_opts) { var _year = _opts.StartYear || this.GetSelectedYear() || new Date().getFullYear(); if (this._MinMonth !== null) { - _year = Math.max(this._MinMonth.getFullYear(), _year); + _year = Math.max(_toYear(this._MinMonth), _year); } if (this._MaxMonth !== null) { - _year = Math.min(this._MaxMonth.getFullYear(), _year); + _year = Math.min(_toYear(this._MaxMonth), _year); } this._setPickerYear( _year ); @@ -768,37 +777,32 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. var _minDate = this._MinMonth, _maxDate = this._MaxMonth; - this._prevButton.button('option', 'disabled', _minDate && _curYear == _minDate.getFullYear()); - this._nextButton.button('option', 'disabled', _maxDate && _curYear == _maxDate.getFullYear()); + this._prevButton.button('option', 'disabled', _minDate && _curYear == _toYear(_minDate)); + this._nextButton.button('option', 'disabled', _maxDate && _curYear == _toYear(_maxDate)); for (var i = 0; i < 12; i++) { // Disable the button if the month is not between the // min and max interval. + var _currMonth = ((_curYear * 12) + i); $(this._buttons[i]).button('option', 'disabled', ( - (_minDate && new Date(_curYear, i, 1) < _minDate) || - (_maxDate && new Date(_curYear, i, 0) > _maxDate) + (_minDate && _currMonth < _minDate) || + (_maxDate && _currMonth > _maxDate) )); } }, - _toDate: function(_val) { + _toMonth: function(_val) { if (_val === null) { return _val; } else if (_val instanceof Date) { - _val = new Date(_val.getTime()); - _val.setDate( 0 ); - - return _val; + return _toMonth(_val); } else if ($.isNumeric(_val)) { - var _date = new Date; - _date.setMonth( _date.getMonth() + parseInt(_val, 10) ); - _date.setDate( 0 ); - return _date; + return _toMonth(new Date) + parseInt(_val, 10); } - + var _date = this._parseMonth(_val); if (_date) { - return _date; + return _toMonth(_date); } return this._parsePeriod(_val); @@ -814,19 +818,15 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. _json = _json.replace(/m/i, '":"m"'); try { - var _rev = JSON.parse( '{"' + _json.replace(/ /g, ',"') + '}' ), - obj = {}; + var _rev = JSON.parse( '{"' + _json.replace(/ /g, ',"') + '}' ), obj = {}; for (var key in _rev) { obj[ _rev[key] ] = key; } - var _date = new Date; - - _date.setFullYear( _date.getFullYear() + (parseInt(obj.y, 10) || 0) ); - _date.setMonth( _date.getMonth() + (parseInt(obj.m, 10) || 0) ); - _date.setDate( 0 ); - return _date; + var _month = _toMonth(new Date); + _month += (parseInt(obj.m, 10) || 0); + return _month + (parseInt(obj.y, 10) || 0) * 12; } catch (e) { return false; } @@ -834,5 +834,5 @@ http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. }); // Added in version 2.4. - $.MonthPicker.VERSION = '2.6.1'; + $.MonthPicker.VERSION = '2.6.2'; }(jQuery, window, document)); diff --git a/MonthPicker.min.js b/MonthPicker.min.js index 0e072d6..6aa3a30 100644 --- a/MonthPicker.min.js +++ b/MonthPicker.min.js @@ -1 +1 @@ -!function(a,b,c){function d(b){return a(''+b.i18n.buttonText+"").button({text:!1,icons:{primary:b.ButtonIcon}})}function e(a,b){a.button("option",{icons:{primary:"ui-icon-circle-triangle-"+(b?"w":"e")}})}var f=a.fx.speeds,g=".MonthPicker",h={my:"left top+1",at:"left bottom"},i={my:"right top+1",at:"right bottom"},j="MonthPicker Setup Error: ",k=j+"The jQuery UI position plug-in must be loaded in order to specify a position.",l=j+"Unsupported % option value, supported (case sensitive) values are: ",m=j+'"_" is not a valid %Month value.',n={Animation:["slideToggle","fadeToggle","none"],ShowAnim:["fadeIn","slideDown","none"],HideAnim:["fadeOut","slideUp","none"]},o={ValidationErrorMessage:"_createValidationMessage",Disabled:"_setDisabledState",ShowIcon:"_showIcon",Button:"_createButton",ShowOn:"_updateFieldEvents",IsRTL:"_setRTL",StartYear:"_setPickerYear",MinMonth:"_setMinMonth",MaxMonth:"_setMaxMonth"};if(!(a&&a.ui&&a.ui.button&&a.ui.datepicker))return alert(j+"The jQuery UI button and datepicker plug-ins must be loaded before MonthPicker is called."),!1;var p=a.noop,q=a.datepicker,r=null,s=!!a.ui.position;a.MonthPicker={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 t='
';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:d,OnAfterSetDisabled:p,ButtonIcon:"ui-icon-calculator",OnBeforeMenuOpen:p,OnAfterMenuOpen:p,OnBeforeMenuClose:p,OnAfterMenuClose:p,OnAfterNextYear:p,OnAfterNextYears:p,OnAfterPreviousYear:p,OnAfterPreviousYears:p,OnAfterChooseMonth:p,OnAfterChooseYear:p,OnAfterChooseYears:p,OnAfterChooseMonths:p},_monthPickerButton:a(),_validationMessage:a(),_destroy:function(){var b=this.element;jQuery.mask&&this.options.UseInputMask&&(b.unmask(),this.GetSelectedDate()||b.val("")),b.removeClass("month-year-input").off(g),a(c).off("click"+g+this.uuid),this._monthPickerMenu.remove();var d=this._monthPickerButton.off("click"+g);this._removeOldBtn&&d.remove(),this._validationMessage.remove()},_setOption:function(b,c){switch(b){case"i18n":c=a.extend({},c);break;case"Position":if(!s)return void alert(k);case"MonthFormat":var d=this.GetSelectedDate();d&&this.element.val(this.FormatMonth(d,c))}return b in n&&-1===n[b].indexOf(c)?void alert(l.replace(/%/,b)+n[b]):(this._super(b,c),void(o[b]?this[o[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=j+"MonthPicker can only be called on text or month inputs.";return alert(d+" \n\nSee console (developer tools) for more details."),console.error(d+"\n Caused by:"),console.log(b[0]),!1}if(!a.mask&&c.UseInputMask)return alert(j+"The UseInputMask option is set but the Digital Bush Input Mask jQuery Plugin is not loaded. Get the plugin from http://digitalbush.com/"),!1;if(null!==c.Position&&!s)return alert(k),!1;for(var e in n)if(null!==c[e]&&-1===n[e].indexOf(c[e]))return alert(l.replace(/%/,e)+n[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(t).appendTo(f),a("body").append(f),a(".year-title",f).text(this._i18n("year")),a(".year-container-all",f).attr("title",this._i18n("jumpYears")),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 h=a(".month-picker-month-table",f),i=0;12>i;i++){var o=i%3?o: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 @@ -141,7 +141,7 @@ However this is not supported and might stop working in future releases i
Set the option upon init. -
$('.selector').MonthPicker({ ShowIcon: true });
+ $('.selector').MonthPicker({ Disabled: true });
Get or set the option, after init.
@@ -276,8 +276,8 @@ $('.selector').MonthPicker({
Create a button with different images for enabled and disabled state.
-
-$('.selector').MonthPicker({
+
+$('.selector').MonthPicker({
Button: function(opts) {
var src = 'images/calendar_' + (opts.Disabled ? 'disabled' : 'enabled') + '.gif';
return '<img src="' + src + '" title="Select date" />';
@@ -987,11 +987,11 @@ $('.selector').MonthPicker('option', 'OnAfterChooseYear', function(){ ... } );
Get or set the callback function, after init.
- //getter
- var disabled = $('.selector').MonthPicker('option', 'OnAfterChooseYears');
-
- //setter
- $('.selector').MonthPicker('option', 'OnAfterChooseYears', function(){ ... } );
+//getter
+var disabled = $('.selector').MonthPicker('option', 'OnAfterChooseYears');
+
+//setter
+$('.selector').MonthPicker('option', 'OnAfterChooseYears', function(){ ... } );
diff --git a/demo/Demo.min.js b/demo/Demo.min.js
index b5fd7be..6a07b0e 100644
--- a/demo/Demo.min.js
+++ b/demo/Demo.min.js
@@ -1 +1 @@
-!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){var b,c=navigator.userAgent,d=/iphone/i.test(c),e=/chrome/i.test(c),f=/android/i.test(c);a.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},autoclear:!0,dataName:"rawMaskFn",placeholder:"_"},a.fn.extend({caret:function(a,b){var c;return 0===this.length||this.is(":hidden")?void 0:"number"==typeof a?(b="number"==typeof b?b:a,this.each(function(){this.setSelectionRange?this.setSelectionRange(a,b):this.createTextRange&&(c=this.createTextRange(),c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",a),c.select())})):(this[0].setSelectionRange?(a=this[0].selectionStart,b=this[0].selectionEnd):document.selection&&document.selection.createRange&&(c=document.selection.createRange(),a=0-c.duplicate().moveStart("character",-1e5),b=a+c.text.length),{begin:a,end:b})},unmask:function(){return this.trigger("unmask")},mask:function(c,g){var h,i,j,k,l,m,n,o;if(!c&&this.length>0){h=a(this[0]);var p=h.data(a.mask.dataName);return p?p():void 0}return g=a.extend({autoclear:a.mask.autoclear,placeholder:a.mask.placeholder,completed:null},g),i=a.mask.definitions,j=[],k=n=c.length,l=null,a.each(c.split(""),function(a,b){"?"==b?(n--,k=a):i[b]?(j.push(new RegExp(i[b])),null===l&&(l=j.length-1),k>a&&(m=j.length-1)):j.push(null)}),this.trigger("unmask").each(function(){function h(){if(g.completed){for(var a=l;m>=a;a++)if(j[a]&&C[a]===p(a))return;g.completed.call(B)}}function p(a){return g.placeholder.charAt(a=0&&!j[a];);return a}function s(a,b){var c,d;if(!(0>a)){for(c=a,d=q(b);n>c;c++)if(j[c]){if(!(n>d&&j[c].test(C[d])))break;C[c]=C[d],C[d]=p(d),d=q(d)}z(),B.caret(Math.max(l,a))}}function t(a){var b,c,d,e;for(b=a,c=p(a);n>b;b++)if(j[b]){if(d=q(b),e=C[b],C[b]=c,!(n>d&&j[d].test(e)))break;c=e}}function u(){var a=B.val(),b=B.caret();if(o&&o.length&&o.length>a.length){for(A(!0);b.begin>0&&!j[b.begin-1];)b.begin--;if(0===b.begin)for(;b.beging)&&g&&13!==g){if(i.end-i.begin!==0&&(y(i.begin,i.end),s(i.begin,i.end-1)),c=q(i.begin-1),n>c&&(d=String.fromCharCode(g),j[c].test(d))){if(t(c),C[c]=d,z(),e=q(c),f){var k=function(){a.proxy(a.fn.caret,B,e)()};setTimeout(k,0)}else B.caret(e);i.begin<=m&&h()}b.preventDefault()}}}function y(a,b){var c;for(c=a;b>c&&n>c;c++)j[c]&&(C[c]=p(c))}function z(){B.val(C.join(""))}function A(a){var b,c,d,e=B.val(),f=-1;for(b=0,d=0;n>b;b++)if(j[b]){for(C[b]=p(b);d++e.length){y(b+1,n);break}}else C[b]===e.charAt(d)&&d++,k>b&&(f=b);return a?z():k>f+1?g.autoclear||C.join("")===D?(B.val()&&B.val(""),y(0,n)):z():(z(),B.val(B.val().substring(0,f+1))),k?b:l}var B=a(this),C=a.map(c.split(""),function(a,b){return"?"!=a?i[a]?p(b):a:void 0}),D=C.join(""),E=B.val();B.data(a.mask.dataName,function(){return a.map(C,function(a,b){return j[b]&&a!=p(b)?a:null}).join("")}),B.one("unmask",function(){B.off(".mask").removeData(a.mask.dataName)}).on("focus.mask",function(){if(!B.prop("readonly")){clearTimeout(b);var a;E=B.val(),a=A(),b=setTimeout(function(){B.get(0)===document.activeElement&&(z(),a==c.replace("?","").length?B.caret(0,a):B.caret(a))},10)}}).on("blur.mask",v).on("keydown.mask",w).on("keypress.mask",x).on("input.mask paste.mask",function(){B.prop("readonly")||setTimeout(function(){var a=A(!0);B.caret(a),h()},0)}),e&&f&&B.off("input.mask").on("input.mask",u),A()})}})}),function(a,b,c){function d(b){return a(''+b.i18n.buttonText+"").button({text:!1,icons:{primary:b.ButtonIcon}})}function e(a,b){a.button("option",{icons:{primary:"ui-icon-circle-triangle-"+(b?"w":"e")}})}var f=a.fx.speeds,g=".MonthPicker",h={my:"left top+1",at:"left bottom"},i={my:"right top+1",at:"right bottom"},j="MonthPicker Setup Error: ",k=j+"The jQuery UI position plug-in must be loaded in order to specify a position.",l=j+"Unsupported % option value, supported (case sensitive) values are: ",m=j+'"_" is not a valid %Month value.',n={Animation:["slideToggle","fadeToggle","none"],ShowAnim:["fadeIn","slideDown","none"],HideAnim:["fadeOut","slideUp","none"]},o={ValidationErrorMessage:"_createValidationMessage",Disabled:"_setDisabledState",ShowIcon:"_showIcon",Button:"_createButton",ShowOn:"_updateFieldEvents",IsRTL:"_setRTL",StartYear:"_setPickerYear",MinMonth:"_setMinMonth",MaxMonth:"_setMaxMonth"};if(!(a&&a.ui&&a.ui.button&&a.ui.datepicker))return alert(j+"The jQuery UI button and datepicker plug-ins must be loaded before MonthPicker is called."),!1;var p=a.noop,q=a.datepicker,r=null,s=!!a.ui.position;a.MonthPicker={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 t='';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:d,OnAfterSetDisabled:p,ButtonIcon:"ui-icon-calculator",OnBeforeMenuOpen:p,OnAfterMenuOpen:p,OnBeforeMenuClose:p,OnAfterMenuClose:p,OnAfterNextYear:p,OnAfterNextYears:p,OnAfterPreviousYear:p,OnAfterPreviousYears:p,OnAfterChooseMonth:p,OnAfterChooseYear:p,OnAfterChooseYears:p,OnAfterChooseMonths:p},_monthPickerButton:a(),_validationMessage:a(),_destroy:function(){var b=this.element;jQuery.mask&&this.options.UseInputMask&&(b.unmask(),this.GetSelectedDate()||b.val("")),b.removeClass("month-year-input").off(g),a(c).off("click"+g+this.uuid),this._monthPickerMenu.remove();var d=this._monthPickerButton.off("click"+g);this._removeOldBtn&&d.remove(),this._validationMessage.remove()},_setOption:function(b,c){switch(b){case"i18n":c=a.extend({},c);break;case"Position":if(!s)return void alert(k);case"MonthFormat":var d=this.GetSelectedDate();d&&this.element.val(this.FormatMonth(d,c))}return b in n&&-1===n[b].indexOf(c)?void alert(l.replace(/%/,b)+n[b]):(this._super(b,c),void(o[b]?this[o[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=j+"MonthPicker can only be called on text or month inputs.";return alert(d+" \n\nSee console (developer tools) for more details."),console.error(d+"\n Caused by:"),console.log(b[0]),!1}if(!a.mask&&c.UseInputMask)return alert(j+"The UseInputMask option is set but the Digital Bush Input Mask jQuery Plugin is not loaded. Get the plugin from http://digitalbush.com/"),!1;if(null!==c.Position&&!s)return alert(k),!1;for(var e in n)if(null!==c[e]&&-1===n[e].indexOf(c[e]))return alert(l.replace(/%/,e)+n[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(t).appendTo(f),a("body").append(f),a(".year-title",f).text(this._i18n("year")),a(".year-container-all",f).attr("title",this._i18n("jumpYears")),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 h=a(".month-picker-month-table",f),i=0;12>i;i++){var o=i%3?o:a(" ").appendTo(h);o.append(' ')}this._buttons=a("button",h).button(),a(".year-container-all",f).click(a.proxy(this._showYearsClickHandler,this)),f.on("click"+g,function(a){return!1});var p=this,q="Month";a.each(["Min","Max"],function(a,b){p["_set"+b+q]=function(a){(p["_"+b+q]=this._toDate(a))===!1&&alert(m.replace(/%/,b).replace(/_/,a))},p._setOption(b+q,p.options[b+q])}),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[a?"hide":"show"](),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]=p)},Clear:function(){this.element.val(""),this._validationMessage.hide()},Toggle:function(){return this._visible?this.Close():this.Open()},Open:function(b){if(!this.options.Disabled&&!this._visible){var d=this.element,e=this.options;if(b=b||new a.Event,e.OnBeforeMenuOpen.call(d[0],b)===!1||b.isDefaultPrevented())return!1;this._visible=!0,this._ajustYear(e),r&&r.Close(b),r=this;var f=this._monthPickerMenu;this._showMonths(),a(c).on("click"+g+this.uuid,a.proxy(this.Close,this)).on("keydown"+g+this.uuid,a.proxy(this._keyDown,this)),d.off("blur"+g).focus();var h=e.ShowAnim||e.Animation,i="none"===h;f[i?"fadeIn":h]({duration:i?0:this._duration(),start:a.proxy(this._position,this,f),complete:a.proxy(e.OnAfterMenuOpen,d[0])})}return!1},Close:function(b){if(this._visible){var d=this._monthPickerMenu,e=this.options,f=this.element;if(b=b||new a.Event,e.OnBeforeMenuClose.call(f[0],b)===!1||b.isDefaultPrevented())return;this._visible=!1,r=null,a(c).off("keydown"+g+this.uuid).off("click"+g+this.uuid),this.Validate(),f.on("blur"+g,a.proxy(this.Validate,this));var h=a.proxy(e.OnAfterMenuClose,f[0]),i=e.HideAnim||e.Animation;"none"===i?d.hide(0,h):d[i](this._duration(),h)}},SetDisabled:function(a,b){try{b.button("option","disabled",a)}catch(c){b.prop("disabled",a)}},MonthInputFormat:"yy-mm",ParseMonth:function(a,b){try{return q.parseDate("dd"+b,"01"+a)}catch(c){return null}},FormatMonth:function(a,b){try{return q.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[this.options.ShowIcon?"show":"hide"]():this._createButton(),this._updateFieldEvents()},_createButton:function(){if(this.options.ShowIcon){var b=this._monthPickerButton.off(g),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("click"+g,a.proxy(this.Toggle,this)),this._removeOldBtn&&b.remove(),this._removeOldBtn=f}},_updateFieldEvents:function(){this.element.off("click"+g),"both"!==this.options.ShowOn&&this._monthPickerButton.length||this.element.on("click"+g,a.proxy(this.Open,this))},_createValidationMessage:function(){var b=this.options.ValidationErrorMessage,c=this.element;if(-1===[null,""].indexOf(b)){var d=a('"),e=this._monthPickerButton;this._validationMessage=d.insertAfter(e.length?e:c),c.on("blur"+g,a.proxy(this.Validate,this))}else this._validationMessage.remove()},_setRTL:function(a){e(this._prevButton,!a),e(this._nextButton,a)},_keyDown:function(){var b=a.ui.keyCode;switch(event.keyCode){case b.ENTER:this._chooseMonth((new Date).getMonth()+1),this.Close();break;case b.ESCAPE:this.Close()}},_duration:function(){var b=this.options.Duration;return a.isNumeric(b)?b:b in f?f[b]:f._default},_position:s?function(b){var c=this.options.IsRTL?i:h,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 Date).replace(/\d/g,9)):this.element.unmask()}catch(a){}},_setDisabledState:function(){var a=this.options.Disabled;this.element[0].disabled=a,this.element[a?"addClass":"removeClass"]("disabled"),a&&this._validationMessage.hide(),this.Close(),this._createButton(),this.SetDisabled(a,this._monthPickerButton),this.options.OnAfterSetDisabled.call(this.element[0],a)},_getPickerYear:function(){return parseInt(this._yearContainer.text(),10)},_setPickerYear:function(a){this._yearContainer.text(a||(new Date).getFullYear())},_chooseMonth:function(a){var b=new Date(this._getPickerYear(),a-1);this.element.val(this._formatMonth(b)).blur(),this.options.OnAfterChooseMonth.call(this.element[0])},_chooseYear:function(a){this._setPickerYear(a),this._showMonths(),this.options.OnAfterChooseYear.call(this.element[0])},_showMonths:function(){var b=this._i18n("months");this._prevButton.attr("title",this._i18n("prevYear")).off("click"+g).on("click"+g,a.proxy(this._addToYear,this,-1)),this._nextButton.attr("title",this._i18n("nextYear")).off("click"+g).on("click"+g,a.proxy(this._addToYear,this,1)),a(".year-container-all",this._monthPickerMenu).css("cursor","pointer"),this._buttons.off(g);var c=this,d=a.proxy(c._onMonthClick,c);a.each(b,function(b,e){a(c._buttons[b]).on("click"+g,{month:b+1},d).button("option","label",e)}),this._enableMonthButtons()},_showYearsClickHandler:function(){this._showYears(),this.options.OnAfterChooseYears.call(this.element[0])},_showYears:function(){var b=this._getPickerYear(),c=-4,d=b+c,e=5,f=this._MinMonth,h=this._MaxMonth;_minYear=f?f.getFullYear():0,_maxYear=h?h.getFullYear():0,this._prevButton.attr("title",this._i18n("prev5Years")).off("click"+g).on("click"+g,a.proxy(this._addToYears,this,-e)).button("option","disabled",_minYear&&d-1<_minYear),this._nextButton.attr("title",this._i18n("next5Years")).off("click"+g).on("click"+g,a.proxy(this._addToYears,this,e)).button("option","disabled",_maxYear&&d+12-1>_maxYear),a(".year-container-all",this._monthPickerMenu).css("cursor","default"),this._buttons.off(g);for(var i=a.proxy(this._onYearClick,this),j=0;12>j;j++){var k=b+c,l=a(this._buttons[j]);l.on("click"+g,{year:k},i).button("option","label",k),a(this._buttons[j]).button("option","disabled",_minYear&&k<_minYear||_maxYear&&k>_maxYear),c++}},_onMonthClick:function(a){this._chooseMonth(a.data.month),this.Close()},_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._enableMonthButtons(),this.options["OnAfter"+(a>0?"Next":"Previous")+"Year"].call(this.element[0])},_addToYears:function(a){var b=this._yearContainer;b.text(parseInt(b.text())+a,10),this._showYears(),this.element.focus(),this.options["OnAfter"+(a>0?"Next":"Previous")+"Years"].call(this.element[0])},_ajustYear:function(a){var b=a.StartYear||this.GetSelectedYear()||(new Date).getFullYear();null!==this._MinMonth&&(b=Math.max(this._MinMonth.getFullYear(),b)),null!==this._MaxMonth&&(b=Math.min(this._MaxMonth.getFullYear(),b)),this._setPickerYear(b)},_enableMonthButtons:function(){var b=this._getPickerYear(),c=this._MinMonth,d=this._MaxMonth;this._prevButton.button("option","disabled",c&&b==c.getFullYear()),this._nextButton.button("option","disabled",d&&b==d.getFullYear());for(var e=0;12>e;e++)a(this._buttons[e]).button("option","disabled",c&&new Date(b,e,1)d)},_toDate:function(b){if(null===b)return b;if(b instanceof Date)return b=new Date(b.getTime()),b.setDate(0),b;if(a.isNumeric(b)){var c=new Date;return c.setMonth(c.getMonth()+parseInt(b,10)),c.setDate(0),c}var c=this._parseMonth(b);return c?c:this._parsePeriod(b)},_parsePeriod:function(a,b){var c=a.trim();c=c.replace(/y/i,'":"y"'),c=c.replace(/m/i,'":"m"');try{var d=JSON.parse('{"'+c.replace(/ /g,',"')+"}"),e={};for(var f in d)e[d[f]]=f;var g=new Date;return g.setFullYear(g.getFullYear()+(parseInt(e.y,10)||0)),g.setMonth(g.getMonth()+(parseInt(e.m,10)||0)),g.setDate(0),g}catch(h){return!1}}}),a.MonthPicker.VERSION="2.6.1"}(jQuery,window,document);
\ No newline at end of file
+!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){var b,c=navigator.userAgent,d=/iphone/i.test(c),e=/chrome/i.test(c),f=/android/i.test(c);a.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},autoclear:!0,dataName:"rawMaskFn",placeholder:"_"},a.fn.extend({caret:function(a,b){var c;return 0===this.length||this.is(":hidden")?void 0:"number"==typeof a?(b="number"==typeof b?b:a,this.each(function(){this.setSelectionRange?this.setSelectionRange(a,b):this.createTextRange&&(c=this.createTextRange(),c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",a),c.select())})):(this[0].setSelectionRange?(a=this[0].selectionStart,b=this[0].selectionEnd):document.selection&&document.selection.createRange&&(c=document.selection.createRange(),a=0-c.duplicate().moveStart("character",-1e5),b=a+c.text.length),{begin:a,end:b})},unmask:function(){return this.trigger("unmask")},mask:function(c,g){var h,i,j,k,l,m,n,o;if(!c&&this.length>0){h=a(this[0]);var p=h.data(a.mask.dataName);return p?p():void 0}return g=a.extend({autoclear:a.mask.autoclear,placeholder:a.mask.placeholder,completed:null},g),i=a.mask.definitions,j=[],k=n=c.length,l=null,a.each(c.split(""),function(a,b){"?"==b?(n--,k=a):i[b]?(j.push(new RegExp(i[b])),null===l&&(l=j.length-1),k>a&&(m=j.length-1)):j.push(null)}),this.trigger("unmask").each(function(){function h(){if(g.completed){for(var a=l;m>=a;a++)if(j[a]&&C[a]===p(a))return;g.completed.call(B)}}function p(a){return g.placeholder.charAt(a=0&&!j[a];);return a}function s(a,b){var c,d;if(!(0>a)){for(c=a,d=q(b);n>c;c++)if(j[c]){if(!(n>d&&j[c].test(C[d])))break;C[c]=C[d],C[d]=p(d),d=q(d)}z(),B.caret(Math.max(l,a))}}function t(a){var b,c,d,e;for(b=a,c=p(a);n>b;b++)if(j[b]){if(d=q(b),e=C[b],C[b]=c,!(n>d&&j[d].test(e)))break;c=e}}function u(){var a=B.val(),b=B.caret();if(o&&o.length&&o.length>a.length){for(A(!0);b.begin>0&&!j[b.begin-1];)b.begin--;if(0===b.begin)for(;b.beging)&&g&&13!==g){if(i.end-i.begin!==0&&(y(i.begin,i.end),s(i.begin,i.end-1)),c=q(i.begin-1),n>c&&(d=String.fromCharCode(g),j[c].test(d))){if(t(c),C[c]=d,z(),e=q(c),f){var k=function(){a.proxy(a.fn.caret,B,e)()};setTimeout(k,0)}else B.caret(e);i.begin<=m&&h()}b.preventDefault()}}}function y(a,b){var c;for(c=a;b>c&&n>c;c++)j[c]&&(C[c]=p(c))}function z(){B.val(C.join(""))}function A(a){var b,c,d,e=B.val(),f=-1;for(b=0,d=0;n>b;b++)if(j[b]){for(C[b]=p(b);d++e.length){y(b+1,n);break}}else C[b]===e.charAt(d)&&d++,k>b&&(f=b);return a?z():k>f+1?g.autoclear||C.join("")===D?(B.val()&&B.val(""),y(0,n)):z():(z(),B.val(B.val().substring(0,f+1))),k?b:l}var B=a(this),C=a.map(c.split(""),function(a,b){return"?"!=a?i[a]?p(b):a:void 0}),D=C.join(""),E=B.val();B.data(a.mask.dataName,function(){return a.map(C,function(a,b){return j[b]&&a!=p(b)?a:null}).join("")}),B.one("unmask",function(){B.off(".mask").removeData(a.mask.dataName)}).on("focus.mask",function(){if(!B.prop("readonly")){clearTimeout(b);var a;E=B.val(),a=A(),b=setTimeout(function(){B.get(0)===document.activeElement&&(z(),a==c.replace("?","").length?B.caret(0,a):B.caret(a))},10)}}).on("blur.mask",v).on("keydown.mask",w).on("keypress.mask",x).on("input.mask paste.mask",function(){B.prop("readonly")||setTimeout(function(){var a=A(!0);B.caret(a),h()},0)}),e&&f&&B.off("input.mask").on("input.mask",u),A()})}})}),function(a,b,c){"use strict";function d(a){return a.getMonth()+12*a.getFullYear()}function e(a){return Math.floor(a/12)}function f(b){return a(''+b.i18n.buttonText+"").button({text:!1,icons:{primary:b.ButtonIcon}})}function g(a,b){a.button("option",{icons:{primary:"ui-icon-circle-triangle-"+(b?"w":"e")}})}var h=a.fx.speeds,i=".MonthPicker",j={my:"left top+1",at:"left bottom"},k={my:"right top+1",at:"right bottom"},l="MonthPicker Setup Error: ",m=l+"The jQuery UI position plug-in must be loaded in order to specify a position.",n=l+"Unsupported % option value, supported (case sensitive) values are: ",o=l+'"_" is not a valid %Month value.',p={Animation:["slideToggle","fadeToggle","none"],ShowAnim:["fadeIn","slideDown","none"],HideAnim:["fadeOut","slideUp","none"]},q={ValidationErrorMessage:"_createValidationMessage",Disabled:"_setDisabledState",ShowIcon:"_showIcon",Button:"_createButton",ShowOn:"_updateFieldEvents",IsRTL:"_setRTL",StartYear:"_setPickerYear",MinMonth:"_setMinMonth",MaxMonth:"_setMaxMonth"};if(!(a&&a.ui&&a.ui.button&&a.ui.datepicker))return alert(l+"The jQuery UI button and datepicker plug-ins must be loaded before MonthPicker is called."),!1;var r=a.noop,s=a.datepicker,t=null,u=!!a.ui.position;a.MonthPicker={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 v='';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:f,OnAfterSetDisabled:r,ButtonIcon:"ui-icon-calculator",OnBeforeMenuOpen:r,OnAfterMenuOpen:r,OnBeforeMenuClose:r,OnAfterMenuClose:r,OnAfterNextYear:r,OnAfterNextYears:r,OnAfterPreviousYear:r,OnAfterPreviousYears:r,OnAfterChooseMonth:r,OnAfterChooseYear:r,OnAfterChooseYears:r,OnAfterChooseMonths:r},_monthPickerButton:a(),_validationMessage:a(),_destroy:function(){var b=this.element;jQuery.mask&&this.options.UseInputMask&&(b.unmask(),this.GetSelectedDate()||b.val("")),b.removeClass("month-year-input").off(i),a(c).off("click"+i+this.uuid),this._monthPickerMenu.remove();var d=this._monthPickerButton.off("click"+i);this._removeOldBtn&&d.remove(),this._validationMessage.remove()},_setOption:function(b,c){switch(b){case"i18n":c=a.extend({},c);break;case"Position":if(!u)return void alert(m);case"MonthFormat":var d=this.GetSelectedDate();d&&this.element.val(this.FormatMonth(d,c))}return b in p&&-1===p[b].indexOf(c)?void alert(n.replace(/%/,b)+p[b]):(this._super(b,c),void(q[b]?this[q[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=l+"MonthPicker can only be called on text or month inputs.";return alert(d+" \n\nSee console (developer tools) for more details."),console.error(d+"\n Caused by:"),console.log(b[0]),!1}if(!a.mask&&c.UseInputMask)return alert(l+"The UseInputMask option is set but the Digital Bush Input Mask jQuery Plugin is not loaded. Get the plugin from http://digitalbush.com/"),!1;if(null!==c.Position&&!u)return alert(m),!1;for(var e in p)if(null!==c[e]&&-1===p[e].indexOf(c[e]))return alert(n.replace(/%/,e)+p[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(v).appendTo(f),a("body").append(f),a(".year-title",f).text(this._i18n("year")),a(".year-container-all",f).attr("title",this._i18n("jumpYears")),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 j=h%3?j:a(" ").appendTo(g);j.append(' ')}this._buttons=a("button",g).button(),a(".year-container-all",f).click(a.proxy(this._showYearsClickHandler,this)),f.on("click"+i,function(a){return!1});var k=this,q="Month";a.each(["Min","Max"],function(a,b){k["_set"+b+q]=function(a){(k["_"+b+q]=this._toMonth(a))===!1&&alert(o.replace(/%/,b).replace(/_/,a))},k._setOption(b+q,k.options[b+q])}),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[a?"hide":"show"](),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]=r)},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,e.OnBeforeMenuOpen.call(d[0],b)===!1||b.isDefaultPrevented())return!1;this._visible=!0,this._ajustYear(e),t&&t.Close(b),t=this;var f=this._monthPickerMenu;this._showMonths(),a(c).on("click"+i+this.uuid,a.proxy(this.Close,this)).on("keydown"+i+this.uuid,a.proxy(this._keyDown,this)),d.off("blur"+i).focus();var g=e.ShowAnim||e.Animation,h="none"===g;f[h?"fadeIn":g]({duration:h?0:this._duration(),start:a.proxy(this._position,this,f),complete:a.proxy(e.OnAfterMenuOpen,d[0])})}return!1},Close:function(b){if(this._visible){var d=this._monthPickerMenu,e=this.options,f=this.element;if(b=b||new a.Event,e.OnBeforeMenuClose.call(f[0],b)===!1||b.isDefaultPrevented())return;this._visible=!1,t=null,a(c).off("keydown"+i+this.uuid).off("click"+i+this.uuid),this.Validate(),f.on("blur"+i,a.proxy(this.Validate,this));var g=a.proxy(e.OnAfterMenuClose,f[0]),h=e.HideAnim||e.Animation;"none"===h?d.hide(0,g):d[h](this._duration(),g)}},SetDisabled:function(a,b){try{b.button("option","disabled",a)}catch(c){b.prop("disabled",a)}},MonthInputFormat:"yy-mm",ParseMonth:function(a,b){try{return s.parseDate("dd"+b,"01"+a)}catch(c){return null}},FormatMonth:function(a,b){try{return s.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[this.options.ShowIcon?"show":"hide"]():this._createButton(),this._updateFieldEvents()},_createButton:function(){if(this.options.ShowIcon){var b=this._monthPickerButton.off(i),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("click"+i,a.proxy(this.Toggle,this)),this._removeOldBtn&&b.remove(),this._removeOldBtn=f}},_updateFieldEvents:function(){this.element.off("click"+i),"both"!==this.options.ShowOn&&this._monthPickerButton.length||this.element.on("click"+i,a.proxy(this.Open,this))},_createValidationMessage:function(){var b=this.options.ValidationErrorMessage,c=this.element;if(-1===[null,""].indexOf(b)){var d=a('"),e=this._monthPickerButton;this._validationMessage=d.insertAfter(e.length?e:c),c.on("blur"+i,a.proxy(this.Validate,this))}else this._validationMessage.remove()},_setRTL:function(a){g(this._prevButton,!a),g(this._nextButton,a)},_keyDown:function(){var b=a.ui.keyCode;switch(event.keyCode){case b.ENTER:this._chooseMonth((new Date).getMonth()+1),this.Close();break;case b.ESCAPE:this.Close()}},_duration:function(){var b=this.options.Duration;return a.isNumeric(b)?b:b in h?h[b]:h._default},_position:u?function(b){var c=this.options.IsRTL?k:j,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 Date).replace(/\d/g,9)):this.element.unmask()}catch(a){}},_setDisabledState:function(){var a=this.options.Disabled;this.element[0].disabled=a,this.element[a?"addClass":"removeClass"]("disabled"),a&&this._validationMessage.hide(),this.Close(),this._createButton(),this.SetDisabled(a,this._monthPickerButton),this.options.OnAfterSetDisabled.call(this.element[0],a)},_getPickerYear:function(){return parseInt(this._yearContainer.text(),10)},_setPickerYear:function(a){this._yearContainer.text(a||(new Date).getFullYear())},_chooseMonth:function(a){var b=new Date(this._getPickerYear(),a-1);this.element.val(this._formatMonth(b)).blur(),this.options.OnAfterChooseMonth.call(this.element[0])},_chooseYear:function(a){this._setPickerYear(a),this._showMonths(),this.options.OnAfterChooseYear.call(this.element[0])},_showMonths:function(){var b=this._i18n("months");this._prevButton.attr("title",this._i18n("prevYear")).off("click"+i).on("click"+i,a.proxy(this._addToYear,this,-1)),this._nextButton.attr("title",this._i18n("nextYear")).off("click"+i).on("click"+i,a.proxy(this._addToYear,this,1)),a(".year-container-all",this._monthPickerMenu).css("cursor","pointer"),this._buttons.off(i);var c=this,d=a.proxy(c._onMonthClick,c);a.each(b,function(b,e){a(c._buttons[b]).on("click"+i,{month:b+1},d).button("option","label",e)}),this._enableMonthButtons()},_showYearsClickHandler:function(){this._showYears(),this.options.OnAfterChooseYears.call(this.element[0])},_showYears:function(){var b=this._getPickerYear(),c=-4,d=b+c,f=5,g=this._MinMonth,h=this._MaxMonth,j=g?e(g):0,k=h?e(h):0;this._prevButton.attr("title",this._i18n("prev5Years")).off("click"+i).on("click"+i,a.proxy(this._addToYears,this,-f)).button("option","disabled",j&&j>d-1),this._nextButton.attr("title",this._i18n("next5Years")).off("click"+i).on("click"+i,a.proxy(this._addToYears,this,f)).button("option","disabled",k&&d+12-1>k),a(".year-container-all",this._monthPickerMenu).css("cursor","default"),this._buttons.off(i);for(var l=a.proxy(this._onYearClick,this),m=0;12>m;m++){var n=b+c,o=a(this._buttons[m]);o.on("click"+i,{year:n},l).button("option","label",n),a(this._buttons[m]).button("option","disabled",j&&j>n||k&&n>k),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._enableMonthButtons(),this.options["OnAfter"+(a>0?"Next":"Previous")+"Year"].call(this.element[0])},_addToYears:function(a){var b=this._yearContainer;b.text(parseInt(b.text())+a,10),this._showYears(),this.element.focus(),this.options["OnAfter"+(a>0?"Next":"Previous")+"Years"].call(this.element[0])},_ajustYear:function(a){var b=a.StartYear||this.GetSelectedYear()||(new Date).getFullYear();null!==this._MinMonth&&(b=Math.max(e(this._MinMonth),b)),null!==this._MaxMonth&&(b=Math.min(e(this._MaxMonth),b)),this._setPickerYear(b)},_enableMonthButtons:function(){var b=this._getPickerYear(),c=this._MinMonth,d=this._MaxMonth;this._prevButton.button("option","disabled",c&&b==e(c)),this._nextButton.button("option","disabled",d&&b==e(d));for(var f=0;12>f;f++){var g=12*b+f;a(this._buttons[f]).button("option","disabled",c&&c>g||d&&g>d)}},_toMonth:function(b){if(null===b)return b;if(b instanceof Date)return d(b);if(a.isNumeric(b))return d(new Date)+parseInt(b,10);var c=this._parseMonth(b);return c?d(c):this._parsePeriod(b)},_parsePeriod:function(a,b){var c=a.trim();c=c.replace(/y/i,'":"y"'),c=c.replace(/m/i,'":"m"');try{var e=JSON.parse('{"'+c.replace(/ /g,',"')+"}"),f={};for(var g in e)f[e[g]]=g;var h=d(new Date);return h+=parseInt(f.m,10)||0,h+12*(parseInt(f.y,10)||0)}catch(i){return!1}}}),a.MonthPicker.VERSION="2.6.2"}(jQuery,window,document);
\ No newline at end of file
diff --git a/test/test.html b/test/test.html
index 69ebc68..d0bcbf2 100644
--- a/test/test.html
+++ b/test/test.html
@@ -55,9 +55,7 @@ Version @VERSION
- Button Demonstration
-
-
This demonstrates the plugin's default behaviour.
+
Button test
Choose a Month:
@@ -76,12 +74,31 @@
Version @VERSION
No button:
+
+
ShowOn both:
+
Month format test Choose a Month:
+ Min/MaxMonth test Choose a Month:
+
+
+
+ Right to left Choose a Month:
+
+
+
+ Toggle method test Choose a Month:
+
+
+
+ Events Choose a Month:
+
+
+
Only one picker open test First picker:
Second picker:
@@ -163,14 +180,6 @@
Version @VERSION
- jQuery UI Dialog Integration Demonstration
-
-
This demonstrates the Month Picker running inside of the jQuery UI Modal Dialog.
-
-
-
-
-
HTML 5 Month Input Type Support
This demonstrates how the MonthPicker will work with the HTML 5 Month Input Type. View this section using Chrome
@@ -184,10 +193,6 @@
Version @VERSION
- Test:
-
-
-
qUnit Testing Output
diff --git a/test/test.js b/test/test.js
index 3daec33..6cb846b 100644
--- a/test/test.js
+++ b/test/test.js
@@ -270,16 +270,6 @@ QUnit.test('API Tests', function (assert) {
assert.equal(_picker.prop('disabled'), true, '#EnableDisableDemo was disabled using the Disable() API call.');
_picker.MonthPicker('Enable');
assert.equal(_picker.prop('disabled'), false, '#EnableDisableDemo was enabled using the Disable() API call.');
-
- _picker = $('#DialogDemo').MonthPicker();
-
- $('#Modal').dialog({
- autoOpen: false,
- title: 'MonthPicker Dialog Test',
- modal: true
- });
-
- assert.ok($('#MonthPicker_DialogDemo').length === 1, '#DialogDemo initialized, manually test the MonthPicker behavior in the dialog.');
});
QUnit.test('Digital Bush Tests', function (assert) {
@@ -346,6 +336,195 @@ QUnit.test('MonthFormat Option Tests', function (assert) {
assert.equal($(FormatField).val(), 'April 2012', 'The text field has the value April 2012');
});
+// 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(27);
+
+ var field = $(EventsField).MonthPicker({
+ Animation: 'none', // Disable animation to make sure opening and closing the menu is synchronous.
+ ShowOn: 'both'
+ });
+
+ var menu = $(MonthPicker_EventsField);
+ var OnBeforeMenuOpenTriggred = false;
+ // This event should be triggered twice, the first time it is prevented
+ // and the sceond time it goes through.
+ field.MonthPicker('option', 'OnBeforeMenuOpen', function(event) {
+ OnBeforeMenuOpenTriggred = true;
+ assert.equal( this, EventsField, 'OnBeforeMenuOpen was called in the right context' );
+
+ // Prevent opening if the event was triggered on the input field.
+ if (event.target === EventsField) {
+ event.preventDefault();
+ }
+ });
+
+ // Make sure the open event triggered by clicking the field was prevented.
+ field.trigger('click');
+ assert.ok(OnBeforeMenuOpenTriggred, 'The OnBeforeMenuOpen event was triggered');
+ assert.notOk( menu.is(':visible'), 'The open event was prevented when clicking on the field' );
+
+ var OnAfterMenuOpenTriggred = false;
+ field.MonthPicker('option', 'OnAfterMenuOpen', function() {
+ OnAfterMenuOpenTriggred = true;
+ assert.equal( this, EventsField, 'OnAfterMenuOpen was called in the right context' );
+ });
+
+ // Make sure calling the open method doesn't get prevented.
+ field.MonthPicker('Open');
+ assert.ok(OnAfterMenuOpenTriggred, 'The OnAfterMenuOpen event was triggered');
+ assert.ok( menu.is(':visible'), 'The menu was opend by calling the Open method' );
+
+ // Start duplicate code
+ var OnAfterNextYearTriggered = false;
+ field.MonthPicker('option', 'OnAfterNextYear', function() {
+ OnAfterNextYearTriggered = true;
+
+ assert.equal( this, EventsField, 'OnAfterNextYear was called in the right context' );
+ });
+
+ var nextYearButton = menu.find('.next-year>button');
+ nextYearButton.trigger('click');
+ assert.ok(OnAfterNextYearTriggered, 'Clicking the next button triggered OnAfterNextYear');
+
+ var OnAfterPreviousYearTriggerd = false;
+ field.MonthPicker('option', 'OnAfterPreviousYear', function() {
+ OnAfterPreviousYearTriggerd = true;
+
+ assert.equal( this, EventsField, 'OnAfterPreviousYear was called in the right context' );
+ });
+
+ var previousYearButton = menu.find('.previous-year>button');
+ previousYearButton.trigger('click');
+ assert.ok(OnAfterPreviousYearTriggerd, 'Clciking rhe previous button triggered OnAfterPreviousYear');
+
+ var OnAfterChooseYearsTriggerd = false;
+ field.MonthPicker('option', 'OnAfterChooseYears', function() {
+ OnAfterChooseYearsTriggerd = true;
+ assert.equal( this, EventsField, 'OnAfterChooseYears was called in the right context' );
+ });
+
+ var showYearsButton = menu.find('.year-container-all');
+ showYearsButton.trigger('click');
+
+ assert.ok(OnAfterChooseYearsTriggerd, 'Clicking the show years button triggered OnAfterChooseYears');
+
+ var OnAfterNextYearsTriggered = false;
+ field.MonthPicker('option', 'OnAfterNextYears', function() {
+ OnAfterNextYearsTriggered = true;
+ assert.equal( this, EventsField, 'OnAfterNextYears was called in the right context' );
+ });
+
+ nextYearButton.trigger('click');
+ assert.ok(OnAfterChooseYearsTriggerd, 'Clicking the next button triggered the OnAfterNextYears event');
+
+ var OnAfterPreviousYearsTriggered = false;
+ field.MonthPicker('option', 'OnAfterPreviousYears', function() {
+ OnAfterPreviousYearsTriggered = true;
+ assert.equal( this, EventsField, 'OnAfterPreviousYears was called in the right context' );
+ });
+
+ previousYearButton.trigger('click');
+ assert.ok(OnAfterPreviousYearsTriggered, 'Clicking the prev button triggered the OnAfterPreviousYears event');
+
+ var OnAfterChooseYearTriggered = false;
+ field.MonthPicker('option', 'OnAfterChooseYear', function() {
+ OnAfterChooseYearTriggered = true;
+ assert.equal( this, EventsField, 'OnAfterChooseYear was called in the right context' );
+ });
+
+ menu.find('.button-1').trigger('click');
+ assert.ok(OnAfterChooseYearTriggered, 'Clicking a year triggered OnAfterChooseYear');
+
+ var OnAfterChooseMonthTriggered = false;
+ field.MonthPicker('option', 'OnAfterChooseMonth', function() {
+ OnAfterChooseMonthTriggered = true;
+ assert.equal( this, EventsField, 'OnAfterChooseMonth was called in the right context' );
+ });
+ // End duplicate code
+
+ // This event should be triggered twice, the first time it is prevented
+ // and the sceond time it goes through.
+ field.MonthPicker('option', 'OnBeforeMenuClose', function(event) {
+ assert.equal( this, EventsField, 'OnBeforeMenuClose was called in the right context' );
+
+ var target = event.target, btn1 = menu.find('.button-1')[0];
+ if (event.target === btn1) {
+ event.preventDefault();
+ }
+ });
+
+ // Click January which should triger the OnAfterChooseMonth event
+ // but the OnBeforeMenuClose will be prevented.
+ menu.find('.button-1').trigger('click');
+ assert.ok(OnAfterChooseMonthTriggered, 'Clicking January triggered OnAfterChooseMonth');
+ assert.ok( menu.is(':visible'), 'The close event was canceled' );
+ field.MonthPicker('option', 'OnAfterChooseMonth', $.noop);
+
+ var OnAfterMenuCloseTriggered = false;
+ field.MonthPicker('option', 'OnAfterMenuClose', function(event) {
+ OnAfterMenuCloseTriggered = true;
+ assert.equal( this, EventsField, 'OnAfterMenuClose was called in the right context' );
+ });
+
+ // Clicking May should not be prevented.
+ menu.find('.button-5').trigger('click');
+ assert.ok( !menu.is(':visible'), 'Clicking May closed the menu' );
+ assert.ok(OnAfterMenuCloseTriggered, 'Clicking May triggered the OnAfterMenuClose event');
+
+ field.MonthPicker('ClearAllCallbacks');
+});
+
+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.
+ Position: {collision: 'none'}, // Ensure the menu opens to the right.
+ IsRTL: true
+ });
+
+ field.MonthPicker('Open');
+
+ var menu = $(MonthPicker_RTLField);
+
+ var nextYearButton = menu.find('.next-year>button');
+ var previousYearButton = menu.find('.previous-year>button');
+
+ // Make sure the buttons are pointing in the right (opposite) direction.
+ assert.ok(previousYearButton.find('span.ui-icon-circle-triangle-e').length, 'Previous button is pointed east');
+ assert.ok(nextYearButton.find('span.ui-icon-circle-triangle-w').length, 'Next button is pointed west');
+
+ // Make sure the menu opens to the right of the field.
+ var opendToTheRight = (field.position().left - menu.position().left) > 100;
+ assert.ok(opendToTheRight, 'The menu opened to the right of rhe field');
+
+ field.MonthPicker('Close');
+});
+
+QUnit.test('Toggle method', function (assert) {
+ var field = $(ToggleField).MonthPicker({
+ Animation: 'none', // Disable animation to make sure opening and closing the menu is synchronous.
+ });
+
+ field.MonthPicker('Toggle');
+
+ var menu = $(MonthPicker_ToggleField);
+
+ assert.ok(menu.is(':visible'), 'The menu was opened');
+
+ field.MonthPicker('Toggle');
+
+ assert.ok(!menu.is(':visible'), 'The menu was closed');
+
+ field.MonthPicker('Toggle');
+
+ assert.ok(menu.is(':visible'), 'The menu was again');
+
+ field.MonthPicker('Close');
+});
+
QUnit.module("Button option");
QUnit.test('Plain HTML Button test', function (assert) {
@@ -561,3 +740,447 @@ QUnit.test('Disable button', function (assert) {
$(NoButtonField).MonthPicker('ClearAllCallbacks');
$(NoButtonField).MonthPicker('Close');
});
+
+QUnit.test('ShowOn both', function (assert) {
+ var field = $(ShowOnBothField).MonthPicker({
+ Animation: 'none', // Disable animation to make sure opening and closing the menu is synchronous.
+ Button: '',
+ ShowOn: 'both'
+ });
+
+ field.trigger('click');
+
+ var menu = $(MonthPicker_ShowOnBothField);
+
+ assert.ok(menu.is(':visible'), 'The menu was opened by clicking on the input field');
+
+ field.MonthPicker('Close');
+
+ assert.ok(!menu.is(':visible'), 'The menu was closed');
+
+ $(ShowOnBtn).trigger('click');
+ assert.ok(menu.is(':visible'), 'The menu was opened by clicking on the button');
+
+ field.MonthPicker('Close');
+});
+
+QUnit.module("Min/MaxMonth");
+
+QUnit.test('Month buttons are disabled', function (assert) {
+ var field = $(RistrictMonthField).val('12/2015').MonthPicker({
+ Animation: 'none', // Disable animation to make sure opening and closing the menu is synchronous.
+
+ MinMonth: '10/2015'
+ });
+
+ field.MonthPicker('Open');
+
+ var menu = $(MonthPicker_RistrictMonthField);
+ var previousYearButton = menu.find('.previous-year>button');
+ var nextYearButton = menu.find('.next-year>button');
+
+
+ // Try to click the disabled buttons.
+ var buttons = menu.find('.month-picker-month-table button');
+ $(buttons.slice(0, 8)).trigger('click');
+
+ assert.ok(previousYearButton.is('.ui-button-disabled'), 'The previous year button is disabled');
+
+ // Make sure that the date didn't change as a
+ // result of clicking the disabled button.
+ var selectedMonth = field.MonthPicker('GetSelectedDate');
+ assert.equal( selectedMonth.getFullYear(), 2015, 'The selected year is still 2015');
+ assert.equal( selectedMonth.getMonth() + 1, 12, 'The selected month is still December');
+ assert.equal( field.val(), '12/2015', 'The input field still has the value 12/2015' );
+
+ // Make sure we can still go to the next year.
+ nextYearButton.trigger('click');
+ var pickerYear = parseInt(menu.find('.year').text(), 10);
+ assert.equal(pickerYear, 2016, 'Clicking next year changed the year to 2016');
+
+ // Make none of the buttons are disabled.
+ assert.ok( !menu.find('button').is('.ui-button-disabled'), 'None of the buttons are disabled');
+
+ // Make sure clicking the first button selected January 2016.
+ menu.find('.button-1').trigger('click');
+ var selectedMonth = field.MonthPicker('GetSelectedDate');
+ assert.equal( selectedMonth.getFullYear(), 2016, 'The selected year is still 2016');
+ assert.equal( selectedMonth.getMonth() + 1, 1, 'The selected month is still January');
+ assert.equal( field.val(), '01/2016', 'The input field has the value 01/2016' );
+
+ // Make sure we can only go back to 2015 a.k.a the minimum year.
+ previousYearButton.trigger('click');
+ previousYearButton.trigger('click');
+
+ var pickerYear = parseInt(menu.find('.year').text(), 10);
+ assert.equal(pickerYear, 2015, 'clicking previous year tweice keept the year at 2015');
+
+ // Make sure that month buttons before October (the minimum month)
+ // are still disabled after navigating back to 2015
+ // by clicking the buttons and checking that the
+ // selected date didn't change.
+ $(buttons.slice(0, 8)).trigger('click');
+
+ var selectedMonth = field.MonthPicker('GetSelectedDate');
+ assert.equal( selectedMonth.getFullYear(), 2016, "Clciking the buttons didn't change the selected year");
+ assert.equal( selectedMonth.getMonth() + 1, 1, "Clciking the buttons didn't change the selected month");
+ assert.equal( field.val(), '01/2016', "Clciking the buttons didn't change the fields value" );
+
+ // Make sure the buttons after October (the minumum month) are enabled.
+ var buttonsDisabled = $( buttons.slice(9) ).is('.ui-button-disabled');
+ assert.notOk(buttonsDisabled, 'All buttons after the minumum month are enabled');
+
+ // Make sure clicking October (the minumum month) works as expected.
+ $(buttons[9]).trigger('click');
+
+ var selectedMonth = field.MonthPicker('GetSelectedDate');
+ assert.equal( selectedMonth.getFullYear(), 2015, 'Clciking the minimum month chose the correct year');
+ assert.equal( selectedMonth.getMonth() + 1, 10, 'Clciking the minimum month chose the correct month');
+ assert.equal( field.val(), '10/2015', 'Clciking the minimum month set the field value to 10/2015' );
+
+ // Destroy the plugin so we can use the field over again
+ // in another Min/MaxMonth test.
+ field.MonthPicker('destroy');
+});
+
+QUnit.test('Year buttons are disabled', function (assert) {
+ var field = $(RistrictMonthField).val('02/2015').MonthPicker({
+ Animation: 'none', // Disable animation to make sure opening and closing the menu is synchronous.
+
+ MaxMonth: '10/2015'
+ });
+
+ field.MonthPicker('Open');
+
+ var menu = $(MonthPicker_RistrictMonthField);
+
+ // Click the year title to show the years.
+ menu.find('.year-title').trigger('click');
+
+ // Make sure we are in years view.
+ var buttons = menu.find('.month-picker-month-table button');
+ var firstVisibleYear = parseInt($(buttons[0]).text(), 10);
+ assert.ok(firstVisibleYear, 'The menu is showing the year table');
+
+ // Make sure the years after the maximum year are disabled.
+ var firstDisabledIndex = (2015 - firstVisibleYear) + 1;
+ var disabledButttons = buttons.slice(firstDisabledIndex);
+ var hasEnabledBttons = $( disabledButttons )
+ .trigger('click')
+ .is(':not(.ui-button-disabled)');
+
+ assert.ok(!hasEnabledBttons, 'All year buttons after the maximum year are disabled');
+
+ // Make sure that clicking the disabled buttons didn't select
+ // a year.
+ var firstVisibleYear = parseInt($(buttons[0]).text(), 10);
+ assert.ok(firstVisibleYear, "Clciking the disabled buttons didn't take us to month view");
+
+ // Make sure the next years button is disabled.
+ var nextYearsButton = menu.find('.next-year>button');
+ var isDisabled = nextYearsButton
+ .trigger('click')
+ .is('.ui-button-disabled');
+
+ assert.ok(isDisabled, 'The next year button is disabled');
+ var newFirstYrar = parseInt($(buttons[0]).text(), 10);
+ assert.equal(newFirstYrar, firstVisibleYear, "Clicking next year didn't change the year");
+
+ var previousYearsButton = menu.find('.previous-year>button');
+ // Keep going back until there are no disabled buttons.
+ // We count to 10 to avoid an infinite loop in case there's
+ // a bug where we are going back in time but the the buttons stay disabled.
+ for (var i = 1; i <= 10; i++) {
+ // Make sure we can click the previous years button.
+ previousYearsButton.trigger('click');
+
+ newFirstYrar = parseInt($(buttons[0]).text(), 10);
+ var wentBack = firstVisibleYear > newFirstYrar;
+ assert.ok(wentBack, 'The plugin responsed to clicking previous years');
+ if (!wentBack) {
+ // Avoid failing on the same problem multiple times.
+ return;
+ }
+
+ firstVisibleYear = newFirstYrar;
+
+ // We still have diabled button, make sure they are the right ones.
+ firstDisabledIndex = Math.min( (2015 - firstVisibleYear) + 1, 12 );
+ disabledButttons = buttons.slice(firstDisabledIndex);
+ hasEnabledBttons = $( disabledButttons )
+ .is(':not(.ui-button-disabled)');
+
+ assert.ok(!hasEnabledBttons, 'All year buttons after the maximum year are still disabled');
+
+ // Check if we still have diabled button.
+ if (!buttons.is('.ui-button-disabled')) {
+ // We don't have disabled buttons, make sure both next and previous
+ // years buttons are enabled.
+ assert.ok(!previousYearsButton.is('.ui-button-disabled'), 'previous year button is enabled');
+ assert.ok(!nextYearsButton.is('.ui-button-disabled'), 'next year button is enabled');
+ break;
+ }
+ }
+
+ // Make sure we didn't click back 10 times and we
+ // still have disabled buttons.
+ assert.ok(!buttons.is('.ui-button-disabled'), 'All year buttons are enabled after clicking previous years ' + i + ' times');
+
+ // Make sure we can click enabled months.
+ var firstVisibleYear = parseInt($(buttons[0]).text(), 10);
+ $(buttons[0]).trigger('click');
+
+ assert.equal($(buttons[0]).text(), $.MonthPicker.i18n.months[0], 'Clicking the ' + firstVisibleYear + ' year button showed the months');
+
+ // Make sure none of the buttons are disabled in the month view.
+ var hasDidabledButtons = menu.find('button').is('.ui-button-disabled');
+ assert.ok(!hasDidabledButtons, 'All buttons are enabled');
+
+ // Click the year title to show the years menu.
+ menu.find('.year-title').trigger('click');
+
+ // Keeps clicking next years until we reach the disabled years.
+ for (var i = 1; !buttons.is('.ui-button-disabled') && i <= 10; i++) {
+ nextYearsButton.trigger('click');
+ }
+
+ // Make sure were on the last page.
+ assert.ok(buttons.is('.ui-button-disabled'), 'Clciking next took us to the last page');
+ assert.ok(nextYearsButton.is('.ui-button-disabled'), 'The next years button is disabled');
+ assert.ok(!previousYearsButton.is('.ui-button-disabled'), 'The previous years button is enabled');
+
+ firstVisibleYear = parseInt($(buttons[0]).text(), 10);
+ nextYearsButton.trigger('click');
+ newFirstYrar = parseInt($(buttons[0]).text(), 10);
+ assert.equal(newFirstYrar, firstVisibleYear, 'Clicking the next years button keept us on the same page');
+
+ // Click on 2015 and make sure we have disabled button.
+ var firstVisibleYear = parseInt($(buttons[0]).text(), 10);
+ $(buttons[(2015 - firstVisibleYear)]).trigger('click');
+
+ assert.ok(buttons.is('.ui-button-disabled'), 'Clciking the maximum year shows disabled month buttons');
+ $(buttons[(2015 - firstVisibleYear)]).trigger('click');
+
+ // Click October and make sure were in month view.
+ $(buttons[9]).trigger('click');
+ assert.equal(field.val(), '10/2015', 'Clicking October (the maximum month) sets the expected value');
+
+ // Destroy the plugin so we can use the field over again
+ // in another Min/MaxMonth test.
+ field.MonthPicker('destroy');
+});
+
+// Here we make sure that if the user types in a year
+// that is outside the restricted range the menu will
+// open in the closest year that is within range, for example:
+//
+// If the MinMonth is: 10/2015 and the user types in 11/2020
+// the menu will open and show the year 2015.
+//
+// This test purposely juggles between types to ensure
+// that passing in different types before and after init works
+// as expected.
+QUnit.test('Menu opens within range', function (assert) {
+ var field = $(RistrictMonthField).MonthPicker({
+ Animation: 'none', // Disable animation to make sure opening and closing the menu is synchronous.
+
+ MinMonth: '01/2013',
+ MaxMonth: new Date(2016, 11 - 1)
+ });
+
+ var menu = $(MonthPicker_RistrictMonthField);
+
+ // Make sure the menu opens in the year 2013 even if the user
+ // types in 02/2010.
+ field.val('02/2010');
+ field.MonthPicker('Open');
+
+ assert.equal(menu.find('.year').text(), 2013, 'The menu opend at the minimum year (2013) and not 2010' );
+
+ field.MonthPicker('Close');
+
+ // Make sure the menu opens in the year 2016 even if the user
+ // types in 02/2020.
+ field.val('12/2020');
+ field.MonthPicker('Open');
+
+ assert.equal(menu.find('.year').text(), 2016, 'The menu opend at the maximum year (2016) and not 2020' );
+
+ field.MonthPicker('Close');
+
+ // Make sure that the menu will open at the year 2018
+ // If we change the MaxMonth option.
+ field.MonthPicker('option', 'MaxMonth', '12/2018');
+ field.MonthPicker('Open');
+
+ assert.equal(menu.find('.year').text(), 2018, 'The menu opend at the year 2018 after changing the MaxMonth option' );
+
+ field.MonthPicker('Close');
+
+ // Make sure the menu opens at the the selected year if the MaxMonth
+ // is greater than the selected month.
+ field.MonthPicker('option', 'MaxMonth', new Date(2021, 12 - 1));
+ field.MonthPicker('Open');
+
+ assert.equal(menu.find('.year').text(), 2020, 'The menu opend at the the selected year 2020 after' );
+
+ field.MonthPicker('Close');
+
+ field.MonthPicker('option', 'MinMonth', new Date(2010, 12 - 1));
+ field.val('02/2009');
+ field.MonthPicker('Open');
+
+ assert.equal(menu.find('.year').text(), 2010, 'The menu opend at the year 2010 after chagnig the MinMonth option' );
+
+ field.MonthPicker('Close');
+
+ // Make sure the menu opens at the selected year the MinMonth option
+ // to soemthing smaller than the selected month.
+ field.MonthPicker('option', 'MinMonth', new Date(2008, 04));
+ field.MonthPicker('Open');
+
+ assert.equal(menu.find('.year').text(), 2009, 'The menu opend at the selected year after changing the MinMonth option again' );
+
+ // Destroy the plugin so we can use the field over again
+ // in another Min/MaxMonth test.
+ field.MonthPicker('destroy');
+});
+
+QUnit.test('Number of months from today', function (assert) {
+ var field = $(RistrictMonthField).MonthPicker({
+ Animation: 'none', // Disable animation to make sure opening and closing the menu is synchronous.
+
+ MinMonth: 0,
+ MaxMonth: 16
+ });
+
+ // Make sure the menu will open on the current month.
+ field.val($.datepicker.formatDate('mm/yy', new Date));
+
+ field.MonthPicker('Open');
+
+ var menu = $(MonthPicker_RistrictMonthField);
+
+ // Make sure we are in years view.
+ var buttons = menu.find('.month-picker-month-table button');
+ var nextYearButton = menu.find('.next-year>button');
+ var previousYearButton = menu.find('.previous-year>button');
+ var enabledMonths = 0;
+
+ // Make sure that 16 buttons + 1 for today are disabled.
+ //
+ // Keep clicking next until the next year button is disabled
+ // We count to 10 to avoid an infinite loop in case there's
+ // a bug where the next button is not disabled.
+ var hasNext = nextYearButton.is(':not(.ui-button-disabled)');
+ for (var i = 0; hasNext && i < 10; i++) {
+ hasNext = nextYearButton.is(':not(.ui-button-disabled)');
+ enabledMonths += buttons.not('.ui-button-disabled').length;
+ nextYearButton.trigger('click');
+ }
+ assert.equal(enabledMonths, 17, 'Today + 16 month buttons are enabled');
+
+ field.MonthPicker('Close');
+
+ // Make sure that 20 buttons + 1 for today are disabled.
+ field.MonthPicker({MinMonth: -20, MaxMonth: 0});
+ field.MonthPicker('Open');
+ enabledMonths = 0;
+
+ hasNext = previousYearButton.is(':not(.ui-button-disabled)');
+
+ for (var i = 0; hasNext && i < 10; i++) {
+ hasNext = previousYearButton.is(':not(.ui-button-disabled)');
+ enabledMonths += buttons.not('.ui-button-disabled').length;
+ previousYearButton.trigger('click');
+ }
+ assert.equal(enabledMonths, 21, 'Today + 20 month buttons are enabled');
+
+ // Destroy the plugin so we can use the field over again
+ // in another Min/MaxMonth test.
+ field.MonthPicker('destroy');
+});
+
+QUnit.test('Relative month periods', function (assert) {
+ var field = $(RistrictMonthField).MonthPicker({
+ Animation: 'none', // Disable animation to make sure opening and closing the menu is synchronous.
+
+ MinMonth: '+1Y -12m', // a.k.a 0 months (this month).
+ MaxMonth: '6M +1y' // a.k.a 18 months.
+ });
+
+ // Make sure the menu will open on the current month.
+ field.val($.datepicker.formatDate('mm/yy', new Date));
+
+ field.MonthPicker('Open');
+
+ var menu = $(MonthPicker_RistrictMonthField);
+
+ // Make sure we are in years view.
+ var buttons = menu.find('.month-picker-month-table button');
+ var nextYearButton = menu.find('.next-year>button');
+ var previousYearButton = menu.find('.previous-year>button');
+ var enabledMonths = 0;
+
+ // Make sure that 18 buttons + 1 for today are disabled.
+ //
+ // Keep clicking next until the next year button is disabled
+ // We count to 10 to avoid an infinite loop in case there's
+ // a bug where the next button is not disabled.
+ var hasNext = nextYearButton.is(':not(.ui-button-disabled)');
+ for (var i = 0; hasNext && i < 10; i++) {
+ hasNext = nextYearButton.is(':not(.ui-button-disabled)');
+ enabledMonths += buttons.not('.ui-button-disabled').length;
+ nextYearButton.trigger('click');
+ }
+ assert.equal(enabledMonths, 19, 'Today + 18 month buttons are enabled');
+
+ field.MonthPicker('Close');
+
+ // Make sure that 24 buttons + 1 for today are disabled.
+ field.MonthPicker({MinMonth: '-2y', MaxMonth: '0M'});
+ field.MonthPicker('Open');
+ enabledMonths = 0;
+
+ hasNext = previousYearButton.is(':not(.ui-button-disabled)');
+
+ for (var i = 0; hasNext && i < 10; i++) {
+ hasNext = previousYearButton.is(':not(.ui-button-disabled)');
+ enabledMonths += buttons.not('.ui-button-disabled').length;
+ previousYearButton.trigger('click');
+ }
+ assert.equal(enabledMonths, 25, 'Today + 24 month buttons are enabled');
+
+ // Destroy the plugin so we can use the field over again
+ // in another Min/MaxMonth test.
+ field.MonthPicker('destroy');
+});
+
+QUnit.test('JavaScript Date objects', function (assert) {
+ var field = $(RistrictMonthField).MonthPicker({
+ Animation: 'none', // Disable animation to make sure opening and closing the menu is synchronous.
+
+ MinMonth: new Date(2015, 2 - 1),
+ MaxMonth: new Date(2015, 11 - 1)
+ });
+
+ field.val('05/2015');
+
+ var menu = $(MonthPicker_RistrictMonthField);
+ var buttons = menu.find('.month-picker-month-table button');
+
+ field.MonthPicker('Open');
+ assert.equal(buttons.not('.ui-button-disabled').length, 10, '10 month buttons are enabled');
+
+ field.MonthPicker('Close');
+ field.MonthPicker('option', 'MinMonth', new Date(2016, 1 - 1));
+ field.MonthPicker('option', 'MaxMonth', new Date(2016, 6 - 1));
+
+ field.MonthPicker('Open');
+ assert.equal(menu.find('.year').text(), 2016, 'The menu opend at the expected year 2015');
+ assert.equal(buttons.not('.ui-button-disabled').length, 6, '12 month buttons are enabled');
+
+ // Destroy the plugin so we can use the field over again
+ // in another Min/MaxMonth test.
+ field.MonthPicker('destroy');
+});