web-dev-qa-db-fra.com

Comment changer la position contextuelle du contrôle jQuery DatePicker

Avez-vous une idée de la façon d’obtenir le DatePicker à la fin de la zone de texte associée au lieu de juste en dessous? Ce qui a tendance à se produire est que la zone de texte se trouve vers le bas de la page et que DatePicker se déplace pour en rendre compte et couvre totalement la zone de texte. Si l'utilisateur veut taper la date au lieu de la choisir, il ne le peut pas. Je préférerais qu'il apparaisse juste après la zone de texte afin que la façon dont elle s'ajuste verticalement importe peu.

Une idée de comment contrôler le positionnement? Je n'ai vu aucun paramètre pour le widget et je n'ai pas eu la chance de modifier les paramètres CSS, mais il se peut que quelque chose me manque.

96
gfrizzle

La réponse acceptée pour cette question ne concerne en réalité pas jpu uu datepicker. Pour changer la position du Datepicker de l'interface utilisateur jQuery, il suffit de modifier .ui-datepicker dans le fichier css. La taille du Datepicker peut également être modifiée de cette façon, il vous suffit d'ajuster la taille de la police.

26
jonmc12

Voici ce que j'utilise:

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

Vous voudrez peut-être aussi ajouter un peu plus dans la marge de gauche pour que cela ne soit pas à la hauteur du champ de saisie.

117
Sean CH

Je le fais directement dans le CSS:

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

Mes champs de saisie de date ont tous une largeur de 100 pixels. J'ai également ajouté l'index z afin que le calendrier apparaisse également au-dessus des fenêtres contextuelles AJAX.

Je ne modifie pas le fichier CSS jquery-ui; Je surcharge la classe dans mon fichier CSS principal afin de pouvoir changer de thème ou mettre à jour le widget sans avoir à ressaisir mes mods spécifiques.

38
Christian Lescuyer

Voici ma variante de l'alignement du calendrier Datepicker. 

Je pense que c'est plutôt agréable, car vous pouvez contrôler le positionnement via jQuery UI Position util.

Une restriction: jquery.ui.position.js requise.

Code:

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

Voici une autre variante qui me convient, ajustez rect.top + 40, rect.left + 0 à vos besoins:

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

22
Patrick

Cela fonctionne pour moi:

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

Premièrement, je pense qu’il devrait exister une méthode afterShowing dans l’objet datepicker, dans laquelle vous pouvez modifier la position une fois que jquery a effectué tous ses efforts dans la méthode _showDatepicker. En outre, un paramètre appelé preferedPosition serait également souhaitable. Vous pouvez donc le définir et le modifier au besoin si la boîte de dialogue est rendue en dehors de la fenêtre d'affichage.

Il y a un "truc" pour faire cette dernière chose. Si vous étudiez la méthode _showDatepicker, vous constaterez l’utilisation d’une variable privée $.datepikcer._pos. Cette variable sera configurée si personne ne l’a configurée auparavant. Si vous modifiez cette variable avant d'afficher la boîte de dialogue, Jquery la prendra et tentera d'allouer la boîte de dialogue à cette position. Si elle s'affiche en dehors de l'écran, elle l'ajustera pour qu'elle soit visible. Ça sonne bien, hein?

Le problème est; _pos est privé, mais si cela ne vous dérange pas. Vous pouvez:

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

Mais faites attention aux mises à jour de Jquery-ui, car un changement dans l'implémentation interne du _showDatepicker pourrait endommager votre code.

6
monzonj

Je devais positionner le sélecteur de date en fonction d'une division parent dans laquelle résidait le contrôle d'entrée sans frontière. Pour ce faire, j'ai utilisé l'utilitaire "position" inclus dans le noyau de jquery UI. Je l'ai fait dans l'événement beforeShow. Comme d'autres commentés ci-dessus, vous ne pouvez pas définir la position directement dans beforeShow, car le code datepicker réinitialisera l'emplacement après avoir terminé la fonction beforeShow. Pour contourner ce problème, définissez simplement la position à l'aide de setInterval. Le script en cours se terminera et affichera le sélecteur de date. Le code de repositionnement sera exécuté immédiatement après l'affichage du sélecteur de date. Bien que cela ne devrait jamais se produire, si le sélecteur de date n'est pas visible après 0,5 seconde, le code dispose d'une sécurité intégrée pour abandonner et effacer l'intervalle.

        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);
        }
3
Brett Birschbach

lier focusin après avoir utilisé datepicker changer le css du widget de datepicker wish help

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

je l'ai corrigé avec mon code jQuery personnalisé.

  1. a donné à mon champ de saisie datepicker une classe ".datepicker2"

  2. trouver sa position actuelle à partir du haut et

  3. positionné la fenêtre contextuelle, dont le nom de classe est ".ui-datepicker"

voici mon code.

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

ici "40" est mon pixel attendu, vous pouvez changer avec le vôtre.

2
sh6210

Je l'ai pris à partir de .__ (( Comment contrôler le positionnement de jQueryUI datepicker ))

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

Ça marche !!!

1
masoud Cheragee

correction du problème d'affichage de la position

//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
zersina

Ils ont changé le nom de la classe en ui-datepicker-trigger

Donc, cela fonctionne dans jquery 1.11.x

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

Une fonction JQuery très simple.

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

J'ai passé un temps ridicule à essayer de résoudre ce problème pendant plusieurs pages d'un nouveau site que je développe et rien ne semblait fonctionner (y compris les solutions présentées ci-dessus que j'ai mises en œuvre. Je suppose que jQuery a simplement changé les choses se sont assez bien passées, car il a été suggéré que les solutions ne fonctionnent plus. Je ne sais pas. Honnêtement, je ne comprends pas pourquoi il n'y a pas quelque chose de simple implémenté dans le jQuery ui pour le configurer, car cela semble être un problème assez important avec le calendrier apparaissant toujours à une position très éloignée de la page par rapport à l'entrée à laquelle il est attaché.

Quoi qu'il en soit, je voulais une solution finale suffisamment générique pour pouvoir l’utiliser n’importe où et pour que cela fonctionne. Je semble être enfin arrivé à une conclusion qui évite certaines des réponses plus complexes et spécifiques au code jQuery ci-dessus:

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

J'attache essentiellement une nouvelle balise de style à la tête avant chaque événement "show" de datepicker (en supprimant le précédent, le cas échéant). Cette méthode de travail résout une grande majorité des problèmes que j'ai rencontrés au cours du développement.

Testé sur Chrome, Firefox, Safari et IE> 8 (IE8 ne fonctionnant pas bien avec jsFiddle, je perds mon enthousiasme pour avoir pris soin de

Je sais qu'il s'agit d'un mélange de contextes jQuery et javascript, mais pour le moment, je ne veux simplement pas faire l'effort de le convertir en jQuery. Serait simple, je sais. Je suis tellement fini avec cette chose en ce moment. J'espère que quelqu'un d'autre pourra bénéficier de cette solution.

1
Programmer Dan

Il convient également de noter que si IE se met en mode quirks, vos composants de l'interface utilisateur jQuery et d'autres éléments seront mal positionnés.

Pour vous assurer que vous ne tombez pas en mode quirks, assurez-vous de définir correctement votre type de document sur le dernier HTML5.

<!DOCTYPE html>

L'utilisation de la transition crée un désordre. Espérons que cela permettra à quelqu'un de gagner un peu de temps dans le futur.

0
Halfstop
$('.PDatePicker').MdPersianDateTimePicker({
                Placement: 'top',          
            });
0
hamed hossani

Vous pouvez également utiliser l’événement de focus sur votre dateSelect et positionner l’API ensemble. Vous pouvez échanger le haut et le bas et la gauche pour la droite ou le centre (ou vraiment tout ce que vous voulez de l'api de position). De cette façon, vous n'avez pas besoin d'intervalle ni de solution incroyablement complexe et vous pouvez configurer la présentation en fonction de vos besoins en fonction de l'emplacement de l'entrée.

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

Cela place la fonctionnalité dans une méthode nommée fonction, permettant à votre code de l’encapsuler ou de transformer la méthode en une extension jquery. Juste utilisé sur mon code, fonctionne parfaitement

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
Brett Weber

Dans Jquery.UI, mettez simplement à jour la fonction _checkOffset, de sorte que viewHeight soit ajouté à offset.top, avant que offset ne soit renvoyé. 

_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;
    },
0
David Moore
.ui-datepicker {-ms-transform: translate(100px,100px); -webkit-transform: translate(100px,100px); transform: translate(100px,100px);}
0
James