web-dev-qa-db-fra.com

Afficher du texte supplémentaire à côté des dates dans le sélecteur de dates jQuery UI

J'utilise jQuery UI datepicker et je souhaite afficher du texte supplémentaire à l'intérieur des cellules de date à côté de la date. C'est le comportement souhaité:

jQuery UI datepicker with custom text inside cells

Malheureusement, la manipulation des cellules de date à l'aide des fonctions .text() et .html() rompt la fonctionnalité de sélection de date. Voir la démo suivante et essayez d'utiliser le sélecteur de date. Notez que lorsque vous sélectionnez une date (i) le texte personnalisé a disparu (ii) le changement de mois détruit le calendrier et vous amène sur le mois "NaN non défini":

https://jsfiddle.net/salman/aLdx4L0y/

Y a-t-il une solution?

23
Salman A

Eh bien, vous pouvez monkey-patch jQuery UI et risquer de casser le code avec des versions plus récentes ou vous pouvez utiliser des rappels documentés pour ajouter des attributs data-* Personnalisés à datepicker et les afficher en utilisant pseudo-éléments CSS :

$(function() {
  $("#datepicker").datepicker({
    beforeShow: addCustomInformation,
    //---^----------- if closed by default (when you're using <input>)
    beforeShowDay: function(date) {
      return [true, date.getDay() === 5 || date.getDay() === 6 ? "weekend" : "weekday"];
    },
    onChangeMonthYear: addCustomInformation,
    onSelect: addCustomInformation
  });
  addCustomInformation(); // if open by default (when you're using <div>)
});

function addCustomInformation() {
  setTimeout(function() {
    $(".ui-datepicker-calendar td").filter(function() {
      var date = $(this).text();
      return /\d/.test(date);
    }).find("a").attr('data-custom', 110); // Add custom data here
  }, 0)
}
.ui-datepicker .weekend .ui-state-default {
  background: #FEA;
}
.ui-datepicker-calendar td a[data-custom] {
  position: relative;
  padding-bottom: 10px;
}
.ui-datepicker-calendar td a[data-custom]::after {
  /*STYLE THE CUSTOME DATA HERE*/
  content: '$' attr(data-custom);
  display: block;
  font-size: small;
}
<script src="//code.jquery.com/jquery-1.9.1.min.js"></script>
<link href="//code.jquery.com/ui/1.9.2/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<script src="//code.jquery.com/ui/1.9.2/jquery-ui.min.js"></script>
<input id="datepicker">

Voici une mise à jour JSFiddle


Note latérale: je ne sais pas quelle fonctionnalité est cassée dans votre démo, mais comme cette solution utilise des rappels documentés et CSS, je pense qu'il est moins susceptible de casser quoi que ce soit à l'avenir que le patch de singe

19
T J

Étant donné que le sélecteur de données jQuery UI est assez monolithique, il est difficile de l'améliorer proprement.

J'irais avec le patch de singe une de ses fonctions internes, à savoir _generateHTML.

$.datepicker._generateHTML = (function () {
    var realGenerateHtml = $.datepicker._generateHTML;
    return function (instance) {
        var html = realGenerateHtml.apply(this, arguments), $temp;
        
        if ( instance.input.is(".datepicker-price") ) {
            $temp = $("<table></table>").append(html);
            $temp.find(".ui-datepicker-calendar td a").each(function () {
                var yy = $(this).parent().data("year"),
                    mm = $(this).parent().data("month"),
                    dd = +$(this).text();

                $(this).append("<br><small class='price'>$100</small>");
            });
            html = $temp[0].innerHTML;
        }
        return html;
    };
})();

$(function() {
    $("#datepicker").datepicker();
});
.ui-datepicker .weekend .ui-state-default {
  background: #FEA;
}
.price {
    color: blue;
}
<link href="https://code.jquery.com/ui/1.9.2/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.9.2/jquery-ui.min.js"></script>

<div id="datepicker" class="datepicker-price"></div>
10
Tomalak

Il existe une solution beaucoup plus simple basée sur la réponse acceptée :

La fonction beforeShowDay nous permet de définir l'attribut "title" pour chaque date. Nous pouvons afficher l'attribut à l'aide de pseudo-éléments CSS.

$(function() {
  var dayrates = [100, 150, 150, 150, 150, 250, 250];

  $("#datepicker").datepicker({
    beforeShowDay: function(date) {
      var selectable = true;
      var classname = "";
      var title = "\u20AC" + dayrates[date.getDay()];
      return [selectable, classname, title];
    }
  });
});
@import url("https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/blitzer/jquery-ui.min.css");

.ui-datepicker td span,
.ui-datepicker td a {
  padding-bottom: 1em;
}

.ui-datepicker td[title]::after {
  content: attr(title);
  display: block;
  position: relative;
  font-size: .8em;
  height: 1.25em;
  margin-top: -1.25em;
  text-align: right;
  padding-right: .25em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>

<div id="datepicker"></div>
9
Salman A

Ajoutez ce code dans votre JS ...

$('#DatePicker').datepicker({
changeMonth: true,
changeYear: true,
minDate: 0,
onSelect: function (date, dp) {
    updateDatePickerCells();
},
onChangeMonthYear: function(month, year, dp) {
    updateDatePickerCells();
},
beforeShow: function(elem, dp) { 
    updateDatePickerCells();
}});
updateDatePickerCells();
function updateDatePickerCells(dp) {

setTimeout(function () {

    var cellContents = {1: '20', 15: '60', 28: '$99.99'};


    $('.ui-datepicker td > *').each(function (idx, elem) {
        var value = '$125';//cellContents[idx + 1] || 0;


        var className = 'datepicker-content-' + CryptoJS.MD5(value).toString();

        if(value == 0)
            addCSSRule('.ui-datepicker td a.' + className + ':after {content: "\\a0";}'); //&nbsp;
        else
            addCSSRule('.ui-datepicker td a.' + className + ':after {content: "' + value + '";}');

        $(this).addClass(className);
    });
}, 0);
}
var dynamicCSSRules = [];
function addCSSRule(rule) {
if ($.inArray(rule, dynamicCSSRules) == -1) {
    $('head').append('<style>' + rule + '</style>');
    dynamicCSSRules.Push(rule);
}
}

Lien de démonstration ... http://jsfiddle.net/pratikgavas/e3uu9/131/

7
Pratik Gavas