web-dev-qa-db-ja.com

jQueryUI datepickerの位置を制御する方法

JQueryUIの日付ピッカーは、動的な位置でレンダリングします。十分なスペースがある場合はcssに従ってレンダリングしますが、十分なウィンドウスペースがない場合は画面上でレンダリングしようとします。画面の位置やその他の状況に関係なく、常に同じ場所に置いてレンダリングする必要があります。 jQueryUI datepickerでこれをどのように行うことができますか? jQuery datepickerの他の実装にはこれを行う方法があるように見えますが、UIバージョンでそれを行う方法は見当たりません。

答えはcssを変更するだけではないようです:

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

...日付ピッカーが作成されると、要素スタイルで上下を動的に作成します。まだこれを回避する方法を見つけていません。私が見た1つのアプローチは、beforeShowオプションでこのようなものを与えることです:

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

これにはある程度の効果がありますが、datepickerがレンダリングされるときにこれが実行された後も、上部および左側のプロパティが動的に設定されています。まだ画面にレンダリングしようとしています。常に同じ場所でレンダリングするにはどうすればよいですか?私の次のステップは、おそらく日付ピッカーの内臓に入り、物を引き出し始めることです。何か案は?

(UIバージョンの)答えは以下にないことに注意してください。

35
Purrell

これが他の人の役に立つことを期待して投稿しています。少なくともdatepicker v1.8.1の時点で、「window.DP_jQuery.datepicker」の使用は機能しなくなりました。これは、ポインター(正しい用語?)が作成のタイムスタンプで名前が付けられるためです。たとえば、「window」になります。 DP_jQuery_1273700460448 '。したがって、今では、datepickerオブジェクトへのポインターを使用するのではなく、次のように直接参照します。

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

私が必要なものを手に入れてくれた以下の答えに感謝します。

65
JaredC

編集: JaredCは、上記のjQueryの以降のバージョンに対して更新された回答を提供しました。受け入れられた答えを切り替えます。

さて、これは、機能を有効/無効にするオプションが提供されていないため、ビューポートで常にレンダリングしようとする機能を猿パッチする問題です。幸いなことに、それは1つの関数で切り離されて分離されているため、そのままでオーバーライドできます。次のコードは、その機能のみを完全に無効にします。

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

_checkOffsetは、開いているときに呼び出され、オフセットの計算を行い、ビューポートの外側にある場合は新しいオフセットを返します。これにより、関数本体が置き換えられ、元のオフセットがそのまま渡されます。次に、beforeShow設定ハックまたは.ui-datepicker cssクラスを使用して、必要な場所に配置できます。

10
Purrell

datepickerを使用した後にfocusinをバインドするdatepickerのウィジェットのCSSを変更する

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

私が抱えていた問題は、日付ピッカーが派手/ライトボックスなどの固定要素内に誤って配置されていることです。何らかの理由で、これが発生すると、日付ピッカーは「固定」位置決めモードに切り替わり、絶対位置決めがうまく機能するとオフセット計算が不正確になります。

ただし、このハックで正しい固定位置を取得できます。

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,
        };
    }
});
3
mpen

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);
}

あなたのcssファイルで、例えば:

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

重要な設定は、それが何であれ、インラインのデフォルトを上書きします。

1
Joe Lalgee

以前、datepicker.jsのbeforeShowイベントに残っていたtopを与えようとしましたが、jquery-ui-custom.jsの_showDatePickerメソッドによってオーバーライドされます。しかし、タイムアウト後、ウィンドウは正常に機能します。以下はコードです

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
Sudeep

これは私にとってうまくいった方法です:

$( "input[name='birthdate']" ).datepicker({
    beforeShow : function(input,inst){
    window.setTimeout(function () {
        $("#ui-datepicker-div").position({ my: "left top", at: "left bottom", of: input });
    }, 1);
    }
});

画面のサイズが変更されたときに配置するには:

$(window).resize(function(){ $("#ui-datepicker-div").position({ my: "left top", at: "left bottom", of: "input[name='birthdate']" }); });
1
obeliksz
$("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
Pardeep Goyal

これはかなり古い質問ですが、最近、jQuery UI Datepickerでこれに似た問題に遭遇しました。上記の@JaredCによって投稿されたソリューション(具体的にはこのコードスニペット:$.extend($.datepicker,{_checkOffset:function(inst,offset,isFixed){return offset}});)を使用していましたが、ドロップダウンをレンダリングする必要がある入力を含むモーダルでは機能しません。

この問題は、ページを下にスクロールすると、モーダルの入力のオフセットがスクロールされたページの上部に対して変化するために発生します。結果として生じる動作は、ページを下にスクロールした距離に応じて、日付ピッカーが異なる垂直位置にレンダリングされることを意味します(注:表示および日付ピッカーのスクロールは既に修正されています)。この問題(「モーダル内にネストされたdatepicker入力」)の解決策は、代わりにビュー画面に対する入力の垂直位置を計算し、入力の高さを追加することです(datepickerの "top" cssプロパティを許可します)入力のすぐ下にあります)。

次のスニペットはcoffeescriptにあります。 @JaredCのソリューションに従って通常のオフセットを返す代わりに、「inst」オブジェクトから入力のelementIdを取得し、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
Eric Walsh

受け入れられた答えは全体的に非常にうまく機能します。

ただし、jQuery UI v1.11.4を使用すると、ブラウザーウィンドウが下にスクロールされたときに、datepickerがモーダルウィンドウの入力から離れて配置されるという問題がありました(固定配置)。この問題を修正して、受け入れられた回答を次のように編集できました。

const checkOffset = $.datepicker._checkOffset;

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