<!DOCTYPE html>
<html>
  <head>
    <script data-require="angular.js@*" data-semver="1.2.3" src="http://code.angularjs.org/1.2.3/angular.js"></script>
    <link rel="stylesheet" type="text/css" href="angular-pickadate.css" />
    <style type="text/css">
      .container {
        width: 300px;
        margin: auto;
      }
      .selected-date {
        padding: 10px;
        text-align: center;
      }
      
      .fluid-control {
        margin-top: 100px;
        text-align: center;
      }
      
      #slider {
        width: 450px;
        text-align: center;
      }
      
      h3 {
        font-weight: normal;
      }
    </style>
  </head>

  <body ng-app="testApp" id="ng-app" ng-controller="TestController">
    <div class="container">
      <div pickadate="" ng-model="date" min-date="minDate"></div>
      <div class="selected-date">
        Selected date is {{date || '(no date selected)'}}
      </div>
    </div>
    
    <div class="fluid-control">
      <h3>Move the slider to change the datepicker's width</h3>
      <input id="slider" type="range" min="200" max="500" value="300"></input>
    </div>
    
    <script type="text/javascript" src="angular-pickadate.js"></script>
    <script type="text/javascript">
      angular.module('testApp', ['pickadate']);

      function TestController($scope, dateFilter) {
        $scope.date = dateFilter(new Date(), 'yyyy-MM-dd');
        $scope.minDate = '2015-10-06';
      }
      
      var slider = document.querySelector('#slider'),
        container = document.querySelector('.container');
        
      slider.addEventListener("input", function() {
        container.style.width = slider.value + 'px';
      }, false); 
    </script>
  </body>

</html>
/* Styles go here */

.pickadate-header {
  position: relative;
}

.pickadate {
  font-family: 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif;
}

.pickadate-main {
  margin: 0;
  padding: 0;
  width: 100%;
  text-align: center;
  font-size: 12px;
}

.pickadate a:visited, .pickadate a {
  color: #666666;
}

.pickadate-cell {
  overflow: hidden;
  margin: 0;
  padding: 0;
}

.pickadate-cell li {
  display: block;
  float: left;
  border: 1px solid #DCDCDC;
  border-width: 0 1px 1px 0;
  width: 14.285%;
  padding: 1.3% 0 1.3% 0;
  box-sizing: border-box;
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
}

.pickadate-cell li:nth-child(7n+0) {
  border-right: 1px solid #DCDCDC;
}

.pickadate-cell li:nth-child(1),
.pickadate-cell li:nth-child(8),
.pickadate-cell li:nth-child(15),
.pickadate-cell li:nth-child(22),
.pickadate-cell li:nth-child(29),
.pickadate-cell li:nth-child(36) {
  border-left: 1px solid #DCDCDC;
}

.pickadate-cell .pickadate-disabled,
.pickadate-cell .pickadate-disabled a {
  color: #DCDCDC;
}

.pickadate-cell .pickadate-enabled {
  cursor: pointer;
  font-size: 12px;
  color: #666666;
}

.pickadate-cell .pickadate-today {
  background-color: #eaeaea;
}

.pickadate-cell .pickadate-active {
  background-color: #b52a00;
}

.pickadate-cell .pickadate-active {
  color: white;
}

.pickadate-cell .pickadate-head {
  border-top: 1px solid #DCDCDC;
  background: #f3f3f3;
}

.pickadate-cell .pickadate-head:nth-child(1),
.pickadate-cell .pickadate-head:nth-child(7) {
  background: #f3f3f3;
}

.pickadate-centered-heading {
  font-weight: normal;
  text-align: center;
  font-size: 1em;
  margin: 13px 0 13px 0;
}

.pickadate-controls {
  position: absolute;
  z-index: 10;
  width: 100%;
}

.pickadate-controls .pickadate-next {
  float: right;
}

.pickadate-controls a {
  text-decoration: none;
  font-size: 0.9em;
}
;(function(angular){
  var indexOf = [].indexOf || function(item) {
    for (var i = 0, l = this.length; i < l; i++) {
      if (i in this && this[i] === item) return i;
    }
    return -1;
  };

  angular.module('pickadate.utils', [])
    .factory('pickadateUtils', ['dateFilter', function(dateFilter) {
      return {
        isDate: function(obj) {
          return Object.prototype.toString.call(obj) === '[object Date]';
        },

        stringToDate: function(dateString) {
          if (this.isDate(dateString)) return new Date(dateString);
          var dateParts = dateString.split('-'),
            year  = dateParts[0],
            month = dateParts[1],
            day   = dateParts[2];

          // set hour to 3am to easily avoid DST change
          return new Date(year, month - 1, day, 3);
        },

        dateRange: function(first, last, initial, format) {
          var date, i, _i, dates = [];

          if (!format) format = 'yyyy-MM-dd';

          for (i = _i = first; first <= last ? _i < last : _i > last; i = first <= last ? ++_i : --_i) {
            date = this.stringToDate(initial);
            date.setDate(date.getDate() + i);
            dates.push(dateFilter(date, format));
          }
          return dates;
        }
      };
    }]);

  angular.module('pickadate', ['pickadate.utils'])

    .directive('pickadate', ['$locale', 'pickadateUtils', 'dateFilter', function($locale, dateUtils, dateFilter) {
      return {
        require: 'ngModel',
        scope: {
          date: '=ngModel',
          minDate: '=',
          maxDate: '=',
          disabledDates: '='
        },
        template:
          '<div class="pickadate">' +
            '<div class="pickadate-header">' +
              '<div class="pickadate-controls">' +
                '<a href="" class="pickadate-prev" ng-click="changeMonth(-1)" ng-show="allowPrevMonth">prev</a>' +
                '<a href="" class="pickadate-next" ng-click="changeMonth(1)" ng-show="allowNextMonth">next</a>' +
              '</div>'+
              '<h3 class="pickadate-centered-heading">' +
                '{{currentDate | date:"MMMM yyyy"}}' +
              '</h3>' +
            '</div>' +
            '<div class="pickadate-body">' +
              '<div class="pickadate-main">' +
                '<ul class="pickadate-cell">' +
                  '<li class="pickadate-head" ng-repeat="dayName in dayNames">' +
                    '{{dayName}}' +
                  '</li>' +
                '</ul>' +
                '<ul class="pickadate-cell">' +
                  '<li ng-repeat="d in dates" ng-click="setDate(d)" class="{{d.className}}" ng-class="{\'pickadate-active\': date == d.date}">' +
                    '{{d.date | date:"d"}}' +
                  '</li>' +
                '</ul>' +
              '</div>' +
            '</div>' +
          '</div>',

        link: function(scope, element, attrs, ngModel)  {
          var minDate       = scope.minDate && dateUtils.stringToDate(scope.minDate),
              maxDate       = scope.maxDate && dateUtils.stringToDate(scope.maxDate),
              disabledDates = scope.disabledDates || [],
              currentDate   = new Date();

          scope.dayNames    = $locale.DATETIME_FORMATS['SHORTDAY'];
          scope.currentDate = currentDate;

          scope.render = function(initialDate) {
            initialDate = new Date(initialDate.getFullYear(), initialDate.getMonth(), 1, 3);

            var currentMonth    = initialDate.getMonth() + 1,
              dayCount          = new Date(initialDate.getFullYear(), initialDate.getMonth() + 1, 0, 3).getDate(),
              prevDates         = dateUtils.dateRange(-initialDate.getDay(), 0, initialDate),
              currentMonthDates = dateUtils.dateRange(0, dayCount, initialDate),
              lastDate          = dateUtils.stringToDate(currentMonthDates[currentMonthDates.length - 1]),
              nextMonthDates    = dateUtils.dateRange(1, 7 - lastDate.getDay(), lastDate),
              allDates          = prevDates.concat(currentMonthDates, nextMonthDates),
              dates             = [],
              today             = dateFilter(new Date(), 'yyyy-MM-dd');

            // Add an extra row if needed to make the calendar to have 6 rows
            if (allDates.length / 7 < 6) {
              allDates = allDates.concat(dateUtils.dateRange(1, 8, allDates[allDates.length - 1]));
            }

            var nextMonthInitialDate = new Date(initialDate);
            nextMonthInitialDate.setMonth(currentMonth);

            scope.allowPrevMonth = !minDate || initialDate > minDate;
            scope.allowNextMonth = !maxDate || nextMonthInitialDate < maxDate;

            for (var i = 0; i < allDates.length; i++) {
              var className = "", date = allDates[i];

              if (date < scope.minDate || date > scope.maxDate || dateFilter(date, 'M') !== currentMonth.toString()) {
                className = 'pickadate-disabled';
              } else if (indexOf.call(disabledDates, date) >= 0) {
                className = 'pickadate-disabled pickadate-unavailable';
              } else {
                className = 'pickadate-enabled';
              }

              if (date === today) {
                className += ' pickadate-today';
              }

              dates.push({date: date, className: className});
            }

            scope.dates = dates;
          };

          scope.setDate = function(dateObj) {
            if (isDateDisabled(dateObj)) return;
            ngModel.$setViewValue(dateObj.date);
          };

          ngModel.$render = function () {
            if ((date = ngModel.$modelValue) && (indexOf.call(disabledDates, date) === -1)) {
              scope.currentDate = currentDate = dateUtils.stringToDate(date);
            } else if (date) {
              // if the initial date set by the user is in the disabled dates list, unset it
              scope.setDate(undefined);
            }
            scope.render(currentDate);
          };

          scope.changeMonth = function (offset) {
            // If the current date is January 31th, setting the month to date.getMonth() + 1
            // sets the date to March the 3rd, since the date object adds 30 days to the current
            // date. Settings the date to the 2nd day of the month is a workaround to prevent this
            // behaviour
            currentDate.setDate(1);
            currentDate.setMonth(currentDate.getMonth() + offset);
            scope.render(currentDate);
          };

          function isDateDisabled(dateObj) {
            return (/pickadate-disabled/.test(dateObj.className));
          }
        }
      };
    }]);
})(window.angular);