LoginSignup
0
0

More than 5 years have passed since last update.

JQueryのDatepickerを年月指定のカレンダー選択入力に変える

Posted at

日付をカレンダーから選択して年月日をinputに設定できるJQueryのdatepicker。
日付入力欄がある画面を作る場合、フォーマットの問題もあるのでかなり重宝する。
これを日付選択ではなく、年月を選択して月初日や月末日を入力欄に設定したいとの要件があったため対応。
その時のソースをせっかくなのでメモしておく。
#修正箇所については後日説明を追記したいと思うが、取り急ぎソースのみ貼り付け

JQueryのDatepickerを年月指定のカレンダー選択入力に変える
(function( factory ) {
    if ( typeof define === "function" && define.amd ) {
        // AMD. Register as an anonymous module.
        define([ "jquery" ], factory );
    } else {
        // Browser globals
        factory( jQuery );
    }
}(function( $ ) {
/*!
 * monthpicker
 * customized jQuery-UI's datepicker.
 * It must be included jquery-ui.js or jquery-ui.min.js, if you use this.
 */
$.extend($.ui, { monthpicker: { version: "based on datepicker 1.11.4" } });
var datepicker_instActive;
function datepicker_getZindex( elem ) {
    var position, value;
    while ( elem.length && elem[ 0 ] !== document ) {
        // Ignore z-index if position is set to a value where z-index is ignored by the browser
        // This makes behavior of this function consistent across browsers
        // WebKit always returns auto if the element is positioned
        position = elem.css( "position" );
        if ( position === "absolute" || position === "relative" || position === "fixed" ) {
            // IE returns 0 when zIndex is not specified
            // other browsers return a string
            // we ignore the case of nested elements with an explicit value of 0
            // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
            value = parseInt( elem.css( "zIndex" ), 10 );
            if ( !isNaN( value ) && value !== 0 ) {
                return value;
            }
        }
        elem = elem.parent();
    }
    return 0;
}
function Monthpicker() {
    this._curInst = null; // The current instance in use
    this._keyEvent = false; // If the last event was a key event
    this._disabledInputs = []; // List of date picker inputs that have been disabled
    this._datepickerShowing = false; // True if the popup picker is showing , false if not
    this._inDialog = false; // True if showing within a "dialog", false if not
    this._mainDivId = "ui-monthpicker-div"; // The ID of the main datepicker division
    this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
    this._appendClass = "ui-datepicker-append"; // The name of the append marker class
    this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
    this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
    this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
    this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
    this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
    this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
    this.regional = []; // Available regional settings, indexed by language code
    this.regional[""] = { // Default regional settings
        closeText: "Done", // Display text for close link
        prevText: "Prev", // Display text for previous month link
        nextText: "Next", // Display text for next month link
        currentText: "Today", // Display text for current month link
        monthNames: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'], // Names of months for drop-down and formatting
        monthNamesShort: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'], // For formatting
        dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
        dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
        dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
        weekHeader: "Wk", // Column header for week of the year
        dateFormat: 'yy/mm/dd', // See format options on parseDate
        firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
        isRTL: false, // True if right-to-left language, false if left-to-right
        showMonthAfterYear: false, // True if the year select precedes month, false for month then year
        yearSuffix: "" // Additional text to append to the year in the month headers
    };
    this._defaults = { // Global defaults for all the date picker instances
        showOn: "focus", // "focus" for popup on focus,
            // "button" for trigger button, or "both" for either
        showAnim: "fadeIn", // Name of jQuery animation for popup
        showOptions: {}, // Options for enhanced animations
        defaultDate: null, // Used when field is blank: actual date,
            // +/-number for offset from today, null for today
        appendText: "", // Display text following the input box, e.g. showing the format
        buttonText: "...", // Text for trigger button
        buttonImage: "", // URL for trigger button image
        buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
        hideIfNoPrevNext: false, // True to hide next/previous month links
            // if not applicable, false to just disable them
        navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
        gotoCurrent: false, // True if today link goes back to current selection instead
        changeMonth: false, // True if month can be selected directly, false if only prev/next
        changeYear: false, // True if year can be selected directly, false if only prev/next
        yearRange: "c-10:c+10", // Range of years to display in drop-down,
            // either relative to today's year (-nn:+nn), relative to currently displayed year
            // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
        showOtherMonths: true, // True to show dates in other months, false to leave blank
        selectOtherMonths: true, // True to allow selection of dates in other months, false for unselectable
        showWeek: false, // True to show week of the year, false to not show it
        calculateWeek: this.iso8601Week, // How to calculate the week of the year,
            // takes a Date and returns the number of the week for it
        shortYearCutoff: "+10", // Short year values < this are in the current century,
            // > this are in the previous century,
            // string value starting with "+" for current year + value
        minDate: '2000/01/01', // The earliest selectable date, or null for no limit
        maxDate: '9999/12/31', // The latest selectable date, or null for no limit
        duration: "fast", // Duration of display/closure
        beforeShowDay: null, // Function that takes a date and returns an array with
            // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
            // [2] = cell title (optional), e.g. $.datepicker.noWeekends
        beforeShow: null, // Function that takes an input field and
            // returns a set of custom settings for the date picker
        onSelect: null, // Define a callback function when a date is selected
        onChangeMonthYear: null, // Define a callback function when the month or year is changed
        onClose: null, // Define a callback function when the datepicker is closed
        numberOfMonths: 1, // Number of months to show at a time
        showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
        stepMonths: 12, // Number of months to step back/forward
        stepBigMonths: 12, // Number of months to step back/forward for the big links
        altField: "", // Selector for an alternate field to store selected dates into
        altFormat: "", // The date format to use for the alternate field
        constrainInput: true, // The input is constrained by the current date format
        showButtonPanel: true, // True to show button panel, false to not show it
        autoSize: false, // True to size the input for the date format, false to leave as is
        disabled: false // The initial disabled state
    };
    $.extend(this._defaults, this.regional[""]);
    this.regional.en = $.extend( true, {}, this.regional[ "" ]);
    this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
    this.dpDiv = monthpicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
}
$.extend(Monthpicker.prototype, $.datepicker.constructor.prototype, {
    /* Class name added to elements to indicate already configured with a date picker. */
    markerClassName: "hasMonthpicker",
    //Keep track of the maximum number of rows displayed (see #7043)
    maxRows: 4,
    /* Make attachments based on settings. */
    _attachments: function(input, inst) {
        var showOn, buttonText, buttonImage,
            appendText = this._get(inst, "appendText"),
            isRTL = this._get(inst, "isRTL");
        if (inst.append) {
            inst.append.remove();
        }
        if (appendText) {
            inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
            input[isRTL ? "before" : "after"](inst.append);
        }
        input.unbind("focus", this._showDatepicker);
        if (inst.trigger) {
            inst.trigger.remove();
        }
        showOn = this._get(inst, "showOn");
        if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
            input.focus(this._showDatepicker);
        }
        if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
            buttonText = this._get(inst, "buttonText");
            buttonImage = this._get(inst, "buttonImage");
            inst.trigger = $(this._get(inst, "buttonImageOnly") ?
                $("<img/>").addClass(this._triggerClass).
                    attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
                $("<button type='button'></button>").addClass(this._triggerClass).
                    html(!buttonImage ? buttonText : $("<img/>").attr(
                    { src:buttonImage, alt:buttonText, title:buttonText })));
            input[isRTL ? "before" : "after"](inst.trigger);
            inst.trigger.click(function() {
                if ($.monthpicker._datepickerShowing && $.monthpicker._lastInput === input[0]) {
                    $.monthpicker._hideDatepicker();
                } else if ($.monthpicker._datepickerShowing && $.monthpicker._lastInput !== input[0]) {
                    $.monthpicker._hideDatepicker();
                    $.monthpicker._showDatepicker(input[0]);
                } else {
                    $.monthpicker._showDatepicker(input[0]);
                }
                return false;
            });
        }
    },
    /* Update or retrieve the settings for a date picker attached to an input field or division.
     * @param  target  element - the target input field or division or span
     * @param  name object - the new settings to update or
     *              string - the name of the setting to change or retrieve,
     *              when retrieving also "all" for all instance settings or
     *              "defaults" for all global defaults
     * @param  value   any - the new value for the setting
     *              (omit if above is an object or to retrieve a value)
     */
    _optionDatepicker: function(target, name, value) {
        var settings, date, minDate, maxDate,
            inst = this._getInst(target);
        if (arguments.length === 2 && typeof name === "string") {
            return (name === "defaults" ? $.extend({}, $.monthpicker._defaults) :
                (inst ? (name === "all" ? $.extend({}, inst.settings) :
                this._get(inst, name)) : null));
        }
        settings = name || {};
        if (typeof name === "string") {
            settings = {};
            settings[name] = value;
        }
        if (inst) {
            if (this._curInst === inst) {
                this._hideDatepicker();
            }
            date = this._getDateDatepicker(target, true);
            minDate = this._getMinMaxDate(inst, "min");
            maxDate = this._getMinMaxDate(inst, "max");
            datepicker_extendRemove(inst.settings, settings);
            // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
            if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
                inst.settings.minDate = this._formatDate(inst, minDate);
            }
            if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
                inst.settings.maxDate = this._formatDate(inst, maxDate);
            }
            if ( "disabled" in settings ) {
                if ( settings.disabled ) {
                    this._disableDatepicker(target);
                } else {
                    this._enableDatepicker(target);
                }
            }
            this._attachments($(target), inst);
            this._autoSize(inst);
            this._setDate(inst, date);
            this._updateAlternate(inst);
            this._updateDatepicker(inst);
        }
    },
    /* Handle keystrokes. */
    _doKeyDown: function(event) {
        var onSelect, dateStr, sel,
            inst = $.monthpicker._getInst(event.target),
            handled = true,
            isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
        inst._keyEvent = true;
        if ($.monthpicker._datepickerShowing) {
            switch (event.keyCode) {
                case 9: $.monthpicker._hideDatepicker();
                        handled = false;
                        break; // hide on tab out
                case 13: sel = $("td." + $.monthpicker._dayOverClass + ":not(." +
                                    $.monthpicker._currentClass + ")", inst.dpDiv);
                        if (sel[0]) {
                            $.monthpicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, 1, sel[0]);
                        }
                        onSelect = $.monthpicker._get(inst, "onSelect");
                        if (onSelect) {
                            dateStr = $.monthpicker._formatDate(inst);
                            // trigger custom callback
                            onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
                        } else {
                            $.monthpicker._hideDatepicker();
                        }
                        return false; // don't submit the form
                case 27: $.monthpicker._hideDatepicker();
                        break; // hide on escape
                case 33: $.monthpicker._adjustDate(event.target, (event.ctrlKey ?
                            -$.monthpicker._get(inst, "stepBigMonths") :
                            -$.monthpicker._get(inst, "stepMonths")), "M");
                        break; // previous month/year on page up/+ ctrl
                case 34: $.monthpicker._adjustDate(event.target, (event.ctrlKey ?
                            +$.monthpicker._get(inst, "stepBigMonths") :
                            +$.monthpicker._get(inst, "stepMonths")), "M");
                        break; // next month/year on page down/+ ctrl
                case 35: if (event.ctrlKey || event.metaKey) {
                            $.monthpicker._clearDate(event.target);
                        }
                        handled = event.ctrlKey || event.metaKey;
                        break; // clear on ctrl or command +end
                case 36: if (event.ctrlKey || event.metaKey) {
                            $.monthpicker._gotoToday(event.target);
                        }
                        handled = event.ctrlKey || event.metaKey;
                        break; // current on ctrl or command +home
                case 37: if (event.ctrlKey || event.metaKey) {
                            $.monthpicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
                        }
                        handled = event.ctrlKey || event.metaKey;
                        // -1 day on ctrl or command +left
                        if (event.originalEvent.altKey) {
                            $.monthpicker._adjustDate(event.target, (event.ctrlKey ?
                                -$.monthpicker._get(inst, "stepBigMonths") :
                                -$.monthpicker._get(inst, "stepMonths")), "M");
                        }
                        // next month/year on alt +left on Mac
                        break;
                case 38: if (event.ctrlKey || event.metaKey) {
                            $.monthpicker._adjustDate(event.target, -7, "D");
                        }
                        handled = event.ctrlKey || event.metaKey;
                        break; // -1 week on ctrl or command +up
                case 39: if (event.ctrlKey || event.metaKey) {
                            $.monthpicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
                        }
                        handled = event.ctrlKey || event.metaKey;
                        // +1 day on ctrl or command +right
                        if (event.originalEvent.altKey) {
                            $.monthpicker._adjustDate(event.target, (event.ctrlKey ?
                                +$.monthpicker._get(inst, "stepBigMonths") :
                                +$.monthpicker._get(inst, "stepMonths")), "M");
                        }
                        // next month/year on alt +right
                        break;
                case 40: if (event.ctrlKey || event.metaKey) {
                            $.monthpicker._adjustDate(event.target, +7, "D");
                        }
                        handled = event.ctrlKey || event.metaKey;
                        break; // +1 week on ctrl or command +down
                default: handled = false;
            }
        } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
            $.monthpicker._showDatepicker(this);
        } else {
            handled = false;
        }
        if (handled) {
            event.preventDefault();
            event.stopPropagation();
        }
    },
    /* Filter entered characters - based on date format. */
    _doKeyPress: function(event) {
        var chars, chr,
            inst = $.monthpicker._getInst(event.target);
        if ($.monthpicker._get(inst, "constrainInput")) {
            chars = $.monthpicker._possibleChars($.monthpicker._get(inst, "dateFormat"));
            chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
            return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
        }
    },
    /* Synchronise manual entry and field/alternate field. */
    _doKeyUp: function(event) {
        var date,
            inst = $.monthpicker._getInst(event.target);
        if (inst.input.val() !== inst.lastVal) {
            try {
                date = $.monthpicker.parseDate($.monthpicker._get(inst, "dateFormat"),
                    (inst.input ? inst.input.val() : null),
                    $.monthpicker._getFormatConfig(inst));
                if (date) { // only if valid
                    $.monthpicker._setDateFromField(inst);
                    $.monthpicker._updateAlternate(inst);
                    $.monthpicker._updateDatepicker(inst);
                }
            }
            catch (err) {
            }
        }
        return true;
    },
    /* Pop-up the date picker for a given input field.
     * If false returned from beforeShow event handler do not show.
     * @param  input  element - the input field attached to the date picker or
     *                  event - if triggered by focus
     */
    _showDatepicker: function(input) {
        input = input.target || input;
        if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
            input = $("input", input.parentNode)[0];
        }
        if ($.monthpicker._isDisabledDatepicker(input) || $.monthpicker._lastInput === input) { // already here
            return;
        }
        var inst, beforeShow, beforeShowSettings, isFixed,
            offset, showAnim, duration;
        inst = $.monthpicker._getInst(input);
        if ($.monthpicker._curInst && $.monthpicker._curInst !== inst) {
            $.monthpicker._curInst.dpDiv.stop(true, true);
            if ( inst && $.monthpicker._datepickerShowing ) {
                $.monthpicker._hideDatepicker( $.monthpicker._curInst.input[0] );
            }
        }
        beforeShow = $.monthpicker._get(inst, "beforeShow");
        beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
        if(beforeShowSettings === false){
            return;
        }
        datepicker_extendRemove(inst.settings, beforeShowSettings);
        inst.lastVal = null;
        $.monthpicker._lastInput = input;
        $.monthpicker._setDateFromField(inst);
        if ($.monthpicker._inDialog) { // hide cursor
            input.value = "";
        }
        if (!$.monthpicker._pos) { // position below input
            $.monthpicker._pos = $.monthpicker._findPos(input);
            $.monthpicker._pos[1] += input.offsetHeight; // add the height
        }
        isFixed = false;
        $(input).parents().each(function() {
            isFixed |= $(this).css("position") === "fixed";
            return !isFixed;
        });
        offset = {left: $.monthpicker._pos[0], top: $.monthpicker._pos[1]};
        $.monthpicker._pos = null;
        //to avoid flashes on Firefox
        inst.dpDiv.empty();
        // determine sizing offscreen
        inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
        $.monthpicker._updateDatepicker(inst);
        // fix width for dynamic number of date pickers
        // and adjust position before showing
        offset = $.monthpicker._checkOffset(inst, offset, isFixed);
        inst.dpDiv.css({position: ($.monthpicker._inDialog && $.blockUI ?
            "static" : (isFixed ? "fixed" : "absolute")), display: "none",
            left: offset.left + "px", top: offset.top + "px"});
        if (!inst.inline) {
            showAnim = $.monthpicker._get(inst, "showAnim");
            duration = $.monthpicker._get(inst, "duration");
            inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
            $.monthpicker._datepickerShowing = true;
            if ( $.effects && $.effects.effect[ showAnim ] ) {
                inst.dpDiv.show(showAnim, $.monthpicker._get(inst, "showOptions"), duration);
            } else {
                inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
            }
            if ( $.monthpicker._shouldFocusInput( inst ) ) {
                inst.input.focus();
            }
            $.monthpicker._curInst = inst;
        }
    },
    /* Generate the date picker content. */
    _updateDatepicker: function(inst) {
        this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
        datepicker_inst
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0