# The date range picker you've ever needed!

Caleran is a Date Range Picker plugin, built using jQuery and moment.js libraries. It can also be used as a single date picker besides the range selection feature. Can be shown inline or used as a dropdown beside an input.

Get it from CodeCanyon

## Features

Date Range Picker

It's a range picker!

Predefined Ranges

You can use default ranges, or define your own!

Single Date Support

It can also be used as a single date picker!

Customizable

You can modify all the picker's behaviour like hiding some part, disabling some feature etc.

Quick Switching

Supports fast month and year navigation!

Inline Support

If you don't like dropdowns, you can convert your input to an inline calendar!

Mobile Ready

It renders beautifully on mobile devices

Portrait/Landscape Support

Also has a different landscape layout

Touch Slide Support

You can slide between months!

109 Languages

We support them all!
(What moment.js supports :P)

Sass Support

You can re-design completely using SASS.

Grunt Tasks

Yes, it's the automation era.

Icons (except Sass and Grunt logo) made by Freepik from www.flaticon.com is licensed by CC 3.0 BY

## How to use it

The main files of this plugin are `caleran.min.js` and `caleran.min.css`, which are generated by compiling and minifying `caleran.js` and `caleran.css`. The plugin relies on jQuery and moment.js libraries, also needs to be included before including `caleran.min.js`.

The font used on this plugin is Roboto, and the icons are provided by Font Awesome which are included remotely from their CDN's. You can change it anyway you want.

The example configuration which can be found in the base index file is:

    <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,500,700" rel="stylesheet"/>
    <link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="js/jquery-2.1.4.min.js" type="text/javascript"><\/script>');
    </script>
    <!-- .caleran includes -->
    <link href="build/css/caleran.min.css" rel="stylesheet"/>
    <script src="build/js/moment.min.js"></script>
    <script src="build/js/caleran.min.js"></script>
    <!-- .end caleran includes -->

Then, to attach a caleran object to an element you desire, use this:

    $(".caleran").caleran();

You can customize your plugin with options you provide to the initializing function,

    $(".caleran").caleran({inline: true, startOnMonday: true});

or the element's `data-plugin-options` property.

    <input class="caleran" data-plugin-options='{"calendarCount":1,"showHeader":true,"showFooter":true}'
    name="calendar-input" type="text" value="08.08.2017 - 08.09.2017"/>

Once initalized, you can access the caleran object like this:

    var caleran = $(".caleran:eq(3)").data("caleran");
    caleran.config.startDate = new Date();
    caleran.reDrawCalendars();

## Properties

Once you've got the `caleran` instance object, you can access these properties:

- `elem` [DOM node object]: The HTML dom node which the instance is created on.
- `$elem` [jQuery Object]: jQuery object of the dom node. Equals to `$(caleran.elem)`

> Please Note that if you've chosen a different target element, you will be accessing the initiator element by calling `caleran.$elem`. Your actual target element would be `caleran.config.target`.

For example,

        var caleran = $("#elem1").caleran();
        // caleran.elem will be equal to document.getElementById("elem1") or $("#elem1").get(0);
        // caleran.$elem will be equal to $("#elem1");

- `config` [JS Object]: The instance's configuration object. Consists of merging default values and user defined settings. The details of it is explained in the Options section.

These properties are also defined, but not recommended to tinker on.

- `container` [jQuery Object]: This refers to the outermost container element of the instance dropdown or inline instance and the input itself.
- `header` [jQuery Object]: This refers to the header part of the plugin.
- `footer` [jQuery Object]: This refers to the footer part, - not the mobile buttons part - the ranges part of the plugin.
- `input` [jQuery Object]: This refers to the first child of the container, which contains everything except the input which is caleran instantiated on.

## Configuration

These are the options you can set with the javascript plugin initialization object, or with the `data-plugin-options` html attribute on the input element, or within the events by directly modifying the `caleran.config` object.

- `startDate` [moment object|javascript Date Object|string]: the selected start date, initially today is selected if not defined inside the input's value, or any of the initialization configuration methods.
- `endDate` [moment object|javascript Date Object|string]: the selected end date, initially today is selected if not defined inside the input's value, or any of the initialization configuration methods.
- `format` [string]: the default format for showing in input, defaults to short date format of locale, for all possible inputs, look here: https://momentjs.com/docs/#/displaying/format/ default: 'L'
- `dateSeparator` [string]: if not used as a single date picker, this will be the seperator, default " - ".
- `calendarCount` [integer]: how many calendars will be shown in the plugin screen, default 2
- `inline` [boolean]: display as an inline input replacement instead of input dropdown. default: false
- `minDate` [moment object|javascript Date Object|string|null]: minimum selectable date, default null (no minimum)
- `maxDate` [moment object|javascript Date Object|string|null]: maximum selectable date, default null (no maximum)
- `showHeader` [boolean]: visibility of the part which displays the selected start and end dates, default true
- `showFooter` [boolean]: visibility of the part which contains user defined ranges, default true
- `startEmpty` [boolean]: whether the input should remain empty until user makes a selection, default false
- `showButtons` [boolean]: whether the input should display the apply and cancel buttons in dropdown, default false
- `enableKeyboard` [boolean]: enable this if you want to add keyboard support to the calendar. The keys are:
- `enableKeyboard` [boolean]: enable this if you want to add keyboard support to the calendar. The keys are:
  - `UP` : Go to same weekday on the previous week
  - `DOWN` : Go to same weekday on the next week
  - `LEFT` : Go to the previous day
  - `RIGHT` : Go to the next day
  - `PG UP` : Go to the previous month
  - `PG DOWN` : Go to the next month
  - `SHIFT + PG UP` : Go to the previous year
  - `SHIFT + PG DOWN` : Go to the next year
- `startOnMonday` [boolean]: false, // if you want to start the calendars on Monday, set this to true. Note that if the locale already starts on Monday, this setting will be ignored.
- `container` [string]: the selector of the dropdowns container, default "body"
- `oneCalendarWidth` [integer]: the width of one calendar, if two calendars are shown, the input width will be 2 * this setting. default 230
- `showOn` ["bottom"|"top"|"left"|"right"|"center"]: dropdown placement position relative to input element, will be adjusted to the viewport, default "bottom"
- `arrowOn` ["bottom"|"top"|"left"|"right"|"center"]: arrow position relative to dropdown element, will be adjusted to the viewport, default "left"
- `autoAlign` [boolean]: enables dropdown auto placement change when the dropdown is not fully visible on the viewport. Default "true"
- `locale` [string]: moment locale setting, for more information: https://momentjs.com/docs/#/i18n/changing-locale/, and for a list of available locales: https://momentjs.com/ (bottom of the page)
- `singleDate` [boolean]: if you want a single date picker, set this to true, default false
- `target`: [jquery object] the element to update after selection, if it's null, the element that is instantiated on will be updated. default null

- `ranges`: [array] predefined ranges range objects array, which each will create a button in the footer, and when the user clicks, it'll automatically will be applied. One range is defined like below:

  - `title` [string]: the label which will appear on the button,
  - `startDate` [moment object|javascript Date Object|string]: the first date of the range,
  - `endDate` [moment object|javascript Date Object|string]: the last date of the range,
- `rangeLabel` [string] : The title displayed in the defined ranges list section, default "Ranges: "
- `cancelLabel` [string]: The cancel button label, default "Cancel"
- `applyLabel` [string]: The apply button label, default "Apply"
- `enableMonthSwitcher` [boolean]: Enables the month switcher when clicking on month names. Default: true
- `enableYearSwitcher` [boolean]: Enables the year switcher when clicking on years. Default: true
- `numericMonthSwitcher` [boolean]: If set to true, shows month numbers instead of month names in month selector. Default: false
- `monthSwitcherFormat` [string]: Changes the format of the month name displayed on the month selector. Default: "MMMM" (long month name format)
- `showWeekNumbers` [string]: Shows week numbers on the left of the calendars. Default: false
- `autoCloseOnSelect` [boolean]: On instances that are not displayed inline, this setting is used to automatically close the dropdown when a selection is made.
- `disableDays` [function]: Enables day based disabling filters, input value is the current day to be processed. Example:

      {
        disableDays: function(day){
           return day.isSame(moment("17/05/2017")); // will return true on that day and the day will be disabled.
        }
      }

- `disabledRanges` [object array]: Enables user to disable specific ranges from selection. Can be used with `continuous` option to preserve continuity. Object structure:

       [{ start: [moment object], end: [moment object]}, ..]

- `continuous` [boolean]: Adds a check if the selected range continues any disabled days. Reverts the selection to it's original state when the user tries to select a range which contains a disabled date.
- `rangeOrientation` [string]: Sets the range view to "vertical" or "horizontal" which renders the range part on the right or on the bottom of the calendar. Default: "horizontal"
- `verticalRangeWidth` [string]: Sets the vertical range view panel width in pixels. Default: 150

## Available Events

- `onbeforeselect` [function]: event which is triggered before selecting the end date ( a range selection is completed). The return value decides whether the selection will happen. Returning false will prevent the input to update.

  Prototype:

            onbeforeselect: function(caleran, startDate, endDate){
                // caleran: caleran object instance
                // startDate: moment.js instance
                // endDate: moment.js instance
                return true; // false prevents update
            }

- `onafterselect` [function]: event which is triggered after selecting the end date ( the input value changed )

  Prototype:

            onafterselect: function(caleran, startDate, endDate){
                // caleran: caleran object instance
                // startDate: moment.js instance
                // endDate: moment.js instance
            }

- `onbeforeshow` [function]: event which is triggered before showing the dropdown

  Prototype:

            onbeforeshow: function(caleran){
                // caleran: caleran object instance
            }

- `onbeforehide` [function]: event which is triggered before hiding the dropdown

  Prototype:

            onbeforehide: function(caleran){
                // caleran: caleran object instance
            }

- `onaftershow` [function]: event which is triggered after showing the dropdown

  Prototype:

            onaftershow: function(caleran){
                // caleran: caleran object instance
            }

- `onafterhide` [function]: event which is triggered after hiding the dropdown

  Prototype:

            onafterhide: function(caleran){
                // caleran: caleran object instance
            }

- `onfirstselect` [function]: event which is triggered after selecting the first date of ranges

  Prototype:

            onfirstselect: function(caleran, startDate){
                // caleran: caleran object instance
                // startDate: moment.js instance
            }

- `onrangeselect` [function]: event which is triggered after selecting a range from the defined range links

  Prototype:

            onrangeselect: function(caleran, range){
                // caleran: caleran object instance
                // range: selected range definition
            }

- `onbeforemonthchange` [function]: event which fires before changing the first calendar month of multiple calendars, or the month of a single calendar. The return value decides whether the month switch will take place.

  Prototype:

            onbeforemonthchange: function(caleran, month, direction){
                // caleran: caleran object instance
                // month : moment.js object of first day of the month selected on the **first** calendar
                // direction: "next" or "prev", shows the month change direction. if `month.month()` is 4,
                // and direction is "prev", next month will be 3.
                return true; // false disables switching
            }

- `onaftermonthchange` [function]: event which fires after changing the first calendar month of multiple calendars, or the month of a single calendar

  Prototype:

            onaftermonthchange: function(caleran, month){
                // caleran: caleran object instance
                // month : moment.js object of first day of the month selected on the first calendar
            }

- `ondraw` [function]: event which fires after redraws in calendar

  Prototype:

        onredraw: function(caleran){
          // caleran: caleran object instance
        }

- `oninit` [function]: event which fires after instance initialization

  Prototype:

        oninit: function(caleran){
          // caleran: caleran object instance
        }

## Methods

- `validateDates` [function]: Validates the startDate, endDate, minDate, maxDate parameters of the instance configuration, by the means of parsability and order, and defaults to today's date for startDate and endDate, and to null for maxDate and minDate.

- `clearInput` [function]: Clears the input.

- `fetchInputs` [function]: Retrieves the date(s) from the instance holder input and validates them before putting it to it's configuration.

- `updateInput` [function]: Updates the instance holder input with the instance values and configuration.

- `drawNextMonth` [function]: Triggers the instance show the next month after the first calendar month as the first calendar.

- `drawPrevMonth` [function]: Triggers the instance show the previous month before the first calendar month as the first calendar.

- `reDrawCalendars` [function]: Triggers a complete restructuring of the instance. Drawing the container first, then the header, then the calendars, then the footer.

- `reDrawCells` [function]: Only modifies the calendar's related parts with the configuration variables. Doesn't entirely build the instance again like `reDrawCalendars` method does.

- `setViewport` [function]: On dropdown instances, if the dropdown falls outside of the viewport (when shown, not scrolled) this function decides and calculates it's new position opposed to its configuration. For example, if the dropdown position is set to `bottom` and it falls below the page bottom edge, this method makes it appear as it was set to `top` for once.

- `showDropdown` [function]: On dropdown and mobile instances, if the dropdown is not visible, this method triggers the show method.

- `hideDropdown` [function]: On dropdown and mobile instances, if the dropdown is visible, this method hides it.

- `setStart` [function]: Sets the start date of the input. Time portion is ignored.

- `setEnd` [function]: Sets the end date of the input. Time portion is ignored.

- `setMinDate` [function]: Sets the minimum selectable date of the input. Time portion is ignored.

- `setMaxDate` [function]: Sets the maximum selectable date of the input. Time portion is ignored.

- `setDisplayDate` [function] : Sets the displayed month and year, day and hours are ignored.

         var instance = $(".caleran").data("caleran");

         // using moment object
         instance.setStart(moment());

         // using javascript Date object
         instance.setStart(new Date());

         // using ISO and RFC standardized date strings
         instance.setStart("2017-11-27T13:07:04+00:00"); // ISO 8601 and RFC 3339
         instance.setStart("Mon, 27 Nov 2017 13:07:04 +0000"); // RFC 822, 1035, 1123, 2822
         instance.setStart("Monday, 27-Nov-17 13:07:04 UTC"); // RFC 2822

         // using unix timestamp
         instance.setStart(1511788024);

         // using custom formatted date time string
         instance.setStart(moment("16:06 27.11.2017","HH:mm dd.MM.YYYY"));

## Examples

### Default Range Picker

Preview:

HTML:

          <input type="text" id="caleran-ex-1" />

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-1").caleran();
          </script>

### Dropdown Positioning (Auto Alignment Enabled)

Preview:

HTML:

          <input type="text" id="caleran-ex-1-1" />
        <input type="text" id="caleran-ex-1-2" />
        <input type="text" id="caleran-ex-1-3" />
        <input type="text" id="caleran-ex-1-4" />

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-1-1").caleran({showOn:"top",autoAlign:true});
              $("#caleran-ex-1-2").caleran({showOn:"left",autoAlign:true});
              $("#caleran-ex-1-3").caleran({showOn:"right",autoAlign:true});
              $("#caleran-ex-1-4").caleran({showOn:"bottom",autoAlign:true});
          </script>

### Dropdown Positioning (Auto Alignment Disabled)

Preview:

HTML:

          <input type="text" id="caleran-ex-1-5" />
        <input type="text" id="caleran-ex-1-6" />
        <input type="text" id="caleran-ex-1-7" />
        <input type="text" id="caleran-ex-1-8" />

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-1-5").caleran({showOn:"top",autoAlign:false});
              $("#caleran-ex-1-6").caleran({showOn:"left",autoAlign:false});
              $("#caleran-ex-1-7").caleran({showOn:"right",autoAlign:false});
              $("#caleran-ex-1-8").caleran({showOn:"bottom",autoAlign:false});
          </script>

### Arrow Positioning

Preview:

HTML:

        <style> .vhide{ visibility:hidden; } </style>
        <input type="text" class="vhide"><input type="text" id="caleran-ex-t-r" value="06/21/2017" /><input type="text" id="caleran-ex-t-c" value="06/21/2017" /><input type="text" id="caleran-ex-t-l" value="06/21/2017" /><input type="text" class="vhide"><br><br>
        <input type="text" id="caleran-ex-l-t" value="06/21/2017" /><input type="text" class="vhide"><input type="text" class="vhide"><input type="text" class="vhide"><input type="text" id="caleran-ex-r-t" value="06/21/2017" /><br><br>
        <input type="text" id="caleran-ex-l-c" value="06/21/2017" /><input type="text" class="vhide"><input type="text" id="caleran-ex-c-c" value="06/21/2017" /><input type="text" class="vhide"><input type="text" id="caleran-ex-r-c" value="06/21/2017" /><br><br>
        <input type="text" id="caleran-ex-l-b" value="06/21/2017" /><input type="text" class="vhide"><input type="text" class="vhide"><input type="text" class="vhide"><input type="text" id="caleran-ex-r-b" value="06/21/2017" /><br><br>
        <input type="text" class="vhide"><input type="text" id="caleran-ex-b-r" value="06/21/2017" /><input type="text" id="caleran-ex-b-c" value="06/21/2017" /><input type="text" id="caleran-ex-b-l" value="06/21/2017" /><input type="text" class="vhide"><br><br>

JavaScript:

      <script type="text/javascript">
        $("#caleran-ex-t-r").caleran({
            showOn: "top",
            arrowOn: "right"
        });
        $("#caleran-ex-t-c").caleran({
            showOn: "top",
            arrowOn: "center"
        });
        $("#caleran-ex-t-l").caleran({
            showOn: "top",
            arrowOn: "left"
        });
        $("#caleran-ex-l-c").caleran({
            showOn: "left",
            arrowOn: "center"
        });
        $("#caleran-ex-l-t").caleran({
            showOn: "left",
            arrowOn: "top"
        });
        $("#caleran-ex-l-b").caleran({
            showOn: "left",
            arrowOn: "bottom"
        });
        $("#caleran-ex-c-c").caleran({
            showOn: "center",
            arrowOn: "center"
        });
        $("#caleran-ex-r-c").caleran({
            showOn: "right",
            arrowOn: "center"
        });
        $("#caleran-ex-r-t").caleran({
            showOn: "right",
            arrowOn: "top"
        });
        $("#caleran-ex-r-b").caleran({
            showOn: "right",
            arrowOn: "bottom"
        });

        $("#caleran-ex-b-r").caleran({
            showOn: "bottom",
            arrowOn: "right"
        });
        $("#caleran-ex-b-c").caleran({
            showOn: "bottom",
            arrowOn: "center"
        });
        $("#caleran-ex-b-l").caleran({
            showOn: "bottom",
            arrowOn: "left"
        });
      </script>

### Hiding the header

Preview:

HTML:

          <input type="text" id="caleran-ex-2" />

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-2").caleran({showHeader: false});
          </script>

### Hiding the footer

Preview:

HTML:

          <input type="text" id="caleran-ex-3" />

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-3").caleran({showFooter: false});
          </script>

### Showing dropdown apply/cancel buttons

This will only work with dropdown desktop view, inline views don't support cancel and apply buttons. Mobile modal view already has them.
Preview:

HTML:

          <input type="text" id="caleran-ex-5-3" placeholder="Select a Date" />

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-5-3").caleran({showButtons: true});
          </script>

### Changing calendar count

Preview:

HTML:

          <input type="text" id="caleran-ex-4" />

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-4").caleran({calendarCount: 3});
          </script>

### Inline calendar

Preview:

HTML:

          <input type="text" id="caleran-ex-5" />

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-5").caleran({inline: true});
          </script>

### Empty on initialization

Preview:

HTML:

          <input type="text" id="caleran-ex-5-1" placeholder="Select a date" />

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-5-1").caleran({startEmpty: true});
          </script>

### Single date picker

Preview:

HTML:

          <input type="text" id="caleran-ex-6" />

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-6").caleran({singleDate: true});
          </script>

### Range/Single switch

Preview:

Single Date Multiple Dates

HTML:

    <label for='single-caleran-mod'>
      <input type='radio' value="single"  id='single-caleran-mod' name="caleran-type-selector"
        class='caleran-type-selector'>
        &nbsp;Single Date
      </label>
    <label for='multi-caleran-mod'>
      <input type='radio' value="multi"  id='multi-caleran-mod' name="caleran-type-selector"
        class='caleran-type-selector' checked>
      &nbsp;Multiple Dates
    </label>
    <input type="text" id="caleran-ex-6-4" />

JavaScript:

      <script type="text/javascript">
        $("#caleran-ex-6-4").caleran();
        $(".caleran-type-selector").click(function(){
          $("#caleran-ex-6-4").data("caleran").destroy();
          $("#caleran-ex-6-4").caleran({
            singleDate: $("input[name='caleran-type-selector']:checked").val() == "single" ? true : false
          });
        });
      </script>

### Linked Single Date Pickers

Preview:

Start Date:
End Date:

HTML:

      <div style='display: flex;'><div>Start Date: <input type="text" id="caleran-ex-6-5-start" /></div><div style='margin-left:20px;'>End Date:  <input type="text" id="caleran-ex-6-5-end" /></div></div>

JavaScript:

      <script type="text/javascript">
        var startDate, endDate, startInstance, endInstance;
        var fillInputs = function () {
            startInstance.$elem.val(startDate ? startDate.locale(startInstance.config.format).format(startInstance.config.format) : "");
            endInstance.$elem.val(endDate ? endDate.locale(endInstance.config.format).format(endInstance.config.format) : "");
        };
        $("#caleran-ex-6-5-start").caleran({
            startEmpty: $("#caleran-ex-6-5-start").val() === "",
            startDate: $("#caleran-ex-6-5-start").val(),
            endDate: $("#caleran-ex-6-5-end").val(),
            enableKeyboard: false,
            oninit: function (instance) {
                startInstance = instance;
                if (!instance.config.startEmpty && instance.config.startDate) {
                    instance.$elem.val(instance.config.startDate.locale(instance.config.format).format(instance.config.format));
                    startDate = instance.config.startDate.clone();
                }
            },
            onbeforeshow: function (instance) {
                if (startDate) {
                    startInstance.config.startDate = startDate;
                    endInstance.config.startDate = startDate;
                }
                if (endDate) {
                    startInstance.config.endDate = endDate.clone();
                    endInstance.config.endDate = endDate.clone();
                }
                fillInputs();
                instance.updateHeader();
                instance.reDrawCells();
            },
            onfirstselect: function (instance, start) {
                startDate = start.clone();
                startInstance.globals.startSelected = false;
                startInstance.hideDropdown();
                endInstance.showDropdown();
                endInstance.config.minDate = startDate.clone();
                endInstance.config.startDate = startDate.clone();
                endInstance.config.endDate = null;
                endInstance.globals.startSelected = true;
                endInstance.globals.endSelected = false;
                endInstance.globals.firstValueSelected = true;
                endInstance.setDisplayDate(start);
                if (endDate && startDate.isAfter(endDate)) {
                    endInstance.globals.endDate = endDate.clone();
                }
                endInstance.updateHeader();
                endInstance.reDrawCells();
                fillInputs();
            }
        });
        $("#caleran-ex-6-5-end").caleran({
            startEmpty: $("#caleran-ex-6-5-end").val() === "",
            startDate: $("#caleran-ex-6-5-start").val(),
            endDate: $("#caleran-ex-6-5-end").val(),
            enableKeyboard: false,
            autoCloseOnSelect: true,
            oninit: function (instance) {
                endInstance = instance;
                if (!instance.config.startEmpty && instance.config.endDate) {
                    instance.$elem.val(instance.config.endDate.locale(instance.config.format).format(instance.config.format));
                    endDate = instance.config.endDate.clone();
                }
            },
            onbeforeshow: function (instance) {
                if (startDate) {
                    startInstance.config.startDate = startDate;
                    endInstance.config.startDate = startDate;
                }
                if (endDate) {
                    startInstance.config.endDate = endDate.clone();
                    endInstance.config.endDate = endDate.clone();
                }
                fillInputs();
                instance.updateHeader();
                instance.reDrawCells();
            },
            onafterselect: function (instance, start, end) {
                startDate = start.clone();
                endDate = end.clone();
                endInstance.hideDropdown();
                startInstance.config.endDate = endDate.clone();
                startInstance.globals.firstValueSelected = true;
                fillInputs();
                endInstance.globals.startSelected = true;
                endInstance.globals.endSelected = false;
            }
        });
    </script>

### Minimal Single date picker

Preview:

HTML:

        <input type="text" id="caleran-ex-6-2" />

JavaScript:

        <script type="text/javascript">
          $("#caleran-ex-6-2").caleran({
            singleDate: true,
            calendarCount: 1,
            showHeader: false,
            showFooter: false,
            autoCloseOnSelect: true
          });
        </script>

### Ranges on the Right

Preview:

HTML:

        <input type="text" id="caleran-ex-6-6-1" />

JavaScript:

        <script type="text/javascript">
          $("#caleran-ex-6-6-1").caleran({
            rangeOrientation: "vertical"
          });
        </script>

### Ranges on the Right with Buttons

Preview:

HTML:

        <input type="text" id="caleran-ex-6-6-2" />

JavaScript:

        <script type="text/javascript">
          $("#caleran-ex-6-6-2").caleran({
            rangeOrientation: "vertical",
            showButtons: true
          });
        </script>

### Ranges on the Right (inline)

Preview:

HTML:

        <input type="text" id="caleran-ex-6-6-3" />

JavaScript:

        <script type="text/javascript">
          $("#caleran-ex-6-6-3").caleran({
            inline: true,
            rangeOrientation: "vertical"
          });
        </script>

### Showing week numbers

Preview:

HTML:

        <input type="text" id="caleran-ex-6-6-4" />

JavaScript:

        <script type="text/javascript">
          $("#caleran-ex-6-6-4").caleran({
            showWeekNumbers: true
          });
        </script>

### Auto Close on Select

Preview:

HTML:

      <input type="text" id="caleran-ex-6-1" />

JavaScript:

      <script type="text/javascript">
        $("#caleran-ex-6-1").caleran({autoCloseOnSelect: true});
      </script>

### Defining Min/Max Dates

Preview:

HTML:

      <input type="text" id="caleran-ex-6-3" />

JavaScript:

      <script type="text/javascript">
        $("#caleran-ex-6-3").caleran({
          minDate: moment().subtract(1, "weeks").startOf("week"),
          maxDate: moment().add(1, "weeks").endOf("week")
        });
      </script>

### Defining custom ranges

Preview:

HTML:

          <input type="text" id="caleran-ex-7" />

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-7").caleran({ranges: [
                  {
                      title: "Next Week",
                      startDate: moment().add(1,"weeks").startOf("week"),
                      endDate: moment().add(1,"weeks").endOf("week")
                  },
                  {
                      title: "Today",
                      startDate: moment(),
                      endDate: moment()
                  },
                  {
                      title: "Yesterday",
                      startDate: moment().subtract(1,"days"),
                      endDate: moment().subtract(1,"days")
                  },
                  {
                      title: "Last 7 days",
                      startDate: moment().subtract(7,"days"),
                      endDate: moment().subtract(1,"days")
                  },
                  {
                      title: "Last 30 days",
                      startDate: moment().subtract(30,"days"),
                      endDate: moment().subtract(1,"days")
                  },
                  {
                      title: "This month",
                      startDate: moment().startOf("month"),
                      endDate: moment().endOf("month")
                  },
                  {
                      title: "Last month",
                      startDate: moment().subtract(1,"months").startOf("month"),
                      endDate: moment().subtract(1,"months").endOf("month")
                  }
              ]});
          </script>

### Custom events

Preview:

HTML:

          <input type="text" id="caleran-ex-8" />
          <div class="caleranlabel"></div>

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-8").caleran({
                  onafterselect: function(caleran, startDate, endDate) {
                      caleran.$elem.closest(".well").find(".caleranlabel")
                        .text("You have chosen between " + startDate.format('LLLL') + " and " + endDate.format('LLLL'));
                  }
              });
          </script>

### Change first day of week

Preview:

HTML:

          <input type="text" id="caleran-ex-9" />

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-9").caleran({startOnMonday: true});
          </script>

### Changing locale

Preview:

HTML:

          <input type="text" id="caleran-ex-10" />

JavaScript:

          <script type="text/javascript">
              var userLanguage = navigator.language || navigator.userLanguage;
              if(userLanguage == "en") userLanguage = "fr";
              $("#caleran-ex-10").caleran({locale: userLanguage });
          </script>

### Changing locale (inline)

Preview:

HTML:

          <input type="text" id="caleran-ex-10-2" />

JavaScript:

          <script type="text/javascript">
              var userLanguage = navigator.language || navigator.userLanguage;
              if(userLanguage == "en") userLanguage = "fr";
              $("#caleran-ex-10-2").caleran({locale: userLanguage, inline: true });
          </script>

### Week Select Mode

Preview:

HTML:

        <input type="text" id="caleran-ex-10-1" />

JavaScript:

        <script type="text/javascript">
          $("#caleran-ex-10").caleran({
            onfirstselect: function(elem,start){
                elem.config.startDate = moment(start).startOf("week");
                elem.config.endDate = moment(start).endOf("week");
                elem.globals.endSelected = true;
                elem.globals.startSelected = false;
                elem.globals.hoverDate = null;
                elem.$elem.find( ".caleran-apply" ).removeAttr( "disabled" );
                elem.updateInput();
            }
          });
        </script>

### Custom target element

Preview:

HTML:

        <input type="text" id="caleran-ex-11-target" />
        <button id="caleran-ex-11">Open Caleran</button>

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-11").caleran({target: $("#caleran-ex-11-target")});
          </script>

### Custom disabled ranges (with callback)

Note: This task would only fill the input on Wednesdays, because the only valid (selectable) dates are Wednesdays on the calendar. If the start day or end day isn't selectable, the plugin will revert itself to `startEmpty` state when initialized.

Preview:

HTML:

        <input type="text" id="caleran-ex-13" />

JavaScript:

        <script type="text/javascript">
          $("#caleran-ex-13").caleran({
            disableDays: function(day){
              return day.day() != 3;
            }
          });
        </script>

### Custom disabled ranges (with array)

Preview:

HTML:

        <input type="text" id="caleran-ex-13-2" value="03/19/2017 - 03/20/2017" />

JavaScript:

        <script type="text/javascript">
          $("#caleran-ex-13-2").caleran({
            disabledRanges: [
              {
                "start": moment("10/03/2017","DD/MM/YYYY"),
                "end": moment("18/03/2017", "DD/MM/YYYY")
              },
              {
                "start": moment("01/04/2017","DD/MM/YYYY"),
                "end": moment("05/04/2017", "DD/MM/YYYY")
              },
              {
                "start": moment("11/04/2017","DD/MM/YYYY"),
                "end": moment("15/04/2017", "DD/MM/YYYY")
              }
            ]
          });
        </script>

### Custom disabled ranges (preserve continuousity)

Preview:

HTML:

        <input type="text" id="caleran-ex-13-3" value="03/19/2017 - 03/20/2017" />

JavaScript:

        <script type="text/javascript">
          $("#caleran-ex-13-3").caleran({
            continuous: true,
            disabledRanges: [
              {
                start: moment("10/03/2017","DD/MM/YYYY"),
                end: moment("18/03/2017", "DD/MM/YYYY")
              },
              {
                "start": moment("01/04/2017","DD/MM/YYYY"),
                "end": moment("05/04/2017", "DD/MM/YYYY")
              },
              {
                "start": moment("11/04/2017","DD/MM/YYYY"),
                "end": moment("15/04/2017", "DD/MM/YYYY")
              }
            ]
          });
        </script>

### Show & Hide with triggers

Preview:

HTML:

        <input type="text" id="caleran-ex-13-1" />
        <button class="caleran-show">Show Instance</button>
        <button class="caleran-hide">Hide Instance</button>

JavaScript:

        <script type="text/javascript">
          $("#caleran-ex-13-1").caleran();
          $(".caleran-show").on("click",function(e){
            var caleran = $("#caleran-ex-13-1").data("caleran");
            caleran.showDropdown(e);
          });
          $(".caleran-hide").on("click",function(e){
            var caleran = $("#caleran-ex-13-1").data("caleran");
            caleran.hideDropdown(e);
          });
        </script>

### Using inside a modal

Preview:

HTML:

        <!-- Modal -->
        <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
          <div class="modal-dialog" role="document">
            <div class="modal-content">
              <div class="modal-body">
                <input type="text" id="caleran-ex-12" />
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
              </div>
            </div>
          </div>
        </div>
        <!-- Button trigger modal -->
        <button type="button" class="btn btn-primary" onclick="$('#myModal').modal('show');" >
              Launch demo modal
        </button>

JavaScript:

          <script type="text/javascript">
              $("#caleran-ex-12").caleran();
          </script>

## Important Notes

- I left the caleran object fully accessible to the inner variables, so you can alter the object's config in any event. For example, you can alter the max date of the calendar after first selection like this (limiting the user to select max 7 days of the first selection):

        onfirstselect: function(caleran, startDate){
            caleran.config.maxDate = startDate.clone().add(7,"days");
        },
        onafterselect: function(caleran, startDate, endDate){
            caleran.config.maxDate = null;
        }

  or another example, disabling previous date selection:

        onfirstselect: function(caleran, startDate){
            caleran.config.minDate = startDate.clone();
        },
        onafterselect: function(caleran, startDate, endDate){
            caleran.config.minDate = null;
        }

- The cloning is very important when adding or subtracting, because they modify the reference element too! As you can see in the above examples, the startDate and the endDate elements are cloned when defining the maxDate and minDate values. If you don't want to modify the startDate or endDate intentionally, use cloning.

- Mobile only supports modal like interface. Dropdowns and inline options currently don't work on mobile phones. Added inline support on mobile on version 1.3.1.

- Mobile versions only show 1 calendar. If you want it to support multiple calendars on mobile or inline support, let me know how it should be designed, and I'll try to put it on the next release. Thanks to ginharja, it's now implemented.

- Only one event can be bound using the initialize config object. Multiple events are not supported.

## Changelog

- #### v1.0.0

  - Released initial version.

- #### v1.0.1

  - before updating the input, added check for null variables

- #### v1.1.0

  - added `ondraw` event
  - added `disableDays` function to disable custom days
  - fixed `startOnMonday` if moment.js locale already starts at Monday
  - fixed deprecated `jQuery.size()` warnings
  - added `autoCloseOnSelect` option to close when a date/range is selected
  - added Show & Hide methods (`showDropdown`/`hideDropdown`)
  - changed all locale aware weekdays to act constant in every locale (0-Sunday and 6-Saturday)
  - added `oninit` event

- #### v1.1.1

  - added event handler checks before event.stopPropagation occurances
  - seperated click & tap events on mobile and desktop
  - checked jQuery UI tap event exist before loading hammer.js

- #### v1.1.2

  - fixed range click locale bug (which causes wrong start date output)

- #### v1.1.3

  - fixed apply button click event on mobile screens
  - added `disabledRanges` option to specify schedule like selections
  - added `countinuous` option to only allow continuous range selection

- #### v1.2.0

  - added direction parameter to `onbeforemonthchange` event
  - added quick year and month switching feature
  - added multiple calendar support for mobile

- #### v1.2.1

  - fixed IE10 compatibility on JS and CSS
  - made some optimizations

- #### v1.2.2

  - fixed uninitialized `startDateBackup` variable bug
  - added browserSync support

- #### v1.2.3

  - fixed event duplication on document click
  - fixed outside triggers closing dropdown
  - fixed target element confusion when different target option is specified
  - added startEmpty option
  - fixed multiple instance closing issues
  - added missing event parameters to hideDropdown method

- #### v1.3.0

  - fixed autoCloseOnSelect on singleDate version / mobile views
  - changed code to make clicking on disabled days select start/end date
  - added some transition delays to make it smoother
  - added keyboard navigation (`enableKeyboard` option) up: previous week down: next week left: previous day right: next day space: select day pageup: previous month pagedown next month shift + pageup: previous year shift + pagedown: next year
  - added easy year switch buttons on year list
  - fixed `startEmpty` cell selected classes
  - added destroy method and some extra tests

- #### v1.3.1

  - fixed missing cloning in isDisabled method
  - buttons now don't submit forms
  - added inline view support on mobile devices
  - startEmpty property clears input on initialization
  - added apply and cancel buttons in dropdown mode

- #### v1.3.2

  - fixed hovering bug after month change when first date is selected
  - added jshint javascript linter to gruntfile
  - some optimizations
  - moved event bubbling in one method

- #### v1.3.3

  - documentation fixes
  - fixed clickable disabled days

- #### v1.3.4

  - removed event bubbling prevention in document.click event
  - configuration objects attached to prototype converted to independent objects
  - added "left" "right" display options ("showOn" option, default "bottom")
  - added auto positioning enable/disable flag ("autoAlign" option, default "true")
  - added position recalculation on window scroll and resize events

- #### v1.3.5

  - fixed css issue about month selector in small calendars
  - fixed locale error on month selector
  - added adjustment for font-size in month selector page

- #### v1.3.6

  - fixed header display bug on startEmpty
  - converted moment instances to unix timestamps on reDrawCells method
  - added first and last hover classes (border radius effect)
  - removed autoprefixer and added postcss plugin for browser compatible CSS
  - fixed visibility issues

- #### v1.3.7

  - Repeating day issue caused by daylight saving time activation fixed.

- #### v1.3.8

  - Added `caleran-not-in-month` class for the days that don't belong to that month
  - Replaced moment's `.startOf("day")` to `middleOfDay()` extension function to minimize DST change bugs.

- #### v1.3.9

  - startDate and endDate setting on plugin intialization didn't work, fixed.
  - fixed mobile inline view resize bug after month changes
  - fixed dropdown closing issues
  - fixed ESC key closing inline calendars bug
  - removed clearing of user value when user inputs a valid date when startEmpty is still active

- #### v1.3.10

  - fixed month selector styling on small calendars on all browsers
  - added numericMonthSwitcher config option to show month numbers instead of month names in month selector

- #### v1.4.0

  - updated jQuery library in demos and readme to v3.1.2
  - updated getDimensions method to more paint and memory friendly version
  - added setStart, setEnd, setMinDate, setMaxDate and setDisplayDate methods
  - added istanbul test code coverage tools
  - added start and end date validation regarding minimum and maximum allowed dates

- #### v1.4.1

  - fixed dropdown positioning on inner scrolling container other than window
  - fixed wrong calendarStart calculation when startOnMonday is set and start of month is sunday

- #### v1.4.2

  - changed header's end month display from full to short.
  - added predefined events to hideDropdown and showDropdown to prevent var undefined exception.
  - updated example about linked date pickers
  - added month name format on monthselector
  - added week numbers on calendars

- #### v1.4.3

  - added vertical range listing feature
  - updated missing parts of documentation
  - added smart positioning on top/bottom dropdowns
  - added selected range indicators
  - massive performance upgrade
  - added arrowOn parameter which moves the arrow to the desired position.
  - improved positioning on viewport edges
  - added center/center display option

- #### v1.4.4

  - added onaftermonthchange and onafteryearchange to month and year selectors
  - added caleran-disabled-range class on mindate/maxdate effective days
  - added day clones instead of real ones as attributes of events
  - added formats when given start and end dates are strings to validateDates function
  - changed mobile view instances to delay input update until apply button is pressed
  - fixed cancel button click bug

- #### v1.4.5

  - fixed mobile button bug on month change
  - fixed autocloseonselect not updating input on mobile

- #### v1.4.6

  - updated linked calendars example in documentation
  - added onBeforeInit, onBeforeDestroy and ondestroy event

## Copyright & Licenses

- Caleran Date Range Picker
  Copyright (c) Taha PAKSU http://www.tahapaksu.com
  All rights reserved.

- Based on jQuery — New Wave JavaScript http://www.jquery.org
  Copyright (c) JS Foundation and other contributors, https://js.foundation/
  Released under jQuery License
  All rights reserved.

- Based on Moment.js http://www.momentjs.com
  Copyright (c) JS Foundation and other contributors
  Moment.js is freely distributable under the terms of the MIT license.
  All rights reserved.

- Includes hammer.js http://hammerjs.github.io
  Copyright (C) 2011-2014 by Jorik Tangelder (Eight Media)
  hammer.js is freely distributable under the terms of the MIT license.
  All rights reserved.