├── .gitignore ├── index.js ├── screenshot.gif ├── .babelrc ├── dist ├── datepicker.min.css.map ├── datepicker.min.css ├── datepicker.min.js └── datepicker.min.js.map ├── src ├── scripts │ ├── util.js │ ├── index.js │ ├── decorators.js │ ├── date.js │ ├── DatePickerRange.js │ ├── Calendar.js │ └── DatePicker.js └── styles │ └── datepicker.css ├── .editorconfig ├── example ├── index.js └── index.html ├── webpack.config.js ├── LICENSE.md ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require("./dist/datepicker"); 2 | -------------------------------------------------------------------------------- /screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evangilo/light-datepicker/HEAD/screenshot.gif -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0"], 3 | "plugins": ["transform-object-rest-spread"] 4 | } 5 | -------------------------------------------------------------------------------- /dist/datepicker.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"datepicker.min.css","sourceRoot":""} -------------------------------------------------------------------------------- /src/scripts/util.js: -------------------------------------------------------------------------------- 1 | export function createNode(name, className, html) { 2 | let node = document.createElement(name); 3 | node.className = className; 4 | node.innerHTML = html; 5 | return node; 6 | } 7 | -------------------------------------------------------------------------------- /src/scripts/index.js: -------------------------------------------------------------------------------- 1 | import { Calendar } from './Calendar'; 2 | import { DatePicker } from './DatePicker'; 3 | import { DatePickerRange } from './DatePickerRange'; 4 | 5 | export { 6 | Calendar, 7 | DatePicker, 8 | DatePickerRange 9 | }; 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | draw_white_space = true 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | const single = new datepicker.DatePicker({ selector: '#datepicker' }); 2 | const range = new datepicker.DatePickerRange({ 3 | language: 'pt-BR', 4 | leftSelector: '#left-datepicker', 5 | rightSelector: '#right-datepicker', 6 | appendTo: '.jumbotron' 7 | }); 8 | 9 | single.calendar.on('clickDate', event => console.log('single:date', event.detail)); 10 | range.leftDatePicker.calendar.on('clickDate', event => console.log('left:date', event.detail)); 11 | range.rightDatePicker.calendar.on('clickDate', event => console.log('right:date', event.detail)); 12 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require("webpack"); 2 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 3 | 4 | module.exports = { 5 | entry: "./src/scripts", 6 | devtool: "source-map", 7 | output: { 8 | path: `${__dirname}/dist`, 9 | filename: "datepicker.min.js", 10 | watch: true, 11 | libraryTarget: "var", 12 | library: 'datepicker' 13 | }, 14 | module: { 15 | loaders: [ 16 | {test: /\.js$/, exclude: /node_modules/, loader: "babel-loader"}, 17 | { test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader") } 18 | ] 19 | }, 20 | plugins: [ 21 | new webpack.optimize.UglifyJsPlugin({minimize: true}), 22 | new ExtractTextPlugin("datepicker.min.css") 23 | ] 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /src/scripts/decorators.js: -------------------------------------------------------------------------------- 1 | import { isSame } from './date'; 2 | 3 | export const todayDecorator = () => ({ 4 | shouldApply: (nodeDate) => isSame(nodeDate, new Date()), 5 | className: 'today' 6 | }); 7 | 8 | export const outMonthDecorator = (cb) => ({ 9 | shouldApply: (nodeDate) => !isSame(nodeDate, cb(), 'year month'), 10 | className: 'out-month' 11 | }); 12 | 13 | export const thisMonthDecorator = (cb) => ({ 14 | shouldApply: (nodeDate) => isSame(nodeDate, cb(), 'year month'), 15 | className: 'enabled' 16 | }); 17 | 18 | export const selectedDecorator = (cb) => ({ 19 | shouldApply: (nodeDate) => isSame(nodeDate, cb()), 20 | className: 'selected' 21 | }); 22 | 23 | export const disabledRangeDecorator = (cb) => ({ 24 | shouldApply: (nodeDate) => nodeDate < cb(), 25 | className: 'disabled' 26 | }); 27 | 28 | export const rangeDecorator = (startCB, endCB) => ({ 29 | shouldApply: (nodeDate) => nodeDate >= startCB() && nodeDate <= endCB(), 30 | className: 'range' 31 | }); 32 | -------------------------------------------------------------------------------- /src/scripts/date.js: -------------------------------------------------------------------------------- 1 | export function nextMonth(date) { 2 | return new Date(date.getFullYear(), date.getMonth() + 1); 3 | } 4 | 5 | export function prevMonth(date) { 6 | return new Date(date.getFullYear(), date.getMonth() - 1); 7 | } 8 | 9 | export function startMonth(date) { 10 | return new Date(date.getFullYear(), date.getMonth(), 1); 11 | } 12 | 13 | export function endMonth(date) { 14 | return new Date(date.getFullYear(), date.getMonth() + 1, 0); 15 | } 16 | 17 | export function datesInMonth(date) { 18 | let length = {length: endMonth(date).getDate()}; 19 | return Array.from(length, (_, day) => new Date(date.getFullYear(), date.getMonth(), day + 1)); 20 | } 21 | 22 | export function isSame(date, other, filter='year month day') { 23 | if (!date || !other) return false; 24 | return (!filter.includes('year') || date.getFullYear() === other.getFullYear()) && 25 | (!filter.includes('month') || date.getMonth() === other.getMonth()) && 26 | (!filter.includes('day') || date.getDate() === other.getDate()) 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Evangilo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "light-datepicker", 3 | "version": "0.1.1", 4 | "description": "Light DatePicker", 5 | "main": "index", 6 | "scripts": { 7 | "start": "webpack-dev-server --inline --hot --content-base ./", 8 | "build": "webpack" 9 | }, 10 | "devDependencies": { 11 | "babel-cli": "^6.11.4", 12 | "babel-core": "^6.11.4", 13 | "babel-loader": "^6.2.4", 14 | "babel-plugin-transform-object-rest-spread": "^6.8.0", 15 | "babel-preset-es2015": "^6.9.0", 16 | "babel-preset-stage-0": "^6.5.0", 17 | "babel-runtime": "^6.11.6", 18 | "css-loader": "^0.23.1", 19 | "extract-text-webpack-plugin": "^1.0.1", 20 | "style-loader": "^0.13.1", 21 | "webpack": "^1.13.2", 22 | "webpack-dev-server": "^1.14.1" 23 | }, 24 | "dependencies": {}, 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/evangilo/light-datepicker.git" 28 | }, 29 | "author": "Evangilo Morais", 30 | "email": "evangilo@gmail.com", 31 | "license": "MIT", 32 | "keywords": [ 33 | "Calendar", 34 | "DatePicker", 35 | "DateRangePicker" 36 | ], 37 | "bugs": { 38 | "url": "https://github.com/evangilo/light-datepicker/issues" 39 | }, 40 | "homepage": "https://github.com/evangilo/light-datepicker#readme" 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Light Datepicker 2 | 3 | > Ultra light and minimalist Datepicker with zero dependencies. 4 | 5 | ## Preview 6 | ![Screenshot](https://raw.githubusercontent.com/evangilo/light-datepicker/master/screenshot.gif) 7 | 8 | 9 | ## Install 10 | ``` 11 | npm install light-datepicker --save 12 | ``` 13 | 14 | ## Basic Usage 15 | 16 | ```HTML 17 | // HTML 18 | 19 | 20 | 21 | ``` 22 | 23 | ```JS 24 | // Javascript 25 | const single = new datepicker.DatePicker({ selector: '#datepicker' }); 26 | 27 | const range = new datepicker.DatePickerRange({ 28 | leftSelector: '#left-datepicker', 29 | rightSelector: '#right-datepicker', 30 | }); 31 | 32 | single.calendar.on('clickDate', event => console.log('single:date', event.detail)); 33 | range.leftDatePicker.calendar.on('clickDate', event => console.log('left:date', event.detail)); 34 | range.rightDatePicker.calendar.on('clickDate', event => console.log('right:date', event.detail)); 35 | ``` 36 | 37 | ## Run Example 38 | ``` 39 | git clone https://github.com/evangilo/light-datepicker.git 40 | 41 | npm install 42 | 43 | npm start 44 | ``` 45 | 46 | Open url in your browser: http://localhost:8080/example/ 47 | 48 | License 49 | Light Datepicker is released under the MIT License. See [LICENSE](https://github.com/evangilo/light-datepicker/blob/master/LICENSE.md) file for details. 50 | 51 | ## Browser Support 52 | 53 | @TODO 54 | -------------------------------------------------------------------------------- /dist/datepicker.min.css: -------------------------------------------------------------------------------- 1 | .datepicker{position:absolute;width:260px;box-shadow:0 0 10px rgba(0,0,0,.4);padding:15px;z-index:9999;background-color:#fff}.datepicker,.datepicker span{box-sizing:content-box}.datepicker .arrow{position:relative;background:#fff}.datepicker .arrow:after{content:"";position:absolute;width:0;height:0;border:10px solid rgba(0,0,0,.4);border-color:#fff #fff transparent transparent;transform:rotate(-45deg);top:-23px;left:15px;box-shadow:3px -3px 3px 0 rgba(0,0,0,.15)}.datepicker .weekdays{width:260px}.datepicker .calendar span,.datepicker .weekdays span{display:inline-block;background-color:#fff;text-align:center;text-transform:capitalize;margin:3px;padding:5px;border:1px solid #fff;width:calc(1 / 7 * 100% - 18px)}.datepicker .weekdays span{padding:0!important}.calendar span.out-month{visibility:hidden}.calendar span.enabled{background-color:#eee;border:1px solid #eee;cursor:pointer}.calendar span.enabled:hover,.calendar span.range{background-color:#fff;border:1px solid #ff690f;color:#ff690f}.calendar span.disabled,.calendar span.disabled:hover{background-color:#fff;color:#ccc;border:1px solid #fff;cursor:default}.calendar span.selected,.calendar span.selected:hover{background-color:#ff690f;color:#fff;font-weight:600}.datepicker .header{display:flex;flex-direction:row;justify-content:space-between;line-height:28px}.datepicker .header .next,.datepicker .header .prev{background-color:transparent;border:none;font-size:1.5em;font-weight:900;padding:0;cursor:pointer;line-height:18px}.datepicker .header .next:hover,.datepicker .header .prev:hover{color:#ff690f;cursor:pointer}.datepicker .header .next.disabled,.datepicker .header .prev.disabled{visibility:hidden} 2 | /*# sourceMappingURL=datepicker.min.css.map*/ -------------------------------------------------------------------------------- /src/scripts/DatePickerRange.js: -------------------------------------------------------------------------------- 1 | import { DatePicker } from './DatePicker'; 2 | import { disabledRangeDecorator, rangeDecorator } from './decorators'; 3 | 4 | export class DatePickerRange { 5 | 6 | constructor(options) { 7 | this.leftDatePicker = new DatePicker({ ...options, ...{ selector: options.leftSelector } }); 8 | this.rightDatePicker = new DatePicker({ ...options, ...{ selector: options.rightSelector } }); 9 | this.leftDatePicker.calendar.on('clickDate', (event) => this.onLeftSelectDate(event.detail)); 10 | this.rightDatePicker.calendar.on('clickDate', (event) => this.onRightSelectDate(event.detail)); 11 | 12 | this.rightDatePicker.parentElement.addEventListener('focus', e => this.leftDatePicker.hide()); 13 | this.leftDatePicker.parentElement.addEventListener('focus', e => this.rightDatePicker.hide()); 14 | 15 | this.setupDecorators(); 16 | } 17 | 18 | onLeftSelectDate(date) { 19 | let leftDate = this.leftDatePicker.options.currentDate; 20 | let rightDate = this.rightDatePicker.options.currentDate; 21 | if (rightDate < leftDate) { 22 | this.rightDatePicker.options.currentMonth = leftDate; 23 | this.rightDatePicker.options.currentDate = leftDate; 24 | this.rightDatePicker.updateInputValue(); 25 | this.rightDatePicker.draw(); 26 | } 27 | this.leftDatePicker.hide(); 28 | this.rightDatePicker.show(); 29 | } 30 | 31 | onRightSelectDate(date) { 32 | this.rightDatePicker.hide(300); 33 | } 34 | 35 | setupDecorators() { 36 | const getStartDate = () => this.leftDatePicker.options.currentDate; 37 | const getEndDate = () => this.rightDatePicker.options.currentDate; 38 | const rangeDec = rangeDecorator(getStartDate, getEndDate); 39 | this.leftDatePicker.calendar.addDecorator(rangeDec); 40 | this.rightDatePicker.calendar.addDecorator(rangeDec); 41 | this.rightDatePicker.calendar.addDecorator(disabledRangeDecorator(() => this.leftDatePicker.options.currentDate)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | DatePicker 5 | 6 | 7 | 8 | 9 |
10 |
11 |

DatePicker

12 | 13 |
14 | 15 |
16 |
17 | 18 |
19 | 20 | 21 | 22 | 23 |
24 |
25 |
26 | 27 |
28 |
29 | 30 |
31 |
32 | 33 | 34 | 35 | 36 |
37 |
38 | 39 | 40 | 41 | 42 |
43 |
44 |
45 |
46 | 47 |
48 |
49 |
50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/scripts/Calendar.js: -------------------------------------------------------------------------------- 1 | import { createNode } from './util'; 2 | import { 3 | nextMonth, 4 | prevMonth, 5 | startMonth, 6 | datesInMonth 7 | } from './date'; 8 | 9 | const MAXIMUM_NUMBER_OF_DAYS = 42; 10 | 11 | export class Calendar { 12 | constructor() { 13 | this.decorators = []; 14 | this.container = createNode('div', 'calendar', null); 15 | this.nodes = new Array(MAXIMUM_NUMBER_OF_DAYS); 16 | this.render(); 17 | } 18 | 19 | render() { 20 | const container = this.container; 21 | const nodes = this.nodes; 22 | const fragment = document.createDocumentFragment(); 23 | // TODO: Evited assign and use immutability 24 | for (let i = 0; i < MAXIMUM_NUMBER_OF_DAYS; i++) { 25 | nodes[i] = this.createDateNode(); 26 | fragment.appendChild(nodes[i]); 27 | } 28 | container.appendChild(fragment); 29 | } 30 | 31 | createDateNode() { 32 | const node = createNode('span', ''); 33 | node.addEventListener('click', (event) => this.emit('clickDate', node)); 34 | node.addEventListener('mouseover', (event) => this.emit('hoverDate', node)); 35 | return node; 36 | } 37 | 38 | on(eventName, callback) { 39 | this.container.addEventListener(eventName, callback); 40 | } 41 | 42 | emit(eventName, node) { 43 | if (!node.classList.contains('disabled')) { 44 | const event = new CustomEvent(eventName, { detail: node.date }); 45 | this.container.dispatchEvent(event); 46 | } 47 | } 48 | 49 | addDecorator(decorator) { 50 | this.decorators.push(decorator); 51 | } 52 | 53 | applyDecorators() { 54 | this.nodes.forEach(node => { 55 | this.decorators.forEach(decorator => { 56 | if (decorator.shouldApply(node.date)) { 57 | node.classList.add(decorator.className); 58 | } else { 59 | node.classList.remove(decorator.className); 60 | } 61 | }); 62 | }); 63 | } 64 | 65 | datesOfCalendar(date) { 66 | const month = datesInMonth(date); 67 | const leftPadding = startMonth(date).getDay() || 7; 68 | const paddingLeftItems = datesInMonth(prevMonth(date)) 69 | .reverse() 70 | .slice(0, leftPadding) 71 | .reverse(); 72 | const paddingRightItems = datesInMonth(nextMonth(date)) 73 | .slice(0, 42 - leftPadding - month.length); 74 | return [...paddingLeftItems, ...month, ...paddingRightItems]; 75 | } 76 | 77 | draw(date) { 78 | const dates = this.datesOfCalendar(date); 79 | // TODO: Evited assign and use immutability 80 | this.nodes.forEach((node, index) => { 81 | node.date = dates[index]; 82 | node.innerText = dates[index].getDate(); 83 | }); 84 | this.applyDecorators(); 85 | return this.container; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/styles/datepicker.css: -------------------------------------------------------------------------------- 1 | .datepicker { 2 | position: absolute; 3 | width: 260px; 4 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); 5 | padding: 15px; 6 | z-index: 9999; 7 | background-color: #fff; 8 | } 9 | 10 | .datepicker, .datepicker span { 11 | -webkit-box-sizing: content-box; 12 | -moz-box-sizing: content-box; 13 | box-sizing: content-box; 14 | } 15 | 16 | .datepicker .arrow { 17 | position: relative; 18 | background: #fff; 19 | } 20 | 21 | .datepicker .arrow:after{ 22 | content: ""; 23 | position: absolute; 24 | width: 0; 25 | height: 0; 26 | border: 10px solid rgba(0, 0, 0, 0.4); 27 | border-color: #ffffff #ffffff transparent transparent; 28 | transform: rotate(-45deg); 29 | top: -23px; 30 | left: 15px; 31 | box-shadow: 3px -3px 3px 0 rgba(0, 0, 0, 0.15); 32 | } 33 | 34 | .datepicker .days { 35 | display: inline; 36 | padding: 0; 37 | } 38 | 39 | .datepicker .weekdays { 40 | width: 260px; 41 | } 42 | 43 | .datepicker .weekdays span, 44 | .datepicker .calendar span { 45 | display: inline-block; 46 | background-color: #ffffff; 47 | text-align: center; 48 | text-transform: capitalize; 49 | margin: 3px; 50 | padding: 5px; 51 | border: 1px solid #ffffff; 52 | width: calc(1 / 7 * 100% - 18px); 53 | } 54 | 55 | .datepicker .header { 56 | display: flex; 57 | align-items: center; 58 | justify-content: space-between; 59 | } 60 | 61 | .datepicker .header .prev { 62 | background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAQAAABKfvVzAAAAOUlEQVR4AWMYxqABCElS/p/hN4MWacpDSFMeSlPlYaQo/0OScnyQYg0IJ4XjcsLI0KJFmpa64Zt3AdTaQlFOlKYFAAAAAElFTkSuQmCC'); 63 | background-position: left center; 64 | } 65 | 66 | .datepicker .header .next { 67 | background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAQAAABKfvVzAAAAOUlEQVR4AWMYxqCRoYEU5boMfxj+k6YlgnQtkXTREkW6lmjcWv7jhQ3kayDspGGrnPLE1wCEwxYAABNmQoikBfhoAAAAAElFTkSuQmCC'); 68 | background-position: right center; 69 | } 70 | 71 | .datepicker .header .prev, 72 | .datepicker .header .next { 73 | width: 30px; 74 | height: 30px; 75 | margin: 2.5px; 76 | background-repeat: no-repeat; 77 | cursor: pointer; 78 | } 79 | 80 | .datepicker .header .prev.disabled, 81 | .datepicker .header .next.disabled { 82 | visibility: hidden; 83 | } 84 | 85 | .calendar span.out-month { 86 | visibility: hidden; 87 | } 88 | 89 | .calendar span.enabled { 90 | background-color: #eee; 91 | border: 1px solid #eee; 92 | cursor: pointer; 93 | } 94 | 95 | .calendar span.range, 96 | .calendar span.enabled:hover { 97 | background-color: #ffffff; 98 | border: 1px solid #ff690f; 99 | color: #ff690f; 100 | } 101 | 102 | .calendar span.disabled, 103 | .calendar span.disabled:hover { 104 | background-color: #ffffff; 105 | color: #cccccc; 106 | border: 1px solid #ffffff; 107 | cursor: default; 108 | } 109 | 110 | .calendar span.selected, 111 | .calendar span.selected:hover { 112 | background-color: #ff690f; 113 | color: #fff; 114 | font-weight: 600; 115 | } 116 | -------------------------------------------------------------------------------- /src/scripts/DatePicker.js: -------------------------------------------------------------------------------- 1 | import '../styles/datepicker.css'; 2 | import { Calendar } from './Calendar'; 3 | import { isSame, prevMonth, nextMonth } from './date'; 4 | import { todayDecorator, outMonthDecorator, thisMonthDecorator, selectedDecorator} from './decorators'; 5 | import { createNode } from './util'; 6 | 7 | const LANGUAGE = window.navigator.language; 8 | const WEEKDAYS = 'sun_mon_tue_wed_thu_fri_sat'.split('_'); 9 | const TEMPLATE = 10 | `
11 |
12 | 13 | 14 | 15 |
16 |
17 |
`; 18 | 19 | const doc = window.document; 20 | 21 | export class DatePicker { 22 | 23 | constructor(options) { 24 | const initalState = { 25 | currentDate: new Date(), 26 | selector: null, 27 | updateInput: true, 28 | appendTo: 'body', 29 | language: LANGUAGE, 30 | weekdays: WEEKDAYS, 31 | template: TEMPLATE, 32 | formatInputDate: date => this.formatInputDate(date), 33 | formatTitleDate: date => this.formatTitleDate(date) 34 | }; 35 | this.options = { ...initalState, ...options }; 36 | this.options.currentMonth = Object.assign(this.options.currentDate); 37 | 38 | this.setupParentElement(); 39 | this.updateInputDate(this.options.currentDate); 40 | this.setupCalendar(); 41 | this.setupDatePicker(); 42 | this.setupOutClick(); 43 | this.draw(); 44 | this.hide(); 45 | } 46 | 47 | setupParentElement() { 48 | this.parentElement = doc.querySelector(this.options.selector); 49 | this.parentElement.addEventListener('focus', event => this.show()); 50 | } 51 | 52 | setupCalendar() { 53 | let options = this.options; 54 | this.calendar = new Calendar(options.weekdays); 55 | this.calendar.addDecorator(todayDecorator()) 56 | this.calendar.addDecorator(outMonthDecorator(() => options.currentMonth)); 57 | this.calendar.addDecorator(thisMonthDecorator(() => options.currentMonth)); 58 | this.calendar.addDecorator(selectedDecorator(() => options.currentDate)); 59 | this.calendar.on('clickDate', event => this.selectDate(event.detail)); 60 | } 61 | 62 | setupDatePicker() { 63 | this.datepicker = createNode('div', 'datepicker', this.options.template); 64 | this.datepicker.querySelector('.days').appendChild(this.calendar.container); 65 | this.datepicker.querySelector('.prev').addEventListener('click', event => this.setMonth(prevMonth(this.options.currentMonth))); 66 | this.datepicker.querySelector('.next').addEventListener('click', event => this.setMonth(nextMonth(this.options.currentMonth))); 67 | this.datepicker.style.display = 'none'; 68 | 69 | let weekdays = this.datepicker.querySelector('.weekdays'); 70 | for (let weekday of this.options.weekdays) { 71 | weekdays.appendChild(createNode('span', 'weekday', weekday)); 72 | } 73 | 74 | doc.querySelector(this.options.appendTo).appendChild(this.datepicker); 75 | } 76 | 77 | setupOutClick() { 78 | doc.addEventListener('click', event => { 79 | const target = event.target; 80 | const isOutsideClick = this.isOpened && 81 | !this.parentElement.isEqualNode(target) && 82 | !this.datepicker.isEqualNode(target) && 83 | !this.datepicker.contains(target); 84 | if (isOutsideClick) { 85 | this.hide(); 86 | } 87 | }, true); 88 | } 89 | 90 | show() { 91 | const parentOffset = this.parentElement.getBoundingClientRect(); 92 | const topOffset = parentOffset.top + 55; 93 | const leftOffset = parentOffset.left; 94 | this.isOpened = true; 95 | this.datepicker.style.cssText = `display: block; top: ${(topOffset)}px; left: ${leftOffset}px;`; 96 | this.calendar.applyDecorators(); 97 | } 98 | 99 | hide(delay=0) { 100 | setTimeout(() => { 101 | this.isOpened = false; 102 | this.datepicker.style.display = 'none'; 103 | }, delay); 104 | } 105 | 106 | selectDate(date) { 107 | let options = this.options; 108 | if (isSame(date, options.currentMonth, 'year month')) { 109 | options.currentDate = date; 110 | this.updateInputDate(date); 111 | this.calendar.applyDecorators(); 112 | } 113 | } 114 | 115 | updateInputDate(date) { 116 | const options = this.options; 117 | if (!options.updateInput) { 118 | return; 119 | } 120 | this.parentElement.value = options.formatInputDate(date); 121 | } 122 | 123 | setMonth(date) { 124 | this.options.currentMonth = date; 125 | this.draw(); 126 | } 127 | 128 | updateTitle() { 129 | const options = this.options; 130 | const title = options.formatTitleDate(options.currentMonth); 131 | this.datepicker.querySelector('.title').innerText = title; 132 | } 133 | 134 | draw() { 135 | this.updateTitle(); 136 | this.calendar.draw(this.options.currentMonth); 137 | } 138 | 139 | formatInputDate(date) { 140 | return date.toLocaleDateString(this.options.language, { 141 | weekday: 'short', 142 | day: 'numeric', 143 | month: 'numeric' 144 | }); 145 | } 146 | 147 | formatTitleDate(date) { 148 | return date.toLocaleDateString(this.options.language, { 149 | month: 'long', 150 | year: 'numeric' 151 | }); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /dist/datepicker.min.js: -------------------------------------------------------------------------------- 1 | var datepicker=function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.DatePickerRange=t.DatePicker=t.Calendar=void 0;var r=n(1),a=n(4),i=n(9);t.Calendar=r.Calendar,t.DatePicker=a.DatePicker,t.DatePickerRange=i.DatePickerRange},function(e,t,n){"use strict";function r(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t\n
\n \n \n \n
';this.datepicker=(0,s.createNode)("div","datepicker",t),this.datepicker.style.display="none",this.datepicker.appendChild(this.calendar.container),this.datepicker.querySelector(".prev").addEventListener("click",function(t){return e.onClickPrevMonth()}),this.datepicker.querySelector(".next").addEventListener("click",function(t){return e.onClickNextMonth()}),l.querySelector(this.options.appendTo).appendChild(this.datepicker),l.addEventListener("click",function(t){var n=t.target,r=e.isOpened&&!e.parentElement.isEqualNode(n)&&!e.datepicker.isEqualNode(n)&&!e.datepicker.contains(n);r&&e.hide()},!0)}},{key:"show",value:function(){var e=this.parentElement.getBoundingClientRect();this.isOpened=!0,this.datepicker.style.cssText="display: block; top: "+(e.top+55)+"px; left: "+e.left+"px;",this.calendar.applyDecorators()}},{key:"hide",value:function(){var e=this,t=arguments.length<=0||void 0===arguments[0]?0:arguments[0];setTimeout(function(){e.isOpened=!1,e.datepicker.style.display="none"},t)}},{key:"selectDate",value:function(e){var t=this.options;(0,c.isSame)(e,t.currentMonth,"year month")&&(t.currentDate=e,this.updateInputValue(),this.calendar.applyDecorators())}},{key:"updateInputValue",value:function(){var e=this.options;if(e.updateInput){var t=e.currentDate.toLocaleDateString(e.language,{weekday:"short",day:"numeric",month:"numeric"});this.parentElement.value=t}}},{key:"onClickPrevMonth",value:function(){var e=this.options;e.currentMonth=(0,c.prevMonth)(e.currentMonth),this.draw()}},{key:"onClickNextMonth",value:function(){var e=this.options;e.currentMonth=(0,c.nextMonth)(e.currentMonth),this.draw()}},{key:"updateTitle",value:function(){var e=this.options,t=e.currentMonth.toLocaleDateString(e.language,{month:"long",year:"numeric"});this.datepicker.querySelector(".title").innerText=t}},{key:"draw",value:function(){this.updateTitle(),this.calendar.draw(this.options.currentMonth)}}]),e}()},function(e,t){},,,,function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0}),t.DatePickerRange=void 0;var a=Object.assign||function(e){for(var t=1;t=e.leftDatePicker.options.currentDate&&t<=e.rightDatePicker.options.currentDate};this.rightDatePicker.calendar.addDecorator(t,"disabled"),this.leftDatePicker.calendar.addDecorator(n,"range"),this.rightDatePicker.calendar.addDecorator(n,"range")}}]),e}()}]); 2 | //# sourceMappingURL=datepicker.min.js.map -------------------------------------------------------------------------------- /dist/datepicker.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///datepicker.min.js","webpack:///webpack/bootstrap 678774a63f25d645055c","webpack:///./src/scripts/index.js","webpack:///./src/scripts/calendar.js","webpack:///./src/scripts/util.js","webpack:///./src/scripts/date.js","webpack:///./src/scripts/datepicker.js","webpack:///./src/scripts/datepickerRange.js"],"names":["datepicker","modules","__webpack_require__","moduleId","installedModules","exports","module","id","loaded","call","m","c","p","Object","defineProperty","value","DatePickerRange","DatePicker","Calendar","undefined","_calendar","_datepicker","_datepickerRange","_toConsumableArray","arr","Array","isArray","i","arr2","length","from","_classCallCheck","instance","Constructor","TypeError","_createClass","defineProperties","target","props","descriptor","enumerable","configurable","writable","key","protoProps","staticProps","prototype","_util","_date","MAXIMUM_NUMBER_OF_DAYS","weekdays","this","decorators","listeners","container","createNode","nodes","render","forEach","weekday","appendChild","fragment","document","createDocumentFragment","createDateNode","_this","node","addEventListener","event","emit","eventName","callback","classList","contains","CustomEvent","detail","date","dispatchEvent","filter","className","push","_this2","some","decorator","add","remove","month","datesInMonth","leftPadding","startMonth","getDay","paddingLeftItems","prevMonth","reverse","slice","paddingRightItems","nextMonth","concat","dates","datesOfCalendar","index","innerText","getDate","applyDecorators","name","html","createElement","innerHTML","Date","getFullYear","getMonth","endMonth","_","day","isSame","other","arguments","includes","_extends","assign","source","hasOwnProperty","WEEKDAYS","window","navigator","language","split","doc","options","currentDate","selector","updateInput","appendTo","currentMonth","setupParentElement","updateInputValue","setupCalendar","setupDatePicker","draw","hide","parentElement","querySelector","show","calendar","addDecorator","on","selectDate","_this3","template","style","display","onClickPrevMonth","onClickNextMonth","isOutsideClick","isOpened","isEqualNode","parentOffset","getBoundingClientRect","cssText","top","left","_this4","delay","setTimeout","toLocaleDateString","title","year","updateTitle","rightDateSelected","leftDatePicker","leftSelector","rightDatePicker","rightSelector","onLeftSelectDate","onRightSelectDate","e","setupDecorators","leftDate","rightDate","rangeDisableRightDecorator","rangeDecorator"],"mappings":"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","file":"datepicker.min.js","sourcesContent":["var datepicker =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.DatePickerRange = exports.DatePicker = exports.Calendar = undefined;\n\t\n\tvar _calendar = __webpack_require__(1);\n\t\n\tvar _datepicker = __webpack_require__(4);\n\t\n\tvar _datepickerRange = __webpack_require__(9);\n\t\n\texports.Calendar = _calendar.Calendar;\n\texports.DatePicker = _datepicker.DatePicker;\n\texports.DatePickerRange = _datepickerRange.DatePickerRange;\n\n/***/ },\n/* 1 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.Calendar = undefined;\n\t\n\tvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\t\n\tvar _util = __webpack_require__(2);\n\t\n\tvar _date = __webpack_require__(3);\n\t\n\tfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\t\n\tfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\t\n\tvar MAXIMUM_NUMBER_OF_DAYS = 42;\n\t\n\tvar Calendar = exports.Calendar = function () {\n\t function Calendar(weekdays) {\n\t _classCallCheck(this, Calendar);\n\t\n\t this.decorators = [];\n\t this.listeners = [];\n\t this.container = (0, _util.createNode)('div', 'calendar', null);\n\t this.nodes = new Array(MAXIMUM_NUMBER_OF_DAYS);\n\t this.weekdays = weekdays;\n\t\n\t this.render();\n\t }\n\t\n\t _createClass(Calendar, [{\n\t key: 'render',\n\t value: function render() {\n\t var container = this.container;\n\t var nodes = this.nodes;\n\t this.weekdays.forEach(function (weekday) {\n\t return container.appendChild((0, _util.createNode)('span', 'weekday', weekday));\n\t });\n\t\n\t var fragment = document.createDocumentFragment();\n\t // TODO: Evited assign and use immutability\n\t for (var i = 0; i < MAXIMUM_NUMBER_OF_DAYS; i++) {\n\t nodes[i] = this.createDateNode();\n\t fragment.appendChild(nodes[i]);\n\t }\n\t container.appendChild(fragment);\n\t }\n\t }, {\n\t key: 'createDateNode',\n\t value: function createDateNode() {\n\t var _this = this;\n\t\n\t var node = (0, _util.createNode)('span', '');\n\t node.addEventListener('click', function (event) {\n\t return _this.emit('clickDate', node);\n\t });\n\t node.addEventListener('mouseover', function (event) {\n\t return _this.emit('hoverDate', node);\n\t });\n\t return node;\n\t }\n\t }, {\n\t key: 'on',\n\t value: function on(eventName, callback) {\n\t this.container.addEventListener(eventName, callback);\n\t }\n\t }, {\n\t key: 'emit',\n\t value: function emit(eventName, node) {\n\t if (!node.classList.contains('disabled')) {\n\t var event = new CustomEvent(eventName, { detail: node.date });\n\t this.container.dispatchEvent(event);\n\t }\n\t }\n\t }, {\n\t key: 'addDecorator',\n\t value: function addDecorator(filter, className) {\n\t this.decorators.push({ filter: filter, className: className });\n\t }\n\t }, {\n\t key: 'applyDecorators',\n\t value: function applyDecorators() {\n\t var _this2 = this;\n\t\n\t this.nodes.forEach(function (node) {\n\t _this2.decorators.some(function (decorator) {\n\t if (decorator.filter(node.date)) {\n\t node.classList.add(decorator.className);\n\t } else {\n\t node.classList.remove(decorator.className);\n\t }\n\t });\n\t });\n\t }\n\t }, {\n\t key: 'datesOfCalendar',\n\t value: function datesOfCalendar(date) {\n\t var month = (0, _date.datesInMonth)(date);\n\t var leftPadding = (0, _date.startMonth)(date).getDay() || 7;\n\t var paddingLeftItems = (0, _date.datesInMonth)((0, _date.prevMonth)(date)).reverse().slice(0, leftPadding).reverse();\n\t var paddingRightItems = (0, _date.datesInMonth)((0, _date.nextMonth)(date)).slice(0, 42 - leftPadding - month.length);\n\t return [].concat(_toConsumableArray(paddingLeftItems), _toConsumableArray(month), _toConsumableArray(paddingRightItems));\n\t }\n\t }, {\n\t key: 'draw',\n\t value: function draw(date) {\n\t var dates = this.datesOfCalendar(date);\n\t // TODO: Evited assign and use immutability\n\t this.nodes.forEach(function (node, index) {\n\t node.date = dates[index];\n\t node.innerText = dates[index].getDate();\n\t });\n\t this.applyDecorators();\n\t return this.container;\n\t }\n\t }]);\n\n\t return Calendar;\n\t}();\n\n/***/ },\n/* 2 */\n/***/ function(module, exports) {\n\n\t\"use strict\";\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.createNode = createNode;\n\tfunction createNode(name, className, html) {\n\t var node = document.createElement(name);\n\t node.className = className;\n\t node.innerHTML = html;\n\t return node;\n\t}\n\n/***/ },\n/* 3 */\n/***/ function(module, exports) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.nextMonth = nextMonth;\n\texports.prevMonth = prevMonth;\n\texports.startMonth = startMonth;\n\texports.endMonth = endMonth;\n\texports.datesInMonth = datesInMonth;\n\texports.isSame = isSame;\n\tfunction nextMonth(date) {\n\t return new Date(date.getFullYear(), date.getMonth() + 1);\n\t}\n\t\n\tfunction prevMonth(date) {\n\t return new Date(date.getFullYear(), date.getMonth() - 1);\n\t}\n\t\n\tfunction startMonth(date) {\n\t return new Date(date.getFullYear(), date.getMonth(), 1);\n\t}\n\t\n\tfunction endMonth(date) {\n\t return new Date(date.getFullYear(), date.getMonth() + 1, 0);\n\t}\n\t\n\tfunction datesInMonth(date) {\n\t var length = { length: endMonth(date).getDate() };\n\t return Array.from(length, function (_, day) {\n\t return new Date(date.getFullYear(), date.getMonth(), day + 1);\n\t });\n\t}\n\t\n\tfunction isSame(date, other) {\n\t var filter = arguments.length <= 2 || arguments[2] === undefined ? 'year month day' : arguments[2];\n\t\n\t if (!date || !other) return false;\n\t return (!filter.includes('year') || date.getFullYear() === other.getFullYear()) && (!filter.includes('month') || date.getMonth() === other.getMonth()) && (!filter.includes('day') || date.getDate() === other.getDate());\n\t}\n\n/***/ },\n/* 4 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.DatePicker = undefined;\n\t\n\tvar _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };\n\t\n\tvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\t\n\t__webpack_require__(5);\n\t\n\tvar _calendar = __webpack_require__(1);\n\t\n\tvar _date = __webpack_require__(3);\n\t\n\tvar _util = __webpack_require__(2);\n\t\n\tfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\t\n\tvar LANGUAGE = window.navigator.language;\n\tvar WEEKDAYS = 'sun_mon_tue_wed_thu_fri_sat'.split('_');\n\t\n\tvar doc = window.document;\n\t\n\tvar DatePicker = exports.DatePicker = function () {\n\t function DatePicker(options) {\n\t _classCallCheck(this, DatePicker);\n\t\n\t this.options = {\n\t currentDate: new Date(),\n\t language: 'en-Us',\n\t selector: null,\n\t updateInput: true,\n\t weekdays: WEEKDAYS,\n\t appendTo: 'body'\n\t };\n\t this.options = _extends({}, this.options, options);\n\t this.options.currentMonth = Object.assign(this.options.currentDate);\n\t\n\t this.setupParentElement();\n\t this.updateInputValue();\n\t this.setupCalendar();\n\t this.setupDatePicker();\n\t this.draw();\n\t this.hide();\n\t }\n\t\n\t _createClass(DatePicker, [{\n\t key: 'setupParentElement',\n\t value: function setupParentElement() {\n\t var _this = this;\n\t\n\t this.parentElement = doc.querySelector(this.options.selector);\n\t this.parentElement.addEventListener('focus', function (event) {\n\t return _this.show();\n\t });\n\t }\n\t }, {\n\t key: 'setupCalendar',\n\t value: function setupCalendar() {\n\t var _this2 = this;\n\t\n\t var options = this.options;\n\t this.calendar = new _calendar.Calendar(options.weekdays);\n\t this.calendar.addDecorator(function (date) {\n\t return !(0, _date.isSame)(date, options.currentMonth, 'year month');\n\t }, 'out-month');\n\t this.calendar.addDecorator(function (date) {\n\t return (0, _date.isSame)(date, options.currentMonth, 'year month');\n\t }, 'enabled');\n\t this.calendar.addDecorator(function (date) {\n\t return (0, _date.isSame)(date, options.currentDate);\n\t }, 'selected');\n\t this.calendar.on('clickDate', function (event) {\n\t return _this2.selectDate(event.detail);\n\t });\n\t }\n\t }, {\n\t key: 'setupDatePicker',\n\t value: function setupDatePicker() {\n\t var _this3 = this;\n\t\n\t var template = '
\\n
\\n \\n \\n \\n
';\n\t this.datepicker = (0, _util.createNode)('div', 'datepicker', template);\n\t this.datepicker.style.display = 'none';\n\t this.datepicker.appendChild(this.calendar.container);\n\t this.datepicker.querySelector('.prev').addEventListener('click', function (event) {\n\t return _this3.onClickPrevMonth();\n\t });\n\t this.datepicker.querySelector('.next').addEventListener('click', function (event) {\n\t return _this3.onClickNextMonth();\n\t });\n\t\n\t doc.querySelector(this.options.appendTo).appendChild(this.datepicker);\n\t doc.addEventListener('click', function (event) {\n\t var target = event.target;\n\t var isOutsideClick = _this3.isOpened && !_this3.parentElement.isEqualNode(target) && !_this3.datepicker.isEqualNode(target) && !_this3.datepicker.contains(target);\n\t if (isOutsideClick) {\n\t _this3.hide();\n\t }\n\t }, true);\n\t }\n\t }, {\n\t key: 'show',\n\t value: function show() {\n\t var parentOffset = this.parentElement.getBoundingClientRect();\n\t this.isOpened = true;\n\t this.datepicker.style.cssText = 'display: block; top: ' + (parentOffset.top + 55) + 'px; left: ' + parentOffset.left + 'px;';\n\t this.calendar.applyDecorators();\n\t }\n\t }, {\n\t key: 'hide',\n\t value: function hide() {\n\t var _this4 = this;\n\t\n\t var delay = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];\n\t\n\t setTimeout(function () {\n\t _this4.isOpened = false;\n\t _this4.datepicker.style.display = 'none';\n\t }, delay);\n\t }\n\t }, {\n\t key: 'selectDate',\n\t value: function selectDate(date) {\n\t var options = this.options;\n\t if ((0, _date.isSame)(date, options.currentMonth, 'year month')) {\n\t options.currentDate = date;\n\t this.updateInputValue();\n\t this.calendar.applyDecorators();\n\t }\n\t }\n\t }, {\n\t key: 'updateInputValue',\n\t value: function updateInputValue() {\n\t var options = this.options;\n\t if (!options.updateInput) {\n\t return;\n\t }\n\t var date = options.currentDate.toLocaleDateString(options.language, {\n\t weekday: 'short',\n\t day: 'numeric',\n\t month: 'numeric'\n\t });\n\t this.parentElement.value = date;\n\t }\n\t }, {\n\t key: 'onClickPrevMonth',\n\t value: function onClickPrevMonth() {\n\t var options = this.options;\n\t options.currentMonth = (0, _date.prevMonth)(options.currentMonth);\n\t this.draw();\n\t }\n\t }, {\n\t key: 'onClickNextMonth',\n\t value: function onClickNextMonth() {\n\t var options = this.options;\n\t options.currentMonth = (0, _date.nextMonth)(options.currentMonth);\n\t this.draw();\n\t }\n\t }, {\n\t key: 'updateTitle',\n\t value: function updateTitle() {\n\t var options = this.options;\n\t var title = options.currentMonth.toLocaleDateString(options.language, {\n\t month: 'long',\n\t year: 'numeric'\n\t });\n\t this.datepicker.querySelector('.title').innerText = title;\n\t }\n\t }, {\n\t key: 'draw',\n\t value: function draw() {\n\t this.updateTitle();\n\t this.calendar.draw(this.options.currentMonth);\n\t }\n\t }]);\n\t\n\t return DatePicker;\n\t}();\n\t\n\t;\n\n/***/ },\n/* 5 */\n/***/ function(module, exports) {\n\n\t// removed by extract-text-webpack-plugin\n\n/***/ },\n/* 6 */,\n/* 7 */,\n/* 8 */,\n/* 9 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.DatePickerRange = undefined;\n\t\n\tvar _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };\n\t\n\tvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\t\n\tvar _datepicker = __webpack_require__(4);\n\t\n\tfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\t\n\tvar DatePickerRange = exports.DatePickerRange = function () {\n\t function DatePickerRange(options) {\n\t var _this = this;\n\t\n\t _classCallCheck(this, DatePickerRange);\n\t\n\t this.rightDateSelected = false;\n\t\n\t this.leftDatePicker = new _datepicker.DatePicker(_extends({}, this.options, { selector: options.leftSelector }));\n\t this.rightDatePicker = new _datepicker.DatePicker(_extends({}, this.options, { selector: options.rightSelector }));\n\t this.leftDatePicker.calendar.on('clickDate', function (event) {\n\t return _this.onLeftSelectDate(event.detail);\n\t });\n\t this.rightDatePicker.calendar.on('clickDate', function (event) {\n\t return _this.onRightSelectDate(event.detail);\n\t });\n\t\n\t this.rightDatePicker.parentElement.addEventListener('focus', function (e) {\n\t return _this.leftDatePicker.hide();\n\t });\n\t this.leftDatePicker.parentElement.addEventListener('focus', function (e) {\n\t return _this.rightDatePicker.hide();\n\t });\n\t\n\t this.setupDecorators();\n\t }\n\t\n\t _createClass(DatePickerRange, [{\n\t key: 'onLeftSelectDate',\n\t value: function onLeftSelectDate(date) {\n\t var leftDate = this.leftDatePicker.options.currentDate;\n\t var rightDate = this.rightDatePicker.options.currentDate;\n\t if (rightDate < leftDate) {\n\t this.rightDatePicker.options.currentMonth = leftDate;\n\t this.rightDatePicker.options.currentDate = leftDate;\n\t this.rightDatePicker.updateInputValue();\n\t this.rightDatePicker.draw();\n\t }\n\t this.leftDatePicker.hide();\n\t this.rightDatePicker.show();\n\t }\n\t }, {\n\t key: 'onRightSelectDate',\n\t value: function onRightSelectDate(date) {\n\t this.rightDatePicker.hide(300);\n\t this.rightDateSelected = true;\n\t }\n\t }, {\n\t key: 'setupDecorators',\n\t value: function setupDecorators() {\n\t var _this2 = this;\n\t\n\t var rangeDisableRightDecorator = function rangeDisableRightDecorator(date) {\n\t return date < _this2.leftDatePicker.options.currentDate;\n\t };\n\t var rangeDecorator = function rangeDecorator(date) {\n\t return date >= _this2.leftDatePicker.options.currentDate && date <= _this2.rightDatePicker.options.currentDate;\n\t };\n\t this.rightDatePicker.calendar.addDecorator(rangeDisableRightDecorator, 'disabled');\n\t this.leftDatePicker.calendar.addDecorator(rangeDecorator, 'range');\n\t this.rightDatePicker.calendar.addDecorator(rangeDecorator, 'range');\n\t }\n\t }]);\n\t\n\t return DatePickerRange;\n\t}();\n\t\n\t;\n\n/***/ }\n/******/ ]);\n\n\n/** WEBPACK FOOTER **\n ** datepicker.min.js\n **/"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n/** WEBPACK FOOTER **\n ** webpack/bootstrap 678774a63f25d645055c\n **/","import { Calendar } from './calendar';\nimport { DatePicker } from './datepicker';\nimport { DatePickerRange } from './datepickerRange';\n\nexport {\n Calendar,\n DatePicker,\n DatePickerRange\n};\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/scripts/index.js\n **/","import { createNode } from './util';\nimport {\n nextMonth,\n prevMonth,\n startMonth,\n datesInMonth,\n isSame\n} from './date';\n\nconst MAXIMUM_NUMBER_OF_DAYS = 42;\n\nexport class Calendar {\n constructor(weekdays) {\n this.decorators = [];\n this.listeners = [];\n this.container = createNode('div', 'calendar', null);\n this.nodes = new Array(MAXIMUM_NUMBER_OF_DAYS);\n this.weekdays = weekdays;\n\n this.render();\n }\n\n render() {\n let container = this.container;\n let nodes = this.nodes;\n this.weekdays.forEach(weekday => container.appendChild(createNode('span', 'weekday', weekday)));\n\n let fragment = document.createDocumentFragment();\n // TODO: Evited assign and use immutability\n for (let i = 0; i < MAXIMUM_NUMBER_OF_DAYS; i++) {\n nodes[i] = this.createDateNode();\n fragment.appendChild(nodes[i]);\n }\n container.appendChild(fragment);\n }\n\n createDateNode() {\n let node = createNode('span', '');\n node.addEventListener('click', (event) => this.emit('clickDate', node));\n node.addEventListener('mouseover', (event) => this.emit('hoverDate', node));\n return node;\n }\n\n on(eventName, callback) {\n this.container.addEventListener(eventName, callback);\n }\n\n emit(eventName, node) {\n if (!node.classList.contains('disabled')) {\n const event = new CustomEvent(eventName, { detail: node.date });\n this.container.dispatchEvent(event);\n }\n }\n\n addDecorator(filter, className) {\n this.decorators.push({filter: filter, className: className});\n }\n\n applyDecorators() {\n this.nodes.forEach(node => {\n this.decorators.some(decorator => {\n if (decorator.filter(node.date)) {\n node.classList.add(decorator.className);\n } else {\n node.classList.remove(decorator.className);\n }\n });\n });\n }\n\n datesOfCalendar(date) {\n let month = datesInMonth(date);\n let leftPadding = startMonth(date).getDay() || 7;\n let paddingLeftItems = datesInMonth(prevMonth(date))\n .reverse()\n .slice(0, leftPadding)\n .reverse();\n let paddingRightItems = datesInMonth(nextMonth(date))\n .slice(0, 42 - leftPadding - month.length);\n return [...paddingLeftItems, ...month, ...paddingRightItems];\n }\n\n draw(date) {\n let dates = this.datesOfCalendar(date);\n // TODO: Evited assign and use immutability\n this.nodes.forEach((node, index) => {\n node.date = dates[index];\n node.innerText = dates[index].getDate();\n });\n this.applyDecorators();\n return this.container;\n }\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/scripts/calendar.js\n **/","export function createNode(name, className, html) {\n let node = document.createElement(name);\n node.className = className;\n node.innerHTML = html;\n return node;\n}\n\n\n/** WEBPACK FOOTER **\n ** ./src/scripts/util.js\n **/","export function nextMonth(date) {\n return new Date(date.getFullYear(), date.getMonth() + 1);\n}\n\nexport function prevMonth(date) {\n return new Date(date.getFullYear(), date.getMonth() - 1);\n}\n\nexport function startMonth(date) {\n return new Date(date.getFullYear(), date.getMonth(), 1);\n}\n\nexport function endMonth(date) {\n return new Date(date.getFullYear(), date.getMonth() + 1, 0);\n}\n\nexport function datesInMonth(date) {\n let length = {length: endMonth(date).getDate()};\n return Array.from(length, (_, day) => new Date(date.getFullYear(), date.getMonth(), day + 1));\n}\n\nexport function isSame(date, other, filter='year month day') {\n if (!date || !other) return false;\n return (!filter.includes('year') || date.getFullYear() === other.getFullYear()) &&\n (!filter.includes('month') || date.getMonth() === other.getMonth()) &&\n (!filter.includes('day') || date.getDate() === other.getDate())\n}\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/scripts/date.js\n **/","import '../styles/datepicker.css';\nimport { Calendar } from './calendar';\nimport { isSame, prevMonth, nextMonth } from './date';\nimport { createNode } from './util';\n\nconst LANGUAGE = window.navigator.language;\nconst WEEKDAYS = 'sun_mon_tue_wed_thu_fri_sat'.split('_');\n\nconst doc = window.document;\n\nexport class DatePicker {\n\n constructor(options) {\n this.options = {\n currentDate: new Date(),\n language: 'en-Us',\n selector: null,\n updateInput: true,\n weekdays: WEEKDAYS,\n appendTo: 'body'\n };\n this.options = { ...this.options, ...options };\n this.options.currentMonth = Object.assign(this.options.currentDate);\n\n this.setupParentElement();\n this.updateInputValue();\n this.setupCalendar();\n this.setupDatePicker();\n this.draw();\n this.hide();\n }\n\n setupParentElement() {\n this.parentElement = doc.querySelector(this.options.selector);\n this.parentElement.addEventListener('focus', event => this.show());\n }\n\n setupCalendar() {\n let options = this.options;\n this.calendar = new Calendar(options.weekdays);\n this.calendar.addDecorator(date => !isSame(date, options.currentMonth, 'year month'), 'out-month');\n this.calendar.addDecorator(date => isSame(date, options.currentMonth, 'year month'), 'enabled');\n this.calendar.addDecorator(date => isSame(date, options.currentDate), 'selected');\n this.calendar.on('clickDate', event => this.selectDate(event.detail));\n }\n\n setupDatePicker() {\n let template = `
\n
\n \n \n \n
`\n this.datepicker = createNode('div', 'datepicker', template);\n this.datepicker.style.display = 'none';\n this.datepicker.appendChild(this.calendar.container);\n this.datepicker.querySelector('.prev').addEventListener('click', event => this.onClickPrevMonth());\n this.datepicker.querySelector('.next').addEventListener('click', event => this.onClickNextMonth());\n\n doc.querySelector(this.options.appendTo).appendChild(this.datepicker);\n doc.addEventListener('click', event => {\n let target = event.target;\n let isOutsideClick = this.isOpened &&\n !this.parentElement.isEqualNode(target) &&\n !this.datepicker.isEqualNode(target) &&\n !this.datepicker.contains(target);\n if (isOutsideClick) {\n this.hide();\n }\n }, true);\n }\n\n show() {\n let parentOffset = this.parentElement.getBoundingClientRect();\n this.isOpened = true;\n this.datepicker.style.cssText = `display: block; top: ${(parentOffset.top + 55)}px; left: ${parentOffset.left}px;`;\n this.calendar.applyDecorators();\n }\n\n hide(delay=0) {\n setTimeout(() => {\n this.isOpened = false;\n this.datepicker.style.display = 'none';\n }, delay);\n }\n\n selectDate(date) {\n let options = this.options;\n if (isSame(date, options.currentMonth, 'year month')) {\n options.currentDate = date;\n this.updateInputValue();\n this.calendar.applyDecorators();\n }\n }\n\n updateInputValue() {\n let options = this.options;\n if (!options.updateInput) {\n return;\n }\n let date = options\n .currentDate\n .toLocaleDateString(options.language, {\n weekday: 'short',\n day: 'numeric',\n month: 'numeric'\n });\n this.parentElement.value = date;\n }\n\n onClickPrevMonth() {\n let options = this.options;\n options.currentMonth = prevMonth(options.currentMonth);\n this.draw();\n }\n\n onClickNextMonth() {\n let options = this.options;\n options.currentMonth = nextMonth(options.currentMonth);\n this.draw();\n }\n\n updateTitle() {\n let options = this.options;\n let title = options\n .currentMonth\n .toLocaleDateString(options.language, {\n month : 'long',\n year : 'numeric'\n });\n this.datepicker.querySelector('.title').innerText = title;\n }\n\n draw() {\n this.updateTitle();\n this.calendar.draw(this.options.currentMonth);\n }\n};\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/scripts/datepicker.js\n **/","import { DatePicker } from './datepicker';\n\nexport class DatePickerRange {\n\n constructor(options) {\n this.rightDateSelected = false;\n\n this.leftDatePicker = new DatePicker({ ...this.options, ...{ selector: options.leftSelector } });\n this.rightDatePicker = new DatePicker({ ...this.options, ...{ selector: options.rightSelector } });\n this.leftDatePicker.calendar.on('clickDate', (event) => this.onLeftSelectDate(event.detail));\n this.rightDatePicker.calendar.on('clickDate', (event) => this.onRightSelectDate(event.detail));\n\n this.rightDatePicker.parentElement.addEventListener('focus', e => this.leftDatePicker.hide());\n this.leftDatePicker.parentElement.addEventListener('focus', e => this.rightDatePicker.hide());\n\n this.setupDecorators();\n }\n\n onLeftSelectDate(date) {\n let leftDate = this.leftDatePicker.options.currentDate;\n let rightDate = this.rightDatePicker.options.currentDate;\n if (rightDate < leftDate) {\n this.rightDatePicker.options.currentMonth = leftDate;\n this.rightDatePicker.options.currentDate = leftDate;\n this.rightDatePicker.updateInputValue();\n this.rightDatePicker.draw();\n }\n this.leftDatePicker.hide();\n this.rightDatePicker.show();\n }\n\n onRightSelectDate(date) {\n this.rightDatePicker.hide(300);\n this.rightDateSelected = true;\n }\n\n setupDecorators() {\n let rangeDisableRightDecorator = (date) => date < this.leftDatePicker.options.currentDate;\n let rangeDecorator = (date) => date >= this.leftDatePicker.options.currentDate &&\n date <= this.rightDatePicker.options.currentDate;\n this.rightDatePicker.calendar.addDecorator(rangeDisableRightDecorator, 'disabled');\n this.leftDatePicker.calendar.addDecorator(rangeDecorator, 'range');\n this.rightDatePicker.calendar.addDecorator(rangeDecorator, 'range');\n }\n};\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/scripts/datepickerRange.js\n **/"],"sourceRoot":""} --------------------------------------------------------------------------------