Bagaimana mengubah posisi pop-up dari jQuery DatePicker control

109

Adakah ide bagaimana agar DatePicker muncul di akhir kotak teks terkait alih-alih langsung di bawahnya? Apa yang cenderung terjadi adalah bahwa kotak teks berada di bagian bawah halaman dan DatePicker bergeser untuk memperhitungkannya dan menutupi kotak teks sepenuhnya. Jika pengguna ingin mengetik tanggal alih-alih memilihnya, mereka tidak bisa. Saya lebih suka menampilkannya tepat setelah kotak teks jadi tidak masalah bagaimana itu menyesuaikan secara vertikal.

Ada ide bagaimana mengontrol pemosisian? Saya tidak melihat pengaturan apa pun untuk widget, dan saya belum beruntung mengubah pengaturan CSS, tetapi saya dapat dengan mudah melewatkan sesuatu.

gfrizzle
sumber
1
+1 untuk tidak hanya "menangani" keluhan, bahwa solusi Anda bukanlah solusi untuk D_N.
Leonidas

Jawaban:

20

Jawaban yang diterima untuk pertanyaan ini sebenarnya bukan untuk jQuery UI Datepicker. Untuk mengubah posisi jQuery UI Datepicker cukup modifikasi .ui-datepicker di file css. Ukuran Datepicker juga dapat diubah dengan cara ini, cukup sesuaikan ukuran font.

jonmc12
sumber
4
Bisakah Anda memberi tahu saya perubahan mana yang Anda buat?
eddy
1
@gfrizzle - ya, jawaban saya salah sekali. Akhirnya sempat binning itu. Tidak tahu apa yang saya pikirkan saat itu: /
Kev
64
Saya tidak tahu mengapa ini adalah jawaban yang diterima karena hampir tidak berguna sama sekali.
Insinyur Perangkat Lunak
10
Jawaban yang diberikan sama sekali tidak berguna karena datepicker akan secara dinamis memodifikasi css .ui-datepicker sebelum memunculkan widget.
whaefelinger
4
Jawaban ini tidak memberikan rincian apapun, dan seharusnya bukan jawaban yang diterima.
chapeljuice
120

Inilah yang saya gunakan:

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

Anda mungkin juga ingin menambahkan sedikit lebih banyak ke margin kiri sehingga tidak tepat terhadap bidang input.


sumber
2
Trik yang bagus. Masalahnya adalah jika datepicker ditampilkan di luar batas layar, _showDatepicker akan mencoba memindahkannya, oleh karena itu, atas dan kiri akan berbeda dan marginTop, marginLeft mungkin perlu disetel.
monzonj
1
Saya menggunakan pendekatan serupa - Saya mengambil ide Anda untuk menggunakan beforeShow, tetapi fungsi beforeShow saya menggunakan efek posisi JQueryUI: $(this).position(my:'left top', at:'left bottom', of:'#altField')(karena saya menggunakan altFieldopsi datepicker untuk tampilan)
Isaac Betesh
Ini mungkin berfungsi untuk menyetel margin, tetapi gagal untuk atribut "left", "top", "z-index", dan "position".
aaronbauman
Seperti yang saya pahami, ini juga tidak berhasil, karena jquery mengatur ulang posisi setelah beforeShow dipanggil.
Insinyur Perangkat Lunak
Jawabannya diberikan adalah salah penyebab datepicker akan mengatur ulang posisi setelah beforeShow () kembali.
whaefelinger
40

Saya melakukannya langsung di CSS:

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

Semua bidang masukan tanggal saya lebarnya 100 piksel. Saya juga menambahkan z-index sehingga kalender juga muncul di atas popup AJAX.

Saya tidak mengubah file CSS jquery-ui; Saya membebani kelas di file CSS utama saya, jadi saya dapat mengubah tema atau memperbarui widget tanpa harus memasukkan kembali mod spesifik saya.

Christian Lescuyer
sumber
Masalah yang sama seperti trik css lainnya: Hanya berfungsi jika Anda sekarang berada tepat di tempat pemilih data seharusnya berada di CSS. Anda tidak dapat menggunakan metode ini untuk menempatkan datepicker secara dinamis. Saya harus menggunakan peretasan, mengikat inst.input.focus ()
aaronbauman
Bekerja untuk saya menggunakan Bootstrap :) tetapi saya hanya mengatur properti z-index.
Francisco Goldenstein
Tidak berguna untuk apa pun selain implementasi yang sepele karena Anda tidak akan tahu di mana kolom input berada di halaman.
Insinyur Perangkat Lunak
35

Berikut adalah variasi penyelarasan kalender Datepicker saya.

Saya pikir itu cukup bagus, karena Anda dapat mengontrol pemosisian melalui jQuery UI Position util.

Satu batasan: jquery.ui.position.js diperlukan.

Kode:

$('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);
    }
})
Rost
sumber
Terima kasih @kottenator, ini sangat berguna (terutama dengan position.js)!
Sebastian
Jawaban ini menunjukkan tidak lebih dari manfaat dari position.js.
whaefelinger
Ini masih berfungsi di v1.11.4 tetapi ini memang peretasan kotor, terlalu buruk jQuery API tidak membiarkan kami melakukan ini dalam suatu afterShowmetode.
Skoua
29

Berikut adalah variasi lain yang bekerja dengan baik untuk saya, sesuaikan rect.top + 40, rect.left + 0 agar sesuai dengan kebutuhan Anda:

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

Patrick
sumber
Wow berhasil. Menggunakan "inst.dpDiv.css (" top "," 40px! Important ");" tidak bekerja!
emeraldhieu
Jauh dari sempurna dalam mengatasi masalah program dengan memperkenalkan batas waktu.
whaefelinger
Terima kasih ini berhasil untuk saya, saya ingin tahu apakah akan ada acara afterShow, itu akan luar biasa !! Tapi untuk saat ini, ini membantu saya melanjutkan apa pun: D
Rob Branaghan
16

Ini bekerja untuk saya:

 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);
David Laberge
sumber
6

Pertama saya pikir harus ada afterShowingmetode di objek datepicker, di mana Anda dapat mengubah posisi setelah jquery melakukan semua voodoo dalam _showDatepickermetode tersebut. Selain itu, parameter yang dipanggil preferedPositionjuga diinginkan, sehingga Anda dapat menyetelnya dan jquery memodifikasinya jika dialog ditampilkan di luar viewport.

Ada "trik" untuk melakukan hal terakhir ini. Jika Anda mempelajari _showDatepickermetode ini, Anda akan melihat penggunaan variabel privat $.datepikcer._pos. Variabel itu akan diatur jika tidak ada yang mengaturnya sebelumnya. Jika Anda memodifikasi variabel itu sebelum menampilkan dialog, Jquery akan mengambilnya dan akan mencoba untuk mengalokasikan dialog di posisi itu, dan jika itu merender keluar dari layar, itu akan menyesuaikannya untuk memastikan itu terlihat. Kedengarannya bagus, ya?

Masalahnya adalah; _posbersifat pribadi, tetapi jika Anda tidak keberatan. Kamu bisa:

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

Tapi hati-hati dengan update Jquery-ui, karena perubahan dalam implementasi internal _showDatepickerdapat merusak kode Anda.

monzonj
sumber
1
Mereka seharusnya menambahkan ini di jQuery UI sebagai item yang dapat dikonfigurasi.
Aleksej Komarov
3

Saya perlu memposisikan datepicker menurut div induk di mana kontrol input tanpa batas saya berada. Untuk melakukannya, saya menggunakan utilitas "posisi" yang termasuk dalam inti UI jquery. Saya melakukan ini di acara beforeShow. Seperti yang dikomentari orang lain di atas, Anda tidak dapat mengatur posisi secara langsung di beforeShow, karena kode pemilih data akan mengatur ulang lokasi setelah menyelesaikan fungsi beforeShow. Untuk menyiasatinya, cukup atur posisinya menggunakan setInterval. Skrip saat ini akan selesai, menampilkan datepicker, dan kemudian kode reposisi akan berjalan segera setelah datepicker terlihat. Meskipun itu seharusnya tidak pernah terjadi, jika datepicker tidak terlihat setelah 0,5 detik, kode tersebut memiliki fail-safe untuk menyerah dan menghapus interval.

        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);
        }
Brett Birschbach
sumber
Solusi yang sangat jelek. Masalah terbesar adalah "lompatan" yang terlihat dari widget datepicker tepat setelah widget itu terlihat di mana tiba-tiba "relokasi" Anda masuk. Untuk dihindari dengan cara apa pun.
whaefelinger
2

mengikat focusin setelah menggunakan css perubahan datepicker dari widget datepicker`s ingin bantuan

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

saya memperbaikinya dengan kode jquery kustom saya.

  1. memberi saya input field datepicker kelas " .datepicker2 "

  2. temukan posisinya saat ini dari atas dan

  3. menempatkan kotak popup, yang nama kelasnya adalah " .ui-datepicker "

ini kode saya.

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

di sini "40" adalah piksel yang saya harapkan, Anda dapat mengubahnya dengan piksel Anda.

sh6210
sumber
1

memperbaiki masalah tampilkan posisi 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();
        }
    }
zersina
sumber
1

Fungsi jquery yang sangat sederhana.

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

Saya menghabiskan banyak waktu untuk mencoba mencari tahu masalah ini untuk beberapa halaman situs baru yang saya kembangkan dan sepertinya tidak ada yang berhasil (termasuk salah satu dari berbagai solusi yang disajikan di atas yang saya terapkan. Saya menduga jQuery baru saja berubah semuanya cukup karena mereka disarankan bahwa solusi tidak berfungsi lagi. Saya tidak tahu. Sejujurnya, saya tidak mengerti mengapa tidak ada sesuatu yang sederhana yang diimplementasikan ke dalam jQuery ui untuk mengonfigurasi ini, karena tampaknya masalah yang cukup besar dengan kalender selalu muncul di beberapa posisi jauh di bawah halaman dari masukan yang dilampirkan.

Bagaimanapun, saya menginginkan solusi akhir yang cukup umum sehingga saya dapat menggunakannya di mana saja dan itu akan berhasil. Sepertinya saya akhirnya sampai pada kesimpulan yang menghindari beberapa jawaban yang lebih rumit dan spesifik kode jQuery di atas:

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

Pada dasarnya saya melampirkan tag gaya baru ke kepala sebelum setiap acara "show" datepicker (menghapus yang sebelumnya, jika ada). Metode melakukan sesuatu ini mengatasi sebagian besar masalah yang saya hadapi selama pengembangan.

Diuji di Chrome, Firefox, Safari, dan IE> 8 (karena IE8 tidak bekerja dengan baik dengan jsFiddle dan saya kehilangan semangat untuk memperhatikan

Saya tahu bahwa ini adalah campuran konteks jQuery dan javascript, tetapi pada titik ini saya hanya tidak ingin berusaha mengubahnya menjadi jQuery. Akan sederhana, saya tahu. Aku sudah selesai dengan hal ini sekarang. Semoga orang lain bisa mendapatkan manfaat dari solusi ini.

Programmer Dan
sumber
1

Mereka mengubah nama kelas menjadi ui-datepicker-trigger

Jadi ini berhasil jquery 1.11.x

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

Saya mengambilnya dari (( Cara mengontrol pemosisian jQueryUI datepicker ))

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

berhasil !!!

masoud Cheragee
sumber
Jawabannya benar meskipun intinya sudah dijawab sebelumnya.
whaefelinger
1

Atau Anda dapat menggunakan acara fokus pada objek dateSelect Anda dan api posisi bersama-sama. Anda dapat menukar atas dan bawah dan kiri ke kanan atau tengah (atau apa pun yang Anda inginkan dari api posisi). Dengan cara ini Anda tidak memerlukan interval atau solusi yang sangat rumit dan Anda dapat mengonfigurasi tata letak agar sesuai dengan kebutuhan Anda tergantung di mana masukannya.

dateSelect.focus(function () {
    $("#ui-datepicker-div").position({
        my: "left top",
        at: "left bottom",
        of: $(this)
    });
});
Taugenichts
sumber
Jawaban Terbaik / Paling Benar !!
HirsuteJim
0

Perlu juga dicatat bahwa jika IE masuk ke mode quirks, komponen jQuery UI Anda, dan elemen lainnya, akan ditempatkan secara tidak benar.

Untuk memastikan Anda tidak masuk ke mode quirks, pastikan Anda menyetel doctype dengan benar ke HTML5 terbaru.

<!DOCTYPE html>

Menggunakan transisi membuat banyak hal menjadi berantakan. Semoga ini akan menghemat waktu seseorang di masa depan.

Halfstop
sumber
0

Ini menempatkan fungsionalitas ke dalam metode bernama fungsi, memungkinkan kode Anda untuk merangkumnya atau metode yang akan dibuat ekstensi jquery. Baru saja digunakan pada kode saya, berfungsi dengan sempurna

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);
}
Brett Weber
sumber
0

Di dalam Jquery.UI, perbarui saja fungsi _checkOffset, sehingga viewHeight ditambahkan ke offset.top, sebelum offset dikembalikan.

_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;
    },
David Moore
sumber
Solusi ini pada dasarnya benar: Masukkan fungsi _checkOffset () Anda sendiri melalui jQuery.extend () dan kembalikan objek arbitrer yang memiliki properti numerik "top" dan "left", yaitu jQuery.extend (jQuery.datepicker, {_checkOffset: function (inst , offset, isFixed) {return {top: mytop , left: myleft };}}); dimana mytop dan myleft sesuai dengan keinginan anda, misalnya diturunkan dari inst .
whaefelinger
0
.ui-datepicker {-ms-transform: translate(100px,100px); -webkit-transform: translate(100px,100px); transform: translate(100px,100px);}
James
sumber
mengapa memilih sendiri? bukankah ini mengatasi masalah? codepen.io/coconewty/pen/rajbNj
Yakobus
memilih sendiri? Karena Anda hanya membaca judul pertanyaan dan tidak berusaha menggali masalah sebenarnya. Anggap saja Anda memiliki dua pemilih data yang dilampirkan ke bidang masukan dengan berbagai lebar. Bagaimana solusi Anda memastikan bahwa tepi kiri setiap widget pemilih data menyentuh tepi kanan kolom input? Di sisi lain, Anda harus mendapatkan setidaknya satu poin untuk orisinalitas jawaban Anda.
whaefelinger
0
$('.PDatePicker').MdPersianDateTimePicker({
                Placement: 'top',          
            });
hamed hossani
sumber