/*
The jQuery UI Month Picker Version 3.0.4
https://github.com/KidSysco/jquery-ui-month-picker/
https://kidsysco.github.io/jquery-ui-month-picker/
Copyright (C) 2007 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
.
*/
(function ($, window, document, Date) {
'use strict';
var _setupErr = 'MonthPicker Error: ';
// 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
// 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;
}
// Creates an alias to jQuery UI's .button() that dosen't
// conflict with Bootstrap.js button (#35)
$.widget.bridge('jqueryUIButton', $.ui.button);
var _speeds = $.fx.speeds;
var _eventsNs = '.MonthPicker';
//var _textfieldClass = 'month-year-input';
var _textfieldClass = 'hasDatepicker';
var _clearHint = 'month-picker-clear-hint';
var _iconClass = '.ui-button-icon-primary';
var _disabledClass = 'month-picker-disabled';
var _todayClass = 'ui-state-highlight';
var _selectedClass = 'ui-state-active';
var _defaultClass = 'ui-state-default';
var _defaultPos = { my: 'left top+1', at: 'left bottom' };
var _RTL_defaultPos = { my: 'right top+1', at: 'right bottom' };
var _posErr = _setupErr + 'The jQuery UI position plug-in must be loaded.';
var _badOptValErr = _setupErr + 'Unsupported % option value, supported values are: ';
var _badMinMaxVal = _setupErr + '"_" is not a valid %Month value.';
var _openedInstance = null;
var _hasPosition = !!$.ui.position;
var _animVals = {
Animation: ['slideToggle', 'fadeToggle', 'none'],
ShowAnim: ['fadeIn', 'slideDown', 'none'],
HideAnim: ['fadeOut', 'slideUp', 'none']
};
var _setOptionHooks = {
ValidationErrorMessage: '_createValidationMessage',
Disabled: '_setDisabledState',
ShowIcon: '_updateButton',
Button: '_updateButton',
ShowOn: '_updateFieldEvents',
IsRTL: '_setRTL',
AltFormat: '_updateAlt',
AltField: '_updateAlt',
StartYear: '_setPickerYear',
MinMonth: '_setMinMonth',
MaxMonth: '_setMaxMonth',
SelectedMonth: '_setSelectedMonth'
};
var $noop = $.noop;
var $proxy = $.proxy;
var $datepicker = $.datepicker;
var click = 'click' + _eventsNs;
function _toMonth(date) {
return date.getMonth() + (date.getFullYear() * 12);
}
function _toYear(month) {
return Math.floor(month / 12);
}
function _stayActive() {
$(this).addClass(_selectedClass);
}
function _setActive( el, state ) {
return el[ state ? 'on' : 'off' ]('mousenter mouseout', _stayActive )
.toggleClass(_selectedClass, state);
}
function _between(month, from, until) {
return (!from || month >= from) && (!until || month <= until);
}
function _encodeMonth(_inst, _val) {
if (_val === null) {
return _val;
} else if (_val instanceof Date) {
return _toMonth(_val);
} else if ($.isNumeric(_val)) {
return _toMonth(new Date) + parseInt(_val, 10);
}
var _date = _inst._parseMonth(_val);
if (_date) {
return _toMonth(_date);
}
return _parsePeriod(_val);
}
function _event(_name, _inst) {
return $proxy(_inst.options[_name] || $noop, _inst.element[0]);
}
function _parsePeriod(_val, _initDate) {
// Parsing is done by replacing tokens in the value to form
// a JSON object with it's keys and values reversed
// (example '+1y +2m' will turn into {"+1":"y","+2":"m"})
// After that we just revers the keys and values.
var _json = $.trim(_val);
_json = _json.replace(/y/i, '":"y"');
_json = _json.replace(/m/i, '":"m"');
try {
var _rev = JSON.parse( '{"' + _json.replace(/ /g, ',"') + '}' ), obj = {};
for (var key in _rev) {
obj[ _rev[key] ] = key;
}
var _month = _toMonth(new Date);
_month += (parseInt(obj.m, 10) || 0);
return _month + (parseInt(obj.y, 10) || 0) * 12;
} catch (e) {
return false;
}
}
function _makeDefaultButton(options) {
// this refers to the associated input field.
return $('' + options.i18n.buttonText + '')
.jqueryUIButton({
text: false,
icons: {
// Defaults to 'ui-icon-calculator'.
primary: options.ButtonIcon
}
});
}
function _applyArrowButton($el, dir) {
$el.jqueryUIButton('option', {
icons: {
primary: 'ui-icon-circle-triangle-' + (dir ? 'w' : 'e')
}
});
}
function _isInline(elem) {
return !elem.is('input');
}
$.MonthPicker = {
VERSION: '3.0.4', // Added in version 2.4;
i18n: {
year: 'Año',
prevYear: 'Año Anterior',
nextYear: 'Siguiente Año',
next12Years: 'Siguentes 12 Años',
prev12Years: 'Anteriores 12 Años',
nextLabel: 'Siguiente',
prevLabel: 'Anterior',
buttonText: 'Abrir calendario',
jumpYears: 'Saltar Años',
backTo: 'Regresar a',
months: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic']
}
};
var _markup =
'
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
';
// Groups state and functionallity to fade in the jump years hint
// when the user mouses over the Year 2016 text.
// NOTE: An invocation of this function:
// 1: Is an independent instance with it's own unique state.
// 2: Assumes that there is no previous hint applied to the
// button (it dosen't remove the existing hint).
function _applyButtonHint(_button, _hintText) {
var _speed = 125, _currentLabel, _startTimeout, _labelElem = $();
_button.on('mouseenter' + _eventsNs + 'h', _prepareToStart);
// Setp 1: Wait to make sure the user isn't just mousing over and
// away from the button.
// NOTE: If _fadeOutHint() is triggered on mouseleave before the
// timeout is triggered the animation is canceled.
function _prepareToStart() {
_startTimeout = setTimeout(_fadeOutLabel, 175);
}
// Setp 2: Fade out the label (Year 2016) text to 45%.
function _fadeOutLabel() {
_startTimeout = null;
_labelElem = $('span', _button).animate({ opacity: 0.45 }, _speed, _fadeInHint);
}
// Setp 3: Fade in the hint text (Jump years).
function _fadeInHint() {
_currentLabel = _labelElem.text();
_labelElem.animate({ opacity: 1 }, _speed).text(_hintText);
}
_button.on('mouseleave' + _eventsNs + 'h', _fadeOutHint);
function _fadeOutHint() {
if (_startTimeout) {
// If the user is just moving over and away from the button, cancel
// the animation completely.
clearTimeout(_startTimeout);
} else {
// Setp 4: Fade out the hint text (Jump years) to 45%.
_labelElem = $('span', _button).animate({ opacity: 0.45 }, _speed, _fadeInLabel);
}
}
// Setp 5: Fade in the label (Year 2016) text.
function _fadeInLabel() {
_labelElem.text( _currentLabel ).animate({opacity: 1}, _speed);
}
// Adds a function to the button elemene which is called when the
// user clicks the button (the hint needs to be removed).
_button.data(_clearHint, function() {
clearTimeout(_startTimeout);
_labelElem.stop().css({ opacity: 1 });
_button.off(_eventsNs + 'h');
});
} // End _applyButtonHint()
function _setDisabled(_button, _value) {
var _btnWidget = _button.data('ui-button');
if (_btnWidget.option('disabled') !== _value) {
_btnWidget.option('disabled', _value);
}
}
$.widget("KidSysco.MonthPicker", {
/******* Properties *******/
options: {
i18n: {},
IsRTL: false,
Position: null,
StartYear: null,
ShowIcon: true,
UseInputMask: false,
ValidationErrorMessage: null,
Disabled: false,
MonthFormat: 'mm/yy',
Animation: 'fadeToggle',
ShowAnim: null,
HideAnim: null,
ShowOn: null,
MinMonth: null,
MaxMonth: null,
Duration: 'normal',
Button: _makeDefaultButton,
ButtonIcon: 'ui-icon-calculator'
},
_monthPickerButton: $(),
_validationMessage: $(),
_selectedBtn: $(),
/******* jQuery UI Widget Factory Overrides ********/
_destroy: function () {
var _elem = this.element;
if ($.mask && this.options.UseInputMask) {
_elem.unmask();
if (!this.GetSelectedDate()) {
_elem.val('');
}
}
_elem.removeClass(_textfieldClass).off(_eventsNs);
$(document).off(_eventsNs + this.uuid);
this._monthPickerMenu.remove();
var _button = this._monthPickerButton.off(click);
if (this._removeOldBtn) {
_button.remove();
}
this._validationMessage.remove();
if (_openedInstance === this) {
_openedInstance = null;
}
},
_setOption: function (key, value) {
switch (key) {
case 'i18n':
// Pass a clone i18n object to the this._super.
value = $.extend({}, value);
break;
case 'Position':
if (!_hasPosition) {
alert(_posErr);
return;
}
break;
case 'MonthFormat':
var date = this.GetSelectedDate();
if (date) {
this.element.val( this.FormatMonth(date, value) );
}
break;
}
// Make sure the user passed in a valid Animation, ShowAnim and HideAnim options values.
if (key in _animVals && $.inArray(value, _animVals[key]) === -1) {
alert(_badOptValErr.replace(/%/, key) + _animVals[key]);
return;
}
// In jQuery UI 1.8, manually invoke the _setOption method from the base widget.
//$.Widget.prototype._setOption.apply(this, arguments);
// In jQuery UI 1.9 and above, you use the _super method instead.
this._super(key, value);
_setOptionHooks[key] ? this[ _setOptionHooks[key] ](value) : 0;
},
_create: function () {
var _el = this.element, _opts = this.options, _type = _el.attr('type');
// According to http://www.w3.org/TR/html-markup/input.html#input
// An input element with no type attribute specified represents the same thing as an
// input element with its type attribute set to "text".
// TLDR:
// http://www.w3.org/TR/html5/forms.html#the-input-element
// https://api.jquery.com/text-selector/
// $.inArray(void 0, ['text', 'month', void 0]) returns -1 when searching for undefined in IE8 (#45)
// This is only noticable in the real version of IE8, emulated versions
// from the dev tools in modern browsers do not suffer from this issue.
// if (!_el.is('input,div,span') || $.inArray(_el.attr('type'), ['text', 'month', void 0]) === -1) {
if (!_el.is('input,div,span') || (_type !== 'text' && _type !== 'month' && _type !== void 0)) {
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.');
console.error(error + '\n Caused by:');
console.log(_el[0]);
return false;
}
if (!$.mask && _opts.UseInputMask) {
alert(_setupErr + 'The UseInputMask option requires the Input Mask Plugin. Get it from digitalbush.com');
return false;
}
if (_opts.Position !== null && !_hasPosition) {
alert(_posErr);
return false;
}
// Make sure the user passed in a valid Animation, ShowAnim and HideAnim options values.
for (var opt in _animVals) {
if (_opts[opt] !== null && $.inArray(_opts[opt], _animVals[opt]) === -1) {
alert(_badOptValErr.replace(/%/, opt) + _animVals[opt]);
return false;
}
}
this._isMonthInputType = _el.attr('type') === 'month';
if (this._isMonthInputType) {
this.options.MonthFormat = this.MonthInputFormat;
_el.css('width', 'auto');
}
var _menu = this._monthPickerMenu = $('').hide();
var isInline = _isInline(_el);
$(_markup).appendTo(_menu);
_menu.appendTo( isInline ? _el : document.body );
this._titleButton =
$('.month-picker-title', _menu)
.click($proxy(this._showYearsClickHandler, this))
.find('a').jqueryUIButton()
.removeClass(_defaultClass);
this._applyJumpYearsHint();
this._createValidationMessage();
this._prevButton = $('.month-picker-previous>a', _menu)
.jqueryUIButton({ text: false })
.removeClass(_defaultClass);
this._nextButton = $('.month-picker-next>a', _menu)
.jqueryUIButton({ text: false })
.removeClass(_defaultClass);
this._setRTL(_opts.IsRTL); //Assigns icons to the next/prev buttons.
$(_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++) {
var $tr = !(i % 3) ? $('