2009-11-30 23 views
30

Il datepicker in jQueryUI esegue il rendering con una posizione dinamica. Rende secondo il suo css se c'è abbastanza spazio per esso, ma se non c'è abbastanza spazio per la finestra prova a renderizzare sullo schermo. Ho bisogno che rimanga e renda sempre nello stesso posto, indipendentemente dalla posizione dello schermo o da altre circostanze. Come si può fare con jQueryUI datepicker? Altre implementazioni di jQuery datepicker sembrano avere modi per farlo, ma non vedo un modo per farlo per la versione dell'interfaccia utente.Come controllare il posizionamento di jQueryUI datepicker

La risposta non sembra essere proprio la modifica del CSS:

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

... da quando il DatePicker è stato creato in modo dinamico crea superiore e lasciato in stile elemento. Non ho ancora trovato un modo per aggirare questo. Un approccio che ho visto è quello di dare qualcosa di simile nell'opzione beforeShow:

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

Questo ha un certo effetto, ma le proprietà superiore e sinistro sono ancora in modo dinamico set dopo questo viene eseguito quando l'datepicker rende. Sta ancora cercando di renderizzare sullo schermo. Come faccio a renderlo sempre nello stesso punto? Il mio prossimo passo è probabilmente entrare nelle budella di datepicker e iniziare a tirare fuori le cose. Qualche idea?

Nota che la risposta (per la versione dell'interfaccia utente) non è in:

risposta

60

Inserendo questo nella speranza che possa aiutare gli altri. Almeno a partire dalla v1.8.1 di datepicker, l'uso di 'window.DP_jQuery.datepicker' non funziona più, perché il puntatore (a destra termine?) Ora è chiamato con un timestamp della sua creazione - quindi per esempio ora sarebbe 'window'. DP_jQuery_1273700460448' . Così ora, piuttosto che utilizzare il puntatore all'oggetto DatePicker, fare riferimento ad esso direttamente in questo modo:

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

Molte grazie per la risposta qui sotto per me ottenere quello che mi serviva.

+0

No prob - Sono felice che qualcun altro abbia ottenuto qualcosa da questo, mi ricordo di aver passato un'ora o due a capirlo. – Purrell

+0

Questo funziona a meraviglia! –

+1

Bello, mi ha davvero aiutato! Per chiunque ne abbia bisogno è quindi possibile modificare i margini del datepicker in questo modo: .ui-datepicker {margin-left: -361px; } – bbeckford

9

Edit: JaredC ha dato una risposta aggiornata per le versioni successive di jQuery sopra . Passando a una risposta accettata.

Va bene, è una questione di monkeypatching la funzione che ha di tentare di eseguire sempre il rendering nel viewport poiché non è disponibile alcuna opzione per abilitare/disabilitare la funzionalità. Fortunatamente è disgiunto e isolato in una funzione, quindi possiamo semplicemente entrare e sovrascriverlo. Il codice seguente disabilita completamente solo caratteristica:

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

_checkOffset viene chiamato quando si sta aprendo e fa calcoli sulla offset e restituisce un nuovo offset se sarebbe altrimenti fuori della porta di visualizzazione. Questo sostituisce il corpo della funzione per passare semplicemente l'offset originale. Quindi puoi usare l'impostazione precedente di modellatura e/o la classe css di .ui-datepicker per metterla dove vuoi.

1

Nel file CSS, ad esempio:

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

Le impostazioni importanti, qualunque essi siano, avranno la priorità sulle impostazioni predefinite in linea.

+2

che è sbagliato, gli stili in linea hanno sempre la priorità – hcharge

+2

@hcharge in realtà, non lo fanno, se si usa! Importante all'interno dello stile CSS. Solo gli stili inline che hanno! Importanti stessi possono quindi sovrascrivere il! Importante proveniente dai CSS - http://jsfiddle.net/NTCP7/ – Katai

+0

Mentre '! Important' è un po 'un hack CSS di ultima istanza, questa soluzione funziona bene ed è il più semplice da implementare. –

-1

ecco un più semplice soluzione di

var $picker = $(".myspanclass").datepicker(); // span has display: inline-block 
$picker.find('.ui-datepicker').css('margin-left', '-50px'); 
+0

Questa risposta è errata perché il thread avviato è stato richiesto in modo specifico per una posizione di rendering statica. La tua risposta sposta semplicemente la posizione 50 px a sinistra. – whaefelinger

6

legano focusIn dopo aver usato datepicker cambiamento css di datepicker`s il widget desiderio aiuto

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

quando si vede già una risposta accettata, che cosa è il punto nel rispondere di nuovo. Ad ogni modo, benvenuto in SO! :) – LGAP

+0

Mostrare in che modo come farlo senza un 'hack' è sempre una cosa da sballo. La soluzione accettata ** (che sostituisce la logica interna "privata" di datepicker) ** potrebbe interrompere quella correzione con ogni nuova versione di jquery.ui. Guardando la risposta accettata in realtà mi sembra che sia così ... – CodeLama

1

precedenza ho provato a dare alto, a sinistra in caso beforeShow di datepicker.js, viene sovrascritto dal metodo _showDatePicker di jquery-ui-custom.js. Ma dopo il timeout la finestra funziona correttamente. Di seguito è riportato il codice

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

Questa soluzione non è altro che un trucco. Sebbene funzioni in generale, potresti notare una sorta di "salto" sul widget datepicker, specialmente se la posizione generata da datepicker è lontana dalla tua posizione "compromessa". Questo è ovviamente solo secondario, perché la tua soluzione potrebbe non funzionare affatto su computer "lenti". – whaefelinger

-1

Di default il calendario del selettore data era display in alto a destra della mia casella di inserimento, in modo che la parte superiore di esso era nascosto dalla mia barra dei menu. Ecco come ho posizionato il widget (jquery-ui versione 1.11.4) in modo molto semplice (si noti che 'ui-datepicker' è il nome della classe data dal jquery-ui):

$(document).ready(function() { 
$(".ui-datepicker").css('margin-left', '-50px', 'margin-top', '-50px'); 
//... 
} 
+0

Il tuo problema manca una correlazione con il problema dichiarato di questo thread. Secondo, perché applicare le proprietà CSS via JS e non tramite fogli di stile CSS? – whaefelinger

1

Questa è piuttosto una vecchia questione tuttavia Di recente ho riscontrato un problema simile a quello con jQuery UI Datepicker. Stavamo già utilizzando la soluzione pubblicata da @JaredC sopra (in particolare questo frammento di codice: $.extend($.datepicker,{_checkOffset:function(inst,offset,isFixed){return offset}});), tuttavia non avrebbe funzionato per un modal con un input in cui era necessario eseguire il rendering di un menu a discesa.

Questo problema si verifica perché quando si scorre verso il basso della pagina l'offset dell'ingresso nel modale cambia rispetto alla parte superiore della pagina a scorrimento. Il comportamento risultante significherebbe che il datepicker avrebbe eseguito il rendering in una diversa posizione verticale a seconda di quanto si scorreva verso il basso della pagina (nota: mentre visibile e scorrendo il datepicker era già stato corretto). La soluzione a questo problema ("input datepicker annidato in un modale") consiste invece nel calcolare il posizionamento verticale dell'input relativo alla schermata di visualizzazione e quindi aggiungere l'altezza dell'input (consentendo alla proprietà "top" css del datepicker di essere proprio sotto quella dell'input).

Il seguente frammento è nel coffeescript. Invece di restituire l'offset regolare secondo la soluzione di @ JaredC, otteniamo invece l'elemento Id dell'input dall'oggetto 'inst' e quindi accediamo all'oggetto tramite jquery per utilizzarlo per calcolare la distanza dell'input dalla parte superiore dello schermo rispetto a il viewport.

# 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; 
    } 
}); 
+0

Il tuo caffè è pieno di errori di sintassi. Ti dispiacerebbe ripararli? O meglio ancora, trascrivendolo a JS per noi? ** Modifica: ** Nvm, SO ha solo incasinato la spaziatura. Questo è il motivo per cui odio le lingue che dipendono dallo spazio. Sto modificando la tua risposta con la JS, spero che sia OK. – mpen

1

Il problema che stava avendo è che il DatePicker sia posizionato correttamente all'interno elementi fissi, come fantasia/lightboxes. Per qualche motivo, datepicker passa in modalità di posizionamento "fissa" quando questo accade, e quindi il calcolo dell'offset diventa errato, quando il posizionamento assoluto avrebbe funzionato bene.

Tuttavia, siamo in grado di ottenere la corretta posizione fissa con questo hack:

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

con 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); 
} 
+0

Ho trovato questo più utile con le ultime versioni dell'interfaccia utente jQuery –

1

La risposta accettata funziona molto bene nel complesso.

Tuttavia, utilizzando l'interfaccia utente jQuery v1.11.4, ho riscontrato un problema in cui il datapicker si posizionava lontano dall'input in una finestra modale (posizionamento fisso) quando la finestra del browser è stata spostata verso il basso.Sono stato in grado di risolvere questo problema modificando la risposta accettata come segue:

const checkOffset = $.datepicker._checkOffset; 

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