Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display additional text alongside dates in jQuery UI datepicker

I am using jQuery UI datepicker and I want to display additional text inside date cells next to the date. This is the desired behavior:

jQuery UI datepicker with custom text inside cells

Unfortunately, manipulating date cells using .text() and .html() functions breaks the datepicker functionality. See following demo and try to use the datepicker. Notice that when you select a date (i) the custom text is gone (ii) changing months destroys the calendar and lands you on "undefined NaN" month:

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

Is there a solution?

like image 642
Salman A Avatar asked Mar 03 '16 07:03

Salman A


3 Answers

Well, you can monkey-patch jQuery UI and risk breaking the code with newer versions or you can use documented callbacks to add custom data-* attributes to datepicker and display them using CSS pseudo elements:

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

Here's an updated JSFiddle


Side note: I'm not sure which functionality is broke in your demo, but since this solution is using documented callbacks and CSS, I believe it's less likely to break anything in future than monkey patching

like image 124
T J Avatar answered Nov 03 '22 13:11

T J


There is a much simpler solution based on the accepted answer:

The beforeShowDay function allows us to set the "title" attribute for each date. We can display the attribute using CSS pseudo elements.

$(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>
like image 44
Salman A Avatar answered Nov 03 '22 14:11

Salman A


Since the jQuery UI datapicker is pretty monolithic it is difficult to enhance cleanly.

I would go with monkey-patching one of its internal functions, namely _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>
like image 10
Tomalak Avatar answered Nov 03 '22 14:11

Tomalak