Как изменить положение всплывающего окна элемента управления jQuery DatePicker

Есть идеи, как заставить DatePicker отображаться в конце связанного текстового поля, а не прямо под ним? Что обычно происходит, так это то, что текстовое поле находится в нижней части страницы, а DatePicker смещается вверх, чтобы учесть это, и полностью закрывает текстовое поле. Если пользователь хочет ввести дату, а не выбрать ее, он не сможет. Я бы предпочел, чтобы он отображался сразу после текстового поля, поэтому не имеет значения, как он настраивается по вертикали.

Есть идеи, как контролировать позиционирование? Я не видел никаких настроек для виджета, и мне не удалось настроить настройки CSS, но я легко мог что-то упустить.


person gfrizzle    schedule 19.03.2009    source источник
comment
+1 за то, что не просто обратился к жалобе, что ваше решение не является решением для D_N.   -  person Leonidas    schedule 30.01.2011


Ответы (19)


Принятый ответ на этот вопрос на самом деле не для jQuery UI Datepicker. Чтобы изменить положение jQuery UI Datepicker, просто измените .ui-datepicker в файле css. Размер Datepicker также можно изменить таким же образом, просто отрегулируйте размер шрифта.

person jonmc12    schedule 26.06.2009
comment
Не уверен, почему я изначально принял ответ Кева, потому что я решил свою проблему не так. Я изменил .ui-datepicker, как описано выше. Должно быть, это была долгая ночь. :) - person gfrizzle; 02.02.2011
comment
Не могли бы вы рассказать мне, какие изменения вы внесли? - person eddy; 19.05.2011
comment
@gfrizzle - да, этот мой ответ был совершенно неправильным. Наконец добрались до мусора. Понятия не имею, о чем я тогда думал: / - person Kev; 07.06.2011
comment
Это работает только в том случае, если вы теперь точно знаете, где должен быть указатель даты в CSS. Вы не можете использовать этот метод для динамического размещения датпикера. Пришлось использовать хак, привязку к inst.input.focus () - person aaronbauman; 19.03.2014
comment
Я понятия не имею, почему это принятый ответ, поскольку он почти полностью бесполезен. - person Software Engineer; 25.11.2014
comment
Данный ответ является совершенно бесполезным, поскольку datepicker динамически изменяет css .ui-datepicker перед появлением виджета. - person wh81752; 16.07.2015
comment
Этот ответ не содержит подробностей и не должен быть принятым ответом. - person chapeljuice; 04.12.2018

Вот что я использую:

$('input.date').datepicker({
    beforeShow: function(input, inst) {
        inst.dpDiv.css({
            marginTop: -input.offsetHeight + 'px', 
            marginLeft: input.offsetWidth + 'px'
        });
    }
});

Вы также можете добавить немного больше к левому полю, чтобы оно не совпадало с полем ввода.

person Community    schedule 24.07.2009
comment
Хорошая уловка. Проблема в том, что в тех случаях, когда datepicker отображается за пределами экрана, _showDatepicker будет пытаться переместить его, поэтому верхний и левый угол будут разными, а marginTop, marginLeft может нуждаться в настройке. - person monzonj; 29.06.2011
comment
Я использовал аналогичный подход - я взял вашу идею использования beforeShow, но моя функция beforeShow использует эффект позиции JQueryUI: $(this).position(my:'left top', at:'left bottom', of:'#altField') (поскольку я использую параметр datepicker altField для отображения) - person Isaac Betesh; 13.03.2014
comment
Это может работать для установки полей, но не работает для атрибутов left, top, z-index и position. - person aaronbauman; 19.03.2014
comment
Насколько я понимаю, это тоже не работает, потому что jquery сбрасывает позицию после вызова beforeShow. - person Software Engineer; 25.11.2014
comment
Данный ответ является неверным, потому что datepicker сбросит позицию после того, как beforeShow () вернется. - person wh81752; 16.07.2015
comment
Спас мой день потрясающе - person Arun Bertil; 21.04.2017

Я делаю это прямо в CSS:

.ui-datepicker { 
  margin-left: 100px;
  z-index: 1000;
}

Мои поля ввода даты имеют ширину 100 пикселей. Я также добавил z-index, чтобы календарь также отображался над всплывающими окнами AJAX.

Я не изменяю файл CSS jquery-ui; Я перегружаю класс в моем основном файле CSS, поэтому я могу изменить тему или обновить виджет без повторного ввода моих конкретных модов.

person Christian Lescuyer    schedule 28.08.2009
comment
Та же проблема, что и другой трюк css: работает только в том случае, если теперь вы точно указали, где должен быть указатель даты в CSS. Вы не можете использовать этот метод для динамического размещения датпикера. Пришлось использовать хак, привязку к inst.input.focus () - person aaronbauman; 19.03.2014
comment
У меня работал с использованием Bootstrap :), но я установил только свойство z-index. - person Francisco Goldenstein; 09.09.2014
comment
Бесполезен для чего-либо, кроме тривиальных реализаций, поскольку вы не узнаете, где находится поле ввода на странице. - person Software Engineer; 25.11.2014

Вот мой вариант выравнивания календаря Datepicker.

Я думаю, что это довольно приятно, потому что вы можете управлять позиционированием через jQuery UI Position util.

Одно ограничение: требуется jquery.ui.position.js.

Код:

$('input[name=date]').datepicker({
    beforeShow: function(input, inst) {
        // Handle calendar position before showing it.
        // It's not supported by Datepicker itself (for now) so we need to use its internal variables.
        var calendar = inst.dpDiv;

        // Dirty hack, but we can't do anything without it (for now, in jQuery UI 1.8.20)
        setTimeout(function() {
            calendar.position({
                my: 'right top',
                at: 'right bottom',
                collision: 'none',
                of: input
            });
        }, 1);
    }
})
person Rost    schedule 15.05.2012
comment
Спасибо @kottenator, это действительно полезно (особенно с position.js)! - person Sebastian; 19.02.2015
comment
Эти ответы показывают не что иное, как достоинства position.js. - person wh81752; 16.07.2015
comment
Это все еще работает в v1.11.4, но это действительно грязный хакер, очень плохой API jQuery не позволяет нам сделать это в afterShow методе. - person Skoua; 01.09.2016

Вот еще один вариант, который мне подходит: отрегулируйте rect.top + 40, rect.left + 0 в соответствии с вашими потребностями:

$(".datepicker").datepicker({
    changeMonth: true,
    changeYear: true,
    dateFormat: 'mm/dd/yy',
    beforeShow: function (input, inst) {
        var rect = input.getBoundingClientRect();
        setTimeout(function () {
	        inst.dpDiv.css({ top: rect.top + 40, left: rect.left + 0 });
        }, 0);
    }
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<form>
<input class="datepicker" name="date1" type="text">
<input class="datepicker" name="date2" type="text">
</form>

person Patrick    schedule 19.01.2015
comment
Вау, это работает. Использование inst.dpDiv.css (вверху, 40 пикселей! Важно); не работает! - person emeraldhieu; 26.02.2015
comment
Далеко не идеален для решения программной проблемы с помощью тайм-аута. - person wh81752; 16.07.2015
comment
Спасибо, это сработало для меня, интересно, будет ли когда-нибудь мероприятие afterShow, это было бы здорово !! Но пока это помогает мне продолжать, несмотря ни на что: D - person Rob Branaghan; 17.05.2017
comment
Я пробовал множество других решений, это было единственное, что сработало. - person Calanus; 02.05.2021

Это работает для меня:

beforeShow: function(input, inst) {
    var $this = $(this);
    var cal = inst.dpDiv;
    var top = $this.offset().top + $this.outerHeight();
    var left = $this.offset().left;

    setTimeout(function() {
        cal.css({
            'top': top,
            'left': left
        });
    }, 10);
}
person David Laberge    schedule 23.08.2012

Во-первых, я думаю, что в объекте datepicker должен быть метод afterShowing, где вы могли бы изменить позицию после того, как jquery выполнил всю свою вуду в методе _showDatepicker. Кроме того, также желателен параметр с именем preferedPosition, поэтому вы можете установить его, а jquery изменить его в случае, если диалог отображается вне области просмотра.

Есть «трюк», чтобы сделать это последнее. Если вы изучите метод _showDatepicker, вы увидите использование частной переменной $.datepikcer._pos. Эта переменная будет настроена, если ее еще никто не настраивал. Если вы измените эту переменную перед отображением диалогового окна, JQuery примет ее и попытается разместить диалоговое окно в этой позиции, а если он отображается за пределами экрана, он отрегулирует его, чтобы убедиться, что он виден. Звучит хорошо, а?

Проблема в том; _pos является личным, но если вы не против. Вы можете:

$('input.date').datepicker({
    beforeShow: function(input, inst)
    {
        $.datepicker._pos = $.datepicker._findPos(input); //this is the default position
        $.datepicker._pos[0] = whatever; //left
        $.datepicker._pos[1] = whatever; //top
    }
});

Но будьте осторожны с обновлениями Jquery-ui, потому что изменение внутренней реализации _showDatepicker может нарушить ваш код.

person monzonj    schedule 29.06.2011
comment
Они должны были добавить это в пользовательский интерфейс jQuery как настраиваемый элемент. - person Aleksej Komarov; 20.05.2014

Мне нужно было расположить datepicker в соответствии с родительским div, в котором находился мой элемент управления вводом без полей. Для этого я использовал утилиту "position", включенную в ядро ​​jquery UI. Я сделал это на мероприятии beforeShow. Как другие комментировали выше, вы не можете установить позицию непосредственно в beforeShow, так как код datepicker сбросит местоположение после завершения функции beforeShow. Чтобы обойти это, просто установите позицию с помощью setInterval. Текущий сценарий завершится, и появится указатель даты, а затем код изменения положения будет запущен сразу после того, как указатель даты станет видимым. Хотя этого никогда не должно происходить, но если указатель даты не отображается через 0,5 секунды, код имеет отказоустойчивый режим, позволяющий отказаться и очистить интервал.

        beforeShow: function(a, b) {
            var cnt = 0;
            var interval = setInterval(function() {
                cnt++;
                if (b.dpDiv.is(":visible")) {
                    var parent = b.input.closest("div");
                    b.dpDiv.position({ my: "left top", at: "left bottom", of: parent });
                    clearInterval(interval);
                } else if (cnt > 50) {
                    clearInterval(interval);
                }
            }, 10);
        }
person Brett Birschbach    schedule 01.09.2011
comment
Очень некрасивое решение. Самая большая проблема - это заметный скачок виджета datepicker сразу после того, как он стал видимым, где внезапно начинается ваше перемещение. Избегать любой ценой. - person wh81752; 16.07.2015

привязать focusin после использования datepicker изменить css виджета datepicker желаю помощи

$('input.date').datepicker();
$('input.date').focusin(function(){
    $('input.date').datepicker('widget').css({left:"-=127"});
});
person anubiskong    schedule 22.02.2013

Я исправил это с помощью собственного кода jquery.

  1. присвоил моему полю ввода datepicker класс ".datepicker2"

  2. найти его текущее положение сверху и

  3. разместил всплывающее окно с именем класса ".ui-datepicker"

вот мой код.

$('.datepicker2').click(function(){
    var popup =$(this).offset();
    var popupTop = popup.top - 40;
    $('.ui-datepicker').css({
      'top' : popupTop
     });
});

здесь «40» - это мой ожидаемый пиксель, вы можете поменять его на свой.

person sh6210    schedule 02.06.2016

Очень простая функция jquery.

$(".datepicker").focus(function(event){
                var dim = $(this).offset();
                $("#ui-datepicker-div").offset({
                    top     :   dim.top - 180,
                    left    :   dim.left + 150
                });
            });
person Harry    schedule 07.08.2014

Или вы можете использовать событие focus на своем объекте dateSelect и позиционировать api вместе. Вы можете поменять местами верхний, нижний и левый на правый или центральный (или действительно все, что вы хотите из позиции api). Таким образом, вам не нужен интервал или какое-либо безумно сложное решение, и вы можете настроить макет в соответствии со своими потребностями в зависимости от того, где находится ввод.

dateSelect.focus(function () {
    $("#ui-datepicker-div").position({
        my: "left top",
        at: "left bottom",
        of: $(this)
    });
});
person Taugenichts    schedule 09.10.2018
comment
Лучший / самый правильный ответ !! - person HirsuteJim; 05.07.2020

Я взял его из ((Как контролировать позиционирование jQueryUI datepicker) )

$.extend($.datepicker, { 
    _checkOffset: function(inst, offset, isFixed) { 
        return offset 
    } 
});

оно работает !!!

person masoud Cheragee    schedule 13.05.2015
comment
Ответ правильный, хотя по существу уже ответил ранее. - person wh81752; 16.07.2015

исправить проблему отображения позиции daterangepicker.jQuery.js

//Original Code
//show, hide, or toggle rangepicker
    function showRP() {
        if (rp.data('state') == 'closed') {
            rp.data('state', 'open');
            rp.fadeIn(300);
            options.onOpen();
        }
    }


//Fixed
//show, hide, or toggle rangepicker
    function showRP() {
        rp.parent().css('left', rangeInput.offset().left);
        rp.parent().css('top', rangeInput.offset().top + rangeInput.outerHeight());
        if (rp.data('state') == 'closed') {
            rp.data('state', 'open');
            rp.fadeIn(300);
            options.onOpen();
        }
    }
person zersina    schedule 28.06.2012

Они изменили название класса на ui-datepicker-trigger

Итак, это работает в jquery 1.11.x

.ui-datepicker-trigger { 
margin-top:7px;
  margin-left: -30px;
  margin-bottom:0px;
  position:absolute;
  z-index:1000;
}
person Marc    schedule 21.03.2015

Также стоит отметить, что если IE переходит в режим причуд, ваши компоненты пользовательского интерфейса jQuery и другие элементы будут расположены неправильно.

Чтобы убедиться, что вы не попадете в режим причуд, убедитесь, что вы правильно установили свой doctype на последнюю версию HTML5.

<!DOCTYPE html>

Использование transitional приводит к путанице. Надеюсь, это сэкономит кому-то время в будущем.

person Halfstop    schedule 30.07.2013

Это помещает функциональность в метод с именем function, позволяя вашему коду инкапсулировать ее или сделать метод расширением jquery. Просто используется в моем коде, отлично работает

var nOffsetTop  = /* whatever value, set from wherever */;
var nOffsetLeft = /* whatever value, set from wherever */;

$(input).datepicker
(
   beforeShow : function(oInput, oInst) 
   { 
      AlterPostion(oInput, oInst, nOffsetTop, nOffsetLeft); 
   }
);

/* can be converted to extension, or whatever*/
var AlterPosition = function(oInput, oItst, nOffsetTop, nOffsetLeft)
{
   var divContainer = oInst.dpDiv;
   var oElem        = $(this);
       oInput       = $(oInput);

   setTimeout(function() 
   { 
      divContainer.css
      ({ 
         top  : (nOffsetTop >= 0 ? "+=" + nOffsetTop : "-=" + (nOffsetTop * -1)), 
         left : (nOffsetTop >= 0 ? "+=" + nOffsetLeft : "-=" + (nOffsetLeft * -1))
      }); 
   }, 10);
}
person Brett Weber    schedule 30.04.2014

В Jquery.UI просто обновите функцию _checkOffset, чтобы viewHeight был добавлен в offset.top до того, как будет возвращено смещение.

_checkOffset: function(inst, offset, isFixed) {
    var dpWidth = inst.dpDiv.outerWidth(),
    dpHeight = inst.dpDiv.outerHeight(),
    inputWidth = inst.input ? inst.input.outerWidth() : 0,
    inputHeight = inst.input ? inst.input.outerHeight() : 0,
    viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
            viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : ($(document).scrollTop()||document.body.scrollTop));
        offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
        offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
        offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? ($(document).scrollTop()||document.body.scrollTop) : 0;

        // now check if datepicker is showing outside window viewport - move to a better place if so.
        offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
            Math.abs(offset.left + dpWidth - viewWidth) : 0);
        offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
            Math.abs(dpHeight + inputHeight) : 0);
**offset.top = offset.top + viewHeight;**
        return offset;
    },
person David Moore    schedule 11.07.2014
comment
Это решение, по сути, правильное: введите свою собственную функцию _checkOffset () через jQuery.extend () и верните произвольный объект с числовыми свойствами сверху и слева, т.е. jQuery.extend (jQuery.datepicker, {_checkOffset: function (inst, offset, isFixed ) {return {top: mytop, left: myleft};}}); где mytop и myleft - по вашему вкусу, например, производные от inst. - person wh81752; 16.07.2015

person    schedule
comment
почему голосование? это не решает проблему? codepen.io/coconewty/pen/rajbNj - person James; 12.01.2015
comment
проголосовали? Потому что вы читали только заголовок вопроса и не приложили никаких усилий, чтобы разобраться в реальной проблеме. Просто предположите, что у вас есть два datepicker, прикрепленных к полям ввода с разной шириной. Как ваше решение гарантирует, что левый край каждого виджета datepicker касается правого края поля ввода? С другой стороны, вы должны получить хотя бы один балл за оригинальность ваших ответов. - person wh81752; 16.07.2015