jQuery DatePickerコントロールのポップアップ位置を変更する方法


109

DatePickerを関連するテキストボックスのすぐ下ではなく、最後に表示する方法はありますか?起こりがちなのは、テキストボックスがページの下部にあり、DatePickerがそれを考慮して上にシフトし、テキストボックスを完全に覆っていることです。ユーザーが日付を選択するのではなく入力したい場合は、入力できません。テキストボックスの直後に表示したいので、垂直方向の調整方法は関係ありません。

位置を制御する方法はありますか?ウィジェットの設定は表示されず、CSS設定を調整することもできませんでしたが、簡単に何かが欠けている可能性があります。


1
+1は、苦情に「対応する」だけではなく、あなたのソリューションがD_Nのソリューションではないことを示します。
Leonidas

回答:


20

この質問に対する受け入れられた回答は、jQuery UI Datepickerに対するものではありません。jQuery UI Datepickerの位置を変更するには、cssファイルの.ui-datepickerを変更するだけです。Datepickerのサイズもこの方法で変更できます。フォントサイズを調整するだけです。


4
どの変更を加えたか教えてください。
エディ

1
@gfrizzle-ええ、私の答えはまったく間違っていました。最終的にそれをビニングするために動きました。当時私が何を考えていたかはわかりません:/
Kev

64
これがほとんど完全に役に立たないので、これがなぜ受け入れられた答えなのか私にはわかりません。
ソフトウェアエンジニア

10
datepickerはウィジェットをポップアップする前に.ui-datepickerのcssを動的に変更するため、指定された答え完全に役に立たない。
whaefelinger 2015

4
この回答は詳細を示しておらず、承認された回答ではありません。
chapeljuice 2018

120

これが私が使っているものです:

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

左マージンにもう少し追加して、入力フィールドに対して上にならないようにすることもできます。


2
良いトリック。問題は、日付ピッカーが画面の境界を越えて表示される場合、_showDatepickerがそれを再配置しようとするため、上と左が異なり、marginTop、marginLeftの調整が必要になる可能性があることです。
monzonj 2011年

1
同様のアプローチを使用しました-beforeShowを使用するという考えを採用しましたが、beforeShow関数はJQueryUIの位置効果$(this).position(my:'left top', at:'left bottom', of:'#altField')を使用しaltFieldます(表示に日付ピッカーのオプションを使用しているため)
Isaac Betesh

これはマージンを設定するために機能する可能性がありますが、「左」、「上」、「Z-インデックス」、および「位置」属性では失敗します。
aaronbauman 2014年

私が理解しているように、beforeShowが呼び出された後にjqueryが位置をリセットするため、これも機能しません。
ソフトウェアエンジニア

与えられた回答間違っています。beforeShow()が返された後、datepickerが位置をリセットします。
whaefelinger 2015

40

CSSで直接行います。

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

私の日付入力フィールドはすべて100px幅です。カレンダーもAJAXポップアップの上に表示されるように、z-indexも追加しました。

jquery-ui CSSファイルは変更しません。メインのCSSファイルでクラスをオーバーロードしたので、特定のmodを再入力しなくても、テーマを変更したり、ウィジェットを更新したりできます。


他のcss-trickと同じ問題:日付ピッカーをCSS内の正確に配置する必要がある場合にのみ機能します。このメソッドを使用して、日付ピッカーを動的に配置することはできません。私はハックを使用して、inst.input.focus()にバインドする必要がありました
aaronbauman 2014年

Bootstrap :)を使用して私のために働きましたが、私はz-indexプロパティのみを設定しました。
Francisco Goldenstein 2014

入力フィールドがページのどこにあるかわからないので、簡単な実装以外には役に立たない。
ソフトウェアエンジニア

35

これが、Datepickerカレンダーのアラインメントのバリエーションです。

jQuery UI Position utilを使用して位置を制御できるので、それはかなり良いと思います。

1つの制限: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);
    }
})

@kottenatorに感謝します。これは本当に便利です(特に、position.jsを使用)。
セバスチャン

この答えは、position.jsのメリットにすぎません。
whaefelinger 2015

これはv1.11.4でも機能しますが、これは確かに汚いハックです。あまりに悪いjQuery APIでは、afterShowメソッドでこれを行うことができません。
Skoua

29

これは私にとってうまくいく別のバリエーションです、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>


うわーそれは動作します。「inst.dpDiv.css( "top"、 "40px!important");」を使用する 動作しません!
emeraldhieu 2015

タイムアウトを導入することで、プログラム上の問題を克服することは完全ではありません。
whaefelinger 2015

これは私のために働いてくれてありがとう、これからのアフターショーイベントはありますか?しかし今のところ、これは私が関係なく続けるのに役立ちます:D
ロブブラナガン

16

これは私にとってはうまくいきます:

 beforeShow: function(input, inst) {
     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);

6

まずafterShowing、datepickerオブジェクトにメソッドがあるべきだと思います。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ください。内部実装の変更によりコードが破損する可能性があります。


1
彼らはこれをjQuery UIで構成可能な項目として追加しているはずです。
Aleksej Komarov

3

ボーダーレス入力コントロールが存在する親divに従って日付ピッカーを配置する必要がありました。そのために、jquery UIコアに含まれている「位置」ユーティリティを使用しました。beforeShowイベントでこれを行いました。他のユーザーが上記でコメントしたように、beforeShow関数を終了した後で日付ピッカーコードが位置をリセットするため、beforeShowで直接位置を設定することはできません。これを回避するには、単にsetIntervalを使用して位置を設定します。現在のスクリプトが完了し、日付ピッカーが表示され、日付ピッカーが表示された直後に再配置コードが実行されます。発生することはありませんが、0.5秒後にdatepickerが表示されない場合、コードには間隔をあきらめてクリアするためのフェイルセーフがあります。

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

非常に醜い解決策。最大の問題は、突然「再配置」が開始される場所に表示された直後の、日付ピッカーウィジェットの顕著な「ジャンプ」です。すべてのコストで回避する必要があります。
whaefelinger 2015

2

日付ピッカーを使用した後、focusinをバインドします

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

2

カスタム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」は私の予想されるピクセルです。あなたはあなたと変わるかもしれません。


1

表示位置の問題を修正しました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();
        }
    }

1

非常に単純なjquery関数。

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

1

私が開発している新しいサイトのいくつかのページでこの問題を解決するために途方もない時間を費やしましたが、何も機能しないようでした(上で示したさまざまなソリューションを含めて、実装しました。jQueryが変更されたと思います)解決策が機能しないことが示唆されて以来、十分に改善されています。私にはわかりません。正直なところ、これを構成するための単純なものがjQuery uiに実装されていない理由がわかりません。カレンダーのかなり大きな問題で、カレンダーが接続されている入力からページのかなり下の位置に常にポップアップします。

とにかく、私はどこでも使用できて機能するのに十分な汎用性のある最終ソリューションが必要でした。上記のより複雑でjQueryコード固有の回答のいくつかを回避する結論にようやく到達したようです。

jsFiddle:http ://jsfiddle.net/mu27tLen/

HTML:

<input type="text" class="datePicker" />

JS:

positionDatePicker= function(cssToAdd) {
    /* Remove previous positioner */
    var oldScript= document.getElementById('datePickerPosition');
    if(oldScript) oldScript.parentNode.removeChild(oldScript);
    /* Create new positioner */
    var newStyle= document.createElement("style");
    newStyle.type= 'text/css';
    newStyle.setAttribute('id', 'datePickerPostion');
    if(newStyle.styleSheet) newStyle.styleSheet.cssText= cssToAdd;
    else newStyle.appendChild(document.createTextNode(cssToAdd));
    document.getElementsByTagName("head")[0].appendChild(newStyle);
}
jQuery(document).ready(function() {
    /* Initialize date picker elements */
    var dateInputs= jQuery('input.datePicker');
    dateInputs.datepicker();
    dateInputs.datepicker('option', {
        'dateFormat' : 'mm/dd/yy',
        'beforeShow' : function(input, inst) {
            var bodyRect= document.body.getBoundingClientRect();
            var rect= input.getBoundingClientRect();
            positionDatePicker('.page #ui-datepicker-div{z-index:100 !important;top:' + (rect.top - bodyRect.top + input.offsetHeight + 2) + 'px !important;}');
        }
    }).datepicker('setDate', new Date());
});

基本的に、すべてのdatepicker "show"イベントの前に、新しいスタイルタグをヘッドに添​​付します(存在する場合は、前のイベントを削除します)。この方法で、開発中に遭遇した問題の大部分を回避できます。

Chrome、Firefox、Safari、およびIE> 8でテスト済み(IE8はjsFiddleでうまく機能せず、気にかけることへの熱意を失っています)

これはjQueryとjavascriptコンテキストの混合であることは知っていますが、現時点ではjQueryへの変換に力を入れたくありません。簡単だと思います。私は今、これでこれで終わりです。他の誰かがこのソリューションから利益を得ることができることを願っています。


1

彼らはクラス名を ui-datepicker-trigger

したがって、これは jquery 1.11.x

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


1

または、dateSelectオブジェクトでfocusイベントを使用して、apiを一緒に配置することもできます。上と下と左を右または中央(または位置APIから実際に必要なもの)に交換できます。このようにして、間隔や非常に複雑なソリューションを必要とせず、入力の場所に応じてニーズに合わせてレイアウトを構成できます。

dateSelect.focus(function () {
    $("#ui-datepicker-div").position({
        my: "left top",
        at: "left bottom",
        of: $(this)
    });
});

THE BEST / Most正解!!
HirsuteJim

0

IEが互換モードに該当する場合、jQuery UIコンポーネントおよびその他の要素が正しく配置されないことにも注意してください。

Quirksモードに入らないようにするには、Doctypeを最新のHTML5に正しく設定してください。

<!DOCTYPE html>

トランジショナルを使用すると、混乱を招きます。うまくいけば、これは将来誰かを救うでしょう。


0

これにより、機能が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);
}

0

Jquery.UI内で、_checkOffset関数を更新するだけで、offset.topにviewHeightが追加されてから、オフセットが返されます。

_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;
    },

このソリューションは基本的に正しいです。jQuery.extend()を介して独自の_checkOffset()関数を挿入し、「top」と「left」の数値プロパティを持つ任意のオブジェクト、つまりjQuery.extend(jQuery.datepicker、{_checkOffset:function(inst 、offset、isFixed){return {top:mytop、left:myleft };}}); ここで、mytopとmyleftは、たとえばinstから派生した、ユーザーの好みに合わせたものです。
whaefelinger 2015

0
.ui-datepicker {-ms-transform: translate(100px,100px); -webkit-transform: translate(100px,100px); transform: translate(100px,100px);}

なぜ投票は?これは問題に対処していませんか?codepen.io/coconewty/pen/rajbNj
James

投票?質問のタイトルを読んでいるだけで、実際の問題を掘り下げるための努力をしなかったからです。単純に、さまざまな幅の入力フィールドに2つの日付ピッカーが接続されていると想定します。ソリューションでは、各日付ピッカーウィジェットの左端が入力フィールドの右端に確実に接触するようにする方法を教えてください。反対に、あなたの答えの独創性については、少なくとも1つのポイントを取得する必要があります。
whaefelinger 2015

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.