jQuery DatePicker 컨트롤의 팝업 위치를 변경하는 방법


109

DatePicker가 연결된 텍스트 상자 바로 아래 대신 끝에 표시되도록하는 방법을 알고 계십니까? 발생하는 경향은 텍스트 상자가 페이지 하단에 있고 DatePicker가이를 설명하기 위해 위로 이동하고 텍스트 상자를 완전히 덮는 것입니다. 사용자가 날짜를 선택하는 대신 입력하려는 경우 입력 할 수 없습니다. 차라리 텍스트 상자 바로 뒤에 나타나도록하여 세로로 조정하는 방법은 중요하지 않습니다.

위치를 제어하는 ​​방법을 아십니까? 위젯에 대한 설정이 표시되지 않았고 CSS 설정을 조정하지도 못했지만 쉽게 뭔가를 놓칠 수있었습니다.


1
귀하의 솔루션이 D_N의 솔루션이 아니라고 불만을 "처리"하는 것뿐만 아니라 +1.
Leonidas 2011 년

답변:


20

이 질문에 대한 대답은 실제로 jQuery UI Datepicker가 아닙니다. jQuery UI Datepicker의 위치를 ​​변경하려면 css 파일에서 .ui-datepicker를 수정하면됩니다. Datepicker의 크기도 이러한 방식으로 변경할 수 있으며 글꼴 크기 만 조정하면됩니다.


4
어떤 변경 사항을 적용했는지 말씀해 주시겠습니까?
eddy

1
@gfrizzle-네, 내 대답은 너무 잘못되었습니다. 마침내 그것을 비닝하기 시작했습니다. 그 당시 내가 뭘 생각하고 있었는지 전혀 모르겠다. : /
Kev

64
거의 완전히 쓸모가 없기 때문에 이것이 왜 받아 들여지는 대답인지 모르겠습니다.
소프트웨어 엔지니어

10
datepicker가 위젯을 팝업하기 전에 .ui-datepicker의 CSS를 동적으로 수정하므로 주어진 대답 완전히 쓸모 없습니다.
whaefelinger 2015

4
이 답변은 세부 정보를 제공하지 않으며 허용되는 답변이 아니어야합니다.
chapeljuice

120

내가 사용하는 것은 다음과 같습니다.

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

왼쪽 여백에 조금 더 추가하여 입력 필드에 맞지 않게 할 수도 있습니다.


2
좋은 속임수. 문제는 datepicker가 화면 테두리 너머로 표시되는 경우 _showDatepicker가이를 재배치하려고 시도하므로 위쪽과 왼쪽이 다르고 marginTop, marginLeft가 조정이 필요할 수 있다는 것입니다.
monzonj 2011 년

1
나는 유사한 접근 방식을 사용 - 나는 beforeShow를 사용하여 당신의 생각을했다,하지만 내 beforeShow 기능은 JQueryUI의 위치 효과를 사용합니다 $(this).position(my:'left top', at:'left bottom', of:'#altField')(I이 날짜 선택기의 사용하고 있기 때문에 altField디스플레이 옵션)
이삭 Betesh

여백 설정에는 작동하지만 "left", "top", "z-index"및 "position"속성에 대해서는 실패합니다.
aaronbauman 2014 년

내가 이해했듯이 jquery는 beforeShow가 호출 된 후 위치를 재설정하기 때문에 작동하지 않습니다.
Software Engineer

주어진 대답 잘못된 이유입니다. datepicker는 beforeShow () 반환 후 위치를 재설정합니다.
whaefelinger 2015

40

CSS에서 직접 수행합니다.

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

내 날짜 입력 필드는 모두 100px입니다. 또한 Z- 색인을 추가하여 캘린더도 AJAX 팝업 위에 표시됩니다.

jquery-ui CSS 파일을 수정하지 않습니다. 기본 CSS 파일에서 클래스를 오버로드하므로 특정 모드를 다시 입력하지 않고도 테마를 변경하거나 위젯을 업데이트 할 수 있습니다.


다른 css-trick과 동일한 문제 : CSS에서 datepicker가 정확히 어디에 있어야하는 경우에만 작동합니다. 이 메서드를 사용하여 datepicker를 동적으로 배치 할 수 없습니다. 나는 inst.input.focus에 바인딩, 해킹 ()를 사용했다
aaronbauman

Bootstrap :)을 사용하여 나를 위해 일했지만 z-index 속성 만 설정했습니다.
Francisco Goldenstein 2014 년

페이지에서 입력 필드가 어디에 있는지 알 수 없기 때문에 사소한 구현 외에는 쓸모가 없습니다.
Software Engineer

35

다음은 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);
    }
})

@kottenator에게 감사합니다. 이것은 정말 유용합니다 (특히 position.js와 함께)!
Sebastian

이 답변은 position.js의 장점 만 보여줍니다.
whaefelinger

이것은 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

시간 제한을 도입하여 프로그래밍 문제를 극복하는 데는 완벽하지 않습니다.
whaefelinger

이것이 저를 위해 일해 주셔서 감사합니다. afterShow 이벤트가 있을지 궁금합니다. D :하지만 지금이 나에 관계없이에 수행하는 데 도움이
롭 Branaghan

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

먼저 afterShowingjquery가 _showDatepicker메서드 에서 모든 부두를 수행 한 후에 위치를 변경할 수있는 datepicker 개체에 메서드 가 있어야한다고 생각합니다 . 또한라는 매개 변수 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
    }
});

그러나의 내부 구현이 변경되면 _showDatepicker코드가 손상 될 수 있으므로 Jquery-ui 업데이트에주의 하십시오.


1
구성 가능한 항목으로 jQuery UI에 추가 했어야합니다.
Aleksej Komarov

3

경계없는 입력 컨트롤이있는 부모 div에 따라 datepicker를 배치해야했습니다. 이를 위해 jquery UI 코어에 포함 된 "position"유틸리티를 사용했습니다. beforeShow 이벤트에서 이것을했습니다. 다른 사람들이 위에서 언급했듯이 datepicker 코드는 beforeShow 함수를 마친 후 위치를 재설정하므로 beforeShow에서 직접 위치를 설정할 수 없습니다. 이를 우회하려면 setInterval을 사용하여 위치를 설정하면됩니다. 현재 스크립트가 완료되어 datepicker가 표시되고, datepicker가 표시된 직후 위치 변경 코드가 실행됩니다. 절대 발생해서는 안되지만 .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);
        }

매우 못생긴 솔루션. 가장 큰 문제는 datepicker 위젯이 갑자기 "재배치"가 시작되는 곳이 보이기 직전에 눈에 띄게 "점프"하는 것입니다.
whaefelinger jul.

2

datepicker 사용 후 focusin 바인딩 datepicker 위젯의 CSS 변경 희망 도움말

$('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 객체에 초점 이벤트를 사용하고 API를 함께 배치 할 수 있습니다. 위쪽과 아래쪽 및 왼쪽을 오른쪽 또는 가운데로 바꿀 수 있습니다 (또는 실제로 위치 API에서 원하는 모든 항목). 이렇게하면 간격이나 엄청나게 복잡한 솔루션이 필요하지 않으며 입력 위치에 따라 필요에 맞게 레이아웃을 구성 할 수 있습니다.

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

최고의 / 가장 정답 !!
HirsuteJim

0

IE가 쿼크 모드에 들어가면 jQuery UI 구성 요소 및 기타 요소가 잘못 배치된다는 점도 주목할 가치가 있습니다.

쿼크 모드에 빠지지 않도록 문서 유형을 최신 HTML5로 올바르게 설정했는지 확인하세요.

<!DOCTYPE html>

transitional을 사용하면 상황이 엉망이됩니다. 바라건대 이것은 누군가가 미래에 시간을 절약 할 수 있기를 바랍니다.


0

이렇게하면 함수라는 메서드에 기능이 추가되어 코드에서이를 캡슐화하거나 메서드가 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 내에서 오프셋이 반환되기 전에 viewHeight가 offset.top에 추가되도록 _checkOffset 함수를 업데이트하기 만하면됩니다.

_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 , 오프셋, isFixed) {return {top : mytop , left : myleft };}}); mytop 및 myleft는 개인 취향에 맞습니다 (예 : inst 에서 파생 됨) .
whaefelinger

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

왜 투표하셨습니까? 이것이 문제를 해결하지 않습니까? codepen.io/coconewty/pen/rajbNj
James

투표? 질문의 제목 만 읽고 실제 문제를 파헤 치려고 노력하지 않았기 때문입니다. 다양한 너비의 입력 필드에 두 개의 datepicker가 연결되어 있다고 가정합니다. 솔루션은 각 datepicker 위젯의 왼쪽 가장자리가 입력 필드 오른쪽 가장자리에 닿도록 어떻게 보장합니까? 반면에 답변 독창성에 대해 최소한 1 점을 받아야합니다.
whaefelinger

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.