├── .babelrc ├── .eslintrc.json ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENCE.md ├── README.md ├── bower.json ├── demo ├── date.png ├── index.html └── time.png ├── dist ├── material-datetime-picker.css ├── material-datetime-picker.js ├── material-datetime-picker.js.map ├── material-datetime-picker.mjs └── material-datetime-picker.mjs.map ├── lib ├── js │ ├── __tests__ │ │ ├── helpers │ │ │ ├── dom-polyfills.js │ │ │ ├── empty-module.js │ │ │ └── open-picker.js │ │ └── index-test.js │ ├── events.js │ └── index.js ├── scss │ └── material-datetime-picker.scss └── template │ ├── container.template.js │ ├── datepicker.template.js │ └── scrim.template.js ├── package.json ├── rollup.config.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "development": { 4 | "presets": [["es2015", { "modules": false }]] 5 | }, 6 | "test": { 7 | "plugins": ["transform-async-to-generator", "transform-es2015-modules-commonjs"] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "airbnb-base", 3 | "root": true, 4 | "env": { 5 | "browser": true 6 | }, 7 | "rules": { 8 | "comma-dangle": [2, "never"], 9 | "no-console": 0, 10 | "func-names": 0, 11 | "no-use-before-define": 0, 12 | "no-underscore-dangle": 0 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | bower_components 3 | node_modules 4 | .sass-cache 5 | .vscode 6 | /coverage 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "7" 4 | - "6" 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Contributions are always welcome! 4 | 5 | If you're interested in contributing but you're not sure what to work on, take a look at our [open issues](https://github.com/ripjar/material-datetime-picker/issues). If you have an idea already, we accept [Pull Requests](https://help.github.com/articles/about-pull-requests/). If it's a big change, please open an issue first so we can talk it through. 6 | 7 | ## Getting started 8 | 9 | If you're new to open source, welcome! We would love to help you get started. Here's a quick guide: 10 | 11 | * Decide what to work on, or find an [issue](https://github.com/ripjar/material-datetime-picker/issues) that you're interested in. 12 | * Fork this project. That creates your own copy of the code so can make changes without affecting the main project. 13 | * Clone your fork! That gets the code onto your local computer. You can do that on the command line: 14 | 15 | ``` 16 | git clone https://github.com/YOUR_USERNAME/material-datetime-picker.git 17 | ``` 18 | 19 | * Create a branch to work on. This is a kind of seperate working area for this particular contribution: 20 | 21 | ``` 22 | git checkout -b your-branch-name 23 | ``` 24 | 25 | * Write your code, documentation or whatever you are contributing! 26 | * Commit your code to your local repository: 27 | 28 | ``` 29 | git commit -a -m "Write a short summary of your changes here!" 30 | ``` 31 | 32 | * Push your commited changes to your fork: 33 | 34 | ``` 35 | git push origin your-branch-name 36 | ``` 37 | 38 | * Open a Pull Request on the [main repo](https://github.com/ripjar/material-datetime-picker). That's when we get to see your code. Add a descriptive title and a summary of the changes you've made. 39 | 40 | * We'll review your code and go through any changes that we'd like you to make. Please don't worry about this - it's a totally normal part of most software projects, and it's common for changes to be requested. This isn't a slight on you or your code - it's a way of keeping the project's quality high, and hopefully for you to learn something! 41 | 42 | * Make any fixes that we've asked for, and repeat steps 6 - 9. This might happen a few times. 43 | 44 | * When we're both happy with your pull request, we'll merge it. Congratulations! 45 | 46 | 47 | ## In short 48 | If you've done this kind of thing before: 49 | 50 | * Please be kind and respectful at all times. Treat your fellow contributors with empathy. If your contribution is excellent but your attitude isn't, we're not interested. 51 | * Please make pull requests from a feature branch 52 | * Lint with `eslint`. You can `npm run lint`. 53 | * Follow the existing project style (we use https://github.com/airbnb/javascript) 54 | * Use [BEM](http://getbem.com/introduction/) for CSS 55 | * You don't need to `npm run build`. We'll do that before cutting a release. 56 | 57 | ## Where can I get help? 58 | 59 | Right now the best way to get help is to [open an issue](https://github.com/ripjar/material-datetime-picker/issues), or ask me on Twitter [@jwhitfieldseed](https://twitter.com/jwhitfieldseeds 60 | ). -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | === 3 | 4 | **Copyright (c) 2015 Ripjar** 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Material Datetime Picker 2 | 3 | A Material Design date/time picker modal, built for the web. Works well with Materialize, or standalone. 4 | 5 | [https://ripjar.github.io/material-datetime-picker/](https://ripjar.github.io/material-datetime-picker/) 6 | 7 | [![Status][status]](https://travis-ci.org/ripjar/material-datetime-picker) 8 | [![Package][npm]](https://www.npmjs.com/package/material-datetime-picker) 9 | 10 | ![Time][date] ![Time][time] 11 | 12 | ## Installation 13 | 14 | ``` 15 | npm install material-datetime-picker 16 | ``` 17 | 18 | #### Dependencies 19 | 20 | The picker depends on Google's Material Design icons (packaged with Materialize), or included in the `head` of the document; 21 | 22 | ```html 23 | 24 | ``` 25 | 26 | --- 27 | 28 | For best results also include Google's Material Font `Roboto`; 29 | 30 | ```html 31 | 32 | ``` 33 | 34 | --- 35 | 36 | If you want to use this project as a standalone ` 41 | 42 | 43 | ``` 44 | 45 | ## Usage 46 | 47 | ### Manual (recommended) 48 | 49 | The picker can be instantiated and interacted with manally; 50 | 51 | ```javascript 52 | import MaterialDateTimePicker from 'material-datetime-picker'; 53 | 54 | const picker = new MaterialDateTimePicker() 55 | .on('submit', (val) => console.log(`data: ${val}`)) 56 | .on('open', () => console.log('opened')) 57 | .on('close', () => console.log('closed')); 58 | 59 | document.querySelector('.c-datepicker-btn') 60 | .on('click', () => picker.open()); 61 | ``` 62 | 63 | --- 64 | 65 | ### As form input 66 | 67 | The picker is decoupled from any single form element for simplicity. However, it should be simple to link the picker to a form input or button. For instance, given the input element ``, the following could be written; 68 | 69 | ```javascript 70 | import MaterialDateTimePicker from 'material-datetime-picker'; 71 | 72 | const input = document.querySelector('.c-datepicker-input'); 73 | const picker = new MaterialDateTimePicker() 74 | .on('submit', (val) => { 75 | input.value = val.format("DD/MM/YYYY"); 76 | }); 77 | 78 | input.addEventListener('focus', () => picker.open()); 79 | ``` 80 | 81 | ## Options 82 | 83 | All options are optional, including the `el`. 84 | 85 | ```javascript 86 | { 87 | // DOM Element to attach the datepicker. This element will receive 88 | // events when the data changes. If an input element, will be 89 | // populated with formatted date and time chosen. 90 | // `el` must be a DOM Element object. Selectpr strings or wrappers 91 | // like a jQuery selection are not supported. 92 | el: document.querySelector('.c-datepicker-btn'), 93 | // if `el` is set, the format used to display the datetime in the input, 94 | format: 'DD/MM/YY', 95 | // the default value of the picker 96 | default: moment(), 97 | // the container to append the picker. If you change this, you need to make 98 | // sure your element has a z-index > 0 so that it displays in front of the scrim. 99 | container: document.body, 100 | // cosmetic classes that can be overriden 101 | // mostly used for styling the calendar 102 | styles: { 103 | scrim: 'c-scrim', 104 | back: 'c-datepicker__back', 105 | container: 'c-datepicker__calendar', 106 | date: 'c-datepicker__date', 107 | dayBody: 'c-datepicker__days-body', 108 | dayBodyElem: 'c-datepicker__day-body', 109 | dayConcealed: 'c-datepicker__day--concealed', 110 | dayDisabled: 'c-datepicker__day--disabled', 111 | dayHead: 'c-datepicker__days-head', 112 | dayHeadElem: 'c-datepicker__day-head', 113 | dayRow: 'c-datepicker__days-row', 114 | dayTable: 'c-datepicker__days', 115 | month: 'c-datepicker__month', 116 | next: 'c-datepicker__next', 117 | positioned: 'c-datepicker--fixed', 118 | selectedDay: 'c-datepicker__day--selected', 119 | selectedTime: 'c-datepicker__time--selected', 120 | time: 'c-datepicker__time', 121 | timeList: 'c-datepicker__time-list', 122 | timeOption: 'c-datepicker__time-option', 123 | clockNum: 'c-datepicker__clock__num' 124 | }, 125 | // date range to allow (see rome validator factories) 126 | dateValidator: null 127 | } 128 | ``` 129 | 130 | ## License 131 | 132 | MIT 133 | 134 | 135 | [date]: https://github.com/ripjar/material-datepicker/raw/master/demo/date.png "Date select image" 136 | [time]: https://github.com/ripjar/material-datepicker/raw/master/demo/time.png "Time select image" 137 | [status]: https://api.travis-ci.org/ripjar/material-datetime-picker.svg "Build Status" 138 | [npm]: https://img.shields.io/npm/v/material-datetime-picker.svg "Package" 139 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "material-datetime-picker", 3 | "description": "A Vanilla JS Material Design date/time picker component", 4 | "main": "dist/material-datetime-picker.js", 5 | "authors": [ 6 | "Joe Whitfield-Seed " 7 | ], 8 | "license": "MIT", 9 | "homepage": "https://github.com/ripjar/material-datetime-picker", 10 | "ignore": [ 11 | "**/.*", 12 | "node_modules", 13 | "bower_components", 14 | "test", 15 | "tests" 16 | ], 17 | "dependencies": { 18 | "moment": "2.10.6", 19 | "rome": "2.1.22" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /demo/date.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ripjar/material-datetime-picker/476b08bd6b629828c6a5f9909d94d8d7a4e73f0d/demo/date.png -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 59 | 60 | 61 | 62 | 63 | Open date picker 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /demo/time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ripjar/material-datetime-picker/476b08bd6b629828c6a5f9909d94d8d7a4e73f0d/demo/time.png -------------------------------------------------------------------------------- /dist/material-datetime-picker.css: -------------------------------------------------------------------------------- 1 | .c-scrim { 2 | position: fixed; 3 | left: 0; 4 | right: 0; 5 | top: 0; 6 | bottom: 0; 7 | background-color: rgba(0, 0, 0, 0.541176); 8 | opacity: 0; 9 | transition: 200ms ease opacity; 10 | will-change: opacity; } 11 | .c-scrim--shown { 12 | opacity: 1; } 13 | 14 | .c-datepicker { 15 | min-height: 610px; 16 | position: fixed; 17 | left: 50%; 18 | top: 45%; 19 | transform: translate(-50%, -50%); 20 | background: white; 21 | border: 0; 22 | width: 300px; 23 | text-align: center; 24 | -webkit-tap-highlight-color: transparent; 25 | box-shadow: 0 14px 45px rgba(0, 0, 0, 0.25), 0 10px 18px rgba(0, 0, 0, 0.22); 26 | border-radius: 2px; 27 | opacity: 0; 28 | will-change: opacity; 29 | transition: 200ms ease-in-out opacity, 200ms ease-in-out top; } 30 | .c-datepicker--open { 31 | opacity: 1; 32 | top: 50%; } 33 | 34 | .c-datepicker__header { 35 | position: relative; } 36 | 37 | .c-datepicker__header-day { 38 | height: 32px; 39 | background: #0097a7; 40 | color: white; 41 | line-height: 32px; 42 | font-size: 12px; 43 | font-weight: 200; 44 | letter-spacing: 0.3px; } 45 | 46 | .c-datepicker__header::after { 47 | content: ""; 48 | display: table; 49 | clear: both; } 50 | 51 | .c-datepicker__header-date { 52 | background: #00bcd4; 53 | height: 150px; 54 | padding: 16px 0; } 55 | 56 | .rd-month-label { 57 | height: 56px; 58 | line-height: 56px; 59 | font-size: 14px; 60 | font-weight: 800; } 61 | 62 | .c-datepicker__back, .c-datepicker__next, .c-datepicker__toggle { 63 | position: absolute; 64 | border: 0; 65 | background: white; 66 | font-family: 'Material Icons'; 67 | text-rendering: optimizeLegibility; 68 | font-feature-settings: "liga" 1; 69 | font-style: normal; 70 | text-transform: none; 71 | line-height: 1; 72 | font-size: 24px; 73 | width: 56px; 74 | height: 56px; 75 | display: inline-block; 76 | overflow: hidden; 77 | -webkit-font-smoothing: antialiased; 78 | cursor: pointer; } 79 | .c-datepicker__back:focus, .c-datepicker__next:focus, .c-datepicker__toggle:focus { 80 | outline: 0; } 81 | 82 | .c-datepicker__back { 83 | left: 0; } 84 | 85 | .c-datepicker__next { 86 | right: 0; } 87 | 88 | .c-datepicker__back:before { 89 | content: 'chevron_left'; } 90 | 91 | .c-datepicker__next:after { 92 | content: 'chevron_right'; } 93 | 94 | .c-datepicker--show-time:after { 95 | content: 'access_time'; 96 | color: white; 97 | visibility: visible; } 98 | 99 | .c-datepicker--show-calendar:after { 100 | content: 'grid_on'; 101 | color: white; 102 | visibility: visible; } 103 | 104 | .c-datepicker__header-date span { 105 | display: block; 106 | color: white; 107 | margin: 0; 108 | transition: opacity 100ms ease-in-out; } 109 | 110 | .c-datepicker__header-date__month { 111 | cursor: pointer; 112 | font-size: 24px; 113 | opacity: 0.6; } 114 | 115 | .c-datepicker__header-date__day { 116 | cursor: pointer; 117 | font-size: 64px; 118 | opacity: 0.6; } 119 | 120 | .c-datepicker__header-date__time { 121 | font-size: 25px; 122 | opacity: 0.6; } 123 | .c-datepicker__header-date__time > span { 124 | display: inline-block; } 125 | 126 | .c-datepicker__header-date__hours, .c-datepicker__header-date__minutes { 127 | cursor: pointer; } 128 | 129 | .c-datepicker--show-time.is-selected ~ .c-datepicker__header .c-datepicker__header-date__time { 130 | opacity: 1; } 131 | .c-datepicker--show-time.is-selected ~ .c-datepicker__header .c-datepicker__header-date__time .c-datepicker__header-date__hours, .c-datepicker--show-time.is-selected ~ .c-datepicker__header .c-datepicker__header-date__time .c-datepicker__header-date__minutes { 132 | opacity: .6; } 133 | .c-datepicker--show-time.is-selected ~ .c-datepicker__header .c-datepicker__header-date__time .c-datepicker__header-date__hours.active, .c-datepicker--show-time.is-selected ~ .c-datepicker__header .c-datepicker__header-date__time .c-datepicker__header-date__minutes.active { 134 | opacity: 1; } 135 | 136 | .c-datepicker--show-calendar.is-selected ~ .c-datepicker__header .c-datepicker__header-date__month, .c-datepicker--show-calendar.is-selected ~ .c-datepicker__header .c-datepicker__header-date__day { 137 | opacity: 1; } 138 | 139 | .modal-btns { 140 | padding: 20px; 141 | position: absolute; 142 | bottom: 0; 143 | right: 0; } 144 | 145 | .c-datepicker__day-body { 146 | font-size: 12px; 147 | color: rgba(0, 0, 0, 0.8); 148 | width: 36px; 149 | height: 36px; 150 | cursor: pointer; 151 | position: relative; } 152 | .c-datepicker__day-body:hover { 153 | /* color: white; */ } 154 | 155 | .c-datepicker__day--selected::after { 156 | content: ""; 157 | position: absolute; 158 | left: 50%; 159 | top: 50%; 160 | width: 35px; 161 | height: 35px; 162 | border-radius: 50%; 163 | transform: translate(-50%, -50%); 164 | background: rgba(0, 0, 0, 0.05); } 165 | 166 | .c-datepicker__day-head { 167 | color: rgba(0, 0, 0, 0.54); 168 | font-size: 12px; 169 | height: 36px; } 170 | 171 | .c-datepicker__day-head, c-datepicker__day-body { 172 | -webkit-tap-highlight-color: transparent; } 173 | 174 | .modal-btns { 175 | float: right; } 176 | 177 | .c-btn { 178 | display: inline-block; 179 | min-width: 56px; 180 | cursor: pointer; } 181 | 182 | .rd-day-prev-month { 183 | opacity: 0.1; 184 | pointer-events: none; } 185 | 186 | .rd-day-next-month { 187 | opacity: 0.1; 188 | pointer-events: none; } 189 | 190 | .c-datepicker__calendar { 191 | height: 300px; } 192 | 193 | .c-datepicker__date { 194 | position: absolute; 195 | left: 0; 196 | right: 0; } 197 | 198 | .c-datepicker__days { 199 | margin: 10px 20px; } 200 | 201 | .c-datepicker__header-toggle { 202 | position: absolute; 203 | top: 50%; 204 | color: white; 205 | cursor: pointer; } 206 | .c-datepicker__header-toggle i { 207 | font-size: 26px; } 208 | 209 | .c-datepicker__header-toggle--left { 210 | left: 20px; } 211 | 212 | .c-datepicker__header-toggle--right { 213 | right: 20px; } 214 | 215 | .c-datepicker__header-toggle--inactive { 216 | opacity: 0.2; } 217 | 218 | .c-datepicker__toggle { 219 | top: 170px; 220 | width: 36px; 221 | height: 30px; 222 | visibility: hidden; 223 | opacity: 0.5; 224 | z-index: 1; 225 | transition: opacity 200ms ease-in-out; } 226 | 227 | .c-datepicker__toggle--right { 228 | right: 10px; } 229 | 230 | .c-datepicker__toggle--left { 231 | left: 10px; } 232 | 233 | .c-datepicker__toggle.is-selected { 234 | opacity: 1; } 235 | 236 | .c-datepicker--show-time.is-selected ~ .c-datepicker__calendar { 237 | display: none; } 238 | 239 | .c-datepicker--show-calendar.is-selected ~ .c-datepicker__clock { 240 | display: none; } 241 | 242 | .c-datepicker__clock { 243 | position: relative; 244 | /* [1] */ 245 | width: 200px; 246 | height: 200px; 247 | padding: 0; 248 | border-radius: 50%; 249 | list-style: none; 250 | /* [2] */ 251 | font-size: 14px; 252 | line-height: 50px; 253 | padding: 160px 0 20px 0; 254 | margin: 0 auto; } 255 | .c-datepicker__clock .c-datepicker__clock__num { 256 | display: block; 257 | position: absolute; 258 | top: 50%; 259 | left: 50%; 260 | width: 50px; 261 | height: 50px; 262 | margin: -25px; 263 | z-index: 98; } 264 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(1) { 265 | transform: rotate(0deg) translate(100px) rotate(-0deg); } 266 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(1).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands { 267 | transform: translate(-50%, -50%) rotate(270deg); } 268 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(1).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 269 | opacity: 1; 270 | background: #00bcd4; } 271 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(1):hover ~ .c-datepicker__clock-hands { 272 | transform: translate(-50%, -50%) rotate(270deg); } 273 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(1):hover ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 274 | opacity: 1; 275 | background: #00bcd4; } 276 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(2) { 277 | transform: rotate(30deg) translate(100px) rotate(-30deg); } 278 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(2).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands { 279 | transform: translate(-50%, -50%) rotate(300deg); } 280 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(2).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 281 | opacity: 1; 282 | background: #00bcd4; } 283 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(2):hover ~ .c-datepicker__clock-hands { 284 | transform: translate(-50%, -50%) rotate(300deg); } 285 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(2):hover ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 286 | opacity: 1; 287 | background: #00bcd4; } 288 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(3) { 289 | transform: rotate(60deg) translate(100px) rotate(-60deg); } 290 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(3).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands { 291 | transform: translate(-50%, -50%) rotate(330deg); } 292 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(3).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 293 | opacity: 1; 294 | background: #00bcd4; } 295 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(3):hover ~ .c-datepicker__clock-hands { 296 | transform: translate(-50%, -50%) rotate(330deg); } 297 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(3):hover ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 298 | opacity: 1; 299 | background: #00bcd4; } 300 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(4) { 301 | transform: rotate(90deg) translate(100px) rotate(-90deg); } 302 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(4).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands { 303 | transform: translate(-50%, -50%) rotate(360deg); } 304 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(4).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 305 | opacity: 1; 306 | background: #00bcd4; } 307 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(4):hover ~ .c-datepicker__clock-hands { 308 | transform: translate(-50%, -50%) rotate(360deg); } 309 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(4):hover ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 310 | opacity: 1; 311 | background: #00bcd4; } 312 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(5) { 313 | transform: rotate(120deg) translate(100px) rotate(-120deg); } 314 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(5).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands { 315 | transform: translate(-50%, -50%) rotate(390deg); } 316 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(5).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 317 | opacity: 1; 318 | background: #00bcd4; } 319 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(5):hover ~ .c-datepicker__clock-hands { 320 | transform: translate(-50%, -50%) rotate(390deg); } 321 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(5):hover ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 322 | opacity: 1; 323 | background: #00bcd4; } 324 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(6) { 325 | transform: rotate(150deg) translate(100px) rotate(-150deg); } 326 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(6).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands { 327 | transform: translate(-50%, -50%) rotate(420deg); } 328 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(6).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 329 | opacity: 1; 330 | background: #00bcd4; } 331 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(6):hover ~ .c-datepicker__clock-hands { 332 | transform: translate(-50%, -50%) rotate(420deg); } 333 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(6):hover ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 334 | opacity: 1; 335 | background: #00bcd4; } 336 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(7) { 337 | transform: rotate(180deg) translate(100px) rotate(-180deg); } 338 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(7).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands { 339 | transform: translate(-50%, -50%) rotate(450deg); } 340 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(7).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 341 | opacity: 1; 342 | background: #00bcd4; } 343 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(7):hover ~ .c-datepicker__clock-hands { 344 | transform: translate(-50%, -50%) rotate(450deg); } 345 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(7):hover ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 346 | opacity: 1; 347 | background: #00bcd4; } 348 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(8) { 349 | transform: rotate(210deg) translate(100px) rotate(-210deg); } 350 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(8).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands { 351 | transform: translate(-50%, -50%) rotate(480deg); } 352 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(8).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 353 | opacity: 1; 354 | background: #00bcd4; } 355 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(8):hover ~ .c-datepicker__clock-hands { 356 | transform: translate(-50%, -50%) rotate(480deg); } 357 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(8):hover ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 358 | opacity: 1; 359 | background: #00bcd4; } 360 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(9) { 361 | transform: rotate(240deg) translate(100px) rotate(-240deg); } 362 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(9).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands { 363 | transform: translate(-50%, -50%) rotate(510deg); } 364 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(9).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 365 | opacity: 1; 366 | background: #00bcd4; } 367 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(9):hover ~ .c-datepicker__clock-hands { 368 | transform: translate(-50%, -50%) rotate(510deg); } 369 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(9):hover ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 370 | opacity: 1; 371 | background: #00bcd4; } 372 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(10) { 373 | transform: rotate(270deg) translate(100px) rotate(-270deg); } 374 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(10).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands { 375 | transform: translate(-50%, -50%) rotate(540deg); } 376 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(10).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 377 | opacity: 1; 378 | background: #00bcd4; } 379 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(10):hover ~ .c-datepicker__clock-hands { 380 | transform: translate(-50%, -50%) rotate(540deg); } 381 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(10):hover ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 382 | opacity: 1; 383 | background: #00bcd4; } 384 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(11) { 385 | transform: rotate(300deg) translate(100px) rotate(-300deg); } 386 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(11).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands { 387 | transform: translate(-50%, -50%) rotate(570deg); } 388 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(11).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 389 | opacity: 1; 390 | background: #00bcd4; } 391 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(11):hover ~ .c-datepicker__clock-hands { 392 | transform: translate(-50%, -50%) rotate(570deg); } 393 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(11):hover ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 394 | opacity: 1; 395 | background: #00bcd4; } 396 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(12) { 397 | transform: rotate(330deg) translate(100px) rotate(-330deg); } 398 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(12).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands { 399 | transform: translate(-50%, -50%) rotate(600deg); } 400 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(12).c-datepicker__clock__num--active:not(.hide-hand) ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 401 | opacity: 1; 402 | background: #00bcd4; } 403 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(12):hover ~ .c-datepicker__clock-hands { 404 | transform: translate(-50%, -50%) rotate(600deg); } 405 | .c-datepicker__clock .c-datepicker__clock__num:nth-of-type(12):hover ~ .c-datepicker__clock-hands .c-datepicker__hour-hand { 406 | opacity: 1; 407 | background: #00bcd4; } 408 | .c-datepicker__clock::before { 409 | content: ""; 410 | position: absolute; 411 | top: 70px; 412 | left: -20px; 413 | width: 240px; 414 | height: 240px; 415 | background: rgba(0, 0, 0, 0.05); 416 | border-radius: 50%; } 417 | 418 | .u-hover-ball-effect, .c-datepicker__day-body, .c-datepicker__clock__num, .c-datepicker__clock__am-pm-toggle label { 419 | position: relative; 420 | cursor: pointer; } 421 | .u-hover-ball-effect:before, .c-datepicker__day-body:before, .c-datepicker__clock__num:before, .c-datepicker__clock__am-pm-toggle label:before { 422 | content: ""; 423 | position: absolute; 424 | left: 50%; 425 | top: 50%; 426 | width: 0%; 427 | height: 0%; 428 | border-radius: 50%; 429 | transform: translate(-50%, -50%); 430 | transition: width 100ms ease-in-out, height 100ms ease-in-out; } 431 | .u-hover-ball-effect:hover, .c-datepicker__day-body:hover, .c-datepicker__clock__num:hover, .c-datepicker__clock__am-pm-toggle label:hover { 432 | color: white; } 433 | .u-hover-ball-effect:hover:before, .c-datepicker__day-body:hover:before, .c-datepicker__clock__num:hover:before, .c-datepicker__clock__am-pm-toggle label:hover:before { 434 | background: #00bcd4; 435 | width: 35px; 436 | height: 35px; 437 | z-index: -1; } 438 | 439 | .c-datepicker__day-body--active:not(.hide-hand), .c-datepicker__clock__num--active:not(.hide-hand) { 440 | color: white; } 441 | .c-datepicker__day-body--active:not(.hide-hand):before, .c-datepicker__clock__num--active:not(.hide-hand):before { 442 | background: #00bcd4; 443 | width: 35px; 444 | height: 35px; 445 | z-index: -1; } 446 | 447 | .c-datepicker__clock-hands { 448 | position: absolute; 449 | left: 50%; 450 | top: 50%; 451 | transform: translate(-50%, -50%) rotate(180deg); 452 | width: 10px; 453 | height: 10px; 454 | border-radius: 50%; 455 | background: #0097a7; } 456 | 457 | .c-datepicker__hour-hand { 458 | position: absolute; 459 | opacity: 0; 460 | height: 78px; 461 | width: 2px; 462 | background: #00bcd4; 463 | left: 4px; 464 | top: 10px; } 465 | 466 | .c-datepicker__clock__minutes { 467 | display: none; 468 | height: 200px; 469 | margin: -69px 0 0 0; 470 | width: 200px; 471 | display: none; } 472 | .c-datepicker__clock__minutes.active { 473 | display: block; } 474 | 475 | .c-datepicker__clock__hours { 476 | height: 200px; 477 | margin: -69px 0 0 0; 478 | width: 200px; 479 | display: none; } 480 | .c-datepicker__clock__hours.active { 481 | display: block; } 482 | 483 | .c-datepicker__mask { 484 | width: 127px; 485 | height: 132px; 486 | position: absolute; 487 | top: 122px; 488 | left: 37px; 489 | z-index: 99; } 490 | .c-datepicker__mask:after { 491 | content: ' '; 492 | width: 156px; 493 | height: 70px; 494 | display: block; 495 | position: absolute; 496 | top: 32px; 497 | left: 0; 498 | margin-left: -13px; } 499 | .c-datepicker__mask:before { 500 | content: ' '; 501 | width: 75px; 502 | height: 158px; 503 | display: block; 504 | position: absolute; 505 | top: 6px; 506 | left: 28px; 507 | margin-top: -18px; } 508 | 509 | .c-datepicker__clock--show-minutes .c-datepicker__clock__minutes { 510 | visibility: visible; } 511 | 512 | .c-datepicker__clock--show-minutes .c-datepicker__clock__hours { 513 | visibility: hidden; } 514 | 515 | .c-datepicker__clock--show-hours .c-datepicker__clock__minutes { 516 | visibility: hidden; } 517 | 518 | .c-datepicker__clock--show-hours .c-datepicker__clock__hours { 519 | visibility: visible; } 520 | 521 | .c-datepicker__clock__am-pm-toggle { 522 | position: absolute; 523 | top: 0; 524 | left: 10px; 525 | right: 10px; 526 | height: 40px; 527 | padding: 20px; 528 | line-height: 40px; } 529 | .c-datepicker__clock__am-pm-toggle label { 530 | width: 40px; 531 | position: absolute; } 532 | .c-datepicker__clock__am-pm-toggle label:nth-child(1) { 533 | left: 0; } 534 | .c-datepicker__clock__am-pm-toggle label:nth-child(2) { 535 | right: 0; } 536 | .c-datepicker__clock__am-pm-toggle label.c-datepicker__toggle--checked::after { 537 | content: ""; 538 | position: absolute; 539 | left: 50%; 540 | top: 50%; 541 | width: 0%; 542 | height: 0%; 543 | border-radius: 50%; 544 | transform: translate(-50%, -50%); 545 | width: 36px; 546 | height: 36px; 547 | z-index: -1; 548 | background: rgba(0, 0, 0, 0.05); } 549 | -------------------------------------------------------------------------------- /dist/material-datetime-picker.js: -------------------------------------------------------------------------------- 1 | (function (global, factory) { 2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('rome'), require('moment')) : 3 | typeof define === 'function' && define.amd ? define(['rome', 'moment'], factory) : 4 | (global.MaterialDatetimePicker = factory(global.rome,global.moment)); 5 | }(this, (function (rome,moment) { 'use strict'; 6 | 7 | rome = 'default' in rome ? rome['default'] : rome; 8 | moment = 'default' in moment ? moment['default'] : moment; 9 | 10 | var popupTemplate = (function () { 11 | return "\n\n \n \n\n \n \n\n \n \n Monday\n \n \n \n \n \n 09:00\n \n \n \n\n \n \n \n \n \n AM\n \n\n \n \n PM\n \n \n \n \n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10\n 11\n 12\n 1\n 2\n \n \n \n \n \n 15\n 20\n 25\n 30\n 35\n 40\n 45\n 50\n 55\n 0\n 5\n 10\n \n \n \n \n \n \n Cancel\n OK\n \n\n"; 12 | }); 13 | 14 | var scrimTemplate = (function (_ref) { 15 | var styles = _ref.styles; 16 | return "\n\n"; 17 | }); 18 | 19 | var classCallCheck = function (instance, Constructor) { 20 | if (!(instance instanceof Constructor)) { 21 | throw new TypeError("Cannot call a class as a function"); 22 | } 23 | }; 24 | 25 | var createClass = function () { 26 | function defineProperties(target, props) { 27 | for (var i = 0; i < props.length; i++) { 28 | var descriptor = props[i]; 29 | descriptor.enumerable = descriptor.enumerable || false; 30 | descriptor.configurable = true; 31 | if ("value" in descriptor) descriptor.writable = true; 32 | Object.defineProperty(target, descriptor.key, descriptor); 33 | } 34 | } 35 | 36 | return function (Constructor, protoProps, staticProps) { 37 | if (protoProps) defineProperties(Constructor.prototype, protoProps); 38 | if (staticProps) defineProperties(Constructor, staticProps); 39 | return Constructor; 40 | }; 41 | }(); 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | var inherits = function (subClass, superClass) { 52 | if (typeof superClass !== "function" && superClass !== null) { 53 | throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); 54 | } 55 | 56 | subClass.prototype = Object.create(superClass && superClass.prototype, { 57 | constructor: { 58 | value: subClass, 59 | enumerable: false, 60 | writable: true, 61 | configurable: true 62 | } 63 | }); 64 | if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; 65 | }; 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | var possibleConstructorReturn = function (self, call) { 78 | if (!self) { 79 | throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 80 | } 81 | 82 | return call && (typeof call === "object" || typeof call === "function") ? call : self; 83 | }; 84 | 85 | 86 | 87 | 88 | 89 | var slicedToArray = function () { 90 | function sliceIterator(arr, i) { 91 | var _arr = []; 92 | var _n = true; 93 | var _d = false; 94 | var _e = undefined; 95 | 96 | try { 97 | for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { 98 | _arr.push(_s.value); 99 | 100 | if (i && _arr.length === i) break; 101 | } 102 | } catch (err) { 103 | _d = true; 104 | _e = err; 105 | } finally { 106 | try { 107 | if (!_n && _i["return"]) _i["return"](); 108 | } finally { 109 | if (_d) throw _e; 110 | } 111 | } 112 | 113 | return _arr; 114 | } 115 | 116 | return function (arr, i) { 117 | if (Array.isArray(arr)) { 118 | return arr; 119 | } else if (Symbol.iterator in Object(arr)) { 120 | return sliceIterator(arr, i); 121 | } else { 122 | throw new TypeError("Invalid attempt to destructure non-iterable instance"); 123 | } 124 | }; 125 | }(); 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | var toConsumableArray = function (arr) { 140 | if (Array.isArray(arr)) { 141 | for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; 142 | 143 | return arr2; 144 | } else { 145 | return Array.from(arr); 146 | } 147 | }; 148 | 149 | // 150 | // basic event triggering and listening 151 | // 152 | var Events = function () { 153 | function Events() { 154 | classCallCheck(this, Events); 155 | 156 | this._events = { 157 | '*': [] 158 | }; 159 | } 160 | 161 | createClass(Events, [{ 162 | key: 'trigger', 163 | value: function trigger(eventName, evtData) { 164 | var _this = this; 165 | 166 | eventName.split(' ').forEach(function (evtName) { 167 | // trigger a global event event 168 | _this._events['*'].forEach(function (evt) { 169 | return evt.fn.call(evt.scope, evtName, evtData); 170 | }); 171 | // if there are any listeners to this event 172 | // then fire their handlers 173 | if (_this._events[evtName]) { 174 | _this._events[evtName].forEach(function (evt) { 175 | evt.fn.call(evt.scope, evtData); 176 | }); 177 | } 178 | }); 179 | return this; 180 | } 181 | }, { 182 | key: 'on', 183 | value: function on(eventName, fn, scope) { 184 | if (!this._events[eventName]) this._events[eventName] = []; 185 | this._events[eventName].push({ 186 | eventName: eventName, 187 | fn: fn, 188 | scope: scope || this 189 | }); 190 | return this; 191 | } 192 | }, { 193 | key: 'off', 194 | value: function off(eventName, fn) { 195 | if (!this._events[eventName]) return this; 196 | if (!fn) { 197 | this._events[eventName] = []; 198 | } 199 | this._events[eventName] = this._events[eventName].filter(function (evt) { 200 | return evt.fn !== fn; 201 | }); 202 | return this; 203 | } 204 | }, { 205 | key: 'once', 206 | value: function once(eventName, fn, scope) { 207 | var _this2 = this; 208 | 209 | var func = function func() { 210 | fn.call(scope, eventName, fn, scope); 211 | _this2.off(eventName, func); 212 | }; 213 | return this.on(eventName, func, scope); 214 | } 215 | }]); 216 | return Events; 217 | }(); 218 | 219 | var ESC_KEY = 27; 220 | 221 | var prefix = 'c-datepicker'; 222 | var defaults$$1 = function defaults$$1() { 223 | return { 224 | default: moment().startOf('hour'), 225 | // allow the user to override all the classes 226 | // used for styling the calendar 227 | styles: { 228 | scrim: 'c-scrim', 229 | back: prefix + '__back', 230 | container: prefix + '__calendar', 231 | date: prefix + '__date', 232 | dayBody: prefix + '__days-body', 233 | dayBodyElem: prefix + '__day-body', 234 | dayConcealed: prefix + '__day--concealed', 235 | dayDisabled: prefix + '__day--disabled', 236 | dayHead: prefix + '__days-head', 237 | dayHeadElem: prefix + '__day-head', 238 | dayRow: prefix + '__days-row', 239 | dayTable: prefix + '__days', 240 | month: prefix + '__month', 241 | next: prefix + '__next', 242 | positioned: prefix + '--fixed', 243 | selectedDay: prefix + '__day--selected', 244 | selectedTime: prefix + '__time--selected', 245 | time: prefix + '__time', 246 | timeList: prefix + '__time-list', 247 | timeOption: prefix + '__time-option', 248 | clockNum: prefix + '__clock__num' 249 | }, 250 | // format to display in the input, or set on the element 251 | format: 'DD/MM/YY', 252 | // the container to append the picker 253 | container: document.body, 254 | // allow any dates 255 | dateValidator: undefined 256 | }; 257 | }; 258 | 259 | var DateTimePicker = function (_Events) { 260 | inherits(DateTimePicker, _Events); 261 | 262 | function DateTimePicker() { 263 | var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 264 | classCallCheck(this, DateTimePicker); 265 | 266 | var _this = possibleConstructorReturn(this, (DateTimePicker.__proto__ || Object.getPrototypeOf(DateTimePicker)).call(this)); 267 | 268 | var styles = Object.assign(defaults$$1().styles, options.styles); 269 | _this.options = Object.assign(defaults$$1(), options); 270 | _this.options.styles = styles; 271 | 272 | // listen to any event 273 | _this.on('*', function (evtName, evtData) { 274 | if (_this.options.el) { 275 | // if there is a custom element, fire a real dom 276 | // event on that now 277 | var event = new CustomEvent(evtName, _this, evtData); 278 | _this.options.el.dispatchEvent(event); 279 | } 280 | }); 281 | return _this; 282 | } 283 | 284 | // intialize the rom calendar with our default date and 285 | // style options 286 | 287 | 288 | createClass(DateTimePicker, [{ 289 | key: 'initializeRome', 290 | value: function initializeRome(container, validator) { 291 | var onData = this.onChangeDate.bind(this); 292 | 293 | return rome(container, { 294 | styles: this.options.styles, 295 | time: false, 296 | dateValidator: validator, 297 | initialValue: this.value 298 | }).on('data', onData); 299 | } 300 | 301 | // called to open the picker 302 | 303 | }, { 304 | key: 'open', 305 | value: function open() { 306 | var scrimEl = scrimTemplate(this.options); 307 | _appendTemplate(document.body, scrimEl); 308 | _appendTemplate(this.options.container, popupTemplate()); 309 | this.pickerEl = this.options.container.querySelector('.' + prefix); 310 | this.scrimEl = document.body.querySelector('.' + this.options.styles.scrim); 311 | this.amToggleEl = this.$('.c-datepicker__clock--am'); 312 | this.pmToggleEl = this.$('.c-datepicker__clock--pm'); 313 | 314 | if (!this.value) { 315 | // TODO hack 316 | // set/setDate/setTime need refactoring to have single concerns 317 | // (set: set the value; setDate/setTime rename to renderDate/renderTime 318 | // and deal with updating the view only). 319 | // For now this allows us to set the default time using the same quantize 320 | // rules as setting the date explicitly. Setting this.value meets setTime|Date's 321 | // expectation that we have a value, and `0` guarantees that we will detect 322 | this.value = moment(0); 323 | this.setDate(this.options.default); 324 | this.setTime(this.options.default); 325 | } else { 326 | this.setDate(this.value); 327 | this.setTime(this.value); 328 | } 329 | 330 | this.initializeRome(this.$('.' + this.options.styles.container), this.options.dateValidator); 331 | this._listenForCloseEvents(); 332 | 333 | this._show(); 334 | } 335 | }, { 336 | key: 'close', 337 | value: function close() { 338 | this._stopListeningForCloseEvents(); 339 | this._hide(); 340 | } 341 | }, { 342 | key: '_hide', 343 | value: function _hide() { 344 | var _this2 = this; 345 | 346 | this.pickerEl.classList.remove('open'); 347 | window.setTimeout(function () { 348 | _this2.options.container.removeChild(_this2.pickerEl); 349 | document.body.removeChild(_this2.scrimEl); 350 | _this2.trigger('close'); 351 | }, 200); 352 | return this; 353 | } 354 | }, { 355 | key: '_show', 356 | value: function _show() { 357 | var _this3 = this; 358 | 359 | this.delegateEvents(); 360 | // add the animation classes on the next animation tick 361 | // so that they actually work 362 | window.requestAnimationFrame(function () { 363 | _this3.scrimEl.classList.add(_this3.options.styles.scrim + '--shown'); 364 | _this3.pickerEl.classList.add(prefix + '--open'); 365 | _this3.trigger('open'); 366 | }); 367 | return this; 368 | } 369 | }, { 370 | key: '_listenForCloseEvents', 371 | value: function _listenForCloseEvents() { 372 | var _this4 = this; 373 | 374 | this._onWindowKeypress = function (e) { 375 | if (e.which === ESC_KEY) { 376 | _this4.close(); 377 | } 378 | }; 379 | 380 | window.addEventListener("keydown", this._onWindowKeypress); 381 | } 382 | }, { 383 | key: '_stopListeningForCloseEvents', 384 | value: function _stopListeningForCloseEvents() { 385 | window.removeEventListener("keydown", this._onWindowKeypress); 386 | this._closeHandler = null; 387 | } 388 | }, { 389 | key: 'delegateEvents', 390 | value: function delegateEvents() { 391 | var _this5 = this; 392 | 393 | this.$('.js-cancel').addEventListener('click', function () { 394 | return _this5.clickCancel(); 395 | }, false); 396 | this.$('.js-ok').addEventListener('click', function () { 397 | return _this5.clickSubmit(); 398 | }, false); 399 | 400 | this.$('.js-date-hours').addEventListener('click', function (e) { 401 | return _this5.showHourClock(e); 402 | }, false); 403 | this.$('.js-date-minutes').addEventListener('click', function (e) { 404 | return _this5.showMinuteClock(e); 405 | }, false); 406 | 407 | this.$('.js-clock-hours').addEventListener('mouseleave', function (e) { 408 | return _this5.mouseOutHourClock(e); 409 | }, false); 410 | this.$('.js-clock-hours .' + this.options.styles.clockNum).forEach(function (el) { 411 | el.addEventListener('click', function (e) { 412 | return _this5.clickClickHour(e).showMinuteClock(); 413 | }, false); 414 | el.addEventListener('mouseenter', function (e) { 415 | return _this5.mouseInHourClock(e); 416 | }, false); 417 | }); 418 | 419 | this.$('.js-clock-minutes').addEventListener('mouseleave', function (e) { 420 | return _this5.mouseOutMinuteClock(e); 421 | }, false); 422 | this.$('.js-clock-minutes .' + this.options.styles.clockNum).forEach(function (el) { 423 | el.addEventListener('click', function (e) { 424 | return _this5.clickClockMinute(e); 425 | }, false); 426 | el.addEventListener('mouseenter', function (e) { 427 | return _this5.mouseInMinuteClock(e); 428 | }, false); 429 | }); 430 | 431 | this.$('.c-datepicker__clock--am').addEventListener('click', function (e) { 432 | return _this5.clickAm(e); 433 | }, false); 434 | this.$('.c-datepicker__clock--pm').addEventListener('click', function (e) { 435 | return _this5.clickPm(e); 436 | }, false); 437 | 438 | this.$('.js-show-calendar').addEventListener('click', function (e) { 439 | return _this5.clickShowCalendar(e); 440 | }, false); 441 | this.$('.js-date-day').addEventListener('click', function (e) { 442 | return _this5.clickShowCalendar(e); 443 | }, false); 444 | this.$('.js-date-month').addEventListener('click', function (e) { 445 | return _this5.clickShowCalendar(e); 446 | }, false); 447 | 448 | this.$('.js-show-clock').addEventListener('click', function (e) { 449 | return _this5.clickShowClock(e); 450 | }, false); 451 | 452 | this.scrimEl.addEventListener('click', function () { 453 | return _this5.close(); 454 | }, false); 455 | 456 | return this; 457 | } 458 | }, { 459 | key: 'clickSubmit', 460 | value: function clickSubmit() { 461 | this.close(); 462 | this.trigger('submit', this.value, this); 463 | return this; 464 | } 465 | }, { 466 | key: 'clickCancel', 467 | value: function clickCancel() { 468 | this.close(); 469 | this.trigger('cancel', this.value, this); 470 | return this; 471 | } 472 | }, { 473 | key: 'clickClickHour', 474 | value: function clickClickHour(e) { 475 | var newValue = moment(this.value); 476 | var number = parseInt(e.currentTarget.getAttribute('data-number'), 10); 477 | if (number === 0 && this.meridiem === 'pm') { 478 | number = 12; 479 | } else if (this.meridiem === 'pm') { 480 | number += 12; 481 | } 482 | 483 | newValue.hour(number); 484 | this.set(newValue); 485 | return this; 486 | } 487 | }, { 488 | key: 'clickClockMinute', 489 | value: function clickClockMinute(e) { 490 | var newValue = moment(this.value); 491 | var number = parseInt(e.currentTarget.getAttribute('data-number'), 10); 492 | 493 | newValue.minute(number); 494 | this.set(newValue); 495 | return this; 496 | } 497 | }, { 498 | key: 'onChangeDate', 499 | value: function onChangeDate(dateString) { 500 | var newValue = moment(this.value); 501 | 502 | var _dateString$split = dateString.split('-'), 503 | _dateString$split2 = slicedToArray(_dateString$split, 3), 504 | year = _dateString$split2[0], 505 | month = _dateString$split2[1], 506 | date = _dateString$split2[2]; 507 | 508 | newValue.set({ year: year, month: month - 1, date: date }); 509 | 510 | this.set(newValue); 511 | return this; 512 | } 513 | }, { 514 | key: 'mouseInHourClock', 515 | value: function mouseInHourClock() { 516 | var active = this.$('.js-clock-hours .' + this.options.styles.clockNum + '--active'); 517 | 518 | if (active) { 519 | active.classList.add('hide-hand'); 520 | } 521 | } 522 | }, { 523 | key: 'mouseInMinuteClock', 524 | value: function mouseInMinuteClock() { 525 | var active = this.$('.js-clock-minutes .' + this.options.styles.clockNum + '--active'); 526 | 527 | if (active) { 528 | active.classList.add('hide-hand'); 529 | } 530 | } 531 | }, { 532 | key: 'mouseOutHourClock', 533 | value: function mouseOutHourClock() { 534 | var hideHand = this.$('.js-clock-hours .' + this.options.styles.clockNum + '--active.hide-hand'); 535 | 536 | if (hideHand) { 537 | hideHand.classList.remove('hide-hand'); 538 | } 539 | } 540 | }, { 541 | key: 'mouseOutMinuteClock', 542 | value: function mouseOutMinuteClock() { 543 | var hideHand = this.$('.js-clock-minutes .' + this.options.styles.clockNum + '--active.hide-hand'); 544 | 545 | if (hideHand) { 546 | hideHand.classList.remove('hide-hand'); 547 | } 548 | } 549 | }, { 550 | key: 'clickAm', 551 | value: function clickAm() { 552 | var newValue = moment(this.value); 553 | if (this.meridiem === 'pm') { 554 | this.meridiem = 'am'; 555 | newValue.hour(newValue.hour() - 12); 556 | } 557 | this.set(newValue); 558 | return this; 559 | } 560 | }, { 561 | key: 'clickPm', 562 | value: function clickPm() { 563 | var newValue = moment(this.value); 564 | if (this.meridiem === 'am') { 565 | this.meridiem = 'pm'; 566 | newValue.hour(newValue.hour() + 12); 567 | } 568 | this.set(newValue); 569 | return this; 570 | } 571 | }, { 572 | key: 'showHourClock', 573 | value: function showHourClock() { 574 | this.clickShowClock(); 575 | this.$('.js-clock-hours').classList.add('active'); 576 | this.$('.js-clock-minutes').classList.remove('active'); 577 | this.$('.js-date-hours').classList.add('active'); 578 | this.$('.js-date-minutes').classList.remove('active'); 579 | } 580 | }, { 581 | key: 'showMinuteClock', 582 | value: function showMinuteClock() { 583 | this.clickShowClock(); 584 | this.$('.js-clock-hours').classList.remove('active'); 585 | this.$('.js-clock-minutes').classList.add('active'); 586 | this.$('.js-date-hours').classList.remove('active'); 587 | this.$('.js-date-minutes').classList.add('active'); 588 | } 589 | }, { 590 | key: 'clickShowCalendar', 591 | value: function clickShowCalendar() { 592 | this.$('.js-show-calendar').classList.add('is-selected'); 593 | this.$('.js-show-clock').classList.remove('is-selected'); 594 | } 595 | }, { 596 | key: 'clickShowClock', 597 | value: function clickShowClock() { 598 | this.$('.js-show-clock').classList.add('is-selected'); 599 | this.$('.js-show-calendar').classList.remove('is-selected'); 600 | } 601 | }, { 602 | key: 'data', 603 | value: function data(val) { 604 | console.warn('MaterialDatetimePicker#data is deprecated and will be removed in a future release. Please use get or set.'); 605 | return val ? this.set(val) : this.value; 606 | } 607 | }, { 608 | key: 'get', 609 | value: function get$$1() { 610 | return moment(this.value); 611 | } 612 | 613 | // update the picker's date/time value 614 | // value: moment 615 | // silent: if true, do not fire any events on change 616 | 617 | }, { 618 | key: 'set', 619 | value: function set$$1(value) { 620 | var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, 621 | _ref$silent = _ref.silent, 622 | silent = _ref$silent === undefined ? false : _ref$silent; 623 | 624 | var m = moment(value); 625 | 626 | // maintain a list of change events to fire all at once later 627 | var evts = []; 628 | if (m.date() !== this.value.date() || m.month() !== this.value.month() || m.year() !== this.value.year()) { 629 | this.setDate(m); 630 | evts.push('change:date'); 631 | } 632 | 633 | if (m.hour() !== this.value.hour() || m.minutes() !== this.value.minutes()) { 634 | this.setTime(m); 635 | evts.push('change:time'); 636 | } 637 | 638 | if (this.options.el) { 639 | // if there is an element to fire events on 640 | if (this.options.el.tagName === 'INPUT') { 641 | // and it is an input element then set the value 642 | this.options.el.value = m.format(this.options.format); 643 | } else { 644 | // or any other element set a data-value attribute 645 | this.options.el.setAttribute('data-value', m.format(this.options.format)); 646 | } 647 | } 648 | if (evts.length > 0 && !silent) { 649 | // fire all the events we've collected 650 | this.trigger(['change'].concat(evts).join(' '), this.value, this); 651 | } 652 | } 653 | 654 | // set the value and header elements to `date` 655 | // the calendar will be updated automatically 656 | // by rome when clicked 657 | 658 | }, { 659 | key: 'setDate', 660 | value: function setDate(date) { 661 | var m = moment(date); 662 | var month = m.format('MMM'); 663 | var day = m.format('Do'); 664 | var dayOfWeek = m.format('dddd'); 665 | var year = m.format('YYYY'); 666 | 667 | this.$('.js-day').innerText = dayOfWeek; 668 | this.$('.js-date-month').innerText = month + ' ' + year; 669 | this.$('.js-date-day').innerText = day; 670 | this.value.year(m.year()); 671 | this.value.month(m.month()); 672 | this.value.date(m.date()); 673 | return this; 674 | } 675 | 676 | // set the value and header elements to `time` 677 | // also update the hands of the clock 678 | 679 | }, { 680 | key: 'setTime', 681 | value: function setTime(time) { 682 | var m = moment(time); 683 | var minuteAsInt = Math.round(parseInt(m.format('mm'), 10) / 5) * 5; 684 | m.minutes(minuteAsInt); 685 | 686 | var hour = m.format('HH'); 687 | var minutes = m.format('mm'); 688 | var hourAsInt = parseInt(hour, 10) % 12; 689 | 690 | var oldActiveHours = this.$('.js-clock-hours .' + this.options.styles.clockNum + '--active'); 691 | var oldActiveMinutes = this.$('.js-clock-minutes .' + this.options.styles.clockNum + '--active'); 692 | 693 | this.$('.js-date-hours').innerText = hour; 694 | this.$('.js-date-minutes').innerText = minutes; 695 | 696 | if (oldActiveHours) { 697 | oldActiveHours.classList.remove(this.options.styles.clockNum + '--active'); 698 | } 699 | 700 | if (oldActiveMinutes) { 701 | oldActiveMinutes.classList.remove(this.options.styles.clockNum + '--active'); 702 | } 703 | 704 | this.$('.js-clock-hours .' + this.options.styles.clockNum + '[data-number="' + hourAsInt + '"]').classList.add(this.options.styles.clockNum + '--active'); 705 | this.$('.js-clock-minutes .' + this.options.styles.clockNum + '[data-number="' + minuteAsInt + '"]').classList.add(this.options.styles.clockNum + '--active'); 706 | 707 | this.value.hours(m.hours()); 708 | this.value.minutes(m.minutes()); 709 | this.meridiem = this.value.format('a'); 710 | 711 | if (this.meridiem === 'pm') { 712 | this.amToggleEl.removeAttribute('checked'); 713 | this.pmToggleEl.setAttribute('checked', 'checked'); 714 | this.amToggleEl.parentElement.classList.remove('c-datepicker__toggle--checked'); 715 | this.pmToggleEl.parentElement.classList.add('c-datepicker__toggle--checked'); 716 | } else { 717 | this.pmToggleEl.removeAttribute('checked'); 718 | this.amToggleEl.setAttribute('checked', 'checked'); 719 | this.pmToggleEl.parentElement.classList.remove('c-datepicker__toggle--checked'); 720 | this.amToggleEl.parentElement.classList.add('c-datepicker__toggle--checked'); 721 | } 722 | return this; 723 | } 724 | }, { 725 | key: '$', 726 | value: function $(selector) { 727 | var els = this.pickerEl.querySelectorAll(selector); 728 | return els.length > 1 ? [].concat(toConsumableArray(els)) : els[0]; 729 | } 730 | }]); 731 | return DateTimePicker; 732 | }(Events); 733 | 734 | function _appendTemplate(parent, template) { 735 | var tempEl = document.createElement('div'); 736 | tempEl.innerHTML = template.trim(); 737 | parent.appendChild(tempEl.firstChild); 738 | return this; 739 | } 740 | 741 | return DateTimePicker; 742 | 743 | }))); 744 | //# sourceMappingURL=material-datetime-picker.js.map 745 | -------------------------------------------------------------------------------- /dist/material-datetime-picker.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"material-datetime-picker.js","sources":["../lib/template/datepicker.template.js","../lib/template/scrim.template.js","../lib/js/events.js","../lib/js/index.js"],"sourcesContent":["export default () => `\n\n \n \n\n \n \n\n \n \n Monday\n \n \n \n \n \n 09:00\n \n \n \n\n \n \n \n \n \n AM\n \n\n \n \n PM\n \n \n \n \n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10\n 11\n 12\n 1\n 2\n \n \n \n \n \n 15\n 20\n 25\n 30\n 35\n 40\n 45\n 50\n 55\n 0\n 5\n 10\n \n \n \n \n \n \n Cancel\n OK\n \n\n`;\n","export default ({ styles }) => `\n\n`;\n","//\n// basic event triggering and listening\n//\nexport default class Events {\n constructor() {\n this._events = {\n '*': []\n };\n }\n\n trigger(eventName, evtData) {\n eventName.split(' ').forEach((evtName) => {\n // trigger a global event event\n this._events['*'].forEach(evt => evt.fn.call(evt.scope, evtName, evtData));\n // if there are any listeners to this event\n // then fire their handlers\n if (this._events[evtName]) {\n this._events[evtName].forEach((evt) => {\n evt.fn.call(evt.scope, evtData);\n });\n }\n });\n return this;\n }\n\n on(eventName, fn, scope) {\n if (!this._events[eventName]) this._events[eventName] = [];\n this._events[eventName].push({\n eventName,\n fn,\n scope: scope || this\n });\n return this;\n }\n\n off(eventName, fn) {\n if (!this._events[eventName]) return this;\n if (!fn) {\n this._events[eventName] = [];\n }\n this._events[eventName] = this._events[eventName].filter(evt => evt.fn !== fn);\n return this;\n }\n\n once(eventName, fn, scope) {\n const func = () => {\n fn.call(scope, eventName, fn, scope);\n this.off(eventName, func);\n };\n return this.on(eventName, func, scope);\n }\n}\n","import rome from 'rome';\nimport moment from 'moment';\n\nimport popupTemplate from '../template/datepicker.template';\nimport scrimTemplate from '../template/scrim.template';\nimport Events from './events';\n\nimport '../scss/material-datetime-picker.scss';\n\nconst ESC_KEY = 27;\n\nconst prefix = 'c-datepicker';\nconst defaults = () => ({\n default: moment().startOf('hour'),\n // allow the user to override all the classes\n // used for styling the calendar\n styles: {\n scrim: 'c-scrim',\n back: `${prefix}__back`,\n container: `${prefix}__calendar`,\n date: `${prefix}__date`,\n dayBody: `${prefix}__days-body`,\n dayBodyElem: `${prefix}__day-body`,\n dayConcealed: `${prefix}__day--concealed`,\n dayDisabled: `${prefix}__day--disabled`,\n dayHead: `${prefix}__days-head`,\n dayHeadElem: `${prefix}__day-head`,\n dayRow: `${prefix}__days-row`,\n dayTable: `${prefix}__days`,\n month: `${prefix}__month`,\n next: `${prefix}__next`,\n positioned: `${prefix}--fixed`,\n selectedDay: `${prefix}__day--selected`,\n selectedTime: `${prefix}__time--selected`,\n time: `${prefix}__time`,\n timeList: `${prefix}__time-list`,\n timeOption: `${prefix}__time-option`,\n clockNum: `${prefix}__clock__num`\n },\n // format to display in the input, or set on the element\n format: 'DD/MM/YY',\n // the container to append the picker\n container: document.body,\n // allow any dates\n dateValidator: undefined\n});\n\nclass DateTimePicker extends Events {\n constructor(options = {}) {\n super();\n const styles = Object.assign(defaults().styles, options.styles);\n this.options = Object.assign(defaults(), options);\n this.options.styles = styles;\n\n // listen to any event\n this.on('*', (evtName, evtData) => {\n if (this.options.el) {\n // if there is a custom element, fire a real dom\n // event on that now\n const event = new CustomEvent(evtName, this, evtData);\n this.options.el.dispatchEvent(event);\n }\n });\n }\n\n // intialize the rom calendar with our default date and\n // style options\n initializeRome(container, validator) {\n const onData = this.onChangeDate.bind(this);\n\n return rome(container, {\n styles: this.options.styles,\n time: false,\n dateValidator: validator,\n initialValue: this.value\n }).on('data', onData);\n }\n\n // called to open the picker\n open() {\n const scrimEl = scrimTemplate(this.options);\n _appendTemplate(document.body, scrimEl);\n _appendTemplate(this.options.container, popupTemplate());\n this.pickerEl = this.options.container.querySelector(`.${prefix}`);\n this.scrimEl = document.body.querySelector(`.${this.options.styles.scrim}`);\n this.amToggleEl = this.$('.c-datepicker__clock--am');\n this.pmToggleEl = this.$('.c-datepicker__clock--pm');\n\n if (!this.value) {\n // TODO hack\n // set/setDate/setTime need refactoring to have single concerns\n // (set: set the value; setDate/setTime rename to renderDate/renderTime\n // and deal with updating the view only).\n // For now this allows us to set the default time using the same quantize\n // rules as setting the date explicitly. Setting this.value meets setTime|Date's\n // expectation that we have a value, and `0` guarantees that we will detect\n this.value = moment(0);\n this.setDate(this.options.default);\n this.setTime(this.options.default);\n } else {\n this.setDate(this.value);\n this.setTime(this.value);\n }\n\n this.initializeRome(this.$(`.${this.options.styles.container}`), this.options.dateValidator);\n this._listenForCloseEvents();\n\n this._show();\n }\n\n close() {\n this._stopListeningForCloseEvents();\n this._hide();\n }\n\n _hide() {\n this.pickerEl.classList.remove('open');\n window.setTimeout(() => {\n this.options.container.removeChild(this.pickerEl);\n document.body.removeChild(this.scrimEl);\n this.trigger('close');\n }, 200);\n return this;\n }\n\n _show() {\n this.delegateEvents();\n // add the animation classes on the next animation tick\n // so that they actually work\n window.requestAnimationFrame(() => {\n this.scrimEl.classList.add(`${this.options.styles.scrim}--shown`);\n this.pickerEl.classList.add(`${prefix}--open`);\n this.trigger('open');\n });\n return this;\n }\n\n _listenForCloseEvents() {\n this._onWindowKeypress = (e) => {\n if (e.which === ESC_KEY) {\n this.close();\n }\n };\n\n window.addEventListener(\"keydown\", this._onWindowKeypress);\n }\n\n _stopListeningForCloseEvents() {\n window.removeEventListener(\"keydown\", this._onWindowKeypress);\n this._closeHandler = null;\n }\n\n delegateEvents() {\n this.$('.js-cancel')\n .addEventListener('click', () => this.clickCancel(), false);\n this.$('.js-ok')\n .addEventListener('click', () => this.clickSubmit(), false);\n\n this.$('.js-date-hours').addEventListener('click', e => this.showHourClock(e), false);\n this.$('.js-date-minutes').addEventListener('click', e => this.showMinuteClock(e), false);\n\n this.$('.js-clock-hours').addEventListener('mouseleave', e => this.mouseOutHourClock(e), false);\n this.$(`.js-clock-hours .${this.options.styles.clockNum}`).forEach((el) => {\n el.addEventListener('click', e => this.clickClickHour(e).showMinuteClock(), false);\n el.addEventListener('mouseenter', e => this.mouseInHourClock(e), false);\n });\n\n this.$('.js-clock-minutes').addEventListener('mouseleave', e => this.mouseOutMinuteClock(e), false);\n this.$(`.js-clock-minutes .${this.options.styles.clockNum}`).forEach(el => {\n el.addEventListener('click', (e) => this.clickClockMinute(e), false);\n el.addEventListener('mouseenter', e => this.mouseInMinuteClock(e), false);\n });\n\n this.$('.c-datepicker__clock--am')\n .addEventListener('click', e => this.clickAm(e), false);\n this.$('.c-datepicker__clock--pm')\n .addEventListener('click', e => this.clickPm(e), false);\n\n this.$('.js-show-calendar')\n .addEventListener('click', e => this.clickShowCalendar(e), false);\n this.$('.js-date-day')\n .addEventListener('click', e => this.clickShowCalendar(e), false);\n this.$('.js-date-month')\n .addEventListener('click', e => this.clickShowCalendar(e), false);\n\n this.$('.js-show-clock')\n .addEventListener('click', e => this.clickShowClock(e), false);\n\n this.scrimEl.addEventListener('click', () => this.close(), false);\n\n return this;\n }\n\n clickSubmit() {\n this.close();\n this.trigger('submit', this.value, this);\n return this;\n }\n\n clickCancel() {\n this.close();\n this.trigger('cancel', this.value, this);\n return this;\n }\n\n clickClickHour(e) {\n const newValue = moment(this.value);\n let number = parseInt(e.currentTarget.getAttribute('data-number'), 10);\n if (number === 0 && this.meridiem === 'pm') {\n number = 12;\n } else if (this.meridiem === 'pm') {\n number += 12;\n }\n\n newValue.hour(number);\n this.set(newValue);\n return this;\n }\n\n clickClockMinute(e) {\n const newValue = moment(this.value);\n let number = parseInt(e.currentTarget.getAttribute('data-number'), 10);\n\n newValue.minute(number);\n this.set(newValue);\n return this;\n }\n\n onChangeDate(dateString) {\n const newValue = moment(this.value);\n const [year, month, date] = dateString.split('-');\n newValue.set({ year, month: month - 1, date });\n\n this.set(newValue);\n return this;\n }\n\n mouseInHourClock() {\n const active = this.$(`.js-clock-hours .${this.options.styles.clockNum}--active`);\n\n if (active) {\n active.classList.add('hide-hand');\n }\n }\n\n mouseInMinuteClock() {\n const active = this.$(`.js-clock-minutes .${this.options.styles.clockNum}--active`);\n\n if (active) {\n active.classList.add('hide-hand');\n }\n }\n\n mouseOutHourClock() {\n const hideHand = this.$(`.js-clock-hours .${this.options.styles.clockNum}--active.hide-hand`);\n\n if (hideHand) {\n hideHand.classList.remove('hide-hand');\n }\n }\n\n mouseOutMinuteClock() {\n const hideHand = this.$(`.js-clock-minutes .${this.options.styles.clockNum}--active.hide-hand`);\n\n if (hideHand) {\n hideHand.classList.remove('hide-hand');\n }\n }\n\n clickAm() {\n const newValue = moment(this.value);\n if (this.meridiem === 'pm') {\n this.meridiem = 'am';\n newValue.hour(newValue.hour() - 12);\n }\n this.set(newValue);\n return this;\n }\n\n clickPm() {\n const newValue = moment(this.value);\n if (this.meridiem === 'am') {\n this.meridiem = 'pm';\n newValue.hour(newValue.hour() + 12);\n }\n this.set(newValue);\n return this;\n }\n\n showHourClock() {\n this.clickShowClock();\n this.$('.js-clock-hours').classList.add('active');\n this.$('.js-clock-minutes').classList.remove('active');\n this.$('.js-date-hours').classList.add('active');\n this.$('.js-date-minutes').classList.remove('active');\n }\n\n showMinuteClock() {\n this.clickShowClock();\n this.$('.js-clock-hours').classList.remove('active');\n this.$('.js-clock-minutes').classList.add('active');\n this.$('.js-date-hours').classList.remove('active');\n this.$('.js-date-minutes').classList.add('active');\n }\n\n clickShowCalendar() {\n this.$('.js-show-calendar').classList.add('is-selected');\n this.$('.js-show-clock').classList.remove('is-selected');\n }\n\n clickShowClock() {\n this.$('.js-show-clock').classList.add('is-selected');\n this.$('.js-show-calendar').classList.remove('is-selected');\n }\n\n data(val) {\n console.warn(`MaterialDatetimePicker#data is deprecated and will be removed in a future release. Please use get or set.`)\n return (val ? this.set(val) : this.value);\n }\n\n get() {\n return moment(this.value);\n }\n\n // update the picker's date/time value\n // value: moment\n // silent: if true, do not fire any events on change\n set(value, { silent = false } = {}) {\n const m = moment(value);\n\n // maintain a list of change events to fire all at once later\n const evts = [];\n if (m.date() !== this.value.date()\n || m.month() !== this.value.month()\n || m.year() !== this.value.year()\n ) {\n this.setDate(m);\n evts.push('change:date');\n }\n\n if (m.hour() !== this.value.hour()\n || m.minutes() !== this.value.minutes()\n ) {\n this.setTime(m);\n evts.push('change:time');\n }\n\n if (this.options.el) {\n // if there is an element to fire events on\n if (this.options.el.tagName === 'INPUT') {\n // and it is an input element then set the value\n this.options.el.value = m.format(this.options.format);\n } else {\n // or any other element set a data-value attribute\n this.options.el.setAttribute('data-value', m.format(this.options.format));\n }\n }\n if (evts.length > 0 && !silent) {\n // fire all the events we've collected\n this.trigger(['change', ...evts].join(' '), this.value, this);\n }\n }\n\n // set the value and header elements to `date`\n // the calendar will be updated automatically\n // by rome when clicked\n setDate(date) {\n const m = moment(date);\n const month = m.format('MMM');\n const day = m.format('Do');\n const dayOfWeek = m.format('dddd');\n const year = m.format('YYYY');\n\n this.$('.js-day').innerText = dayOfWeek;\n this.$('.js-date-month').innerText = (`${month} ${year}`);\n this.$('.js-date-day').innerText = day;\n this.value.year(m.year());\n this.value.month(m.month());\n this.value.date(m.date());\n return this;\n }\n\n // set the value and header elements to `time`\n // also update the hands of the clock\n setTime(time) {\n const m = moment(time);\n const minuteAsInt = Math.round(parseInt(m.format('mm'), 10) / 5) * 5;\n m.minutes(minuteAsInt);\n\n const hour = m.format('HH');\n const minutes = m.format('mm');\n const hourAsInt = parseInt(hour, 10) % 12;\n\n const oldActiveHours = this.$(`.js-clock-hours .${this.options.styles.clockNum}--active`);\n const oldActiveMinutes = this.$(`.js-clock-minutes .${this.options.styles.clockNum}--active`);\n\n this.$('.js-date-hours').innerText = hour;\n this.$('.js-date-minutes').innerText = minutes;\n\n if (oldActiveHours) {\n oldActiveHours.classList.remove(`${this.options.styles.clockNum}--active`);\n }\n\n if (oldActiveMinutes) {\n oldActiveMinutes.classList.remove(`${this.options.styles.clockNum}--active`);\n }\n\n this.$(`.js-clock-hours .${this.options.styles.clockNum}[data-number=\"${hourAsInt}\"]`)\n .classList.add(`${this.options.styles.clockNum}--active`);\n this.$(`.js-clock-minutes .${this.options.styles.clockNum}[data-number=\"${minuteAsInt}\"]`)\n .classList.add(`${this.options.styles.clockNum}--active`);\n\n this.value.hours(m.hours());\n this.value.minutes(m.minutes());\n this.meridiem = this.value.format('a');\n\n if (this.meridiem === 'pm') {\n this.amToggleEl.removeAttribute('checked');\n this.pmToggleEl.setAttribute('checked', 'checked');\n this.amToggleEl.parentElement.classList.remove('c-datepicker__toggle--checked');\n this.pmToggleEl.parentElement.classList.add('c-datepicker__toggle--checked');\n } else {\n this.pmToggleEl.removeAttribute('checked');\n this.amToggleEl.setAttribute('checked', 'checked');\n this.pmToggleEl.parentElement.classList.remove('c-datepicker__toggle--checked');\n this.amToggleEl.parentElement.classList.add('c-datepicker__toggle--checked');\n }\n return this;\n }\n\n $(selector) {\n const els = this.pickerEl.querySelectorAll(selector);\n return els.length > 1 ? [...els] : els[0];\n }\n}\n\nexport default DateTimePicker;\n\nfunction _appendTemplate(parent, template) {\n const tempEl = document.createElement('div');\n tempEl.innerHTML = template.trim();\n parent.appendChild(tempEl.firstChild);\n return this;\n}\n"],"names":["styles","scrim","Events","_events","eventName","evtData","split","forEach","evtName","evt","fn","call","scope","push","filter","func","off","on","ESC_KEY","prefix","defaults","moment","startOf","document","body","undefined","DateTimePicker","options","Object","assign","el","event","CustomEvent","dispatchEvent","container","validator","onData","onChangeDate","bind","rome","value","scrimEl","scrimTemplate","popupTemplate","pickerEl","querySelector","amToggleEl","$","pmToggleEl","setDate","default","setTime","initializeRome","dateValidator","_listenForCloseEvents","_show","_stopListeningForCloseEvents","_hide","classList","remove","setTimeout","removeChild","trigger","delegateEvents","requestAnimationFrame","add","_onWindowKeypress","e","which","close","addEventListener","removeEventListener","_closeHandler","clickCancel","clickSubmit","showHourClock","showMinuteClock","mouseOutHourClock","clockNum","clickClickHour","mouseInHourClock","mouseOutMinuteClock","clickClockMinute","mouseInMinuteClock","clickAm","clickPm","clickShowCalendar","clickShowClock","newValue","number","parseInt","currentTarget","getAttribute","meridiem","hour","set","minute","dateString","year","month","date","active","hideHand","val","warn","silent","m","evts","minutes","tagName","format","setAttribute","length","join","day","dayOfWeek","innerText","time","minuteAsInt","Math","round","hourAsInt","oldActiveHours","oldActiveMinutes","hours","removeAttribute","parentElement","selector","els","querySelectorAll","_appendTemplate","parent","template","tempEl","createElement","innerHTML","trim","appendChild","firstChild"],"mappings":"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"} -------------------------------------------------------------------------------- /dist/material-datetime-picker.mjs: -------------------------------------------------------------------------------- 1 | import rome from 'rome'; 2 | import moment from 'moment'; 3 | 4 | var popupTemplate = (function () { 5 | return "\n\n \n \n\n \n \n\n \n \n Monday\n \n \n \n \n \n 09:00\n \n \n \n\n \n \n \n \n \n AM\n \n\n \n \n PM\n \n \n \n \n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10\n 11\n 12\n 1\n 2\n \n \n \n \n \n 15\n 20\n 25\n 30\n 35\n 40\n 45\n 50\n 55\n 0\n 5\n 10\n \n \n \n \n \n \n Cancel\n OK\n \n\n"; 6 | }); 7 | 8 | var scrimTemplate = (function (_ref) { 9 | var styles = _ref.styles; 10 | return "\n\n"; 11 | }); 12 | 13 | var classCallCheck = function (instance, Constructor) { 14 | if (!(instance instanceof Constructor)) { 15 | throw new TypeError("Cannot call a class as a function"); 16 | } 17 | }; 18 | 19 | var createClass = function () { 20 | function defineProperties(target, props) { 21 | for (var i = 0; i < props.length; i++) { 22 | var descriptor = props[i]; 23 | descriptor.enumerable = descriptor.enumerable || false; 24 | descriptor.configurable = true; 25 | if ("value" in descriptor) descriptor.writable = true; 26 | Object.defineProperty(target, descriptor.key, descriptor); 27 | } 28 | } 29 | 30 | return function (Constructor, protoProps, staticProps) { 31 | if (protoProps) defineProperties(Constructor.prototype, protoProps); 32 | if (staticProps) defineProperties(Constructor, staticProps); 33 | return Constructor; 34 | }; 35 | }(); 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | var inherits = function (subClass, superClass) { 46 | if (typeof superClass !== "function" && superClass !== null) { 47 | throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); 48 | } 49 | 50 | subClass.prototype = Object.create(superClass && superClass.prototype, { 51 | constructor: { 52 | value: subClass, 53 | enumerable: false, 54 | writable: true, 55 | configurable: true 56 | } 57 | }); 58 | if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; 59 | }; 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | var possibleConstructorReturn = function (self, call) { 72 | if (!self) { 73 | throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 74 | } 75 | 76 | return call && (typeof call === "object" || typeof call === "function") ? call : self; 77 | }; 78 | 79 | 80 | 81 | 82 | 83 | var slicedToArray = function () { 84 | function sliceIterator(arr, i) { 85 | var _arr = []; 86 | var _n = true; 87 | var _d = false; 88 | var _e = undefined; 89 | 90 | try { 91 | for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { 92 | _arr.push(_s.value); 93 | 94 | if (i && _arr.length === i) break; 95 | } 96 | } catch (err) { 97 | _d = true; 98 | _e = err; 99 | } finally { 100 | try { 101 | if (!_n && _i["return"]) _i["return"](); 102 | } finally { 103 | if (_d) throw _e; 104 | } 105 | } 106 | 107 | return _arr; 108 | } 109 | 110 | return function (arr, i) { 111 | if (Array.isArray(arr)) { 112 | return arr; 113 | } else if (Symbol.iterator in Object(arr)) { 114 | return sliceIterator(arr, i); 115 | } else { 116 | throw new TypeError("Invalid attempt to destructure non-iterable instance"); 117 | } 118 | }; 119 | }(); 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | var toConsumableArray = function (arr) { 134 | if (Array.isArray(arr)) { 135 | for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; 136 | 137 | return arr2; 138 | } else { 139 | return Array.from(arr); 140 | } 141 | }; 142 | 143 | // 144 | // basic event triggering and listening 145 | // 146 | var Events = function () { 147 | function Events() { 148 | classCallCheck(this, Events); 149 | 150 | this._events = { 151 | '*': [] 152 | }; 153 | } 154 | 155 | createClass(Events, [{ 156 | key: 'trigger', 157 | value: function trigger(eventName, evtData) { 158 | var _this = this; 159 | 160 | eventName.split(' ').forEach(function (evtName) { 161 | // trigger a global event event 162 | _this._events['*'].forEach(function (evt) { 163 | return evt.fn.call(evt.scope, evtName, evtData); 164 | }); 165 | // if there are any listeners to this event 166 | // then fire their handlers 167 | if (_this._events[evtName]) { 168 | _this._events[evtName].forEach(function (evt) { 169 | evt.fn.call(evt.scope, evtData); 170 | }); 171 | } 172 | }); 173 | return this; 174 | } 175 | }, { 176 | key: 'on', 177 | value: function on(eventName, fn, scope) { 178 | if (!this._events[eventName]) this._events[eventName] = []; 179 | this._events[eventName].push({ 180 | eventName: eventName, 181 | fn: fn, 182 | scope: scope || this 183 | }); 184 | return this; 185 | } 186 | }, { 187 | key: 'off', 188 | value: function off(eventName, fn) { 189 | if (!this._events[eventName]) return this; 190 | if (!fn) { 191 | this._events[eventName] = []; 192 | } 193 | this._events[eventName] = this._events[eventName].filter(function (evt) { 194 | return evt.fn !== fn; 195 | }); 196 | return this; 197 | } 198 | }, { 199 | key: 'once', 200 | value: function once(eventName, fn, scope) { 201 | var _this2 = this; 202 | 203 | var func = function func() { 204 | fn.call(scope, eventName, fn, scope); 205 | _this2.off(eventName, func); 206 | }; 207 | return this.on(eventName, func, scope); 208 | } 209 | }]); 210 | return Events; 211 | }(); 212 | 213 | var ESC_KEY = 27; 214 | 215 | var prefix = 'c-datepicker'; 216 | var defaults$$1 = function defaults$$1() { 217 | return { 218 | default: moment().startOf('hour'), 219 | // allow the user to override all the classes 220 | // used for styling the calendar 221 | styles: { 222 | scrim: 'c-scrim', 223 | back: prefix + '__back', 224 | container: prefix + '__calendar', 225 | date: prefix + '__date', 226 | dayBody: prefix + '__days-body', 227 | dayBodyElem: prefix + '__day-body', 228 | dayConcealed: prefix + '__day--concealed', 229 | dayDisabled: prefix + '__day--disabled', 230 | dayHead: prefix + '__days-head', 231 | dayHeadElem: prefix + '__day-head', 232 | dayRow: prefix + '__days-row', 233 | dayTable: prefix + '__days', 234 | month: prefix + '__month', 235 | next: prefix + '__next', 236 | positioned: prefix + '--fixed', 237 | selectedDay: prefix + '__day--selected', 238 | selectedTime: prefix + '__time--selected', 239 | time: prefix + '__time', 240 | timeList: prefix + '__time-list', 241 | timeOption: prefix + '__time-option', 242 | clockNum: prefix + '__clock__num' 243 | }, 244 | // format to display in the input, or set on the element 245 | format: 'DD/MM/YY', 246 | // the container to append the picker 247 | container: document.body, 248 | // allow any dates 249 | dateValidator: undefined 250 | }; 251 | }; 252 | 253 | var DateTimePicker = function (_Events) { 254 | inherits(DateTimePicker, _Events); 255 | 256 | function DateTimePicker() { 257 | var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 258 | classCallCheck(this, DateTimePicker); 259 | 260 | var _this = possibleConstructorReturn(this, (DateTimePicker.__proto__ || Object.getPrototypeOf(DateTimePicker)).call(this)); 261 | 262 | var styles = Object.assign(defaults$$1().styles, options.styles); 263 | _this.options = Object.assign(defaults$$1(), options); 264 | _this.options.styles = styles; 265 | 266 | // listen to any event 267 | _this.on('*', function (evtName, evtData) { 268 | if (_this.options.el) { 269 | // if there is a custom element, fire a real dom 270 | // event on that now 271 | var event = new CustomEvent(evtName, _this, evtData); 272 | _this.options.el.dispatchEvent(event); 273 | } 274 | }); 275 | return _this; 276 | } 277 | 278 | // intialize the rom calendar with our default date and 279 | // style options 280 | 281 | 282 | createClass(DateTimePicker, [{ 283 | key: 'initializeRome', 284 | value: function initializeRome(container, validator) { 285 | var onData = this.onChangeDate.bind(this); 286 | 287 | return rome(container, { 288 | styles: this.options.styles, 289 | time: false, 290 | dateValidator: validator, 291 | initialValue: this.value 292 | }).on('data', onData); 293 | } 294 | 295 | // called to open the picker 296 | 297 | }, { 298 | key: 'open', 299 | value: function open() { 300 | var scrimEl = scrimTemplate(this.options); 301 | _appendTemplate(document.body, scrimEl); 302 | _appendTemplate(this.options.container, popupTemplate()); 303 | this.pickerEl = this.options.container.querySelector('.' + prefix); 304 | this.scrimEl = document.body.querySelector('.' + this.options.styles.scrim); 305 | this.amToggleEl = this.$('.c-datepicker__clock--am'); 306 | this.pmToggleEl = this.$('.c-datepicker__clock--pm'); 307 | 308 | if (!this.value) { 309 | // TODO hack 310 | // set/setDate/setTime need refactoring to have single concerns 311 | // (set: set the value; setDate/setTime rename to renderDate/renderTime 312 | // and deal with updating the view only). 313 | // For now this allows us to set the default time using the same quantize 314 | // rules as setting the date explicitly. Setting this.value meets setTime|Date's 315 | // expectation that we have a value, and `0` guarantees that we will detect 316 | this.value = moment(0); 317 | this.setDate(this.options.default); 318 | this.setTime(this.options.default); 319 | } else { 320 | this.setDate(this.value); 321 | this.setTime(this.value); 322 | } 323 | 324 | this.initializeRome(this.$('.' + this.options.styles.container), this.options.dateValidator); 325 | this._listenForCloseEvents(); 326 | 327 | this._show(); 328 | } 329 | }, { 330 | key: 'close', 331 | value: function close() { 332 | this._stopListeningForCloseEvents(); 333 | this._hide(); 334 | } 335 | }, { 336 | key: '_hide', 337 | value: function _hide() { 338 | var _this2 = this; 339 | 340 | this.pickerEl.classList.remove('open'); 341 | window.setTimeout(function () { 342 | _this2.options.container.removeChild(_this2.pickerEl); 343 | document.body.removeChild(_this2.scrimEl); 344 | _this2.trigger('close'); 345 | }, 200); 346 | return this; 347 | } 348 | }, { 349 | key: '_show', 350 | value: function _show() { 351 | var _this3 = this; 352 | 353 | this.delegateEvents(); 354 | // add the animation classes on the next animation tick 355 | // so that they actually work 356 | window.requestAnimationFrame(function () { 357 | _this3.scrimEl.classList.add(_this3.options.styles.scrim + '--shown'); 358 | _this3.pickerEl.classList.add(prefix + '--open'); 359 | _this3.trigger('open'); 360 | }); 361 | return this; 362 | } 363 | }, { 364 | key: '_listenForCloseEvents', 365 | value: function _listenForCloseEvents() { 366 | var _this4 = this; 367 | 368 | this._onWindowKeypress = function (e) { 369 | if (e.which === ESC_KEY) { 370 | _this4.close(); 371 | } 372 | }; 373 | 374 | window.addEventListener("keydown", this._onWindowKeypress); 375 | } 376 | }, { 377 | key: '_stopListeningForCloseEvents', 378 | value: function _stopListeningForCloseEvents() { 379 | window.removeEventListener("keydown", this._onWindowKeypress); 380 | this._closeHandler = null; 381 | } 382 | }, { 383 | key: 'delegateEvents', 384 | value: function delegateEvents() { 385 | var _this5 = this; 386 | 387 | this.$('.js-cancel').addEventListener('click', function () { 388 | return _this5.clickCancel(); 389 | }, false); 390 | this.$('.js-ok').addEventListener('click', function () { 391 | return _this5.clickSubmit(); 392 | }, false); 393 | 394 | this.$('.js-date-hours').addEventListener('click', function (e) { 395 | return _this5.showHourClock(e); 396 | }, false); 397 | this.$('.js-date-minutes').addEventListener('click', function (e) { 398 | return _this5.showMinuteClock(e); 399 | }, false); 400 | 401 | this.$('.js-clock-hours').addEventListener('mouseleave', function (e) { 402 | return _this5.mouseOutHourClock(e); 403 | }, false); 404 | this.$('.js-clock-hours .' + this.options.styles.clockNum).forEach(function (el) { 405 | el.addEventListener('click', function (e) { 406 | return _this5.clickClickHour(e).showMinuteClock(); 407 | }, false); 408 | el.addEventListener('mouseenter', function (e) { 409 | return _this5.mouseInHourClock(e); 410 | }, false); 411 | }); 412 | 413 | this.$('.js-clock-minutes').addEventListener('mouseleave', function (e) { 414 | return _this5.mouseOutMinuteClock(e); 415 | }, false); 416 | this.$('.js-clock-minutes .' + this.options.styles.clockNum).forEach(function (el) { 417 | el.addEventListener('click', function (e) { 418 | return _this5.clickClockMinute(e); 419 | }, false); 420 | el.addEventListener('mouseenter', function (e) { 421 | return _this5.mouseInMinuteClock(e); 422 | }, false); 423 | }); 424 | 425 | this.$('.c-datepicker__clock--am').addEventListener('click', function (e) { 426 | return _this5.clickAm(e); 427 | }, false); 428 | this.$('.c-datepicker__clock--pm').addEventListener('click', function (e) { 429 | return _this5.clickPm(e); 430 | }, false); 431 | 432 | this.$('.js-show-calendar').addEventListener('click', function (e) { 433 | return _this5.clickShowCalendar(e); 434 | }, false); 435 | this.$('.js-date-day').addEventListener('click', function (e) { 436 | return _this5.clickShowCalendar(e); 437 | }, false); 438 | this.$('.js-date-month').addEventListener('click', function (e) { 439 | return _this5.clickShowCalendar(e); 440 | }, false); 441 | 442 | this.$('.js-show-clock').addEventListener('click', function (e) { 443 | return _this5.clickShowClock(e); 444 | }, false); 445 | 446 | this.scrimEl.addEventListener('click', function () { 447 | return _this5.close(); 448 | }, false); 449 | 450 | return this; 451 | } 452 | }, { 453 | key: 'clickSubmit', 454 | value: function clickSubmit() { 455 | this.close(); 456 | this.trigger('submit', this.value, this); 457 | return this; 458 | } 459 | }, { 460 | key: 'clickCancel', 461 | value: function clickCancel() { 462 | this.close(); 463 | this.trigger('cancel', this.value, this); 464 | return this; 465 | } 466 | }, { 467 | key: 'clickClickHour', 468 | value: function clickClickHour(e) { 469 | var newValue = moment(this.value); 470 | var number = parseInt(e.currentTarget.getAttribute('data-number'), 10); 471 | if (number === 0 && this.meridiem === 'pm') { 472 | number = 12; 473 | } else if (this.meridiem === 'pm') { 474 | number += 12; 475 | } 476 | 477 | newValue.hour(number); 478 | this.set(newValue); 479 | return this; 480 | } 481 | }, { 482 | key: 'clickClockMinute', 483 | value: function clickClockMinute(e) { 484 | var newValue = moment(this.value); 485 | var number = parseInt(e.currentTarget.getAttribute('data-number'), 10); 486 | 487 | newValue.minute(number); 488 | this.set(newValue); 489 | return this; 490 | } 491 | }, { 492 | key: 'onChangeDate', 493 | value: function onChangeDate(dateString) { 494 | var newValue = moment(this.value); 495 | 496 | var _dateString$split = dateString.split('-'), 497 | _dateString$split2 = slicedToArray(_dateString$split, 3), 498 | year = _dateString$split2[0], 499 | month = _dateString$split2[1], 500 | date = _dateString$split2[2]; 501 | 502 | newValue.set({ year: year, month: month - 1, date: date }); 503 | 504 | this.set(newValue); 505 | return this; 506 | } 507 | }, { 508 | key: 'mouseInHourClock', 509 | value: function mouseInHourClock() { 510 | var active = this.$('.js-clock-hours .' + this.options.styles.clockNum + '--active'); 511 | 512 | if (active) { 513 | active.classList.add('hide-hand'); 514 | } 515 | } 516 | }, { 517 | key: 'mouseInMinuteClock', 518 | value: function mouseInMinuteClock() { 519 | var active = this.$('.js-clock-minutes .' + this.options.styles.clockNum + '--active'); 520 | 521 | if (active) { 522 | active.classList.add('hide-hand'); 523 | } 524 | } 525 | }, { 526 | key: 'mouseOutHourClock', 527 | value: function mouseOutHourClock() { 528 | var hideHand = this.$('.js-clock-hours .' + this.options.styles.clockNum + '--active.hide-hand'); 529 | 530 | if (hideHand) { 531 | hideHand.classList.remove('hide-hand'); 532 | } 533 | } 534 | }, { 535 | key: 'mouseOutMinuteClock', 536 | value: function mouseOutMinuteClock() { 537 | var hideHand = this.$('.js-clock-minutes .' + this.options.styles.clockNum + '--active.hide-hand'); 538 | 539 | if (hideHand) { 540 | hideHand.classList.remove('hide-hand'); 541 | } 542 | } 543 | }, { 544 | key: 'clickAm', 545 | value: function clickAm() { 546 | var newValue = moment(this.value); 547 | if (this.meridiem === 'pm') { 548 | this.meridiem = 'am'; 549 | newValue.hour(newValue.hour() - 12); 550 | } 551 | this.set(newValue); 552 | return this; 553 | } 554 | }, { 555 | key: 'clickPm', 556 | value: function clickPm() { 557 | var newValue = moment(this.value); 558 | if (this.meridiem === 'am') { 559 | this.meridiem = 'pm'; 560 | newValue.hour(newValue.hour() + 12); 561 | } 562 | this.set(newValue); 563 | return this; 564 | } 565 | }, { 566 | key: 'showHourClock', 567 | value: function showHourClock() { 568 | this.clickShowClock(); 569 | this.$('.js-clock-hours').classList.add('active'); 570 | this.$('.js-clock-minutes').classList.remove('active'); 571 | this.$('.js-date-hours').classList.add('active'); 572 | this.$('.js-date-minutes').classList.remove('active'); 573 | } 574 | }, { 575 | key: 'showMinuteClock', 576 | value: function showMinuteClock() { 577 | this.clickShowClock(); 578 | this.$('.js-clock-hours').classList.remove('active'); 579 | this.$('.js-clock-minutes').classList.add('active'); 580 | this.$('.js-date-hours').classList.remove('active'); 581 | this.$('.js-date-minutes').classList.add('active'); 582 | } 583 | }, { 584 | key: 'clickShowCalendar', 585 | value: function clickShowCalendar() { 586 | this.$('.js-show-calendar').classList.add('is-selected'); 587 | this.$('.js-show-clock').classList.remove('is-selected'); 588 | } 589 | }, { 590 | key: 'clickShowClock', 591 | value: function clickShowClock() { 592 | this.$('.js-show-clock').classList.add('is-selected'); 593 | this.$('.js-show-calendar').classList.remove('is-selected'); 594 | } 595 | }, { 596 | key: 'data', 597 | value: function data(val) { 598 | console.warn('MaterialDatetimePicker#data is deprecated and will be removed in a future release. Please use get or set.'); 599 | return val ? this.set(val) : this.value; 600 | } 601 | }, { 602 | key: 'get', 603 | value: function get$$1() { 604 | return moment(this.value); 605 | } 606 | 607 | // update the picker's date/time value 608 | // value: moment 609 | // silent: if true, do not fire any events on change 610 | 611 | }, { 612 | key: 'set', 613 | value: function set$$1(value) { 614 | var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, 615 | _ref$silent = _ref.silent, 616 | silent = _ref$silent === undefined ? false : _ref$silent; 617 | 618 | var m = moment(value); 619 | 620 | // maintain a list of change events to fire all at once later 621 | var evts = []; 622 | if (m.date() !== this.value.date() || m.month() !== this.value.month() || m.year() !== this.value.year()) { 623 | this.setDate(m); 624 | evts.push('change:date'); 625 | } 626 | 627 | if (m.hour() !== this.value.hour() || m.minutes() !== this.value.minutes()) { 628 | this.setTime(m); 629 | evts.push('change:time'); 630 | } 631 | 632 | if (this.options.el) { 633 | // if there is an element to fire events on 634 | if (this.options.el.tagName === 'INPUT') { 635 | // and it is an input element then set the value 636 | this.options.el.value = m.format(this.options.format); 637 | } else { 638 | // or any other element set a data-value attribute 639 | this.options.el.setAttribute('data-value', m.format(this.options.format)); 640 | } 641 | } 642 | if (evts.length > 0 && !silent) { 643 | // fire all the events we've collected 644 | this.trigger(['change'].concat(evts).join(' '), this.value, this); 645 | } 646 | } 647 | 648 | // set the value and header elements to `date` 649 | // the calendar will be updated automatically 650 | // by rome when clicked 651 | 652 | }, { 653 | key: 'setDate', 654 | value: function setDate(date) { 655 | var m = moment(date); 656 | var month = m.format('MMM'); 657 | var day = m.format('Do'); 658 | var dayOfWeek = m.format('dddd'); 659 | var year = m.format('YYYY'); 660 | 661 | this.$('.js-day').innerText = dayOfWeek; 662 | this.$('.js-date-month').innerText = month + ' ' + year; 663 | this.$('.js-date-day').innerText = day; 664 | this.value.year(m.year()); 665 | this.value.month(m.month()); 666 | this.value.date(m.date()); 667 | return this; 668 | } 669 | 670 | // set the value and header elements to `time` 671 | // also update the hands of the clock 672 | 673 | }, { 674 | key: 'setTime', 675 | value: function setTime(time) { 676 | var m = moment(time); 677 | var minuteAsInt = Math.round(parseInt(m.format('mm'), 10) / 5) * 5; 678 | m.minutes(minuteAsInt); 679 | 680 | var hour = m.format('HH'); 681 | var minutes = m.format('mm'); 682 | var hourAsInt = parseInt(hour, 10) % 12; 683 | 684 | var oldActiveHours = this.$('.js-clock-hours .' + this.options.styles.clockNum + '--active'); 685 | var oldActiveMinutes = this.$('.js-clock-minutes .' + this.options.styles.clockNum + '--active'); 686 | 687 | this.$('.js-date-hours').innerText = hour; 688 | this.$('.js-date-minutes').innerText = minutes; 689 | 690 | if (oldActiveHours) { 691 | oldActiveHours.classList.remove(this.options.styles.clockNum + '--active'); 692 | } 693 | 694 | if (oldActiveMinutes) { 695 | oldActiveMinutes.classList.remove(this.options.styles.clockNum + '--active'); 696 | } 697 | 698 | this.$('.js-clock-hours .' + this.options.styles.clockNum + '[data-number="' + hourAsInt + '"]').classList.add(this.options.styles.clockNum + '--active'); 699 | this.$('.js-clock-minutes .' + this.options.styles.clockNum + '[data-number="' + minuteAsInt + '"]').classList.add(this.options.styles.clockNum + '--active'); 700 | 701 | this.value.hours(m.hours()); 702 | this.value.minutes(m.minutes()); 703 | this.meridiem = this.value.format('a'); 704 | 705 | if (this.meridiem === 'pm') { 706 | this.amToggleEl.removeAttribute('checked'); 707 | this.pmToggleEl.setAttribute('checked', 'checked'); 708 | this.amToggleEl.parentElement.classList.remove('c-datepicker__toggle--checked'); 709 | this.pmToggleEl.parentElement.classList.add('c-datepicker__toggle--checked'); 710 | } else { 711 | this.pmToggleEl.removeAttribute('checked'); 712 | this.amToggleEl.setAttribute('checked', 'checked'); 713 | this.pmToggleEl.parentElement.classList.remove('c-datepicker__toggle--checked'); 714 | this.amToggleEl.parentElement.classList.add('c-datepicker__toggle--checked'); 715 | } 716 | return this; 717 | } 718 | }, { 719 | key: '$', 720 | value: function $(selector) { 721 | var els = this.pickerEl.querySelectorAll(selector); 722 | return els.length > 1 ? [].concat(toConsumableArray(els)) : els[0]; 723 | } 724 | }]); 725 | return DateTimePicker; 726 | }(Events); 727 | 728 | function _appendTemplate(parent, template) { 729 | var tempEl = document.createElement('div'); 730 | tempEl.innerHTML = template.trim(); 731 | parent.appendChild(tempEl.firstChild); 732 | return this; 733 | } 734 | 735 | export default DateTimePicker; 736 | //# sourceMappingURL=material-datetime-picker.mjs.map 737 | -------------------------------------------------------------------------------- /dist/material-datetime-picker.mjs.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"material-datetime-picker.mjs","sources":["../lib/template/datepicker.template.js","../lib/template/scrim.template.js","../lib/js/events.js","../lib/js/index.js"],"sourcesContent":["export default () => `\n\n \n \n\n \n \n\n \n \n Monday\n \n \n \n \n \n 09:00\n \n \n \n\n \n \n \n \n \n AM\n \n\n \n \n PM\n \n \n \n \n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10\n 11\n 12\n 1\n 2\n \n \n \n \n \n 15\n 20\n 25\n 30\n 35\n 40\n 45\n 50\n 55\n 0\n 5\n 10\n \n \n \n \n \n \n Cancel\n OK\n \n\n`;\n","export default ({ styles }) => `\n\n`;\n","//\n// basic event triggering and listening\n//\nexport default class Events {\n constructor() {\n this._events = {\n '*': []\n };\n }\n\n trigger(eventName, evtData) {\n eventName.split(' ').forEach((evtName) => {\n // trigger a global event event\n this._events['*'].forEach(evt => evt.fn.call(evt.scope, evtName, evtData));\n // if there are any listeners to this event\n // then fire their handlers\n if (this._events[evtName]) {\n this._events[evtName].forEach((evt) => {\n evt.fn.call(evt.scope, evtData);\n });\n }\n });\n return this;\n }\n\n on(eventName, fn, scope) {\n if (!this._events[eventName]) this._events[eventName] = [];\n this._events[eventName].push({\n eventName,\n fn,\n scope: scope || this\n });\n return this;\n }\n\n off(eventName, fn) {\n if (!this._events[eventName]) return this;\n if (!fn) {\n this._events[eventName] = [];\n }\n this._events[eventName] = this._events[eventName].filter(evt => evt.fn !== fn);\n return this;\n }\n\n once(eventName, fn, scope) {\n const func = () => {\n fn.call(scope, eventName, fn, scope);\n this.off(eventName, func);\n };\n return this.on(eventName, func, scope);\n }\n}\n","import rome from 'rome';\nimport moment from 'moment';\n\nimport popupTemplate from '../template/datepicker.template';\nimport scrimTemplate from '../template/scrim.template';\nimport Events from './events';\n\nimport '../scss/material-datetime-picker.scss';\n\nconst ESC_KEY = 27;\n\nconst prefix = 'c-datepicker';\nconst defaults = () => ({\n default: moment().startOf('hour'),\n // allow the user to override all the classes\n // used for styling the calendar\n styles: {\n scrim: 'c-scrim',\n back: `${prefix}__back`,\n container: `${prefix}__calendar`,\n date: `${prefix}__date`,\n dayBody: `${prefix}__days-body`,\n dayBodyElem: `${prefix}__day-body`,\n dayConcealed: `${prefix}__day--concealed`,\n dayDisabled: `${prefix}__day--disabled`,\n dayHead: `${prefix}__days-head`,\n dayHeadElem: `${prefix}__day-head`,\n dayRow: `${prefix}__days-row`,\n dayTable: `${prefix}__days`,\n month: `${prefix}__month`,\n next: `${prefix}__next`,\n positioned: `${prefix}--fixed`,\n selectedDay: `${prefix}__day--selected`,\n selectedTime: `${prefix}__time--selected`,\n time: `${prefix}__time`,\n timeList: `${prefix}__time-list`,\n timeOption: `${prefix}__time-option`,\n clockNum: `${prefix}__clock__num`\n },\n // format to display in the input, or set on the element\n format: 'DD/MM/YY',\n // the container to append the picker\n container: document.body,\n // allow any dates\n dateValidator: undefined\n});\n\nclass DateTimePicker extends Events {\n constructor(options = {}) {\n super();\n const styles = Object.assign(defaults().styles, options.styles);\n this.options = Object.assign(defaults(), options);\n this.options.styles = styles;\n\n // listen to any event\n this.on('*', (evtName, evtData) => {\n if (this.options.el) {\n // if there is a custom element, fire a real dom\n // event on that now\n const event = new CustomEvent(evtName, this, evtData);\n this.options.el.dispatchEvent(event);\n }\n });\n }\n\n // intialize the rom calendar with our default date and\n // style options\n initializeRome(container, validator) {\n const onData = this.onChangeDate.bind(this);\n\n return rome(container, {\n styles: this.options.styles,\n time: false,\n dateValidator: validator,\n initialValue: this.value\n }).on('data', onData);\n }\n\n // called to open the picker\n open() {\n const scrimEl = scrimTemplate(this.options);\n _appendTemplate(document.body, scrimEl);\n _appendTemplate(this.options.container, popupTemplate());\n this.pickerEl = this.options.container.querySelector(`.${prefix}`);\n this.scrimEl = document.body.querySelector(`.${this.options.styles.scrim}`);\n this.amToggleEl = this.$('.c-datepicker__clock--am');\n this.pmToggleEl = this.$('.c-datepicker__clock--pm');\n\n if (!this.value) {\n // TODO hack\n // set/setDate/setTime need refactoring to have single concerns\n // (set: set the value; setDate/setTime rename to renderDate/renderTime\n // and deal with updating the view only).\n // For now this allows us to set the default time using the same quantize\n // rules as setting the date explicitly. Setting this.value meets setTime|Date's\n // expectation that we have a value, and `0` guarantees that we will detect\n this.value = moment(0);\n this.setDate(this.options.default);\n this.setTime(this.options.default);\n } else {\n this.setDate(this.value);\n this.setTime(this.value);\n }\n\n this.initializeRome(this.$(`.${this.options.styles.container}`), this.options.dateValidator);\n this._listenForCloseEvents();\n\n this._show();\n }\n\n close() {\n this._stopListeningForCloseEvents();\n this._hide();\n }\n\n _hide() {\n this.pickerEl.classList.remove('open');\n window.setTimeout(() => {\n this.options.container.removeChild(this.pickerEl);\n document.body.removeChild(this.scrimEl);\n this.trigger('close');\n }, 200);\n return this;\n }\n\n _show() {\n this.delegateEvents();\n // add the animation classes on the next animation tick\n // so that they actually work\n window.requestAnimationFrame(() => {\n this.scrimEl.classList.add(`${this.options.styles.scrim}--shown`);\n this.pickerEl.classList.add(`${prefix}--open`);\n this.trigger('open');\n });\n return this;\n }\n\n _listenForCloseEvents() {\n this._onWindowKeypress = (e) => {\n if (e.which === ESC_KEY) {\n this.close();\n }\n };\n\n window.addEventListener(\"keydown\", this._onWindowKeypress);\n }\n\n _stopListeningForCloseEvents() {\n window.removeEventListener(\"keydown\", this._onWindowKeypress);\n this._closeHandler = null;\n }\n\n delegateEvents() {\n this.$('.js-cancel')\n .addEventListener('click', () => this.clickCancel(), false);\n this.$('.js-ok')\n .addEventListener('click', () => this.clickSubmit(), false);\n\n this.$('.js-date-hours').addEventListener('click', e => this.showHourClock(e), false);\n this.$('.js-date-minutes').addEventListener('click', e => this.showMinuteClock(e), false);\n\n this.$('.js-clock-hours').addEventListener('mouseleave', e => this.mouseOutHourClock(e), false);\n this.$(`.js-clock-hours .${this.options.styles.clockNum}`).forEach((el) => {\n el.addEventListener('click', e => this.clickClickHour(e).showMinuteClock(), false);\n el.addEventListener('mouseenter', e => this.mouseInHourClock(e), false);\n });\n\n this.$('.js-clock-minutes').addEventListener('mouseleave', e => this.mouseOutMinuteClock(e), false);\n this.$(`.js-clock-minutes .${this.options.styles.clockNum}`).forEach(el => {\n el.addEventListener('click', (e) => this.clickClockMinute(e), false);\n el.addEventListener('mouseenter', e => this.mouseInMinuteClock(e), false);\n });\n\n this.$('.c-datepicker__clock--am')\n .addEventListener('click', e => this.clickAm(e), false);\n this.$('.c-datepicker__clock--pm')\n .addEventListener('click', e => this.clickPm(e), false);\n\n this.$('.js-show-calendar')\n .addEventListener('click', e => this.clickShowCalendar(e), false);\n this.$('.js-date-day')\n .addEventListener('click', e => this.clickShowCalendar(e), false);\n this.$('.js-date-month')\n .addEventListener('click', e => this.clickShowCalendar(e), false);\n\n this.$('.js-show-clock')\n .addEventListener('click', e => this.clickShowClock(e), false);\n\n this.scrimEl.addEventListener('click', () => this.close(), false);\n\n return this;\n }\n\n clickSubmit() {\n this.close();\n this.trigger('submit', this.value, this);\n return this;\n }\n\n clickCancel() {\n this.close();\n this.trigger('cancel', this.value, this);\n return this;\n }\n\n clickClickHour(e) {\n const newValue = moment(this.value);\n let number = parseInt(e.currentTarget.getAttribute('data-number'), 10);\n if (number === 0 && this.meridiem === 'pm') {\n number = 12;\n } else if (this.meridiem === 'pm') {\n number += 12;\n }\n\n newValue.hour(number);\n this.set(newValue);\n return this;\n }\n\n clickClockMinute(e) {\n const newValue = moment(this.value);\n let number = parseInt(e.currentTarget.getAttribute('data-number'), 10);\n\n newValue.minute(number);\n this.set(newValue);\n return this;\n }\n\n onChangeDate(dateString) {\n const newValue = moment(this.value);\n const [year, month, date] = dateString.split('-');\n newValue.set({ year, month: month - 1, date });\n\n this.set(newValue);\n return this;\n }\n\n mouseInHourClock() {\n const active = this.$(`.js-clock-hours .${this.options.styles.clockNum}--active`);\n\n if (active) {\n active.classList.add('hide-hand');\n }\n }\n\n mouseInMinuteClock() {\n const active = this.$(`.js-clock-minutes .${this.options.styles.clockNum}--active`);\n\n if (active) {\n active.classList.add('hide-hand');\n }\n }\n\n mouseOutHourClock() {\n const hideHand = this.$(`.js-clock-hours .${this.options.styles.clockNum}--active.hide-hand`);\n\n if (hideHand) {\n hideHand.classList.remove('hide-hand');\n }\n }\n\n mouseOutMinuteClock() {\n const hideHand = this.$(`.js-clock-minutes .${this.options.styles.clockNum}--active.hide-hand`);\n\n if (hideHand) {\n hideHand.classList.remove('hide-hand');\n }\n }\n\n clickAm() {\n const newValue = moment(this.value);\n if (this.meridiem === 'pm') {\n this.meridiem = 'am';\n newValue.hour(newValue.hour() - 12);\n }\n this.set(newValue);\n return this;\n }\n\n clickPm() {\n const newValue = moment(this.value);\n if (this.meridiem === 'am') {\n this.meridiem = 'pm';\n newValue.hour(newValue.hour() + 12);\n }\n this.set(newValue);\n return this;\n }\n\n showHourClock() {\n this.clickShowClock();\n this.$('.js-clock-hours').classList.add('active');\n this.$('.js-clock-minutes').classList.remove('active');\n this.$('.js-date-hours').classList.add('active');\n this.$('.js-date-minutes').classList.remove('active');\n }\n\n showMinuteClock() {\n this.clickShowClock();\n this.$('.js-clock-hours').classList.remove('active');\n this.$('.js-clock-minutes').classList.add('active');\n this.$('.js-date-hours').classList.remove('active');\n this.$('.js-date-minutes').classList.add('active');\n }\n\n clickShowCalendar() {\n this.$('.js-show-calendar').classList.add('is-selected');\n this.$('.js-show-clock').classList.remove('is-selected');\n }\n\n clickShowClock() {\n this.$('.js-show-clock').classList.add('is-selected');\n this.$('.js-show-calendar').classList.remove('is-selected');\n }\n\n data(val) {\n console.warn(`MaterialDatetimePicker#data is deprecated and will be removed in a future release. Please use get or set.`)\n return (val ? this.set(val) : this.value);\n }\n\n get() {\n return moment(this.value);\n }\n\n // update the picker's date/time value\n // value: moment\n // silent: if true, do not fire any events on change\n set(value, { silent = false } = {}) {\n const m = moment(value);\n\n // maintain a list of change events to fire all at once later\n const evts = [];\n if (m.date() !== this.value.date()\n || m.month() !== this.value.month()\n || m.year() !== this.value.year()\n ) {\n this.setDate(m);\n evts.push('change:date');\n }\n\n if (m.hour() !== this.value.hour()\n || m.minutes() !== this.value.minutes()\n ) {\n this.setTime(m);\n evts.push('change:time');\n }\n\n if (this.options.el) {\n // if there is an element to fire events on\n if (this.options.el.tagName === 'INPUT') {\n // and it is an input element then set the value\n this.options.el.value = m.format(this.options.format);\n } else {\n // or any other element set a data-value attribute\n this.options.el.setAttribute('data-value', m.format(this.options.format));\n }\n }\n if (evts.length > 0 && !silent) {\n // fire all the events we've collected\n this.trigger(['change', ...evts].join(' '), this.value, this);\n }\n }\n\n // set the value and header elements to `date`\n // the calendar will be updated automatically\n // by rome when clicked\n setDate(date) {\n const m = moment(date);\n const month = m.format('MMM');\n const day = m.format('Do');\n const dayOfWeek = m.format('dddd');\n const year = m.format('YYYY');\n\n this.$('.js-day').innerText = dayOfWeek;\n this.$('.js-date-month').innerText = (`${month} ${year}`);\n this.$('.js-date-day').innerText = day;\n this.value.year(m.year());\n this.value.month(m.month());\n this.value.date(m.date());\n return this;\n }\n\n // set the value and header elements to `time`\n // also update the hands of the clock\n setTime(time) {\n const m = moment(time);\n const minuteAsInt = Math.round(parseInt(m.format('mm'), 10) / 5) * 5;\n m.minutes(minuteAsInt);\n\n const hour = m.format('HH');\n const minutes = m.format('mm');\n const hourAsInt = parseInt(hour, 10) % 12;\n\n const oldActiveHours = this.$(`.js-clock-hours .${this.options.styles.clockNum}--active`);\n const oldActiveMinutes = this.$(`.js-clock-minutes .${this.options.styles.clockNum}--active`);\n\n this.$('.js-date-hours').innerText = hour;\n this.$('.js-date-minutes').innerText = minutes;\n\n if (oldActiveHours) {\n oldActiveHours.classList.remove(`${this.options.styles.clockNum}--active`);\n }\n\n if (oldActiveMinutes) {\n oldActiveMinutes.classList.remove(`${this.options.styles.clockNum}--active`);\n }\n\n this.$(`.js-clock-hours .${this.options.styles.clockNum}[data-number=\"${hourAsInt}\"]`)\n .classList.add(`${this.options.styles.clockNum}--active`);\n this.$(`.js-clock-minutes .${this.options.styles.clockNum}[data-number=\"${minuteAsInt}\"]`)\n .classList.add(`${this.options.styles.clockNum}--active`);\n\n this.value.hours(m.hours());\n this.value.minutes(m.minutes());\n this.meridiem = this.value.format('a');\n\n if (this.meridiem === 'pm') {\n this.amToggleEl.removeAttribute('checked');\n this.pmToggleEl.setAttribute('checked', 'checked');\n this.amToggleEl.parentElement.classList.remove('c-datepicker__toggle--checked');\n this.pmToggleEl.parentElement.classList.add('c-datepicker__toggle--checked');\n } else {\n this.pmToggleEl.removeAttribute('checked');\n this.amToggleEl.setAttribute('checked', 'checked');\n this.pmToggleEl.parentElement.classList.remove('c-datepicker__toggle--checked');\n this.amToggleEl.parentElement.classList.add('c-datepicker__toggle--checked');\n }\n return this;\n }\n\n $(selector) {\n const els = this.pickerEl.querySelectorAll(selector);\n return els.length > 1 ? [...els] : els[0];\n }\n}\n\nexport default DateTimePicker;\n\nfunction _appendTemplate(parent, template) {\n const tempEl = document.createElement('div');\n tempEl.innerHTML = template.trim();\n parent.appendChild(tempEl.firstChild);\n return this;\n}\n"],"names":["styles","scrim","Events","_events","eventName","evtData","split","forEach","evtName","evt","fn","call","scope","push","filter","func","off","on","ESC_KEY","prefix","defaults","moment","startOf","document","body","undefined","DateTimePicker","options","Object","assign","el","event","CustomEvent","dispatchEvent","container","validator","onData","onChangeDate","bind","rome","value","scrimEl","scrimTemplate","popupTemplate","pickerEl","querySelector","amToggleEl","$","pmToggleEl","setDate","default","setTime","initializeRome","dateValidator","_listenForCloseEvents","_show","_stopListeningForCloseEvents","_hide","classList","remove","setTimeout","removeChild","trigger","delegateEvents","requestAnimationFrame","add","_onWindowKeypress","e","which","close","addEventListener","removeEventListener","_closeHandler","clickCancel","clickSubmit","showHourClock","showMinuteClock","mouseOutHourClock","clockNum","clickClickHour","mouseInHourClock","mouseOutMinuteClock","clickClockMinute","mouseInMinuteClock","clickAm","clickPm","clickShowCalendar","clickShowClock","newValue","number","parseInt","currentTarget","getAttribute","meridiem","hour","set","minute","dateString","year","month","date","active","hideHand","val","warn","silent","m","evts","minutes","tagName","format","setAttribute","length","join","day","dayOfWeek","innerText","time","minuteAsInt","Math","round","hourAsInt","oldActiveHours","oldActiveMinutes","hours","removeAttribute","parentElement","selector","els","querySelectorAll","_appendTemplate","parent","template","tempEl","createElement","innerHTML","trim","appendChild","firstChild"],"mappings":"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"} -------------------------------------------------------------------------------- /lib/js/__tests__/helpers/dom-polyfills.js: -------------------------------------------------------------------------------- 1 | // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 2 | // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 3 | 4 | // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel 5 | 6 | // MIT license 7 | 8 | (function() { 9 | var lastTime = 0; 10 | var vendors = ['ms', 'moz', 'webkit', 'o']; 11 | for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 12 | window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; 13 | window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 14 | || window[vendors[x]+'CancelRequestAnimationFrame']; 15 | } 16 | 17 | if (!window.requestAnimationFrame) 18 | window.requestAnimationFrame = function(callback, element) { 19 | var currTime = new Date().getTime(); 20 | var timeToCall = Math.max(0, 16 - (currTime - lastTime)); 21 | var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 22 | timeToCall); 23 | lastTime = currTime + timeToCall; 24 | return id; 25 | }; 26 | 27 | if (!window.cancelAnimationFrame) 28 | window.cancelAnimationFrame = function(id) { 29 | clearTimeout(id); 30 | }; 31 | }()); -------------------------------------------------------------------------------- /lib/js/__tests__/helpers/empty-module.js: -------------------------------------------------------------------------------- 1 | // An empty JS module used to stub out CSS imports in testing -------------------------------------------------------------------------------- /lib/js/__tests__/helpers/open-picker.js: -------------------------------------------------------------------------------- 1 | import delay from "delay"; 2 | import MaterialDatetimePicker from "../../"; 3 | 4 | // return a Promise to create a picker. open it, and have it interactive in the DOM 5 | // the delay is to wait for the open transition. 6 | export default async function openPicker(options) { 7 | const picker = new MaterialDatetimePicker(options); 8 | picker.open(); 9 | await delay(300); 10 | return picker; 11 | } 12 | -------------------------------------------------------------------------------- /lib/js/__tests__/index-test.js: -------------------------------------------------------------------------------- 1 | import delay from "delay"; 2 | import moment from "moment"; 3 | 4 | import openPicker from "./helpers/open-picker"; 5 | import MaterialDatetimePicker from "../"; 6 | 7 | const $ = document.querySelector.bind(document); 8 | 9 | afterEach(() => { 10 | document.body.innerHTML = ""; 11 | }) 12 | 13 | test("opening the picker ads backdrop and picker elements to the dom", () => { 14 | const picker = new MaterialDatetimePicker(); 15 | picker.open(); 16 | 17 | const $backdrop = $(".c-scrim"); 18 | const $picker = $(".c-datepicker"); 19 | 20 | expect($picker).not.toBeNull(); 21 | expect($backdrop).not.toBeNull(); 22 | }); 23 | 24 | test("closing the picker removes elements from the dom", async () => { 25 | const picker = await openPicker(); 26 | picker.close(); 27 | await delay(300); 28 | 29 | const $backdrop = $(".c-scrim"); 30 | const $picker = $(".c-datepicker"); 31 | 32 | expect($picker).toBeNull(); 33 | expect($backdrop).toBeNull(); 34 | }); 35 | 36 | test("the picker closes when the escape key is pressed", async () => { 37 | const picker = await openPicker(); 38 | 39 | const event = new window.KeyboardEvent('keydown', { which: 27, keyCode: 27 }); 40 | window.dispatchEvent(event); 41 | 42 | await delay(300); 43 | const $picker = $(".c-datepicker"); 44 | expect($picker).toBeNull(); 45 | }); 46 | 47 | test("the picker closes when the scrim element is clicked", async () => { 48 | const picker = await openPicker(); 49 | 50 | const event = new MouseEvent('click'); 51 | $(".c-scrim").dispatchEvent(event); 52 | 53 | await delay(300); 54 | const $picker = $(".c-datepicker"); 55 | expect($picker).toBeNull(); 56 | }); 57 | 58 | test("opening the picker with a default time", async () => { 59 | // time divides 5 minutes; set exactly 60 | const time = "2017-02-01T17:30:00.000Z"; 61 | const picker = await openPicker({ default: moment(time) }); 62 | expect(picker.data().toISOString()).toEqual(time); 63 | }); 64 | 65 | // test("opening the picker with a default time rounds down to the nearest 5 minute interval", async () => { 66 | // const time = "2017-02-01T17:31:02.003Z"; 67 | // const picker = await openPicker({ default: moment(time) }); 68 | // expect(picker.data().toISOString()).toEqual("2017-02-01T17:30:00.000Z"); 69 | // }); 70 | 71 | test("opening the picker with a default time rounds up to the nearest 5 minute interval", async () => { 72 | const time = "2017-02-01T17:34:02.003Z"; 73 | const picker = await openPicker({ default: moment(time) }); 74 | expect(picker.data().toISOString()).toEqual("2017-02-01T17:35:00.000Z"); 75 | }); 76 | 77 | // TODO deprecated 78 | test("picker#data() returns the selected date as a `moment` object", async () => { 79 | const startTimestamp = Date.now(); 80 | const picker = await openPicker(); 81 | 82 | expect(+picker.data() - startTimestamp).toBeLessThan(60 * 60 * 10000); // TODO set the time so we can assert on a known value 83 | expect(picker.data()._isAMomentObject).toBe(true); 84 | }) 85 | 86 | test("picker#get returns the selected date as a `moment` object", async () => { 87 | const startTimestamp = Date.now(); 88 | const picker = await openPicker(); 89 | 90 | expect(+picker.get() - startTimestamp).toBeLessThan(60 * 60 * 10000); // TODO set the time so we can assert on a known value 91 | expect(picker.get()._isAMomentObject).toBe(true); 92 | }) 93 | 94 | // TODO deprecated 95 | test("picker#data(momentObject) sets the selected date", async () => { 96 | const startIsoTime = "2017-02-01T18:00:00.000Z"; 97 | const startMoment = moment(startIsoTime); 98 | const picker = await openPicker(); 99 | 100 | picker.set(startMoment); 101 | expect(picker.data().toISOString()).toEqual(startIsoTime); 102 | }) 103 | 104 | test("picker#set(momentObject) sets the selected date", async () => { 105 | // FIXME 17:30 is rounded up to 18:00, which is inconsistent with 106 | // default. Fix: apply the same minute rounding (no hour rounding) to both. 107 | const startIsoTime = "2017-02-01T18:30:00.000Z"; 108 | const startMoment = moment(startIsoTime); 109 | const picker = await openPicker(); 110 | 111 | picker.set(startMoment); 112 | expect(picker.data().toISOString()).toEqual(startIsoTime); 113 | }) 114 | 115 | test("picker#set(DateObject) sets the selected date", async () => { 116 | const startIsoTime = "2017-02-01T18:00:00.000Z"; 117 | const startDate = new Date(startIsoTime); 118 | const picker = await openPicker(); 119 | 120 | picker.set(startDate); 121 | expect(picker.data().toISOString()).toEqual(startIsoTime); 122 | }) 123 | 124 | test("picker#set(isoTimeString) sets the selected date", async () => { 125 | const startIsoTime = "2017-02-01T18:00:00.000Z"; 126 | const picker = await openPicker(); 127 | 128 | picker.set(startIsoTime); 129 | expect(picker.data().toISOString()).toEqual(startIsoTime); 130 | }) 131 | 132 | test("picker#set(timestampInMillis) sets the selected date", async () => { 133 | const startIsoTime = "2017-02-01T18:00:00.000Z"; 134 | const startTimestamp = +(new Date(startIsoTime)); 135 | const picker = await openPicker(); 136 | 137 | picker.set(startTimestamp); 138 | expect(picker.data().toISOString()).toEqual(startIsoTime); 139 | }) 140 | 141 | test("picker#set quanitizes to the nearest 5 minutes", async () => { 142 | const picker = await openPicker(); 143 | 144 | // test round down 145 | picker.set("2017-02-01T18:31:04.941Z"); 146 | expect(picker.data().toISOString()).toEqual( "2017-02-01T18:30:00.000Z"); 147 | 148 | // test round up 149 | picker.set("2017-02-01T18:35:04.941Z"); 150 | expect(picker.data().toISOString()).toEqual( "2017-02-01T18:35:00.000Z"); 151 | }) 152 | -------------------------------------------------------------------------------- /lib/js/events.js: -------------------------------------------------------------------------------- 1 | // 2 | // basic event triggering and listening 3 | // 4 | export default class Events { 5 | constructor() { 6 | this._events = { 7 | '*': [] 8 | }; 9 | } 10 | 11 | trigger(eventName, evtData) { 12 | eventName.split(' ').forEach((evtName) => { 13 | // trigger a global event event 14 | this._events['*'].forEach(evt => evt.fn.call(evt.scope, evtName, evtData)); 15 | // if there are any listeners to this event 16 | // then fire their handlers 17 | if (this._events[evtName]) { 18 | this._events[evtName].forEach((evt) => { 19 | evt.fn.call(evt.scope, evtData); 20 | }); 21 | } 22 | }); 23 | return this; 24 | } 25 | 26 | on(eventName, fn, scope) { 27 | if (!this._events[eventName]) this._events[eventName] = []; 28 | this._events[eventName].push({ 29 | eventName, 30 | fn, 31 | scope: scope || this 32 | }); 33 | return this; 34 | } 35 | 36 | off(eventName, fn) { 37 | if (!this._events[eventName]) return this; 38 | if (!fn) { 39 | this._events[eventName] = []; 40 | } 41 | this._events[eventName] = this._events[eventName].filter(evt => evt.fn !== fn); 42 | return this; 43 | } 44 | 45 | once(eventName, fn, scope) { 46 | const func = () => { 47 | fn.call(scope, eventName, fn, scope); 48 | this.off(eventName, func); 49 | }; 50 | return this.on(eventName, func, scope); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/js/index.js: -------------------------------------------------------------------------------- 1 | import rome from 'rome'; 2 | import moment from 'moment'; 3 | 4 | import popupTemplate from '../template/datepicker.template'; 5 | import scrimTemplate from '../template/scrim.template'; 6 | import Events from './events'; 7 | 8 | import '../scss/material-datetime-picker.scss'; 9 | 10 | const ESC_KEY = 27; 11 | 12 | const prefix = 'c-datepicker'; 13 | const defaults = () => ({ 14 | default: moment().startOf('hour'), 15 | // allow the user to override all the classes 16 | // used for styling the calendar 17 | styles: { 18 | scrim: 'c-scrim', 19 | back: `${prefix}__back`, 20 | container: `${prefix}__calendar`, 21 | date: `${prefix}__date`, 22 | dayBody: `${prefix}__days-body`, 23 | dayBodyElem: `${prefix}__day-body`, 24 | dayConcealed: `${prefix}__day--concealed`, 25 | dayDisabled: `${prefix}__day--disabled`, 26 | dayHead: `${prefix}__days-head`, 27 | dayHeadElem: `${prefix}__day-head`, 28 | dayRow: `${prefix}__days-row`, 29 | dayTable: `${prefix}__days`, 30 | month: `${prefix}__month`, 31 | next: `${prefix}__next`, 32 | positioned: `${prefix}--fixed`, 33 | selectedDay: `${prefix}__day--selected`, 34 | selectedTime: `${prefix}__time--selected`, 35 | time: `${prefix}__time`, 36 | timeList: `${prefix}__time-list`, 37 | timeOption: `${prefix}__time-option`, 38 | clockNum: `${prefix}__clock__num` 39 | }, 40 | // format to display in the input, or set on the element 41 | format: 'DD/MM/YY', 42 | // the container to append the picker 43 | container: document.body, 44 | // allow any dates 45 | dateValidator: undefined 46 | }); 47 | 48 | class DateTimePicker extends Events { 49 | constructor(options = {}) { 50 | super(); 51 | const styles = Object.assign(defaults().styles, options.styles); 52 | this.options = Object.assign(defaults(), options); 53 | this.options.styles = styles; 54 | 55 | // listen to any event 56 | this.on('*', (evtName, evtData) => { 57 | if (this.options.el) { 58 | // if there is a custom element, fire a real dom 59 | // event on that now 60 | const event = new CustomEvent(evtName, this, evtData); 61 | this.options.el.dispatchEvent(event); 62 | } 63 | }); 64 | } 65 | 66 | // intialize the rom calendar with our default date and 67 | // style options 68 | initializeRome(container, validator) { 69 | const onData = this.onChangeDate.bind(this); 70 | 71 | return rome(container, { 72 | styles: this.options.styles, 73 | time: false, 74 | dateValidator: validator, 75 | initialValue: this.value 76 | }).on('data', onData); 77 | } 78 | 79 | // called to open the picker 80 | open() { 81 | const scrimEl = scrimTemplate(this.options); 82 | _appendTemplate(document.body, scrimEl); 83 | _appendTemplate(this.options.container, popupTemplate()); 84 | this.pickerEl = this.options.container.querySelector(`.${prefix}`); 85 | this.scrimEl = document.body.querySelector(`.${this.options.styles.scrim}`); 86 | this.amToggleEl = this.$('.c-datepicker__clock--am'); 87 | this.pmToggleEl = this.$('.c-datepicker__clock--pm'); 88 | 89 | if (!this.value) { 90 | // TODO hack 91 | // set/setDate/setTime need refactoring to have single concerns 92 | // (set: set the value; setDate/setTime rename to renderDate/renderTime 93 | // and deal with updating the view only). 94 | // For now this allows us to set the default time using the same quantize 95 | // rules as setting the date explicitly. Setting this.value meets setTime|Date's 96 | // expectation that we have a value, and `0` guarantees that we will detect 97 | this.value = moment(0); 98 | this.setDate(this.options.default); 99 | this.setTime(this.options.default); 100 | } else { 101 | this.setDate(this.value); 102 | this.setTime(this.value); 103 | } 104 | 105 | this.initializeRome(this.$(`.${this.options.styles.container}`), this.options.dateValidator); 106 | this._listenForCloseEvents(); 107 | 108 | this._show(); 109 | } 110 | 111 | close() { 112 | this._stopListeningForCloseEvents(); 113 | this._hide(); 114 | } 115 | 116 | _hide() { 117 | this.pickerEl.classList.remove('open'); 118 | window.setTimeout(() => { 119 | this.options.container.removeChild(this.pickerEl); 120 | document.body.removeChild(this.scrimEl); 121 | this.trigger('close'); 122 | }, 200); 123 | return this; 124 | } 125 | 126 | _show() { 127 | this.delegateEvents(); 128 | // add the animation classes on the next animation tick 129 | // so that they actually work 130 | window.requestAnimationFrame(() => { 131 | this.scrimEl.classList.add(`${this.options.styles.scrim}--shown`); 132 | this.pickerEl.classList.add(`${prefix}--open`); 133 | this.trigger('open'); 134 | }); 135 | return this; 136 | } 137 | 138 | _listenForCloseEvents() { 139 | this._onWindowKeypress = (e) => { 140 | if (e.which === ESC_KEY) { 141 | this.close(); 142 | } 143 | }; 144 | 145 | window.addEventListener('keydown', this._onWindowKeypress); 146 | } 147 | 148 | _stopListeningForCloseEvents() { 149 | window.removeEventListener('keydown', this._onWindowKeypress); 150 | this._closeHandler = null; 151 | } 152 | 153 | delegateEvents() { 154 | this.$('.js-cancel') 155 | .addEventListener('click', () => this.clickCancel(), false); 156 | this.$('.js-ok') 157 | .addEventListener('click', () => this.clickSubmit(), false); 158 | 159 | this.$('.js-date-hours').addEventListener('click', e => this.showHourClock(e), false); 160 | this.$('.js-date-minutes').addEventListener('click', e => this.showMinuteClock(e), false); 161 | 162 | this.$('.js-clock-hours').addEventListener('mouseleave', e => this.mouseOutHourClock(e), false); 163 | this.$(`.js-clock-hours .${this.options.styles.clockNum}`).forEach((el) => { 164 | el.addEventListener('click', e => this.clickClickHour(e).showMinuteClock(), false); 165 | el.addEventListener('mouseenter', e => this.mouseInHourClock(e), false); 166 | }); 167 | 168 | this.$('.js-clock-minutes').addEventListener('mouseleave', e => this.mouseOutMinuteClock(e), false); 169 | this.$(`.js-clock-minutes .${this.options.styles.clockNum}`).forEach((el) => { 170 | el.addEventListener('click', e => this.clickClockMinute(e), false); 171 | el.addEventListener('mouseenter', e => this.mouseInMinuteClock(e), false); 172 | }); 173 | 174 | this.$('.c-datepicker__clock--am') 175 | .addEventListener('click', e => this.clickAm(e), false); 176 | this.$('.c-datepicker__clock--pm') 177 | .addEventListener('click', e => this.clickPm(e), false); 178 | 179 | this.$('.js-show-calendar') 180 | .addEventListener('click', e => this.clickShowCalendar(e), false); 181 | this.$('.js-date-day') 182 | .addEventListener('click', e => this.clickShowCalendar(e), false); 183 | this.$('.js-date-month') 184 | .addEventListener('click', e => this.clickShowCalendar(e), false); 185 | 186 | this.$('.js-show-clock') 187 | .addEventListener('click', e => this.clickShowClock(e), false); 188 | 189 | this.scrimEl.addEventListener('click', () => this.close(), false); 190 | 191 | return this; 192 | } 193 | 194 | clickSubmit() { 195 | this.close(); 196 | this.trigger('submit', this.value, this); 197 | return this; 198 | } 199 | 200 | clickCancel() { 201 | this.close(); 202 | this.trigger('cancel', this.value, this); 203 | return this; 204 | } 205 | 206 | clickClickHour(e) { 207 | const newValue = moment(this.value); 208 | let number = parseInt(e.currentTarget.getAttribute('data-number'), 10); 209 | if (number === 0 && this.meridiem === 'pm') { 210 | number = 12; 211 | } else if (this.meridiem === 'pm') { 212 | number += 12; 213 | } 214 | 215 | newValue.hour(number); 216 | this.set(newValue); 217 | return this; 218 | } 219 | 220 | clickClockMinute(e) { 221 | const newValue = moment(this.value); 222 | const number = parseInt(e.currentTarget.getAttribute('data-number'), 10); 223 | 224 | newValue.minute(number); 225 | this.set(newValue); 226 | return this; 227 | } 228 | 229 | onChangeDate(dateString) { 230 | const newValue = moment(this.value); 231 | const [year, month, date] = dateString.split('-'); 232 | newValue.set({ year, month: month - 1, date }); 233 | 234 | this.set(newValue); 235 | return this; 236 | } 237 | 238 | mouseInHourClock() { 239 | const active = this.$(`.js-clock-hours .${this.options.styles.clockNum}--active`); 240 | 241 | if (active) { 242 | active.classList.add('hide-hand'); 243 | } 244 | } 245 | 246 | mouseInMinuteClock() { 247 | const active = this.$(`.js-clock-minutes .${this.options.styles.clockNum}--active`); 248 | 249 | if (active) { 250 | active.classList.add('hide-hand'); 251 | } 252 | } 253 | 254 | mouseOutHourClock() { 255 | const hideHand = this.$(`.js-clock-hours .${this.options.styles.clockNum}--active.hide-hand`); 256 | 257 | if (hideHand) { 258 | hideHand.classList.remove('hide-hand'); 259 | } 260 | } 261 | 262 | mouseOutMinuteClock() { 263 | const hideHand = this.$(`.js-clock-minutes .${this.options.styles.clockNum}--active.hide-hand`); 264 | 265 | if (hideHand) { 266 | hideHand.classList.remove('hide-hand'); 267 | } 268 | } 269 | 270 | clickAm() { 271 | const newValue = moment(this.value); 272 | if (this.meridiem === 'pm') { 273 | this.meridiem = 'am'; 274 | newValue.hour(newValue.hour() - 12); 275 | } 276 | this.set(newValue); 277 | return this; 278 | } 279 | 280 | clickPm() { 281 | const newValue = moment(this.value); 282 | if (this.meridiem === 'am') { 283 | this.meridiem = 'pm'; 284 | newValue.hour(newValue.hour() + 12); 285 | } 286 | this.set(newValue); 287 | return this; 288 | } 289 | 290 | showHourClock() { 291 | this.clickShowClock(); 292 | this.$('.js-clock-hours').classList.add('active'); 293 | this.$('.js-clock-minutes').classList.remove('active'); 294 | this.$('.js-date-hours').classList.add('active'); 295 | this.$('.js-date-minutes').classList.remove('active'); 296 | } 297 | 298 | showMinuteClock() { 299 | this.clickShowClock(); 300 | this.$('.js-clock-hours').classList.remove('active'); 301 | this.$('.js-clock-minutes').classList.add('active'); 302 | this.$('.js-date-hours').classList.remove('active'); 303 | this.$('.js-date-minutes').classList.add('active'); 304 | } 305 | 306 | clickShowCalendar() { 307 | this.$('.js-show-calendar').classList.add('is-selected'); 308 | this.$('.js-show-clock').classList.remove('is-selected'); 309 | } 310 | 311 | clickShowClock() { 312 | this.$('.js-show-clock').classList.add('is-selected'); 313 | this.$('.js-show-calendar').classList.remove('is-selected'); 314 | } 315 | 316 | data(val) { 317 | console.warn('MaterialDatetimePicker#data is deprecated and will be removed in a future release. Please use get or set.'); 318 | return (val ? this.set(val) : this.value); 319 | } 320 | 321 | get() { 322 | return moment(this.value); 323 | } 324 | 325 | // update the picker's date/time value 326 | // value: moment 327 | // silent: if true, do not fire any events on change 328 | set(value, { silent = false } = {}) { 329 | const m = moment(value); 330 | 331 | // maintain a list of change events to fire all at once later 332 | const evts = []; 333 | if (m.date() !== this.value.date() 334 | || m.month() !== this.value.month() 335 | || m.year() !== this.value.year() 336 | ) { 337 | this.setDate(m); 338 | evts.push('change:date'); 339 | } 340 | 341 | if (m.hour() !== this.value.hour() 342 | || m.minutes() !== this.value.minutes() 343 | ) { 344 | this.setTime(m); 345 | evts.push('change:time'); 346 | } 347 | 348 | if (this.options.el) { 349 | // if there is an element to fire events on 350 | if (this.options.el.tagName === 'INPUT') { 351 | // and it is an input element then set the value 352 | this.options.el.value = m.format(this.options.format); 353 | } else { 354 | // or any other element set a data-value attribute 355 | this.options.el.setAttribute('data-value', m.format(this.options.format)); 356 | } 357 | } 358 | if (evts.length > 0 && !silent) { 359 | // fire all the events we've collected 360 | this.trigger(['change', ...evts].join(' '), this.value, this); 361 | } 362 | } 363 | 364 | // set the value and header elements to `date` 365 | // the calendar will be updated automatically 366 | // by rome when clicked 367 | setDate(date) { 368 | const m = moment(date); 369 | const month = m.format('MMM'); 370 | const day = m.format('Do'); 371 | const dayOfWeek = m.format('dddd'); 372 | const year = m.format('YYYY'); 373 | 374 | this.$('.js-day').innerText = dayOfWeek; 375 | this.$('.js-date-month').innerText = (`${month} ${year}`); 376 | this.$('.js-date-day').innerText = day; 377 | this.value.year(m.year()); 378 | this.value.month(m.month()); 379 | this.value.date(m.date()); 380 | return this; 381 | } 382 | 383 | // set the value and header elements to `time` 384 | // also update the hands of the clock 385 | setTime(time) { 386 | const m = moment(time); 387 | const minuteAsInt = Math.round(parseInt(m.format('mm'), 10) / 5) * 5; 388 | m.minutes(minuteAsInt); 389 | 390 | const hour = m.format('HH'); 391 | const minutes = m.format('mm'); 392 | const hourAsInt = parseInt(hour, 10) % 12; 393 | 394 | const oldActiveHours = this.$(`.js-clock-hours .${this.options.styles.clockNum}--active`); 395 | const oldActiveMinutes = this.$(`.js-clock-minutes .${this.options.styles.clockNum}--active`); 396 | 397 | this.$('.js-date-hours').innerText = hour; 398 | this.$('.js-date-minutes').innerText = minutes; 399 | 400 | if (oldActiveHours) { 401 | oldActiveHours.classList.remove(`${this.options.styles.clockNum}--active`); 402 | } 403 | 404 | if (oldActiveMinutes) { 405 | oldActiveMinutes.classList.remove(`${this.options.styles.clockNum}--active`); 406 | } 407 | 408 | this.$(`.js-clock-hours .${this.options.styles.clockNum}[data-number="${hourAsInt}"]`) 409 | .classList.add(`${this.options.styles.clockNum}--active`); 410 | this.$(`.js-clock-minutes .${this.options.styles.clockNum}[data-number="${minuteAsInt}"]`) 411 | .classList.add(`${this.options.styles.clockNum}--active`); 412 | 413 | this.value.hours(m.hours()); 414 | this.value.minutes(m.minutes()); 415 | this.meridiem = this.value.format('a'); 416 | 417 | if (this.meridiem === 'pm') { 418 | this.amToggleEl.removeAttribute('checked'); 419 | this.pmToggleEl.setAttribute('checked', 'checked'); 420 | this.amToggleEl.parentElement.classList.remove('c-datepicker__toggle--checked'); 421 | this.pmToggleEl.parentElement.classList.add('c-datepicker__toggle--checked'); 422 | } else { 423 | this.pmToggleEl.removeAttribute('checked'); 424 | this.amToggleEl.setAttribute('checked', 'checked'); 425 | this.pmToggleEl.parentElement.classList.remove('c-datepicker__toggle--checked'); 426 | this.amToggleEl.parentElement.classList.add('c-datepicker__toggle--checked'); 427 | } 428 | return this; 429 | } 430 | 431 | $(selector) { 432 | const els = this.pickerEl.querySelectorAll(selector); 433 | return els.length > 1 ? [...els] : els[0]; 434 | } 435 | } 436 | 437 | export default DateTimePicker; 438 | 439 | function _appendTemplate(parent, template) { 440 | const tempEl = document.createElement('div'); 441 | tempEl.innerHTML = template.trim(); 442 | parent.appendChild(tempEl.firstChild); 443 | return this; 444 | } 445 | -------------------------------------------------------------------------------- /lib/scss/material-datetime-picker.scss: -------------------------------------------------------------------------------- 1 | $lowlight: #0097a7 !default; 2 | $primary: #00bcd4 !default; 3 | 4 | .c-scrim { 5 | position: fixed; 6 | left: 0; 7 | right: 0; 8 | top: 0; 9 | bottom: 0; 10 | background-color: rgba(0, 0, 0, 0.541176); 11 | opacity: 0; 12 | transition: 200ms ease opacity; 13 | will-change: opacity; 14 | 15 | &--shown { 16 | opacity: 1; 17 | } 18 | } 19 | 20 | .c-datepicker { 21 | min-height: 610px; 22 | position: fixed; 23 | left: 50%; 24 | top: 45%; 25 | transform: translate(-50%, -50%); 26 | background: white; 27 | border: 0; 28 | width: 300px; 29 | text-align: center; 30 | -webkit-tap-highlight-color: rgba(0,0,0,0); 31 | box-shadow: 0 14px 45px rgba(0, 0, 0, 0.25), 0 10px 18px rgba(0, 0, 0, 0.22); 32 | border-radius: 2px; 33 | opacity: 0; 34 | will-change: opacity; 35 | transition: 200ms ease-in-out opacity, 200ms ease-in-out top; 36 | 37 | &--open { 38 | opacity: 1; 39 | top: 50%; 40 | } 41 | } 42 | 43 | .c-datepicker--horizontal { 44 | 45 | } 46 | 47 | .c-datepicker__header { 48 | position: relative; 49 | } 50 | 51 | .c-datepicker__header-day { 52 | height: 32px; 53 | background: $lowlight; 54 | color: white; 55 | line-height: 32px; 56 | font-size: 12px; 57 | font-weight: 200; 58 | letter-spacing: 0.3px; 59 | } 60 | 61 | .c-datepicker__header::after { 62 | content: ""; 63 | display: table; 64 | clear: both; 65 | } 66 | 67 | .c-datepicker__header-date { 68 | background: $primary; 69 | height: 150px; 70 | padding: 16px 0; 71 | } 72 | 73 | .c-datepicker__month { 74 | } 75 | 76 | .rd-month-label { 77 | height: 56px; 78 | line-height: 56px; 79 | font-size: 14px; 80 | font-weight: 800; 81 | } 82 | 83 | .c-datepicker__back, .c-datepicker__next, .c-datepicker__toggle { 84 | position: absolute; 85 | border: 0; 86 | background: white; 87 | font-family: 'Material Icons'; 88 | text-rendering: optimizeLegibility; 89 | font-feature-settings: "liga" 1; 90 | font-style: normal; 91 | text-transform: none; 92 | line-height: 1; 93 | font-size: 24px; 94 | width: 56px; 95 | height: 56px; 96 | display: inline-block; 97 | overflow: hidden; 98 | -webkit-font-smoothing: antialiased; 99 | cursor: pointer; 100 | 101 | &:focus { 102 | outline: 0; 103 | } 104 | } 105 | 106 | .c-datepicker__back { 107 | left: 0; 108 | } 109 | 110 | .c-datepicker__next { 111 | right: 0; 112 | } 113 | 114 | .c-datepicker__back:before { 115 | content: 'chevron_left'; 116 | } 117 | 118 | .c-datepicker__next:after { 119 | content: 'chevron_right'; 120 | } 121 | 122 | .c-datepicker--show-time:after { 123 | content: 'access_time'; 124 | color: white; 125 | visibility: visible; 126 | } 127 | 128 | .c-datepicker--show-calendar:after { 129 | content: 'grid_on'; 130 | color: white; 131 | visibility: visible; 132 | } 133 | 134 | .c-datepicker__header-date span { 135 | display: block; 136 | color: white; 137 | margin: 0; 138 | transition: opacity 100ms ease-in-out; 139 | } 140 | 141 | .c-datepicker__header-date__month { 142 | cursor: pointer; 143 | font-size: 24px; 144 | opacity: 0.6; 145 | } 146 | 147 | .c-datepicker__header-date__day { 148 | cursor: pointer; 149 | font-size: 64px; 150 | opacity: 0.6; 151 | } 152 | 153 | .c-datepicker__header-date__time { 154 | font-size: 25px; 155 | opacity: 0.6; 156 | 157 | > span { 158 | display: inline-block; 159 | } 160 | } 161 | 162 | .c-datepicker__header-date__hours, .c-datepicker__header-date__minutes { 163 | cursor: pointer; 164 | } 165 | 166 | .c-datepicker--show-time.is-selected ~ .c-datepicker__header .c-datepicker__header-date__time { 167 | opacity: 1; 168 | 169 | .c-datepicker__header-date__hours, .c-datepicker__header-date__minutes { 170 | opacity: .6; 171 | &.active { 172 | opacity: 1; 173 | } 174 | } 175 | } 176 | 177 | .c-datepicker--show-calendar.is-selected { 178 | ~ .c-datepicker__header { 179 | .c-datepicker__header-date__month, .c-datepicker__header-date__day { 180 | opacity: 1 181 | } 182 | } 183 | } 184 | 185 | .modal-btns { 186 | padding: 20px; 187 | position: absolute; 188 | bottom: 0; 189 | right: 0; 190 | } 191 | 192 | .c-datepicker__day-body { 193 | font-size: 12px; 194 | color: rgba(0, 0, 0, 0.8); 195 | width: 36px; 196 | height: 36px; 197 | cursor: pointer; 198 | position: relative; 199 | 200 | &:hover { 201 | /* color: white; */ 202 | } 203 | } 204 | 205 | .c-datepicker__day--selected::after { 206 | content: ""; 207 | position: absolute; 208 | left: 50%; 209 | top: 50%; 210 | width: 35px; 211 | height: 35px; 212 | border-radius: 50%; 213 | transform: translate(-50%, -50%); 214 | background: rgba(0,0,0,0.05); 215 | } 216 | 217 | .c-datepicker__day-body:hover { 218 | 219 | } 220 | 221 | .c-datepicker__day-head { 222 | color: rgba(0,0,0,0.54); 223 | font-size: 12px; 224 | height: 36px; 225 | } 226 | 227 | .c-datepicker__day-head, c-datepicker__day-body { 228 | -webkit-tap-highlight-color: rgba(0,0,0,0); 229 | } 230 | 231 | .modal-btns { 232 | float: right; 233 | } 234 | 235 | .c-btn { 236 | display: inline-block; 237 | min-width: 56px; 238 | cursor: pointer; 239 | } 240 | 241 | .rd-day-prev-month { 242 | opacity: 0.1; 243 | pointer-events: none; 244 | } 245 | 246 | .rd-day-next-month { 247 | opacity: 0.1; 248 | pointer-events: none; 249 | } 250 | 251 | .c-datepicker__calendar { 252 | height: 300px; 253 | } 254 | 255 | .c-datepicker__date { 256 | position: absolute; 257 | left: 0; 258 | right: 0; 259 | } 260 | 261 | .c-datepicker__days { 262 | margin: 10px 20px; 263 | } 264 | 265 | .c-datepicker__header-toggle { 266 | position: absolute; 267 | top: 50%; 268 | color: white; 269 | cursor: pointer; 270 | 271 | i { 272 | font-size: 26px; 273 | } 274 | } 275 | 276 | .c-datepicker__header-toggle--left { 277 | left: 20px; 278 | } 279 | 280 | .c-datepicker__header-toggle--right { 281 | right: 20px; 282 | } 283 | 284 | .c-datepicker__header-toggle--inactive { 285 | opacity: 0.2; 286 | } 287 | 288 | .c-datepicker__toggle { 289 | top: 170px; 290 | width: 36px; 291 | height: 30px; 292 | visibility: hidden; 293 | opacity: 0.5; 294 | z-index: 1; 295 | transition: opacity 200ms ease-in-out; 296 | } 297 | 298 | .c-datepicker__toggle--right { 299 | right: 10px; 300 | } 301 | 302 | .c-datepicker__toggle--left { 303 | left: 10px; 304 | } 305 | 306 | .c-datepicker__toggle.is-selected { 307 | opacity: 1; 308 | } 309 | 310 | .c-datepicker--show-time.is-selected ~ .c-datepicker__calendar { 311 | display: none; 312 | } 313 | 314 | .c-datepicker--show-calendar.is-selected ~ .c-datepicker__clock { 315 | display: none; 316 | } 317 | 318 | @mixin putOnCircle( 319 | $nb-items, //Number of items 320 | $circle-size, //Parent size 321 | $item-size //Item size 322 | ) { 323 | $half-item: $item-size / 2; 324 | $half-parent: $circle-size / 2; 325 | 326 | position: relative; /* [1] */ 327 | width: $circle-size; 328 | height: $circle-size; 329 | padding: 0; 330 | border-radius: 50%; 331 | list-style: none; /* [2] */ 332 | 333 | .c-datepicker__clock__num { 334 | display: block; 335 | position: absolute; 336 | top: 50%; 337 | left: 50%; 338 | width: $item-size; 339 | height: $item-size; 340 | margin: -$half-item; 341 | z-index: 98; 342 | 343 | $angle: 360 / $nb-items; 344 | $rot: 0; 345 | @for $i from 1 to $nb-items+1 { 346 | 347 | &:nth-of-type(#{$i}) { 348 | transform: rotate(#{$rot}deg) translate($half-parent) rotate(-#{$rot}deg); 349 | } 350 | 351 | &:nth-of-type(#{$i}) { 352 | &.c-datepicker__clock__num--active:not(.hide-hand) { 353 | ~ .c-datepicker__clock-hands { 354 | $handRot: $rot + 270; 355 | transform: translate(-50%, -50%) rotate(#{$handRot}deg); 356 | .c-datepicker__hour-hand { 357 | opacity: 1; 358 | background: $primary; 359 | } 360 | } 361 | } 362 | &:hover { 363 | ~ .c-datepicker__clock-hands { 364 | $handRot: $rot + 270; 365 | transform: translate(-50%, -50%) rotate(#{$handRot}deg); 366 | .c-datepicker__hour-hand { 367 | opacity: 1; 368 | background: $primary 369 | } 370 | } 371 | } 372 | } 373 | $rot: $rot + $angle; 374 | } 375 | } 376 | } 377 | 378 | 379 | .c-datepicker__clock { 380 | @include putOnCircle(12, 200px, 50px); 381 | font-size: 14px; 382 | line-height: 50px; 383 | padding: 160px 0 20px 0; 384 | margin: 0 auto; 385 | 386 | &::before { 387 | content: ""; 388 | position: absolute; 389 | top: 70px; 390 | left: -20px; 391 | width: 240px; 392 | height: 240px; 393 | background: rgba(0, 0, 0, 0.05); 394 | border-radius: 50%; 395 | } 396 | } 397 | 398 | .u-hover-ball-effect { 399 | position: relative; 400 | cursor: pointer; 401 | 402 | &:before { 403 | content: ""; 404 | position: absolute; 405 | left: 50%; 406 | top: 50%; 407 | width: 0%; 408 | height: 0%; 409 | border-radius: 50%; 410 | transform: translate(-50%, -50%); 411 | transition: 412 | width 100ms ease-in-out, 413 | height 100ms ease-in-out 414 | } 415 | &:hover { 416 | color: white; 417 | &:before { 418 | background: $primary; 419 | width: 35px; 420 | height: 35px; 421 | z-index: -1; 422 | } 423 | } 424 | } 425 | 426 | 427 | 428 | .c-datepicker__day-body, .c-datepicker__clock__num { 429 | @extend .u-hover-ball-effect; 430 | 431 | &--active:not(.hide-hand) { 432 | color: white; 433 | &:before { 434 | background: $primary; 435 | width: 35px; 436 | height: 35px; 437 | z-index: -1; 438 | } 439 | } 440 | } 441 | 442 | .c-datepicker__clock-hands { 443 | position: absolute; 444 | left: 50%; 445 | top: 50%; 446 | transform: translate(-50%, -50%) rotate(180deg); 447 | width: 10px; 448 | height: 10px; 449 | border-radius: 50%; 450 | background: $lowlight; 451 | } 452 | 453 | .c-datepicker__hour-hand { 454 | position: absolute; 455 | opacity: 0; 456 | height: 78px; 457 | width: 2px; 458 | background: $primary; 459 | left: 4px; 460 | top: 10px; 461 | } 462 | 463 | .c-datepicker__clock__minutes { 464 | display: none; 465 | height: 200px; 466 | margin: -69px 0 0 0; 467 | width: 200px; 468 | display: none; 469 | &.active { 470 | display: block; 471 | } 472 | } 473 | 474 | .c-datepicker__clock__hours { 475 | height: 200px; 476 | margin: -69px 0 0 0; 477 | width: 200px; 478 | display: none; 479 | 480 | &.active { 481 | display: block; 482 | } 483 | } 484 | 485 | .c-datepicker__mask { 486 | &:after { 487 | content: ' '; 488 | width: 156px; 489 | height: 70px; 490 | display: block; 491 | position: absolute; 492 | top: 32px; 493 | left: 0; 494 | margin-left: -13px; 495 | } 496 | &:before { 497 | content: ' '; 498 | width: 75px; 499 | height: 158px; 500 | display: block; 501 | position: absolute; 502 | top: 6px; 503 | left: 28px; 504 | margin-top: -18px; 505 | } 506 | width: 127px; 507 | height: 132px; 508 | position: absolute; 509 | top: 122px; 510 | left: 37px; 511 | z-index: 99; 512 | } 513 | 514 | .c-datepicker__clock--show-minutes { 515 | .c-datepicker__clock__minutes { 516 | visibility: visible; 517 | } 518 | .c-datepicker__clock__hours { 519 | visibility: hidden; 520 | } 521 | } 522 | 523 | .c-datepicker__clock--show-hours { 524 | .c-datepicker__clock__minutes { 525 | visibility: hidden; 526 | } 527 | .c-datepicker__clock__hours { 528 | visibility: visible; 529 | } 530 | } 531 | 532 | .c-datepicker__clock__am-pm-toggle { 533 | position: absolute; 534 | top: 0; 535 | left: 10px; 536 | right: 10px; 537 | height: 40px; 538 | padding: 20px; 539 | line-height: 40px; 540 | 541 | label { 542 | width: 40px; 543 | position: absolute; 544 | &:nth-child(1) { 545 | left: 0; 546 | } 547 | &:nth-child(2) { 548 | right: 0; 549 | } 550 | @extend .u-hover-ball-effect; 551 | 552 | &.c-datepicker__toggle--checked::after { 553 | content: ""; 554 | position: absolute; 555 | left: 50%; 556 | top: 50%; 557 | width: 0%; 558 | height: 0%; 559 | border-radius: 50%; 560 | transform: translate(-50%, -50%); 561 | width: 36px; 562 | height: 36px; 563 | z-index: -1; 564 | background: rgba(0, 0, 0, 0.05); 565 | } 566 | } 567 | } 568 | -------------------------------------------------------------------------------- /lib/template/container.template.js: -------------------------------------------------------------------------------- 1 | export default () => ` 2 | 3 | 4 | `; 5 | -------------------------------------------------------------------------------- /lib/template/datepicker.template.js: -------------------------------------------------------------------------------- 1 | export default () => ` 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Monday 12 | 13 | 14 | 15 | 16 | 17 | 09:00 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | AM 28 | 29 | 30 | 31 | 32 | PM 33 | 34 | 35 | 36 | 37 | 3 38 | 4 39 | 5 40 | 6 41 | 7 42 | 8 43 | 9 44 | 10 45 | 11 46 | 12 47 | 1 48 | 2 49 | 50 | 51 | 52 | 53 | 54 | 15 55 | 20 56 | 25 57 | 30 58 | 35 59 | 40 60 | 45 61 | 50 62 | 55 63 | 0 64 | 5 65 | 10 66 | 67 | 68 | 69 | 70 | 71 | 72 | Cancel 73 | OK 74 | 75 | 76 | `; 77 | -------------------------------------------------------------------------------- /lib/template/scrim.template.js: -------------------------------------------------------------------------------- 1 | export default ({ styles }) => ` 2 | 3 | `; 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "material-datetime-picker", 3 | "version": "2.4.0", 4 | "description": "A Vanilla JS Material Design date/time picker component", 5 | "main": "dist/material-datetime-picker.js", 6 | "module": "dist/material-datetime-picker.mjs", 7 | "jsnext:main": "dist/material-datetime-picker.mjs", 8 | "scripts": { 9 | "build": "rollup -c", 10 | "build:watch": "rollup -c -w", 11 | "clean": "rm -r dist/*", 12 | "lint": "eslint lib/**/*.js", 13 | "test": "jest" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/ripjar/material-datetime-picker.git" 18 | }, 19 | "author": "@jivings", 20 | "contributors": [ 21 | "Joe Whitfield-Seed " 22 | ], 23 | "license": "MIT", 24 | "dependencies": { 25 | "moment": "2.10.6", 26 | "rome": "https://github.com/jwhitfieldseed/rome.git#19f5d3031a922c29c52b9038b2832a827e5e99d6" 27 | }, 28 | "devDependencies": { 29 | "babel-plugin-external-helpers": "^6.18.0", 30 | "babel-plugin-transform-async-to-generator": "^6.22.0", 31 | "babel-plugin-transform-es2015-modules-commonjs": "^6.22.0", 32 | "babel-preset-es2015": "^6.18.0", 33 | "babelrc-rollup": "^3.0.0", 34 | "delay": "^1.3.1", 35 | "eslint": "^3.13.1", 36 | "eslint-config-airbnb-base": "^11.0.1", 37 | "eslint-plugin-import": "^2.2.0", 38 | "jest": "^18.1.0", 39 | "node-sass": "^4.3.0", 40 | "rollup": "^0.41.4", 41 | "rollup-plugin-babel": "^2.7.1", 42 | "rollup-plugin-sass": "^0.4.8", 43 | "rollup-watch": "^3.2.2" 44 | }, 45 | "jest": { 46 | "moduleNameMapper": { 47 | "\\.scss$": "/lib/js/__tests__/helpers/empty-module.js" 48 | }, 49 | "testPathIgnorePatterns": [ 50 | "/helpers/" 51 | ], 52 | "setupFiles": [ 53 | "/lib/js/__tests__/helpers/dom-polyfills.js" 54 | ] 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import babelrc from 'babelrc-rollup'; 3 | import sass from 'rollup-plugin-sass'; 4 | 5 | const pkg = require('./package.json'); 6 | const external = Object.keys(pkg.dependencies); 7 | 8 | export default { 9 | entry: 'lib/js/index.js', 10 | plugins: [ 11 | sass({ 12 | // FIXME: source maps #100 13 | output: 'dist/material-datetime-picker.css' 14 | }), 15 | babel(babelrc()) 16 | ], 17 | external, 18 | globals: { 19 | rome: 'rome', 20 | moment: 'moment' 21 | }, 22 | targets: [ 23 | { 24 | dest: pkg.main, 25 | format: 'umd', 26 | moduleName: 'MaterialDatetimePicker', 27 | sourceMap: true 28 | }, 29 | { 30 | dest: pkg.module, 31 | format: 'es', 32 | sourceMap: true 33 | } 34 | ] 35 | }; 36 | --------------------------------------------------------------------------------