PageSourceSearch

https://www.bcr.com.ar/modules/custom/cms_tweaks/lib/monthPicker/src/MonthPicker.js?tj9dnt

js bcr.com.ar collected 2026-09-24 20:47:35 UTC 38,510 bytes, 1,047 lines download raw bytes

1/*
2The jQuery UI Month Picker Version 3.0.4
3https://github.com/KidSysco/jquery-ui-month-picker/
4
5Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
6This program is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program.  If not, see
18<http://www.gnu.org/licenses/gpl-3.0.txt>.
19*/
20
21(function ($, window, document, Date) {
22    'use strict';
23
24    var _setupErr = 'MonthPicker Error: ';
25    // This test must be run before any rererence is made to jQuery.
26    // In case the user didn't load jQuery or jQuery UI the plugin
27    // will fail before it get's to this test + there is no reason
28    // to perform this test for every MonthPicker instance being created.
29    if (!$ || !$.ui || !$.ui.button || !$.ui.datepicker) {
30        alert(_setupErr + 'The jQuery UI button and datepicker plug-ins must be loaded.');
31        return;
32    }
33
34    // Creates an alias to jQuery UI's .button() that dosen't
35    // conflict with Bootstrap.js button (#35)
36    $.widget.bridge('jqueryUIButton', $.ui.button);
37
38    var _speeds = $.fx.speeds;
39    var _eventsNs = '.MonthPicker';
40    var _textfieldClass = 'month-year-input';
41    var _clearHint = 'month-picker-clear-hint';
42    var _iconClass = '.ui-button-icon-primary';
43    var _disabledClass = 'month-picker-disabled';
44    var _todayClass = 'ui-state-highlight';
45    var _selectedClass = 'ui-state-active';
46    var _defaultClass = 'ui-state-default';
47    var _defaultPos = { my: 'left top+1', at: 'left bottom' };
48    var _RTL_defaultPos = { my: 'right top+1', at: 'right bottom' };
49    var _posErr = _setupErr + 'The jQuery UI position plug-in must be loaded.';
50    var _badOptValErr = _setupErr + 'Unsupported % option value, supported values are: ';
51    var _badMinMaxVal =  _setupErr + '"_" is not a valid %Month value.';
52    var _openedInstance = null;
53    var _hasPosition = !!$.ui.position;
54    var _animVals = {
55        Animation: ['slideToggle', 'fadeToggle', 'none'],
56        ShowAnim: ['fadeIn', 'slideDown', 'none'],
57        HideAnim: ['fadeOut', 'slideUp', 'none']
58    };
59    var _setOptionHooks = {
60        ValidationErrorMessage: '_createValidationMessage',
61        Disabled: '_setDisabledState',
62        ShowIcon: '_updateButton',
63        Button: '_updateButton',
64        ShowOn: '_updateFieldEvents',
65        IsRTL: '_setRTL',
66        AltFormat: '_updateAlt',
67        AltField: '_updateAlt',
68        StartYear: '_setPickerYear',
69        MinMonth: '_setMinMonth',
70        MaxMonth: '_setMaxMonth',
71        SelectedMonth: '_setSelectedMonth'
72    };
73    var $noop = $.noop;
74    var $proxy = $.proxy;
75    var $datepicker = $.datepicker;
76    var click = 'click' + _eventsNs;
77
78    function _toMonth(date) {
79        return date.getMonth() + (date.getFullYear() * 12);
80    }
81
82    function _toYear(month) {
83        return Math.floor(month / 12);
84    }
85
86    function _stayActive() {
87        $(this).addClass(_selectedClass);
88    }
89
90    function _setActive( el, state ) {
91        return el[ state ? 'on' : 'off' ]('mousenter mouseout',  _stayActive )
92              .toggleClass(_selectedClass, state);
93    }
94
95    function _between(month, from, until) {
96        return (!from || month >= from) && (!until || month <= until);
97    }
98
99    function _encodeMonth(_inst, _val) {
100        if (_val === null) {
101            return _val;
102        } else if (_val instanceof Date) {
103            return _toMonth(_val);
104        } else if ($.isNumeric(_val)) {
105            return _toMonth(new Date) + parseInt(_val, 10);
106        }
107
108        var _date = _inst._parseMonth(_val);
109        if (_date) {
110            return _toMonth(_date);
111        }
112
113        return _parsePeriod(_val);
114    }
115
116    function _event(_name, _inst) {
117        return $proxy(_inst.options[_name] || $noop, _inst.element[0]);
118    }
119
120    function _parsePeriod(_val, _initDate) {
121        // Parsing is done by replacing tokens in the value to form
122        // a JSON object with it's keys and values reversed
123        // (example '+1y +2m' will turn into {"+1":"y","+2":"m"})
124        // After that we just revers the keys and values.
125        var _json = $.trim(_val);
126        _json = _json.replace(/y/i, '":"y"');
127        _json = _json.replace(/m/i, '":"m"');
128
129        try {
130            var _rev = JSON.parse( '{"' + _json.replace(/ /g, ',"') + '}' ), obj = {};
131
132            for (var key in _rev) {
133                obj[ _rev[key] ] = key;
134            }
135
136            var _month = _toMonth(new Date);
137            _month += (parseInt(obj.m, 10) || 0);
138            return _month + (parseInt(obj.y, 10) || 0) * 12;
139        } catch (e) {
140            return false;
141        }
142    }
143
144    function _makeDefaultButton(options) {
145        // this refers to the associated input field.
146        return $('<span id="MonthPicker_Button_' + this.id + '" class="month-picker-open-button">' + options.i18n.buttonText + '</span>')
147            .jqueryUIButton({
148                text: false,
149                icons: {
150                    // Defaults to 'ui-icon-calculator'.
151                    primary: options.ButtonIcon
152                }
153            });
154    }
155
156    function _applyArrowButton($el, dir) {
157        $el.jqueryUIButton('option', {
158            icons: {
159                primary: 'ui-icon-circle-triangle-' + (dir ? 'w' : 'e')
160            }
161        });
162    }
163
164    function _isInline(elem) {
165        return !elem.is('input');
166    }
167
168    $.MonthPicker = {
169        VERSION: '3.0.4', // Added in version 2.4;
170        i18n: {
171            year: 'Year',
172            prevYear: 'Previous Year',
173            nextYear: 'Next Year',
174            next12Years: 'Jump Forward 12 Years',
175            prev12Years: 'Jump Back 12 Years',
176            nextLabel: 'Next',
177            prevLabel: 'Prev',
178            buttonText: 'Open Month Chooser',
179            jumpYears: 'Jump Years',
180            backTo: 'Back to',
181            months: ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'June', 'July', 'Aug.', 'Sep.', 'Oct.', 'Nov.', 'Dec.']
182        }
183    };
184
185    var _markup =
186        '<div class="ui-widget-header month-picker-header ui-corner-all">' +
187            '<table class="month-picker-year-table">' +
188                '<tr>' +
189                    '<td class="month-picker-previous"><a /></td>' +
190                    '<td class="month-picker-title"><a /></td>' +
191                    '<td class="month-picker-next"><a /></td>' +
192                '</tr>' +
193            '</table>' +
194        '</div>' +
195        '<div>' +
196            '<table class="month-picker-month-table" />' +
197        '</div>';
198
199    // Groups state and functionallity to fade in the jump years hint
200    // when the user mouses over the Year 2016 text.
201    // NOTE: An invocation of this function:
202    // 1: Is an independent instance with it's own unique state.
203    // 2: Assumes that there is no previous hint applied to the
204    //    button (it dosen't remove the existing hint).
205    function _applyButtonHint(_button, _hintText) {
206      var _speed = 125, _currentLabel, _startTimeout, _labelElem = $();
207
208      _button.on('mouseenter' + _eventsNs + 'h', _prepareToStart);
209
210      // Setp 1: Wait to make sure the user isn't just mousing over and
211      // away from the button.
212      // NOTE: If _fadeOutHint() is triggered on mouseleave before the
213      // timeout is triggered the animation is canceled.
214      function _prepareToStart() {
215        _startTimeout = setTimeout(_fadeOutLabel, 175);
216      }
217
218      // Setp 2: Fade out the label (Year 2016) text to 45%.
219      function _fadeOutLabel() {
220        _startTimeout = null;
221        _labelElem = $('span', _button).animate({ opacity: 0.45 }, _speed, _fadeInHint);
222      }
223
224      // Setp 3: Fade in the hint text (Jump years).
225      function _fadeInHint() {
226        _currentLabel = _labelElem.text();
227        _labelElem.animate({ opacity: 1 }, _speed).text(_hintText);
228      }
229
230      _button.on('mouseleave' + _eventsNs + 'h', _fadeOutHint);
231
232      function _fadeOutHint() {
233        if (_startTimeout) {
234          // If the user is just moving over and away from the button, cancel
235          // the animation completely.
236          clearTimeout(_startTimeout);
237        } else {
238          // Setp 4: Fade out the hint text (Jump years) to 45%.
239          _labelElem = $('span', _button).animate({ opacity: 0.45 }, _speed, _fadeInLabel);
240        }
241      }
242
243      // Setp 5: Fade in the label (Year 2016) text.
244      function _fadeInLabel() {
245        _labelElem.text( _currentLabel ).animate({opacity: 1}, _speed);
246      }
247
248      // Adds a function to the button elemene which is called when the
249      // user clicks the button (the hint needs to be removed).
250      _button.data(_clearHint, function() {
251        clearTimeout(_startTimeout);
252        _labelElem.stop().css({ opacity: 1 });
253        _button.off(_eventsNs + 'h');
254      });
255    } // End _applyButtonHint()
256
257    function _setDisabled(_button, _value) {
258      var _btnWidget = _button.data('ui-button');
259      if (_btnWidget.option('disabled') !== _value) {
260        _btnWidget.option('disabled', _value);
261      }
262    }
263
264    $.widget("KidSysco.MonthPicker", {
265
266        /******* Properties *******/
267
268        options: {
269            i18n: {},
270            IsRTL: false,
271            Position: null,
272            StartYear: null,
273            ShowIcon: true,
274            UseInputMask: false,
275            ValidationErrorMessage: null,
276            Disabled: false,
277            MonthFormat: 'mm/yy',
278            Animation: 'fadeToggle',
279            ShowAnim: null,
280            HideAnim: null,
281            ShowOn: null,
282            MinMonth: null,
283            MaxMonth: null,
284            Duration: 'normal',
285            Button: _makeDefaultButton,
286            ButtonIcon: 'ui-icon-calculator'
287        },
288
289        _monthPickerButton: $(),
290        _validationMessage: $(),
291        _selectedBtn: $(),
292
293        /******* jQuery UI Widget Factory Overrides ********/
294
295        _destroy: function () {
296            var _elem = this.element;
297            if ($.mask && this.options.UseInputMask) {
298                _elem.unmask();
299
300                if (!this.GetSelectedDate()) {
301                    _elem.val('');
302                }
303            }
304
305            _elem.removeClass(_textfieldClass).off(_eventsNs);
306
307            $(document).off(_eventsNs + this.uuid);
308
309            this._monthPickerMenu.remove();
310
311            var _button = this._monthPickerButton.off(click);
312            if (this._removeOldBtn) {
313                _button.remove();
314            }
315
316            this._validationMessage.remove();
317
318            if (_openedInstance === this) {
319              _openedInstance = null;
320            }
321        },
322
323        _setOption: function (key, value) {
324            switch (key) {
325                case 'i18n':
326                    // Pass a clone i18n object to the this._super.
327                    value = $.extend({}, value);
328                    break;
329                case 'Position':
330                    if (!_hasPosition) {
331                        alert(_posErr);
332                        return;
333                    }
334                    break;
335                case 'MonthFormat':
336                    var date = this.GetSelectedDate();
337                    if (date) {
338                        this.element.val( this.FormatMonth(date, value) );
339                    }
340                    break;
341            }
342
343            // Make sure the user passed in a valid Animation, ShowAnim and HideAnim options values.
344            if (key in _animVals && $.inArray(value, _animVals[key]) === -1) {
345                alert(_badOptValErr.replace(/%/, key) + _animVals[key]);
346                return;
347            }
348
349            // In jQuery UI 1.8, manually invoke the _setOption method from the base widget.
350            //$.Widget.prototype._setOption.apply(this, arguments);
351            // In jQuery UI 1.9 and above, you use the _super method instead.
352            this._super(key, value);
353
354            _setOptionHooks[key] ? this[ _setOptionHooks[key] ](value) : 0;
355        },
356
357        _create: function () {
358            var _el = this.element, _opts = this.options, _type = _el.attr('type');
359            // According to http://www.w3.org/TR/html-markup/input.html#input
360            // An input element with no type attribute specified represents the same thing as an
361            // input element with its type attribute set to "text".
362            // TLDR:
363            // http://www.w3.org/TR/html5/forms.html#the-input-element
364            // https://api.jquery.com/text-selector/
365
366            // $.inArray(void 0, ['text', 'month', void 0]) returns -1 when searching for undefined in IE8 (#45)
367            // This is only noticable in the real version of IE8, emulated versions
368            // from the dev tools in modern browsers do not suffer from this issue.
369            // if (!_el.is('input,div,span') || $.inArray(_el.attr('type'), ['text', 'month', void 0]) === -1) {
370            if (!_el.is('input,div,span') || (_type !== 'text' && _type !== 'month' && _type !==  void 0)) {
371                var error = _setupErr + 'MonthPicker can only be called on text or month inputs.';
372                // Call alert first so that IE<10 won't trip over console.log and swallow all errors.
373                alert(error + ' \n\nSee (developer tools) for more details.');
374
375                console.error(error + '\n Caused by:');
376                console.log(_el[0]);
377                return false;
378            }
379
380            if (!$.mask && _opts.UseInputMask) {
381                alert(_setupErr + 'The UseInputMask option requires the Input Mask Plugin. Get it from digitalbush.com');
382                return false;
383            }
384
385            if (_opts.Position !== null && !_hasPosition) {
386                alert(_posErr);
387                return false;
388            }
389
390            // Make sure the user passed in a valid Animation, ShowAnim and HideAnim options values.
391            for (var opt in _animVals) {
392                if (_opts[opt] !== null && $.inArray(_opts[opt], _animVals[opt]) === -1) {
393                    alert(_badOptValErr.replace(/%/, opt) + _animVals[opt]);
394                    return false;
395                }
396            }
397
398            this._isMonthInputType = _el.attr('type') === 'month';
399            if (this._isMonthInputType) {
400                this.options.MonthFormat = this.MonthInputFormat;
401                _el.css('width', 'auto');
402            }
403
404            var _menu = this._monthPickerMenu = $('<div id="MonthPicker_' + _el[0].id + '" class="month-picker ui-widget ui-widget-content ui-corner-all"></div>').hide();
405            var isInline = _isInline(_el);
406
407            $(_markup).appendTo(_menu);
408            _menu.appendTo( isInline ? _el : document.body );
409
410            this._titleButton =
411                $('.month-picker-title', _menu)
412                .click($proxy(this._showYearsClickHandler, this))
413                .find('a').jqueryUIButton()
414                .removeClass(_defaultClass);
415
416            this._applyJumpYearsHint();
417            this._createValidationMessage();
418
419            this._prevButton = $('.month-picker-previous>a', _menu)
420              .jqueryUIButton({ text: false })
421              .removeClass(_defaultClass);
422
423            this._nextButton = $('.month-picker-next>a', _menu)
424              .jqueryUIButton({ text: false })
425              .removeClass(_defaultClass);
426
427            this._setRTL(_opts.IsRTL); //Assigns icons to the next/prev buttons.
428
429            $(_iconClass, this._nextButton).text(this._i18n('nextLabel'));
430            $(_iconClass, this._prevButton).text(this._i18n('prevLabel'));
431
432            var $table = $('.month-picker-month-table', _menu);
433            for (var i = 0; i < 12; i++) {
434                var $tr = !(i % 3) ? $('<tr />').appendTo($table) : $tr;
435
436                // Use <a> tag instead of <button> to avoid issues
437                // only with Google Chrome (#50).
438                $tr.append('<td><a class="button-' + (i + 1) + '" /></td>');
439            }
440
441            this._buttons = $('a', $table).jqueryUIButton();
442
443            _menu.on('mousedown' + _eventsNs, function (event) {
444                event.preventDefault();
445            });
446
447            // Checks and initailizes Min/MaxMonth properties
448            // (creates _setMinMonth and _setMaxMonth methods).
449            var me = this, Month = 'Month';
450            $.each(['Min', 'Max'], function(i, type) {
451                me["_set" + type + Month] = function(val) {
452                    if ((me['_' + type + Month] = _encodeMonth(me, val)) === false) {
453                        alert(_badMinMaxVal.replace(/%/, type).replace(/_/, val));
454                    }
455                };
456
457                me._setOption(type + Month, me.options[type + Month]);
458            });
459
460            var _selMonth = _opts.SelectedMonth;
461            if (_selMonth !== void 0) {
462                var month = _encodeMonth(this, _selMonth);
463                _el.val( this._formatMonth(new Date( _toYear(month), month % 12, 1)) );
464            }
465
466            this._updateAlt();
467
468            this._setUseInputMask();
469            this._setDisabledState();
470            this.Destroy = this.destroy;
471
472            if (isInline) {
473                this.Open();
474            } else {
475               // Update the alt field if the user manually changes
476               // the input field.
477               _el.addClass(_textfieldClass);
478               _el.change($proxy(this._updateAlt, this));
479            }
480        },
481
482        /****** Publicly Accessible API functions ******/
483
484        GetSelectedDate: function () {
485            return this._parseMonth();
486        },
487
488        GetSelectedYear: function () {
489            var date = this.GetSelectedDate();
490            return date ? date.getFullYear() : NaN;
491        },
492
493        GetSelectedMonth: function () {
494            var date = this.GetSelectedDate();
495            return date ? date.getMonth()+1 : NaN;
496        },
497
498        Validate: function() {
499            var _date = this.GetSelectedDate();
500
501            if (this.options.ValidationErrorMessage !== null && !this.options.Disabled) {
502                this._validationMessage.toggle(!_date);
503            }
504
505            return _date;
506        },
507
508        GetSelectedMonthYear: function () {
509            var date = this.Validate();
510            return date ? (date.getMonth() + 1) + '/' + date.getFullYear() : null;
511        },
512
513        Disable: function () {
514            this._setOption("Disabled", true);
515        },
516
517        Enable: function () {
518            this._setOption("Disabled", false);
519        },
520
521        ClearAllCallbacks: function () {
522            for (var _opt in this.options) {
523                if (_opt.indexOf('On') === 0) {
524                    this.options[_opt] = $noop;
525                }
526            }
527        },
528
529        Clear: function () {
530            this.element.val('');
531            $(this.options.AltField).val('');
532            this._validationMessage.hide();
533        },
534
535        Toggle: function (event) {
536            return this._visible ? this.Close(event) : this.Open(event);
537        },
538
539        Open: function (event) {
540            var _elem = this.element, _opts = this.options;
541            if (!_opts.Disabled && !this._visible) {
542                // Allow the user to prevent opening the menu.
543                event = event || $.Event();
544                if (_event('OnBeforeMenuOpen', this)(event) === false || event.isDefaultPrevented()) {
545                    return;
546                }
547
548                this._visible = true;
549                this._ajustYear(_opts);
550
551                var _menu = this._monthPickerMenu;
552                this._showMonths();
553
554                if (_isInline(_elem)) {
555                    _menu.css('position', 'static').show();
556                    _event('OnAfterMenuOpen', this)();
557                } else {
558                    // If there is an open menu close it first.
559                    if (_openedInstance) {
560                        _openedInstance.Close(event);
561                    }
562
563                    _openedInstance = this;
564                    $(document).on('mousedown' + _eventsNs + this.uuid, $proxy(this.Close, this))
565                               .on('keydown' + _eventsNs + this.uuid, $proxy(this._keyDown, this));
566
567                    // Trun off validation so that clicking one of the months
568                    // won't blur the input field and trogger vlaidation
569                    // befroe the month was chosen (click event was triggered).
570                    // It is turned back on when Hide() is called.
571                    _elem.off('blur' + _eventsNs).focus();
572
573                    var _anim = _opts.ShowAnim || _opts.Animation,
574                        _noAnim = _anim === 'none';
575
576                    // jQuery UI overrides jQuery.show and dosen't
577                    // call the start callback.
578                    // see: http://api.jqueryui.com/show/
579                    _menu[ _noAnim ? 'fadeIn' : _anim ]({
580                       duration: _noAnim ? 0 : this._duration(),
581                       start: $proxy(this._position, this, _menu),
582                       complete: _event('OnAfterMenuOpen', this)
583                    });
584                }
585            }
586        },
587
588        Close: function (event) {
589            var _elem = this.element;
590            if (!_isInline(_elem) && this._visible) {
591                var _menu = this._monthPickerMenu,
592                    _opts = this.options;
593
594                event = event || $.Event();
595                if (_event('OnBeforeMenuClose', this)(event) === false || event.isDefaultPrevented()) {
596                    return;
597                }
598
599                // If the menu is closed while in jump years mode, bring back
600                // the jump years hint.
601                if (this._backToYear) {
602                  this._applyJumpYearsHint();
603                  this._backToYear = 0;
604                }
605
606                this._visible = false;
607                _openedInstance = null;
608                $(document).off('keydown' + _eventsNs + this.uuid)
609                           .off('mousedown' + _eventsNs + this.uuid);
610
611                this.Validate();
612                _elem.on('blur' + _eventsNs, $proxy(this.Validate, this));
613                var _callback = _event('OnAfterMenuClose', this);
614
615                var _anim = _opts.HideAnim || _opts.Animation;
616                if (_anim === 'none') {
617                    _menu.hide(0, _callback);
618                } else {
619                    _menu[ _anim ](this._duration(), _callback);
620                }
621            }
622        },
623
624        /**
625         * Methods the user can override to use a third party library
626         * such as http://momentjs.com for parsing and formatting months.
627         */
628        MonthInputFormat: 'yy-mm',
629
630        ParseMonth: function (str, format) {
631            try {
632                return $datepicker.parseDate('dd' + format, '01' + str);
633            } catch (e) {
634                return null;
635            }
636        },
637
638        FormatMonth: function (date, format) {
639            try {
640                return $datepicker.formatDate(format, date) || null;
641            } catch (e) {
642                return null;
643            }
644        },
645
646        /****** Private and Misc Utility functions ******/
647
648        _setSelectedMonth: function (_selMonth) {
649            var month = _encodeMonth(this, _selMonth), _el = this.element;
650
651            if (month) {
652                var date = new Date( _toYear(month), month % 12, 1 );
653                _el.val( this._formatMonth( date ) );
654
655                this._updateAlt(0, date);
656                this._validationMessage.hide();
657            } else {
658                this.Clear();
659            }
660
661            this._ajustYear(this.options);
662            this._showMonths();
663        },
664
665        _applyJumpYearsHint: function() {
666          _applyButtonHint(this._titleButton, this._i18n('jumpYears'));
667        },
668
669        _i18n: function(str) {
670          var _trans = this.options.i18n[str];
671
672          if (typeof _trans === 'undefined') {
673            return $.MonthPicker.i18n[str];
674          } else {
675            return _trans;
676          }
677        },
678
679        _parseMonth: function (str, format) {
680            return this.ParseMonth(str || this.element.val(), format || this.options.MonthFormat);
681        },
682
683        _formatMonth: function (date, format) {
684            return this.FormatMonth(date || this._parseMonth(), format || this.options.MonthFormat);
685        },
686
687        _updateButton: function () {
688            var isDisabled = this.options.Disabled;
689
690            this._createButton();
691
692            // If the button is a jQuery UI button,
693            // plain HTML button or an input we support disable it,
694            // otherwise the user must handle the diabled state
695            // by creating an appropriate button by passing
696            // a function. See Button option: Img tag tests for
697            // more details.
698            var _button = this._monthPickerButton;
699            try {
700                _button.jqueryUIButton('option', 'disabled', isDisabled);
701            } catch (e) {
702                _button.filter('button,input').prop('disabled', isDisabled);
703            }
704
705            this._updateFieldEvents();
706        },
707
708        _createButton: function () {
709            var _elem = this.element, _opts = this.options;
710            if (_isInline(_elem)) return;
711
712            var _oldButton = this._monthPickerButton.off(_eventsNs);
713            var _btnOpt = _opts.ShowIcon ? _opts.Button : false;
714
715            if ($.isFunction(_btnOpt)) {
716                var _params = $.extend(true, {i18n: $.extend(true, {}, $.MonthPicker.i18n)}, this.options);
717                _btnOpt = _btnOpt.call(_elem[0], _params);
718            }
719
720            var _removeOldBtn = false;
721            this._monthPickerButton = ( _btnOpt instanceof $ ? _btnOpt : $(_btnOpt) )
722                .each(function() {
723                    if (!$.contains(document.body, this)) {
724                        _removeOldBtn = true;
725                        $(this).insertAfter(_elem);
726                    }
727                })
728                .on(click, $proxy(this.Toggle, this))
729                .on('mousedown' + _eventsNs, function(r) {
730                  r.preventDefault();
731                });
732
733            if (this._removeOldBtn) {
734                _oldButton.remove();
735            }
736
737            this._removeOldBtn = _removeOldBtn;
738        },
739
740        _updateFieldEvents: function () {
741            var _events = click + ' focus' + _eventsNs;
742            this.element.off(_events);
743            if (this.options.ShowOn === 'both' || !this._monthPickerButton.length) {
744                this.element.on(_events, $proxy(this.Open, this));
745            }
746        },
747
748        _createValidationMessage: function () {
749            var _errMsg = this.options.ValidationErrorMessage, _elem = this.element;
750            if ($.inArray(_errMsg, [null, '']) === -1) {
751                var _msgEl = $('<span id="MonthPicker_Validation_' + _elem[0].id + '" class="month-picker-invalid-message">' + _errMsg + '</span>');
752
753                var _button = this._monthPickerButton;
754                this._validationMessage = _msgEl.insertAfter(_button.length ? _button : _elem);
755
756                _elem.on('blur' + _eventsNs, $proxy(this.Validate, this));
757            } else {
758                this._validationMessage.remove();
759            }
760        },
761
762        _setRTL: function(value) {
763            _applyArrowButton( this._prevButton.css('float', value ? 'right' : 'left'), !value );
764            _applyArrowButton( this._nextButton.css('float', value ? 'left' : 'right'), value );
765        },
766
767        _keyDown: function (event) {
768            // Don't use $.ui.keyCode to help minification.
769            switch (event.keyCode) {
770                case 13: // Enter.
771                    if (!this.element.val()) {
772                        this._chooseMonth(new Date().getMonth() + 1);
773                    }
774                    this.Close(event);
775                    break;
776                case 27: // Escape
777                case 9: // Tab
778                    this.Close(event);
779                    break;
780            }
781        },
782
783        _duration: function() {
784            var _dur = this.options.Duration;
785
786            if ($.isNumeric(_dur)) {
787                return _dur;
788            }
789
790            return _dur in _speeds ? _speeds[ _dur ] : _speeds._default;
791        },
792
793        _position: _hasPosition ?
794            function($menu) {
795                var _defauts = this.options.IsRTL ? _RTL_defaultPos : _defaultPos;
796                var _posOpts = $.extend(_defauts, this.options.Position);
797
798                // Only in IE and jQuery 1.12.0 or 2.2.0, .position() will add scrollTop to the top coordinate (#40)
799                return $menu.position($.extend({of: this.element}, _posOpts));
800            } :
801            function($menu) {
802                // Only in IE and jQuery 1.12.0 or 2.2.0, .offset() will add scrollTop to the top coordinate (#40)
803                var _el = this.element,
804                    _css = { top: (_el.offset().top + _el.height() + 7) + 'px' };
805
806                if (this.options.IsRTL) {
807                    _css.left = (_el.offset().left-$menu.width()+_el.width() + 7) + 'px';
808                } else {
809                    _css.left = _el.offset().left + 'px';
810                }
811
812                return $menu.css(_css);
813            },
814
815        _setUseInputMask: function () {
816            if (!this._isMonthInputType) {
817                try {
818                    if (this.options.UseInputMask) {
819                        this.element.mask( this._formatMonth(new Date).replace(/\d/g, 9) );
820                    } else {
821                        this.element.unmask();
822                    }
823                } catch (e) {}
824            }
825        },
826
827        _setDisabledState: function () {
828            var isDisabled = this.options.Disabled, _elem = this.element;
829
830            // Disable the associated input field.
831            _elem[0].disabled = isDisabled;
832            _elem.toggleClass(_disabledClass, isDisabled);
833
834            if (isDisabled) {
835                this._validationMessage.hide();
836            }
837
838            this.Close();
839            this._updateButton();
840
841            _event('OnAfterSetDisabled', this)(isDisabled);
842        },
843
844        _getPickerYear: function () {
845            return this._pickerYear;
846        },
847
848        _setPickerYear: function (year) {
849            this._pickerYear = year || new Date().getFullYear();
850            this._titleButton.jqueryUIButton({ label: this._i18n('year') + ' ' + this._pickerYear });
851        },
852
853        // When calling this method with a falsy (undefined) date
854        // value, this.element.val() is used as the date value.
855        //
856        // Therefore it's important to update the input field
857        // before calling this method.
858        _updateAlt: function (noop, date) {
859            var _field = $(this.options.AltField);
860            if (_field.length) {
861                _field.val( this._formatMonth(date, this.options.AltFormat) );
862            }
863        },
864
865        _chooseMonth: function (month) {
866            var _year = this._getPickerYear();
867            var date = new Date(_year, month-1);
868            this.element.val(this._formatMonth( date )).blur();
869            this._updateAlt(0, date);
870
871            _setActive( this._selectedBtn, false );
872            this._selectedBtn = _setActive( $(this._buttons[month-1]), true );
873
874            _event('OnAfterChooseMonth', this)(date);
875        },
876
877        _chooseYear: function (year) {
878            this._backToYear = 0;
879            this._setPickerYear(year);
880            this._buttons.removeClass(_todayClass);
881            this._showMonths();
882            this._applyJumpYearsHint();
883
884            _event('OnAfterChooseYear', this)();
885        },
886
887        _showMonths: function () {
888            var _months = this._i18n('months');
889
890            this._prevButton
891                .attr('title', this._i18n('prevYear'))
892                .off(click)
893                .on(click, $proxy(this._addToYear, this, -1));
894
895            this._nextButton
896                .attr('title', this._i18n('nextYear'))
897                .off(click)
898                .on(click, $proxy(this._addToYear, this, 1));
899
900            this._buttons.off(_eventsNs);
901
902            var me = this, _onMonthClick = $proxy(me._onMonthClick, me);
903            $.each(_months, function(index, monthName) {
904                $(me._buttons[index])
905                    .on(click, {month: index+1}, _onMonthClick )
906                    .jqueryUIButton('option', 'label', monthName);
907            });
908
909            this._decorateButtons();
910        },
911
912        _showYearsClickHandler: function () {
913            this._buttons.removeClass(_todayClass);
914            if (!this._backToYear) {
915                this._backToYear = this._getPickerYear();
916                this._showYears();
917
918                var _label = this._i18n('backTo') + ' ' + this._getPickerYear();
919                this._titleButton.jqueryUIButton({ label: _label }).data( _clearHint )();
920
921                _event('OnAfterChooseYears', this)();
922            } else {
923                this._setPickerYear(this._backToYear);
924                this._applyJumpYearsHint();
925                this._showMonths();
926                this._backToYear = 0;
927            }
928        },
929
930        _showYears: function () {
931            var _currYear = this._getPickerYear(),
932                _yearDifferential = -4,
933                _firstYear = (_currYear + _yearDifferential),
934                AMOUNT_TO_ADD = 12,
935                _thisYear = new Date().getFullYear();
936
937            var _minDate = this._MinMonth;
938            var _maxDate = this._MaxMonth;
939            var _minYear = _minDate ? _toYear(_minDate) : 0;
940            var _maxYear = _maxDate ? _toYear(_maxDate) : 0;
941            this._prevButton
942                .attr('title', this._i18n('prev12Years'))
943                .off(click)
944                .on(click, $proxy(this._addToYears, this, -AMOUNT_TO_ADD));
945
946            this._nextButton
947                .attr('title', this._i18n('next12Years'))
948                .off(click)
949                .on(click, $proxy(this._addToYears, this, AMOUNT_TO_ADD));
950
951            _setDisabled(this._prevButton, _minYear && (_firstYear - 1) < _minYear);
952            _setDisabled(this._nextButton, _maxYear && (_firstYear + 12) -1 > _maxYear);
953
954            this._buttons.off(_eventsNs);
955
956            _setActive( this._selectedBtn, false );
957
958            var _selYear = this.GetSelectedYear();
959            var _onClick = $proxy(this._onYearClick, this);
960            var _todayWithinBounds = _between(_thisYear, _minYear, _maxYear);
961            var _selWithinBounds = _between(_selYear, _minYear, _maxYear);
962
963            for (var _counter = 0; _counter < 12; _counter++) {
964                var _year = _currYear + _yearDifferential;
965
966                var _btn = $( this._buttons[_counter] ).jqueryUIButton({
967                        disabled: !_between(_year, _minYear, _maxYear),
968                        label: _year
969                    })
970                    .toggleClass(_todayClass, _year === _thisYear && _todayWithinBounds) // Heighlight the current year.
971                    .on(click, { year: _year }, _onClick );
972
973                 // Heighlight the selected year.
974                if (_selWithinBounds && _selYear && _selYear === _year) {
975                    this._selectedBtn = _setActive( _btn , true );
976                }
977
978                _yearDifferential++;
979            }
980        },
981
982        _onMonthClick: function(event) {
983            this._chooseMonth(event.data.month);
984            this.Close(event);
985        },
986
987        _onYearClick: function(event) {
988            this._chooseYear(event.data.year);
989        },
990
991        _addToYear: function(amount) {
992            this._setPickerYear( this._getPickerYear() + amount );
993            this.element.focus();
994            this._decorateButtons();
995
996            _event('OnAfter' + (amount > 0 ? 'Next' : 'Previous') + 'Year', this)();
997        },
998
999        _addToYears: function(amount) {
1000            this._pickerYear = this._getPickerYear() + amount;
1001            this._showYears();
1002            this.element.focus();
1003
1004            _event('OnAfter' + (amount > 0 ? 'Next' : 'Previous') + 'Years', this)();
1005        },
1006
1007        _ajustYear: function(_opts) {
1008            var _year = _opts.StartYear || this.GetSelectedYear() || new Date().getFullYear();
1009            if (this._MinMonth !== null) {
1010                _year = Math.max(_toYear(this._MinMonth), _year);
1011            }
1012            if (this._MaxMonth !== null) {
1013                _year = Math.min(_toYear(this._MaxMonth), _year);
1014            }
1015
1016            this._setPickerYear( _year );
1017        },
1018
1019        _decorateButtons: function() {
1020            var _curYear = this._getPickerYear(), _todaysMonth = _toMonth(new Date),
1021                _minDate = this._MinMonth, _maxDate = this._MaxMonth;
1022
1023            // Heighlight the selected month.
1024            _setActive( this._selectedBtn, false );
1025            var _sel = this.GetSelectedDate();
1026            var _withinBounds = _between(_sel ? _toMonth(_sel) : null, _minDate, _maxDate);
1027
1028            if (_sel && _sel.getFullYear() === _curYear) {
1029                this._selectedBtn = _setActive( $(this._buttons[_sel.getMonth()]) , _withinBounds );
1030            }
1031
1032            // Disable the next/prev button if we've reached the min/max year.
1033            _setDisabled(this._prevButton,  _minDate && _curYear == _toYear(_minDate));
1034            _setDisabled(this._nextButton,  _maxDate && _curYear == _toYear(_maxDate));
1035
1036            for (var i = 0; i < 12; i++) {
1037                // Disable the button if the month is not between the
1038                // min and max interval.
1039                var _month = (_curYear * 12) + i, _isBetween = _between(_month, _minDate, _maxDate);
1040
1041                $(this._buttons[i])
1042                    .jqueryUIButton({ disabled: !_isBetween })
1043                    .toggleClass(_todayClass, _isBetween && _month == _todaysMonth); // Highlights today's month.
1044            }
1045        }
1046    });
1047}(jQuery, window, document, Date));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.