text: var Calendar = {
      init: function( options, elem ) {
          this.options = $.extend( {}, this.options, options );
          this.elem  = elem;
          this.element = $(elem);
          this.today = new Date();
          this.today.setHours(0,0,0,0);
          this.show = new Date();
          this.show.setHours(0,0,0,0);
          this.current = {
              year: this.show.getFullYear(),
              month: this.show.getMonth(),
              day: this.show.getDate()
          };
          this.preset = [];
          this.selected = [];
          this.exclude = [];
          this.special = [];
          this.excludeDay = [];
          this.min = null;
          this.max = null;
          this.locale = null;
          this.minYear = this.current.year - this.options.yearsBefore;
          this.maxYear = this.current.year + this.options.yearsAfter;
          this.offset = (new Date()).getTimezoneOffset() / 60 + 1;
  
          this._setOptionsFromDOM();
          this._create();
  
          return this;
      },
  
      options: {
          dayBorder: false,
          excludeDay: null,
          prevMonthIcon: "<span class='default-icon-chevron-left'></span>",
          nextMonthIcon: "<span class='default-icon-chevron-right'></span>",
          prevYearIcon: "<span class='default-icon-chevron-left'></span>",
          nextYearIcon: "<span class='default-icon-chevron-right'></span>",
          compact: false,
          wide: false,
          widePoint: null,
          pickerMode: false,
          show: null,
          locale: METRO_LOCALE,
          weekStart: METRO_WEEK_START,
          outside: true,
          buttons: 'cancel, today, clear, done',
          yearsBefore: 100,
          yearsAfter: 100,
          headerFormat: "%A, %b %e",
          showHeader: true,
          showFooter: true,
          showTimeField: true,
          showWeekNumber: false,
          clsCalendar: "",
          clsCalendarHeader: "",
          clsCalendarContent: "",
          clsCalendarFooter: "",
          clsCalendarMonths: "",
          clsCalendarYears: "",
          clsToday: "",
          clsSelected: "",
          clsExcluded: "",
          clsCancelButton: "",
          clsTodayButton: "",
          clsClearButton: "",
          clsDoneButton: "",
          isDialog: false,
          ripple: false,
          rippleColor: "#cccccc",
          exclude: null,
          preset: null,
          minDate: null,
          maxDate: null,
          weekDayClick: false,
          weekNumberClick: false,
          multiSelect: false,
          special: null,
          format: METRO_DATE_FORMAT,
          inputFormat: null,
          onCancel: Metro.noop,
          onToday: Metro.noop,
          onClear: Metro.noop,
          onDone: Metro.noop,
          onDayClick: Metro.noop,
          onDayDraw: Metro.noop,
          onWeekDayClick: Metro.noop,
          onWeekNumberClick: Metro.noop,
          onMonthChange: Metro.noop,
          onYearChange: Metro.noop,
          onCalendarCreate: Metro.noop
      },
  
      _setOptionsFromDOM: function(){
          var element = this.element, o = this.options;
  
          $.each(element.data(), function(value, key){
              if (key in o) {
                  try {
                      o[key] = JSON.parse(value);
                  } catch (e) {
                      o[key] = value;
                  }
              }
          });
      },
  
      _create: function(){
          var element = this.element, o = this.options;
  
          element.html("").addClass("calendar " + (o.compact === true ? "compact" : "")).addClass(o.clsCalendar);
  
          if (o.dayBorder === true) {
              element.addClass("day-border");
          }
  
          if (Utils.isValue(o.excludeDay)) {
              this.excludeDay = (""+o.excludeDay).toArray(",", "int");
          }
  
          if (Utils.isValue(o.preset)) {
              this._dates2array(o.preset, 'selected');
          }
  
          if (Utils.isValue(o.exclude)) {
              this._dates2array(o.exclude, 'exclude');
          }
  
          if (Utils.isValue(o.special)) {
              this._dates2array(o.special, 'special');
          }
  
          if (o.buttons !== false) {
              if (Array.isArray(o.buttons) === false) {
                  o.buttons = o.buttons.split(",").map(function(item){
                      return item.trim();
                  });
              }
          }
  
          if (o.minDate !== null && Utils.isDate(o.minDate, o.inputFormat)) {
              this.min = Utils.isValue(o.inputFormat) ? o.minDate.toDate(o.inputFormat) : (new Date(o.minDate));
          }
  
          if (o.maxDate !== null && Utils.isDate(o.maxDate, o.inputFormat)) {
              this.max = Utils.isValue(o.inputFormat) ? o.maxDate.toDate(o.inputFormat) : (new Date(o.maxDate));
          }
  
          if (o.show !== null && Utils.isDate(o.show, o.inputFormat)) {
              this.show = Utils.isValue(o.inputFormat) ? o.show.toDate(o.inputFormat) : (new Date(o.show));
              this.show.setHours(0,0,0,0);
              this.current = {
                  year: this.show.getFullYear(),
                  month: this.show.getMonth(),
                  day: this.show.getDate()
              }
          }
  
          this.locale = Metro.locales[o.locale] !== undefined ? Metro.locales[o.locale] : Metro.locales["en-US"];
  
          this._drawCalendar();
          this._createEvents();
  
          if (o.wide === true) {
              element.addClass("calendar-wide");
          } else {
              if (!Utils.isNull(o.widePoint) && Utils.mediaExist(o.widePoint)) {
                  element.addClass("calendar-wide");
              }
          }
  
  
          if (o.ripple === true && Utils.isFunc(element.ripple) !== false) {
              element.ripple({
                  rippleTarget: ".button, .prev-month, .next-month, .prev-year, .next-year, .day",
                  rippleColor: this.options.rippleColor
              });
          }
  
          Utils.exec(this.options.onCalendarCreate, [this.element]);
      },
  
      _dates2array: function(val, category){
          var that = this, o = this.options;
          var dates;
  
          if (Utils.isNull(val)) {
              return ;
          }
  
          dates = typeof val === 'string' ? Utils.strToArray(val) : val;
  
          $.each(dates, function(){
              var _d;
  
              if (!Utils.isDateObject(this)) {
                  _d = Utils.isValue(o.inputFormat) ? this.toDate(o.inputFormat) : new Date(this);
                  if (Utils.isDate(_d) === false) {
                      return ;
                  }
                  _d.setHours(0,0,0,0);
              } else {
                  _d = this;
              }
  
              that[category].push(_d.getTime());
          });
      },
  
      _createEvents: function(){
          var that = this, element = this.element, o = this.options;
  
          $(window).on(Metro.events.resize, function(){
              if (o.wide !== true) {
                  if (!Utils.isNull(o.widePoint) && Utils.mediaExist(o.widePoint)) {
                      element.addClass("calendar-wide");
                  } else {
                      element.removeClass("calendar-wide");
                  }
              }
          });
  
          element.on(Metro.events.click, ".prev-month, .next-month, .prev-year, .next-year", function(e){
              var new_date, el = $(this);
  
              if (el.hasClass("prev-month")) {
                  new_date = new Date(that.current.year, that.current.month - 1, 1);
                  if (new_date.getFullYear() < that.minYear) {
                      return ;
                  }
              }
              if (el.hasClass("next-month")) {
                  new_date = new Date(that.current.year, that.current.month + 1, 1);
                  if (new_date.getFullYear() > that.maxYear) {
                      return ;
                  }
              }
              if (el.hasClass("prev-year")) {
                  new_date = new Date(that.current.year - 1, that.current.month, 1);
                  if (new_date.getFullYear() < that.minYear) {
                      return ;
                  }
              }
              if (el.hasClass("next-year")) {
                  new_date = new Date(that.current.year + 1, that.current.month, 1);
                  if (new_date.getFullYear() > that.maxYear) {
                      return ;
                  }
              }
  
              that.current = {
                  year: new_date.getFullYear(),
                  month: new_date.getMonth(),
                  day: new_date.getDate()
              };
              setTimeout(function(){
                  that._drawContent();
                  if (el.hasClass("prev-month") || el.hasClass("next-month")) {
                      Utils.exec(o.onMonthChange, [that.current, element], element[0]);
                  }
                  if (el.hasClass("prev-year") || el.hasClass("next-year")) {
                      Utils.exec(o.onYearChange, [that.current, element], element[0]);
                  }
              }, o.ripple ? 300 : 0);
  
              e.preventDefault();
              e.stopImmediatePropagation();
          });
  
          element.on(Metro.events.click, ".button.today", function(e){
              that.toDay();
              Utils.exec(o.onToday, [that.today, element]);
  
              e.preventDefault();
              e.stopImmediatePropagation();
          });
  
          element.on(Metro.events.click, ".button.clear", function(e){
              that.selected = [];
              that._drawContent();
              Utils.exec(o.onClear, [element]);
  
              e.preventDefault();
              e.stopImmediatePropagation();
          });
  
          element.on(Metro.events.click, ".button.cancel", function(e){
              that._drawContent();
              Utils.exec(o.onCancel, [element]);
  
              e.preventDefault();
              e.stopImmediatePropagation();
          });
  
          element.on(Metro.events.click, ".button.done", function(e){
              that._drawContent();
              Utils.exec(o.onDone, [that.selected, element]);
  
              e.preventDefault();
              e.stopImmediatePropagation();
          });
  
          element.on(Metro.events.click, ".week-days .day", function (e) {
              var day, index, days;
  
              if (o.weekDayClick !== true) {
                  return ;
              }
  
              day = $(this);
              index = day.index();
  
              if (o.multiSelect === true) {
                  days = o.outside === true ? element.find(".days-row .day:nth-child(" + (index + 1) + ")") : element.find(".days-row .day:not(.outside):nth-child(" + (index + 1) + ")");
                  $.each(days, function () {
                      var d = $(this);
                      var dd = d.data('day');
  
                      if (d.hasClass("disabled") || d.hasClass("excluded")) return;
  
                      if (!that.selected.contains(dd))
                          that.selected.push(dd);
                      d.addClass("selected").addClass(o.clsSelected);
                  });
              }
  
              Utils.exec(o.onWeekDayClick, [that.selected, day], element[0]);
  
              e.preventDefault();
              e.stopImmediatePropagation();
          });
  
          element.on(Metro.events.click, ".days-row .week-number", function (e) {
              var weekNumElement, weekNumber, days;
  
              if (o.weekNumberClick !== true)  {
                  return ;
              }
  
              weekNumElement = $(this);
              weekNumber = weekNumElement.text();
  
              if (o.multiSelect === true) {
                  days = $(this).siblings(".day");
                  $.each(days, function () {
                      var d = $(this);
                      var dd = d.data('day');
  
                      if (d.hasClass("disabled") || d.hasClass("excluded")) return;
  
                      if (!that.selected.contains(dd))
                          that.selected.push(dd);
                      d.addClass("selected").addClass(o.clsSelected);
                  });
              }
  
              Utils.exec(o.onWeekNumberClick, [that.selected, weekNumber, weekNumElement], element[0]);
  
              e.preventDefault();
              e.stopImmediatePropagation();
          });
  
          element.on(Metro.events.click, ".days-row .day", function(e){
              var day = $(this);
              var index, date;
  
              date = day.data('day');
              index = that.selected.indexOf(date);
  
              if (day.hasClass("outside")) {
                  date = new Date(date);
                  that.current = {
                      year: date.getFullYear(),
                      month: date.getMonth(),
                      day: date.getDate()
                  };
                  that._drawContent();
                  return ;
              }
  
              if (!day.hasClass("disabled")) {
  
                  if (o.pickerMode === true) {
                      that.selected = [date];
                      that.today = new Date(date);
                      that.current.year = that.today.getFullYear();
                      that.current.month = that.today.getMonth();
                      that.current.day = that.today.getDate();
                      that._drawHeader();
                      that._drawContent();
                  } else {
                      if (index === -1) {
                          if (o.multiSelect === false) {
                              element.find(".days-row .day").removeClass("selected").removeClass(o.clsSelected);
                              that.selected = [];
                          }
                          that.selected.push(date);
                          day.addClass("selected").addClass(o.clsSelected);
                      } else {
                          day.removeClass("selected").removeClass(o.clsSelected);
                          Utils.arrayDelete(that.selected, date);
                      }
                  }
  
              }
  
              Utils.exec(o.onDayClick, [that.selected, day, element]);
  
              e.preventDefault();
              e.stopImmediatePropagation();
          });
  
          element.on(Metro.events.click, ".curr-month", function(e){
              var target;
              var list = element.find(".months-list");
  
              list.find(".active").removeClass("active");
              target = list.find(".js-month-"+that.current.month).addClass("active");
              list.scrollTop = target.position().top - ( (list.height() - target.height() )/ 2);
              element.find(".calendar-months").addClass("open");
  
              e.preventDefault();
              e.stopImmediatePropagation();
          });
  
          element.on(Metro.events.click, ".calendar-months li", function(e){
              that.current.month = $(this).index();
              that._drawContent();
              Utils.exec(o.onMonthChange, [that.current, element], element[0]);
              element.find(".calendar-months").removeClass("open");
              e.preventDefault();
              e.stopImmediatePropagation();
          });
  
          element.on(Metro.events.click, ".curr-year", function(e){
              var target;
              var list = element.find(".years-list");
              var years = element.find(".calendar-years");
  
              list.find(".active").removeClass("active");
              target = list.find(".js-year-"+that.current.year).addClass("active");
  
              list[0].scrollTop = target.position().top - ( (list.height() - target.height() )/ 2);
  
              years.addClass("open");
  
              e.preventDefault();
              e.stopImmediatePropagation();
          });
  
          element.on(Metro.events.click, ".calendar-years li", function(e){
              that.current.year = $(this).text();
              that._drawContent();
              Utils.exec(o.onYearChange, [that.current, element], element[0]);
              element.find(".calendar-years").removeClass("open");
              e.preventDefault();
              e.stopImmediatePropagation();
          });
  
          element.on(Metro.events.click, function(e){
              var months = element.find(".calendar-months");
              var years = element.find(".calendar-years");
              if (months.hasClass("open")) {
                  months.removeClass("open");
              }
              if (years.hasClass("open")) {
                  years.removeClass("open");
              }
              e.preventDefault();
              e.stopPropagation();
          });
      },
  
      _drawHeader: function(){
          var element = this.element, o = this.options;
          var header = element.find(".calendar-header");
  
          if (header.length === 0) {
              header = $("<div>").addClass("calendar-header").addClass(o.clsCalendarHeader).appendTo(element);
          }
  
          header.html("");
  
          $("<div>").addClass("header-year").html(this.today.getFullYear()).appendTo(header);
          $("<div>").addClass("header-day").html(this.today.format(o.headerFormat, o.locale)).appendTo(header);
  
          if (o.showHeader === false) {
              header.hide();
          }
      },
  
      _drawFooter: function(){
          var element = this.element, o = this.options;
          var buttons_locale = this.locale['buttons'];
          var footer = element.find(".calendar-footer");
  
          if (o.buttons === false) {
              return ;
          }
  
          if (footer.length === 0) {
              footer = $("<div>").addClass("calendar-footer").addClass(o.clsCalendarFooter).appendTo(element);
          }
  
          footer.html("");
  
          $.each(o.buttons, function(){
              var button = $("<button>").attr("type", "button").addClass("button " + this + " " + o['cls'+this.capitalize()+'Button']).html(buttons_locale[this]).appendTo(footer);
              if (this === 'cancel' || this === 'done') {
                  button.addClass("js-dialog-close");
              }
          });
  
          if (o.showFooter === false) {
              footer.hide();
          }
      },
  
      _drawMonths: function(){
          var element = this.element, o = this.options;
          var months = $("<div>").addClass("calendar-months").addClass(o.clsCalendarMonths).appendTo(element);
          var list = $("<ul>").addClass("months-list").appendTo(months);
          var calendar_locale = this.locale['calendar'];
          var i;
          for(i = 0; i < 12; i++) {
              $("<li>").addClass("js-month-"+i).html(calendar_locale['months'][i]).appendTo(list);
          }
      },
  
      _drawYears: function(){
          var element = this.element, o = this.options;
          var years = $("<div>").addClass("calendar-years").addClass(o.clsCalendarYears).appendTo(element);
          var list = $("<ul>").addClass("years-list").appendTo(years);
          var i;
          for(i = this.minYear; i <= this.maxYear; i++) {
              $("<li>").addClass("js-year-"+i).html(i).appendTo(list);
          }
      },
  
      _drawContent: function(){
          var element = this.element, o = this.options;
          var content = element.find(".calendar-content"), toolbar;
          var calendar_locale = this.locale['calendar'];
          var i, j, d, s, counter = 0;
          var first = new Date(this.current.year, this.current.month, 1);
          var first_day;
          var prev_month_days = (new Date(this.current.year, this.current.month, 0)).getDate();
          var year, month;
  
          if (content.length === 0) {
              content = $("<div>").addClass("calendar-content").addClass(o.clsCalendarContent).appendTo(element);
          }
  
          content.html("");
  
          toolbar = $("<div>").addClass("calendar-toolbar").appendTo(content);
  
          /**
           * Calendar toolbar
           */
          $("<span>").addClass("prev-month").html(o.prevMonthIcon).appendTo(toolbar);
          $("<span>").addClass("curr-month").html(calendar_locale['months'][this.current.month]).appendTo(toolbar);
          $("<span>").addClass("next-month").html(o.nextMonthIcon).appendTo(toolbar);
  
          $("<span>").addClass("prev-year").html(o.prevYearIcon).appendTo(toolbar);
          $("<span>").addClass("curr-year").html(this.current.year).appendTo(toolbar);
          $("<span>").addClass("next-year").html(o.nextYearIcon).appendTo(toolbar);
  
          /**
           * Week days
           */
          var week_days = $("<div>").addClass("week-days").appendTo(content);
          var day_class = "day";
  
          if (o.showWeekNumber === true) {
              $("<span>").addClass("week-number").html("#").appendTo(week_days);
              day_class += " and-week-number";
          }
  
          for (i = 0; i < 7; i++) {
              if (o.weekStart === 0) {
                  j = i;
              } else {
                  j = i + 1;
                  if (j === 7) j = 0;
              }
              $("<span>").addClass(day_class).html(calendar_locale["days"][j + 7]).appendTo(week_days);
          }
  
          /**
           * Calendar days
           */
          var days = $("<div>").addClass("days").appendTo(content);
          var days_row = $("<div>").addClass("days-row").appendTo(days);
  
          first_day = o.weekStart === 0 ? first.getDay() : (first.getDay() === 0 ? 6 : first.getDay() - 1);
  
          if (this.current.month - 1 < 0) {
              month = 11;
              year = this.current.year - 1;
          } else {
              month = this.current.month - 1;
              year = this.current.year;
          }
  
          if (o.showWeekNumber === true) {
              $("<div>").addClass("week-number").html((new Date(year, month, prev_month_days - first_day + 1)).getWeek(o.weekStart)).appendTo(days_row);
          }
  
          for(i = 0; i < first_day; i++) {
              var v = prev_month_days - first_day + i + 1;
              d = $("<div>").addClass(day_class+" outside").appendTo(days_row);
  
              s = new Date(year, month, v);
              s.setHours(0,0,0,0);
  
              d.data('day', s.getTime());
  
              if (o.outside === true) {
                  d.html(v);
  
                  if (this.excludeDay.length > 0) {
                      if (this.excludeDay.indexOf(s.getDay()) > -1) {
                          d.addClass("disabled excluded").addClass(o.clsExcluded);
                      }
                  }
  
                  Utils.exec(o.onDayDraw, [s], d[0]);
              }
  
              counter++;
          }
  
          first.setHours(0,0,0,0);
          while(first.getMonth() === this.current.month) {
  
              d = $("<div>").addClass(day_class).html(first.getDate()).appendTo(days_row);
  
              d.data('day', first.getTime());
  
              // console.log(this.show.getTime() === first.getTime());
              if (this.show.getTime() === first.getTime()) {
                  d.addClass("showed");
              }
  
              // console.log(this.today.getTime() === first.getTime());
              if (this.today.getTime() === first.getTime()) {
                  d.addClass("today").addClass(o.clsToday);
              }
  
              if (this.special.length === 0) {
  
                  if (this.selected.indexOf(first.getTime()) !== -1) {
                      d.addClass("selected").addClass(o.clsSelected);
                  }
                  if (this.exclude.indexOf(first.getTime()) !== -1) {
                      d.addClass("disabled excluded").addClass(o.clsExcluded);
                  }
  
                  if (this.min !== null && first.getTime() < this.min.getTime()) {
                      d.addClass("disabled excluded").addClass(o.clsExcluded);
                  }
                  if (this.max !== null && first.getTime() > this.max.getTime()) {
                      d.addClass("disabled excluded").addClass(o.clsExcluded);
                  }
  
                  if (this.excludeDay.length > 0) {
                      if (this.excludeDay.indexOf(first.getDay()) > -1) {
                          d.addClass("disabled excluded").addClass(o.clsExcluded);
                      }
                  }
              } else {
  
                  if (this.special.indexOf(first.getTime()) === -1) {
                      d.addClass("disabled excluded").addClass(o.clsExcluded);
                  }
  
              }
  
              Utils.exec(o.onDayDraw, [first], d[0]);
  
              counter++;
              if (counter % 7 === 0) {
                  days_row = $("<div>").addClass("days-row").appendTo(days);
                  if (o.showWeekNumber === true) {
                      $("<div>").addClass("week-number").html((new Date(first.getFullYear(), first.getMonth(), first.getDate() + 1)).getWeek(o.weekStart)).appendTo(days_row);
                  }
              }
              first.setDate(first.getDate() + 1);
              first.setHours(0,0,0,0);
          }
  
          first_day = o.weekStart === 0 ? first.getDay() : (first.getDay() === 0 ? 6 : first.getDay() - 1);
  
          if (this.current.month + 1 > 11) {
              month = 0;
              year = this.current.year + 1;
          } else {
              month = this.current.month + 1;
              year = this.current.year;
          }
  
          if (first_day > 0) for(i = 0; i < 7 - first_day; i++) {
              d = $("<div>").addClass(day_class+" outside").appendTo(days_row);
              s = new Date(year, month, i + 1);
              s.setHours(0,0,0,0);
              d.data('day', s.getTime());
              if (o.outside === true) {
                  d.html(i + 1);
  
                  if (this.excludeDay.length > 0) {
                      if (this.excludeDay.indexOf(s.getDay()) > -1) {
                          d.addClass("disabled excluded").addClass(o.clsExcluded);
                      }
                  }
  
                  Utils.exec(o.onDayDraw, [s], d[0]);
              }
          }
      },
  
      _drawCalendar: function(){
          var that = this;
          setImmediate(function(){
              that.element.html("");
              that._drawHeader();
              that._drawContent();
              that._drawFooter();
              that._drawMonths();
              that._drawYears();
          });
      },
  
      getPreset: function(){
          return this.preset;
      },
  
      getSelected: function(){
          return this.selected;
      },
  
      getExcluded: function(){
          return this.exclude;
      },
  
      getToday: function(){
          return this.today;
      },
  
      getCurrent: function(){
          return this.current;
      },
  
      clearSelected: function(){
          this.selected = [];
          this._drawContent();
      },
  
      toDay: function(){
          this.today = new Date();
          this.today.setHours(0,0,0,0);
          this.current = {
              year: this.today.getFullYear(),
              month: this.today.getMonth(),
              day: this.today.getDate()
          };
          this._drawHeader();
          this._drawContent();
      },
  
      setExclude: function(exclude){
          var element = this.element, o = this.options;
          if (Utils.isNull(exclude) && Utils.isNull(element.attr("data-exclude"))) {
              return ;
          }
          o.exclude = !Utils.isNull(exclude) ? exclude : element.attr("data-exclude");
          this._dates2array(o.exclude, 'exclude');
          this._drawContent();
      },
  
      setPreset: function(preset){
          var element = this.element, o = this.options;
          if (Utils.isNull(preset) && Utils.isNull(element.attr("data-preset"))) {
              return ;
          }
  
          o.preset = !Utils.isNull(preset) ? preset : element.attr("data-preset");
          this._dates2array(o.preset, 'selected');
          this._drawContent();
      },
  
      setSpecial: function(special){
          var element = this.element, o = this.options;
          if (Utils.isNull(special) && Utils.isNull(element.attr("data-special"))) {
              return ;
          }
          o.special = !Utils.isNull(special) ? special : element.attr("data-special");
          this._dates2array(o.exclude, 'special');
          this._drawContent();
      },
  
      setShow: function(show){
          var element = this.element, o = this.options;
  
          if (Utils.isNull(show) && Utils.isNull(element.attr("data-show"))) {
              return ;
          }
          o.show = !Utils.isNull(show) ? show : element.attr("data-show");
  
          this.show = Utils.isDateObject(show) ? show : Utils.isValue(o.inputFormat) ? o.show.toDate(o.inputFormat) : new Date(o.show);
          this.show.setHours(0,0,0,0);
          this.current = {
              year: this.show.getFullYear(),
              month: this.show.getMonth(),
              day: this.show.getDate()
          };
  
          this._drawContent();
      },
  
      setMinDate: function(date){
          var element = this.element, o = this.options;
  
          o.minDate = date !== null ? date : element.attr("data-min-date");
  
          this._drawContent();
      },
  
      setMaxDate: function(date){
          var element = this.element, o = this.options;
  
          o.maxDate = date !== null ? date : element.attr("data-max-date");
  
          this._drawContent();
      },
  
      setToday: function(val){
          var o = this.options;
  
          if (!Utils.isValue(val)) {
              val = new Date();
          }
          this.today = Utils.isDateObject(val) ? val : Utils.isValue(o.inputFormat) ? val.toDate(o.inputFormat) : new Date(val);
          this.today.setHours(0,0,0,0);
          this._drawHeader();
          this._drawContent();
      },
  
      i18n: function(val){
          var o = this.options;
          if (val === undefined) {
              return o.locale;
          }
          if (Metro.locales[val] === undefined) {
              return false;
          }
          o.locale = val;
          this.locale = Metro.locales[o.locale];
          this._drawCalendar();
      },
  
      changeAttrLocale: function(){
          var element = this.element;
          this.i18n(element.attr("data-locale"));
      },
  
      changeAttribute: function(attributeName){
          switch (attributeName) {
              case 'data-exclude': this.setExclude(); break;
              case 'data-preset': this.setPreset(); break;
              case 'data-special': this.setSpecial(); break;
              case 'data-show': this.setShow(); break;
              case 'data-min-date': this.setMinDate(); break;
              case 'data-max-date': this.setMaxDate(); break;
              case 'data-locale': this.changeAttrLocale(); break;
          }
      },
  
      destroy: function(){
          var element = this.element, o = this.options;
  
          element.off(Metro.events.click, ".prev-month, .next-month, .prev-year, .next-year");
          element.off(Metro.events.click, ".button.today");
          element.off(Metro.events.click, ".button.clear");
          element.off(Metro.events.click, ".button.cancel");
          element.off(Metro.events.click, ".button.done");
          element.off(Metro.events.click, ".week-days .day");
          element.off(Metro.events.click, ".days-row .day");
          element.off(Metro.events.click, ".curr-month");
          element.off(Metro.events.click, ".calendar-months li");
          element.off(Metro.events.click, ".curr-year");
          element.off(Metro.events.click, ".calendar-years li");
          element.off(Metro.events.click);
  
          if (o.ripple === true) Metro.destroyPlugin(element, "ripple");
  
          element.html("");
      }
  };
  
  $(document).on(Metro.events.click, function(){
      $('.calendar .calendar-years').each(function(){
          $(this).removeClass("open");
      });
      $('.calendar .calendar-months').each(function(){
          $(this).removeClass("open");
      });
  });
  
  Metro.plugin('calendar', Calendar);