JQuery DatePicker denetiminin açılır konumu nasıl değiştirilir


109

DatePicker'ın doğrudan altında değil, ilişkili metin kutusunun sonunda görünmesini nasıl sağlayacağınız hakkında bir fikriniz var mı? Olma eğilimi, metin kutusunun sayfanın altına doğru olması ve DatePicker'ın bunu hesaba katmak için yukarı kayması ve metin kutusunu tamamen kaplamasıdır. Kullanıcı tarih seçmek yerine yazmak isterse, yapamaz. Metin kutusunun hemen ardından görünmesini tercih ederim, böylece dikey olarak nasıl ayarlandığı önemli değildir.

Konumlandırmayı nasıl kontrol edeceğiniz hakkında bir fikriniz var mı? Widget için herhangi bir ayar görmedim ve CSS ayarlarını değiştirme konusunda hiç şansım olmadı, ancak bir şeyleri kolayca gözden kaçırabilirim.


1
+1, sadece şikayeti "adreslemek" için değil, çözümünüzün D_N için çözüm olmadığına dair.
Leonidas

Yanıtlar:


20

Bu soru için kabul edilen cevap aslında jQuery UI Datepicker için değil. JQuery UI Datepicker'ın konumunu değiştirmek için css dosyasındaki .ui-datepicker'ı değiştirin. Datepicker'ın boyutu da bu şekilde değiştirilebilir, sadece yazı tipi boyutunu ayarlayın.


4
Lütfen bana hangi değişiklikleri yaptığınızı söyler misiniz?
girdap

1
@gfrizzle - evet, cevabım çok yanlıştı. Sonunda çöpe atmaya başladım. O zamanlar ne düşündüğüm hakkında hiçbir fikrim yok: /
Kev

64
Neredeyse tamamen işe yaramaz olduğu için bunun neden kabul edilen cevap olduğu hakkında hiçbir fikrim yok.
Software Engineer

10
Verilen cevap ise datepicker olarak tamamen yararsız olacaktır dinamik widget'ı haşhaş önce değiştirir .ui-datepicker en css.
whaefelinger

4
Bu cevap herhangi bir ayrıntı vermez ve kabul edilen cevap olmamalıdır.
chapeljuice

120

İşte kullandığım şey:

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

Sol kenar boşluğuna biraz daha fazla eklemek isteyebilirsiniz, böylece giriş alanına tam olarak denk gelmez.


2
İyi numara. Sorun şu ki, tarih seçicinin ekran sınırlarının ötesinde gösterilmesi durumunda, _showDatepicker onu yeniden konumlandırmaya çalışacak, bu nedenle üst ve sol farklı olacak ve marginTop, marginLeft'in ayarlanması gerekebilir.
monzonj

1
Benzer bir yaklaşım kullandım - beforeShow'u kullanma fikrinizi aldım, ancak beforeShow işlevim JQueryUI'nin konum efektini kullanıyor: $(this).position(my:'left top', at:'left bottom', of:'#altField')( altFieldgörüntüleme için datepicker seçeneğini kullandığım için)
Isaac Betesh

Bu, kenar boşluklarını ayarlamak için işe yarayabilir, ancak "sol", "üst", "z-endeksi" ve "konum" özellikleri için başarısız olur.
aaronbauman

Anladığım kadarıyla, bu da işe yaramıyor, çünkü jquery, beforeShow çağrıldıktan sonra konumu sıfırlar.
Software Engineer

Verilen cevap ise yanlış neden datepicker döndü beforeShow () sonra pozisyonunu sıfırlayacak.
whaefelinger

40

Bunu doğrudan CSS'de yapıyorum:

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

Tarih giriş alanlarımın tümü 100 piksel genişliğindedir. Ayrıca takvimin AJAX açılır pencerelerinin üzerinde görünmesi için z-endeksini de ekledim.

Jquery-ui CSS dosyasını değiştirmiyorum; Sınıfı ana CSS dosyamda aşırı yükledim, böylece belirli modlarımı yeniden girmek zorunda kalmadan temayı değiştirebilir veya widget'ı güncelleyebilirim.


Diğer css-trick ile aynı sorun: Yalnızca şu anda tarih seçicinin CSS'de tam olarak nerede olması gerekiyorsa çalışır. Tarih seçiciyi dinamik olarak yerleştirmek için bu yöntemi kullanamazsınız. İnst.input.focus () için bir hack kullanmak zorunda kaldım
aaronbauman

Bootstrap :) kullanarak benim için çalıştı ama ben sadece z-index özelliğini ayarladım.
Francisco Goldenstein

Giriş alanının sayfada nerede olduğunu bilmeyeceğiniz için önemsiz uygulamalar dışında hiçbir işe yaramaz.
Software Engineer

35

İşte Datepicker takvim hizalama varyasyonum.

Bunun oldukça hoş olduğunu düşünüyorum çünkü jQuery UI Position kullanım ile konumlandırmayı kontrol edebilirsiniz.

Bir kısıtlama: jquery.ui.position.js gereklidir.

Kod:

$('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);
    }
})

Teşekkürler @ kottenator, bu gerçekten kullanışlı (özellikle position.js ile)!
Sebastian

Bu yanıt, position.js değerinden başka bir şey göstermez.
whaefelinger

Bu hala v1.11.4'te çalışıyor ancak bu gerçekten kirli bir hack, çok kötü jQuery API bunu bir afterShowyöntemde yapmamıza izin vermiyor .
Skoua

29

İşte benim için işe yarayan başka bir varyasyon, ihtiyaçlarınıza göre rect.top + 40, rect.left + 0'ı ayarlayın:

$(".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>


Vay be işe yarıyor. "İnst.dpDiv.css (" top "," 40px! Önemli ");" çalışmıyor!
emeraldhieu

Bir zaman aşımı getirerek programatik bir sorunun üstesinden gelmek konusunda mükemmel olmaktan uzaktır.
whaefelinger

Teşekkür ederim bu benim için çalıştı, merak ediyorum bir afterShow etkinliği olacak mı, bu harika olurdu !! Ama şimdilik bu, ne olursa olsun devam etmeme yardımcı oluyor: D
Rob Branaghan

16

Bu benim için çalışıyor:

 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

Öncelikle afterShowing, datepicker nesnesinde jquery'nin tüm voodoo'sunu _showDatepickeryöntemde yaptıktan sonra konumu değiştirebileceğiniz bir yöntem olması gerektiğini düşünüyorum . Ek olarak, çağrılan bir parametre preferedPositionde arzu edilir, böylece onu ayarlayabilir ve jquery, diyalog penceresi görünüm alanının dışında işlenirse değiştirebilir.

Bu son şeyi yapmanın bir "hilesi" var. Eğer incelerseniz _showDatepickeryöntemini, özel bir değişkenin kullanımını göreceksiniz $.datepikcer._pos. Daha önce kimse ayarlamadıysa bu değişken ayarlanacaktır. Diyaloğu göstermeden önce bu değişkeni değiştirirseniz, Jquery onu alacak ve diyaloğu bu konuma tahsis etmeye çalışacak ve eğer ekran dışına çıkarsa, görünür olduğundan emin olmak için ayarlayacaktır. Kulağa hoş geliyor değil mi?

Problem şu; _posözeldir, ancak buna aldırmazsanız. Yapabilirsin:

$('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
    }
});

Ancak Jquery-ui güncellemelerine dikkat edin, çünkü dahili uygulamasındaki bir değişiklik _showDatepickerkodunuzu bozabilir.


1
Bunu jQuery kullanıcı arayüzüne yapılandırılabilir öğe olarak eklemeleri gerekirdi.
Aleksej Komarov

3

Tarih seçiciyi, kenarlıksız giriş denetimimin bulunduğu üst bölüme göre konumlandırmam gerekiyordu. Bunu yapmak için jquery UI çekirdeğinde bulunan "position" yardımcı programını kullandım. Bunu beforeShow etkinliğinde yaptım. Başkalarının yukarıda açıkladığı gibi, konum seçici kodu beforeShow işlevini bitirdikten sonra konumu sıfırlayacağından, konumu doğrudan Göster'den önce ayarlayamazsınız. Bunu aşmak için setInterval kullanarak konumu ayarlamanız yeterlidir. Geçerli komut dosyası tamamlanacak ve tarih seçici gösterilecek ve ardından yeniden konumlandırma kodu tarih seçici görünür olduktan hemen sonra çalışacaktır. Asla gerçekleşmemesi gerekse de, tarih seçici 0,5 saniye sonra görünmezse, kodun pes etme ve aralığı temizleme konusunda bir hata güvenliği vardır.

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

Çok çirkin bir çözüm. En büyük sorun, tarih seçici widget'ının aniden "yeniden konumlandırmanızın" devreye girdiği yerde görünür hale geldikten sonra gözle görülür bir "atlaması" olabilir. Ne pahasına olursa olsun kaçınılmalıdır.
whaefelinger

2

datepicker'ı kullandıktan sonra odaklamayı bağla datepicker'ın widget'ının css'sini değiştir yardım diliyorum

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

2

özel jquery kodumla düzelttim.

  1. tarih seçici girdi alanıma " .datepicker2 " sınıfı verdi

  2. mevcut konumunu yukarıdan bul ve

  3. sınıf adı " .ui-datepicker " olan açılır kutuyu konumlandırdı

İşte benim kodum.

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

burada "40" benim beklenen pikseldir, sizinkiyle değiştirebilirsiniz.


1

düzeltme konumu sorunu 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

Çok basit bir jquery işlevi.

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

1

Geliştirdiğim yeni bir sitenin birkaç sayfası için bu sorunu çözmeye çalışırken çok fazla zaman harcadım ve hiçbir şey işe yaramadı (yukarıda sunduğum çeşitli çözümlerden herhangi biri dahil. JQuery'nin değiştiğini tahmin ediyorum. Çözümlerin artık çalışmadığı önerildiğinden, işler yeterince arttı. Bilmiyorum. Dürüst olmak gerekirse, jQuery kullanıcı arayüzünde bunu yapılandırmak için neden basit bir şey olmadığını anlamıyorum, göründüğü gibi takvimin her zaman eklendiği girişten sayfanın oldukça aşağısındaki bir konumda ortaya çıkmasıyla ilgili oldukça büyük bir sorun.

Her neyse, onu her yerde kullanabileceğim ve işe yarayacak kadar genel bir son çözüm istedim. Görünüşe göre nihayet yukarıdaki daha karmaşık ve jQuery koduna özgü bazı cevaplardan kaçınan bir sonuca ulaştım:

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

Esasen, her tarih seçici "show" etkinliğinden önce başa yeni bir stil etiketi ekliyorum (varsa bir öncekini silerek). Bir şeyler yapmanın bu yöntemi, geliştirme sırasında karşılaştığım sorunların büyük çoğunluğunu çözüyor.

Chrome, Firefox, Safari ve IE> 8'de test edildi (IE8, jsFiddle ile iyi çalışmadığından ve bakım için zevki kaybediyorum

Bunun jQuery ve javascript bağlamlarının bir karışımı olduğunu biliyorum, ancak bu noktada onu jQuery'ye dönüştürmek için çaba sarf etmek istemiyorum. Basit olurdu, biliyorum. Şu anda bu işi çok bitirdim. Umarım bir başkası bu çözümden yararlanabilir.


1

Sınıf adını şu şekilde değiştirdiler: ui-datepicker-trigger

Yani bu çalışıyor jquery 1.11.x

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


1

Veya dateSelect nesnenizde focus olayını kullanabilir ve api'yi birlikte konumlandırabilirsiniz. Sağ veya merkez (veya gerçekten api konumundan istediğiniz herhangi bir şey) için üst ve alt ve solu değiştirebilirsiniz. Bu şekilde bir aralığa veya çılgınca karmaşık bir çözüme ihtiyacınız olmaz ve girişin nerede olduğuna bağlı olarak düzeni ihtiyaçlarınıza uyacak şekilde yapılandırabilirsiniz.

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

En İyi / En Doğru Cevap !!
HirsuteJim

0

Ayrıca, IE'nin tuhaflık moduna girmesi durumunda, jQuery UI bileşenlerinizin ve diğer öğelerinizin yanlış konumlandırılacağını da belirtmek gerekir.

Tuhaflık moduna girmediğinizden emin olmak için, belge türünüzü en son HTML5'e doğru şekilde ayarladığınızdan emin olun.

<!DOCTYPE html>

Geçiş kullanmak işleri berbat eder. Umarım bu, gelecekte birine biraz zaman kazandırır.


0

Bu, işlevselliği işlev adında bir yönteme yerleştirerek kodunuzun onu sarmalamasına veya yöntemin bir jquery uzantısı yapılmasına izin verir. Sadece kodumda kullanıldı, mükemmel çalışıyor

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 içinde, _checkOffset işlevini güncelleyin, böylece offset döndürülmeden önce viewHeight ofset.top öğesine eklenir.

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

Bu çözüm esasen doğrudur: jQuery.extend () aracılığıyla kendi _checkOffset () işlevinizi enjekte edin ve "top" ve "left" sayısal özelliklerine sahip rastgele bir nesne, yani jQuery.extend (jQuery.datepicker, {_checkOffset: function (inst , uzaklık, isFixed) {return {top: mytop , left: myleft };}}); mytop ve myleft kişisel zevk için nerede, örneğin türetilmiş inst .
whaefelinger

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

neden oylama? bu sorunu çözmüyor mu? codepen.io/coconewty/pen/rajbNj
James

votedown? Çünkü sadece sorunun başlığını okuyordunuz ve gerçek sorunu çözmek için herhangi bir çaba göstermediniz. Çeşitli genişliklere sahip giriş alanlarına eklenmiş iki tarih seçici olduğunu varsayalım. Çözümünüz, her bir tarih seçici widget'in sol kenarının girişler alanının sağ kenarına temas etmesini nasıl sağlıyor? Öte yandan, cevaplarınızın özgünlüğü için en az bir puan almalısınız.
whaefelinger

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.