├── .cjsescache ├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── babel.config.js ├── build-demo.js ├── dist ├── datetime.js └── datetime.js.map ├── example ├── demo-1.5.html └── demo.html ├── index.js ├── lib ├── .eslintrc.json ├── directive.js ├── factory.js └── main.js ├── package-lock.json ├── package.json ├── rollup.config.js └── test └── test.js /.cjsescache: -------------------------------------------------------------------------------- 1 | { 2 | "node_modules/event-lite/event-lite.js": null 3 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_size = 2 3 | indent_style = space 4 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "rules": { 7 | "no-use-before-define": [2, "nofunc"], 8 | "semi": [2, "always"] 9 | }, 10 | "extends": [ 11 | "eslint:recommended" 12 | ], 13 | "overrides": [{ 14 | "files": ["**/rollup.config.js", "bundle.js"], 15 | "parserOptions": { 16 | "sourceType": "module" 17 | } 18 | }] 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | coverage 3 | node_modules 4 | .eslintcache 5 | *.bak 6 | *.log 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | after_success: 5 | - npx codecov 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 eight 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | angular-datetime 2 | ================ 3 | 4 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/e65b981268564476bbecb04911e743be)](https://www.codacy.com/app/eight04/angular-datetime?utm_source=github.com&utm_medium=referral&utm_content=eight04/angular-datetime&utm_campaign=badger) 5 | [![Build Status](https://travis-ci.org/eight04/angular-datetime.svg?branch=master)](https://travis-ci.org/eight04/angular-datetime) 6 | [![codecov](https://codecov.io/gh/eight04/angular-datetime/branch/master/graph/badge.svg)](https://codecov.io/gh/eight04/angular-datetime) 7 | 8 | This module includes a datetime directive and a parser service. 9 | 10 | Features 11 | -------- 12 | * This module includes: 13 | - A directive which can simulate datetime input within a text field. 14 | - A service which can convert a string of date into a Date object, and vice versa. 15 | * Support IE8. Note that old browsers (including IE8-11) require [babel-polyfill](https://unpkg.com/babel-polyfill@6.23.0/dist/polyfill.js) to be installed. 16 | 17 | Dependencies 18 | ------------ 19 | 20 | * Angular 1.2+ 21 | * custom-input 0.2.1 - https://github.com/eight04/custom-input 22 | 23 | Date string format 24 | ------------------ 25 | Apart from [the formats provided officially](https://docs.angularjs.org/api/ng/filter/date), angular-datetime support some new tokens: 26 | 27 | * ZZ - represent timezone with colon (e.g. +08:00) 28 | 29 | Demo 30 | ---- 31 | * With Angular 1.2.x: 32 | * With Angular 1.5.x: 33 | 34 | Installation 35 | ------------ 36 | Via npm: 37 | 38 | ```shell 39 | npm install angular angular-datetime-input --save 40 | ``` 41 | ```javascript 42 | require("angular-datetime-input"); 43 | ``` 44 | 45 | Or use pre-built dist: 46 | 47 | ```html 48 | 49 | ``` 50 | 51 | Example 52 | ------- 53 | ### datetime service 54 | ```Javascript 55 | // Setup dependency 56 | angular.module("myApp", ["datetime"]); 57 | 58 | // Use datetime parser 59 | angular.controller("myController", function(datetime){ 60 | // Create a parser 61 | var parser = datetime("yyyy-MM-dd"); 62 | 63 | // Set to current date 64 | parser.setDate(new Date); 65 | parser.getText(); // -> "2015-01-30" 66 | 67 | // Parse a date string 68 | parser.parse("2015-01-30"); 69 | parser.getDate(); // -> Date object 70 | 71 | // Set working timezone. Changing timezone will not affect date object but 72 | // date string (i.e. parser.getText()). 73 | parser.setTimezone("+0800"); 74 | 75 | // Reset to default timezone. 76 | parser.setTimezone(); 77 | 78 | // Catch the parsing error 79 | try { 80 | parser.parse("2015-123-456"); 81 | } catch (err) { 82 | console.log(err); // -> {code: "...", message: "...", ...} 83 | } 84 | }); 85 | ``` 86 | 87 | ### datetime directive 88 | 89 | Check out the [demo page](https://rawgit.com/eight04/angular-datetime/master/example/demo.html) for details. 90 | 91 | ```html 92 | 93 | 94 | 95 | 96 | 97 | 98 | ``` 99 | 100 | API reference 101 | ------------- 102 | 103 | This module exports: 104 | 105 | * `datetime` service - a function to create DatetimeParser object. 106 | * `datetimePlaceholder` constant - a map that define the placeholder of each element. 107 | 108 | #### datetimePlaceholder object 109 | 110 | Just a plain object. Edit it in config phase to specify different placeholder. 111 | 112 | Default value: 113 | 114 | ```js 115 | { 116 | year: "(year)", 117 | yearShort: "(year)", 118 | month: "(month)", 119 | date: "(date)", 120 | day: "(day)", 121 | hour: "(hour)", 122 | hour12: "(hour12)", 123 | minute: "(minute)", 124 | second: "(second)", 125 | millisecond: "(millisecond)", 126 | ampm: "(AM/PM)", 127 | week: "(week)" 128 | } 129 | ``` 130 | 131 | #### datetime(format: String) => DatetimeParser 132 | 133 | A function to construct a date parser. format is a string containing date definition tokens defined by Angular: https://docs.angularjs.org/api/ng/filter/date 134 | 135 | #### DatetimeParser 136 | 137 | A parser object which can convert String to Date and vice versa. 138 | 139 | ##### DatetimeParser.parse(text: String) => DatetimeParser 140 | 141 | Parse text. This method might throw error. 142 | 143 | ##### DatetimeParser.getText() => String 144 | 145 | Return formatted text. 146 | 147 | ##### DatetimeParser.setDate(date: Date) => DatetimeParser 148 | 149 | Set date and conver date to text. 150 | 151 | ##### DatetimeParser.getDate() => Date 152 | 153 | Return Date object. 154 | 155 | These methods are usually used like: 156 | 157 | ```js 158 | date = parser.parse(text).getDate(); 159 | text = parser.setDate(date).getText(); 160 | ``` 161 | 162 | ##### DatetimeParser.setTimezone([timezone: String]) => DatetimeParser 163 | 164 | Set the timezone of the parser. timezone is a string matching `/[+-]\d{2}:?\d{2}/`. 165 | 166 | If timezone is not provided, reset timezone to browser default. 167 | 168 | Setting timezone doesn't affect model value but update text. 169 | 170 | ```js 171 | time = parser.getDate().getTime(); 172 | parser.setTimezone(newTimezone); 173 | time2 = parser.getDate().getTime(); 174 | 175 | console.assert(time == time2); 176 | ``` 177 | 178 | ##### DatetimeParser.isEmpty() => boolean 179 | 180 | Return true if there is any empty element. 181 | 182 | ##### DatetimeParser.isInit() => boolean 183 | 184 | Return true if all elements are set. 185 | 186 | ##### DatetimeParser.unset() => DatetimeParser 187 | 188 | Set all elements to empty. 189 | 190 | Known issues 191 | ------------ 192 | * 2 digit year 'yy' is ambiguous when converting datestring back to date object (Ex. 14 -> 2014, 1914, ...). You should avoid it. 193 | 194 | Notes 195 | ----- 196 | * Some info about getting selection range across all browsers: 197 | - https://github.com/acdvorak/jquery.caret 198 | - http://stackoverflow.com/questions/19814465/is-it-possible-to-insert-text-in-textarea-and-update-undo-redo-queue 199 | 200 | Changelog 201 | --------- 202 | * 5.3.0 (Apr 19, 2018) 203 | - Add: `datetime-timezone` attribute. Now you can customize the timezone in the directive. #60 @andreyjkee 204 | * 5.2.1 (Sep 17, 2017) 205 | - Fix: use unpkg field in package.json. 206 | * 5.2.0 (Sep 17, 2017) 207 | - Fix: use explicit DI annotation. [#57](https://github.com/eight04/angular-datetime/issues/57) 208 | - Change: dist file is minimized. [#14](https://github.com/eight04/angular-datetime/issues/14) 209 | - **Change: pre-built dist now includes custom-input so there is no need to inject it manually.** 210 | - Update custom-input to 0.3.0 which uses event-lite for smaller file size. 211 | * 5.1.3 (Jul 24, 2017) 212 | - Fix overflowed day issue. [#52](https://github.com/eight04/angular-datetime/issues/52) 213 | * 5.1.2 (Apr 16, 2017) 214 | - Fix jQuery compat issue. [#45](https://github.com/eight04/angular-datetime/issues/45) 215 | * 5.1.1 (Mar 30, 2017) 216 | - Increase directive's priority. [#46](https://github.com/eight04/angular-datetime/issues/46) 217 | * 5.1.0 (Mar 9, 2017) 218 | - Switch to browserify. 219 | - Drop karma, switch to mocha + jsdom. 220 | - **Update custom-input to 0.2.0.** 221 | - Now this package is requirable, perhaps it works better in different bundlers. 222 | * 5.0.0 (Dec 23, 2016) 223 | - Rewritten in ES6. 224 | - The core part of the parser and the input mask are pulled out as [custom-input](https://github.com/eight04/custom-input) 225 | - Support IE8 by transpiling through babel and using polyfill for missing functions. 226 | - Add constant `datetimePlaceholder`. 227 | * 4.1.0 (Oct 5, 2016) 228 | - Refactor. 229 | - Fix day priority bug. 230 | - Add `parser.isEmpty`. Fix required issue. 231 | * 4.0.0 (Sep 1, 2016) 232 | - Change how parser work. It can represent "undefined" node now. 233 | - Use tab key to navigate between different parts. 234 | * 3.2.2 (Jun 30, 2016) 235 | - Return false if there is no ngModel. 236 | * 3.2.1 (Jun 18, 2016) 237 | - Fix a bug that empty `min`, `max` cause invalid date. 238 | * 3.2.0 (May 17, 2016) 239 | - Support dynamic datetime-utc. [#29](https://github.com/eight04/angular-datetime/issues/29) 240 | * 3.1.1 (Apr 17, 2016) 241 | - Deploy to npmjs/angular-datetime-input. 242 | - Drop grunt. 243 | * 3.1.0 244 | - Jump on the next segment on pressing next separator key. ([#26](https://github.com/eight04/angular-datetime/pull/26)) 245 | - Add `datetime-separator` option. 246 | - Now it will try to fix NUMBER_TOOSHORT error when pressing left/right/separator key. 247 | * 3.0.1 (Apr 9, 2016) 248 | - Fix validator and datetime-model bug. [#27](https://github.com/eight04/angular-datetime/issues/27) 249 | * 3.0.0 (Apr 1, 2016) 250 | - Add token `ZZ`. [#24](https://github.com/eight04/angular-datetime/pull/24) 251 | - Fix datetime-utc issue. [#21](https://github.com/eight04/angular-datetime/issues/21) 252 | - Add `parser.setTimezone`. [#22](https://github.com/eight04/angular-datetime/issues/22) 253 | - Use PhantomJS for testing. 254 | - Change Angular dependency to ^1.2.0. 255 | - Fix [date overflow bug](http://stackoverflow.com/questions/14680396/the-date-getmonth-method-has-bug). 256 | * 2.2.1 (Mar 31, 2016) 257 | - Fix reference error with "Z" token. See [#20](https://github.com/eight04/angular-datetime/pull/20) 258 | * 2.2.0 (Feb 23, 2016) 259 | - Add new error type "LEADING_ZERO", "NUMBER_TOOSMALL". 260 | - Use the behavior introduced in #18. 261 | - Add `default` attribute. 262 | * 2.1.0 (Jan 12, 2016) 263 | - Add `datetime-utc` option. 264 | * 2.0.1 (Jan 1, 2016) 265 | - Add MIT License 266 | * 2.0 267 | - Add `min`, `max`, `datetime-model` directive. 268 | - Support `$validators` in angular 1.3.x. 269 | - Update Eslint to 1.x. 270 | - Fix timezone token `Z`. 271 | * 1.0 272 | - Added Karma test. 273 | - Changed source structure. 274 | - Now you can chain parser's methods. 275 | - Parsing error won't mess up modelValue anymore. 276 | 277 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | const presets = [ 2 | [ 3 | "@babel/env", 4 | { 5 | targets: { 6 | ie: 8 7 | }, 8 | loose: true, 9 | modules: false, 10 | exclude: ["transform-function-name"] 11 | } 12 | ] 13 | ]; 14 | 15 | module.exports = {presets}; 16 | -------------------------------------------------------------------------------- /build-demo.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | 3 | fs.readFile("example/demo.html", "utf8", function(err, data) { 4 | if (err) throw err; 5 | data = data.replace(/\/1\.2\.\d+\/angular\.js/, "/1.5.8/angular.js"); 6 | fs.writeFile("example/demo-1.5.html", data, function(err) { 7 | if (err) throw err; 8 | }); 9 | }); -------------------------------------------------------------------------------- /dist/datetime.js: -------------------------------------------------------------------------------- 1 | !function(L){"use strict";function e(){if(!(this instanceof e))return new e}L.module("datetime",[]),L.module("datetime").constant("datetimePlaceholder",{year:"(year)",yearShort:"(year)",month:"(month)",date:"(date)",day:"(day)",hour:"(hour)",hour12:"(hour12)",minute:"(minute)",second:"(second)",millisecond:"(millisecond)",ampm:"(AM/PM)",week:"(week)"});var u={exports:{}};!function(e){void 0!==u&&(u.exports=e);var s="listeners",n={on:r,once:i,off:o,emit:a};function t(e){for(var t in n)e[t]=n[t];return e}function r(e,t){return l(this,e).push(t),this}function i(e,t){var n=this;return r.originalListener=t,l(n,e).push(r),n;function r(){o.call(n,e,r),t.apply(this,arguments)}}function o(e,t){var n,r=this;if(arguments.length){if(t){if(n=l(r,e,!0)){if(!(n=n.filter(i)).length)return o.call(r,e);r[s][e]=n}}else if((n=r[s])&&(delete n[e],!Object.keys(n).length))return o.call(r)}else delete r[s];return r;function i(e){return e!==t&&e.originalListener!==t}}function a(e,t){var n=this,r=l(n,e,!0);if(!r)return!1;var i=arguments.length;if(1===i)r.forEach(o);else if(2===i)r.forEach(a);else{var s=Array.prototype.slice.call(arguments,1);r.forEach(u)}return!!r.length;function o(e){e.call(n)}function a(e){e.call(n,t)}function u(e){e.apply(n,s)}}function l(e,t,n){if(!n||e[s]){var r=e[s]||(e[s]={});return r[t]||(r[t]=[])}}t(e.prototype),e.mixin=t}(e);var t=u.exports,S=function(e,t,n){var r;if((e=""+e).length>n)e=e.substr(e.length-n);else if(e.lengtht.maxLength&&(s=s.substr(0,t.maxLength)),+st.minLength&&"0"==s[0]?{err:1,code:"LEADING_ZERO",message:"The number has too many leading zero",value:+s,viewValue:s,properValue:S(+s,t.minLength,t.maxLength)}:+s>t.max?{err:1,code:"NUMBER_TOOLARGE",message:"The number is too large",value:+s,viewValue:s,properValue:S(t.max,t.minLength,t.maxLength)}:{value:+s,viewValue:s});if("select"!=t.type)throw"Unknown token type: "+t.type;for(i="",o=0;oi.length&&(s=o,i=r);return i?i!=t.select[s]?{err:1,code:"SELECT_INCOMPLETE",message:"Incomplete select",value:s+1,viewValue:i,selected:t.select[s]}:{value:s+1,viewValue:i}:{err:1,code:"SELECT_MISMATCH",message:"Invalid select",viewValue:""}}function g(e,t){var n,r,i=0,s=[],o=e,a=Array.isArray(o),u=0;for(o=a?o:o[Symbol.iterator]();;){if(a){if(u>=o.length)break;n=o[u++]}else{if((u=o.next()).done)break;n=u.value}if((r=h(t,n.token,i)).node=n,r.pos=i,r.token=n.token,2<=r.err)throw r.text=t,r;i+=r.viewValue.length,s.push(r)}var l=s[s.length-1];if(l.pos+l.viewValue.length=o.length)break;i=o[u++]}else{if((u=o.next()).done)break;i=u.value}r=c(e,i.token),"static"!=i.token.type&&i.empty&&!n&&(r.value=null,r.viewValue=i.token.placeholder),s.push(r)}return s}var d=function(){function e(e,t){this.parser=e,this.token=t,this.value=null,this.viewValue=t.value,this.offset=0,this.next=null,this.prev=null,this.nextEdit=null,this.prevEdit=null,this.empty=!0}var t=e.prototype;return t.unset=function n(){"static"==this.token.type||this.parser.noEmpty||(this.empty=!0,this.parser.setValue(this.parser.value,!1))},t.parse=function i(e,t){void 0===t&&(t=0);var n=h(e,this.token,t);if(n.err)throw n.node=this,n.token=this.token,n;if(this.parser.noEmpty&&n.empty)throw{code:"NOT_INIT_FORBIDDEN",message:"Empty node is forbidden",node:this};if(n.empty)this.unset();else{this.empty=!1;var r=v(this.parser.copyValue(this.parser.value),this.token,n.value,this.parser);this.parser.setValue(r,!1)}},t.add=function s(e){var t,n,r,i=this.parser.copyValue(this.parser.value);this.empty=!1,i=o(i,this.token,e,this.parser),t=this.token.extract(i),"number"==this.token.type?(n=this.token.min,r=this.token.max):"select"==this.token.type&&(n=1,r=this.token.select.length),t=o.length)break;n=o[u++]}else{if((u=o.next()).done)break;n=u.value}s.push(new d(e,n))}for(r=0;r=n.length)break;s=n[i++]}else{if((i=n.next()).done)break;s=i.value}var o=s,a=t.get(o.token.name);a||(a=[],t.set(o.token.name,a)),a.push(o)}return t}var n=function(t){function e(){var e;return(e=t.call(this)||this)._constructor.apply(m(e),arguments),e.initialize(),e}f(e,t);var n=e.prototype;return n._constructor=function u(e){var t=e.tokens,n=e.noEmpty,r=void 0!==n&&n,i=e.value,s=e.text,o=e.copyValue,a=void 0===o?x:o;if(!t||!t.length)throw new Error("option.tokens is required");this.tokens=t,this.nodes=y(this,t),this.nameMap=T(this.nodes),this.value=i,this.text=s,this.noEmpty=r,this.copyValue=a,this.err=!1},n.initialize=function r(){this.setValue(this.value)},n.parse=function d(e){if(!e)throw{code:"EMPTY",message:"The input is empty",oldText:this.text};var t,n;t=g(this.nodes,e);var r,i=[];for(r=this.err?g(this.nodes,this.text):this.nodes,n=0;n=t.length)break;e=t[r++]}else{if((r=t.next()).done)break;e=r.value}if("static"!=e.token.type&&e.empty)return!1}return!0},n.unset=function a(){var e,t=this.nodes,n=Array.isArray(t),r=0;for(t=n?t:t[Symbol.iterator]();;){if(n){if(r>=t.length)break;e=t[r++]}else{if((r=t.next()).done)break;e=r.value}e.empty=!0}return this.setValue(this.value,!1),this},n.getText=function l(){return this.text},n.getValue=function h(){return this.value},n.getNodes=function c(e){return e?this.nameMap.get(e):this.nodes},e}(t);function w(e,t){if(t.length){var n=k(t,e).map(function(e){return e.node}),r=n[0],i=n[1];return r==i?r:e-r.offset-r.viewValue.length<=i.offset-e?r:i}}function k(e,t,n){var r,i,s;void 0===n&&(n=t);var o=e,a=Array.isArray(o),u=0;for(o=a?o:o[Symbol.iterator]();;){if(a){if(u>=o.length)break;r=o[u++]}else{if((u=o.next()).done)break;r=u.value}r.offset<=t&&(i={node:r,pos:t-r.offset}),r.offset+r.viewValue.length>=n&&!s&&(s={node:r,pos:n-r.offset})}if(!s){var l=e[e.length-1];s={node:l,pos:l.viewValue.length}}i=i||{node:e[0],pos:0};return i.pos>i.node.viewValue.length&&(i.pos=i.node.viewValue.length),[i,s]}var E=function(){function e(e,t){this.el=e,this.nodes=t,this.range={node:w(0,this.nodes),start:0,end:"end"}}var t=e.prototype;return t.selectNearestNode=function n(){var e=this.el.getSelection();e&&this.select({node:w(e.start,this.nodes),start:0,end:"end"})},t.select=function r(e){(e=Object.assign(this.range,e)).node&&this.el.setSelection(e.node.offset+e.start,e.node.offset+("end"==e.end?e.node.viewValue.length:e.end))},t.hasNext=function i(){if(this.range.node)return this.range.node.nextEdit},t.hasPrev=function s(){if(this.range.node)return this.range.node.prevEdit},t.selectNext=function o(){var e=this.hasNext(),t={start:0,end:"end"};e&&(t.node=e),this.select(t)},t.selectPrev=function a(){var e=this.hasPrev(),t={start:0,end:"end"};e&&(t.node=e),this.select(t)},t.get=function u(){if(this.nodes.length){var e=this.el.getSelection();if(e){var t=k(this.nodes,e.start,e.end),n=t[0],r=t[1];n.node==r.node&&(this.range={node:n.node,start:n.pos,end:r.pos})}}},t.atNodeEnd=function l(){if(this.range.node){this.get();var e=this.range.node.viewValue.length,t=this.range.node.token.maxLength,n="end"==this.range.start?e:this.range.start;return n==("end"==this.range.end?e:this.range.end)&&n==(null!=t?t:e)||!e}},t.atNodeStart=function h(){if(this.range.node){this.get();var e=this.range.node.viewValue.length,t="end"==this.range.start?e:this.range.start;return t==("end"==this.range.end?e:this.range.end)&&0==t}},e}(),N=n,b=function(t){function e(){var e;return(e=t.call(this)||this)._constructor.apply(m(e),arguments),e.initialize(),e}f(e,t);var n=e.prototype;return n._constructor=function r(e,t,n){void 0===n&&(n=""),this.el=e,this.tp=t,this.separators=n,this.sel=new E(e,t.getNodes().filter(function(e){return"static"!=e.token.type}))},n.initialize=function i(){var s=this;this.el.on("mousedown",function(){s.mousedown=!0}),this.el.on("focus",function(){s.mousedown||setTimeout(function(){s.sel.select({start:0,end:"end"})})}),this.el.on("click",function(){s.mousedown=!1,s.sel.selectNearestNode()}),this.el.on("input",function(){s.digest(null,s.el.val())}),this.el.on("keydown",function(e){e.altKey||e.ctrlKey||(37==e.keyCode||9==e.keyCode&&e.shiftKey&&s.sel.hasPrev()?(e.preventDefault(),s.tryFixingError(),s.sel.selectPrev()):39==e.keyCode||9==e.keyCode&&!e.shiftKey&&s.sel.hasNext()?(e.preventDefault(),s.tryFixingError(),s.sel.selectNext()):38==e.keyCode?(e.preventDefault(),s.sel.selectNearestNode(),s.sel.range.node&&s.sel.range.node.add(1),s.val(s.tp.getText()),s.sel.select({start:0,end:"end"})):40==e.keyCode?(e.preventDefault(),s.sel.selectNearestNode(),s.sel.range.node&&s.sel.range.node.add(-1),s.val(s.tp.getText()),s.sel.select({start:0,end:"end"})):36==e.keyCode||35==e.keyCode?setTimeout(function(){return s.sel.selectNearestNode()}):46==e.keyCode?s.sel.atNodeEnd()&&(e.preventDefault(),s.tryFixingError(),s.sel.selectNext()):8==e.keyCode&&s.sel.atNodeStart()&&(e.preventDefault(),s.tryFixingError(),s.sel.selectPrev()))}),this.el.on("keypress",function(e){var t=null==e.charCode?e.keyCode:e.charCode,n=String.fromCharCode(t),r=s.separators,i=s.sel.range.node;if(i&&i.next&&"static"==i.next.token.type&&(r+=i.next.viewValue[0]),r.includes(n))return e.preventDefault(),s.tryFixingError(),void s.sel.selectNext();setTimeout(function(){s.sel.atNodeEnd()&&s.sel.range.node.viewValue&&(s.tryFixingError(),s.sel.selectNext())})}),this.el.on("blur",function(){setTimeout(function(){s.tryFixingError()})}),this.tp.on("change",function(){s.err||s.inDigest||(s.val(s.tp.getText()),s.sel.select())});var e=this.el.val();e?this.digest(null,e,!0):this.val(this.tp.getText())},n.errorViewLength=function s(){return this.err&&null!=this.err.viewValue?this.err.viewValue.length:undefined},n.val=function o(e){this.el.val()!=e&&this.el.val(e),this.err=null},n.tryFixingError=function a(){this.err&&(this.err.properValue?this.digest(this.err.node,this.err.properValue,!0):this.err.node&&(this.err.node.unset(),this.digest(null,this.tp.getText())))},n.digest=function u(e,t,n){var r,u=10;for(this.inDigest=!0;u--;){this.err=null;try{e?e.parse(t):this.tp.parse(t)}catch(i){if(this.emit("digest",i),this.sel.get(),"NOT_INIT"==i.code)break;if(this.err=i,!n&&("NUMBER_TOOSHORT"==i.code||"NUMBER_TOOSMALL"==i.code||"NUMBER_MISMATCH"==i.code||"SELECT_MISMATCH"==i.code||"LEADING_ZERO"==i.code))break;if("SELECT_INCOMPLETE"==i.code){e=i.node,t=i.selected,r={end:"end"};continue}null!=i.properValue?(e=i.node,t=i.properValue):null!=i.properText?(e=null,t=i.properText):("EMPTY"==i.code&&this.tp.unset(),i.node&&i.node.unset(),e=null,t=this.tp.getText(),r={start:0,end:"end"});continue}break}if(this.err||(this.val(this.tp.getText()),u<9&&this.sel.select(r)),this.inDigest=!1,u<0)throw new Error("InputMask.digest crashed! Infinite loop on "+t)},e}(t);function r(e,t){var l=e.DATETIME_FORMATS,s=/yyyy|yy|y|M{1,4}|dd?|EEEE?|HH?|hh?|mm?|ss?|([.,])sss|a|Z{1,2}|ww|w|'(([^']+|'')*)'/g,o={y:{minLength:1,maxLength:4,max:9999,min:0,name:"year",type:"number"},yy:{minLength:2,maxLength:2,name:"yearShort",type:"number"},yyyy:{minLength:4,maxLength:4,max:9999,min:0,name:"year",type:"number"},MMMM:{name:"month",type:"select",select:l.MONTH},MMM:{name:"month",type:"select",select:l.SHORTMONTH},MM:{minLength:2,maxLength:2,name:"month",type:"number"},M:{minLength:1,maxLength:2,name:"month",type:"number",min:1},dd:{minLength:2,maxLength:2,name:"date",type:"number"},d:{minLength:1,maxLength:2,name:"date",type:"number",min:1},EEEE:{name:"day",type:"select",select:p(l.DAY)},EEE:{name:"day",type:"select",select:p(l.SHORTDAY)},HH:{minLength:2,maxLength:2,name:"hour",type:"number"},H:{minLength:1,maxLength:2,name:"hour",type:"number"},hh:{minLength:2,maxLength:2,name:"hour12",type:"number"},h:{minLength:1,maxLength:2,name:"hour12",type:"number"},mm:{minLength:2,maxLength:2,name:"minute",type:"number"},m:{minLength:1,maxLength:2,name:"minute",type:"number"},ss:{minLength:2,maxLength:2,name:"second",type:"number"},s:{minLength:1,maxLength:2,name:"second",type:"number"},sss:{minLength:3,maxLength:3,name:"millisecond",type:"number"},a:{name:"ampm",type:"select",select:l.AMPMS},ww:{minLength:2,maxLength:2,max:53,name:"week",type:"number"},w:{minLength:1,maxLength:2,max:53,name:"week",type:"number"},Z:{name:"timezone",type:"static"},ZZ:{name:"timezone",type:"static",colon:!0},string:{name:"string",type:"static"}},n={year:{extract:function(e){var t=e.getFullYear()%1e4;return 0<=t?t:0},restore:function(e,t){return e.setFullYear(t)},add:function(e,t){return e.setFullYear(e.getFullYear()+t)},prior:7},yearShort:{extract:function(e){var t=e.getFullYear()%100;return 0<=t?t:t+100},restore:function(e,t){return e.setFullYear(t)},add:function(e,t){return e.setFullYear(e.getFullYear()+t)},prior:7},month:{extract:function(e){return e.getMonth()+1},restore:function(e,t){e.setMonth(t-1),e.getMonth()==t&&e.setDate(0)},add:function(e,t){t=e.getMonth()+t,e.setMonth(t),e.getMonth()==t+1&&e.setDate(0)},prior:5},date:{extract:function(e){return e.getDate()},restore:function(e,t,n){var r=e.getMonth();if(e.setDate(t),e.getMonth()!=r&&t<=31){var i=n.getNodes("month");i&&i.every(function(e){return e.empty})&&e.setDate(t)}},add:function(e,t,n){this.restore(e,e.getDate()+t,n)},prior:4},day:{extract:function(e){return e.getDay()||7},restore:x,add:function(e,t){return e.setDate(e.getDate()+t)},prior:4},hour:{extract:function(e){return e.getHours()},restore:function(e,t){return e.setHours(t)},add:function(e,t){return e.setHours(e.getHours()+t)},prior:2},hour12:{extract:function(e){return e.getHours()%12||12},restore:T,add:function(e,t){return e.setHours(e.getHours()+t)},prior:2},ampm:{extract:function(e){return e.getHours()<12?1:2},restore:w,add:function(e,t){return e.setHours(e.getHours()+12*t)},prior:3},minute:{extract:function(e){return e.getMinutes()},restore:function(e,t){return e.setMinutes(t)},add:function(e,t){return e.setMinutes(e.getMinutes()+t)},prior:0},second:{extract:function(e){return e.getSeconds()},restore:function(e,t){return e.setSeconds(t)},add:function(e,t){return e.setSeconds(e.getSeconds()+t)},prior:1},millisecond:{extract:function(e){return e.getMilliseconds()},restore:function(e,t){return e.setMilliseconds(t)},add:function(e,t){return e.setMilliseconds(e.getMilliseconds()+t)},prior:1},week:{extract:y,restore:function(e,t){return e.setDate(e.getDate()+7*(t-y(e)))},add:function(e,t){return e.setDate(e.getDate()+7*t)},prior:6}};for(var r in n)n[r].placeholder=t[r];for(var i=0,a=Object.values(o);ir&&(n.push(L.extend({value:e.substring(r,t.index)},o.string)),r=t.index),t.index==r){if(t[1])n.push(L.extend({value:t[1]},o.string)),n.push(o.sss);else if(t[2])n.push(L.extend({value:t[2].replace("''","'")},o.string));else if("timezone"==o[t[0]].name){var i=g;o[t[0]].colon&&(i=k(i)),n.push(L.extend({value:i},o[t[0]]))}else n.push(o[t[0]]);r=s.lastIndex}return r=n.length)break;s=n[i++]}else{if((i=n.next()).done)break;s=i.value}var o=s;o.token.colon?o.token.value=k(e):o.token.value=E(e)}return this.setDate(t,!1)}},t.isEmpty=function o(){return this.tp.isEmpty.apply(this.tp,arguments)},t.isInit=function u(){return this.tp.isInit.apply(this.tp,arguments)},t.unset=function l(){return this.tp.unset(),this},e}();function M(e){var t,n=v(l[e]||e);t=n.some(function(e){return"yearShort"==e.name})?function(n){return function(e){n.apply(this,arguments);var t=e.getFullYear();t<0&&e.setFullYear(t+100)}}:function(n){return function(e){n.apply(this,arguments);var t=e.getFullYear();t<0&&e.setFullYear(0),9999=r.length)break;o=r[s++]}else{if((s=r.next()).done)break;o=s.value}var a=o;a.add&&(a.add=t(a.add)),a.restore&&(a.restore=t(a.restore))}var u=new N({tokens:n,value:new Date,copyValue:function(e){return new Date(e.getTime())}});return new D(u)}return M}function s(g,e,p){var v=function(){function e(e,t){this.el=e,this.doc=t}var t=e.prototype;return t.on=function n(e,t){if("input"!=e)return this.el.on(e,t)},t.getSelection=function r(){var e=this.el[0];if(this.doc.activeElement==e){var t=e.selectionStart,n=e.selectionEnd;return L.isDefined(t)&&L.isDefined(n)?{start:t,end:n}:this.getSelectionIE()}},t.getSelectionIE=function s(){var e=this.el[0],t=this.doc.selection.createRange().getBookmark(),n=e.createTextRange(),r=n.duplicate();n.moveToBookmark(t),r.setEndPoint("EndToStart",n);var i=r.text.length;return{start:i,end:i+n.text.length}},t.setSelection=function i(e,t){var n=this.el[0];this.doc.activeElement==n&&(n.setSelectionRange?n.setSelectionRange(e,t):this.setSelectionIE(e,t))},t.setSelectionIE=function o(e,t){var n=this.el[0].createTextRange();n.moveStart("character",e),n.collapse(),n.moveEnd("character",t-e),n.select()},t.val=function a(){var e;return(e=this.el).val.apply(e,arguments)},e}();function t(t,e,n,r){if(!r)return!1;n.ngTrim="false";var i,s=g(n.datetime),o=n.datetimeModel&&g(n.datetimeModel),a=new v(e,p[0]),u=new b(a,s.tp,n.datetimeSeparator);function l(e){e&&!i?(i=!0,s.setTimezone("+0000"),o&&o.setTimezone("+0000")):!e&&i&&(i=!1,s.setTimezone(),o&&o.setTimezone())}function h(e){s.setTimezone(e),o&&o.setTimezone(e)}function c(e){return!(!r.$isEmpty(e)&&!r.$isEmpty(n.min))||(L.isDate(e)||(e=o.getDate()),e>=new Date(n.min))}function d(e){return!(!r.$isEmpty(e)&&!r.$isEmpty(n.max))||(L.isDate(e)||(e=o.getDate()),e<=new Date(n.max))}function f(e){return r.$validate?r.$validate():(r.$setValidity("min",c(e)),r.$setValidity("max",d(e))),!r.$error.min&&!r.$error.max}function m(e){return!(!L.isDate(e)||o)||!(!L.isString(e)||!o)}u.on("digest",function(e){"NOT_INIT"!=e.code&&r.$setValidity("datetime",!1)}),s.tp.on("change",function(){t.$evalAsync(function(){u.err?r.$setValidity("datetime",!1):(s.isInit()||s.isEmpty()?r.$setValidity("datetime",!0):r.$setValidity("datetime",!1),s.getText()!=r.$viewValue&&r.$setViewValue(s.getText()))})}),L.isDefined(n.datetimeUtc)&&(0 maxLength) {\r\n\t\t\tnum = num.substr(num.length - maxLength);\r\n\t\t} else if (num.length < minLength) {\r\n\t\t\tfor (i = num.length; i < minLength; i++) {\r\n\t\t\t\tnum = \"0\" + num;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn num;\r\n\t},\r\n\tEmitter: require(\"event-lite\")\r\n};\r\n","var { num2str, Emitter } = require(\"./utils\");\r\n\r\nfunction getMatch(str, pos, pattern) {\r\n\tvar i = 0,\r\n\t\tstrQ = str.toUpperCase(),\r\n\t\tpatternQ = pattern.toUpperCase();\r\n\r\n\twhile (strQ[pos + i] && strQ[pos + i] == patternQ[i]) {\r\n\t\ti++;\r\n\t}\r\n\r\n\treturn str.substr(pos, i);\r\n}\r\n\r\nfunction getInteger(str, pos) {\r\n\tstr = str.substring(pos);\r\n\tvar match = str.match(/^\\d+/);\r\n\treturn match && match[0];\r\n}\r\n\r\nfunction parseNode(text, token, pos) {\r\n\tvar result = parseToken(text, token, pos);\r\n\t\r\n\t// check placeholder\r\n\tif (\r\n\t\tresult.err &&\r\n\t\ttoken.type != \"static\" && text.startsWith(token.placeholder, pos) &&\r\n\t\t(result.err > 1 || result.viewValue.length <= token.placeholder.length)\r\n\t) {\r\n\t\treturn {\r\n\t\t\tempty: true,\r\n\t\t\tviewValue: token.placeholder\r\n\t\t};\r\n\t}\r\n\t\r\n\treturn result;\r\n}\r\n\r\nfunction parseToken(text, token, pos) {\r\n\tvar m, match, value, j;\r\n\r\n\tif (token.type == \"static\") {\r\n\t\tif (!text.startsWith(token.value, pos)) {\r\n\t\t\treturn {\r\n\t\t\t\terr: 2,\r\n\t\t\t\tcode: \"TEXT_MISMATCH\",\r\n\t\t\t\tmessage: \"Pattern value mismatch\"\r\n\t\t\t};\r\n\t\t}\r\n\t\treturn {\r\n\t\t\tviewValue: token.value\r\n\t\t};\r\n\t}\r\n\r\n\tif (token.type == \"number\") {\r\n\t\tvalue = getInteger(text, pos);\r\n\r\n\t\tif (value == null) {\r\n\t\t\treturn {\r\n\t\t\t\terr: 1,\r\n\t\t\t\tcode: \"NUMBER_MISMATCH\",\r\n\t\t\t\tmessage: \"Invalid number\",\r\n\t\t\t\tviewValue: \"\"\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tif (value.length < token.minLength) {\r\n\t\t\treturn {\r\n\t\t\t\terr: 1,\r\n\t\t\t\tcode: \"NUMBER_TOOSHORT\",\r\n\t\t\t\tmessage: \"The length of number is too short\",\r\n\t\t\t\tvalue: +value,\r\n\t\t\t\tviewValue: value,\r\n\t\t\t\tproperValue: num2str(+value, token.minLength, token.maxLength)\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tif (value.length > token.maxLength) {\r\n\t\t\tvalue = value.substr(0, token.maxLength);\r\n\t\t}\r\n\r\n\t\tif (+value < token.min) {\r\n\t\t\treturn {\r\n\t\t\t\terr: 1,\r\n\t\t\t\tcode: \"NUMBER_TOOSMALL\",\r\n\t\t\t\tmessage: \"The number is too small\",\r\n\t\t\t\tvalue: +value,\r\n\t\t\t\tviewValue: value,\r\n\t\t\t\tproperValue: num2str(token.min, token.minLength, token.maxLength)\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tif (value.length > token.minLength && value[0] == \"0\") {\r\n\t\t\treturn {\r\n\t\t\t\terr: 1,\r\n\t\t\t\tcode: \"LEADING_ZERO\",\r\n\t\t\t\tmessage: \"The number has too many leading zero\",\r\n\t\t\t\tvalue: +value,\r\n\t\t\t\tviewValue: value,\r\n\t\t\t\tproperValue: num2str(+value, token.minLength, token.maxLength)\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tif (+value > token.max) {\r\n\t\t\treturn {\r\n\t\t\t\terr: 1,\r\n\t\t\t\tcode: \"NUMBER_TOOLARGE\",\r\n\t\t\t\tmessage: \"The number is too large\",\r\n\t\t\t\tvalue: +value,\r\n\t\t\t\tviewValue: value,\r\n\t\t\t\tproperValue: num2str(token.max, token.minLength, token.maxLength)\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tvalue: +value,\r\n\t\t\tviewValue: value\r\n\t\t};\r\n\t}\r\n\r\n\tif (token.type == \"select\") {\r\n\t\tmatch = \"\";\r\n\t\tfor (j = 0; j < token.select.length; j++) {\r\n\t\t\tm = getMatch(text, pos, token.select[j]);\r\n\t\t\tif (m && m.length > match.length) {\r\n\t\t\t\tvalue = j;\r\n\t\t\t\tmatch = m;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!match) {\r\n\t\t\treturn {\r\n\t\t\t\terr: 1,\r\n\t\t\t\tcode: \"SELECT_MISMATCH\",\r\n\t\t\t\tmessage: \"Invalid select\",\r\n\t\t\t\tviewValue: \"\"\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tif (match != token.select[value]) {\r\n\t\t\treturn {\r\n\t\t\t\terr: 1,\r\n\t\t\t\tcode: \"SELECT_INCOMPLETE\",\r\n\t\t\t\tmessage: \"Incomplete select\",\r\n\t\t\t\tvalue: value + 1,\r\n\t\t\t\tviewValue: match,\r\n\t\t\t\tselected: token.select[value]\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tvalue: value + 1,\r\n\t\t\tviewValue: match\r\n\t\t};\r\n\t}\r\n\r\n\tthrow \"Unknown token type: \" + token.type;\r\n}\r\n\r\nfunction parseNodes(nodes, text) {\r\n\tvar pos = 0, node, result = [], r;\r\n\r\n\tfor (node of nodes) {\r\n\t\tr = parseNode(text, node.token, pos);\r\n\t\tr.node = node;\r\n\t\tr.pos = pos;\r\n\t\tr.token = node.token;\r\n\t\tif (r.err >= 2) {\r\n\t\t\tr.text = text;\r\n\t\t\tthrow r;\r\n\t\t}\r\n\t\tpos += r.viewValue.length;\r\n\t\tresult.push(r);\r\n\t}\r\n\r\n\t// throw TEXT_TOOLONG error\r\n\tvar last = result[result.length - 1];\r\n\tif (last.pos + last.viewValue.length < text.length) {\r\n\t\tthrow {\r\n\t\t\tcode: \"TEXT_TOOLONG\",\r\n\t\t\tmessage: \"Text is too long\",\r\n\t\t\ttext: text\r\n\t\t};\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\nfunction formatNode(value, token) {\r\n\tif (token.type == \"static\") {\r\n\t\treturn {\r\n\t\t\tviewValue: token.value\r\n\t\t};\r\n\t}\r\n\tvar v = token.extract(value);\r\n\tif (token.type == \"number\") {\r\n\t\treturn {\r\n\t\t\tvalue: v,\r\n\t\t\tviewValue: num2str(v, token.minLength, token.maxLength)\r\n\t\t};\r\n\t}\r\n\tif (token.type == \"select\") {\r\n\t\treturn {\r\n\t\t\tvalue: v,\r\n\t\t\tviewValue: token.select[v - 1]\r\n\t\t};\r\n\t}\r\n\tthrow \"Unknown type to format: \" + token.type;\r\n}\r\n\r\nfunction formatNodes(value, nodes, ignoreEmpty) {\r\n\tvar result = [], r, node;\r\n\tfor (node of nodes) {\r\n\t\tr = formatNode(value, node.token);\r\n\t\tif (node.token.type != \"static\" && node.empty && !ignoreEmpty) {\r\n\t\t\tr.value = null;\r\n\t\t\tr.viewValue = node.token.placeholder;\r\n\t\t}\r\n\t\tresult.push(r);\r\n\t}\r\n\treturn result;\r\n}\r\n\r\nclass Node {\r\n\tconstructor (parser, token) {\r\n\t\tthis.parser = parser;\r\n\t\tthis.token = token;\r\n\t\tthis.value = null;\r\n\t\tthis.viewValue = token.value;\r\n\t\tthis.offset = 0;\r\n\t\tthis.next = null;\r\n\t\tthis.prev = null;\r\n\t\tthis.nextEdit = null;\r\n\t\tthis.prevEdit = null;\r\n\t\tthis.empty = true;\r\n\t}\r\n\r\n\tunset () {\r\n\t\tif (this.token.type == \"static\" || this.parser.noEmpty) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis.empty = true;\r\n\t\tthis.parser.setValue(this.parser.value, false);\r\n\t}\r\n\r\n\tparse (text, pos = 0) {\r\n\t\tvar result = parseNode(text, this.token, pos);\r\n\t\tif (result.err) {\r\n\t\t\tresult.node = this;\r\n\t\t\tresult.token = this.token;\r\n\t\t\tthrow result;\r\n\t\t}\r\n\r\n\t\tif (this.parser.noEmpty && result.empty) {\r\n\t\t\tthrow {\r\n\t\t\t\tcode: \"NOT_INIT_FORBIDDEN\",\r\n\t\t\t\tmessage: \"Empty node is forbidden\",\r\n\t\t\t\tnode: this\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tif (result.empty) {\r\n\t\t\tthis.unset();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tthis.empty = false;\r\n\r\n\t\tvar value = restoreValue(this.parser.copyValue(this.parser.value), this.token, result.value, this.parser);\r\n\t\tthis.parser.setValue(value, false);\r\n\t}\r\n\r\n\tadd (diff) {\r\n\t\tvar value = this.parser.copyValue(this.parser.value),\r\n\t\t\tnodeValue;\r\n\r\n\t\tthis.empty = false;\r\n\r\n\t\tvalue = addValue(value, this.token, diff, this.parser);\r\n\t\tnodeValue = this.token.extract(value);\r\n\r\n\t\t// min/max check\r\n\t\tvar min, max;\r\n\t\tif (this.token.type == \"number\") {\r\n\t\t\tmin = this.token.min;\r\n\t\t\tmax = this.token.max;\r\n\t\t} else if (this.token.type == \"select\") {\r\n\t\t\tmin = 1;\r\n\t\t\tmax = this.token.select.length;\r\n\t\t}\r\n\t\t\r\n\t\tif (nodeValue < min) {\r\n\t\t\tvalue = restoreValue(value, this.token, min, this.parser);\r\n\t\t}\r\n\t\tif (nodeValue > max) {\r\n\t\t\tvalue = restoreValue(value, this.token, max, this.parser);\r\n\t\t}\r\n\r\n\t\tthis.parser.setValue(value, false);\r\n\t}\r\n}\r\n\r\nfunction addValue(o, tk, v, p) {\r\n\tif (typeof o == \"object\") {\r\n\t\ttk.add(o, v, p);\r\n\t\treturn o;\r\n\t} else {\r\n\t\treturn tk.add(o, v, p);\r\n\t}\r\n}\r\n\r\nfunction restoreValue(o, tk, v, p) {\r\n\tif (typeof o == \"object\") {\r\n\t\ttk.restore(o, v, p);\r\n\t\treturn o;\r\n\t} else {\r\n\t\treturn tk.restore(o, v, p);\r\n\t}\r\n}\r\n\r\nfunction createNodes(parser, tokens) {\r\n\tvar tk, i, edit,\r\n\t\tnodes = [];\r\n\r\n\tfor (tk of tokens) {\r\n\t\tnodes.push(new Node(parser, tk));\r\n\t}\r\n\t// Build relationship between nodes\r\n\tfor (i = 0; i < nodes.length; i++) {\r\n\t\tnodes[i].next = nodes[i + 1] || null;\r\n\t\tnodes[i].prev = nodes[i - 1] || null;\r\n\t}\r\n\r\n\tedit = null;\r\n\tfor (i = 0; i < nodes.length; i++) {\r\n\t\tnodes[i].prevEdit = edit;\r\n\t\tif (nodes[i].token.type != \"static\") {\r\n\t\t\tedit = nodes[i];\r\n\t\t}\r\n\t}\r\n\r\n\tedit = null;\r\n\tfor (i = nodes.length - 1; i >= 0; i--) {\r\n\t\tnodes[i].nextEdit = edit;\r\n\t\tif (nodes[i].token.type != \"static\") {\r\n\t\t\tedit = nodes[i];\r\n\t\t}\r\n\t}\r\n\r\n\treturn nodes;\r\n}\r\n\r\nfunction nocopy(o) {\r\n\treturn o;\r\n}\r\n\r\nfunction createNameMap(nodes) {\r\n\tvar map = new Map;\r\n\tfor (var node of nodes) {\r\n\t\tvar l = map.get(node.token.name);\r\n\t\tif (!l) {\r\n\t\t\tl = [];\r\n\t\t\tmap.set(node.token.name, l);\r\n\t\t}\r\n\t\tl.push(node);\r\n\t}\r\n\treturn map;\r\n}\r\n\r\n// a stated text parser\r\nclass TextParser extends Emitter {\r\n\tconstructor() {\r\n\t\tsuper();\r\n\t\tthis._constructor.apply(this, arguments);\r\n\t\tthis.initialize();\r\n\t}\r\n\t\r\n\t_constructor ({tokens, noEmpty = false, value, text, copyValue = nocopy}) {\r\n\t\tif (!tokens || !tokens.length) {\r\n\t\t\tthrow new Error(\"option.tokens is required\");\r\n\t\t}\r\n\t\tthis.tokens = tokens;\r\n\t\tthis.nodes = createNodes(this, tokens);\r\n\t\tthis.nameMap = createNameMap(this.nodes);\r\n\t\tthis.value = value;\r\n\t\tthis.text = text;\r\n\t\tthis.noEmpty = noEmpty;\r\n\t\tthis.copyValue = copyValue;\r\n\t\tthis.err = false;\r\n\t}\r\n\t\r\n\tinitialize() {\r\n\t\tthis.setValue(this.value);\r\n\t}\r\n\r\n\tparse (text) {\r\n\t\tif (!text) {\r\n\t\t\tthrow {\r\n\t\t\t\tcode: \"EMPTY\",\r\n\t\t\t\tmessage: \"The input is empty\",\r\n\t\t\t\toldText: this.text\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tvar result, i;\r\n\t\t\r\n\t\tresult = parseNodes(this.nodes, text);\r\n\r\n\t\t// grab changed nodes\r\n\t\tvar changed = [], comparer;\r\n\t\t\r\n\t\tif (this.err) {\r\n\t\t\tcomparer = parseNodes(this.nodes, this.text);\r\n\t\t} else {\r\n\t\t\tcomparer = this.nodes;\r\n\t\t}\r\n\r\n\t\tfor (i = 0; i < result.length; i++) {\r\n\t\t\tif (!result[i].empty && result[i].viewValue != comparer[i].viewValue) {\r\n\t\t\t\t// expose token for sorting and consistent check\r\n\t\t\t\tresult[i].token = this.nodes[i].token;\r\n\t\t\t\tchanged.push(result[i]);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// grab empty nodes\r\n\t\tvar empties = result.filter(r => r.empty),\r\n\t\t\terrors = result.filter(r => r.err);\r\n\r\n\t\t// copy result value into nodes\r\n\t\tfor (i = 0; i < result.length; i++) {\r\n\t\t\tthis.nodes[i].value = result[i].value;\r\n\t\t\tthis.nodes[i].viewValue = result[i].viewValue;\r\n\t\t\tthis.nodes[i].offset = result[i].pos;\r\n\t\t\tthis.nodes[i].empty = result[i].empty;\r\n\t\t}\r\n\r\n\t\t// throw error\r\n\t\tif (errors.length) {\r\n\t\t\tthis.err = true;\r\n\t\t\tthrow errors[0];\r\n\t\t} else {\r\n\t\t\tthis.err = false;\r\n\t\t}\r\n\r\n\t\t// sort result\r\n\t\tchanged.sort((a, b) => {\r\n\t\t\tif (b.empty) {\r\n\t\t\t\treturn -1;\r\n\t\t\t}\r\n\t\t\tif (a.empty) {\r\n\t\t\t\treturn 1;\r\n\t\t\t}\r\n\t\t\treturn (b.token.prior || 0) - (a.token.prior || 0);\r\n\t\t});\r\n\r\n\t\t// consistent check\r\n\t\tvar c, value = this.copyValue(this.value);\r\n\t\tfor (c of changed) {\r\n\t\t\tvalue = restoreValue(value, c.token, c.value, this);\r\n\t\t}\r\n\r\n\t\tvar newText = formatNodes(value, result).map(r => r.viewValue).join(\"\");\r\n\t\tif (text != newText) {\r\n\t\t\tthis.err = true;\r\n\t\t\tthrow {\r\n\t\t\t\tcode: \"INCONSISTENT_INPUT\",\r\n\t\t\t\tmessage: \"Successfully parsed but the output text doesn't match the input\",\r\n\t\t\t\ttext: text,\r\n\t\t\t\toldText: this.text,\r\n\t\t\t\tproperText: newText\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\t// Done. Manipulate value and text\r\n\t\tthis.text = text;\r\n\t\tthis.value = value;\r\n\r\n\t\tthis.emit(\"change\", this.value);\r\n\r\n\t\t// throw not_init error\r\n\t\tif (empties.length) {\r\n\t\t\tthrow {\r\n\t\t\t\tcode: \"NOT_INIT\",\r\n\t\t\t\tmessage: \"Some nodes are empty\",\r\n\t\t\t\ttext: text,\r\n\t\t\t\tnode: empties[0]\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tsetValue (value, ignoreEmpty = true) {\r\n\t\t// value => text\r\n\t\tvar result = formatNodes(value, this.nodes, ignoreEmpty);\r\n\t\tvar i, pos = 0, text = \"\";\r\n\t\tfor (i = 0; i < result.length; i++) {\r\n\t\t\tthis.nodes[i].value = result[i].value;\r\n\t\t\tthis.nodes[i].viewValue = result[i].viewValue;\r\n\t\t\tthis.nodes[i].offset = pos;\r\n\t\t\tthis.nodes[i].empty = ignoreEmpty ? false : this.nodes[i].empty;\r\n\t\t\tpos += this.nodes[i].viewValue.length;\r\n\t\t\ttext += this.nodes[i].viewValue;\r\n\t\t}\r\n\t\tthis.value = value;\r\n\t\tthis.text = text;\r\n\r\n\t\tthis.emit(\"change\", this.value);\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tisEmpty (text) {\r\n\t\tvar result;\r\n\t\tif (text) {\r\n\t\t\ttry {\r\n\t\t\t\tresult = parseNodes(this.nodes, text);\r\n\t\t\t} catch (err) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tresult = this.nodes;\r\n\t\t}\r\n\t\tvar i;\r\n\t\tfor (i = 0; i < result.length; i++) {\r\n\t\t\tif (this.nodes[i].token.type != \"static\" && !result[i].empty) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\tisInit() {\r\n\t\tvar node;\r\n\t\tfor (node of this.nodes) {\r\n\t\t\tif (node.token.type != \"static\" && node.empty) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\tunset() {\r\n\t\tvar node;\r\n\t\tfor (node of this.nodes) {\r\n\t\t\tnode.empty = true;\r\n\t\t}\r\n\t\tthis.setValue(this.value, false);\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tgetText() {\r\n\t\treturn this.text;\r\n\t}\r\n\r\n\tgetValue() {\r\n\t\treturn this.value;\r\n\t}\r\n\r\n\tgetNodes(name) {\r\n\t\tif (name) {\r\n\t\t\treturn this.nameMap.get(name);\r\n\t\t}\r\n\t\treturn this.nodes;\r\n\t}\r\n}\r\n\r\nmodule.exports = {\r\n\tTextParser\r\n};\r\n","var {Emitter} = require(\"./utils\");\r\n\r\nfunction findNearestNode(i, nodes) {\r\n\tif (!nodes.length) return;\r\n\r\n\tvar [left, right] = matchNodes(nodes, i).map(r => r.node);\r\n\r\n\tif (left == right) {\r\n\t\treturn left;\r\n\t}\r\n\r\n\tif (i - left.offset - left.viewValue.length <= right.offset - i) {\r\n\t\treturn left;\r\n\t}\r\n\r\n\treturn right;\r\n}\r\n\r\nfunction matchNodes(nodes, start, end = start) {\r\n\tvar node, left, right;\r\n\r\n\tfor (node of nodes) {\r\n\t\tif (node.offset <= start) {\r\n\t\t\tleft = {\r\n\t\t\t\tnode: node,\r\n\t\t\t\tpos: start - node.offset\r\n\t\t\t};\r\n\t\t}\r\n\t\tif (node.offset + node.viewValue.length >= end && !right) {\r\n\t\t\tright = {\r\n\t\t\t\tnode: node,\r\n\t\t\t\tpos: end - node.offset\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n\r\n\tif (!right) {\r\n\t\tvar last = nodes[nodes.length - 1];\r\n\t\tright = {\r\n\t\t\tnode: last,\r\n\t\t\tpos: last.viewValue.length\r\n\t\t};\r\n\t}\r\n\r\n\tif (!left) {\r\n\t\tvar first = nodes[0];\r\n\t\tleft = {\r\n\t\t\tnode: first,\r\n\t\t\tpos: 0\r\n\t\t};\r\n\t}\r\n\r\n\tif (left.pos > left.node.viewValue.length) {\r\n\t\tleft.pos = left.node.viewValue.length;\r\n\t}\r\n\r\n\treturn [left, right];\r\n}\r\n\r\nclass Selection {\r\n\tconstructor(element, nodes) {\r\n\t\tthis.el = element;\r\n\t\tthis.nodes = nodes;\r\n\t\tthis.range = {\r\n\t\t\tnode: findNearestNode(0, this.nodes),\r\n\t\t\tstart: 0,\r\n\t\t\tend: \"end\"\r\n\t\t};\r\n\t}\r\n\tselectNearestNode() {\r\n\t\tvar range = this.el.getSelection();\r\n\t\tif (!range) return;\r\n\t\t\r\n\t\tthis.select({\r\n\t\t\tnode: findNearestNode(range.start, this.nodes),\r\n\t\t\tstart: 0,\r\n\t\t\tend: \"end\"\r\n\t\t});\r\n\t}\r\n\tselect(range) {\r\n\t\trange = Object.assign(this.range, range);\r\n\t\tif (range.node) {\r\n\t\t\tthis.el.setSelection(\r\n\t\t\t\trange.node.offset + range.start,\r\n\t\t\t\trange.node.offset + (range.end == \"end\" ? range.node.viewValue.length : range.end)\r\n\t\t\t);\r\n\t\t}\r\n\t}\r\n\thasNext() {\r\n\t\tif (this.range.node) {\r\n\t\t\treturn this.range.node.nextEdit;\r\n\t\t}\r\n\t}\r\n\thasPrev() {\r\n\t\tif (this.range.node) {\r\n\t\t\treturn this.range.node.prevEdit;\r\n\t\t}\r\n\t}\r\n\tselectNext() {\r\n\t\tvar node = this.hasNext(),\r\n\t\t\trange = {start: 0, end: \"end\"};\r\n\t\tif (node) {\r\n\t\t\trange.node = node;\r\n\t\t}\r\n\t\tthis.select(range);\r\n\t}\r\n\tselectPrev() {\r\n\t\tvar node = this.hasPrev(),\r\n\t\t\trange = {start: 0, end: \"end\"};\r\n\t\tif (node) {\r\n\t\t\trange.node = node;\r\n\t\t}\r\n\t\tthis.select(range);\r\n\t}\r\n\tget() {\r\n\t\tif (!this.nodes.length) return;\r\n\t\t\r\n\t\tvar range = this.el.getSelection();\r\n\t\t\r\n\t\tif (!range) return;\r\n\r\n\t\tvar [left, right] = matchNodes(this.nodes, range.start, range.end);\r\n\r\n\t\tif (left.node == right.node) {\r\n\t\t\tthis.range = {\r\n\t\t\t\tnode: left.node,\r\n\t\t\t\tstart: left.pos,\r\n\t\t\t\tend: right.pos\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n\tatNodeEnd() {\r\n\t\tif (!this.range.node) return;\r\n\r\n\t\tthis.get();\r\n\r\n\t\tvar len = this.range.node.viewValue.length,\r\n\t\t\tmax = this.range.node.token.maxLength,\r\n\t\t\tstart = this.range.start == \"end\" ? len : this.range.start,\r\n\t\t\tend = this.range.end == \"end\" ? len : this.range.end;\r\n\r\n\t\treturn start == end && start == (max != null ? max : len) || !len;\r\n\t}\r\n\tatNodeStart() {\r\n\t\tif (!this.range.node) return;\r\n\r\n\t\tthis.get();\r\n\r\n\t\tvar len = this.range.node.viewValue.length,\r\n\t\t\tstart = this.range.start == \"end\" ? len : this.range.start,\r\n\t\t\tend = this.range.end == \"end\" ? len : this.range.end;\r\n\r\n\t\treturn start == end && start == 0;\r\n\t}\r\n}\r\n\r\nclass InputMask extends Emitter {\r\n\r\n\tconstructor() {\r\n\t\tsuper();\r\n\t\tthis._constructor.apply(this, arguments);\r\n\t\tthis.initialize();\r\n\t}\r\n\r\n\t_constructor(element, textParser, separators = \"\") {\r\n\t\tthis.el = element;\r\n\t\tthis.tp = textParser;\r\n\t\tthis.separators = separators;\r\n\t\tthis.sel = new Selection(element, textParser.getNodes().filter(n => n.token.type != \"static\"));\r\n\t}\r\n\r\n\tinitialize() {\r\n\t\tthis.el.on(\"mousedown\", () => {\r\n\t\t\tthis.mousedown = true;\r\n\t\t});\r\n\r\n\t\tthis.el.on(\"focus\", () => {\r\n\t\t\tif (this.mousedown) return;\t// wait mouseup then decide range\r\n\t\t\tsetTimeout(() => {\r\n\t\t\t\tthis.sel.select({\r\n\t\t\t\t\tstart: 0,\r\n\t\t\t\t\tend: \"end\"\r\n\t\t\t\t});\r\n\t\t\t});\r\n\t\t});\r\n\r\n\t\tthis.el.on(\"click\", () => {\r\n\t\t\tthis.mousedown = false;\r\n\t\t\tthis.sel.selectNearestNode();\r\n\t\t});\r\n\r\n\t\tthis.el.on(\"input\", () => {\r\n\t\t\tthis.digest(null, this.el.val());\r\n\t\t});\r\n\r\n\t\tthis.el.on(\"keydown\", (e) => {\r\n\t\t\tif (e.altKey || e.ctrlKey) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tif (e.keyCode == 37 || e.keyCode == 9 && e.shiftKey && this.sel.hasPrev()) {\r\n\t\t\t\t// Left, Shift + Tab\r\n\t\t\t\te.preventDefault();\r\n\t\t\t\tthis.tryFixingError();\r\n\t\t\t\tthis.sel.selectPrev();\r\n\t\t\t} else if (e.keyCode == 39 || e.keyCode == 9 && !e.shiftKey && this.sel.hasNext()) {\r\n\t\t\t\t// Right, Tab\r\n\t\t\t\te.preventDefault();\r\n\t\t\t\tthis.tryFixingError();\r\n\t\t\t\tthis.sel.selectNext();\r\n\t\t\t} else if (e.keyCode == 38) {\r\n\t\t\t\t// Up\r\n\t\t\t\te.preventDefault();\r\n\t\t\t\tthis.sel.selectNearestNode();\r\n\t\t\t\tif (this.sel.range.node) {\r\n\t\t\t\t\t// this.err = null;\r\n\t\t\t\t\tthis.sel.range.node.add(1);\r\n\t\t\t\t}\r\n\t\t\t\tthis.val(this.tp.getText());\r\n\t\t\t\tthis.sel.select({\r\n\t\t\t\t\tstart: 0,\r\n\t\t\t\t\tend: \"end\"\r\n\t\t\t\t});\r\n\t\t\t} else if (e.keyCode == 40) {\r\n\t\t\t\t// Down\r\n\t\t\t\te.preventDefault();\r\n\t\t\t\tthis.sel.selectNearestNode();\r\n\t\t\t\tif (this.sel.range.node) {\r\n\t\t\t\t\t// this.err = null;\r\n\t\t\t\t\tthis.sel.range.node.add(-1);\r\n\t\t\t\t}\r\n\t\t\t\tthis.val(this.tp.getText());\r\n\t\t\t\tthis.sel.select({\r\n\t\t\t\t\tstart: 0,\r\n\t\t\t\t\tend: \"end\"\r\n\t\t\t\t});\r\n\t\t\t} else if (e.keyCode == 36 || e.keyCode == 35) {\r\n\t\t\t\t// Home or End\r\n\t\t\t\tsetTimeout(() => this.sel.selectNearestNode());\r\n\t\t\t} else if (e.keyCode == 46) {\r\n\t\t\t\t// Del\r\n\t\t\t\tif (this.sel.atNodeEnd()) {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tthis.tryFixingError();\r\n\t\t\t\t\tthis.sel.selectNext();\r\n\t\t\t\t}\r\n\t\t\t} else if (e.keyCode == 8) {\r\n\t\t\t\t// Backspace\r\n\t\t\t\tif (this.sel.atNodeStart()) {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tthis.tryFixingError();\r\n\t\t\t\t\tthis.sel.selectPrev();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tthis.el.on(\"keypress\", e => {\r\n\t\t\tvar charCode = e.charCode == null ? e.keyCode : e.charCode,\r\n\t\t\t\tkey = String.fromCharCode(charCode),\r\n\t\t\t\tseparators = this.separators,\r\n\t\t\t\tnode = this.sel.range.node;\r\n\r\n\t\t\t// check for separator only when there is a next node which is static string\r\n\t\t\tif (node && node.next && node.next.token.type == \"static\") {\r\n\t\t\t\tseparators += node.next.viewValue[0];\r\n\t\t\t}\r\n\r\n\t\t\tif (separators.includes(key)) {\r\n\t\t\t\te.preventDefault();\r\n\t\t\t\tthis.tryFixingError();\r\n\t\t\t\tthis.sel.selectNext();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tsetTimeout(() => {\r\n\t\t\t\tif (this.sel.atNodeEnd() && this.sel.range.node.viewValue) {\r\n\t\t\t\t\tthis.tryFixingError();\r\n\t\t\t\t\tthis.sel.selectNext();\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t});\r\n\r\n\t\tthis.el.on(\"blur\", () => {\r\n\t\t\tsetTimeout(() => {\r\n\t\t\t\tthis.tryFixingError();\r\n\t\t\t});\r\n\t\t});\r\n\r\n\t\tthis.tp.on(\"change\", () => {\r\n\t\t\tif (!this.err && !this.inDigest) {\r\n\t\t\t\tthis.val(this.tp.getText());\r\n\t\t\t\tthis.sel.select();\r\n\t\t\t}\r\n\t\t});\r\n\t\t\r\n\t\t// Init value\r\n\t\tvar text = this.el.val();\r\n\t\tif (text) {\r\n\t\t\tthis.digest(null, text, true);\r\n\t\t} else {\r\n\t\t\tthis.val(this.tp.getText());\r\n\t\t}\r\n\t}\r\n\terrorViewLength() {\r\n\t\tif (this.err && this.err.viewValue != null) {\r\n\t\t\treturn this.err.viewValue.length;\r\n\t\t}\r\n\t\treturn undefined;\r\n\t}\r\n\tval(text) {\r\n\t\tif (this.el.val() != text) {\r\n\t\t\tthis.el.val(text);\r\n\t\t}\r\n\t\tthis.err = null;\r\n\t}\r\n\ttryFixingError() {\r\n\t\tif (!this.err) return;\r\n\r\n\t\tif (this.err.properValue) {\r\n\t\t\tthis.digest(this.err.node, this.err.properValue, true);\r\n\r\n\t\t} else if (this.err.node) {\r\n\t\t\tthis.err.node.unset();\r\n\t\t\tthis.digest(null, this.tp.getText());\r\n\t\t}\r\n\t}\r\n\tdigest(node, text, fixErr) {\r\n\t\tvar digest = 10,\r\n\t\t\trange;\r\n\r\n\t\tthis.inDigest = true;\r\n\r\n\t\twhile (digest--) {\r\n\t\t\tthis.err = null;\r\n\t\t\ttry {\r\n\t\t\t\tif (node) {\r\n\t\t\t\t\tnode.parse(text);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis.tp.parse(text);\r\n\t\t\t\t}\r\n\t\t\t} catch (err) {\r\n\t\t\t\tthis.emit(\"digest\", err);\r\n\t\t\t\t\r\n\t\t\t\tthis.sel.get();\r\n\r\n\t\t\t\tif (err.code == \"NOT_INIT\") {\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.err = err;\r\n\r\n\t\t\t\tif (!fixErr && (err.code == \"NUMBER_TOOSHORT\" || err.code == \"NUMBER_TOOSMALL\" || err.code == \"NUMBER_MISMATCH\" || err.code == \"SELECT_MISMATCH\" || err.code == \"LEADING_ZERO\")) {\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (err.code == \"SELECT_INCOMPLETE\") {\r\n\t\t\t\t\tnode = err.node;\r\n\t\t\t\t\ttext = err.selected;\r\n\t\t\t\t\trange = {end: \"end\"};\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (err.properValue != null) {\r\n\t\t\t\t\tnode = err.node;\r\n\t\t\t\t\ttext = err.properValue;\r\n\t\t\t\t} else if (err.properText != null) {\r\n\t\t\t\t\tnode = null;\r\n\t\t\t\t\ttext = err.properText;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tif (err.code == \"EMPTY\") {\r\n\t\t\t\t\t\tthis.tp.unset();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (err.node) {\r\n\t\t\t\t\t\terr.node.unset();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tnode = null;\r\n\t\t\t\t\ttext = this.tp.getText();\r\n\t\t\t\t\trange = {start: 0, end: \"end\"};\r\n\t\t\t\t}\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tif (!this.err) {\r\n\t\t\tthis.val(this.tp.getText());\r\n\t\t\tif (digest < 9) {\r\n\t\t\t\tthis.sel.select(range);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.inDigest = false;\r\n\r\n\t\tif (digest < 0) {\r\n\t\t\tthrow new Error(`InputMask.digest crashed! Infinite loop on ${text}`);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nmodule.exports = {\r\n\tInputMask\r\n};\r\n","module.exports = {\r\n\tTextParser: require(\"./lib/text-parser\").TextParser,\r\n\tInputMask: require(\"./lib/input-mask\").InputMask,\r\n\tutils: require(\"./lib/utils\")\r\n};\r\n","var angular = require(\"angular\"),\r\n\t{TextParser} = require(\"custom-input\"),\r\n\t{num2str} = require(\"custom-input/lib/utils\");\r\n\r\nangular.module(\"datetime\").factory(\"datetime\", init);\r\ninit.$inject = [\"$locale\", \"datetimePlaceholder\"];\r\nfunction init($locale, datetimePlaceholder) {\r\n\t// Fetch date and time formats from $locale service\r\n\tvar formats = $locale.DATETIME_FORMATS;\r\n\t// Valid format tokens. 1=sss, 2=''\r\n\tvar tokenRE = /yyyy|yy|y|M{1,4}|dd?|EEEE?|HH?|hh?|mm?|ss?|([.,])sss|a|Z{1,2}|ww|w|'(([^']+|'')*)'/g;\r\n\t// Token definition\r\n\tvar definedTokens = {\r\n\t\t\"y\": {\r\n\t\t\tminLength: 1,\r\n\t\t\tmaxLength: 4,\r\n\t\t\tmax: 9999,\r\n\t\t\tmin: 0,\r\n\t\t\tname: \"year\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"yy\": {\r\n\t\t\tminLength: 2,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tname: \"yearShort\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"yyyy\": {\r\n\t\t\tminLength: 4,\r\n\t\t\tmaxLength: 4,\r\n\t\t\tmax: 9999,\r\n\t\t\tmin: 0,\r\n\t\t\tname: \"year\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"MMMM\": {\r\n\t\t\tname: \"month\",\r\n\t\t\ttype: \"select\",\r\n\t\t\tselect: formats.MONTH\r\n\t\t},\r\n\t\t\"MMM\": {\r\n\t\t\tname: \"month\",\r\n\t\t\ttype: \"select\",\r\n\t\t\tselect: formats.SHORTMONTH\r\n\t\t},\r\n\t\t\"MM\": {\r\n\t\t\tminLength: 2,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tname: \"month\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"M\": {\r\n\t\t\tminLength: 1,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tname: \"month\",\r\n\t\t\ttype: \"number\",\r\n\t\t\tmin: 1\r\n\t\t},\r\n\t\t\"dd\": {\r\n\t\t\tminLength: 2,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tname: \"date\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"d\": {\r\n\t\t\tminLength: 1,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tname: \"date\",\r\n\t\t\ttype: \"number\",\r\n\t\t\tmin: 1\r\n\t\t},\r\n\t\t\"EEEE\": {\r\n\t\t\tname: \"day\",\r\n\t\t\ttype: \"select\",\r\n\t\t\tselect: fixDay(formats.DAY)\r\n\t\t},\r\n\t\t\"EEE\": {\r\n\t\t\tname: \"day\",\r\n\t\t\ttype: \"select\",\r\n\t\t\tselect: fixDay(formats.SHORTDAY)\r\n\t\t},\r\n\t\t\"HH\": {\r\n\t\t\tminLength: 2,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tname: \"hour\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"H\": {\r\n\t\t\tminLength: 1,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tname: \"hour\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"hh\": {\r\n\t\t\tminLength: 2,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tname: \"hour12\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"h\": {\r\n\t\t\tminLength: 1,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tname: \"hour12\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"mm\": {\r\n\t\t\tminLength: 2,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tname: \"minute\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"m\": {\r\n\t\t\tminLength: 1,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tname: \"minute\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"ss\": {\r\n\t\t\tminLength: 2,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tname: \"second\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"s\": {\r\n\t\t\tminLength: 1,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tname: \"second\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"sss\": {\r\n\t\t\tminLength: 3,\r\n\t\t\tmaxLength: 3,\r\n\t\t\tname: \"millisecond\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"a\": {\r\n\t\t\tname: \"ampm\",\r\n\t\t\ttype: \"select\",\r\n\t\t\tselect: formats.AMPMS\r\n\t\t},\r\n\t\t\"ww\": {\r\n\t\t\tminLength: 2,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tmax: 53,\r\n\t\t\tname: \"week\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"w\": {\r\n\t\t\tminLength: 1,\r\n\t\t\tmaxLength: 2,\r\n\t\t\tmax: 53,\r\n\t\t\tname: \"week\",\r\n\t\t\ttype: \"number\"\r\n\t\t},\r\n\t\t\"Z\": {\r\n\t\t\tname: \"timezone\",\r\n\t\t\ttype: \"static\"\r\n\t\t},\r\n\t\t\"ZZ\": {\r\n\t\t\tname: \"timezone\",\r\n\t\t\ttype: \"static\",\r\n\t\t\tcolon: true\r\n\t\t},\r\n\t\t\"string\": {\r\n\t\t\tname: \"string\",\r\n\t\t\ttype: \"static\"\r\n\t\t}\r\n\t};\r\n\t\r\n\tvar nameConf = {\r\n\t\tyear: {\r\n\t\t\textract: d => {\r\n\t\t\t\t// year might be negative\r\n\t\t\t\tvar v = d.getFullYear() % 10000;\r\n\t\t\t\treturn v >= 0 ? v : 0;\r\n\t\t\t},\r\n\t\t\trestore: (d, v) => d.setFullYear(v),\r\n\t\t\tadd: (d, v) => d.setFullYear(d.getFullYear() + v),\r\n\t\t\tprior: 7\r\n\t\t},\r\n\t\tyearShort: {\r\n\t\t\textract: d => {\r\n\t\t\t\tvar v = d.getFullYear() % 100;\r\n\t\t\t\treturn v >= 0 ? v : v + 100;\r\n\t\t\t},\r\n\t\t\trestore: (d, v) => d.setFullYear(v),\r\n\t\t\tadd: (d, v) => d.setFullYear(d.getFullYear() + v),\r\n\t\t\tprior: 7\r\n\t\t},\r\n\t\tmonth: {\r\n\t\t\textract: d => d.getMonth() + 1,\r\n\t\t\trestore: (d, v) => {\r\n\t\t\t\t// http://stackoverflow.com/questions/14680396/the-date-getmonth-method-has-bug\r\n\t\t\t\td.setMonth(v - 1);\r\n\t\t\t\t// handle date overflow\r\n\t\t\t\tif (d.getMonth() == v) {\r\n\t\t\t\t\td.setDate(0);\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tadd: (d, v) => {\r\n\t\t\t\tv = d.getMonth() + v;\r\n\t\t\t\td.setMonth(v);\r\n\t\t\t\t// date overflow\r\n\t\t\t\tif (d.getMonth() == v + 1) {\r\n\t\t\t\t\td.setDate(0);\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tprior: 5\r\n\t\t},\r\n\t\tdate: {\r\n\t\t\textract: d => d.getDate(),\r\n\t\t\trestore: (d, v, p) => {\r\n\t\t\t\t// handle overflowed day\r\n\t\t\t\tvar oldMonth = d.getMonth();\r\n\t\t\t\td.setDate(v);\r\n\t\t\t\tif (d.getMonth() != oldMonth && v <= 31) {\r\n\t\t\t\t\tvar monthNodes = p.getNodes(\"month\");\r\n\t\t\t\t\tif (monthNodes && monthNodes.every(n => n.empty)) {\r\n\t\t\t\t\t\td.setDate(v);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tadd(d, v, p) {\r\n\t\t\t\tthis.restore(d, d.getDate() + v, p);\r\n\t\t\t},\r\n\t\t\tprior: 4\r\n\t\t},\r\n\t\tday: {\r\n\t\t\textract: d => d.getDay() || 7,\r\n\t\t\trestore: setDay,\r\n\t\t\tadd: (d, v) => d.setDate(d.getDate() + v),\r\n\t\t\tprior: 4\r\n\t\t},\r\n\t\thour: {\r\n\t\t\textract: d => d.getHours(),\r\n\t\t\trestore: (d, v) => d.setHours(v),\r\n\t\t\tadd: (d, v) => d.setHours(d.getHours() + v),\r\n\t\t\tprior: 2\r\n\t\t},\r\n\t\thour12: {\r\n\t\t\textract: d => d.getHours() % 12 || 12,\r\n\t\t\trestore: setHour12,\r\n\t\t\tadd: (d, v) => d.setHours(d.getHours() + v),\r\n\t\t\tprior: 2\r\n\t\t},\r\n\t\tampm: {\r\n\t\t\textract: d => d.getHours() < 12 ? 1 : 2,\r\n\t\t\trestore: setAmpm,\r\n\t\t\tadd: (d, v) => d.setHours(d.getHours() + v * 12),\r\n\t\t\tprior: 3\r\n\t\t},\r\n\t\tminute: {\r\n\t\t\textract: d => d.getMinutes(),\r\n\t\t\trestore: (d, v) => d.setMinutes(v),\r\n\t\t\tadd: (d, v) => d.setMinutes(d.getMinutes() + v),\r\n\t\t\tprior: 0\r\n\t\t},\r\n\t\tsecond: {\r\n\t\t\textract: d => d.getSeconds(),\r\n\t\t\trestore: (d, v) => d.setSeconds(v),\r\n\t\t\tadd: (d, v) => d.setSeconds(d.getSeconds() + v),\r\n\t\t\tprior: 1\r\n\t\t},\r\n\t\tmillisecond: {\r\n\t\t\textract: d => d.getMilliseconds(),\r\n\t\t\trestore: (d, v) => d.setMilliseconds(v),\r\n\t\t\tadd: (d, v) => d.setMilliseconds(d.getMilliseconds() + v),\r\n\t\t\tprior: 1\r\n\t\t},\r\n\t\tweek: {\r\n\t\t\textract: getWeek,\r\n\t\t\trestore: (d, v) => d.setDate(d.getDate() + (v - getWeek(d)) * 7),\r\n\t\t\tadd: (d, v) => d.setDate(d.getDate() + v * 7),\r\n\t\t\tprior: 6\r\n\t\t}\r\n\t};\r\n\t\r\n\t// setup placeholder\r\n\tfor (var name in nameConf) {\r\n\t\tnameConf[name].placeholder = datetimePlaceholder[name];\r\n\t}\r\n\t\r\n\t// setup tokens\r\n\tfor (var tk of Object.values(definedTokens)) {\r\n\t\tif (nameConf[tk.name]) {\r\n\t\t\tangular.extend(tk, nameConf[tk.name]);\r\n\t\t}\r\n\t}\r\n\t\r\n\tvar SYS_TIMEZONE = (function(){\r\n\t\tvar offset = -(new Date).getTimezoneOffset(),\r\n\t\t\tsign = offset >= 0 ? \"+\" : \"-\",\r\n\t\t\tabsOffset = Math.abs(offset),\r\n\t\t\thour = Math.floor(absOffset / 60),\r\n\t\t\tmin = absOffset % 60;\r\n\t\treturn sign + num2str(hour, 2, 2) + num2str(min, 2, 2);\r\n\t})();\r\n\r\n\t// Push Sunday to the end\r\n\tfunction fixDay(days) {\r\n\t\tvar s = [], i;\r\n\t\tfor (i = 1; i < days.length; i++) {\r\n\t\t\ts.push(days[i]);\r\n\t\t}\r\n\t\ts.push(days[0]);\r\n\t\treturn s;\r\n\t}\r\n\r\n\t// Split format into multiple tokens\r\n\tfunction createTokens(format) {\r\n\t\tvar tokens = [],\r\n\t\t\tpos = 0,\r\n\t\t\tmatch;\r\n\t\t\t\r\n\t\twhile ((match = tokenRE.exec(format))) {\r\n\t\t\tif (match.index > pos) {\r\n\t\t\t\t// doesn't match any token, static string\r\n\t\t\t\ttokens.push(angular.extend({\r\n\t\t\t\t\tvalue: format.substring(pos, match.index)\r\n\t\t\t\t}, definedTokens.string));\r\n\t\t\t\tpos = match.index;\r\n\t\t\t} \r\n\r\n\t\t\tif (match.index == pos) {\r\n\t\t\t\tif (match[1]) {\r\n\t\t\t\t\t// sss\r\n\t\t\t\t\ttokens.push(angular.extend({\r\n\t\t\t\t\t\tvalue: match[1]\r\n\t\t\t\t\t}, definedTokens.string));\r\n\t\t\t\t\ttokens.push(definedTokens.sss);\r\n\t\t\t\t} else if (match[2]) {\r\n\t\t\t\t\t// escaped string\r\n\t\t\t\t\ttokens.push(angular.extend({\r\n\t\t\t\t\t\tvalue: match[2].replace(\"''\", \"'\")\r\n\t\t\t\t\t}, definedTokens.string));\r\n\t\t\t\t} else if (definedTokens[match[0]].name == \"timezone\") {\r\n\t\t\t\t\t// static timezone\r\n\t\t\t\t\tvar tz = SYS_TIMEZONE;\r\n\t\t\t\t\tif (definedTokens[match[0]].colon) {\r\n\t\t\t\t\t\ttz = insertColon(tz);\r\n\t\t\t\t\t}\r\n\t\t\t\t\ttokens.push(angular.extend({\r\n\t\t\t\t\t\tvalue: tz\r\n\t\t\t\t\t}, definedTokens[match[0]]));\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// other tokens\r\n\t\t\t\t\ttokens.push(definedTokens[match[0]]);\r\n\t\t\t\t}\r\n\t\t\t\tpos = tokenRE.lastIndex;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif (pos < format.length) {\r\n\t\t\ttokens.push(angular.extend({\r\n\t\t\t\tvalue: format.substring(pos)\r\n\t\t\t}, definedTokens.string));\r\n\t\t}\r\n\t\t\r\n\t\treturn tokens;\r\n\t}\r\n\r\n\tfunction getWeek(date) {\r\n\t\tvar yearStart = new Date(date.getFullYear(), 0, 1);\r\n\r\n\t\tvar weekStart = new Date(yearStart.getTime());\r\n\r\n\t\tif (weekStart.getDay() > 4) {\r\n\t\t\tweekStart.setDate(weekStart.getDate() + (1 - weekStart.getDay()) + 7);\r\n\t\t} else {\r\n\t\t\tweekStart.setDate(weekStart.getDate() + (1 - weekStart.getDay()));\r\n\t\t}\r\n\t\tvar diff = date.getTime() - weekStart.getTime();\r\n\r\n\t\treturn Math.floor(diff / (7 * 24 * 60 * 60 * 1000));\r\n\t}\r\n\r\n\t// set the proper date value matching the weekday\r\n\tfunction setDay(date, day) {\r\n\t\t// we don't want to change month when changing date\r\n\t\tvar month = date.getMonth(),\r\n\t\t\tdiff = day - (date.getDay() || 7);\r\n\t\t// move to correct date\r\n\t\tdate.setDate(date.getDate() + diff);\r\n\t\t// check month\r\n\t\tif (date.getMonth() != month) {\r\n\t\t\tif (diff > 0) {\r\n\t\t\t\tdate.setDate(date.getDate() - 7);\r\n\t\t\t} else {\r\n\t\t\t\tdate.setDate(date.getDate() + 7);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfunction setHour12(date, hour) {\r\n\t\thour = hour % 12;\r\n\t\tif (date.getHours() >= 12) {\r\n\t\t\thour += 12;\r\n\t\t}\r\n\t\tdate.setHours(hour);\r\n\t}\r\n\r\n\tfunction setAmpm(date, ampm) {\r\n\t\tvar hour = date.getHours();\r\n\t\tif ((hour < 12) == (ampm > 1)) {\r\n\t\t\tdate.setHours((hour + 12) % 24);\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction insertColon(timezone) {\r\n\t\tif (timezone[3] == \":\") {\r\n\t\t\treturn timezone;\r\n\t\t}\r\n\t\treturn timezone.substr(0, 3) + \":\" + timezone.substr(3, 2);\r\n\t}\r\n\t\r\n\tfunction removeColon(timezone) {\r\n\t\tif (timezone[3] != \":\") {\r\n\t\t\treturn timezone;\r\n\t\t}\r\n\t\treturn timezone.substr(0, 3) + timezone.substr(4, 2);\r\n\t}\r\n\t\r\n\tfunction offset(date, timezone) {\r\n\t\ttimezone = removeColon(timezone);\r\n\t\tvar hour = +timezone.substr(1, 2),\r\n\t\t\tmin = +timezone.substr(3, 2),\r\n\t\t\tsig = (timezone[0] + \"1\"),\r\n\t\t\toffset = (hour * 60 + min) * sig;\r\n\t\t\t\r\n\t\treturn new Date(date.getTime() + (offset - -date.getTimezoneOffset()) * 60 * 1000);\r\n\t}\r\n\t\r\n\tfunction deoffset(date, timezone) {\r\n\t\ttimezone = removeColon(timezone);\r\n\t\tvar hour = +timezone.substr(1, 2),\r\n\t\t\tmin = +timezone.substr(3, 2),\r\n\t\t\tsig = (timezone[0] + \"1\"),\r\n\t\t\toffset = (hour * 60 + min) * sig;\r\n\t\t\r\n\t\treturn new Date(date.getTime() + (-date.getTimezoneOffset() - offset) * 60 * 1000);\r\n\t}\r\n\t\r\n\tclass DatetimeParser {\r\n\t\t// Apply timezone offset\r\n\t\tconstructor(tp) {\r\n\t\t\tthis.tp = tp;\r\n\t\t\tthis.timezone = SYS_TIMEZONE;\r\n\t\t\tthis.timezoneNodes = this.tp.nodes.filter(n => n.token.name == \"timezone\");\r\n\t\t}\r\n\t\tparse(text) {\r\n\t\t\tthis.tp.parse(text);\r\n\t\t\treturn this;\r\n\t\t}\r\n\t\tgetText() {\r\n\t\t\treturn this.tp.getText();\r\n\t\t}\r\n\t\tsetDate(date, ignoreEmpty) {\r\n\t\t\tthis.tp.setValue(offset(date, this.timezone), ignoreEmpty);\r\n\t\t\treturn this;\r\n\t\t}\r\n\t\tgetDate() {\r\n\t\t\treturn deoffset(this.tp.getValue(), this.timezone);\r\n\t\t}\r\n\t\tsetTimezone(timezone = SYS_TIMEZONE) {\r\n\t\t\tif (timezone == this.timezone) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tvar date = this.getDate();\r\n\t\t\tthis.timezone = timezone;\r\n\t\t\tfor (var n of this.timezoneNodes) {\r\n\t\t\t\tif (n.token.colon) {\r\n\t\t\t\t\tn.token.value = insertColon(timezone);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tn.token.value = removeColon(timezone);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn this.setDate(date, false);\r\n\t\t}\r\n\t\tisEmpty() {\r\n\t\t\treturn this.tp.isEmpty.apply(this.tp, arguments);\r\n\t\t}\r\n\t\tisInit() {\t\t\t\r\n\t\t\treturn this.tp.isInit.apply(this.tp, arguments);\r\n\t\t}\r\n\t\tunset() {\r\n\t\t\tthis.tp.unset();\r\n\t\t\treturn this;\r\n\t\t}\r\n\t}\r\n\t\r\n\tfunction createParser(format) {\r\n\t\tvar tokens = createTokens(formats[format] || format),\r\n\t\t\tyearCheck;\r\n\t\t\t\r\n\t\tif (tokens.some(t => t.name == \"yearShort\")) {\r\n\t\t\tyearCheck = function(fn) {\r\n\t\t\t\treturn function(d) {\r\n\t\t\t\t\tfn.apply(this, arguments);\r\n\t\t\t\t\tvar y = d.getFullYear();\r\n\t\t\t\t\tif (y < 0) {\r\n\t\t\t\t\t\td.setFullYear(y + 100);\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\t\t\t};\r\n\t\t} else {\r\n\t\t\tyearCheck = function(fn) {\r\n\t\t\t\treturn function(d) {\r\n\t\t\t\t\tfn.apply(this, arguments);\r\n\t\t\t\t\tvar y = d.getFullYear();\r\n\t\t\t\t\tif (y < 0) {\r\n\t\t\t\t\t\td.setFullYear(0);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (y > 9999) {\r\n\t\t\t\t\t\td.setFullYear(9999);\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\t\t\t};\r\n\t\t}\r\n\t\t\r\n\t\tfor (var tk of tokens) {\r\n\t\t\tif (tk.add) {\r\n\t\t\t\ttk.add = yearCheck(tk.add);\r\n\t\t\t}\r\n\t\t\tif (tk.restore) {\r\n\t\t\t\ttk.restore = yearCheck(tk.restore);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tvar tp = new TextParser({\r\n\t\t\ttokens: tokens,\r\n\t\t\tvalue: new Date,\r\n\t\t\tcopyValue: o => new Date(o.getTime())\r\n\t\t});\r\n\t\t\r\n\t\treturn new DatetimeParser(tp);\r\n\t}\r\n\r\n\treturn createParser;\r\n}\r\n","var angular = require(\"angular\"),\r\n\t{InputMask} = require(\"custom-input\");\r\n\r\nangular.module(\"datetime\").directive(\"datetime\", init);\r\ninit.$inject = [\"datetime\", \"$log\", \"$document\"];\r\nfunction init(datetime, $log, $document){\r\n\tclass Element {\r\n\t\tconstructor(element, document) {\r\n\t\t\tthis.el = element;\r\n\t\t\tthis.doc = document;\r\n\t\t}\r\n\t\ton(eventType, callback) {\r\n\t\t\t// use ngModel.parser to execute digest\r\n\t\t\tif (eventType == \"input\") return;\r\n\r\n\t\t\treturn this.el.on(eventType, callback);\r\n\t\t}\r\n\t\tgetSelection() {\r\n\t\t\tvar el = this.el[0],\r\n\t\t\t\tdoc = this.doc;\r\n\r\n\t\t\tif (doc.activeElement != el) return;\r\n\r\n\t\t\tvar start = el.selectionStart,\r\n\t\t\t\tend = el.selectionEnd;\r\n\r\n\t\t\tif (angular.isDefined(start) && angular.isDefined(end)) {\r\n\t\t\t\treturn { start, end };\r\n\t\t\t}\r\n\t\t\treturn this.getSelectionIE();\r\n\t\t}\r\n\t\tgetSelectionIE() {\r\n\t\t\tvar el = this.el[0],\r\n\t\t\t\tdoc = this.doc;\r\n\r\n\t\t\tvar bookmark = doc.selection.createRange().getBookmark(),\r\n\t\t\t\trange = el.createTextRange(),\r\n\t\t\t\trange2 = range.duplicate();\r\n\r\n\t\t\trange.moveToBookmark(bookmark);\r\n\t\t\trange2.setEndPoint(\"EndToStart\", range);\r\n\r\n\t\t\tvar start = range2.text.length,\r\n\t\t\t\tend = start + range.text.length;\r\n\r\n\t\t\treturn { start, end };\r\n\t\t}\r\n\t\tsetSelection(start, end) {\r\n\t\t\tvar el = this.el[0],\r\n\t\t\t\tdoc = this.doc;\r\n\r\n\t\t\tif (doc.activeElement != el) return;\r\n\t\t\t\r\n\t\t\tif (el.setSelectionRange) {\r\n\t\t\t\tel.setSelectionRange(start, end);\r\n\t\t\t} else {\r\n\t\t\t\tthis.setSelectionIE(start, end);\r\n\t\t\t}\r\n\t\t}\r\n\t\tsetSelectionIE(start, end) {\r\n\t\t\tvar el = this.el[0],\r\n\t\t\t\tselect = el.createTextRange();\r\n\r\n\t\t\tselect.moveStart(\"character\", start);\r\n\t\t\tselect.collapse();\r\n\t\t\tselect.moveEnd(\"character\", end - start);\r\n\t\t\tselect.select();\r\n\t\t}\r\n\t\tval(...args) {\r\n\t\t\treturn this.el.val(...args);\r\n\t\t}\r\n\t}\r\n\r\n\tfunction linkFunc(scope, element, attrs, ngModel) {\r\n\r\n\t\tif (!ngModel) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tattrs.ngTrim = \"false\";\r\n\r\n\t\tvar parser = datetime(attrs.datetime),\r\n\t\t\tmodelParser = attrs.datetimeModel && datetime(attrs.datetimeModel),\r\n\t\t\tmaskElement = new Element(element, $document[0]),\r\n\t\t\tmask = new InputMask(maskElement, parser.tp, attrs.datetimeSeparator),\r\n\t\t\tisUtc;\r\n\r\n\t\tmask.on(\"digest\", err => {\r\n\t\t\tif (err.code != \"NOT_INIT\") {\r\n\t\t\t\tngModel.$setValidity(\"datetime\", false);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tparser.tp.on(\"change\", () => {\r\n\t\t\tscope.$evalAsync(() => {\r\n\t\t\t\tif (mask.err) {\r\n\t\t\t\t\tngModel.$setValidity(\"datetime\", false);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (parser.isInit() || parser.isEmpty()) {\r\n\t\t\t\t\tngModel.$setValidity(\"datetime\", true);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tngModel.$setValidity(\"datetime\", false);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (parser.getText() != ngModel.$viewValue) {\r\n\t\t\t\t\tngModel.$setViewValue(parser.getText());\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t});\r\n\r\n\t\tfunction setUtc(val) {\r\n\t\t\tif (val && !isUtc) {\r\n\t\t\t\tisUtc = true;\r\n\t\t\t\tparser.setTimezone(\"+0000\");\r\n\t\t\t\tif (modelParser) {\r\n\t\t\t\t\tmodelParser.setTimezone(\"+0000\");\r\n\t\t\t\t}\r\n\t\t\t} else if (!val && isUtc) {\r\n\t\t\t\tisUtc = false;\r\n\t\t\t\tparser.setTimezone();\r\n\t\t\t\tif (modelParser) {\r\n\t\t\t\t\tmodelParser.setTimezone();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfunction setTimezone(val) {\r\n\t\t\tparser.setTimezone(val);\r\n\t\t\tif (modelParser) {\r\n\t\t\t\tmodelParser.setTimezone(val);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (angular.isDefined(attrs.datetimeUtc)) {\r\n\t\t\tif (attrs.datetimeUtc.length > 0) {\r\n\t\t\t\tscope.$watch(attrs.datetimeUtc, setUtc);\r\n\t\t\t} else {\r\n\t\t\t\tsetUtc(true);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (angular.isDefined(attrs.datetimeTimezone)) {\r\n\t\t\tif (/^[+-]\\d{2}:?\\d{2}$/.test(attrs.datetimeTimezone)) {\r\n\t\t\t\tsetTimezone(attrs.datetimeTimezone);\r\n\t\t\t} else {\r\n\t\t\t\tscope.$watch(attrs.datetimeTimezone, setTimezone);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfunction validMin(value) {\r\n\t\t\tif (ngModel.$isEmpty(value) || ngModel.$isEmpty(attrs.min)) {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif (!angular.isDate(value)) {\r\n\t\t\t\tvalue = modelParser.getDate();\r\n\t\t\t}\r\n\t\t\treturn value >= new Date(attrs.min);\r\n\t\t}\r\n\r\n\t\tfunction validMax(value) {\r\n\t\t\tif (ngModel.$isEmpty(value) || ngModel.$isEmpty(attrs.max)) {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif (!angular.isDate(value)) {\r\n\t\t\t\tvalue = modelParser.getDate();\r\n\t\t\t}\r\n\t\t\treturn value <= new Date(attrs.max);\r\n\t\t}\r\n\r\n\t\tif (ngModel.$validators) {\r\n\t\t\tngModel.$validators.min = validMin;\r\n\t\t\tngModel.$validators.max = validMax;\r\n\t\t}\r\n\r\n\t\tattrs.$observe(\"min\", function(){\r\n\t\t\tvalidMinMax(parser.getDate());\r\n\t\t});\r\n\r\n\t\tattrs.$observe(\"max\", function(){\r\n\t\t\tvalidMinMax(parser.getDate());\r\n\t\t});\r\n\r\n\t\tngModel.$render = function(){\r\n\t\t\t// let mask do render stuff?\r\n\t\t\t// element.val(ngModel.$viewValue || \"\");\r\n\t\t};\r\n\r\n\t\tngModel.$isEmpty = function(value) {\r\n\t\t\tif (!value) {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif (typeof value == \"string\") {\r\n\t\t\t\treturn parser.isEmpty(value);\r\n\t\t\t}\r\n\t\t\treturn false;\r\n\t\t};\r\n\r\n\t\tfunction validMinMax(date) {\r\n\t\t\tif (ngModel.$validate) {\r\n\t\t\t\tngModel.$validate();\r\n\t\t\t} else {\r\n\t\t\t\tngModel.$setValidity(\"min\", validMin(date));\r\n\t\t\t\tngModel.$setValidity(\"max\", validMax(date));\r\n\t\t\t}\r\n\t\t\treturn !ngModel.$error.min && !ngModel.$error.max;\r\n\t\t}\r\n\r\n\t\tngModel.$parsers.unshift(function(viewValue){\r\n\t\t\t// You will get undefined when input is required and model get unset\r\n\t\t\tif (angular.isUndefined(viewValue)) {\r\n\t\t\t\tviewValue = parser.getText();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (!angular.isString(viewValue)) {\r\n\t\t\t\t// let unknown value pass through\r\n\t\t\t\treturn viewValue;\r\n\t\t\t}\r\n\r\n\t\t\tmask.digest(null, viewValue);\r\n\r\n\t\t\tif (!parser.isInit()) {\r\n\t\t\t\treturn undefined;\r\n\t\t\t}\r\n\r\n\t\t\tvar date = parser.getDate();\r\n\r\n\t\t\tif (ngModel.$validate || validMinMax(date)) {\r\n\t\t\t\tif (modelParser) {\r\n\t\t\t\t\treturn modelParser.setDate(date).getText();\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// Create new date to make Angular notice the difference.\r\n\t\t\t\t\treturn new Date(date.getTime());\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\treturn undefined;\r\n\t\t});\r\n\t\t\r\n\t\tfunction validModelType(model) {\r\n\t\t\tif (angular.isDate(model) && !modelParser) {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif (angular.isString(model) && modelParser) {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tngModel.$formatters.push(function(modelValue){\r\n\t\t\t\r\n\t\t\t// formatter clean the error\r\n\t\t\tngModel.$setValidity(\"datetime\", true);\r\n\t\t\t\r\n\t\t\t// handle empty value\r\n\t\t\tif (!modelValue) {\r\n\t\t\t\tparser.unset();\r\n\t\t\t\t// FIXME: input will be cleared if modelValue is empty and the input is required. This is a temporary fix.\r\n\t\t\t\tscope.$evalAsync(() => {\r\n\t\t\t\t\tngModel.$setViewValue(parser.getText());\r\n\t\t\t\t});\r\n\t\t\t\treturn parser.getText();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// let unknown model type pass through\r\n\t\t\tif (!validModelType(modelValue)) {\r\n\t\t\t\treturn modelValue;\r\n\t\t\t}\r\n\r\n\t\t\tif (modelParser) {\r\n\t\t\t\tmodelValue = modelParser.parse(modelValue).getDate();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (!ngModel.$validate) {\r\n\t\t\t\tvalidMinMax(modelValue);\r\n\t\t\t}\r\n\r\n\t\t\treturn parser.setDate(modelValue).getText();\r\n\t\t});\r\n\t}\r\n\r\n\treturn {\r\n\t\trestrict: \"A\",\r\n\t\trequire: \"?ngModel\",\r\n\t\tlink: linkFunc,\r\n\t\tpriority: 100\r\n\t};\r\n}\r\n"],"names":["angular","constant","year","yearShort","month","date","day","hour","hour12","minute","second","millisecond","ampm","week","EventLite","_module_","exports","LISTENERS","methods","on","once","off","emit","mixin","prototype","target","key","type","func","getListeners","push","that","wrap","originalListener","call","apply","arguments","listners","length","Object","keys","filter","ne","test","value","listeners","arglen","forEach","zeroarg","onearg","args","Array","slice","moreargs","readonly","num","minLength","maxLength","i","substr","getMatch","str","pos","pattern","strQ","toUpperCase","patternQ","getInteger","substring","match","parseNode","text","token","result","parseToken","err","startsWith","placeholder","viewValue","empty","m","j","code","message","properValue","num2str","min","max","select","selected","parseNodes","nodes","node","r","last","formatNode","v","extract","formatNodes","ignoreEmpty","Node","parser","offset","next","prev","nextEdit","prevEdit","unset","noEmpty","setValue","parse","restoreValue","copyValue","add","diff","nodeValue","addValue","o","tk","p","restore","createNodes","tokens","edit","nocopy","createNameMap","map","Map","l","get","name","set","TextParser","_constructor","initialize","Error","nameMap","oldText","changed","comparer","empties","errors","sort","a","b","prior","c","newText","join","properText","isEmpty","isInit","getText","getValue","getNodes","Emitter","findNearestNode","matchNodes","left","right","start","end","first","Selection","element","el","range","selectNearestNode","getSelection","assign","setSelection","hasNext","hasPrev","selectNext","selectPrev","atNodeEnd","len","atNodeStart","InputMask","textParser","separators","tp","sel","n","mousedown","setTimeout","digest","val","e","altKey","ctrlKey","keyCode","shiftKey","preventDefault","tryFixingError","charCode","String","fromCharCode","includes","inDigest","errorViewLength","undefined","fixErr","_require__$lib$text_parser_","_require__$lib$input_mask_","_require_angular_","_require_custom_input_","_require_custom_input$lib$utils_","module","factory","init","$inject","$locale","datetimePlaceholder","formats","DATETIME_FORMATS","tokenRE","definedTokens","MONTH","SHORTMONTH","fixDay","DAY","SHORTDAY","AMPMS","colon","nameConf","d","getFullYear","setFullYear","getMonth","setMonth","setDate","getDate","oldMonth","monthNodes","every","getDay","setDay","getHours","setHours","setHour12","setAmpm","getMinutes","setMinutes","getSeconds","setSeconds","getMilliseconds","setMilliseconds","getWeek","values","extend","SYS_TIMEZONE","Date","getTimezoneOffset","sign","absOffset","Math","abs","floor","days","s","createTokens","format","exec","index","string","sss","replace","tz","insertColon","lastIndex","yearStart","weekStart","getTime","timezone","removeColon","sig","deoffset","DatetimeParser","timezoneNodes","setTimezone","createParser","yearCheck","some","t","fn","y","directive","datetime","$log","$document","Element","document","doc","eventType","callback","activeElement","selectionStart","selectionEnd","isDefined","getSelectionIE","bookmark","selection","createRange","getBookmark","createTextRange","range2","duplicate","moveToBookmark","setEndPoint","setSelectionRange","setSelectionIE","moveStart","collapse","moveEnd","linkFunc","scope","attrs","ngModel","ngTrim","modelParser","datetimeModel","maskElement","mask","datetimeSeparator","isUtc","$setValidity","$evalAsync","$viewValue","$setViewValue","setUtc","datetimeUtc","$watch","datetimeTimezone","validMin","$isEmpty","isDate","validMax","$validators","$observe","validMinMax","$render","$validate","$error","$parsers","unshift","isUndefined","isString","validModelType","model","$formatters","modelValue","restrict","require","link","priority"],"mappings":"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"} -------------------------------------------------------------------------------- /example/demo-1.5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular Datetime 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 49 | 50 | 51 |

Angular Datetime Demo Page

52 |

To use the directive, add datetime="date-format" attribute to your input.

53 | 54 |
myDate = {{data.myDate | json}}
55 |
<input type="text" datetime="yyyy-MM-dd HH:mm:ss" ng-model="myDate">
56 | 57 |

To set a date, just set your model to a Date object. Set to null to remove it.

58 |

59 | 60 | 61 |

62 |
<button ng-click="myDate = new Date">reset</button>
63 | 64 |

min / max

65 |

Validation for min/max date. The min/max attribute will be used to construct the date object.

66 |
67 | 68 |
69 |
input.$error = {{minmaxForm.input.$error | json}}
70 |
<input type="text" datetime="yyyy-MM-dd HH:mm:ss" ng-model="myDate" min="Jan 1, 2010" max="Dec 31, 2019">
71 | 72 |
73 | 77 |
78 | 79 |
80 | 84 |
85 | 86 |

required

87 |

ng-invalid-required will be added to the class list when all parts are empty.

88 |
89 | 90 |
91 |
input.$error = {{requireForm.input.$error | json}}
92 |
<input type="text" datetime="yyyy-MM-dd HH:mm:ss" ng-model="myDate" required>
93 | 94 |

Use ng-require.

95 |
96 | 97 | 98 |
99 |
input.$error = {{ngRequireForm.input.$error | json}}
100 | 101 |

model-format

102 |

With this attribute, it will convert the model into a date string automatically.

103 | 104 |
myDateString = {{data.myDateString | json}}
105 |
<input type="text" datetime="medium" datetime-model="yyyy-MM-dd HH:mm:ss" ng-model="myDateString">
106 | 107 |

datetime-timezone

108 |

By the default, angular-datetime will format the date in the local timezone. Use datetime-timezone to specify a different timezone.

109 | 110 |
myDate = {{data.myDate | json}}
111 |
<input type="text" datetime="yyyy-MM-dd HH:mm:ssZ" ng-model="myDate" datetime-timezone="+0000">
112 |

Also support expression.

113 | 114 |
myDate = {{data.myDate | json}}
myTimezone = {{data.myTimezone | json}}
115 |
<input type="text" datetime="yyyy-MM-dd HH:mm:ssZ" ng-model="data.myDate" datetime-timezone="myTimezone">
116 |
117 | 121 |
122 | 123 |

datetime-separator

124 |

By the default, you can use left/right keys to navigate between each part of date. With this attribute, you will be able to use different keys to jump to next part.

125 | 126 |
<input type="text" datetime="dd.MM.yyyy" ng-model="myDate" datetime-separator=",.-/">
127 | 128 |

Localizable formats

129 |

The parser supports localizable formats in Angular.

130 |
131 | 135 |
136 | 137 |

Other tests

138 |
139 | 140 | 141 |
142 |
143 | 147 |
148 |
149 | 153 |
154 |
155 | 159 |
160 |
161 | 165 |
166 |
167 | 172 |
173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /example/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular Datetime 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 49 | 50 | 51 |

Angular Datetime Demo Page

52 |

To use the directive, add datetime="date-format" attribute to your input.

53 | 54 |
myDate = {{data.myDate | json}}
55 |
<input type="text" datetime="yyyy-MM-dd HH:mm:ss" ng-model="myDate">
56 | 57 |

To set a date, just set your model to a Date object. Set to null to remove it.

58 |

59 | 60 | 61 |

62 |
<button ng-click="myDate = new Date">reset</button>
63 | 64 |

min / max

65 |

Validation for min/max date. The min/max attribute will be used to construct the date object.

66 |
67 | 68 |
69 |
input.$error = {{minmaxForm.input.$error | json}}
70 |
<input type="text" datetime="yyyy-MM-dd HH:mm:ss" ng-model="myDate" min="Jan 1, 2010" max="Dec 31, 2019">
71 | 72 |
73 | 77 |
78 | 79 |
80 | 84 |
85 | 86 |

required

87 |

ng-invalid-required will be added to the class list when all parts are empty.

88 |
89 | 90 |
91 |
input.$error = {{requireForm.input.$error | json}}
92 |
<input type="text" datetime="yyyy-MM-dd HH:mm:ss" ng-model="myDate" required>
93 | 94 |

Use ng-require.

95 |
96 | 97 | 98 |
99 |
input.$error = {{ngRequireForm.input.$error | json}}
100 | 101 |

model-format

102 |

With this attribute, it will convert the model into a date string automatically.

103 | 104 |
myDateString = {{data.myDateString | json}}
105 |
<input type="text" datetime="medium" datetime-model="yyyy-MM-dd HH:mm:ss" ng-model="myDateString">
106 | 107 |

datetime-timezone

108 |

By the default, angular-datetime will format the date in the local timezone. Use datetime-timezone to specify a different timezone.

109 | 110 |
myDate = {{data.myDate | json}}
111 |
<input type="text" datetime="yyyy-MM-dd HH:mm:ssZ" ng-model="myDate" datetime-timezone="+0000">
112 |

Also support expression.

113 | 114 |
myDate = {{data.myDate | json}}
myTimezone = {{data.myTimezone | json}}
115 |
<input type="text" datetime="yyyy-MM-dd HH:mm:ssZ" ng-model="data.myDate" datetime-timezone="myTimezone">
116 |
117 | 121 |
122 | 123 |

datetime-separator

124 |

By the default, you can use left/right keys to navigate between each part of date. With this attribute, you will be able to use different keys to jump to next part.

125 | 126 |
<input type="text" datetime="dd.MM.yyyy" ng-model="myDate" datetime-separator=",.-/">
127 | 128 |

Localizable formats

129 |

The parser supports localizable formats in Angular.

130 |
131 | 135 |
136 | 137 |

Other tests

138 |
139 | 140 | 141 |
142 |
143 | 147 |
148 |
149 | 153 |
154 |
155 | 159 |
160 |
161 | 165 |
166 |
167 | 172 |
173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require("./lib/main"); 2 | require("./lib/factory"); 3 | require("./lib/directive"); 4 | -------------------------------------------------------------------------------- /lib/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "rules": { 7 | "no-use-before-define": [2, "nofunc"], 8 | "semi": [2, "always"], 9 | "angular/di": ["error", "$inject"] 10 | }, 11 | "extends": [ 12 | "eslint:recommended", 13 | "angular" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /lib/directive.js: -------------------------------------------------------------------------------- 1 | var angular = require("angular"), 2 | {InputMask} = require("custom-input"); 3 | 4 | angular.module("datetime").directive("datetime", init); 5 | init.$inject = ["datetime", "$log", "$document"]; 6 | function init(datetime, $log, $document){ 7 | class Element { 8 | constructor(element, document) { 9 | this.el = element; 10 | this.doc = document; 11 | } 12 | on(eventType, callback) { 13 | // use ngModel.parser to execute digest 14 | if (eventType == "input") return; 15 | 16 | return this.el.on(eventType, callback); 17 | } 18 | getSelection() { 19 | var el = this.el[0], 20 | doc = this.doc; 21 | 22 | if (doc.activeElement != el) return; 23 | 24 | var start = el.selectionStart, 25 | end = el.selectionEnd; 26 | 27 | if (angular.isDefined(start) && angular.isDefined(end)) { 28 | return { start, end }; 29 | } 30 | return this.getSelectionIE(); 31 | } 32 | getSelectionIE() { 33 | var el = this.el[0], 34 | doc = this.doc; 35 | 36 | var bookmark = doc.selection.createRange().getBookmark(), 37 | range = el.createTextRange(), 38 | range2 = range.duplicate(); 39 | 40 | range.moveToBookmark(bookmark); 41 | range2.setEndPoint("EndToStart", range); 42 | 43 | var start = range2.text.length, 44 | end = start + range.text.length; 45 | 46 | return { start, end }; 47 | } 48 | setSelection(start, end) { 49 | var el = this.el[0], 50 | doc = this.doc; 51 | 52 | if (doc.activeElement != el) return; 53 | 54 | if (el.setSelectionRange) { 55 | el.setSelectionRange(start, end); 56 | } else { 57 | this.setSelectionIE(start, end); 58 | } 59 | } 60 | setSelectionIE(start, end) { 61 | var el = this.el[0], 62 | select = el.createTextRange(); 63 | 64 | select.moveStart("character", start); 65 | select.collapse(); 66 | select.moveEnd("character", end - start); 67 | select.select(); 68 | } 69 | val(...args) { 70 | return this.el.val(...args); 71 | } 72 | } 73 | 74 | function linkFunc(scope, element, attrs, ngModel) { 75 | 76 | if (!ngModel) { 77 | return false; 78 | } 79 | 80 | attrs.ngTrim = "false"; 81 | 82 | var parser = datetime(attrs.datetime), 83 | modelParser = attrs.datetimeModel && datetime(attrs.datetimeModel), 84 | maskElement = new Element(element, $document[0]), 85 | mask = new InputMask(maskElement, parser.tp, attrs.datetimeSeparator), 86 | isUtc; 87 | 88 | mask.on("digest", err => { 89 | if (err.code != "NOT_INIT") { 90 | ngModel.$setValidity("datetime", false); 91 | } 92 | }); 93 | 94 | parser.tp.on("change", () => { 95 | scope.$evalAsync(() => { 96 | if (mask.err) { 97 | ngModel.$setValidity("datetime", false); 98 | return; 99 | } 100 | 101 | if (parser.isInit() || parser.isEmpty()) { 102 | ngModel.$setValidity("datetime", true); 103 | } else { 104 | ngModel.$setValidity("datetime", false); 105 | } 106 | 107 | if (parser.getText() != ngModel.$viewValue) { 108 | ngModel.$setViewValue(parser.getText()); 109 | } 110 | }); 111 | }); 112 | 113 | function setUtc(val) { 114 | if (val && !isUtc) { 115 | isUtc = true; 116 | parser.setTimezone("+0000"); 117 | if (modelParser) { 118 | modelParser.setTimezone("+0000"); 119 | } 120 | } else if (!val && isUtc) { 121 | isUtc = false; 122 | parser.setTimezone(); 123 | if (modelParser) { 124 | modelParser.setTimezone(); 125 | } 126 | } 127 | } 128 | 129 | function setTimezone(val) { 130 | parser.setTimezone(val); 131 | if (modelParser) { 132 | modelParser.setTimezone(val); 133 | } 134 | } 135 | 136 | if (angular.isDefined(attrs.datetimeUtc)) { 137 | if (attrs.datetimeUtc.length > 0) { 138 | scope.$watch(attrs.datetimeUtc, setUtc); 139 | } else { 140 | setUtc(true); 141 | } 142 | } 143 | 144 | if (angular.isDefined(attrs.datetimeTimezone)) { 145 | if (/^[+-]\d{2}:?\d{2}$/.test(attrs.datetimeTimezone)) { 146 | setTimezone(attrs.datetimeTimezone); 147 | } else { 148 | scope.$watch(attrs.datetimeTimezone, setTimezone); 149 | } 150 | } 151 | 152 | function validMin(value) { 153 | if (ngModel.$isEmpty(value) || ngModel.$isEmpty(attrs.min)) { 154 | return true; 155 | } 156 | if (!angular.isDate(value)) { 157 | value = modelParser.getDate(); 158 | } 159 | return value >= new Date(attrs.min); 160 | } 161 | 162 | function validMax(value) { 163 | if (ngModel.$isEmpty(value) || ngModel.$isEmpty(attrs.max)) { 164 | return true; 165 | } 166 | if (!angular.isDate(value)) { 167 | value = modelParser.getDate(); 168 | } 169 | return value <= new Date(attrs.max); 170 | } 171 | 172 | if (ngModel.$validators) { 173 | ngModel.$validators.min = validMin; 174 | ngModel.$validators.max = validMax; 175 | } 176 | 177 | attrs.$observe("min", function(){ 178 | validMinMax(parser.getDate()); 179 | }); 180 | 181 | attrs.$observe("max", function(){ 182 | validMinMax(parser.getDate()); 183 | }); 184 | 185 | ngModel.$render = function(){ 186 | // let mask do render stuff? 187 | // element.val(ngModel.$viewValue || ""); 188 | }; 189 | 190 | ngModel.$isEmpty = function(value) { 191 | if (!value) { 192 | return true; 193 | } 194 | if (typeof value == "string") { 195 | return parser.isEmpty(value); 196 | } 197 | return false; 198 | }; 199 | 200 | function validMinMax(date) { 201 | if (ngModel.$validate) { 202 | ngModel.$validate(); 203 | } else { 204 | ngModel.$setValidity("min", validMin(date)); 205 | ngModel.$setValidity("max", validMax(date)); 206 | } 207 | return !ngModel.$error.min && !ngModel.$error.max; 208 | } 209 | 210 | ngModel.$parsers.unshift(function(viewValue){ 211 | // You will get undefined when input is required and model get unset 212 | if (angular.isUndefined(viewValue)) { 213 | viewValue = parser.getText(); 214 | } 215 | 216 | if (!angular.isString(viewValue)) { 217 | // let unknown value pass through 218 | return viewValue; 219 | } 220 | 221 | mask.digest(null, viewValue); 222 | 223 | if (!parser.isInit()) { 224 | return undefined; 225 | } 226 | 227 | var date = parser.getDate(); 228 | 229 | if (ngModel.$validate || validMinMax(date)) { 230 | if (modelParser) { 231 | return modelParser.setDate(date).getText(); 232 | } else { 233 | // Create new date to make Angular notice the difference. 234 | return new Date(date.getTime()); 235 | } 236 | } 237 | 238 | return undefined; 239 | }); 240 | 241 | function validModelType(model) { 242 | if (angular.isDate(model) && !modelParser) { 243 | return true; 244 | } 245 | if (angular.isString(model) && modelParser) { 246 | return true; 247 | } 248 | return false; 249 | } 250 | 251 | ngModel.$formatters.push(function(modelValue){ 252 | 253 | // formatter clean the error 254 | ngModel.$setValidity("datetime", true); 255 | 256 | // handle empty value 257 | if (!modelValue) { 258 | parser.unset(); 259 | // FIXME: input will be cleared if modelValue is empty and the input is required. This is a temporary fix. 260 | scope.$evalAsync(() => { 261 | ngModel.$setViewValue(parser.getText()); 262 | }); 263 | return parser.getText(); 264 | } 265 | 266 | // let unknown model type pass through 267 | if (!validModelType(modelValue)) { 268 | return modelValue; 269 | } 270 | 271 | if (modelParser) { 272 | modelValue = modelParser.parse(modelValue).getDate(); 273 | } 274 | 275 | if (!ngModel.$validate) { 276 | validMinMax(modelValue); 277 | } 278 | 279 | return parser.setDate(modelValue).getText(); 280 | }); 281 | } 282 | 283 | return { 284 | restrict: "A", 285 | require: "?ngModel", 286 | link: linkFunc, 287 | priority: 100 288 | }; 289 | } 290 | -------------------------------------------------------------------------------- /lib/factory.js: -------------------------------------------------------------------------------- 1 | var angular = require("angular"), 2 | {TextParser} = require("custom-input"), 3 | {num2str} = require("custom-input/lib/utils"); 4 | 5 | angular.module("datetime").factory("datetime", init); 6 | init.$inject = ["$locale", "datetimePlaceholder"]; 7 | function init($locale, datetimePlaceholder) { 8 | // Fetch date and time formats from $locale service 9 | var formats = $locale.DATETIME_FORMATS; 10 | // Valid format tokens. 1=sss, 2='' 11 | var tokenRE = /yyyy|yy|y|M{1,4}|dd?|EEEE?|HH?|hh?|mm?|ss?|([.,])sss|a|Z{1,2}|ww|w|'(([^']+|'')*)'/g; 12 | // Token definition 13 | var definedTokens = { 14 | "y": { 15 | minLength: 1, 16 | maxLength: 4, 17 | max: 9999, 18 | min: 0, 19 | name: "year", 20 | type: "number" 21 | }, 22 | "yy": { 23 | minLength: 2, 24 | maxLength: 2, 25 | name: "yearShort", 26 | type: "number" 27 | }, 28 | "yyyy": { 29 | minLength: 4, 30 | maxLength: 4, 31 | max: 9999, 32 | min: 0, 33 | name: "year", 34 | type: "number" 35 | }, 36 | "MMMM": { 37 | name: "month", 38 | type: "select", 39 | select: formats.MONTH 40 | }, 41 | "MMM": { 42 | name: "month", 43 | type: "select", 44 | select: formats.SHORTMONTH 45 | }, 46 | "MM": { 47 | minLength: 2, 48 | maxLength: 2, 49 | name: "month", 50 | type: "number" 51 | }, 52 | "M": { 53 | minLength: 1, 54 | maxLength: 2, 55 | name: "month", 56 | type: "number", 57 | min: 1 58 | }, 59 | "dd": { 60 | minLength: 2, 61 | maxLength: 2, 62 | name: "date", 63 | type: "number" 64 | }, 65 | "d": { 66 | minLength: 1, 67 | maxLength: 2, 68 | name: "date", 69 | type: "number", 70 | min: 1 71 | }, 72 | "EEEE": { 73 | name: "day", 74 | type: "select", 75 | select: fixDay(formats.DAY) 76 | }, 77 | "EEE": { 78 | name: "day", 79 | type: "select", 80 | select: fixDay(formats.SHORTDAY) 81 | }, 82 | "HH": { 83 | minLength: 2, 84 | maxLength: 2, 85 | name: "hour", 86 | type: "number" 87 | }, 88 | "H": { 89 | minLength: 1, 90 | maxLength: 2, 91 | name: "hour", 92 | type: "number" 93 | }, 94 | "hh": { 95 | minLength: 2, 96 | maxLength: 2, 97 | name: "hour12", 98 | type: "number" 99 | }, 100 | "h": { 101 | minLength: 1, 102 | maxLength: 2, 103 | name: "hour12", 104 | type: "number" 105 | }, 106 | "mm": { 107 | minLength: 2, 108 | maxLength: 2, 109 | name: "minute", 110 | type: "number" 111 | }, 112 | "m": { 113 | minLength: 1, 114 | maxLength: 2, 115 | name: "minute", 116 | type: "number" 117 | }, 118 | "ss": { 119 | minLength: 2, 120 | maxLength: 2, 121 | name: "second", 122 | type: "number" 123 | }, 124 | "s": { 125 | minLength: 1, 126 | maxLength: 2, 127 | name: "second", 128 | type: "number" 129 | }, 130 | "sss": { 131 | minLength: 3, 132 | maxLength: 3, 133 | name: "millisecond", 134 | type: "number" 135 | }, 136 | "a": { 137 | name: "ampm", 138 | type: "select", 139 | select: formats.AMPMS 140 | }, 141 | "ww": { 142 | minLength: 2, 143 | maxLength: 2, 144 | max: 53, 145 | name: "week", 146 | type: "number" 147 | }, 148 | "w": { 149 | minLength: 1, 150 | maxLength: 2, 151 | max: 53, 152 | name: "week", 153 | type: "number" 154 | }, 155 | "Z": { 156 | name: "timezone", 157 | type: "static" 158 | }, 159 | "ZZ": { 160 | name: "timezone", 161 | type: "static", 162 | colon: true 163 | }, 164 | "string": { 165 | name: "string", 166 | type: "static" 167 | } 168 | }; 169 | 170 | var nameConf = { 171 | year: { 172 | extract: d => { 173 | // year might be negative 174 | var v = d.getFullYear() % 10000; 175 | return v >= 0 ? v : 0; 176 | }, 177 | restore: (d, v) => d.setFullYear(v), 178 | add: (d, v) => d.setFullYear(d.getFullYear() + v), 179 | prior: 7 180 | }, 181 | yearShort: { 182 | extract: d => { 183 | var v = d.getFullYear() % 100; 184 | return v >= 0 ? v : v + 100; 185 | }, 186 | restore: (d, v) => d.setFullYear(v), 187 | add: (d, v) => d.setFullYear(d.getFullYear() + v), 188 | prior: 7 189 | }, 190 | month: { 191 | extract: d => d.getMonth() + 1, 192 | restore: (d, v) => { 193 | // http://stackoverflow.com/questions/14680396/the-date-getmonth-method-has-bug 194 | d.setMonth(v - 1); 195 | // handle date overflow 196 | if (d.getMonth() == v) { 197 | d.setDate(0); 198 | } 199 | }, 200 | add: (d, v) => { 201 | v = d.getMonth() + v; 202 | d.setMonth(v); 203 | // date overflow 204 | if (d.getMonth() == v + 1) { 205 | d.setDate(0); 206 | } 207 | }, 208 | prior: 5 209 | }, 210 | date: { 211 | extract: d => d.getDate(), 212 | restore: (d, v, p) => { 213 | // handle overflowed day 214 | var oldMonth = d.getMonth(); 215 | d.setDate(v); 216 | if (d.getMonth() != oldMonth && v <= 31) { 217 | var monthNodes = p.getNodes("month"); 218 | if (monthNodes && monthNodes.every(n => n.empty)) { 219 | d.setDate(v); 220 | } 221 | } 222 | }, 223 | add(d, v, p) { 224 | this.restore(d, d.getDate() + v, p); 225 | }, 226 | prior: 4 227 | }, 228 | day: { 229 | extract: d => d.getDay() || 7, 230 | restore: setDay, 231 | add: (d, v) => d.setDate(d.getDate() + v), 232 | prior: 4 233 | }, 234 | hour: { 235 | extract: d => d.getHours(), 236 | restore: (d, v) => d.setHours(v), 237 | add: (d, v) => d.setHours(d.getHours() + v), 238 | prior: 2 239 | }, 240 | hour12: { 241 | extract: d => d.getHours() % 12 || 12, 242 | restore: setHour12, 243 | add: (d, v) => d.setHours(d.getHours() + v), 244 | prior: 2 245 | }, 246 | ampm: { 247 | extract: d => d.getHours() < 12 ? 1 : 2, 248 | restore: setAmpm, 249 | add: (d, v) => d.setHours(d.getHours() + v * 12), 250 | prior: 3 251 | }, 252 | minute: { 253 | extract: d => d.getMinutes(), 254 | restore: (d, v) => d.setMinutes(v), 255 | add: (d, v) => d.setMinutes(d.getMinutes() + v), 256 | prior: 0 257 | }, 258 | second: { 259 | extract: d => d.getSeconds(), 260 | restore: (d, v) => d.setSeconds(v), 261 | add: (d, v) => d.setSeconds(d.getSeconds() + v), 262 | prior: 1 263 | }, 264 | millisecond: { 265 | extract: d => d.getMilliseconds(), 266 | restore: (d, v) => d.setMilliseconds(v), 267 | add: (d, v) => d.setMilliseconds(d.getMilliseconds() + v), 268 | prior: 1 269 | }, 270 | week: { 271 | extract: getWeek, 272 | restore: (d, v) => d.setDate(d.getDate() + (v - getWeek(d)) * 7), 273 | add: (d, v) => d.setDate(d.getDate() + v * 7), 274 | prior: 6 275 | } 276 | }; 277 | 278 | // setup placeholder 279 | for (var name in nameConf) { 280 | nameConf[name].placeholder = datetimePlaceholder[name]; 281 | } 282 | 283 | // setup tokens 284 | for (var tk of Object.values(definedTokens)) { 285 | if (nameConf[tk.name]) { 286 | angular.extend(tk, nameConf[tk.name]); 287 | } 288 | } 289 | 290 | var SYS_TIMEZONE = (function(){ 291 | var offset = -(new Date).getTimezoneOffset(), 292 | sign = offset >= 0 ? "+" : "-", 293 | absOffset = Math.abs(offset), 294 | hour = Math.floor(absOffset / 60), 295 | min = absOffset % 60; 296 | return sign + num2str(hour, 2, 2) + num2str(min, 2, 2); 297 | })(); 298 | 299 | // Push Sunday to the end 300 | function fixDay(days) { 301 | var s = [], i; 302 | for (i = 1; i < days.length; i++) { 303 | s.push(days[i]); 304 | } 305 | s.push(days[0]); 306 | return s; 307 | } 308 | 309 | // Split format into multiple tokens 310 | function createTokens(format) { 311 | var tokens = [], 312 | pos = 0, 313 | match; 314 | 315 | while ((match = tokenRE.exec(format))) { 316 | if (match.index > pos) { 317 | // doesn't match any token, static string 318 | tokens.push(angular.extend({ 319 | value: format.substring(pos, match.index) 320 | }, definedTokens.string)); 321 | pos = match.index; 322 | } 323 | 324 | if (match.index == pos) { 325 | if (match[1]) { 326 | // sss 327 | tokens.push(angular.extend({ 328 | value: match[1] 329 | }, definedTokens.string)); 330 | tokens.push(definedTokens.sss); 331 | } else if (match[2]) { 332 | // escaped string 333 | tokens.push(angular.extend({ 334 | value: match[2].replace("''", "'") 335 | }, definedTokens.string)); 336 | } else if (definedTokens[match[0]].name == "timezone") { 337 | // static timezone 338 | var tz = SYS_TIMEZONE; 339 | if (definedTokens[match[0]].colon) { 340 | tz = insertColon(tz); 341 | } 342 | tokens.push(angular.extend({ 343 | value: tz 344 | }, definedTokens[match[0]])); 345 | } else { 346 | // other tokens 347 | tokens.push(definedTokens[match[0]]); 348 | } 349 | pos = tokenRE.lastIndex; 350 | } 351 | } 352 | 353 | if (pos < format.length) { 354 | tokens.push(angular.extend({ 355 | value: format.substring(pos) 356 | }, definedTokens.string)); 357 | } 358 | 359 | return tokens; 360 | } 361 | 362 | function getWeek(date) { 363 | var yearStart = new Date(date.getFullYear(), 0, 1); 364 | 365 | var weekStart = new Date(yearStart.getTime()); 366 | 367 | if (weekStart.getDay() > 4) { 368 | weekStart.setDate(weekStart.getDate() + (1 - weekStart.getDay()) + 7); 369 | } else { 370 | weekStart.setDate(weekStart.getDate() + (1 - weekStart.getDay())); 371 | } 372 | var diff = date.getTime() - weekStart.getTime(); 373 | 374 | return Math.floor(diff / (7 * 24 * 60 * 60 * 1000)); 375 | } 376 | 377 | // set the proper date value matching the weekday 378 | function setDay(date, day) { 379 | // we don't want to change month when changing date 380 | var month = date.getMonth(), 381 | diff = day - (date.getDay() || 7); 382 | // move to correct date 383 | date.setDate(date.getDate() + diff); 384 | // check month 385 | if (date.getMonth() != month) { 386 | if (diff > 0) { 387 | date.setDate(date.getDate() - 7); 388 | } else { 389 | date.setDate(date.getDate() + 7); 390 | } 391 | } 392 | } 393 | 394 | function setHour12(date, hour) { 395 | hour = hour % 12; 396 | if (date.getHours() >= 12) { 397 | hour += 12; 398 | } 399 | date.setHours(hour); 400 | } 401 | 402 | function setAmpm(date, ampm) { 403 | var hour = date.getHours(); 404 | if ((hour < 12) == (ampm > 1)) { 405 | date.setHours((hour + 12) % 24); 406 | } 407 | } 408 | 409 | function insertColon(timezone) { 410 | if (timezone[3] == ":") { 411 | return timezone; 412 | } 413 | return timezone.substr(0, 3) + ":" + timezone.substr(3, 2); 414 | } 415 | 416 | function removeColon(timezone) { 417 | if (timezone[3] != ":") { 418 | return timezone; 419 | } 420 | return timezone.substr(0, 3) + timezone.substr(4, 2); 421 | } 422 | 423 | function offset(date, timezone) { 424 | timezone = removeColon(timezone); 425 | var hour = +timezone.substr(1, 2), 426 | min = +timezone.substr(3, 2), 427 | sig = (timezone[0] + "1"), 428 | offset = (hour * 60 + min) * sig; 429 | 430 | return new Date(date.getTime() + (offset - -date.getTimezoneOffset()) * 60 * 1000); 431 | } 432 | 433 | function deoffset(date, timezone) { 434 | timezone = removeColon(timezone); 435 | var hour = +timezone.substr(1, 2), 436 | min = +timezone.substr(3, 2), 437 | sig = (timezone[0] + "1"), 438 | offset = (hour * 60 + min) * sig; 439 | 440 | return new Date(date.getTime() + (-date.getTimezoneOffset() - offset) * 60 * 1000); 441 | } 442 | 443 | class DatetimeParser { 444 | // Apply timezone offset 445 | constructor(tp) { 446 | this.tp = tp; 447 | this.timezone = SYS_TIMEZONE; 448 | this.timezoneNodes = this.tp.nodes.filter(n => n.token.name == "timezone"); 449 | } 450 | parse(text) { 451 | this.tp.parse(text); 452 | return this; 453 | } 454 | getText() { 455 | return this.tp.getText(); 456 | } 457 | setDate(date, ignoreEmpty) { 458 | this.tp.setValue(offset(date, this.timezone), ignoreEmpty); 459 | return this; 460 | } 461 | getDate() { 462 | return deoffset(this.tp.getValue(), this.timezone); 463 | } 464 | setTimezone(timezone = SYS_TIMEZONE) { 465 | if (timezone == this.timezone) { 466 | return; 467 | } 468 | var date = this.getDate(); 469 | this.timezone = timezone; 470 | for (var n of this.timezoneNodes) { 471 | if (n.token.colon) { 472 | n.token.value = insertColon(timezone); 473 | } else { 474 | n.token.value = removeColon(timezone); 475 | } 476 | } 477 | return this.setDate(date, false); 478 | } 479 | isEmpty() { 480 | return this.tp.isEmpty.apply(this.tp, arguments); 481 | } 482 | isInit() { 483 | return this.tp.isInit.apply(this.tp, arguments); 484 | } 485 | unset() { 486 | this.tp.unset(); 487 | return this; 488 | } 489 | } 490 | 491 | function createParser(format) { 492 | var tokens = createTokens(formats[format] || format), 493 | yearCheck; 494 | 495 | if (tokens.some(t => t.name == "yearShort")) { 496 | yearCheck = function(fn) { 497 | return function(d) { 498 | fn.apply(this, arguments); 499 | var y = d.getFullYear(); 500 | if (y < 0) { 501 | d.setFullYear(y + 100); 502 | } 503 | }; 504 | }; 505 | } else { 506 | yearCheck = function(fn) { 507 | return function(d) { 508 | fn.apply(this, arguments); 509 | var y = d.getFullYear(); 510 | if (y < 0) { 511 | d.setFullYear(0); 512 | } 513 | if (y > 9999) { 514 | d.setFullYear(9999); 515 | } 516 | }; 517 | }; 518 | } 519 | 520 | for (var tk of tokens) { 521 | if (tk.add) { 522 | tk.add = yearCheck(tk.add); 523 | } 524 | if (tk.restore) { 525 | tk.restore = yearCheck(tk.restore); 526 | } 527 | } 528 | 529 | var tp = new TextParser({ 530 | tokens: tokens, 531 | value: new Date, 532 | copyValue: o => new Date(o.getTime()) 533 | }); 534 | 535 | return new DatetimeParser(tp); 536 | } 537 | 538 | return createParser; 539 | } 540 | -------------------------------------------------------------------------------- /lib/main.js: -------------------------------------------------------------------------------- 1 | var angular = require("angular"); 2 | 3 | angular.module("datetime", []); 4 | 5 | angular.module("datetime").constant("datetimePlaceholder", { 6 | year: "(year)", 7 | yearShort: "(year)", 8 | month: "(month)", 9 | date: "(date)", 10 | day: "(day)", 11 | hour: "(hour)", 12 | hour12: "(hour12)", 13 | minute: "(minute)", 14 | second: "(second)", 15 | millisecond: "(millisecond)", 16 | ampm: "(AM/PM)", 17 | week: "(week)" 18 | }); 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-datetime-input", 3 | "version": "5.3.0", 4 | "description": "A directive to add the behavior of datetime input on unsupported browsers", 5 | "keywords": [ 6 | "angular", 7 | "datetime", 8 | "input", 9 | "time", 10 | "parser" 11 | ], 12 | "eslintIgnore": [ 13 | "dist" 14 | ], 15 | "scripts": { 16 | "test": "eslint **/*.js --cache && c8 --reporter=lcov mocha", 17 | "build": "rollup -c && node build-demo.js", 18 | "watch": "rollup -cw", 19 | "preversion": "npm test && npm run build", 20 | "version": "git add .", 21 | "postversion": "git push --follow-tags && npm publish" 22 | }, 23 | "homepage": "https://github.com/eight04/angular-datetime", 24 | "bugs": { 25 | "url": "https://github.com/eight04/angular-datetime/issues", 26 | "email": "eight04@gmail.com" 27 | }, 28 | "license": "MIT", 29 | "author": "eight ", 30 | "main": "index.js", 31 | "unpkg": "dist/datetime.js", 32 | "repository": { 33 | "type": "git", 34 | "url": "https://github.com/eight04/angular-datetime.git" 35 | }, 36 | "dependencies": { 37 | "custom-input": "^0.3.1" 38 | }, 39 | "devDependencies": { 40 | "@babel/core": "^7.4.5", 41 | "@babel/preset-env": "^7.4.5", 42 | "angular": "^1.7.8", 43 | "angular-mocks": "^1.7.8", 44 | "babel-core": "^6.26.3", 45 | "c8": "^5.0.1", 46 | "eslint": "^5.16.0", 47 | "eslint-config-angular": "^0.5.0", 48 | "eslint-plugin-angular": "^4.0.1", 49 | "jsdom": "^15.1.1", 50 | "jsdom-global": "^3.0.2", 51 | "mocha": "^6.1.4", 52 | "rollup": "^1.13.1", 53 | "rollup-plugin-babel": "^4.3.2", 54 | "rollup-plugin-cjs-es": "^0.8.0", 55 | "rollup-plugin-node-resolve": "^5.0.1", 56 | "rollup-plugin-uglify": "^6.0.2" 57 | }, 58 | "peerDependencies": { 59 | "angular": "^1.2.0" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import cjs from "rollup-plugin-cjs-es"; 2 | import babel from "rollup-plugin-babel"; 3 | import {uglify} from "rollup-plugin-uglify"; 4 | import resolve from "rollup-plugin-node-resolve"; 5 | 6 | export default { 7 | input: "index.js", 8 | output: { 9 | file: "dist/datetime.js", 10 | format: "iife", 11 | globals: {angular: "angular"}, 12 | sourcemap: false 13 | }, 14 | external: ["angular"], 15 | plugins: [ 16 | resolve(), 17 | cjs({nested: true}), 18 | babel(), 19 | uglify({ 20 | // https://github.com/mishoo/UglifyJS2/issues/3197 21 | compress: { 22 | reduce_vars: false 23 | }, 24 | ie8: true 25 | }) 26 | ] 27 | }; 28 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | require("jsdom-global")(); 3 | 4 | var {describe, it, beforeEach, afterEach} = require("mocha"), 5 | assert = require("assert"); 6 | 7 | // setup angular 8 | require("angular/angular"); 9 | global.angular = window.angular; 10 | 11 | // setup mocha for angular mock 12 | window.mocha = true; 13 | window.beforeEach = beforeEach; 14 | window.afterEach = afterEach; 15 | require("angular-mocks"); 16 | 17 | var {module, inject} = window; 18 | 19 | require("../index"); 20 | 21 | var FORMATS = [ 22 | "yyyy-MM-dd HH:mm:ss", 23 | "medium", 24 | "short", 25 | "fullDate", 26 | "longDate", 27 | "mediumDate", 28 | "shortDate", 29 | "mediumTime", 30 | "shortTime", 31 | ",sss .sss", 32 | "yyyy-MM-dd", 33 | "Z" 34 | ]; 35 | 36 | function insertColon(timezone) { 37 | if (timezone[3] == ":") { 38 | return timezone; 39 | } 40 | return timezone.substr(0, 3) + ":" + timezone.substr(3, 2); 41 | } 42 | 43 | function randomTimezone(){ 44 | var offset = Math.floor(Math.random() * 24 * 60) - 12 * 60, 45 | sign = offset >= 0 ? "+" : "-", 46 | absOffset = Math.abs(offset), 47 | hour = Math.floor(absOffset / 60), 48 | min = absOffset % 60, 49 | text = sign + padStart(hour, 2, "0") + padStart(min, 2, "0"); 50 | return { 51 | time: offset * 60 * 1000, 52 | text: text 53 | }; 54 | } 55 | 56 | function padStart(text, n, pad = " ") { 57 | text = String(text); 58 | if (n > text.length) { 59 | text = pad 60 | .repeat(Math.ceil((n - text.length) / pad.length)) 61 | .slice(0, n - text.length) + text; 62 | } 63 | return text; 64 | } 65 | 66 | describe("datetime service", () => { 67 | var datetime, $date; 68 | 69 | beforeEach(module("datetime")); 70 | beforeEach(inject(function(_datetime_, $filter) { 71 | datetime = _datetime_; 72 | $date = $filter("date"); 73 | })); 74 | 75 | FORMATS.forEach(format => { 76 | it(`Format: ${format}`, () => { 77 | var parser = datetime(format), 78 | date = new Date, 79 | text, model; 80 | 81 | text = parser.setDate(date).getText(); 82 | assert.equal(text, $date(date, format)); 83 | model = parser.parse(text).getDate(); 84 | // 'yy' is ambigous in shortDate/short 85 | if (format == "shortDate" || format == "short") { 86 | assert.equal(model.getFullYear() % 100, date.getFullYear() % 100); 87 | model.setFullYear(date.getFullYear()); 88 | } 89 | assert.equal(model.getTime(), date.getTime()); 90 | }); 91 | }); 92 | 93 | 94 | it("duplicate tokens", () => { 95 | var parser = datetime("yyyy-yyyy"); 96 | parser.parse("2000-2000"); 97 | 98 | assert.throws( 99 | () => parser.parse("2000-2001"), 100 | err => err.properText == "2001-2001" 101 | ); 102 | 103 | assert.throws( 104 | () => parser.parse("2001-2000"), 105 | err => err.properText == "2001-2001" 106 | ); 107 | }); 108 | 109 | it("tokens affect each others", () => { 110 | var parser = datetime("fullDate"); 111 | parser.parse("Tuesday, May 5, 2015"); 112 | assert.throws( 113 | () => parser.parse("Tuesday, May 1, 2015"), 114 | err => err.properText == "Friday, May 1, 2015" 115 | ); 116 | parser.parse("Friday, May 1, 2015"); 117 | assert.throws( 118 | () => parser.parse("Friday, May 19, 2015"), 119 | err => err.properText == "Tuesday, May 19, 2015" 120 | ); 121 | parser.parse("Tuesday, May 19, 2015"); 122 | assert.equal(parser.getText(), "Tuesday, May 19, 2015"); 123 | assert.throws( 124 | () => parser.parse("Monday, May 19, 2015"), 125 | err => err.properText == "Monday, May 18, 2015" 126 | ); 127 | parser.parse("Monday, May 18, 2015"); 128 | parser.parse("Sunday, May 17, 2015"); 129 | parser.parse("Sunday, May 17, 2015"); 130 | }); 131 | 132 | it("31 date overflow", () => { 133 | var parser = datetime("medium"); 134 | 135 | parser.parse("Mar 31, 2016 6:19:20 PM"); 136 | parser.parse("Apr 1, 2016 10:42:20 AM"); 137 | }); 138 | 139 | it("initial value", () => { 140 | var parser = datetime("fullDate"), 141 | date = new Date; 142 | 143 | assert.ok(date.getTime() - parser.getDate().getTime() < 10); 144 | assert.equal(parser.getText(), $date(parser.getDate(), "fullDate")); 145 | }); 146 | 147 | it("timezone: utc time + offset should always equal on same date", () => { 148 | var parser = datetime("medium"), 149 | r1 = randomTimezone(), 150 | r2 = randomTimezone(), 151 | text = parser.getText(), 152 | t1, t2; 153 | 154 | parser.setTimezone(r1.text); 155 | parser.parse(text); 156 | t1 = parser.getDate().getTime(); 157 | 158 | parser.setTimezone(r2.text); 159 | parser.parse(text); 160 | t2 = parser.getDate().getTime(); 161 | 162 | assert.equal(t1 + r1.time, t2 + r2.time); 163 | }); 164 | 165 | it("ZZ token", () => { 166 | var parser = datetime("ZZ"); 167 | 168 | assert.equal(parser.getText(), insertColon($date(parser.getDate(), "Z"))); 169 | }); 170 | 171 | it("Overflowed day with empty month", ()=> { 172 | var parser = datetime("dd.MM.yyyy"); 173 | parser.parse("01.06.2017"); 174 | assert.throws( 175 | () => parser.parse("31.(month).(year)"), 176 | err => err.code == "NOT_INIT" 177 | ); 178 | }); 179 | 180 | it("Overflowed day with empty month (add)", ()=> { 181 | var parser = datetime("dd.MM.yyyy"); 182 | parser.parse("30.06.2017"); 183 | parser.tp.nodes[0].add(1); 184 | assert.equal(parser.getText(), "01.07.2017"); 185 | 186 | parser.parse("30.06.2017"); 187 | parser.tp.unset(); 188 | parser.tp.nodes[0].add(1); 189 | assert.equal(parser.getText(), "31.(month).(year)"); 190 | }); 191 | 192 | }); 193 | 194 | describe("datetime directive", function(){ 195 | var $rootScope, $date, $compile; 196 | 197 | beforeEach(module("datetime")); 198 | beforeEach(inject(function(_$compile_, _$rootScope_, $filter){ 199 | $rootScope = _$rootScope_; 200 | $date = $filter("date"); 201 | $compile = _$compile_; 202 | })); 203 | 204 | FORMATS.forEach(format => { 205 | it(`Format: ${format}`, function(){ 206 | $rootScope.format = format; 207 | $rootScope.date = new Date; 208 | 209 | var element = $compile("")($rootScope); 210 | 211 | $rootScope.$digest(); 212 | 213 | assert.equal(element.val(), $date($rootScope.date, format)); 214 | }); 215 | }); 216 | 217 | it("timezone and utc", function(){ 218 | $rootScope.date = new Date; 219 | 220 | var element = $compile("")($rootScope); 221 | 222 | $rootScope.$digest(); 223 | 224 | assert.equal(element.val(), "+0000"); 225 | }); 226 | 227 | it("datetime-timezone and custom timezone", function(){ 228 | $rootScope.date = new Date; 229 | $rootScope.timezone = "+0500"; 230 | 231 | var element = $compile("")($rootScope); 232 | 233 | $rootScope.$digest(); 234 | 235 | assert.equal(element.val(), "+0500"); 236 | }); 237 | 238 | it("datetime-timezone and utc format with colon", function(){ 239 | $rootScope.date = new Date; 240 | $rootScope.timezone = "+07:00"; 241 | 242 | var element = $compile("")($rootScope); 243 | 244 | $rootScope.$digest(); 245 | 246 | assert.equal(element.val(), "+0700"); 247 | }); 248 | 249 | it("dynamic datetime-timezone", function(){ 250 | $rootScope.date = new Date; 251 | $rootScope.timezone = "+0500"; 252 | 253 | var element = $compile("")($rootScope); 254 | $rootScope.$digest(); 255 | assert.equal(element.val(), "+0500"); 256 | 257 | $rootScope.timezone = "+0800"; 258 | $rootScope.$digest(); 259 | assert.equal(element.val(), "+0800"); 260 | }); 261 | 262 | it("static datetime-timezone", function(){ 263 | $rootScope.date = new Date; 264 | 265 | var element = $compile("")($rootScope); 266 | $rootScope.$digest(); 267 | assert.equal(element.val(), "+0500"); 268 | }); 269 | 270 | it("dynamic datetime-utc", function(){ 271 | var date = $rootScope.date = new Date; 272 | $rootScope.utc = true; 273 | 274 | var element = $compile("")($rootScope); 275 | 276 | $rootScope.$digest(); 277 | 278 | assert.equal(element.val(), "+0000"); 279 | 280 | $rootScope.utc = false; 281 | 282 | $rootScope.$digest(); 283 | 284 | assert.equal(element.val(), $date(date, "Z")); 285 | }); 286 | 287 | it("datetime-model", function(){ 288 | var date = new Date; 289 | $rootScope.dateString = $date(date, "yyyy-MM-dd HH:mm:ss"); 290 | var element = $compile("")($rootScope); 291 | 292 | $rootScope.$digest(); 293 | 294 | assert.equal(element.val(), $date(date, "medium")); 295 | }); 296 | 297 | it("min & max", function(){ 298 | $rootScope.min = "2000-01-01"; 299 | $rootScope.max = "2020-01-01"; 300 | 301 | var element = $compile("")($rootScope); 302 | 303 | $rootScope.$digest(); 304 | 305 | element.val("1999-01-01 00:00:00").triggerHandler("input"); 306 | $rootScope.$digest(); 307 | assert.equal(element.hasClass("ng-invalid-min"), true); 308 | 309 | element.val("2016-06-18 22:59:00").triggerHandler("input"); 310 | $rootScope.$digest(); 311 | assert.equal(element.hasClass("ng-invalid"), false); 312 | 313 | element.val("2021-01-01 00:00:00").triggerHandler("input"); 314 | $rootScope.$digest(); 315 | assert.equal(element.hasClass("ng-invalid-max"), true); 316 | 317 | $rootScope.min = null; 318 | $rootScope.max = null; 319 | $rootScope.$digest(); 320 | assert.equal(element.hasClass("ng-invalid"), false); 321 | }); 322 | }); 323 | --------------------------------------------------------------------------------