KennethanCeyer/pg-calendar

View on GitHub
src/js/methods/init.js

Summary

Maintainability
F
1 wk
Test Coverage
define([
  '../manager/index',
  '../component/classNames',
  '../component/helper',
  '../component/models',
  '../component/global',
  './configure',
  'jquery',
  'moment'
], (DateManager,
    classNames,
    helper,
    models,
    global,
    methodConfigure,
    $,
    moment) => {
  const $window = $(window);
  const $document = $(document);

  return function (options) {
    const context = this;

    context.settings = {};
    methodConfigure.call(context, options);

    context.global = {
      calendarHtml: helper.format('<div class="{0} {0}-{4}">\
                                    <div class="{1}">\
                                      <a href="#" class="{1}-nav {1}-prev">\
                                          <span class="icon-arrow-left {1}-icon"></span>\
                                      </a>\
                                      <div class="{1}-date">\
                                          <span class="{1}-month"></span>\
                                          <span class="{1}-year"></span>\
                                      </div>\
                                      <a href="#" class="{1}-nav {1}-next">\
                                          <span class="icon-arrow-right {1}-icon"></span>\
                                      </a>\
                                    </div>\
                                    <div class="{2}"></div>\
                                    <div class="{3}"></div>\
                                  </div>', helper.getClass(models.name), classNames.top, classNames.header, classNames.body, context.settings.theme),
      calendarButtonsHtml: helper.format('<div class="{0}-group">\
                                            <a href="#" class="{0} {0}-cancel">{1}</a>\
                                            <a href="#" class="{0} {0}-apply">{2}</a>\
                                          </div>', classNames.button, context.settings.controls.cancel, context.settings.controls.ok),
      calendarScheduleContainerHtml: helper.format('<div class="{0}-schedule-container"></div>', classNames.button),
      calendarSchedulePinHtml: helper.format('<span class="{0}-schedule-pin {0}-schedule-pin-\\{0\\}" style="background-color: \\{1\\};"></span>', classNames.button),
    };

    const rangeClass = helper.getSubClass('unitRange');
    const rangeFirstClass = helper.getSubClass('unitRangeFirst');
    const rangeLastClass = helper.getSubClass('unitRangeLast');
    const activeClass = helper.getSubClass('unitActive');
    const activePositionClasses = [helper.getSubClass('unitFirstActive'), helper.getSubClass('unitSecondActive')];
    const toggleActiveClass = helper.getSubClass('unitToggleActive');
    const toggleInactiveClass = helper.getSubClass('unitToggleInactive');
    let $calendarButton = null;

    return context.each(function () {
      const $this = $(this);
      const local = {
        initialize: null,
        element: $this,
        calendar: $(context.global.calendarHtml),
        input: $this.is('input'),
        renderer: null,
        current: [null, null],
        date: {
          all: [],
          enabled: [],
          disabled: []
        },
        storage: {
          activeDates: [],
          schedules: []
        },
        dateManager: new DateManager(context.settings.date),
        calendarWrapperHtml: helper.format('<div class="{0}"></div>', helper.getSubClass('wrapper')),
        calendarWrapperOverlayHtml: helper.format('<div class="{0}"></div>', helper.getSubClass('wrapperOverlay')),
        context: context
      };
      let $parent = $this;

      if (context.settings.initialize === true) {
        local.initialize = local.current[0] = local.dateManager.date.clone();
      }

      this.local = local;

      if (context.settings.reverse === true) {
        local.calendar.addClass(helper.getSubClass('reverse'));
      }
      else {
        local.calendar.addClass(helper.getSubClass('default'));
      }

      for (let i = context.settings.week; i < context.settings.weeks.length + context.settings.week; i++) {
        if (i < 0) {
          i = global.languages.weeks.en.length - i;
        }
        let week = context.settings.weeks[i % context.settings.weeks.length];
        if (typeof week !== 'string') {
          continue;
        }
        week = week.toUpperCase();
        const $unit = $(helper.format('<div class="{0} {0}-{2}">{1}</div>', helper.getSubClass('week'), week, global.languages.weeks.en[i % global.languages.weeks.en.length].toLowerCase()));
        $unit.appendTo(local.calendar.find('.' + classNames.header));
      }

      if (context.settings.buttons === true) {
        $calendarButton = $(context.global.calendarButtonsHtml);
        $calendarButton.appendTo(local.calendar);
      }

      if (local.input === true || context.settings.modal === true) {
        const wrapperActiveClass = helper.getSubClass('wrapperActive');
        const overlayActiveClass = helper.getSubClass('wrapperOverlayActive');
        let $overlay;

        $parent = $(local.calendarWrapperHtml);
        $parent.bind('click', function (event) {
          event.stopPropagation();
        });

        $this
          .bind('click', event => {
            event.preventDefault();
            event.stopPropagation();
            event.stopImmediatePropagation();
            $overlay = $('.' + helper.getSubClass('wrapperOverlay'));

            if ($overlay.length < 1) {
              $overlay = $(local.calendarWrapperOverlayHtml);
              $overlay.appendTo('body');
            }

            $overlay.unbind('click.' + helper.getClass(models.name)).bind('click.' + helper.getClass(models.name), event => {
              event.stopPropagation();
              $parent.trigger('cancel.' + helper.getClass(models.name));
            });

            if ($parent.parent().is('body') === false) {
              $parent.appendTo('body');
            }

            $parent.show();
            $overlay.show();

            $window.unbind('resize.' + helper.getClass(models.name)).bind('resize.' + helper.getClass(models.name), () => {
              $parent.css({
                marginLeft: -$parent.outerWidth() / 2,
                marginTop: -$parent.outerHeight() / 2
              });
            }).triggerHandler('resize.' + helper.getClass(models.name));

            $this[models.name]('set', $this.val());

            setTimeout(() => {
              $overlay.addClass(overlayActiveClass);
              $parent.addClass(wrapperActiveClass);
            }, 25);
          })
          .bind('focus', function (event) {
            var $this = $(this);
            $this.blur();
          });

        $parent
          .unbind('cancel.' + helper.getClass(models.name) + ' ' + 'apply.' + helper.getClass(models.name))
          .bind('cancel.' + helper.getClass(models.name) + ' ' + 'apply.' + helper.getClass(models.name), function () {
            $overlay.removeClass(overlayActiveClass).hide();
            $parent.removeClass(wrapperActiveClass).hide();
          });
      }

      const generateDateRange = () => {
        if (
          !local.current[0] ||
          !local.current[1]
        ) {
          return false;
        }

        const firstSelectDate = local.current[0].format('YYYY-MM-DD');
        const lastSelectDate = local.current[1].format('YYYY-MM-DD');
        const firstDate = moment(Math.max(local.current[0].valueOf(), local.dateManager.date.clone().startOf('month').valueOf()));
        const lastDate = moment(Math.min(local.current[1].valueOf(), local.dateManager.date.clone().endOf('month').valueOf()));
        const firstDateIsUndered = (firstDate.format('YYYY-MM-DD') !== firstSelectDate);
        const lastDateIsOvered = (lastDate.format('YYYY-MM-DD') !== lastSelectDate);

        if (firstDateIsUndered === false) {
          firstDate.add(1, 'days');
        }

        if (lastDateIsOvered === false) {
          lastDate.add(-1, 'days');
        }

        const firstDateFixed = firstDate.format('YYYY-MM-DD');
        const lastDateFixed = lastDate.format('YYYY-MM-DD');

        for (; firstDate.format('YYYY-MM-DD') <= lastDate.format('YYYY-MM-DD'); firstDate.add(1, 'days')) {
          const date = firstDate.format('YYYY-MM-DD');
          const isRange = true;
          const $target = local.calendar.find(helper.format('.{0}[data-date="{1}"]', helper.getSubClass('unit'), date)).addClass(rangeClass);

          if (date === firstDateFixed) {
            $target.addClass(rangeFirstClass);
          }

          if (date === lastDateFixed) {
            $target.addClass(rangeLastClass);
          }
        }
      };

      const existsBetweenRange = (startDate, endDate, targetDate) => {
        if (targetDate) {
          if (
            startDate.diff(targetDate) < 0 &&
            endDate.diff(targetDate) > 0
          ) {
            return true;
          }
          else {
            return false;
          }
        }
        else {
          return false;
        }
      };

      const validDate = date => {
        if (context.settings.disabledDates.indexOf(date) !== -1) {
          return false;
        }

        if (date.diff(context.settings.maxDate) >= 0) {
          return false;
        }

        if (date.diff(context.settings.minDate) <= 0) {
          return false;
        }

        for (const idx in context.settings.disabledRanges) {
          const rangeDate = context.settings.disabledRanges[idx];
          const startRangeDate = moment(rangeDate[0]);
          const endRangeDate = moment(rangeDate[1]);

          if (existsBetweenRange(startRangeDate, endRangeDate, date)) {
            return false;
          }
        }


        const weekday = date.weekday();
        if (context.settings.disabledWeekdays.indexOf(weekday) !== -1) {
          return false;
        }

        return true;
      }

      const validDateArea = (startDate, endDate) => {
        let date;

        for (const idx in context.settings.disabledDates) {
          date = moment(context.settings.disabledDates[idx]);
          if (existsBetweenRange(startDate, endDate, date)) {
            return false;
          }
        }

        if (existsBetweenRange(startDate, endDate, context.settings.maxDate)) {
          return false;
        }

        if (existsBetweenRange(startDate, endDate, context.settings.minDate)) {
          return false;
        }

        for (const idx in context.settings.disabledRanges) {
          const rangeDate = context.settings.disabledRanges[idx];
          const startRangeDate = moment(rangeDate[0]);
          const endRangeDate = moment(rangeDate[1]);

          if (
            existsBetweenRange(startDate, endDate, startRangeDate) ||
            existsBetweenRange(startDate, endDate, endRangeDate)
          ) {
            return false;
          }
        }

        let startWeekday = startDate.weekday();
        let endWeekday = endDate.weekday();
        let tmp;

        if (startWeekday > endWeekday) {
          tmp = startWeekday;
          startWeekday = endWeekday;
          endWeekday = tmp;
        }

        for (let idx = 0, index = 0; idx < context.settings.disabledWeekdays.length && index < 7; idx++) {
          index++;
          const week = context.settings.disabledWeekdays[idx];

          if (
            week >= startWeekday &&
            week <= endWeekday
          ) {
            return false;
          }
        }

        return true;
      };

      local.renderer = () => {
        local.calendar.appendTo($parent.empty());
        local.calendar.find('.' + classNames.top + '-year').text(local.dateManager.year);
        local.calendar.find('.' + classNames.top + '-month').text(context.settings.monthsLong[local.dateManager.month - 1]);
        local.calendar.find(helper.format('.{0}-prev .{0}-value', classNames.top)).text(context.settings.months[local.dateManager.prevMonth - 1].toUpperCase());
        local.calendar.find(helper.format('.{0}-next .{0}-value', classNames.top)).text(context.settings.months[local.dateManager.nextMonth - 1].toUpperCase());

        if (context.settings.buttons === true && $calendarButton) {
          const $super = $this;
          $calendarButton.find('.' + classNames.button).bind('click', function (event) {
            event.preventDefault();
            event.stopPropagation();
            const $this = $(this);

            if ($this.hasClass(classNames.button + '-apply')) {
              $this.trigger('apply.' + models.name, local);
              var value = '';
              if (context.settings.toggle === true) {
                value = local.storage.activeDates.join(', ');
              }
              else if (context.settings.multiple === true) {
                var dateValues = [];

                if (local.current[0] !== null) {
                  dateValues.push(local.current[0].format(context.settings.format));
                }

                if (local.current[1] !== null) {
                  dateValues.push(local.current[1].format(context.settings.format));
                }

                value = dateValues.join(' ~ ');
              }
              else {
                value = local.current[0] === null ? '' : moment(local.current[0]).format(context.settings.format);
              }

              if (local.input === true) {
                $super.val(value).triggerHandler('change');
              }

              if (typeof context.settings.apply === 'function') {
                context.settings.apply.call(local.calendar, local.current, local);
              }
              $parent.triggerHandler('apply.' + helper.getClass(models.name));
            }
            else {
              $parent.triggerHandler('cancel.' + helper.getClass(models.name));
            }
          });
        }

        const $calendarBody = local.calendar.find('.' + classNames.body).empty();
        const firstDate = DateManager.Convert(local.dateManager.year, local.dateManager.month, local.dateManager.firstDay);
        const lastDate = DateManager.Convert(local.dateManager.year, local.dateManager.month, local.dateManager.lastDay);
        let firstWeekday = firstDate.weekday() - context.settings.week;
        let lastWeekday = lastDate.weekday() - context.settings.week;

        if (firstWeekday < 0) {
          firstWeekday += context.settings.weeks.length;
        }

        const $unitList = [], currentFormat = [
            local.current[0] === null ? null : local.current[0].format('YYYY-MM-DD'),
            local.current[1] === null ? null : local.current[1].format('YYYY-MM-DD')
          ], minDate = context.settings.minDate === null ? null : moment(context.settings.minDate),
          maxDate = context.settings.maxDate === null ? null : moment(context.settings.maxDate);

        for (let i = 0; i < firstWeekday; i++) {
          var $unit = $(helper.format('<div class="{0} {0}-{1}"></div>', helper.getSubClass('unit'), global.languages.weeks.en[i].toLowerCase()));
          $unitList.push($unit);
        }

        for (let i = local.dateManager.firstDay; i <= local.dateManager.lastDay; i++) {
          const iDate = DateManager.Convert(local.dateManager.year, local.dateManager.month, i);
          const iDateFormat = iDate.format('YYYY-MM-DD');
          const $unit = $(helper.format('<div class="{0} {0}-date {0}-{3}" data-date="{1}"><a href="#">{2}</a></div>', helper.getSubClass('unit'), iDate.format('YYYY-MM-DD'), i, global.languages.weeks.en[iDate.weekday()].toLowerCase()));

          if (context.settings.enabledDates.length > 0) {
            if ($.inArray(iDateFormat, context.settings.enabledDates) === -1) {
              $unit.addClass(helper.getSubClass('unitDisabled'));
            }
          }
          else if (context.settings.disabledWeekdays.length > 0 && $.inArray(iDate.weekday(), context.settings.disabledWeekdays) !== -1) {
            $unit.addClass(helper.getSubClass('unitDisabled')).addClass(helper.getSubClass('unitDisabledWeekdays'));
          }
          else if (
            (minDate !== null && minDate.diff(iDate) > 0) ||
            (maxDate !== null && maxDate.diff(iDate) < 0)
          ) {
            $unit.addClass(helper.getSubClass('unitDisabled')).addClass(helper.getSubClass('unitDisabledRange'));
          }
          else if ($.inArray(iDateFormat, context.settings.disabledDates) !== -1) {
            $unit.addClass(helper.getSubClass('unitDisabled'));
          }
          else if (context.settings.disabledRanges.length > 0) {
            const disabledRangesLength = context.settings.disabledRanges.length;
            for (let j = 0; j < disabledRangesLength; j++) {
              const disabledRange = context.settings.disabledRanges[j];
              const disabledRangeLength = disabledRange.length;

              if (iDate.diff(moment(disabledRange[0])) >= 0 && iDate.diff(moment(disabledRange[1])) <= 0) {
                $unit.addClass(helper.getSubClass('unitDisabled')).addClass(helper.getSubClass('unitDisabledRange')).addClass(helper.getSubClass('unitDisabledMultipleRange'));
                break;
              }
            }
          }

          if (
            context.settings.schedules.length > 0 &&
            typeof context.settings.scheduleOptions === 'object' &&
            typeof context.settings.scheduleOptions.colors === 'object'
          ) {
            const currentSchedules = context.settings.schedules.filter(function (schedule) {
              return schedule.date === iDateFormat;
            });

            const nameOfSchedules = $.unique(currentSchedules.map(function (schedule, index) {
              return schedule.name;
            }).sort());

            if (nameOfSchedules.length > 0) {
              //$unit.data('schedules', currentSchedules);
              const $schedulePinContainer = $(context.global.calendarScheduleContainerHtml);
              $schedulePinContainer.appendTo($unit);
              nameOfSchedules.map((name, index) => {
                if (context.settings.scheduleOptions.colors[name]) {
                  const color = context.settings.scheduleOptions.colors[name];
                  const $schedulePin = $(helper.format(context.global.calendarSchedulePinHtml, name, color));
                  $schedulePin.appendTo($schedulePinContainer);
                }
              });
            }
          }

          if (context.settings.toggle === true) {
            if ($.inArray(iDateFormat, local.storage.activeDates) !== -1 && local.storage.activeDates.length > 0) {
              $unit.addClass(toggleActiveClass);
            }
            else {
              $unit.addClass(toggleInactiveClass);
            }
          }
          else if ($unit.hasClass(helper.getSubClass('unitDisabled')) === false) {
            if (context.settings.multiple === true) {
              if ((currentFormat[0] && iDateFormat === currentFormat[0])) {
                $unit.addClass(activeClass).addClass(activePositionClasses[0]);
              }

              if ((currentFormat[1] && iDateFormat === currentFormat[1])) {
                $unit.addClass(activeClass).addClass(activePositionClasses[1]);
              }
            }
            else {
              if ((currentFormat[0] && iDateFormat === currentFormat[0]) &&
                $.inArray(currentFormat[0], context.settings.disabledDates) === -1 &&
                (context.settings.enabledDates.length < 1 || $.inArray(currentFormat[0], context.settings.enabledDates) !== -1)) {
                $unit.addClass(activeClass).addClass(activePositionClasses[0]);
              }
            }
          }

          $unitList.push($unit);
          const $super = $this;

          $unit.bind('click', function (event) {
            event.preventDefault();
            event.stopPropagation();

            const $this = $(this);
            const date = $this.data('date');
            let position = 0;
            let preventSelect = false;

            if ($this.hasClass(helper.getSubClass('unitDisabled'))) {
              preventSelect = true;
            }
            else {
              if (local.input === true && context.settings.multiple === false && context.settings.buttons === false) {
                $super.val(moment(date).format(context.settings.format));
                $parent.triggerHandler('apply.' + helper.getClass(models.name));
              }
              else {
                if (
                  local.initialize !== null &&
                  local.initialize.format('YYYY-MM-DD') === date &&
                  context.settings.toggle === false
                ) {
                }
                else {
                  if (context.settings.toggle === true) {
                    const match = local.storage.activeDates.filter(function (e, i) {
                      return e === date;
                    });
                    local.current[position] = moment(date);

                    if (match.length < 1) {
                      local.storage.activeDates.push(date);
                      $this.addClass(toggleActiveClass).removeClass(toggleInactiveClass);
                    }
                    else {
                      let index = 0;
                      for (let idx = 0; idx < local.storage.activeDates.length; idx++) {
                        const targetDate = local.storage.activeDates[idx];

                        if (date === targetDate) {
                          index = idx;
                          break;
                        }
                      }
                      local.storage.activeDates.splice(index, 1);
                      $this.removeClass(toggleActiveClass).addClass(toggleInactiveClass);
                    }
                  }
                  else if (
                    $this.hasClass(activeClass) === true &&
                    context.settings.pickWeeks === false
                  ) {
                    if (context.settings.multiple === true) {
                      if ($this.hasClass(activePositionClasses[0])) {
                        position = 0;
                      }
                      else if (activePositionClasses[1]) {
                        position = 1;
                      }
                    }
                    $this.removeClass(activeClass).removeClass(activePositionClasses[position]);
                    local.current[position] = null;
                  }
                  else {
                    if (context.settings.pickWeeks === true) {
                      if (
                        $this.hasClass(activeClass) === true ||
                        $this.hasClass(rangeClass) === true
                      ) {
                        for (let j = 0; j < 2; j++) {
                          local.calendar.find('.' + activeClass + '.' + activePositionClasses[j]).removeClass(activeClass).removeClass(activePositionClasses[j]);
                        }

                        local.current[0] = null;
                        local.current[1] = null;
                      }
                      else {
                        local.current[0] = moment(date).startOf('week').add(context.settings.week, 'days');
                        local.current[1] = moment(date).endOf('week').add(context.settings.week, 'days');

                        for (let j = 0; j < 2; j++) {
                          local.calendar.find('.' + activeClass + '.' + activePositionClasses[j]).removeClass(activeClass).removeClass(activePositionClasses[j]);
                          local.calendar.find(helper.format('.{0}[data-date="{1}"]', helper.getSubClass('unit'), local.current[j].format('YYYY-MM-DD'))).addClass(activeClass).addClass(activePositionClasses[j]);
                        }
                      }
                    }
                    else {
                      if (context.settings.multiple === true) {
                        if (local.current[0] === null) {
                          position = 0;
                        }
                        else if (local.current[1] === null) {
                          position = 1;
                        }
                        else {
                          position = 0;
                          local.current[1] = null;
                          local.calendar.find('.' + activeClass + '.' + activePositionClasses[1]).removeClass(activeClass).removeClass(activePositionClasses[1]);
                        }
                      }

                      local.calendar.find('.' + activeClass + '.' + activePositionClasses[position]).removeClass(activeClass).removeClass(activePositionClasses[position]);
                      $this.addClass(activeClass).addClass(activePositionClasses[position]);
                      local.current[position] = moment(date);
                    }

                    if (
                      local.current[0] &&
                      local.current[1]
                    ) {
                      if (local.current[0].diff(local.current[1]) > 0) {
                        let tmp = local.current[0];
                        local.current[0] = local.current[1];
                        local.current[1] = tmp;
                        tmp = null;

                        local.calendar.find('.' + activeClass).each(function () {
                          const $this = $(this);
                          for (const idx in activePositionClasses) {
                            const className = activePositionClasses[idx];
                            $this.toggleClass(className);
                          }
                        });
                      }

                      if (
                        validDateArea(local.current[0], local.current[1]) === false &&
                        context.settings.selectOver === false
                      ) {
                        local.current[0] = null;
                        local.current[1] = null;
                        local.calendar.find('.' + activeClass).removeClass(activeClass).removeClass(activePositionClasses[0]).removeClass(activePositionClasses[1]);
                      }

                      if (local.input === true && context.settings.buttons === false) {
                        const dateValues = []

                        if (local.current[0] !== null) {
                          dateValues.push(local.current[0].format(context.settings.format));
                        }

                        if (local.current[1] !== null) {
                          dateValues.push(local.current[1].format(context.settings.format));
                        }

                        $this.val(dateValues.join(', '));
                        $parent.trigger('apply.' + helper.getClass(models.name));
                      }
                    }
                  }

                  if (context.settings.multiple === true) {
                    local.calendar.find('.' + rangeClass).removeClass(rangeClass).removeClass(rangeFirstClass).removeClass(rangeLastClass);
                    generateDateRange.call();
                  }

                  if (context.settings.schedules.length > 0) {
                    local.storage.schedules = context.settings.schedules.filter(event => {
                      return event.date === date;
                    });
                  }
                }
              }
            }

            const classifyDate = date => {
              local.date.all.push(date);
              if (validDate(moment(date))) {
                local.date.enabled.push(date);
              }
              else {
                local.date.disabled.push(date);
              }
            };

            if (local.current[0]) {
              if (local.current[1]) {
                const startDate = local.current[0];
                const date = startDate.clone();

                for (; date.format('YYYY-MM-DD') <= local.current[1].format('YYYY-MM-DD'); date.add('1', 'days')) {
                  classifyDate(date.clone());
                }
              }
              else {
                const date = local.current[0];
                classifyDate(date.clone());
              }
            }

            if (preventSelect === false) {
              local.initialize = null;

              if (typeof context.settings.select === 'function') {
                context.settings.select.call($this, local.current, local);
              }
            }

            if (typeof context.settings.click === 'function') {
              context.settings.click.call($this, event, local);
            }
          });
        }

        for (let i = lastWeekday + 1; $unitList.length < context.settings.weeks.length * 5; i++) {
          if (i < 0) {
            i = global.languages.weeks.en.length - i;
          }
          const $unit = $(helper.format('<div class="{0} {0}-{1}"></div>', helper.getSubClass('unit'), global.languages.weeks.en[i % global.languages.weeks.en.length].toLowerCase()));
          $unitList.push($unit);
        }

        let $row = null;
        for (let i = 0; i < $unitList.length; i++) {
          const element = $unitList[i];
          if (i % context.settings.weeks.length == 0 || i + 1 >= $unitList.length) {
            if ($row !== null) {
              $row.appendTo($calendarBody);
            }

            if (i + 1 < $unitList.length) {
              $row = $(helper.format('<div class="{0}"></div>', helper.getSubClass('row')));
            }
          }
          $row.append(element);
        }

        local.calendar.find('.' + classNames.top + '-nav').bind('click', function (event) {
          event.preventDefault();
          event.stopPropagation();
          const $this = $(this);
          let type = 'unkown';

          if ($this.hasClass(classNames.top + '-prev')) {
            type = 'prev';
            local.dateManager = new DateManager(local.dateManager.date.clone().add(-1, 'months'));
          }
          else if ($this.hasClass(classNames.top + '-next')) {
            type = 'next';
            local.dateManager = new DateManager(local.dateManager.date.clone().add(1, 'months'));
          }

          if (typeof context.settings.page === 'function') {
            context.settings.page.call($this, {
              type: type,
              year: local.dateManager.year,
              month: local.dateManager.month,
              day: local.dateManager.day
            }, local);
          }

          if (typeof context.settings[type] === 'function') {
            context.settings[type].call($this, {
              type: type,
              year: local.dateManager.year,
              month: local.dateManager.month,
              day: local.dateManager.day
            }, local);
          }

          local.renderer.call();
        });

        if (context.settings.multiple === true) {
          local.calendar.find('.' + rangeClass).removeClass(rangeClass).removeClass(rangeFirstClass).removeClass(rangeLastClass);
          generateDateRange.call();
        }
      };

      local.renderer.call();
      $this[0][models.name] = local;

      if (typeof context.settings.init === 'function') {
        context.settings.init.call($this, local);
      }
    });
  };
});