Как управлять позиционированием jQueryUI datepicker - PullRequest
34 голосов
/ 30 ноября 2009

Средство выбора даты в jQueryUI отображается с динамической позицией. Он рендерится в соответствии со своим CSS, если для этого достаточно места, но если не хватает места в окне, он пытается отобразить на экране. Мне нужно, чтобы он всегда оставался на месте и отображался в одном и том же месте, независимо от положения экрана или других обстоятельств. Как это можно сделать с помощью инструмента выбора даты jQueryUI? Другие реализации jQuery datepicker, кажется, имеют способы сделать это, но я не вижу способа сделать это для версии пользовательского интерфейса.

Кажется, что ответ не просто изменяет CSS:

.ui-datepicker { width: 17em; padding: .2em .2em 0; (trying top/margin-top/position:relative, etc. here...)}

... поскольку при создании указателя даты он динамически создает верхний и левый элементы в стиле элемента. Пока не нашли способ обойти это. Один из подходов, который я видел, - это дать что-то подобное в параметре beforeShow:

beforeShow: function(input,inst){
                                inst.dpDiv.css({ 
                                   'top': input.offsetHeight+ 'px', 
                                   'left':(input.offsetWidth - input.width)+ 'px'
                                               });
                                }

Это имеет некоторый эффект, но свойства top и left по-прежнему динамически устанавливаются после того, как они запускаются при рендере DatePicker. Это все еще пытается сделать на экране. Как мне заставить его всегда рендериться в одном и том же месте? Мой следующий шаг, вероятно, состоит в том, чтобы пойти в кишки сборщика даты и начать вытаскивать вещи. Есть идеи?

Обратите внимание, что ответ (для версии пользовательского интерфейса) не в:

Ответы [ 13 ]

65 голосов
/ 13 мая 2010

Размещение этого в надежде, что это поможет другим. По крайней мере, начиная с v1.8.1 DatePicker, использование 'window.DP_jQuery.datepicker' больше не работает, потому что указатель (правильный термин?) Теперь называется с отметкой времени его создания - так, например, теперь это будет 'window. DP_jQuery_1273700460448. Так что теперь, вместо того чтобы использовать указатель на объект datepicker, обращайтесь к нему прямо так:

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

Большое спасибо за ответ ниже, что получил то, что мне нужно.

9 голосов
/ 30 ноября 2009

Редактировать: JaredC дал обновленный ответ для более поздних версий jQuery выше. Переключение принятого ответа на этот вопрос.

Ладно, это вопрос обезьяны-патча функции, которую он имеет, пытаясь всегда визуализировать в окне просмотра, так как нет никакой опции для включения / отключения этой функции. К счастью, он не связан и изолирован в одной функции, поэтому мы можем просто войти и переопределить его. Следующий код полностью отключает только эту функцию:

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

_checkOffset вызывается при его открытии, и он выполняет вычисления для смещения и возвращает новое смещение, если оно в противном случае было бы вне порта просмотра. Это заменяет тело функции, чтобы просто передать исходное смещение. Затем вы можете использовать хак с настройкой beforeShow и / или класс .ui-datepicker css, чтобы поместить его в любое место.

6 голосов
/ 22 февраля 2013

bind focusin после использования DatePicker изменить CSS виджета DatePicker желаю помощи

$('input.date').datepicker();
$('input.date').focusin(function(){
    $('input.date').datepicker('widget').css({left:"-=127"});
});
3 голосов
/ 06 июня 2016

с jQuery:

beforeShow : function(input,inst){
    var offset = $(input).offset();
    var height = $(input).height();
    window.setTimeout(function () {
        $(inst.dpDiv).css({ top: (offset.top + height) + 'px', left:offset.left + 'px' })
    }, 1);
}
3 голосов
/ 02 июня 2016

Проблема, с которой я столкнулся, заключается в том, что средство выбора даты неправильно расположено внутри фиксированных элементов, таких как модные / лайтбоксы. По какой-то причине указатель даты переключается в «фиксированный» режим позиционирования, когда это происходит, и затем вычисление смещения становится неправильным, когда абсолютное позиционирование работало бы просто отлично.

Однако, мы можем получить правильную фиксированную позицию с помощью этого хака:

const checkOffset = $.datepicker._checkOffset;

$.extend($.datepicker, {
    _checkOffset: function(inst, offset, isFixed) {
        if(!isFixed) {
            return checkOffset.apply(this, arguments);
        }

        let isRTL = this._get(inst, "isRTL");
        let obj = inst.input[0];

        while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
            obj = obj[isRTL ? "previousSibling" : "nextSibling"];
        }

        let rect = obj.getBoundingClientRect();

        return {
            top: rect.top,
            left: rect.left,
        };
    }
});
1 голос
/ 19 апреля 2018
$("first-selector").datepicker().bind('click',function () {
      $("#ui-datepicker-div").appendTo("other-selector");
});

<style>
#ui-datepicker-div {
        position: absolute !important;
        top: auto !important;
        left: auto !important;
        z-index: 99999999 !important;
}
</style>
1 голос
/ 01 августа 2016

Принятый ответ в целом работает очень хорошо.

Однако при использовании jQuery UI v1.11.4 у меня возникла проблема, из-за которой указатель даты позиционировался вдали от ввода в модальном окне (фиксированное позиционирование), когда окно браузера было прокручено вниз. Я смог решить эту проблему, отредактировав принятый ответ следующим образом:

const checkOffset = $.datepicker._checkOffset;

$.extend($.datepicker, {
  _checkOffset: function(inst, offset, isFixed) {
    if(isFixed) {
      return checkOffset.apply(this, arguments);
    } else {
      return offset;
    }
  }
});
1 голос
/ 09 марта 2016

Это довольно старый вопрос, однако недавно я столкнулся с проблемой, подобной этой, с jQuery UI Datepicker. Мы уже использовали решение, опубликованное @JaredC выше (в частности, этот фрагмент кода: $.extend($.datepicker,{_checkOffset:function(inst,offset,isFixed){return offset}});), однако оно не будет работать для модального объекта, у которого есть вход, для которого нам нужно было отобразить раскрывающийся список.

Эта проблема возникает из-за того, что при прокрутке вниз страницы смещение ввода в модальном режиме изменяется относительно верха прокручиваемой страницы. Получившееся поведение будет означать, что средство выбора даты будет отображаться в другом вертикальном положении в зависимости от того, как далеко вы прокручивали страницу вниз (примечание: пока видимый и прокручиваемый указатель даты уже исправлен). Решение этой проблемы («ввод DatePicker, вложенный в модальный режим») состоит в том, чтобы вместо этого вычислить вертикальное расположение ввода относительно экрана просмотра, а затем добавить высоту ввода (позволяя свойству css «top» DatePicker быть прямо под входом).

Следующий фрагмент написан в coffeescript. Вместо того, чтобы возвращать обычное смещение в соответствии с решением @ JaredC, мы вместо этого получаем elementId ввода из объекта 'inst' и затем обращаемся к объекту через jquery, чтобы использовать его для вычисления расстояния ввода от верхней части экрана относительно окно просмотра.

# CoffeeScript
$.extend( $.datepicker, { _checkOffset: (inst,offset,isFixed) ->
        offset.top = $("##{inst.id}").offset().top - $(window).scrollTop() + $("##{inst.id}")[0].getBoundingClientRect().height
        offset
    }
)

// JavaScript
$.extend($.datepicker, {
    _checkOffset: function(inst, offset, isFixed) {
        offset.top = $("#" + inst.id).offset().top - $(window).scrollTop() + $("#" + inst.id)[0].getBoundingClientRect().height;
        return offset;
    }
});
1 голос
/ 18 июня 2014

ранее я пытался задать top, оставленный в beforeShow событии datepicker.js, который переопределяется методом _showDatePicker из jquery-ui-custom.js Но после тайм-аута окно работает нормально. Ниже приведен код

beforeShow : function(input,inst) {
  var offset = js.select("#" + dpId).offset();
                        var height = js.select("#" + dpId).height();
                        var width = js.select("#" + dpId).width();
                        window.setTimeout(function () {
                              js.select(inst.dpDiv).css({ top: (offset.top + height - 185) + 'px', left: (offset.left + width + 50) + 'px' })
                        }, 1);
}
1 голос
/ 12 октября 2012

В вашем файле CSS, например:

#ui-datepicker-div {
  position: absolute !important;
  top: auto !important;
  left: auto !important;
}

Ваши важные настройки, какими бы они ни были, переопределят встроенные значения по умолчанию.

...