t1m0n / air-datepicker

Lightweight, dependency-free JavaScript datepicker.
https://air-datepicker.com
MIT License
2.63k stars 1.37k forks source link

Datepicker not scrolling in Bootstrap Modal #334

Open witchsmeller opened 5 years ago

witchsmeller commented 5 years ago

First the datepicker looks and works good. But using it in Bootstrap Modal needed a few changes. First a higher z-index to show up. But it won't scroll with the Content of the modal. For me it works with the following changes:

_buildDatepickersContainer: function () { containerBuilt = true; this.$el.parent().css('position', 'relative'); this.$el.parent().append('<div class="datepickers-container" id="datepickers-container"></div>'); $datepickersContainer = $('#datepickers-container'); },

and

`setPosition: function (position) { console.log(position); position = position || this.opts.position;

        var dims = this._getDimensions(this.$el.parent()), //var dims = this._getDimensions(this.$el),
            selfDims = this._getDimensions(this.$datepicker),
            pos = position.split(' '),
            top, left,
            offset = this.opts.offset,
            main = pos[0],
            secondary = pos[1];

        switch (main) {
            case 'top':
                top = 0 - selfDims.height - offset; //dims.top - selfDims.height - offset
                break;
            case 'right':
                left = dims.width + offset; //dims.left + dims.width + offset
                break;
            case 'bottom':
                top = dims.height + offset; //dims.top + dims.height + offset
                break;
            case 'left':
                left = 0 - selfDims.width - offset;  //dims.left - selfDims.width - offset
                break;
        }

        switch(secondary) {
            case 'top':
                top = 0;    //dims.top
                break;
            case 'right':
                left = dims.width - selfDims.width; //dims.left + dims.width - selfDims.width
                break;
            case 'bottom':
                top = dims.height - selfDims.height;    //dims.top + dims.height - selfDims.height
                break;
            case 'left':
                left = 0;   //dims.left
                break;
            case 'center':
                if (/left|right/.test(main)) {
                    top = dims.height/2 - selfDims.height/2;    //dims.top + dims.height/2 - selfDims.height/2;
                } else {
                    left = dims.width/2 - selfDims.width/2; //dims.left + dims.width/2 - selfDims.width/2
                }
        }`

The datepicker will not be attached to the Body element but to the parent element of the input. It works well with bottom left positioning. Didn't test all options. Maybe it helps someone or it can be incorporated into the datepicker code.

And set "containerbuilt" to false in the hide function

`hide: function () { var onHide = this.opts.onHide;

        this.$datepicker
            .removeClass('active')
            .css({
                left: '-100000px'
            });

        this.focused = '';
        this.keys = [];

        this.inFocus = false;
        this.visible = false;
        this.$el.blur();

        if (onHide) {
            this._bindVisionEvents(onHide)
        }
        containerBuilt = false;
    },`
artar94 commented 4 years ago

Here is another way to fix this problem without touching the air-datepicker code:

$('#my-modal').scroll(() => {
    const datepicker = $('#my-date-input').data('datepicker');
    if (datepicker.visible) {
        datepicker.setPosition(datepicker.opts.position);
    }
});

Of course it would be great to solve this problem inside the air-datepicker. For example, add scrollParent to the configuration.