Comment contrôler le positionnement de jQueryUI datepicker

Le datepicker dans jQueryUI s’affiche avec une position dynamic. Il rend en fonction de ses css s’il y a assez de place pour cela, mais s’il n’y a pas assez d’espace dans la fenêtre, il essaie de rendre à l’écran. J’en ai besoin pour restr en place et restituer au même endroit à chaque fois, indépendamment de la position de l’écran ou d’autres circonstances. Comment cela peut-il être fait avec le datepicker jQueryUI? D’autres implémentations de jQuery datepicker semblent avoir des façons de le faire, mais je ne vois pas de moyen de le faire pour la version d’interface utilisateur.

La réponse ne semble pas simplement être une modification du fichier css:

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

… depuis la création du sélecteur de date, il crée dynamicment le style de l’élément supérieur et inférieur. Je n’ai pas encore trouvé de solution. Une approche que j’ai vue consiste à donner quelque chose comme ceci dans l’option beforeShow:

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

Cela a un effet, mais les propriétés top et left sont toujours définies de manière dynamic après son exécution lorsque le sélecteur de date est rendu. Il essaie toujours de rendre à l’écran. Comment puis-je le rendre toujours au même endroit? Ma prochaine étape consiste probablement à entrer dans le sortingpe du sortingeur de dates et à commencer à en tirer quelque chose. Des idées?

Notez que la réponse (pour la version de l’interface utilisateur) n’est pas dans:

  • comment-changer-la-pop-up-position-de-la-jquery-datepicker-control
  • changer-la-position-de-jquery-ui-datepicker

Afficher ceci dans l’espoir que cela aidera les autres. Au moins à partir de la version 1.8.1 de datepicker, l’utilisation de ‘window.DP_jQuery.datepicker’ ne fonctionne plus, car le pointeur (terme exact?) Est désormais nommé avec un horodatage de sa création. Ainsi, par exemple, il s’agirait désormais de ‘window. DP_jQuery_1273700460448 ‘. Alors maintenant, plutôt que d’utiliser le pointeur sur l’object datepicker, faites-le directement comme ceci:

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

Merci beaucoup pour la réponse ci-dessous pour m’avoir obtenu ce dont j’avais besoin.

Edit: JaredC a donné une réponse mise à jour pour les versions ultérieures de jQuery ci-dessus. Changer de réponse acceptée à cela.

Très bien, il s’agit là d’affronter la fonctionnalité qu’il a de tenter de toujours restituer dans la fenêtre d’affichage car aucune option n’a été fournie pour activer / désactiver la fonctionnalité. Heureusement, il est découplé et isolé dans une fonction afin que nous puissions simplement le remplacer. Le code suivant désactive complètement cette fonctionnalité uniquement:

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

_checkOffset est appelé lors de son ouverture. Il effectue des calculs sur le décalage et renvoie un nouveau décalage s’il se trouvait autrement en dehors du port d’affichage. Ceci remplace le corps de la fonction pour simplement passer le décalage d’origine de part en part. Ensuite, vous pouvez utiliser le hack de réglage beforeShow et / ou la classe css .ui-datepicker pour le placer où vous le souhaitez.

lier focusin après avoir utilisé datepicker changer les CSS du widget de datepicker

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

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

Dans votre fichier css, par exemple:

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

Vos parameters importants, quels qu’ils soient, remplaceront les valeurs par défaut en ligne.

Plus tôt, j’ai essayé de donner top, laissé dans l’événement beforeShow de datepicker.js, qui est remplacé par la méthode _showDatePicker de jquery-ui-custom.js. Mais après la temporisation, la fenêtre fonctionne bien. Ci-dessous le code

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

C’est une question assez ancienne, mais j’ai récemment rencontré un problème similaire à celui de jQuery UI Datepicker. Nous utilisions déjà la solution publiée par @JaredC ci-dessus (plus précisément cet extrait de code: $.extend($.datepicker,{_checkOffset:function(inst,offset,isFixed){return offset}}); ), mais cela ne fonctionnerait pas pour un modal qui avait une entrée dans laquelle nous devions rendre une liste déroulante.

Ce problème se produirait car lors du défilement de la page, le décalage de l’entrée dans les modifications modales par rapport au haut de la page défilée. Le comportement qui en résulte signifierait que le sélecteur de date s’afficherait dans une position verticale différente en fonction de la distance parcourue avec le défilement de la page (remarque: lorsque visible et que le défilement du sélecteur de date était déjà résolu). La solution à ce problème (“entrée sélecteur de date nestede dans un modal”) consiste à calculer le positionnement vertical de l’entrée par rapport à l’écran de visualisation, puis à append la hauteur de l’entrée (permettant à la propriété css “supérieure” du sélecteur de date de être juste en dessous de celle de l’entrée).

L’extrait suivant est en coffeescript. Au lieu de renvoyer le décalage régulier selon la solution de @ JaredC, nous obtenons plutôt l’ID elementId de l’entrée de l’object ‘inst’, puis nous accédons à l’object via jquery afin de l’utiliser pour calculer la distance de l’entrée par rapport au haut de l’écran. la fenêtre.

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

La réponse acceptée fonctionne très bien dans l’ensemble.

Cependant, avec jQuery UI v1.11.4, je rencontrais un problème qui faisait que le sélecteur de date se positionnerait loin de l’entrée dans une fenêtre modale (positionnement fixe) lorsque la fenêtre du navigateur aurait été déroulée. J’ai pu résoudre ce problème en modifiant la réponse acceptée comme suit:

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

Le problème que je rencontrais est que le sélecteur de date est mal positionné à l’intérieur d’éléments fixes, tels que les éléments fantaisie / lightboxes. Pour une raison quelconque, le sélecteur de date bascule en mode de positionnement “fixe” lorsque cela se produit, puis le calcul du décalage devient incorrect, lorsque le positionnement absolu aurait parfaitement fonctionné.

Cependant, nous pouvons obtenir la position fixe correcte avec ce 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, }; } }); 
 $("first-selector").datepicker().bind('click',function () { $("#ui-datepicker-div").appendTo("other-selector"); });  

Voici comment cela a fonctionné pour moi:

 $( "input[name='birthdate']" ).datepicker({ beforeShow : function(input,inst){ window.setTimeout(function () { $("#ui-datepicker-div").position({ my: "left top", at: "left bottom", of: input }); }, 1); } }); 

Pour le positionner lorsque l’écran est redimensionné:

 $(window).resize(function(){ $("#ui-datepicker-div").position({ my: "left top", at: "left bottom", of: "input[name='birthdate']" }); }); 

voici une solution plus simple

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

Par défaut, le calendrier du sélecteur de date était affiché dans le coin supérieur droit de ma zone de saisie. Le haut de celui-ci était donc masqué par la barre de menus. Voici comment j’ai positionné le widget (jquery-ui version 1.11.4) très simplement (notez que ‘ui-datepicker’ est le nom de classe donné par jquery-ui):

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