├── .babelrc
├── .eslintrc.json
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── dist
├── grudus-timepicker.es5.js
├── grudus-timepicker.es5.js.map
├── grudus-timepicker.js
├── grudus-timepicker.js.map
├── grudus-timepicker.umd.js
├── grudus-timepicker.umd.js.map
└── index.css
├── package.json
├── rollup
├── es5.js
├── es6.js
└── umd.js
└── src
├── js
├── clock.js
├── clockHeader.js
├── colorStylists.js
├── face
│ ├── clockFace.js
│ ├── clockFaceCreator.js
│ ├── hoursFace.js
│ └── minutesFace.js
├── index.js
├── meta
│ ├── clockHtml.js
│ ├── config.js
│ └── utils.js
├── timeExtractor.js
├── timeFormatter.js
└── timepickerCreator.js
└── styles
└── index.css
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "es2015",
5 | {
6 | "modules": false
7 | }
8 | ]
9 | ],
10 | "ignore": "node_modules/**",
11 | "plugins": [
12 | "external-helpers"
13 | ]
14 | }
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "commonjs": true,
5 | "es6": true
6 | },
7 | "extends": "eslint:recommended",
8 | "parserOptions": {
9 | "sourceType": "module"
10 | },
11 | "rules": {
12 | "indent": [
13 | "error",
14 | 4
15 | ],
16 | "quotes": [
17 | "error",
18 | "double"
19 | ],
20 | "semi": [
21 | "error",
22 | "always"
23 | ],
24 | "dot-location": [
25 | "error",
26 | "property"
27 | ],
28 | "eqeqeq": [
29 | "error",
30 | "always"
31 | ],
32 | "camelcase": "error",
33 | "max-len": [
34 | "error",
35 | 120
36 | ],
37 | "max-lines": [
38 | "error",
39 | 150
40 | ],
41 | "max-depth": [
42 | "error",
43 | 2
44 | ],
45 | "max-params": [
46 | "error",
47 | 4
48 | ],
49 | "no-var": "error",
50 | "one-var-declaration-per-line": "error",
51 | "prefer-const": "warn"
52 | }
53 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | node_modules/
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | node_modules/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2017 grudus
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Grudus Timepicker
2 |
3 | 
4 | 
5 | 
6 | 
7 | 
8 |
9 | Material design timepicker written in Javascript (without any external dependencies - **no jQuery, no Bootstrap, only one file!**)
10 | See https://grudus.github.io/Timepicker/ for more usage!
11 |
12 | ## How it looks?
13 |
14 | By default picker uses blue-white theme:
15 |
16 | 
17 |
18 |
19 | But you can change its colors by overriding some of default configuration:
20 |
21 | ````javascript
22 | defaultConfig = {
23 | headerBackground: "#1976D2",
24 | headerColor: "#c7d6e1",
25 | headerSelected: "#ffffff",
26 | wrapperBackground: "#f0fff0",
27 | footerBackground: "#f0fff0",
28 | submitColor: "#1976D2",
29 | cancelColor: "#1976D2",
30 | clockBackground: "#CFD8DC",
31 | clockItemColor: "#212121",
32 | clockItemInnerColor: "#212121",
33 | handColor: "#1976D2"
34 | };
35 | ````
36 |
37 |
38 | How custom theme can look:
39 |
40 |
41 | 
42 |
43 |
44 | But you can also create more user-friendly view - create your own dark theme:
45 |
46 |
47 | 
48 |
49 |
50 |
51 | ## How to get it?
52 |
53 | You can include all in single `html` file! Just add
54 |
55 | ````html
56 |
57 |
58 |
59 |
60 | Show picker
61 |
62 |
63 | ````
64 |
65 | Or, you can download it from npm
66 |
67 | ````bash
68 | npm install --save grudus-timepicker
69 | ````
70 |
71 | Then, include `index.css` into your project (e.g. add
72 | ` ` into your html file)
73 |
74 | And lastly, somewhere in your code put
75 |
76 | ````javascript
77 | import Timepicker from "path/to/grudus-timepicker/dist/grudus-timepicker.js";
78 |
79 | // ...
80 |
81 | Timepicker.showPicker({
82 | time: new Date(),
83 | onSubmit: (time) => {
84 | //some action ...
85 | },
86 | headerColor: "#ff0000"
87 | // more color configuration ...
88 | })
89 | ````
90 |
91 | You can set initial time by passing `time` field in argument. `time` may be a `Date` object, an object `{hours: 12, minutes: 44}` or a string in format `HH:mm`. If you want to learn more, visit [customization section](https://grudus.github.io/Timepicker/#customization)
92 |
--------------------------------------------------------------------------------
/dist/grudus-timepicker.es5.js:
--------------------------------------------------------------------------------
1 | /*! grudus-timepicker | (c) 2017-2017
2 | grudus | Apache-2.0 license (see LICENSE) */
3 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Timepicker=t()}(this,function(){"use strict";function e(e){if(e){if(e instanceof Date)return i(e);if(r.test(e.hours)&&u.test(e.minutes))return{hours:parseInt(e.hours),minutes:parseInt(e.minutes)};if(a.test(e))return t(e);throw new TypeError("INVALID FORMAT: {"+JSON.stringify(e)+"}.\n Time must be a Date or 'hh:MM' string or object with 'hours' and 'minutes' fields")}return i(new Date)}function t(e){var t=a.exec(e);return{hours:parseInt(t[1]),minutes:parseInt(t[2])}}function i(e){return{hours:e.getHours(),minutes:e.getMinutes()}}function n(e){return new Promise(function(t){setTimeout(t,e)})}function o(e){document.getElementById(f.headerId).style.background=e.headerBackground,document.getElementById(f.headerId).style.color=e.headerColor,document.getElementById(f.wrapperId).style.background=e.wrapperBackground,document.getElementById(f.clockId).style.background=e.clockBackground,document.getElementById(f.handId).style.background=e.handColor,document.getElementById(f.dotId).style.background=e.handColor,document.getElementById(f.buttonsId).style.background=e.footerBackground,document.getElementById(f.submitId).style.color=e.submitColor,document.getElementById(f.cancelId).style.color=e.cancelColor,s(m.clockItem,e.clockItemColor),s(m.inner,e.clockItemInnerColor),s(m.outer,e.handColor,"borderColor")}function s(e,t){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"color",n=Array.from(document.getElementsByClassName(e)),o=!0,s=!1,c=void 0;try{for(var l,r=n[Symbol.iterator]();!(o=(l=r.next()).done);o=!0)l.value.style[i]=t}catch(e){s=!0,c=e}finally{try{!o&&r.return&&r.return()}finally{if(s)throw c}}}function c(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};l();var i=Object.assign({},k.clockConfig,t),n=e(i.time),s=new b(i,n);o(i),s.onStart()}function l(){if(document.getElementById(k.clockId))throw Error("There is already one running grudus-timepicker instance!");var e=document.createElement("div");e.id=k.clockId,e.innerHTML=h,document.body.appendChild(e)}var r=/^([0-1]?[0-9]|2[0-3])$/,u=/^([0-5]?[0-9])$/,a=/^([0-1]?[0-9]|2[0-3]):([0-5][0-9])$/,d=function(t){var i=e(t);return(i.hours<10?"0"+i.hours:i.hours)+":"+(i.minutes<10?"0"+i.minutes:i.minutes)},h="",m={clock:"g-clock",clockItem:"g-clock-item",inner:"g-clock-inner",outer:"g-clock-outer",item:"g-clock-item",hand:"g-hand-of-a-clock",fadeOut:"g-fade-out",selected:"g-selected",active:"g-active",submit:"g-submit",cancel:"g-cancel",hour:"g-hour",minute:"g-minute"},f={headerId:"g-head",hoursId:"g-hours",minutesId:"g-minutes",clockId:"g-clock",innerId:"g-clock-inner",wrapperId:"g-clock-wrapper",dotId:"g-middle-dot",handId:"g-hand-of-a-clock",buttonsId:"g-buttons",submitId:"g-time-submit",cancelId:"g-time-cancel"},k={clockId:"grudus-clock",clockConfig:{onSubmit:function(){},onCancel:function(){},headerBackground:"#1976D2",headerColor:"#c7d6e1",headerSelected:"#ffffff",wrapperBackground:"#f0fff0",footerBackground:"#f0fff0",submitColor:"#1976D2",cancelColor:"#1976D2",clockBackground:"#CFD8DC",clockItemColor:"#212121",clockItemInnerColor:"#212121",handColor:"#1976D2"},FaceType:{HOURS:"hours",MINUTES:"minutes"}},g=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},p=function(){function e(e,t){for(var i=0;i-1}}]),e}(),I=function(){function e(t,i,n){g(this,e),this.displayed=["12","1","2","3","4","5","6","7","8","9","10","11"],this.displayedInner=["00","13","14","15","16","17","18","19","20","21","22","23"],this.type=k.FaceType.MINUTES,this.selected=void 0,this.options=t.options,this.items=t,this.hours=i,this.updateHours=n}return p(e,[{key:"onEnter",value:function(){this.items.innerClockElem.style.display="block";var e=this.hours<13&&0!==this.hours,t=this.hours%12;this.selected=e?this.items.clockItems[t]:this.items.innerClockItems[t],this.colorSelected(),this.updateHours(this.hours,30*t,e?this.items.radius:this.items.radius-50)}},{key:"onLeave",value:function(){this.items.innerClockElem.style.display="none",this.selected&&(this.removeSelected(),this.selected=void 0)}},{key:"selectTime",value:function(e,t){this.selected&&this.removeSelected();var i=Math.round(e/30)%12;this.selected=(t===this.items.innerClockElem?this.items.innerClockItems:this.items.clockItems)[i],this.colorSelected(),this.hours=parseInt(this.selected.innerText);var n=30*Math.round(e/30);this.updateHours(this.hours,n,t===this.items.innerClockElem?this.items.radius-50:this.items.radius)}},{key:"colorSelected",value:function(){this.selected.style.background=this.options.handColor,this.selected.style.color="#ffffff"}},{key:"removeSelected",value:function(){this.selected.style.background="transparent",this.selected.style.color=this.isInner()?this.options.clockItemInnerColor:this.options.clockItemColor}},{key:"isInner",value:function(){return Array.from(this.items.innerClockItems).indexOf(this.selected)>-1}}]),e}();Promise.delay=function(e,t){return t||(t=e,e=function(){}),n(t).then(e)},Promise.prototype.delay=function(e,t){return this.then(function(){return Promise.delay(e,t)})};var C={toRadians:function(e){return e*(Math.PI/180)},toDegrees:function(e){return e*(180/Math.PI)},findMousePosition:function(e,t){var i=t.getBoundingClientRect();return{x:e.clientX-i.left,y:e.clientY-i.top}}},E=function(){function e(t,i){g(this,e),this.clockElem=t,this.innerClockElem=i,this.size={},this.middle={}}return p(e,[{key:"create",value:function(t,i,n,o){e.doCreate(t,this.clockElem,function(e){return e.classList.add(m.item)}),e.doCreate(i,this.innerClockElem,function(e,t){e.classList.add(m.item,m.inner),e.innerText=o.displayedInner[t]});for(var s=0;s<60;s++){var c=document.createElement("span");c.classList.add(m.outer),n.push(c),this.clockElem.appendChild(c)}}},{key:"calculateSize",value:function(t,i,n){this.size.width=this.clockElem.offsetWidth,this.size.height=this.clockElem.offsetHeight,this.middle.x=this.size.width/2,this.middle.y=this.size.height/2,this.itemsRadius=this.size.width/2-20;var o=this.innerClockElem.offsetWidth/2,s=this.innerClockElem.offsetHeight/2;e.doCalculateSize(this.middle.x,this.middle.y,this.itemsRadius,t),e.doCalculateSize(o,s,this.itemsRadius-40,i),e.doCalculateSize(this.middle.x,this.middle.y,this.itemsRadius,n)}}],[{key:"doCreate",value:function(e,t,i){for(var n=0;n<12;n++){var o=document.createElement("span");i(o,n),e.push(o),t.appendChild(o)}}},{key:"doCalculateSize",value:function(e,t,i,n){for(var o=360/n.length,s=0;s1&&void 0!==arguments[1]?arguments[1]:this.itemsRadius;this.handOfAClock.style.transform="rotate("+(e-90)+"deg)",this.handOfAClock.style.width=t+"px"}},{key:"toggleToHours",value:function(){this.minutesFace.onLeave(),this.toggleTime(this.hoursFace)}},{key:"toggleToMinutes",value:function(){this.hoursFace.onLeave(),this.toggleTime(this.minutesFace)}},{key:"toggleTime",value:function(e){var t=this;this.currentFace!==e&&(this.onEachClockElement(function(e){return e.classList.add(m.fadeOut)}),this.handOfAClock.classList.add(m.fadeOut),Promise.delay(function(){t.onEachClockElement(function(e){return e.classList.remove(m.fadeOut)}),t.handOfAClock.classList.remove(m.fadeOut),t.changeDisplayed(e.displayed),t.currentFace=e,t.onEachClockElement(function(e){return t.removeSelected(e)}),e.onEnter()},300))}},{key:"removeSelected",value:function(e){e.classList.remove(m.selected),e.style.background="transparent",e.style.color=this.options.clockItemColor}}]),e}(),b=function(){function e(t,i){g(this,e),this.options=t,this.initView(),this.time=i,this.initElements()}return p(e,[{key:"initView",value:function(){var t=this;this.submitButton=document.getElementById(f.submitId),this.submitButton.onclick=function(){var i=t.time;i.formatted=function(){return d(i)},t.options.onSubmit(i),e.dispose()},this.cancelButton=document.getElementById(f.cancelId),this.cancelButton.onclick=function(){t.options.onCancel(),e.dispose()}}},{key:"initElements",value:function(){var e=this;this.header=new y({options:this.options,time:this.time,onHourClicked:function(){return e.toggleToHours()},onMinutesClicked:function(){return e.toggleToMinutes()}}),this.clockFace=new T(this.options,this.time,function(t,i){return e.onTimeUpdate(t,i)})}},{key:"onStart",value:function(){this.clockFace.onStart()}},{key:"toggleToHours",value:function(){this.clockFace.toggleToHours()}},{key:"toggleToMinutes",value:function(){this.clockFace.toggleToMinutes()}},{key:"onTimeUpdate",value:function(e,t){this.time=e,this.header.time=e,this.header.updateDisplayedTime(),t===k.FaceType.MINUTES&&this.header.toggleActiveToMinutes()}}],[{key:"dispose",value:function(){document.body.removeChild(document.getElementById(k.clockId))}}]),e}();return{showPicker:function(e){return c(e)},format:function(e){return d(e)}}});
4 | //# sourceMappingURL=grudus-timepicker.es5.js.map
5 |
--------------------------------------------------------------------------------
/dist/grudus-timepicker.es5.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"grudus-timepicker.es5.js","sources":["../src/js/timeExtractor.js","../src/js/meta/utils.js","../src/js/colorStylists.js","../src/js/timepickerCreator.js","../src/js/timeFormatter.js","../src/js/meta/clockHtml.js","../src/js/meta/config.js","../src/js/clockHeader.js","../src/js/face/minutesFace.js","../src/js/face/hoursFace.js","../src/js/face/clockFaceCreator.js","../src/js/face/clockFace.js","../src/js/clock.js","../src/js/index.js"],"sourcesContent":["const hoursRegex = /^([0-1]?[0-9]|2[0-3])$/;\r\nconst minutesRegex = /^([0-5]?[0-9])$/;\r\nconst regex = /^([0-1]?[0-9]|2[0-3]):([0-5][0-9])$/;\r\n\r\nexport default function extractTime(date) {\r\n if (!date)\r\n return fromDate(new Date());\r\n else if (date instanceof Date)\r\n return fromDate(date);\r\n else if (hoursRegex.test(date.hours) && minutesRegex.test(date.minutes))\r\n return {hours: parseInt(date.hours), minutes: parseInt(date.minutes)};\r\n else if (regex.test(date))\r\n return fromRegex(date);\r\n else\r\n throw new TypeError(`INVALID FORMAT: {${JSON.stringify(date)}}.\r\n Time must be a Date or 'hh:MM' string or object with 'hours' and 'minutes' fields`);\r\n}\r\n\r\nfunction fromRegex(date) {\r\n const parsed = regex.exec(date);\r\n return {hours: parseInt(parsed[1]), minutes: parseInt(parsed[2])};\r\n}\r\n\r\nfunction fromDate(date) {\r\n return {hours: date.getHours(), minutes: date.getMinutes()};\r\n}","function toRadians(angle) {\r\n return angle * (Math.PI / 180);\r\n}\r\n\r\nfunction toDegrees(angle) {\r\n return angle * (180 / Math.PI);\r\n}\r\n\r\nfunction findMousePosition(event, object) {\r\n const rect = object.getBoundingClientRect();\r\n return {\r\n x: event.clientX - rect.left,\r\n y: event.clientY - rect.top\r\n };\r\n}\r\n\r\nfunction delay(t) {\r\n return new Promise(function (resolve) {\r\n setTimeout(resolve, t);\r\n });\r\n}\r\n\r\nPromise.delay = function (fn, t) {\r\n if (!t) {\r\n t = fn;\r\n fn = function () {\r\n };\r\n }\r\n return delay(t).then(fn);\r\n};\r\n\r\nPromise.prototype.delay = function (fn, t) {\r\n return this.then(function () {\r\n return Promise.delay(fn, t);\r\n });\r\n};\r\n\r\nexport default {toRadians, toDegrees, findMousePosition};","import {css, DOM} from \"./meta/config\";\r\n\r\nexport default function styleColors(options) {\r\n document.getElementById(DOM.headerId).style.background = options.headerBackground;\r\n document.getElementById(DOM.headerId).style.color = options.headerColor;\r\n document.getElementById(DOM.wrapperId).style.background = options.wrapperBackground;\r\n document.getElementById(DOM.clockId).style.background = options.clockBackground;\r\n document.getElementById(DOM.handId).style.background = options.handColor;\r\n document.getElementById(DOM.dotId).style.background = options.handColor;\r\n document.getElementById(DOM.buttonsId).style.background = options.footerBackground;\r\n document.getElementById(DOM.submitId).style.color = options.submitColor;\r\n document.getElementById(DOM.cancelId).style.color = options.cancelColor;\r\n\r\n changeColor(css.clockItem, options.clockItemColor);\r\n changeColor(css.inner, options.clockItemInnerColor);\r\n changeColor(css.outer, options.handColor, \"borderColor\");\r\n}\r\n\r\nfunction changeColor(className, color, property = \"color\") {\r\n const items = Array.from(document.getElementsByClassName(className));\r\n for (const item of items)\r\n item.style[property] = color;\r\n}\r\n","import clockHtml from \"./meta/clockHtml\";\r\nimport Config from \"./meta/config\";\r\nimport Clock from \"./clock\";\r\nimport styleColors from \"./colorStylists\";\r\nimport getTime from \"./timeExtractor\";\r\n\r\n\r\nexport default function showPicker(config = {}) {\r\n createDom();\r\n\r\n const options = Object.assign({}, Config.clockConfig, config);\r\n const time = getTime(options.time);\r\n\r\n const clock = new Clock(options, time);\r\n styleColors(options);\r\n clock.onStart();\r\n}\r\n\r\n\r\nfunction createDom() {\r\n if (document.getElementById(Config.clockId))\r\n throw Error(\"There is already one running grudus-timepicker instance!\");\r\n\r\n const clockDiv = document.createElement(\"div\");\r\n clockDiv.id = Config.clockId;\r\n clockDiv.innerHTML = clockHtml;\r\n document.body.appendChild(clockDiv);\r\n}\r\n","import extractTime from \"./timeExtractor\";\r\n\r\nexport default function (time) {\r\n const extractedTime = extractTime(time);\r\n return (extractedTime.hours < 10 ? \"0\" + extractedTime.hours : extractedTime.hours)\r\n + \":\" + (extractedTime.minutes < 10 ? \"0\" + extractedTime.minutes : extractedTime.minutes);\r\n}","export default \"\\n\" +\r\n\" \\n\" +\r\n\" \\n\" +\r\n\" 21 \\n\" +\r\n\" : \\n\" +\r\n\" 37 \\n\" +\r\n\" \\n\" +\r\n\" \\n\" +\r\n\"\\n\" +\r\n\"\\n\" +\r\n\" \\n\" +\r\n\" \" +\r\n\"
\\n\" +\r\n\"
\\n\" +\r\n\"
\\n\" +\r\n\"
\\n\" +\r\n\" \\n\" +\r\n\"\\n\" +\r\n\"\\n\" +\r\n\" \\n\" +\r\n\"\\n\" +\r\n\" \";","const clockId = \"grudus-clock\";\r\n\r\nconst defaultConfig = {\r\n onSubmit: () => {\r\n },\r\n onCancel: () => {\r\n },\r\n headerBackground: \"#1976D2\",\r\n headerColor: \"#c7d6e1\",\r\n headerSelected: \"#ffffff\",\r\n wrapperBackground: \"#f0fff0\",\r\n footerBackground: \"#f0fff0\",\r\n submitColor: \"#1976D2\",\r\n cancelColor: \"#1976D2\",\r\n clockBackground: \"#CFD8DC\",\r\n clockItemColor: \"#212121\",\r\n clockItemInnerColor: \"#212121\",\r\n handColor: \"#1976D2\"\r\n};\r\n\r\nconst FaceType = {HOURS: \"hours\", MINUTES: \"minutes\"};\r\n\r\nconst css = {\r\n clock: \"g-clock\",\r\n clockItem: \"g-clock-item\",\r\n inner: \"g-clock-inner\",\r\n outer: \"g-clock-outer\",\r\n item: \"g-clock-item\",\r\n hand: \"g-hand-of-a-clock\",\r\n fadeOut: \"g-fade-out\",\r\n selected: \"g-selected\",\r\n active: \"g-active\",\r\n submit: \"g-submit\",\r\n cancel: \"g-cancel\",\r\n hour: \"g-hour\",\r\n minute: \"g-minute\"\r\n};\r\n\r\nconst DOM = {\r\n headerId: \"g-head\",\r\n hoursId: \"g-hours\",\r\n minutesId: \"g-minutes\",\r\n clockId: \"g-clock\",\r\n innerId: \"g-clock-inner\",\r\n wrapperId: \"g-clock-wrapper\",\r\n dotId: \"g-middle-dot\",\r\n handId: \"g-hand-of-a-clock\",\r\n buttonsId: \"g-buttons\",\r\n submitId: \"g-time-submit\",\r\n cancelId: \"g-time-cancel\"\r\n};\r\n\r\nexport default {clockId, clockConfig: defaultConfig, FaceType};\r\nexport {css, DOM};","import {DOM} from \"./meta/config\";\r\n\r\nexport default class ClockHeader {\r\n\r\n constructor(config) {\r\n this.options = config.options;\r\n this.time = config.time;\r\n this.onHourClicked = config.onHourClicked;\r\n this.onMinutesClicked = config.onMinutesClicked;\r\n\r\n this.initView();\r\n }\r\n\r\n initView() {\r\n this.headerHours = document.getElementById(DOM.hoursId);\r\n this.headerHours.onclick = () => {\r\n this.toggleActiveToHours();\r\n this.onHourClicked();\r\n };\r\n\r\n this.headerMinutes = document.getElementById(DOM.minutesId);\r\n this.headerMinutes.onclick = () => {\r\n this.toggleActiveToMinutes();\r\n this.onMinutesClicked();\r\n };\r\n\r\n this.updateDisplayedTime();\r\n this.toggleActiveToHours();\r\n }\r\n\r\n toggleActiveToMinutes() {\r\n this.toggleActive(this.headerHours, this.headerMinutes);\r\n }\r\n\r\n toggleActiveToHours() {\r\n this.toggleActive(this.headerMinutes, this.headerHours);\r\n }\r\n\r\n toggleActive(objectToRemoveClass, objectToAddClass) {\r\n objectToRemoveClass.style.color = this.options.headerColor;\r\n objectToAddClass.style.color = this.options.headerSelected;\r\n }\r\n\r\n updateDisplayedTime() {\r\n ClockHeader.doUpdateDisplayedTime(this.headerHours, this.time.hours);\r\n ClockHeader.doUpdateDisplayedTime(this.headerMinutes, this.time.minutes);\r\n }\r\n\r\n static doUpdateDisplayedTime(node, value) {\r\n if (value < 10)\r\n node.innerText = \"0\" + value;\r\n else node.innerText = value;\r\n }\r\n}","import Config, {css} from \"../meta/config\";\r\n\r\nexport default class MinutesFace {\r\n\r\n constructor(items, initialMinutes, updateMinutes) {\r\n this.displayed = [\"00\", \"05\", \"10\", \"15\", \"20\", \"25\", \"30\", \"35\", \"40\", \"45\", \"50\", \"55\"];\r\n this.options = items.options;\r\n this.type = Config.FaceType.MINUTES;\r\n this.selected = undefined;\r\n this.items = items;\r\n this.minutes = initialMinutes;\r\n this.updateMinutes = updateMinutes;\r\n }\r\n\r\n onEnter() {\r\n this.selected = this.findSelected(this.minutes);\r\n this.colorSelected();\r\n this.updateMinutes(this.minutes, this.minutes * 6);\r\n }\r\n\r\n onLeave() {\r\n if (this.selected) {\r\n this.removeSelected();\r\n this.selected = undefined;\r\n }\r\n }\r\n\r\n selectTime(angle) {\r\n if (this.selected)\r\n this.removeSelected();\r\n\r\n const minute = Math.round(angle / 6) % 60;\r\n this.selected = this.findSelected(minute);\r\n this.colorSelected();\r\n this.minutes = minute;\r\n this.updateMinutes(this.minutes, angle);\r\n }\r\n\r\n findSelected(minute) {\r\n return (minute % 5 === 0) ? this.items.clockItems[minute / 5] : this.items.outerClockItems[minute];\r\n }\r\n\r\n colorSelected() {\r\n if (this.isOuter()) {\r\n this.selected.classList.add(css.selected);\r\n return;\r\n }\r\n this.selected.style.background = this.options.handColor;\r\n this.selected.style.color = \"whitesmoke\";\r\n }\r\n\r\n removeSelected() {\r\n if (this.isOuter()) {\r\n this.selected.classList.remove(css.selected);\r\n return;\r\n }\r\n this.selected.style.background = \"transparent\";\r\n this.selected.style.color = this.options.clockItemColor;\r\n }\r\n\r\n isOuter() {\r\n return this.items.outerClockItems.indexOf(this.selected) > -1;\r\n }\r\n}","import Config from \"../meta/config\";\r\n\r\nexport default class HoursFace {\r\n\r\n constructor(items, initialHours, updateHours) {\r\n this.displayed = [\"12\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\", \"11\"];\r\n this.displayedInner = [\"00\", \"13\", \"14\", \"15\", \"16\", \"17\", \"18\", \"19\", \"20\", \"21\", \"22\", \"23\"];\r\n this.type = Config.FaceType.MINUTES;\r\n this.selected = undefined;\r\n this.options = items.options;\r\n\r\n this.items = items;\r\n this.hours = initialHours;\r\n this.updateHours = updateHours;\r\n }\r\n\r\n onEnter() {\r\n this.items.innerClockElem.style.display = \"block\";\r\n const isInnerClock = this.hours < 13 && this.hours !== 0;\r\n const hoursIndex = this.hours % 12;\r\n this.selected = isInnerClock ? this.items.clockItems[hoursIndex] : this.items.innerClockItems[hoursIndex];\r\n this.colorSelected();\r\n\r\n this.updateHours(this.hours, hoursIndex * 30, isInnerClock ? this.items.radius : this.items.radius - 50);\r\n }\r\n\r\n onLeave() {\r\n this.items.innerClockElem.style.display = \"none\";\r\n if (this.selected) {\r\n this.removeSelected();\r\n this.selected = undefined;\r\n }\r\n }\r\n\r\n selectTime(angle, elem) {\r\n if (this.selected)\r\n this.removeSelected();\r\n\r\n const index = Math.round(angle / 30) % 12;\r\n this.selected = (elem === this.items.innerClockElem\r\n ? this.items.innerClockItems\r\n : this.items.clockItems)[index];\r\n\r\n this.colorSelected();\r\n this.hours = parseInt(this.selected.innerText);\r\n const selectedAngle = Math.round(angle / 30) * 30;\r\n\r\n this.updateHours(this.hours, selectedAngle,\r\n elem === this.items.innerClockElem ? this.items.radius - 50 : this.items.radius);\r\n }\r\n\r\n colorSelected() {\r\n this.selected.style.background = this.options.handColor;\r\n this.selected.style.color = \"#ffffff\";\r\n }\r\n\r\n removeSelected() {\r\n this.selected.style.background = \"transparent\";\r\n this.selected.style.color = this.isInner()\r\n ? this.options.clockItemInnerColor\r\n : this.options.clockItemColor;\r\n }\r\n\r\n isInner() {\r\n return Array.from(this.items.innerClockItems).indexOf(this.selected) > -1;\r\n }\r\n}","import Utils from \"../meta/utils\";\r\nimport {css} from \"../meta/config\";\r\n\r\nexport default class ClockFaceCreator {\r\n\r\n constructor(clockElem, innerClockElem) {\r\n this.clockElem = clockElem;\r\n this.innerClockElem = innerClockElem;\r\n this.size = {};\r\n this.middle = {};\r\n }\r\n\r\n create(clockItems, innerClockItems, outerClockItems, face) {\r\n ClockFaceCreator.doCreate(clockItems, this.clockElem, span => span.classList.add(css.item));\r\n ClockFaceCreator.doCreate(innerClockItems, this.innerClockElem, (span, i) => {\r\n span.classList.add(css.item, css.inner);\r\n span.innerText = face.displayedInner[i];\r\n });\r\n\r\n for (let i = 0; i < 60; i++) {\r\n const span = document.createElement(\"span\");\r\n span.classList.add(css.outer);\r\n outerClockItems.push(span);\r\n this.clockElem.appendChild(span);\r\n }\r\n }\r\n\r\n static doCreate(clockItems, clockElem, fun) {\r\n for (let i = 0; i < 12; i++) {\r\n const span = document.createElement(\"span\");\r\n fun(span, i);\r\n clockItems.push(span);\r\n clockElem.appendChild(span);\r\n }\r\n }\r\n\r\n calculateSize(clockItems, innerClockItems, outerClockItems) {\r\n this.size.width = this.clockElem.offsetWidth;\r\n this.size.height = this.clockElem.offsetHeight;\r\n this.middle.x = this.size.width / 2;\r\n this.middle.y = this.size.height / 2;\r\n this.itemsRadius = this.size.width / 2 - 20;\r\n\r\n const innerWidth = this.innerClockElem.offsetWidth;\r\n const innerHeight = this.innerClockElem.offsetHeight;\r\n const middleX = innerWidth / 2;\r\n const middleY = innerHeight / 2;\r\n\r\n ClockFaceCreator.doCalculateSize(this.middle.x, this.middle.y, this.itemsRadius, clockItems);\r\n ClockFaceCreator.doCalculateSize(middleX, middleY, this.itemsRadius - 40, innerClockItems);\r\n ClockFaceCreator.doCalculateSize(this.middle.x, this.middle.y, this.itemsRadius, outerClockItems);\r\n }\r\n\r\n static doCalculateSize(middleX, middleY, radius, items) {\r\n const angleQuantum = 360 / items.length;\r\n for (let i = 0; i < items.length; i++) {\r\n\r\n const angle = Utils.toRadians(i * angleQuantum);\r\n const item = items[i];\r\n const itemWidth = item.offsetWidth;\r\n const itemHeight = item.offsetHeight;\r\n\r\n item.style.left = ((middleX + Math.sin(angle) * radius) - itemWidth / 2) + \"px\";\r\n item.style.bottom = ((middleY + Math.cos(angle) * radius) - itemHeight / 2) + \"px\";\r\n }\r\n }\r\n}","import MinutesFace from \"./minutesFace\";\r\nimport HoursFace from \"./hoursFace\";\r\nimport Utils from \"../meta/utils\";\r\nimport Config, {css, DOM} from \"../meta/config\";\r\nimport ClockFaceCreator from \"./clockFaceCreator\";\r\n\r\nexport default class ClockFace {\r\n\r\n constructor(options, initialTime, onTimeUpdate) {\r\n this.options = options;\r\n this.time = initialTime;\r\n this.onTimeUpdate = onTimeUpdate;\r\n this.isMouseDown = false;\r\n this.clockItems = [];\r\n this.innerClockItems = [];\r\n this.outerClockItems = [];\r\n this.size = {};\r\n this.middle = {};\r\n\r\n this.initViews();\r\n this.initTimeFaces(initialTime);\r\n this.createFace();\r\n\r\n this.hoursFace.items.radius = this.itemsRadius;\r\n\r\n this.currentFace = this.hoursFace;\r\n this.changeDisplayed(this.currentFace.displayed);\r\n }\r\n\r\n initViews() {\r\n this.clockElem = document.getElementById(DOM.clockId);\r\n this.innerClockElem = document.getElementById(DOM.innerId);\r\n this.handOfAClock = document.getElementById(DOM.handId);\r\n\r\n this.clockElem.onmousedown = () => this.isMouseDown = true;\r\n this.clockElem.onmouseup = () => {this.isMouseDown = false;\r\n this.toggleToMinutes();\r\n };\r\n\r\n this.handOfAClock.onmouseup = (e) => e.stopPropagation();\r\n this.handOfAClock.onmousemove = (e) => e.stopPropagation();\r\n this.handOfAClock.onclick = (e) => e.stopPropagation();\r\n\r\n this.clockElem.onmousemove = (e) => this.selectTime(e, false, this.clockElem);\r\n this.clockElem.onclick = (e) => this.selectTime(e, true, this.clockElem);\r\n\r\n this.innerClockElem.onmousemove = (e) => this.selectTime(e, false, this.innerClockElem);\r\n this.innerClockElem.onclick = (e) => this.selectTime(e, true, this.innerClockElem);\r\n }\r\n\r\n initTimeFaces(initialTime) {\r\n this.minutesFace = new MinutesFace({\r\n options: this.options,\r\n clockItems: this.clockItems,\r\n outerClockItems: this.outerClockItems\r\n }, initialTime.minutes, (minutes, angle) => this.updateMinutes(minutes, angle));\r\n\r\n this.hoursFace = new HoursFace({\r\n options: this.options,\r\n innerClockItems: this.innerClockItems,\r\n clockItems: this.clockItems,\r\n innerClockElem: this.innerClockElem\r\n }, initialTime.hours, (hours, angle, radius) => this.updateHours(hours, angle, radius));\r\n }\r\n\r\n onStart() {\r\n this.currentFace.onEnter();\r\n }\r\n\r\n createFace() {\r\n const clockFaceCreator = new ClockFaceCreator(this.clockElem, this.innerClockElem);\r\n clockFaceCreator.create(this.clockItems, this.innerClockItems, this.outerClockItems, this.hoursFace);\r\n clockFaceCreator.calculateSize(this.clockItems, this.innerClockItems, this.outerClockItems);\r\n\r\n this.size = clockFaceCreator.size;\r\n this.middle = clockFaceCreator.middle;\r\n this.itemsRadius = clockFaceCreator.itemsRadius;\r\n }\r\n\r\n selectTime(event, isMouseDown, elem) {\r\n if (!(isMouseDown || this.isMouseDown))\r\n return;\r\n const mouse = Utils.findMousePosition(event, this.clockElem);\r\n const x = mouse.x - this.middle.x;\r\n const y = this.middle.y - mouse.y;\r\n let angle = 90 - Utils.toDegrees(Math.atan(y / x));\r\n if (x < 0) angle += 180;\r\n\r\n this.currentFace.selectTime(angle, elem);\r\n event.stopPropagation();\r\n }\r\n\r\n changeDisplayed(array) {\r\n for (let i = 0; i < this.clockItems.length; i++)\r\n this.clockItems[i].innerText = array[i];\r\n }\r\n\r\n onEachClockElement(fun) {\r\n [].forEach.call(this.clockItems, c => fun(c));\r\n }\r\n\r\n updateMinutes(minutes, angle) {\r\n this.time.minutes = minutes;\r\n this.calculateHandOfTheClock(angle, this.itemsRadius);\r\n this.onTimeUpdate(this.time, Config.FaceType.MINUTES);\r\n }\r\n\r\n updateHours(hours, angle, radius) {\r\n this.time.hours = hours;\r\n this.calculateHandOfTheClock(angle, radius);\r\n this.onTimeUpdate(this.time, Config.FaceType.HOURS);\r\n }\r\n\r\n calculateHandOfTheClock(angle, size = this.itemsRadius) {\r\n this.handOfAClock.style.transform = `rotate(${angle - 90}deg)`;\r\n this.handOfAClock.style.width = size + \"px\";\r\n }\r\n\r\n toggleToHours() {\r\n this.minutesFace.onLeave();\r\n this.toggleTime(this.hoursFace);\r\n }\r\n\r\n toggleToMinutes() {\r\n this.hoursFace.onLeave();\r\n this.toggleTime(this.minutesFace);\r\n }\r\n\r\n toggleTime(face) {\r\n if (this.currentFace !== face) {\r\n this.onEachClockElement(c => c.classList.add(css.fadeOut));\r\n this.handOfAClock.classList.add(css.fadeOut);\r\n Promise.delay(() => {\r\n this.onEachClockElement(c => c.classList.remove(css.fadeOut));\r\n this.handOfAClock.classList.remove(css.fadeOut);\r\n this.changeDisplayed(face.displayed);\r\n this.currentFace = face;\r\n this.onEachClockElement(c => this.removeSelected(c));\r\n face.onEnter();\r\n }, 300);\r\n }\r\n }\r\n\r\n removeSelected(c) {\r\n c.classList.remove(css.selected);\r\n c.style.background = \"transparent\";\r\n c.style.color = this.options.clockItemColor;\r\n }\r\n}","import ClockHeader from \"./clockHeader\";\r\nimport ClockFace from \"./face/clockFace\";\r\nimport Config, {DOM} from \"./meta/config\";\r\nimport formatTime from \"./timeFormatter\";\r\n\r\nexport default class Clock {\r\n\r\n constructor(options, time) {\r\n this.options = options;\r\n\r\n this.initView();\r\n this.time = time;\r\n this.initElements();\r\n }\r\n\r\n initView() {\r\n this.submitButton = document.getElementById(DOM.submitId);\r\n this.submitButton.onclick = () => {\r\n const time = this.time;\r\n time.formatted = () => formatTime(time);\r\n this.options.onSubmit(time);\r\n Clock.dispose();\r\n };\r\n\r\n this.cancelButton = document.getElementById(DOM.cancelId);\r\n this.cancelButton.onclick = () => {\r\n this.options.onCancel();\r\n Clock.dispose();\r\n };\r\n }\r\n\r\n initElements() {\r\n this.header = new ClockHeader({\r\n options: this.options,\r\n time: this.time,\r\n onHourClicked: () => this.toggleToHours(),\r\n onMinutesClicked: () => this.toggleToMinutes()\r\n });\r\n this.clockFace = new ClockFace(this.options, this.time, (time, type) => this.onTimeUpdate(time, type));\r\n }\r\n\r\n onStart() {\r\n this.clockFace.onStart();\r\n }\r\n\r\n toggleToHours() {\r\n this.clockFace.toggleToHours();\r\n }\r\n\r\n toggleToMinutes() {\r\n this.clockFace.toggleToMinutes();\r\n }\r\n\r\n onTimeUpdate(time, type) {\r\n this.time = time;\r\n this.header.time = time;\r\n this.header.updateDisplayedTime();\r\n if (type === Config.FaceType.MINUTES)\r\n this.header.toggleActiveToMinutes();\r\n\r\n }\r\n\r\n static dispose() {\r\n document.body.removeChild(document.getElementById(Config.clockId));\r\n }\r\n}","import formatTime from \"./timeFormatter\";\r\nimport showPicker from \"./timepickerCreator\";\r\n\r\nexport default {\r\n showPicker: (config) => showPicker(config),\r\n format: (time) => formatTime(time)\r\n};\r\n\r\n"],"names":["extractTime","date","Date","fromDate","hoursRegex","test","hours","minutesRegex","minutes","parseInt","regex","fromRegex","TypeError","JSON","stringify","parsed","exec","getHours","getMinutes","delay","t","Promise","resolve","styleColors","options","getElementById","DOM","headerId","style","background","headerBackground","color","headerColor","wrapperId","wrapperBackground","clockId","clockBackground","handId","handColor","dotId","buttonsId","footerBackground","submitId","submitColor","cancelId","cancelColor","css","clockItem","clockItemColor","inner","clockItemInnerColor","outer","changeColor","className","property","items","Array","from","document","getElementsByClassName","showPicker","config","Object","assign","Config","clockConfig","time","getTime","clock","Clock","onStart","createDom","Error","clockDiv","createElement","id","innerHTML","clockHtml","body","appendChild","extractedTime","FaceType","HOURS","MINUTES","ClockHeader","onHourClicked","onMinutesClicked","initView","headerHours","hoursId","onclick","toggleActiveToHours","headerMinutes","minutesId","toggleActiveToMinutes","updateDisplayedTime","toggleActive","this","objectToRemoveClass","objectToAddClass","headerSelected","doUpdateDisplayedTime","node","value","innerText","MinutesFace","initialMinutes","updateMinutes","displayed","type","selected","undefined","findSelected","colorSelected","removeSelected","angle","minute","Math","round","clockItems","outerClockItems","isOuter","classList","add","remove","indexOf","HoursFace","initialHours","updateHours","displayedInner","innerClockElem","display","isInnerClock","hoursIndex","innerClockItems","radius","elem","index","selectedAngle","isInner","fn","then","prototype","toRadians","PI","toDegrees","findMousePosition","event","object","rect","getBoundingClientRect","clientX","left","clientY","top","clockElem","size","middle","face","doCreate","span","item","i","push","width","offsetWidth","height","offsetHeight","x","y","itemsRadius","middleX","middleY","doCalculateSize","fun","angleQuantum","length","Utils","itemWidth","itemHeight","sin","bottom","cos","ClockFace","initialTime","onTimeUpdate","isMouseDown","initViews","initTimeFaces","createFace","hoursFace","currentFace","changeDisplayed","innerId","handOfAClock","onmousedown","_this","onmouseup","toggleToMinutes","e","stopPropagation","onmousemove","selectTime","minutesFace","_this2","onEnter","clockFaceCreator","ClockFaceCreator","create","calculateSize","mouse","atan","array","forEach","call","c","calculateHandOfTheClock","transform","onLeave","toggleTime","onEachClockElement","fadeOut","_this3","initElements","submitButton","formatted","formatTime","onSubmit","dispose","cancelButton","onCancel","header","toggleToHours","clockFace","removeChild"],"mappings":"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"}
--------------------------------------------------------------------------------
/dist/grudus-timepicker.js:
--------------------------------------------------------------------------------
1 | /*! grudus-timepicker | (c) 2017-2017
2 | grudus | Apache-2.0 license (see LICENSE) */
3 | var hoursRegex = /^([0-1]?[0-9]|2[0-3])$/;
4 | var minutesRegex = /^([0-5]?[0-9])$/;
5 | var regex = /^([0-1]?[0-9]|2[0-3]):([0-5][0-9])$/;
6 |
7 | function extractTime(date) {
8 | if (!date) return fromDate(new Date());else if (date instanceof Date) return fromDate(date);else if (hoursRegex.test(date.hours) && minutesRegex.test(date.minutes)) return { hours: parseInt(date.hours), minutes: parseInt(date.minutes) };else if (regex.test(date)) return fromRegex(date);else throw new TypeError("INVALID FORMAT: {" + JSON.stringify(date) + "}.\n Time must be a Date or 'hh:MM' string or object with 'hours' and 'minutes' fields");
9 | }
10 |
11 | function fromRegex(date) {
12 | var parsed = regex.exec(date);
13 | return { hours: parseInt(parsed[1]), minutes: parseInt(parsed[2]) };
14 | }
15 |
16 | function fromDate(date) {
17 | return { hours: date.getHours(), minutes: date.getMinutes() };
18 | }
19 |
20 | var formatTime = function (time) {
21 | var extractedTime = extractTime(time);
22 | return (extractedTime.hours < 10 ? "0" + extractedTime.hours : extractedTime.hours) + ":" + (extractedTime.minutes < 10 ? "0" + extractedTime.minutes : extractedTime.minutes);
23 | };
24 |
25 | var clockHtml = "\n" + " \n" + " \n" + " 21 \n" + " : \n" + " 37 \n" + " \n" + " \n" + "\n" + "\n" + " \n" + " " + "
\n" + "
\n" + "
\n" + "
\n" + " \n" + "\n" + "\n" + " \n" + "\n" + " ";
26 |
27 | var clockId = "grudus-clock";
28 |
29 | var defaultConfig = {
30 | onSubmit: function onSubmit() {},
31 | onCancel: function onCancel() {},
32 | headerBackground: "#1976D2",
33 | headerColor: "#c7d6e1",
34 | headerSelected: "#ffffff",
35 | wrapperBackground: "#f0fff0",
36 | footerBackground: "#f0fff0",
37 | submitColor: "#1976D2",
38 | cancelColor: "#1976D2",
39 | clockBackground: "#CFD8DC",
40 | clockItemColor: "#212121",
41 | clockItemInnerColor: "#212121",
42 | handColor: "#1976D2"
43 | };
44 |
45 | var FaceType = { HOURS: "hours", MINUTES: "minutes" };
46 |
47 | var css = {
48 | clock: "g-clock",
49 | clockItem: "g-clock-item",
50 | inner: "g-clock-inner",
51 | outer: "g-clock-outer",
52 | item: "g-clock-item",
53 | hand: "g-hand-of-a-clock",
54 | fadeOut: "g-fade-out",
55 | selected: "g-selected",
56 | active: "g-active",
57 | submit: "g-submit",
58 | cancel: "g-cancel",
59 | hour: "g-hour",
60 | minute: "g-minute"
61 | };
62 |
63 | var DOM = {
64 | headerId: "g-head",
65 | hoursId: "g-hours",
66 | minutesId: "g-minutes",
67 | clockId: "g-clock",
68 | innerId: "g-clock-inner",
69 | wrapperId: "g-clock-wrapper",
70 | dotId: "g-middle-dot",
71 | handId: "g-hand-of-a-clock",
72 | buttonsId: "g-buttons",
73 | submitId: "g-time-submit",
74 | cancelId: "g-time-cancel"
75 | };
76 |
77 | var Config = { clockId: clockId, clockConfig: defaultConfig, FaceType: FaceType };
78 |
79 | var classCallCheck = function (instance, Constructor) {
80 | if (!(instance instanceof Constructor)) {
81 | throw new TypeError("Cannot call a class as a function");
82 | }
83 | };
84 |
85 | var createClass = function () {
86 | function defineProperties(target, props) {
87 | for (var i = 0; i < props.length; i++) {
88 | var descriptor = props[i];
89 | descriptor.enumerable = descriptor.enumerable || false;
90 | descriptor.configurable = true;
91 | if ("value" in descriptor) descriptor.writable = true;
92 | Object.defineProperty(target, descriptor.key, descriptor);
93 | }
94 | }
95 |
96 | return function (Constructor, protoProps, staticProps) {
97 | if (protoProps) defineProperties(Constructor.prototype, protoProps);
98 | if (staticProps) defineProperties(Constructor, staticProps);
99 | return Constructor;
100 | };
101 | }();
102 |
103 | var ClockHeader = function () {
104 | function ClockHeader(config) {
105 | classCallCheck(this, ClockHeader);
106 |
107 | this.options = config.options;
108 | this.time = config.time;
109 | this.onHourClicked = config.onHourClicked;
110 | this.onMinutesClicked = config.onMinutesClicked;
111 |
112 | this.initView();
113 | }
114 |
115 | createClass(ClockHeader, [{
116 | key: "initView",
117 | value: function initView() {
118 | var _this = this;
119 |
120 | this.headerHours = document.getElementById(DOM.hoursId);
121 | this.headerHours.onclick = function () {
122 | _this.toggleActiveToHours();
123 | _this.onHourClicked();
124 | };
125 |
126 | this.headerMinutes = document.getElementById(DOM.minutesId);
127 | this.headerMinutes.onclick = function () {
128 | _this.toggleActiveToMinutes();
129 | _this.onMinutesClicked();
130 | };
131 |
132 | this.updateDisplayedTime();
133 | this.toggleActiveToHours();
134 | }
135 | }, {
136 | key: "toggleActiveToMinutes",
137 | value: function toggleActiveToMinutes() {
138 | this.toggleActive(this.headerHours, this.headerMinutes);
139 | }
140 | }, {
141 | key: "toggleActiveToHours",
142 | value: function toggleActiveToHours() {
143 | this.toggleActive(this.headerMinutes, this.headerHours);
144 | }
145 | }, {
146 | key: "toggleActive",
147 | value: function toggleActive(objectToRemoveClass, objectToAddClass) {
148 | objectToRemoveClass.style.color = this.options.headerColor;
149 | objectToAddClass.style.color = this.options.headerSelected;
150 | }
151 | }, {
152 | key: "updateDisplayedTime",
153 | value: function updateDisplayedTime() {
154 | ClockHeader.doUpdateDisplayedTime(this.headerHours, this.time.hours);
155 | ClockHeader.doUpdateDisplayedTime(this.headerMinutes, this.time.minutes);
156 | }
157 | }], [{
158 | key: "doUpdateDisplayedTime",
159 | value: function doUpdateDisplayedTime(node, value) {
160 | if (value < 10) node.innerText = "0" + value;else node.innerText = value;
161 | }
162 | }]);
163 | return ClockHeader;
164 | }();
165 |
166 | var MinutesFace = function () {
167 | function MinutesFace(items, initialMinutes, updateMinutes) {
168 | classCallCheck(this, MinutesFace);
169 |
170 | this.displayed = ["00", "05", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55"];
171 | this.options = items.options;
172 | this.type = Config.FaceType.MINUTES;
173 | this.selected = undefined;
174 | this.items = items;
175 | this.minutes = initialMinutes;
176 | this.updateMinutes = updateMinutes;
177 | }
178 |
179 | createClass(MinutesFace, [{
180 | key: "onEnter",
181 | value: function onEnter() {
182 | this.selected = this.findSelected(this.minutes);
183 | this.colorSelected();
184 | this.updateMinutes(this.minutes, this.minutes * 6);
185 | }
186 | }, {
187 | key: "onLeave",
188 | value: function onLeave() {
189 | if (this.selected) {
190 | this.removeSelected();
191 | this.selected = undefined;
192 | }
193 | }
194 | }, {
195 | key: "selectTime",
196 | value: function selectTime(angle) {
197 | if (this.selected) this.removeSelected();
198 |
199 | var minute = Math.round(angle / 6) % 60;
200 | this.selected = this.findSelected(minute);
201 | this.colorSelected();
202 | this.minutes = minute;
203 | this.updateMinutes(this.minutes, angle);
204 | }
205 | }, {
206 | key: "findSelected",
207 | value: function findSelected(minute) {
208 | return minute % 5 === 0 ? this.items.clockItems[minute / 5] : this.items.outerClockItems[minute];
209 | }
210 | }, {
211 | key: "colorSelected",
212 | value: function colorSelected() {
213 | if (this.isOuter()) {
214 | this.selected.classList.add(css.selected);
215 | return;
216 | }
217 | this.selected.style.background = this.options.handColor;
218 | this.selected.style.color = "whitesmoke";
219 | }
220 | }, {
221 | key: "removeSelected",
222 | value: function removeSelected() {
223 | if (this.isOuter()) {
224 | this.selected.classList.remove(css.selected);
225 | return;
226 | }
227 | this.selected.style.background = "transparent";
228 | this.selected.style.color = this.options.clockItemColor;
229 | }
230 | }, {
231 | key: "isOuter",
232 | value: function isOuter() {
233 | return this.items.outerClockItems.indexOf(this.selected) > -1;
234 | }
235 | }]);
236 | return MinutesFace;
237 | }();
238 |
239 | var HoursFace = function () {
240 | function HoursFace(items, initialHours, updateHours) {
241 | classCallCheck(this, HoursFace);
242 |
243 | this.displayed = ["12", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"];
244 | this.displayedInner = ["00", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"];
245 | this.type = Config.FaceType.MINUTES;
246 | this.selected = undefined;
247 | this.options = items.options;
248 |
249 | this.items = items;
250 | this.hours = initialHours;
251 | this.updateHours = updateHours;
252 | }
253 |
254 | createClass(HoursFace, [{
255 | key: "onEnter",
256 | value: function onEnter() {
257 | this.items.innerClockElem.style.display = "block";
258 | var isInnerClock = this.hours < 13 && this.hours !== 0;
259 | var hoursIndex = this.hours % 12;
260 | this.selected = isInnerClock ? this.items.clockItems[hoursIndex] : this.items.innerClockItems[hoursIndex];
261 | this.colorSelected();
262 |
263 | this.updateHours(this.hours, hoursIndex * 30, isInnerClock ? this.items.radius : this.items.radius - 50);
264 | }
265 | }, {
266 | key: "onLeave",
267 | value: function onLeave() {
268 | this.items.innerClockElem.style.display = "none";
269 | if (this.selected) {
270 | this.removeSelected();
271 | this.selected = undefined;
272 | }
273 | }
274 | }, {
275 | key: "selectTime",
276 | value: function selectTime(angle, elem) {
277 | if (this.selected) this.removeSelected();
278 |
279 | var index = Math.round(angle / 30) % 12;
280 | this.selected = (elem === this.items.innerClockElem ? this.items.innerClockItems : this.items.clockItems)[index];
281 |
282 | this.colorSelected();
283 | this.hours = parseInt(this.selected.innerText);
284 | var selectedAngle = Math.round(angle / 30) * 30;
285 |
286 | this.updateHours(this.hours, selectedAngle, elem === this.items.innerClockElem ? this.items.radius - 50 : this.items.radius);
287 | }
288 | }, {
289 | key: "colorSelected",
290 | value: function colorSelected() {
291 | this.selected.style.background = this.options.handColor;
292 | this.selected.style.color = "#ffffff";
293 | }
294 | }, {
295 | key: "removeSelected",
296 | value: function removeSelected() {
297 | this.selected.style.background = "transparent";
298 | this.selected.style.color = this.isInner() ? this.options.clockItemInnerColor : this.options.clockItemColor;
299 | }
300 | }, {
301 | key: "isInner",
302 | value: function isInner() {
303 | return Array.from(this.items.innerClockItems).indexOf(this.selected) > -1;
304 | }
305 | }]);
306 | return HoursFace;
307 | }();
308 |
309 | function toRadians(angle) {
310 | return angle * (Math.PI / 180);
311 | }
312 |
313 | function toDegrees(angle) {
314 | return angle * (180 / Math.PI);
315 | }
316 |
317 | function findMousePosition(event, object) {
318 | var rect = object.getBoundingClientRect();
319 | return {
320 | x: event.clientX - rect.left,
321 | y: event.clientY - rect.top
322 | };
323 | }
324 |
325 | function delay(t) {
326 | return new Promise(function (resolve) {
327 | setTimeout(resolve, t);
328 | });
329 | }
330 |
331 | Promise.delay = function (fn, t) {
332 | if (!t) {
333 | t = fn;
334 | fn = function fn() {};
335 | }
336 | return delay(t).then(fn);
337 | };
338 |
339 | Promise.prototype.delay = function (fn, t) {
340 | return this.then(function () {
341 | return Promise.delay(fn, t);
342 | });
343 | };
344 |
345 | var Utils = { toRadians: toRadians, toDegrees: toDegrees, findMousePosition: findMousePosition };
346 |
347 | var ClockFaceCreator = function () {
348 | function ClockFaceCreator(clockElem, innerClockElem) {
349 | classCallCheck(this, ClockFaceCreator);
350 |
351 | this.clockElem = clockElem;
352 | this.innerClockElem = innerClockElem;
353 | this.size = {};
354 | this.middle = {};
355 | }
356 |
357 | createClass(ClockFaceCreator, [{
358 | key: "create",
359 | value: function create(clockItems, innerClockItems, outerClockItems, face) {
360 | ClockFaceCreator.doCreate(clockItems, this.clockElem, function (span) {
361 | return span.classList.add(css.item);
362 | });
363 | ClockFaceCreator.doCreate(innerClockItems, this.innerClockElem, function (span, i) {
364 | span.classList.add(css.item, css.inner);
365 | span.innerText = face.displayedInner[i];
366 | });
367 |
368 | for (var i = 0; i < 60; i++) {
369 | var span = document.createElement("span");
370 | span.classList.add(css.outer);
371 | outerClockItems.push(span);
372 | this.clockElem.appendChild(span);
373 | }
374 | }
375 | }, {
376 | key: "calculateSize",
377 | value: function calculateSize(clockItems, innerClockItems, outerClockItems) {
378 | this.size.width = this.clockElem.offsetWidth;
379 | this.size.height = this.clockElem.offsetHeight;
380 | this.middle.x = this.size.width / 2;
381 | this.middle.y = this.size.height / 2;
382 | this.itemsRadius = this.size.width / 2 - 20;
383 |
384 | var innerWidth = this.innerClockElem.offsetWidth;
385 | var innerHeight = this.innerClockElem.offsetHeight;
386 | var middleX = innerWidth / 2;
387 | var middleY = innerHeight / 2;
388 |
389 | ClockFaceCreator.doCalculateSize(this.middle.x, this.middle.y, this.itemsRadius, clockItems);
390 | ClockFaceCreator.doCalculateSize(middleX, middleY, this.itemsRadius - 40, innerClockItems);
391 | ClockFaceCreator.doCalculateSize(this.middle.x, this.middle.y, this.itemsRadius, outerClockItems);
392 | }
393 | }], [{
394 | key: "doCreate",
395 | value: function doCreate(clockItems, clockElem, fun) {
396 | for (var i = 0; i < 12; i++) {
397 | var span = document.createElement("span");
398 | fun(span, i);
399 | clockItems.push(span);
400 | clockElem.appendChild(span);
401 | }
402 | }
403 | }, {
404 | key: "doCalculateSize",
405 | value: function doCalculateSize(middleX, middleY, radius, items) {
406 | var angleQuantum = 360 / items.length;
407 | for (var i = 0; i < items.length; i++) {
408 |
409 | var angle = Utils.toRadians(i * angleQuantum);
410 | var item = items[i];
411 | var itemWidth = item.offsetWidth;
412 | var itemHeight = item.offsetHeight;
413 |
414 | item.style.left = middleX + Math.sin(angle) * radius - itemWidth / 2 + "px";
415 | item.style.bottom = middleY + Math.cos(angle) * radius - itemHeight / 2 + "px";
416 | }
417 | }
418 | }]);
419 | return ClockFaceCreator;
420 | }();
421 |
422 | var ClockFace = function () {
423 | function ClockFace(options, initialTime, onTimeUpdate) {
424 | classCallCheck(this, ClockFace);
425 |
426 | this.options = options;
427 | this.time = initialTime;
428 | this.onTimeUpdate = onTimeUpdate;
429 | this.isMouseDown = false;
430 | this.clockItems = [];
431 | this.innerClockItems = [];
432 | this.outerClockItems = [];
433 | this.size = {};
434 | this.middle = {};
435 |
436 | this.initViews();
437 | this.initTimeFaces(initialTime);
438 | this.createFace();
439 |
440 | this.hoursFace.items.radius = this.itemsRadius;
441 |
442 | this.currentFace = this.hoursFace;
443 | this.changeDisplayed(this.currentFace.displayed);
444 | }
445 |
446 | createClass(ClockFace, [{
447 | key: "initViews",
448 | value: function initViews() {
449 | var _this = this;
450 |
451 | this.clockElem = document.getElementById(DOM.clockId);
452 | this.innerClockElem = document.getElementById(DOM.innerId);
453 | this.handOfAClock = document.getElementById(DOM.handId);
454 |
455 | this.clockElem.onmousedown = function () {
456 | return _this.isMouseDown = true;
457 | };
458 | this.clockElem.onmouseup = function () {
459 | _this.isMouseDown = false;
460 | _this.toggleToMinutes();
461 | };
462 |
463 | this.handOfAClock.onmouseup = function (e) {
464 | return e.stopPropagation();
465 | };
466 | this.handOfAClock.onmousemove = function (e) {
467 | return e.stopPropagation();
468 | };
469 | this.handOfAClock.onclick = function (e) {
470 | return e.stopPropagation();
471 | };
472 |
473 | this.clockElem.onmousemove = function (e) {
474 | return _this.selectTime(e, false, _this.clockElem);
475 | };
476 | this.clockElem.onclick = function (e) {
477 | return _this.selectTime(e, true, _this.clockElem);
478 | };
479 |
480 | this.innerClockElem.onmousemove = function (e) {
481 | return _this.selectTime(e, false, _this.innerClockElem);
482 | };
483 | this.innerClockElem.onclick = function (e) {
484 | return _this.selectTime(e, true, _this.innerClockElem);
485 | };
486 | }
487 | }, {
488 | key: "initTimeFaces",
489 | value: function initTimeFaces(initialTime) {
490 | var _this2 = this;
491 |
492 | this.minutesFace = new MinutesFace({
493 | options: this.options,
494 | clockItems: this.clockItems,
495 | outerClockItems: this.outerClockItems
496 | }, initialTime.minutes, function (minutes, angle) {
497 | return _this2.updateMinutes(minutes, angle);
498 | });
499 |
500 | this.hoursFace = new HoursFace({
501 | options: this.options,
502 | innerClockItems: this.innerClockItems,
503 | clockItems: this.clockItems,
504 | innerClockElem: this.innerClockElem
505 | }, initialTime.hours, function (hours, angle, radius) {
506 | return _this2.updateHours(hours, angle, radius);
507 | });
508 | }
509 | }, {
510 | key: "onStart",
511 | value: function onStart() {
512 | this.currentFace.onEnter();
513 | }
514 | }, {
515 | key: "createFace",
516 | value: function createFace() {
517 | var clockFaceCreator = new ClockFaceCreator(this.clockElem, this.innerClockElem);
518 | clockFaceCreator.create(this.clockItems, this.innerClockItems, this.outerClockItems, this.hoursFace);
519 | clockFaceCreator.calculateSize(this.clockItems, this.innerClockItems, this.outerClockItems);
520 |
521 | this.size = clockFaceCreator.size;
522 | this.middle = clockFaceCreator.middle;
523 | this.itemsRadius = clockFaceCreator.itemsRadius;
524 | }
525 | }, {
526 | key: "selectTime",
527 | value: function selectTime(event, isMouseDown, elem) {
528 | if (!(isMouseDown || this.isMouseDown)) return;
529 | var mouse = Utils.findMousePosition(event, this.clockElem);
530 | var x = mouse.x - this.middle.x;
531 | var y = this.middle.y - mouse.y;
532 | var angle = 90 - Utils.toDegrees(Math.atan(y / x));
533 | if (x < 0) angle += 180;
534 |
535 | this.currentFace.selectTime(angle, elem);
536 | event.stopPropagation();
537 | }
538 | }, {
539 | key: "changeDisplayed",
540 | value: function changeDisplayed(array) {
541 | for (var i = 0; i < this.clockItems.length; i++) {
542 | this.clockItems[i].innerText = array[i];
543 | }
544 | }
545 | }, {
546 | key: "onEachClockElement",
547 | value: function onEachClockElement(fun) {
548 | [].forEach.call(this.clockItems, function (c) {
549 | return fun(c);
550 | });
551 | }
552 | }, {
553 | key: "updateMinutes",
554 | value: function updateMinutes(minutes, angle) {
555 | this.time.minutes = minutes;
556 | this.calculateHandOfTheClock(angle, this.itemsRadius);
557 | this.onTimeUpdate(this.time, Config.FaceType.MINUTES);
558 | }
559 | }, {
560 | key: "updateHours",
561 | value: function updateHours(hours, angle, radius) {
562 | this.time.hours = hours;
563 | this.calculateHandOfTheClock(angle, radius);
564 | this.onTimeUpdate(this.time, Config.FaceType.HOURS);
565 | }
566 | }, {
567 | key: "calculateHandOfTheClock",
568 | value: function calculateHandOfTheClock(angle) {
569 | var size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.itemsRadius;
570 |
571 | this.handOfAClock.style.transform = "rotate(" + (angle - 90) + "deg)";
572 | this.handOfAClock.style.width = size + "px";
573 | }
574 | }, {
575 | key: "toggleToHours",
576 | value: function toggleToHours() {
577 | this.minutesFace.onLeave();
578 | this.toggleTime(this.hoursFace);
579 | }
580 | }, {
581 | key: "toggleToMinutes",
582 | value: function toggleToMinutes() {
583 | this.hoursFace.onLeave();
584 | this.toggleTime(this.minutesFace);
585 | }
586 | }, {
587 | key: "toggleTime",
588 | value: function toggleTime(face) {
589 | var _this3 = this;
590 |
591 | if (this.currentFace !== face) {
592 | this.onEachClockElement(function (c) {
593 | return c.classList.add(css.fadeOut);
594 | });
595 | this.handOfAClock.classList.add(css.fadeOut);
596 | Promise.delay(function () {
597 | _this3.onEachClockElement(function (c) {
598 | return c.classList.remove(css.fadeOut);
599 | });
600 | _this3.handOfAClock.classList.remove(css.fadeOut);
601 | _this3.changeDisplayed(face.displayed);
602 | _this3.currentFace = face;
603 | _this3.onEachClockElement(function (c) {
604 | return _this3.removeSelected(c);
605 | });
606 | face.onEnter();
607 | }, 300);
608 | }
609 | }
610 | }, {
611 | key: "removeSelected",
612 | value: function removeSelected(c) {
613 | c.classList.remove(css.selected);
614 | c.style.background = "transparent";
615 | c.style.color = this.options.clockItemColor;
616 | }
617 | }]);
618 | return ClockFace;
619 | }();
620 |
621 | var Clock = function () {
622 | function Clock(options, time) {
623 | classCallCheck(this, Clock);
624 |
625 | this.options = options;
626 |
627 | this.initView();
628 | this.time = time;
629 | this.initElements();
630 | }
631 |
632 | createClass(Clock, [{
633 | key: "initView",
634 | value: function initView() {
635 | var _this = this;
636 |
637 | this.submitButton = document.getElementById(DOM.submitId);
638 | this.submitButton.onclick = function () {
639 | var time = _this.time;
640 | time.formatted = function () {
641 | return formatTime(time);
642 | };
643 | _this.options.onSubmit(time);
644 | Clock.dispose();
645 | };
646 |
647 | this.cancelButton = document.getElementById(DOM.cancelId);
648 | this.cancelButton.onclick = function () {
649 | _this.options.onCancel();
650 | Clock.dispose();
651 | };
652 | }
653 | }, {
654 | key: "initElements",
655 | value: function initElements() {
656 | var _this2 = this;
657 |
658 | this.header = new ClockHeader({
659 | options: this.options,
660 | time: this.time,
661 | onHourClicked: function onHourClicked() {
662 | return _this2.toggleToHours();
663 | },
664 | onMinutesClicked: function onMinutesClicked() {
665 | return _this2.toggleToMinutes();
666 | }
667 | });
668 | this.clockFace = new ClockFace(this.options, this.time, function (time, type) {
669 | return _this2.onTimeUpdate(time, type);
670 | });
671 | }
672 | }, {
673 | key: "onStart",
674 | value: function onStart() {
675 | this.clockFace.onStart();
676 | }
677 | }, {
678 | key: "toggleToHours",
679 | value: function toggleToHours() {
680 | this.clockFace.toggleToHours();
681 | }
682 | }, {
683 | key: "toggleToMinutes",
684 | value: function toggleToMinutes() {
685 | this.clockFace.toggleToMinutes();
686 | }
687 | }, {
688 | key: "onTimeUpdate",
689 | value: function onTimeUpdate(time, type) {
690 | this.time = time;
691 | this.header.time = time;
692 | this.header.updateDisplayedTime();
693 | if (type === Config.FaceType.MINUTES) this.header.toggleActiveToMinutes();
694 | }
695 | }], [{
696 | key: "dispose",
697 | value: function dispose() {
698 | document.body.removeChild(document.getElementById(Config.clockId));
699 | }
700 | }]);
701 | return Clock;
702 | }();
703 |
704 | function styleColors(options) {
705 | document.getElementById(DOM.headerId).style.background = options.headerBackground;
706 | document.getElementById(DOM.headerId).style.color = options.headerColor;
707 | document.getElementById(DOM.wrapperId).style.background = options.wrapperBackground;
708 | document.getElementById(DOM.clockId).style.background = options.clockBackground;
709 | document.getElementById(DOM.handId).style.background = options.handColor;
710 | document.getElementById(DOM.dotId).style.background = options.handColor;
711 | document.getElementById(DOM.buttonsId).style.background = options.footerBackground;
712 | document.getElementById(DOM.submitId).style.color = options.submitColor;
713 | document.getElementById(DOM.cancelId).style.color = options.cancelColor;
714 |
715 | changeColor(css.clockItem, options.clockItemColor);
716 | changeColor(css.inner, options.clockItemInnerColor);
717 | changeColor(css.outer, options.handColor, "borderColor");
718 | }
719 |
720 | function changeColor(className, color) {
721 | var property = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "color";
722 |
723 | var items = Array.from(document.getElementsByClassName(className));
724 | var _iteratorNormalCompletion = true;
725 | var _didIteratorError = false;
726 | var _iteratorError = undefined;
727 |
728 | try {
729 | for (var _iterator = items[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
730 | var item = _step.value;
731 |
732 | item.style[property] = color;
733 | }
734 | } catch (err) {
735 | _didIteratorError = true;
736 | _iteratorError = err;
737 | } finally {
738 | try {
739 | if (!_iteratorNormalCompletion && _iterator.return) {
740 | _iterator.return();
741 | }
742 | } finally {
743 | if (_didIteratorError) {
744 | throw _iteratorError;
745 | }
746 | }
747 | }
748 | }
749 |
750 | function showPicker() {
751 | var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
752 |
753 | createDom();
754 |
755 | var options = Object.assign({}, Config.clockConfig, config);
756 | var time = extractTime(options.time);
757 |
758 | var clock = new Clock(options, time);
759 | styleColors(options);
760 | clock.onStart();
761 | }
762 |
763 | function createDom() {
764 | if (document.getElementById(Config.clockId)) throw Error("There is already one running grudus-timepicker instance!");
765 |
766 | var clockDiv = document.createElement("div");
767 | clockDiv.id = Config.clockId;
768 | clockDiv.innerHTML = clockHtml;
769 | document.body.appendChild(clockDiv);
770 | }
771 |
772 | var index = {
773 | showPicker: function showPicker$$1(config) {
774 | return showPicker(config);
775 | },
776 | format: function format(time) {
777 | return formatTime(time);
778 | }
779 | };
780 |
781 | export default index;
782 | //# sourceMappingURL=grudus-timepicker.js.map
783 |
--------------------------------------------------------------------------------
/dist/grudus-timepicker.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"grudus-timepicker.js","sources":["../src/js/timeExtractor.js","../src/js/timeFormatter.js","../src/js/meta/clockHtml.js","../src/js/meta/config.js","../src/js/clockHeader.js","../src/js/face/minutesFace.js","../src/js/face/hoursFace.js","../src/js/meta/utils.js","../src/js/face/clockFaceCreator.js","../src/js/face/clockFace.js","../src/js/clock.js","../src/js/colorStylists.js","../src/js/timepickerCreator.js","../src/js/index.js"],"sourcesContent":["const hoursRegex = /^([0-1]?[0-9]|2[0-3])$/;\r\nconst minutesRegex = /^([0-5]?[0-9])$/;\r\nconst regex = /^([0-1]?[0-9]|2[0-3]):([0-5][0-9])$/;\r\n\r\nexport default function extractTime(date) {\r\n if (!date)\r\n return fromDate(new Date());\r\n else if (date instanceof Date)\r\n return fromDate(date);\r\n else if (hoursRegex.test(date.hours) && minutesRegex.test(date.minutes))\r\n return {hours: parseInt(date.hours), minutes: parseInt(date.minutes)};\r\n else if (regex.test(date))\r\n return fromRegex(date);\r\n else\r\n throw new TypeError(`INVALID FORMAT: {${JSON.stringify(date)}}.\r\n Time must be a Date or 'hh:MM' string or object with 'hours' and 'minutes' fields`);\r\n}\r\n\r\nfunction fromRegex(date) {\r\n const parsed = regex.exec(date);\r\n return {hours: parseInt(parsed[1]), minutes: parseInt(parsed[2])};\r\n}\r\n\r\nfunction fromDate(date) {\r\n return {hours: date.getHours(), minutes: date.getMinutes()};\r\n}","import extractTime from \"./timeExtractor\";\r\n\r\nexport default function (time) {\r\n const extractedTime = extractTime(time);\r\n return (extractedTime.hours < 10 ? \"0\" + extractedTime.hours : extractedTime.hours)\r\n + \":\" + (extractedTime.minutes < 10 ? \"0\" + extractedTime.minutes : extractedTime.minutes);\r\n}","export default \"\\n\" +\r\n\" \\n\" +\r\n\" \\n\" +\r\n\" 21 \\n\" +\r\n\" : \\n\" +\r\n\" 37 \\n\" +\r\n\" \\n\" +\r\n\" \\n\" +\r\n\"\\n\" +\r\n\"\\n\" +\r\n\" \\n\" +\r\n\" \" +\r\n\"
\\n\" +\r\n\"
\\n\" +\r\n\"
\\n\" +\r\n\"
\\n\" +\r\n\" \\n\" +\r\n\"\\n\" +\r\n\"\\n\" +\r\n\" \\n\" +\r\n\"\\n\" +\r\n\" \";","const clockId = \"grudus-clock\";\r\n\r\nconst defaultConfig = {\r\n onSubmit: () => {\r\n },\r\n onCancel: () => {\r\n },\r\n headerBackground: \"#1976D2\",\r\n headerColor: \"#c7d6e1\",\r\n headerSelected: \"#ffffff\",\r\n wrapperBackground: \"#f0fff0\",\r\n footerBackground: \"#f0fff0\",\r\n submitColor: \"#1976D2\",\r\n cancelColor: \"#1976D2\",\r\n clockBackground: \"#CFD8DC\",\r\n clockItemColor: \"#212121\",\r\n clockItemInnerColor: \"#212121\",\r\n handColor: \"#1976D2\"\r\n};\r\n\r\nconst FaceType = {HOURS: \"hours\", MINUTES: \"minutes\"};\r\n\r\nconst css = {\r\n clock: \"g-clock\",\r\n clockItem: \"g-clock-item\",\r\n inner: \"g-clock-inner\",\r\n outer: \"g-clock-outer\",\r\n item: \"g-clock-item\",\r\n hand: \"g-hand-of-a-clock\",\r\n fadeOut: \"g-fade-out\",\r\n selected: \"g-selected\",\r\n active: \"g-active\",\r\n submit: \"g-submit\",\r\n cancel: \"g-cancel\",\r\n hour: \"g-hour\",\r\n minute: \"g-minute\"\r\n};\r\n\r\nconst DOM = {\r\n headerId: \"g-head\",\r\n hoursId: \"g-hours\",\r\n minutesId: \"g-minutes\",\r\n clockId: \"g-clock\",\r\n innerId: \"g-clock-inner\",\r\n wrapperId: \"g-clock-wrapper\",\r\n dotId: \"g-middle-dot\",\r\n handId: \"g-hand-of-a-clock\",\r\n buttonsId: \"g-buttons\",\r\n submitId: \"g-time-submit\",\r\n cancelId: \"g-time-cancel\"\r\n};\r\n\r\nexport default {clockId, clockConfig: defaultConfig, FaceType};\r\nexport {css, DOM};","import {DOM} from \"./meta/config\";\r\n\r\nexport default class ClockHeader {\r\n\r\n constructor(config) {\r\n this.options = config.options;\r\n this.time = config.time;\r\n this.onHourClicked = config.onHourClicked;\r\n this.onMinutesClicked = config.onMinutesClicked;\r\n\r\n this.initView();\r\n }\r\n\r\n initView() {\r\n this.headerHours = document.getElementById(DOM.hoursId);\r\n this.headerHours.onclick = () => {\r\n this.toggleActiveToHours();\r\n this.onHourClicked();\r\n };\r\n\r\n this.headerMinutes = document.getElementById(DOM.minutesId);\r\n this.headerMinutes.onclick = () => {\r\n this.toggleActiveToMinutes();\r\n this.onMinutesClicked();\r\n };\r\n\r\n this.updateDisplayedTime();\r\n this.toggleActiveToHours();\r\n }\r\n\r\n toggleActiveToMinutes() {\r\n this.toggleActive(this.headerHours, this.headerMinutes);\r\n }\r\n\r\n toggleActiveToHours() {\r\n this.toggleActive(this.headerMinutes, this.headerHours);\r\n }\r\n\r\n toggleActive(objectToRemoveClass, objectToAddClass) {\r\n objectToRemoveClass.style.color = this.options.headerColor;\r\n objectToAddClass.style.color = this.options.headerSelected;\r\n }\r\n\r\n updateDisplayedTime() {\r\n ClockHeader.doUpdateDisplayedTime(this.headerHours, this.time.hours);\r\n ClockHeader.doUpdateDisplayedTime(this.headerMinutes, this.time.minutes);\r\n }\r\n\r\n static doUpdateDisplayedTime(node, value) {\r\n if (value < 10)\r\n node.innerText = \"0\" + value;\r\n else node.innerText = value;\r\n }\r\n}","import Config, {css} from \"../meta/config\";\r\n\r\nexport default class MinutesFace {\r\n\r\n constructor(items, initialMinutes, updateMinutes) {\r\n this.displayed = [\"00\", \"05\", \"10\", \"15\", \"20\", \"25\", \"30\", \"35\", \"40\", \"45\", \"50\", \"55\"];\r\n this.options = items.options;\r\n this.type = Config.FaceType.MINUTES;\r\n this.selected = undefined;\r\n this.items = items;\r\n this.minutes = initialMinutes;\r\n this.updateMinutes = updateMinutes;\r\n }\r\n\r\n onEnter() {\r\n this.selected = this.findSelected(this.minutes);\r\n this.colorSelected();\r\n this.updateMinutes(this.minutes, this.minutes * 6);\r\n }\r\n\r\n onLeave() {\r\n if (this.selected) {\r\n this.removeSelected();\r\n this.selected = undefined;\r\n }\r\n }\r\n\r\n selectTime(angle) {\r\n if (this.selected)\r\n this.removeSelected();\r\n\r\n const minute = Math.round(angle / 6) % 60;\r\n this.selected = this.findSelected(minute);\r\n this.colorSelected();\r\n this.minutes = minute;\r\n this.updateMinutes(this.minutes, angle);\r\n }\r\n\r\n findSelected(minute) {\r\n return (minute % 5 === 0) ? this.items.clockItems[minute / 5] : this.items.outerClockItems[minute];\r\n }\r\n\r\n colorSelected() {\r\n if (this.isOuter()) {\r\n this.selected.classList.add(css.selected);\r\n return;\r\n }\r\n this.selected.style.background = this.options.handColor;\r\n this.selected.style.color = \"whitesmoke\";\r\n }\r\n\r\n removeSelected() {\r\n if (this.isOuter()) {\r\n this.selected.classList.remove(css.selected);\r\n return;\r\n }\r\n this.selected.style.background = \"transparent\";\r\n this.selected.style.color = this.options.clockItemColor;\r\n }\r\n\r\n isOuter() {\r\n return this.items.outerClockItems.indexOf(this.selected) > -1;\r\n }\r\n}","import Config from \"../meta/config\";\r\n\r\nexport default class HoursFace {\r\n\r\n constructor(items, initialHours, updateHours) {\r\n this.displayed = [\"12\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\", \"11\"];\r\n this.displayedInner = [\"00\", \"13\", \"14\", \"15\", \"16\", \"17\", \"18\", \"19\", \"20\", \"21\", \"22\", \"23\"];\r\n this.type = Config.FaceType.MINUTES;\r\n this.selected = undefined;\r\n this.options = items.options;\r\n\r\n this.items = items;\r\n this.hours = initialHours;\r\n this.updateHours = updateHours;\r\n }\r\n\r\n onEnter() {\r\n this.items.innerClockElem.style.display = \"block\";\r\n const isInnerClock = this.hours < 13 && this.hours !== 0;\r\n const hoursIndex = this.hours % 12;\r\n this.selected = isInnerClock ? this.items.clockItems[hoursIndex] : this.items.innerClockItems[hoursIndex];\r\n this.colorSelected();\r\n\r\n this.updateHours(this.hours, hoursIndex * 30, isInnerClock ? this.items.radius : this.items.radius - 50);\r\n }\r\n\r\n onLeave() {\r\n this.items.innerClockElem.style.display = \"none\";\r\n if (this.selected) {\r\n this.removeSelected();\r\n this.selected = undefined;\r\n }\r\n }\r\n\r\n selectTime(angle, elem) {\r\n if (this.selected)\r\n this.removeSelected();\r\n\r\n const index = Math.round(angle / 30) % 12;\r\n this.selected = (elem === this.items.innerClockElem\r\n ? this.items.innerClockItems\r\n : this.items.clockItems)[index];\r\n\r\n this.colorSelected();\r\n this.hours = parseInt(this.selected.innerText);\r\n const selectedAngle = Math.round(angle / 30) * 30;\r\n\r\n this.updateHours(this.hours, selectedAngle,\r\n elem === this.items.innerClockElem ? this.items.radius - 50 : this.items.radius);\r\n }\r\n\r\n colorSelected() {\r\n this.selected.style.background = this.options.handColor;\r\n this.selected.style.color = \"#ffffff\";\r\n }\r\n\r\n removeSelected() {\r\n this.selected.style.background = \"transparent\";\r\n this.selected.style.color = this.isInner()\r\n ? this.options.clockItemInnerColor\r\n : this.options.clockItemColor;\r\n }\r\n\r\n isInner() {\r\n return Array.from(this.items.innerClockItems).indexOf(this.selected) > -1;\r\n }\r\n}","function toRadians(angle) {\r\n return angle * (Math.PI / 180);\r\n}\r\n\r\nfunction toDegrees(angle) {\r\n return angle * (180 / Math.PI);\r\n}\r\n\r\nfunction findMousePosition(event, object) {\r\n const rect = object.getBoundingClientRect();\r\n return {\r\n x: event.clientX - rect.left,\r\n y: event.clientY - rect.top\r\n };\r\n}\r\n\r\nfunction delay(t) {\r\n return new Promise(function (resolve) {\r\n setTimeout(resolve, t);\r\n });\r\n}\r\n\r\nPromise.delay = function (fn, t) {\r\n if (!t) {\r\n t = fn;\r\n fn = function () {\r\n };\r\n }\r\n return delay(t).then(fn);\r\n};\r\n\r\nPromise.prototype.delay = function (fn, t) {\r\n return this.then(function () {\r\n return Promise.delay(fn, t);\r\n });\r\n};\r\n\r\nexport default {toRadians, toDegrees, findMousePosition};","import Utils from \"../meta/utils\";\r\nimport {css} from \"../meta/config\";\r\n\r\nexport default class ClockFaceCreator {\r\n\r\n constructor(clockElem, innerClockElem) {\r\n this.clockElem = clockElem;\r\n this.innerClockElem = innerClockElem;\r\n this.size = {};\r\n this.middle = {};\r\n }\r\n\r\n create(clockItems, innerClockItems, outerClockItems, face) {\r\n ClockFaceCreator.doCreate(clockItems, this.clockElem, span => span.classList.add(css.item));\r\n ClockFaceCreator.doCreate(innerClockItems, this.innerClockElem, (span, i) => {\r\n span.classList.add(css.item, css.inner);\r\n span.innerText = face.displayedInner[i];\r\n });\r\n\r\n for (let i = 0; i < 60; i++) {\r\n const span = document.createElement(\"span\");\r\n span.classList.add(css.outer);\r\n outerClockItems.push(span);\r\n this.clockElem.appendChild(span);\r\n }\r\n }\r\n\r\n static doCreate(clockItems, clockElem, fun) {\r\n for (let i = 0; i < 12; i++) {\r\n const span = document.createElement(\"span\");\r\n fun(span, i);\r\n clockItems.push(span);\r\n clockElem.appendChild(span);\r\n }\r\n }\r\n\r\n calculateSize(clockItems, innerClockItems, outerClockItems) {\r\n this.size.width = this.clockElem.offsetWidth;\r\n this.size.height = this.clockElem.offsetHeight;\r\n this.middle.x = this.size.width / 2;\r\n this.middle.y = this.size.height / 2;\r\n this.itemsRadius = this.size.width / 2 - 20;\r\n\r\n const innerWidth = this.innerClockElem.offsetWidth;\r\n const innerHeight = this.innerClockElem.offsetHeight;\r\n const middleX = innerWidth / 2;\r\n const middleY = innerHeight / 2;\r\n\r\n ClockFaceCreator.doCalculateSize(this.middle.x, this.middle.y, this.itemsRadius, clockItems);\r\n ClockFaceCreator.doCalculateSize(middleX, middleY, this.itemsRadius - 40, innerClockItems);\r\n ClockFaceCreator.doCalculateSize(this.middle.x, this.middle.y, this.itemsRadius, outerClockItems);\r\n }\r\n\r\n static doCalculateSize(middleX, middleY, radius, items) {\r\n const angleQuantum = 360 / items.length;\r\n for (let i = 0; i < items.length; i++) {\r\n\r\n const angle = Utils.toRadians(i * angleQuantum);\r\n const item = items[i];\r\n const itemWidth = item.offsetWidth;\r\n const itemHeight = item.offsetHeight;\r\n\r\n item.style.left = ((middleX + Math.sin(angle) * radius) - itemWidth / 2) + \"px\";\r\n item.style.bottom = ((middleY + Math.cos(angle) * radius) - itemHeight / 2) + \"px\";\r\n }\r\n }\r\n}","import MinutesFace from \"./minutesFace\";\r\nimport HoursFace from \"./hoursFace\";\r\nimport Utils from \"../meta/utils\";\r\nimport Config, {css, DOM} from \"../meta/config\";\r\nimport ClockFaceCreator from \"./clockFaceCreator\";\r\n\r\nexport default class ClockFace {\r\n\r\n constructor(options, initialTime, onTimeUpdate) {\r\n this.options = options;\r\n this.time = initialTime;\r\n this.onTimeUpdate = onTimeUpdate;\r\n this.isMouseDown = false;\r\n this.clockItems = [];\r\n this.innerClockItems = [];\r\n this.outerClockItems = [];\r\n this.size = {};\r\n this.middle = {};\r\n\r\n this.initViews();\r\n this.initTimeFaces(initialTime);\r\n this.createFace();\r\n\r\n this.hoursFace.items.radius = this.itemsRadius;\r\n\r\n this.currentFace = this.hoursFace;\r\n this.changeDisplayed(this.currentFace.displayed);\r\n }\r\n\r\n initViews() {\r\n this.clockElem = document.getElementById(DOM.clockId);\r\n this.innerClockElem = document.getElementById(DOM.innerId);\r\n this.handOfAClock = document.getElementById(DOM.handId);\r\n\r\n this.clockElem.onmousedown = () => this.isMouseDown = true;\r\n this.clockElem.onmouseup = () => {this.isMouseDown = false;\r\n this.toggleToMinutes();\r\n };\r\n\r\n this.handOfAClock.onmouseup = (e) => e.stopPropagation();\r\n this.handOfAClock.onmousemove = (e) => e.stopPropagation();\r\n this.handOfAClock.onclick = (e) => e.stopPropagation();\r\n\r\n this.clockElem.onmousemove = (e) => this.selectTime(e, false, this.clockElem);\r\n this.clockElem.onclick = (e) => this.selectTime(e, true, this.clockElem);\r\n\r\n this.innerClockElem.onmousemove = (e) => this.selectTime(e, false, this.innerClockElem);\r\n this.innerClockElem.onclick = (e) => this.selectTime(e, true, this.innerClockElem);\r\n }\r\n\r\n initTimeFaces(initialTime) {\r\n this.minutesFace = new MinutesFace({\r\n options: this.options,\r\n clockItems: this.clockItems,\r\n outerClockItems: this.outerClockItems\r\n }, initialTime.minutes, (minutes, angle) => this.updateMinutes(minutes, angle));\r\n\r\n this.hoursFace = new HoursFace({\r\n options: this.options,\r\n innerClockItems: this.innerClockItems,\r\n clockItems: this.clockItems,\r\n innerClockElem: this.innerClockElem\r\n }, initialTime.hours, (hours, angle, radius) => this.updateHours(hours, angle, radius));\r\n }\r\n\r\n onStart() {\r\n this.currentFace.onEnter();\r\n }\r\n\r\n createFace() {\r\n const clockFaceCreator = new ClockFaceCreator(this.clockElem, this.innerClockElem);\r\n clockFaceCreator.create(this.clockItems, this.innerClockItems, this.outerClockItems, this.hoursFace);\r\n clockFaceCreator.calculateSize(this.clockItems, this.innerClockItems, this.outerClockItems);\r\n\r\n this.size = clockFaceCreator.size;\r\n this.middle = clockFaceCreator.middle;\r\n this.itemsRadius = clockFaceCreator.itemsRadius;\r\n }\r\n\r\n selectTime(event, isMouseDown, elem) {\r\n if (!(isMouseDown || this.isMouseDown))\r\n return;\r\n const mouse = Utils.findMousePosition(event, this.clockElem);\r\n const x = mouse.x - this.middle.x;\r\n const y = this.middle.y - mouse.y;\r\n let angle = 90 - Utils.toDegrees(Math.atan(y / x));\r\n if (x < 0) angle += 180;\r\n\r\n this.currentFace.selectTime(angle, elem);\r\n event.stopPropagation();\r\n }\r\n\r\n changeDisplayed(array) {\r\n for (let i = 0; i < this.clockItems.length; i++)\r\n this.clockItems[i].innerText = array[i];\r\n }\r\n\r\n onEachClockElement(fun) {\r\n [].forEach.call(this.clockItems, c => fun(c));\r\n }\r\n\r\n updateMinutes(minutes, angle) {\r\n this.time.minutes = minutes;\r\n this.calculateHandOfTheClock(angle, this.itemsRadius);\r\n this.onTimeUpdate(this.time, Config.FaceType.MINUTES);\r\n }\r\n\r\n updateHours(hours, angle, radius) {\r\n this.time.hours = hours;\r\n this.calculateHandOfTheClock(angle, radius);\r\n this.onTimeUpdate(this.time, Config.FaceType.HOURS);\r\n }\r\n\r\n calculateHandOfTheClock(angle, size = this.itemsRadius) {\r\n this.handOfAClock.style.transform = `rotate(${angle - 90}deg)`;\r\n this.handOfAClock.style.width = size + \"px\";\r\n }\r\n\r\n toggleToHours() {\r\n this.minutesFace.onLeave();\r\n this.toggleTime(this.hoursFace);\r\n }\r\n\r\n toggleToMinutes() {\r\n this.hoursFace.onLeave();\r\n this.toggleTime(this.minutesFace);\r\n }\r\n\r\n toggleTime(face) {\r\n if (this.currentFace !== face) {\r\n this.onEachClockElement(c => c.classList.add(css.fadeOut));\r\n this.handOfAClock.classList.add(css.fadeOut);\r\n Promise.delay(() => {\r\n this.onEachClockElement(c => c.classList.remove(css.fadeOut));\r\n this.handOfAClock.classList.remove(css.fadeOut);\r\n this.changeDisplayed(face.displayed);\r\n this.currentFace = face;\r\n this.onEachClockElement(c => this.removeSelected(c));\r\n face.onEnter();\r\n }, 300);\r\n }\r\n }\r\n\r\n removeSelected(c) {\r\n c.classList.remove(css.selected);\r\n c.style.background = \"transparent\";\r\n c.style.color = this.options.clockItemColor;\r\n }\r\n}","import ClockHeader from \"./clockHeader\";\r\nimport ClockFace from \"./face/clockFace\";\r\nimport Config, {DOM} from \"./meta/config\";\r\nimport formatTime from \"./timeFormatter\";\r\n\r\nexport default class Clock {\r\n\r\n constructor(options, time) {\r\n this.options = options;\r\n\r\n this.initView();\r\n this.time = time;\r\n this.initElements();\r\n }\r\n\r\n initView() {\r\n this.submitButton = document.getElementById(DOM.submitId);\r\n this.submitButton.onclick = () => {\r\n const time = this.time;\r\n time.formatted = () => formatTime(time);\r\n this.options.onSubmit(time);\r\n Clock.dispose();\r\n };\r\n\r\n this.cancelButton = document.getElementById(DOM.cancelId);\r\n this.cancelButton.onclick = () => {\r\n this.options.onCancel();\r\n Clock.dispose();\r\n };\r\n }\r\n\r\n initElements() {\r\n this.header = new ClockHeader({\r\n options: this.options,\r\n time: this.time,\r\n onHourClicked: () => this.toggleToHours(),\r\n onMinutesClicked: () => this.toggleToMinutes()\r\n });\r\n this.clockFace = new ClockFace(this.options, this.time, (time, type) => this.onTimeUpdate(time, type));\r\n }\r\n\r\n onStart() {\r\n this.clockFace.onStart();\r\n }\r\n\r\n toggleToHours() {\r\n this.clockFace.toggleToHours();\r\n }\r\n\r\n toggleToMinutes() {\r\n this.clockFace.toggleToMinutes();\r\n }\r\n\r\n onTimeUpdate(time, type) {\r\n this.time = time;\r\n this.header.time = time;\r\n this.header.updateDisplayedTime();\r\n if (type === Config.FaceType.MINUTES)\r\n this.header.toggleActiveToMinutes();\r\n\r\n }\r\n\r\n static dispose() {\r\n document.body.removeChild(document.getElementById(Config.clockId));\r\n }\r\n}","import {css, DOM} from \"./meta/config\";\r\n\r\nexport default function styleColors(options) {\r\n document.getElementById(DOM.headerId).style.background = options.headerBackground;\r\n document.getElementById(DOM.headerId).style.color = options.headerColor;\r\n document.getElementById(DOM.wrapperId).style.background = options.wrapperBackground;\r\n document.getElementById(DOM.clockId).style.background = options.clockBackground;\r\n document.getElementById(DOM.handId).style.background = options.handColor;\r\n document.getElementById(DOM.dotId).style.background = options.handColor;\r\n document.getElementById(DOM.buttonsId).style.background = options.footerBackground;\r\n document.getElementById(DOM.submitId).style.color = options.submitColor;\r\n document.getElementById(DOM.cancelId).style.color = options.cancelColor;\r\n\r\n changeColor(css.clockItem, options.clockItemColor);\r\n changeColor(css.inner, options.clockItemInnerColor);\r\n changeColor(css.outer, options.handColor, \"borderColor\");\r\n}\r\n\r\nfunction changeColor(className, color, property = \"color\") {\r\n const items = Array.from(document.getElementsByClassName(className));\r\n for (const item of items)\r\n item.style[property] = color;\r\n}\r\n","import clockHtml from \"./meta/clockHtml\";\r\nimport Config from \"./meta/config\";\r\nimport Clock from \"./clock\";\r\nimport styleColors from \"./colorStylists\";\r\nimport getTime from \"./timeExtractor\";\r\n\r\n\r\nexport default function showPicker(config = {}) {\r\n createDom();\r\n\r\n const options = Object.assign({}, Config.clockConfig, config);\r\n const time = getTime(options.time);\r\n\r\n const clock = new Clock(options, time);\r\n styleColors(options);\r\n clock.onStart();\r\n}\r\n\r\n\r\nfunction createDom() {\r\n if (document.getElementById(Config.clockId))\r\n throw Error(\"There is already one running grudus-timepicker instance!\");\r\n\r\n const clockDiv = document.createElement(\"div\");\r\n clockDiv.id = Config.clockId;\r\n clockDiv.innerHTML = clockHtml;\r\n document.body.appendChild(clockDiv);\r\n}\r\n","import formatTime from \"./timeFormatter\";\r\nimport showPicker from \"./timepickerCreator\";\r\n\r\nexport default {\r\n showPicker: (config) => showPicker(config),\r\n format: (time) => formatTime(time)\r\n};\r\n\r\n"],"names":["hoursRegex","minutesRegex","regex","extractTime","date","fromDate","Date","test","hours","minutes","parseInt","fromRegex","TypeError","JSON","stringify","parsed","exec","getHours","getMinutes","time","extractedTime","clockId","defaultConfig","FaceType","HOURS","MINUTES","css","DOM","clockConfig","ClockHeader","config","options","onHourClicked","onMinutesClicked","initView","headerHours","document","getElementById","hoursId","onclick","toggleActiveToHours","headerMinutes","minutesId","toggleActiveToMinutes","updateDisplayedTime","toggleActive","objectToRemoveClass","objectToAddClass","style","color","headerColor","headerSelected","doUpdateDisplayedTime","node","value","innerText","MinutesFace","items","initialMinutes","updateMinutes","displayed","type","Config","selected","undefined","findSelected","colorSelected","removeSelected","angle","minute","Math","round","clockItems","outerClockItems","isOuter","classList","add","background","handColor","remove","clockItemColor","indexOf","HoursFace","initialHours","updateHours","displayedInner","innerClockElem","display","isInnerClock","hoursIndex","innerClockItems","radius","elem","index","selectedAngle","isInner","clockItemInnerColor","Array","from","toRadians","PI","toDegrees","findMousePosition","event","object","rect","getBoundingClientRect","clientX","left","clientY","top","delay","t","Promise","resolve","fn","then","prototype","ClockFaceCreator","clockElem","size","middle","face","doCreate","span","item","i","inner","createElement","outer","push","appendChild","width","offsetWidth","height","offsetHeight","x","y","itemsRadius","innerWidth","innerHeight","middleX","middleY","doCalculateSize","fun","angleQuantum","length","Utils","itemWidth","itemHeight","sin","bottom","cos","ClockFace","initialTime","onTimeUpdate","isMouseDown","initViews","initTimeFaces","createFace","hoursFace","currentFace","changeDisplayed","innerId","handOfAClock","handId","onmousedown","onmouseup","toggleToMinutes","e","stopPropagation","onmousemove","selectTime","minutesFace","onEnter","clockFaceCreator","create","calculateSize","mouse","atan","array","forEach","call","c","calculateHandOfTheClock","transform","onLeave","toggleTime","onEachClockElement","fadeOut","Clock","initElements","submitButton","submitId","formatted","formatTime","onSubmit","dispose","cancelButton","cancelId","onCancel","header","toggleToHours","clockFace","onStart","body","removeChild","styleColors","headerId","headerBackground","wrapperId","wrapperBackground","clockBackground","dotId","buttonsId","footerBackground","submitColor","cancelColor","clockItem","changeColor","className","property","getElementsByClassName","showPicker","Object","assign","getTime","clock","createDom","Error","clockDiv","id","innerHTML","clockHtml"],"mappings":"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"}
--------------------------------------------------------------------------------
/dist/grudus-timepicker.umd.js:
--------------------------------------------------------------------------------
1 | /*! grudus-timepicker | (c) 2017-2017
2 | grudus | Apache-2.0 license (see LICENSE) */
3 | (function (global, factory) {
4 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
5 | typeof define === 'function' && define.amd ? define(factory) :
6 | (global.Timepicker = factory());
7 | }(this, (function () { 'use strict';
8 |
9 | var hoursRegex = /^([0-1]?[0-9]|2[0-3])$/;
10 | var minutesRegex = /^([0-5]?[0-9])$/;
11 | var regex = /^([0-1]?[0-9]|2[0-3]):([0-5][0-9])$/;
12 |
13 | function extractTime(date) {
14 | if (!date) return fromDate(new Date());else if (date instanceof Date) return fromDate(date);else if (hoursRegex.test(date.hours) && minutesRegex.test(date.minutes)) return { hours: parseInt(date.hours), minutes: parseInt(date.minutes) };else if (regex.test(date)) return fromRegex(date);else throw new TypeError("INVALID FORMAT: {" + JSON.stringify(date) + "}.\n Time must be a Date or 'hh:MM' string or object with 'hours' and 'minutes' fields");
15 | }
16 |
17 | function fromRegex(date) {
18 | var parsed = regex.exec(date);
19 | return { hours: parseInt(parsed[1]), minutes: parseInt(parsed[2]) };
20 | }
21 |
22 | function fromDate(date) {
23 | return { hours: date.getHours(), minutes: date.getMinutes() };
24 | }
25 |
26 | var formatTime = function (time) {
27 | var extractedTime = extractTime(time);
28 | return (extractedTime.hours < 10 ? "0" + extractedTime.hours : extractedTime.hours) + ":" + (extractedTime.minutes < 10 ? "0" + extractedTime.minutes : extractedTime.minutes);
29 | };
30 |
31 | var clockHtml = "\n" + " \n" + " \n" + " 21 \n" + " : \n" + " 37 \n" + " \n" + " \n" + "\n" + "\n" + " \n" + " " + "
\n" + "
\n" + "
\n" + "
\n" + " \n" + "\n" + "\n" + " \n" + "\n" + " ";
32 |
33 | var clockId = "grudus-clock";
34 |
35 | var defaultConfig = {
36 | onSubmit: function onSubmit() {},
37 | onCancel: function onCancel() {},
38 | headerBackground: "#1976D2",
39 | headerColor: "#c7d6e1",
40 | headerSelected: "#ffffff",
41 | wrapperBackground: "#f0fff0",
42 | footerBackground: "#f0fff0",
43 | submitColor: "#1976D2",
44 | cancelColor: "#1976D2",
45 | clockBackground: "#CFD8DC",
46 | clockItemColor: "#212121",
47 | clockItemInnerColor: "#212121",
48 | handColor: "#1976D2"
49 | };
50 |
51 | var FaceType = { HOURS: "hours", MINUTES: "minutes" };
52 |
53 | var css = {
54 | clock: "g-clock",
55 | clockItem: "g-clock-item",
56 | inner: "g-clock-inner",
57 | outer: "g-clock-outer",
58 | item: "g-clock-item",
59 | hand: "g-hand-of-a-clock",
60 | fadeOut: "g-fade-out",
61 | selected: "g-selected",
62 | active: "g-active",
63 | submit: "g-submit",
64 | cancel: "g-cancel",
65 | hour: "g-hour",
66 | minute: "g-minute"
67 | };
68 |
69 | var DOM = {
70 | headerId: "g-head",
71 | hoursId: "g-hours",
72 | minutesId: "g-minutes",
73 | clockId: "g-clock",
74 | innerId: "g-clock-inner",
75 | wrapperId: "g-clock-wrapper",
76 | dotId: "g-middle-dot",
77 | handId: "g-hand-of-a-clock",
78 | buttonsId: "g-buttons",
79 | submitId: "g-time-submit",
80 | cancelId: "g-time-cancel"
81 | };
82 |
83 | var Config = { clockId: clockId, clockConfig: defaultConfig, FaceType: FaceType };
84 |
85 | var classCallCheck = function (instance, Constructor) {
86 | if (!(instance instanceof Constructor)) {
87 | throw new TypeError("Cannot call a class as a function");
88 | }
89 | };
90 |
91 | var createClass = function () {
92 | function defineProperties(target, props) {
93 | for (var i = 0; i < props.length; i++) {
94 | var descriptor = props[i];
95 | descriptor.enumerable = descriptor.enumerable || false;
96 | descriptor.configurable = true;
97 | if ("value" in descriptor) descriptor.writable = true;
98 | Object.defineProperty(target, descriptor.key, descriptor);
99 | }
100 | }
101 |
102 | return function (Constructor, protoProps, staticProps) {
103 | if (protoProps) defineProperties(Constructor.prototype, protoProps);
104 | if (staticProps) defineProperties(Constructor, staticProps);
105 | return Constructor;
106 | };
107 | }();
108 |
109 | var ClockHeader = function () {
110 | function ClockHeader(config) {
111 | classCallCheck(this, ClockHeader);
112 |
113 | this.options = config.options;
114 | this.time = config.time;
115 | this.onHourClicked = config.onHourClicked;
116 | this.onMinutesClicked = config.onMinutesClicked;
117 |
118 | this.initView();
119 | }
120 |
121 | createClass(ClockHeader, [{
122 | key: "initView",
123 | value: function initView() {
124 | var _this = this;
125 |
126 | this.headerHours = document.getElementById(DOM.hoursId);
127 | this.headerHours.onclick = function () {
128 | _this.toggleActiveToHours();
129 | _this.onHourClicked();
130 | };
131 |
132 | this.headerMinutes = document.getElementById(DOM.minutesId);
133 | this.headerMinutes.onclick = function () {
134 | _this.toggleActiveToMinutes();
135 | _this.onMinutesClicked();
136 | };
137 |
138 | this.updateDisplayedTime();
139 | this.toggleActiveToHours();
140 | }
141 | }, {
142 | key: "toggleActiveToMinutes",
143 | value: function toggleActiveToMinutes() {
144 | this.toggleActive(this.headerHours, this.headerMinutes);
145 | }
146 | }, {
147 | key: "toggleActiveToHours",
148 | value: function toggleActiveToHours() {
149 | this.toggleActive(this.headerMinutes, this.headerHours);
150 | }
151 | }, {
152 | key: "toggleActive",
153 | value: function toggleActive(objectToRemoveClass, objectToAddClass) {
154 | objectToRemoveClass.style.color = this.options.headerColor;
155 | objectToAddClass.style.color = this.options.headerSelected;
156 | }
157 | }, {
158 | key: "updateDisplayedTime",
159 | value: function updateDisplayedTime() {
160 | ClockHeader.doUpdateDisplayedTime(this.headerHours, this.time.hours);
161 | ClockHeader.doUpdateDisplayedTime(this.headerMinutes, this.time.minutes);
162 | }
163 | }], [{
164 | key: "doUpdateDisplayedTime",
165 | value: function doUpdateDisplayedTime(node, value) {
166 | if (value < 10) node.innerText = "0" + value;else node.innerText = value;
167 | }
168 | }]);
169 | return ClockHeader;
170 | }();
171 |
172 | var MinutesFace = function () {
173 | function MinutesFace(items, initialMinutes, updateMinutes) {
174 | classCallCheck(this, MinutesFace);
175 |
176 | this.displayed = ["00", "05", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55"];
177 | this.options = items.options;
178 | this.type = Config.FaceType.MINUTES;
179 | this.selected = undefined;
180 | this.items = items;
181 | this.minutes = initialMinutes;
182 | this.updateMinutes = updateMinutes;
183 | }
184 |
185 | createClass(MinutesFace, [{
186 | key: "onEnter",
187 | value: function onEnter() {
188 | this.selected = this.findSelected(this.minutes);
189 | this.colorSelected();
190 | this.updateMinutes(this.minutes, this.minutes * 6);
191 | }
192 | }, {
193 | key: "onLeave",
194 | value: function onLeave() {
195 | if (this.selected) {
196 | this.removeSelected();
197 | this.selected = undefined;
198 | }
199 | }
200 | }, {
201 | key: "selectTime",
202 | value: function selectTime(angle) {
203 | if (this.selected) this.removeSelected();
204 |
205 | var minute = Math.round(angle / 6) % 60;
206 | this.selected = this.findSelected(minute);
207 | this.colorSelected();
208 | this.minutes = minute;
209 | this.updateMinutes(this.minutes, angle);
210 | }
211 | }, {
212 | key: "findSelected",
213 | value: function findSelected(minute) {
214 | return minute % 5 === 0 ? this.items.clockItems[minute / 5] : this.items.outerClockItems[minute];
215 | }
216 | }, {
217 | key: "colorSelected",
218 | value: function colorSelected() {
219 | if (this.isOuter()) {
220 | this.selected.classList.add(css.selected);
221 | return;
222 | }
223 | this.selected.style.background = this.options.handColor;
224 | this.selected.style.color = "whitesmoke";
225 | }
226 | }, {
227 | key: "removeSelected",
228 | value: function removeSelected() {
229 | if (this.isOuter()) {
230 | this.selected.classList.remove(css.selected);
231 | return;
232 | }
233 | this.selected.style.background = "transparent";
234 | this.selected.style.color = this.options.clockItemColor;
235 | }
236 | }, {
237 | key: "isOuter",
238 | value: function isOuter() {
239 | return this.items.outerClockItems.indexOf(this.selected) > -1;
240 | }
241 | }]);
242 | return MinutesFace;
243 | }();
244 |
245 | var HoursFace = function () {
246 | function HoursFace(items, initialHours, updateHours) {
247 | classCallCheck(this, HoursFace);
248 |
249 | this.displayed = ["12", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"];
250 | this.displayedInner = ["00", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"];
251 | this.type = Config.FaceType.MINUTES;
252 | this.selected = undefined;
253 | this.options = items.options;
254 |
255 | this.items = items;
256 | this.hours = initialHours;
257 | this.updateHours = updateHours;
258 | }
259 |
260 | createClass(HoursFace, [{
261 | key: "onEnter",
262 | value: function onEnter() {
263 | this.items.innerClockElem.style.display = "block";
264 | var isInnerClock = this.hours < 13 && this.hours !== 0;
265 | var hoursIndex = this.hours % 12;
266 | this.selected = isInnerClock ? this.items.clockItems[hoursIndex] : this.items.innerClockItems[hoursIndex];
267 | this.colorSelected();
268 |
269 | this.updateHours(this.hours, hoursIndex * 30, isInnerClock ? this.items.radius : this.items.radius - 50);
270 | }
271 | }, {
272 | key: "onLeave",
273 | value: function onLeave() {
274 | this.items.innerClockElem.style.display = "none";
275 | if (this.selected) {
276 | this.removeSelected();
277 | this.selected = undefined;
278 | }
279 | }
280 | }, {
281 | key: "selectTime",
282 | value: function selectTime(angle, elem) {
283 | if (this.selected) this.removeSelected();
284 |
285 | var index = Math.round(angle / 30) % 12;
286 | this.selected = (elem === this.items.innerClockElem ? this.items.innerClockItems : this.items.clockItems)[index];
287 |
288 | this.colorSelected();
289 | this.hours = parseInt(this.selected.innerText);
290 | var selectedAngle = Math.round(angle / 30) * 30;
291 |
292 | this.updateHours(this.hours, selectedAngle, elem === this.items.innerClockElem ? this.items.radius - 50 : this.items.radius);
293 | }
294 | }, {
295 | key: "colorSelected",
296 | value: function colorSelected() {
297 | this.selected.style.background = this.options.handColor;
298 | this.selected.style.color = "#ffffff";
299 | }
300 | }, {
301 | key: "removeSelected",
302 | value: function removeSelected() {
303 | this.selected.style.background = "transparent";
304 | this.selected.style.color = this.isInner() ? this.options.clockItemInnerColor : this.options.clockItemColor;
305 | }
306 | }, {
307 | key: "isInner",
308 | value: function isInner() {
309 | return Array.from(this.items.innerClockItems).indexOf(this.selected) > -1;
310 | }
311 | }]);
312 | return HoursFace;
313 | }();
314 |
315 | function toRadians(angle) {
316 | return angle * (Math.PI / 180);
317 | }
318 |
319 | function toDegrees(angle) {
320 | return angle * (180 / Math.PI);
321 | }
322 |
323 | function findMousePosition(event, object) {
324 | var rect = object.getBoundingClientRect();
325 | return {
326 | x: event.clientX - rect.left,
327 | y: event.clientY - rect.top
328 | };
329 | }
330 |
331 | function delay(t) {
332 | return new Promise(function (resolve) {
333 | setTimeout(resolve, t);
334 | });
335 | }
336 |
337 | Promise.delay = function (fn, t) {
338 | if (!t) {
339 | t = fn;
340 | fn = function fn() {};
341 | }
342 | return delay(t).then(fn);
343 | };
344 |
345 | Promise.prototype.delay = function (fn, t) {
346 | return this.then(function () {
347 | return Promise.delay(fn, t);
348 | });
349 | };
350 |
351 | var Utils = { toRadians: toRadians, toDegrees: toDegrees, findMousePosition: findMousePosition };
352 |
353 | var ClockFaceCreator = function () {
354 | function ClockFaceCreator(clockElem, innerClockElem) {
355 | classCallCheck(this, ClockFaceCreator);
356 |
357 | this.clockElem = clockElem;
358 | this.innerClockElem = innerClockElem;
359 | this.size = {};
360 | this.middle = {};
361 | }
362 |
363 | createClass(ClockFaceCreator, [{
364 | key: "create",
365 | value: function create(clockItems, innerClockItems, outerClockItems, face) {
366 | ClockFaceCreator.doCreate(clockItems, this.clockElem, function (span) {
367 | return span.classList.add(css.item);
368 | });
369 | ClockFaceCreator.doCreate(innerClockItems, this.innerClockElem, function (span, i) {
370 | span.classList.add(css.item, css.inner);
371 | span.innerText = face.displayedInner[i];
372 | });
373 |
374 | for (var i = 0; i < 60; i++) {
375 | var span = document.createElement("span");
376 | span.classList.add(css.outer);
377 | outerClockItems.push(span);
378 | this.clockElem.appendChild(span);
379 | }
380 | }
381 | }, {
382 | key: "calculateSize",
383 | value: function calculateSize(clockItems, innerClockItems, outerClockItems) {
384 | this.size.width = this.clockElem.offsetWidth;
385 | this.size.height = this.clockElem.offsetHeight;
386 | this.middle.x = this.size.width / 2;
387 | this.middle.y = this.size.height / 2;
388 | this.itemsRadius = this.size.width / 2 - 20;
389 |
390 | var innerWidth = this.innerClockElem.offsetWidth;
391 | var innerHeight = this.innerClockElem.offsetHeight;
392 | var middleX = innerWidth / 2;
393 | var middleY = innerHeight / 2;
394 |
395 | ClockFaceCreator.doCalculateSize(this.middle.x, this.middle.y, this.itemsRadius, clockItems);
396 | ClockFaceCreator.doCalculateSize(middleX, middleY, this.itemsRadius - 40, innerClockItems);
397 | ClockFaceCreator.doCalculateSize(this.middle.x, this.middle.y, this.itemsRadius, outerClockItems);
398 | }
399 | }], [{
400 | key: "doCreate",
401 | value: function doCreate(clockItems, clockElem, fun) {
402 | for (var i = 0; i < 12; i++) {
403 | var span = document.createElement("span");
404 | fun(span, i);
405 | clockItems.push(span);
406 | clockElem.appendChild(span);
407 | }
408 | }
409 | }, {
410 | key: "doCalculateSize",
411 | value: function doCalculateSize(middleX, middleY, radius, items) {
412 | var angleQuantum = 360 / items.length;
413 | for (var i = 0; i < items.length; i++) {
414 |
415 | var angle = Utils.toRadians(i * angleQuantum);
416 | var item = items[i];
417 | var itemWidth = item.offsetWidth;
418 | var itemHeight = item.offsetHeight;
419 |
420 | item.style.left = middleX + Math.sin(angle) * radius - itemWidth / 2 + "px";
421 | item.style.bottom = middleY + Math.cos(angle) * radius - itemHeight / 2 + "px";
422 | }
423 | }
424 | }]);
425 | return ClockFaceCreator;
426 | }();
427 |
428 | var ClockFace = function () {
429 | function ClockFace(options, initialTime, onTimeUpdate) {
430 | classCallCheck(this, ClockFace);
431 |
432 | this.options = options;
433 | this.time = initialTime;
434 | this.onTimeUpdate = onTimeUpdate;
435 | this.isMouseDown = false;
436 | this.clockItems = [];
437 | this.innerClockItems = [];
438 | this.outerClockItems = [];
439 | this.size = {};
440 | this.middle = {};
441 |
442 | this.initViews();
443 | this.initTimeFaces(initialTime);
444 | this.createFace();
445 |
446 | this.hoursFace.items.radius = this.itemsRadius;
447 |
448 | this.currentFace = this.hoursFace;
449 | this.changeDisplayed(this.currentFace.displayed);
450 | }
451 |
452 | createClass(ClockFace, [{
453 | key: "initViews",
454 | value: function initViews() {
455 | var _this = this;
456 |
457 | this.clockElem = document.getElementById(DOM.clockId);
458 | this.innerClockElem = document.getElementById(DOM.innerId);
459 | this.handOfAClock = document.getElementById(DOM.handId);
460 |
461 | this.clockElem.onmousedown = function () {
462 | return _this.isMouseDown = true;
463 | };
464 | this.clockElem.onmouseup = function () {
465 | _this.isMouseDown = false;
466 | _this.toggleToMinutes();
467 | };
468 |
469 | this.handOfAClock.onmouseup = function (e) {
470 | return e.stopPropagation();
471 | };
472 | this.handOfAClock.onmousemove = function (e) {
473 | return e.stopPropagation();
474 | };
475 | this.handOfAClock.onclick = function (e) {
476 | return e.stopPropagation();
477 | };
478 |
479 | this.clockElem.onmousemove = function (e) {
480 | return _this.selectTime(e, false, _this.clockElem);
481 | };
482 | this.clockElem.onclick = function (e) {
483 | return _this.selectTime(e, true, _this.clockElem);
484 | };
485 |
486 | this.innerClockElem.onmousemove = function (e) {
487 | return _this.selectTime(e, false, _this.innerClockElem);
488 | };
489 | this.innerClockElem.onclick = function (e) {
490 | return _this.selectTime(e, true, _this.innerClockElem);
491 | };
492 | }
493 | }, {
494 | key: "initTimeFaces",
495 | value: function initTimeFaces(initialTime) {
496 | var _this2 = this;
497 |
498 | this.minutesFace = new MinutesFace({
499 | options: this.options,
500 | clockItems: this.clockItems,
501 | outerClockItems: this.outerClockItems
502 | }, initialTime.minutes, function (minutes, angle) {
503 | return _this2.updateMinutes(minutes, angle);
504 | });
505 |
506 | this.hoursFace = new HoursFace({
507 | options: this.options,
508 | innerClockItems: this.innerClockItems,
509 | clockItems: this.clockItems,
510 | innerClockElem: this.innerClockElem
511 | }, initialTime.hours, function (hours, angle, radius) {
512 | return _this2.updateHours(hours, angle, radius);
513 | });
514 | }
515 | }, {
516 | key: "onStart",
517 | value: function onStart() {
518 | this.currentFace.onEnter();
519 | }
520 | }, {
521 | key: "createFace",
522 | value: function createFace() {
523 | var clockFaceCreator = new ClockFaceCreator(this.clockElem, this.innerClockElem);
524 | clockFaceCreator.create(this.clockItems, this.innerClockItems, this.outerClockItems, this.hoursFace);
525 | clockFaceCreator.calculateSize(this.clockItems, this.innerClockItems, this.outerClockItems);
526 |
527 | this.size = clockFaceCreator.size;
528 | this.middle = clockFaceCreator.middle;
529 | this.itemsRadius = clockFaceCreator.itemsRadius;
530 | }
531 | }, {
532 | key: "selectTime",
533 | value: function selectTime(event, isMouseDown, elem) {
534 | if (!(isMouseDown || this.isMouseDown)) return;
535 | var mouse = Utils.findMousePosition(event, this.clockElem);
536 | var x = mouse.x - this.middle.x;
537 | var y = this.middle.y - mouse.y;
538 | var angle = 90 - Utils.toDegrees(Math.atan(y / x));
539 | if (x < 0) angle += 180;
540 |
541 | this.currentFace.selectTime(angle, elem);
542 | event.stopPropagation();
543 | }
544 | }, {
545 | key: "changeDisplayed",
546 | value: function changeDisplayed(array) {
547 | for (var i = 0; i < this.clockItems.length; i++) {
548 | this.clockItems[i].innerText = array[i];
549 | }
550 | }
551 | }, {
552 | key: "onEachClockElement",
553 | value: function onEachClockElement(fun) {
554 | [].forEach.call(this.clockItems, function (c) {
555 | return fun(c);
556 | });
557 | }
558 | }, {
559 | key: "updateMinutes",
560 | value: function updateMinutes(minutes, angle) {
561 | this.time.minutes = minutes;
562 | this.calculateHandOfTheClock(angle, this.itemsRadius);
563 | this.onTimeUpdate(this.time, Config.FaceType.MINUTES);
564 | }
565 | }, {
566 | key: "updateHours",
567 | value: function updateHours(hours, angle, radius) {
568 | this.time.hours = hours;
569 | this.calculateHandOfTheClock(angle, radius);
570 | this.onTimeUpdate(this.time, Config.FaceType.HOURS);
571 | }
572 | }, {
573 | key: "calculateHandOfTheClock",
574 | value: function calculateHandOfTheClock(angle) {
575 | var size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.itemsRadius;
576 |
577 | this.handOfAClock.style.transform = "rotate(" + (angle - 90) + "deg)";
578 | this.handOfAClock.style.width = size + "px";
579 | }
580 | }, {
581 | key: "toggleToHours",
582 | value: function toggleToHours() {
583 | this.minutesFace.onLeave();
584 | this.toggleTime(this.hoursFace);
585 | }
586 | }, {
587 | key: "toggleToMinutes",
588 | value: function toggleToMinutes() {
589 | this.hoursFace.onLeave();
590 | this.toggleTime(this.minutesFace);
591 | }
592 | }, {
593 | key: "toggleTime",
594 | value: function toggleTime(face) {
595 | var _this3 = this;
596 |
597 | if (this.currentFace !== face) {
598 | this.onEachClockElement(function (c) {
599 | return c.classList.add(css.fadeOut);
600 | });
601 | this.handOfAClock.classList.add(css.fadeOut);
602 | Promise.delay(function () {
603 | _this3.onEachClockElement(function (c) {
604 | return c.classList.remove(css.fadeOut);
605 | });
606 | _this3.handOfAClock.classList.remove(css.fadeOut);
607 | _this3.changeDisplayed(face.displayed);
608 | _this3.currentFace = face;
609 | _this3.onEachClockElement(function (c) {
610 | return _this3.removeSelected(c);
611 | });
612 | face.onEnter();
613 | }, 300);
614 | }
615 | }
616 | }, {
617 | key: "removeSelected",
618 | value: function removeSelected(c) {
619 | c.classList.remove(css.selected);
620 | c.style.background = "transparent";
621 | c.style.color = this.options.clockItemColor;
622 | }
623 | }]);
624 | return ClockFace;
625 | }();
626 |
627 | var Clock = function () {
628 | function Clock(options, time) {
629 | classCallCheck(this, Clock);
630 |
631 | this.options = options;
632 |
633 | this.initView();
634 | this.time = time;
635 | this.initElements();
636 | }
637 |
638 | createClass(Clock, [{
639 | key: "initView",
640 | value: function initView() {
641 | var _this = this;
642 |
643 | this.submitButton = document.getElementById(DOM.submitId);
644 | this.submitButton.onclick = function () {
645 | var time = _this.time;
646 | time.formatted = function () {
647 | return formatTime(time);
648 | };
649 | _this.options.onSubmit(time);
650 | Clock.dispose();
651 | };
652 |
653 | this.cancelButton = document.getElementById(DOM.cancelId);
654 | this.cancelButton.onclick = function () {
655 | _this.options.onCancel();
656 | Clock.dispose();
657 | };
658 | }
659 | }, {
660 | key: "initElements",
661 | value: function initElements() {
662 | var _this2 = this;
663 |
664 | this.header = new ClockHeader({
665 | options: this.options,
666 | time: this.time,
667 | onHourClicked: function onHourClicked() {
668 | return _this2.toggleToHours();
669 | },
670 | onMinutesClicked: function onMinutesClicked() {
671 | return _this2.toggleToMinutes();
672 | }
673 | });
674 | this.clockFace = new ClockFace(this.options, this.time, function (time, type) {
675 | return _this2.onTimeUpdate(time, type);
676 | });
677 | }
678 | }, {
679 | key: "onStart",
680 | value: function onStart() {
681 | this.clockFace.onStart();
682 | }
683 | }, {
684 | key: "toggleToHours",
685 | value: function toggleToHours() {
686 | this.clockFace.toggleToHours();
687 | }
688 | }, {
689 | key: "toggleToMinutes",
690 | value: function toggleToMinutes() {
691 | this.clockFace.toggleToMinutes();
692 | }
693 | }, {
694 | key: "onTimeUpdate",
695 | value: function onTimeUpdate(time, type) {
696 | this.time = time;
697 | this.header.time = time;
698 | this.header.updateDisplayedTime();
699 | if (type === Config.FaceType.MINUTES) this.header.toggleActiveToMinutes();
700 | }
701 | }], [{
702 | key: "dispose",
703 | value: function dispose() {
704 | document.body.removeChild(document.getElementById(Config.clockId));
705 | }
706 | }]);
707 | return Clock;
708 | }();
709 |
710 | function styleColors(options) {
711 | document.getElementById(DOM.headerId).style.background = options.headerBackground;
712 | document.getElementById(DOM.headerId).style.color = options.headerColor;
713 | document.getElementById(DOM.wrapperId).style.background = options.wrapperBackground;
714 | document.getElementById(DOM.clockId).style.background = options.clockBackground;
715 | document.getElementById(DOM.handId).style.background = options.handColor;
716 | document.getElementById(DOM.dotId).style.background = options.handColor;
717 | document.getElementById(DOM.buttonsId).style.background = options.footerBackground;
718 | document.getElementById(DOM.submitId).style.color = options.submitColor;
719 | document.getElementById(DOM.cancelId).style.color = options.cancelColor;
720 |
721 | changeColor(css.clockItem, options.clockItemColor);
722 | changeColor(css.inner, options.clockItemInnerColor);
723 | changeColor(css.outer, options.handColor, "borderColor");
724 | }
725 |
726 | function changeColor(className, color) {
727 | var property = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "color";
728 |
729 | var items = Array.from(document.getElementsByClassName(className));
730 | var _iteratorNormalCompletion = true;
731 | var _didIteratorError = false;
732 | var _iteratorError = undefined;
733 |
734 | try {
735 | for (var _iterator = items[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
736 | var item = _step.value;
737 |
738 | item.style[property] = color;
739 | }
740 | } catch (err) {
741 | _didIteratorError = true;
742 | _iteratorError = err;
743 | } finally {
744 | try {
745 | if (!_iteratorNormalCompletion && _iterator.return) {
746 | _iterator.return();
747 | }
748 | } finally {
749 | if (_didIteratorError) {
750 | throw _iteratorError;
751 | }
752 | }
753 | }
754 | }
755 |
756 | function showPicker() {
757 | var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
758 |
759 | createDom();
760 |
761 | var options = Object.assign({}, Config.clockConfig, config);
762 | var time = extractTime(options.time);
763 |
764 | var clock = new Clock(options, time);
765 | styleColors(options);
766 | clock.onStart();
767 | }
768 |
769 | function createDom() {
770 | if (document.getElementById(Config.clockId)) throw Error("There is already one running grudus-timepicker instance!");
771 |
772 | var clockDiv = document.createElement("div");
773 | clockDiv.id = Config.clockId;
774 | clockDiv.innerHTML = clockHtml;
775 | document.body.appendChild(clockDiv);
776 | }
777 |
778 | var index = {
779 | showPicker: function showPicker$$1(config) {
780 | return showPicker(config);
781 | },
782 | format: function format(time) {
783 | return formatTime(time);
784 | }
785 | };
786 |
787 | return index;
788 |
789 | })));
790 | //# sourceMappingURL=grudus-timepicker.umd.js.map
791 |
--------------------------------------------------------------------------------
/dist/index.css:
--------------------------------------------------------------------------------
1 | @-webkit-keyframes fade-in {
2 | from {
3 | opacity: 0;
4 | }
5 | to {
6 | opacity: 1;
7 | }
8 | }
9 |
10 | @keyframes fade-in {
11 | from {
12 | opacity: 0;
13 | }
14 | to {
15 | opacity: 1;
16 | }
17 | }
18 |
19 | @-webkit-keyframes fade-out {
20 | from {
21 | opacity: 1;
22 | }
23 | to {
24 | opacity: 0;
25 | }
26 | }
27 |
28 | @keyframes fade-out {
29 | from {
30 | opacity: 1;
31 | }
32 | to {
33 | opacity: 0;
34 | }
35 | }
36 |
37 | .g-time-wrapper {
38 | -webkit-box-sizing: content-box;
39 | box-sizing: content-box;
40 | min-width: 300px;
41 | min-height: 450px;
42 | position: fixed;
43 | top: 50%;
44 | left: 50%;
45 | -webkit-transform: translate(-50%, -50%);
46 | transform: translate(-50%, -50%);
47 | font-family: 'Roboto', sans-serif;
48 |
49 | display: -webkit-box;
50 |
51 | display: -ms-flexbox;
52 |
53 | display: flex;
54 | -webkit-box-orient: vertical;
55 | -webkit-box-direction: normal;
56 | -ms-flex-direction: column;
57 | flex-direction: column;
58 | -webkit-box-pack: start;
59 | -ms-flex-pack: start;
60 | justify-content: flex-start;
61 | }
62 |
63 | .g-flex {
64 | -webkit-box-flex: 1;
65 | -ms-flex-positive: 1;
66 | flex-grow: 1;
67 | }
68 |
69 | .g-head {
70 | -webkit-box-flex: 1;
71 | -ms-flex-positive: 1;
72 | flex-grow: 1;
73 | display: -webkit-box;
74 | display: -ms-flexbox;
75 | display: flex;
76 | -webkit-box-pack: center;
77 | -ms-flex-pack: center;
78 | justify-content: center;
79 | -webkit-box-align: center;
80 | -ms-flex-align: center;
81 | align-items: center;
82 | }
83 |
84 | .g-head-content {
85 | font-size: 3em;
86 | display: -webkit-box;
87 | display: -ms-flexbox;
88 | display: flex;
89 | }
90 |
91 | .g-current {
92 | margin: 0 2px;
93 | }
94 |
95 | .g-clock-wrapper {
96 | -webkit-box-flex: 4;
97 | -ms-flex-positive: 4;
98 | flex-grow: 4;
99 | display: -webkit-box;
100 | display: -ms-flexbox;
101 | display: flex;
102 | -webkit-box-align: center;
103 | -ms-flex-align: center;
104 | align-items: center;
105 | -webkit-box-pack: center;
106 | -ms-flex-pack: center;
107 | justify-content: center;
108 | }
109 |
110 | .g-clock {
111 | position: relative;
112 | border-radius: 100%;
113 | height: 240px;
114 | width: 240px;
115 | cursor: default;
116 | }
117 |
118 | .g-clock.g-clock-inner {
119 | top: 50%;
120 | left: 50%;
121 | -webkit-transform: translate(-50%, -50%);
122 | transform: translate(-50%, -50%);
123 | height: 160px;
124 | width: 160px;
125 | }
126 |
127 | .g-clock-item {
128 | position: absolute;
129 | border-radius: 100%;
130 | width: 20px;
131 | height: 20px;
132 | text-align: center;
133 | padding: 10px;
134 | -webkit-user-select: none;
135 | -moz-user-select: none;
136 | -ms-user-select: none;
137 | user-select: none;
138 | cursor: default;
139 | font-size: 1.1em;
140 | z-index: 3;
141 | }
142 |
143 | .g-clock-item.g-clock-inner {
144 | font-size: 0.9em;
145 | z-index: 3;
146 | }
147 |
148 |
149 | .g-clock-outer {
150 | position: absolute;
151 | width: 4px;
152 | height: 4px;
153 | border: 18px solid #1976D2;
154 | background: whitesmoke;
155 | color: whitesmoke;
156 | border-radius: 100%;
157 | visibility: hidden;
158 | z-index: 2;
159 | }
160 |
161 | .g-clock-outer.g-selected {
162 | visibility: visible;
163 | }
164 |
165 | .g-middle-dot {
166 | z-index: 2;
167 | position: absolute;
168 | width: 1px;
169 | height: 1px;
170 | padding: 7px;
171 | border-radius: 100%;
172 | top: 50%;
173 | left: 50%;
174 | -webkit-transform: translate(-50%, -50%);
175 | transform: translate(-50%, -50%);
176 | }
177 |
178 | .g-hand-of-a-clock {
179 | position: absolute;
180 | z-index: 2;
181 | top: 50%;
182 | left: 50%;
183 | -webkit-transform: translateY(-50%);
184 | transform: translateY(-50%);
185 | -webkit-transform-origin: left center;
186 | transform-origin: left center;
187 | height: 3px;
188 | width: 20px;
189 | }
190 |
191 | .g-buttons {
192 | display: -webkit-box;
193 | display: -ms-flexbox;
194 | display: flex;
195 | -webkit-box-pack: end;
196 | -ms-flex-pack: end;
197 | justify-content: flex-end;
198 | -webkit-box-align: center;
199 | -ms-flex-align: center;
200 | align-items: center;
201 | -webkit-box-flex: 0.5;
202 | -ms-flex-positive: 0.5;
203 | flex-grow: 0.5;
204 |
205 | }
206 |
207 | .g-button {
208 | font-weight: 600;
209 | border: none;
210 | background: transparent;
211 | margin-right: 16px;
212 | padding: 8px;
213 | }
214 |
215 | .g-button:hover {
216 | cursor: pointer;
217 | background: #CFD8DC;
218 | }
219 |
220 | .g-fade-in {
221 | -webkit-animation: fade-in 0.4s;
222 | animation: fade-in 0.4s;
223 | }
224 |
225 | .g-fade-out {
226 | -webkit-animation: fade-out 0.4s;
227 | animation: fade-out 0.4s;
228 | }
229 |
230 | .g-pointer:hover {
231 | cursor: pointer;
232 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "grudus-timepicker",
3 | "version": "1.0.2",
4 | "description": "Material design time picker in pure Javascript without any dependencies",
5 | "main": "dist/grudus-timepicker.es5.js",
6 | "jsnext:main": "dist/grudus-timepicker.js",
7 | "scripts": {
8 | "prebuild": "eslint src/**/*.js && npm run css",
9 | "build": "rollup -c rollup/es5.js && rollup -c rollup/umd.js && rollup -c rollup/es6.js",
10 | "patch": "npm version patch && npm publish && git push --tags && git push",
11 | "dev": "rollup -w -c rollup/es5.js",
12 | "fix": "eslint src/**/*.js --fix",
13 | "css": "postcss src/**/*.css --use autoprefixer --no-map -d dist/"
14 | },
15 | "repository": {
16 | "type": "git",
17 | "url": "git+https://github.com/grudus/Timepicker.git"
18 | },
19 | "devDependencies": {
20 | "autoprefixer": "^7.1.2",
21 | "babel-plugin-external-helpers": "^6.22.0",
22 | "babel-preset-es2015": "^6.24.1",
23 | "eslint": "^4.4.0",
24 | "postcss-cli": "^4.1.0",
25 | "rollup": "^0.45.2",
26 | "rollup-plugin-babel": "^2.7.1",
27 | "rollup-plugin-commonjs": "^8.1.0",
28 | "rollup-plugin-node-resolve": "^3.0.0",
29 | "rollup-plugin-uglify": "^2.0.1",
30 | "rollup-watch": "^4.3.1",
31 | "uglify-js": "^3.0.27"
32 | },
33 | "keywords": [
34 | "vanillajs",
35 | "javascript",
36 | "js",
37 | "materialdesign",
38 | "material",
39 | "design",
40 | "timepicker"
41 | ],
42 | "author": "grudus",
43 | "license": "Apache-2.0",
44 | "bugs": {
45 | "url": "https://github.com/grudus/Timepicker/issues"
46 | },
47 | "homepage": "https://github.com/grudus/Timepicker#readme"
48 | }
49 |
--------------------------------------------------------------------------------
/rollup/es5.js:
--------------------------------------------------------------------------------
1 | import nodeResolve from "rollup-plugin-node-resolve";
2 | import convertCJS from "rollup-plugin-commonjs";
3 | import babel from "rollup-plugin-babel";
4 | import uglify from "rollup-plugin-uglify";
5 |
6 | const packageInfo = require("../package.json");
7 | const banner = `/*! ${packageInfo.name} | (c) 2017-${new Date().getFullYear()}
8 | ${packageInfo.author} | ${packageInfo.license} license (see LICENSE) */`;
9 |
10 |
11 | export default {
12 | entry: "src/js/index.js",
13 | format: "umd",
14 | moduleName: "Timepicker",
15 | sourceMap: true,
16 | plugins: [
17 | nodeResolve({
18 | jsnext: true,
19 | main: true,
20 | browser: true,
21 | }),
22 | convertCJS(),
23 | babel(),
24 | uglify({
25 | output: {
26 | preamble: banner
27 | }
28 | })
29 | ],
30 | dest: `dist/${packageInfo.name}.es5.js`
31 | };
--------------------------------------------------------------------------------
/rollup/es6.js:
--------------------------------------------------------------------------------
1 | import nodeResolve from "rollup-plugin-node-resolve";
2 | import convertCJS from "rollup-plugin-commonjs";
3 | import babel from "rollup-plugin-babel";
4 |
5 | const packageInfo = require("../package.json");
6 | const banner = `/*! ${packageInfo.name} | (c) 2017-${new Date().getFullYear()}
7 | ${packageInfo.author} | ${packageInfo.license} license (see LICENSE) */`;
8 |
9 | export default {
10 | entry: "src/js/index.js",
11 | format: "es",
12 | sourceMap: true,
13 | plugins: [
14 | nodeResolve({
15 | jsnext: true,
16 | main: false
17 | }),
18 | convertCJS(),
19 | babel()
20 | ],
21 | banner,
22 | dest: `dist/${packageInfo.name}.js`
23 | };
--------------------------------------------------------------------------------
/rollup/umd.js:
--------------------------------------------------------------------------------
1 | import nodeResolve from "rollup-plugin-node-resolve";
2 | import convertCJS from "rollup-plugin-commonjs";
3 | import babel from "rollup-plugin-babel";
4 |
5 |
6 | const packageInfo = require("../package.json");
7 | const banner = `/*! ${packageInfo.name} | (c) 2017-${new Date().getFullYear()}
8 | ${packageInfo.author} | ${packageInfo.license} license (see LICENSE) */`;
9 |
10 | export default {
11 | entry: "src/js/index.js",
12 | format: "umd",
13 | moduleName: "Timepicker",
14 | sourceMap: true,
15 | plugins: [
16 | nodeResolve({
17 | jsnext: true,
18 | main: false
19 | }),
20 | convertCJS(),
21 | babel(),
22 | ],
23 | banner,
24 | dest: `dist/${packageInfo.name}.umd.js`
25 | };
--------------------------------------------------------------------------------
/src/js/clock.js:
--------------------------------------------------------------------------------
1 | import ClockHeader from "./clockHeader";
2 | import ClockFace from "./face/clockFace";
3 | import Config, {DOM} from "./meta/config";
4 | import formatTime from "./timeFormatter";
5 |
6 | export default class Clock {
7 |
8 | constructor(options, time) {
9 | this.options = options;
10 |
11 | this.initView();
12 | this.time = time;
13 | this.initElements();
14 | }
15 |
16 | initView() {
17 | this.submitButton = document.getElementById(DOM.submitId);
18 | this.submitButton.onclick = () => {
19 | const time = this.time;
20 | time.formatted = () => formatTime(time);
21 | this.options.onSubmit(time);
22 | Clock.dispose();
23 | };
24 |
25 | this.cancelButton = document.getElementById(DOM.cancelId);
26 | this.cancelButton.onclick = () => {
27 | this.options.onCancel();
28 | Clock.dispose();
29 | };
30 | }
31 |
32 | initElements() {
33 | this.header = new ClockHeader({
34 | options: this.options,
35 | time: this.time,
36 | onHourClicked: () => this.toggleToHours(),
37 | onMinutesClicked: () => this.toggleToMinutes()
38 | });
39 | this.clockFace = new ClockFace(this.options, this.time, (time, type) => this.onTimeUpdate(time, type));
40 | }
41 |
42 | onStart() {
43 | this.clockFace.onStart();
44 | }
45 |
46 | toggleToHours() {
47 | this.clockFace.toggleToHours();
48 | }
49 |
50 | toggleToMinutes() {
51 | this.clockFace.toggleToMinutes();
52 | }
53 |
54 | onTimeUpdate(time, type) {
55 | this.time = time;
56 | this.header.time = time;
57 | this.header.updateDisplayedTime();
58 | if (type === Config.FaceType.MINUTES)
59 | this.header.toggleActiveToMinutes();
60 |
61 | }
62 |
63 | static dispose() {
64 | document.body.removeChild(document.getElementById(Config.clockId));
65 | }
66 | }
--------------------------------------------------------------------------------
/src/js/clockHeader.js:
--------------------------------------------------------------------------------
1 | import {DOM} from "./meta/config";
2 |
3 | export default class ClockHeader {
4 |
5 | constructor(config) {
6 | this.options = config.options;
7 | this.time = config.time;
8 | this.onHourClicked = config.onHourClicked;
9 | this.onMinutesClicked = config.onMinutesClicked;
10 |
11 | this.initView();
12 | }
13 |
14 | initView() {
15 | this.headerHours = document.getElementById(DOM.hoursId);
16 | this.headerHours.onclick = () => {
17 | this.toggleActiveToHours();
18 | this.onHourClicked();
19 | };
20 |
21 | this.headerMinutes = document.getElementById(DOM.minutesId);
22 | this.headerMinutes.onclick = () => {
23 | this.toggleActiveToMinutes();
24 | this.onMinutesClicked();
25 | };
26 |
27 | this.updateDisplayedTime();
28 | this.toggleActiveToHours();
29 | }
30 |
31 | toggleActiveToMinutes() {
32 | this.toggleActive(this.headerHours, this.headerMinutes);
33 | }
34 |
35 | toggleActiveToHours() {
36 | this.toggleActive(this.headerMinutes, this.headerHours);
37 | }
38 |
39 | toggleActive(objectToRemoveClass, objectToAddClass) {
40 | objectToRemoveClass.style.color = this.options.headerColor;
41 | objectToAddClass.style.color = this.options.headerSelected;
42 | }
43 |
44 | updateDisplayedTime() {
45 | ClockHeader.doUpdateDisplayedTime(this.headerHours, this.time.hours);
46 | ClockHeader.doUpdateDisplayedTime(this.headerMinutes, this.time.minutes);
47 | }
48 |
49 | static doUpdateDisplayedTime(node, value) {
50 | if (value < 10)
51 | node.innerText = "0" + value;
52 | else node.innerText = value;
53 | }
54 | }
--------------------------------------------------------------------------------
/src/js/colorStylists.js:
--------------------------------------------------------------------------------
1 | import {css, DOM} from "./meta/config";
2 |
3 | export default function styleColors(options) {
4 | document.getElementById(DOM.headerId).style.background = options.headerBackground;
5 | document.getElementById(DOM.headerId).style.color = options.headerColor;
6 | document.getElementById(DOM.wrapperId).style.background = options.wrapperBackground;
7 | document.getElementById(DOM.clockId).style.background = options.clockBackground;
8 | document.getElementById(DOM.handId).style.background = options.handColor;
9 | document.getElementById(DOM.dotId).style.background = options.handColor;
10 | document.getElementById(DOM.buttonsId).style.background = options.footerBackground;
11 | document.getElementById(DOM.submitId).style.color = options.submitColor;
12 | document.getElementById(DOM.cancelId).style.color = options.cancelColor;
13 |
14 | changeColor(css.clockItem, options.clockItemColor);
15 | changeColor(css.inner, options.clockItemInnerColor);
16 | changeColor(css.outer, options.handColor, "borderColor");
17 | }
18 |
19 | function changeColor(className, color, property = "color") {
20 | const items = Array.from(document.getElementsByClassName(className));
21 | for (const item of items)
22 | item.style[property] = color;
23 | }
24 |
--------------------------------------------------------------------------------
/src/js/face/clockFace.js:
--------------------------------------------------------------------------------
1 | import MinutesFace from "./minutesFace";
2 | import HoursFace from "./hoursFace";
3 | import Utils from "../meta/utils";
4 | import Config, {css, DOM} from "../meta/config";
5 | import ClockFaceCreator from "./clockFaceCreator";
6 |
7 | export default class ClockFace {
8 |
9 | constructor(options, initialTime, onTimeUpdate) {
10 | this.options = options;
11 | this.time = initialTime;
12 | this.onTimeUpdate = onTimeUpdate;
13 | this.isMouseDown = false;
14 | this.clockItems = [];
15 | this.innerClockItems = [];
16 | this.outerClockItems = [];
17 | this.size = {};
18 | this.middle = {};
19 |
20 | this.initViews();
21 | this.initTimeFaces(initialTime);
22 | this.createFace();
23 |
24 | this.hoursFace.items.radius = this.itemsRadius;
25 |
26 | this.currentFace = this.hoursFace;
27 | this.changeDisplayed(this.currentFace.displayed);
28 | }
29 |
30 | initViews() {
31 | this.clockElem = document.getElementById(DOM.clockId);
32 | this.innerClockElem = document.getElementById(DOM.innerId);
33 | this.handOfAClock = document.getElementById(DOM.handId);
34 |
35 | this.clockElem.onmousedown = () => this.isMouseDown = true;
36 | this.clockElem.onmouseup = () => {this.isMouseDown = false;
37 | this.toggleToMinutes();
38 | };
39 |
40 | this.handOfAClock.onmouseup = (e) => e.stopPropagation();
41 | this.handOfAClock.onmousemove = (e) => e.stopPropagation();
42 | this.handOfAClock.onclick = (e) => e.stopPropagation();
43 |
44 | this.clockElem.onmousemove = (e) => this.selectTime(e, false, this.clockElem);
45 | this.clockElem.onclick = (e) => this.selectTime(e, true, this.clockElem);
46 |
47 | this.innerClockElem.onmousemove = (e) => this.selectTime(e, false, this.innerClockElem);
48 | this.innerClockElem.onclick = (e) => this.selectTime(e, true, this.innerClockElem);
49 | }
50 |
51 | initTimeFaces(initialTime) {
52 | this.minutesFace = new MinutesFace({
53 | options: this.options,
54 | clockItems: this.clockItems,
55 | outerClockItems: this.outerClockItems
56 | }, initialTime.minutes, (minutes, angle) => this.updateMinutes(minutes, angle));
57 |
58 | this.hoursFace = new HoursFace({
59 | options: this.options,
60 | innerClockItems: this.innerClockItems,
61 | clockItems: this.clockItems,
62 | innerClockElem: this.innerClockElem
63 | }, initialTime.hours, (hours, angle, radius) => this.updateHours(hours, angle, radius));
64 | }
65 |
66 | onStart() {
67 | this.currentFace.onEnter();
68 | }
69 |
70 | createFace() {
71 | const clockFaceCreator = new ClockFaceCreator(this.clockElem, this.innerClockElem);
72 | clockFaceCreator.create(this.clockItems, this.innerClockItems, this.outerClockItems, this.hoursFace);
73 | clockFaceCreator.calculateSize(this.clockItems, this.innerClockItems, this.outerClockItems);
74 |
75 | this.size = clockFaceCreator.size;
76 | this.middle = clockFaceCreator.middle;
77 | this.itemsRadius = clockFaceCreator.itemsRadius;
78 | }
79 |
80 | selectTime(event, isMouseDown, elem) {
81 | if (!(isMouseDown || this.isMouseDown))
82 | return;
83 | const mouse = Utils.findMousePosition(event, this.clockElem);
84 | const x = mouse.x - this.middle.x;
85 | const y = this.middle.y - mouse.y;
86 | let angle = 90 - Utils.toDegrees(Math.atan(y / x));
87 | if (x < 0) angle += 180;
88 |
89 | this.currentFace.selectTime(angle, elem);
90 | event.stopPropagation();
91 | }
92 |
93 | changeDisplayed(array) {
94 | for (let i = 0; i < this.clockItems.length; i++)
95 | this.clockItems[i].innerText = array[i];
96 | }
97 |
98 | onEachClockElement(fun) {
99 | [].forEach.call(this.clockItems, c => fun(c));
100 | }
101 |
102 | updateMinutes(minutes, angle) {
103 | this.time.minutes = minutes;
104 | this.calculateHandOfTheClock(angle, this.itemsRadius);
105 | this.onTimeUpdate(this.time, Config.FaceType.MINUTES);
106 | }
107 |
108 | updateHours(hours, angle, radius) {
109 | this.time.hours = hours;
110 | this.calculateHandOfTheClock(angle, radius);
111 | this.onTimeUpdate(this.time, Config.FaceType.HOURS);
112 | }
113 |
114 | calculateHandOfTheClock(angle, size = this.itemsRadius) {
115 | this.handOfAClock.style.transform = `rotate(${angle - 90}deg)`;
116 | this.handOfAClock.style.width = size + "px";
117 | }
118 |
119 | toggleToHours() {
120 | this.minutesFace.onLeave();
121 | this.toggleTime(this.hoursFace);
122 | }
123 |
124 | toggleToMinutes() {
125 | this.hoursFace.onLeave();
126 | this.toggleTime(this.minutesFace);
127 | }
128 |
129 | toggleTime(face) {
130 | if (this.currentFace !== face) {
131 | this.onEachClockElement(c => c.classList.add(css.fadeOut));
132 | this.handOfAClock.classList.add(css.fadeOut);
133 | Promise.delay(() => {
134 | this.onEachClockElement(c => c.classList.remove(css.fadeOut));
135 | this.handOfAClock.classList.remove(css.fadeOut);
136 | this.changeDisplayed(face.displayed);
137 | this.currentFace = face;
138 | this.onEachClockElement(c => this.removeSelected(c));
139 | face.onEnter();
140 | }, 300);
141 | }
142 | }
143 |
144 | removeSelected(c) {
145 | c.classList.remove(css.selected);
146 | c.style.background = "transparent";
147 | c.style.color = this.options.clockItemColor;
148 | }
149 | }
--------------------------------------------------------------------------------
/src/js/face/clockFaceCreator.js:
--------------------------------------------------------------------------------
1 | import Utils from "../meta/utils";
2 | import {css} from "../meta/config";
3 |
4 | export default class ClockFaceCreator {
5 |
6 | constructor(clockElem, innerClockElem) {
7 | this.clockElem = clockElem;
8 | this.innerClockElem = innerClockElem;
9 | this.size = {};
10 | this.middle = {};
11 | }
12 |
13 | create(clockItems, innerClockItems, outerClockItems, face) {
14 | ClockFaceCreator.doCreate(clockItems, this.clockElem, span => span.classList.add(css.item));
15 | ClockFaceCreator.doCreate(innerClockItems, this.innerClockElem, (span, i) => {
16 | span.classList.add(css.item, css.inner);
17 | span.innerText = face.displayedInner[i];
18 | });
19 |
20 | for (let i = 0; i < 60; i++) {
21 | const span = document.createElement("span");
22 | span.classList.add(css.outer);
23 | outerClockItems.push(span);
24 | this.clockElem.appendChild(span);
25 | }
26 | }
27 |
28 | static doCreate(clockItems, clockElem, fun) {
29 | for (let i = 0; i < 12; i++) {
30 | const span = document.createElement("span");
31 | fun(span, i);
32 | clockItems.push(span);
33 | clockElem.appendChild(span);
34 | }
35 | }
36 |
37 | calculateSize(clockItems, innerClockItems, outerClockItems) {
38 | this.size.width = this.clockElem.offsetWidth;
39 | this.size.height = this.clockElem.offsetHeight;
40 | this.middle.x = this.size.width / 2;
41 | this.middle.y = this.size.height / 2;
42 | this.itemsRadius = this.size.width / 2 - 20;
43 |
44 | const innerWidth = this.innerClockElem.offsetWidth;
45 | const innerHeight = this.innerClockElem.offsetHeight;
46 | const middleX = innerWidth / 2;
47 | const middleY = innerHeight / 2;
48 |
49 | ClockFaceCreator.doCalculateSize(this.middle.x, this.middle.y, this.itemsRadius, clockItems);
50 | ClockFaceCreator.doCalculateSize(middleX, middleY, this.itemsRadius - 40, innerClockItems);
51 | ClockFaceCreator.doCalculateSize(this.middle.x, this.middle.y, this.itemsRadius, outerClockItems);
52 | }
53 |
54 | static doCalculateSize(middleX, middleY, radius, items) {
55 | const angleQuantum = 360 / items.length;
56 | for (let i = 0; i < items.length; i++) {
57 |
58 | const angle = Utils.toRadians(i * angleQuantum);
59 | const item = items[i];
60 | const itemWidth = item.offsetWidth;
61 | const itemHeight = item.offsetHeight;
62 |
63 | item.style.left = ((middleX + Math.sin(angle) * radius) - itemWidth / 2) + "px";
64 | item.style.bottom = ((middleY + Math.cos(angle) * radius) - itemHeight / 2) + "px";
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/src/js/face/hoursFace.js:
--------------------------------------------------------------------------------
1 | import Config from "../meta/config";
2 |
3 | export default class HoursFace {
4 |
5 | constructor(items, initialHours, updateHours) {
6 | this.displayed = ["12", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"];
7 | this.displayedInner = ["00", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"];
8 | this.type = Config.FaceType.MINUTES;
9 | this.selected = undefined;
10 | this.options = items.options;
11 |
12 | this.items = items;
13 | this.hours = initialHours;
14 | this.updateHours = updateHours;
15 | }
16 |
17 | onEnter() {
18 | this.items.innerClockElem.style.display = "block";
19 | const isInnerClock = this.hours < 13 && this.hours !== 0;
20 | const hoursIndex = this.hours % 12;
21 | this.selected = isInnerClock ? this.items.clockItems[hoursIndex] : this.items.innerClockItems[hoursIndex];
22 | this.colorSelected();
23 |
24 | this.updateHours(this.hours, hoursIndex * 30, isInnerClock ? this.items.radius : this.items.radius - 50);
25 | }
26 |
27 | onLeave() {
28 | this.items.innerClockElem.style.display = "none";
29 | if (this.selected) {
30 | this.removeSelected();
31 | this.selected = undefined;
32 | }
33 | }
34 |
35 | selectTime(angle, elem) {
36 | if (this.selected)
37 | this.removeSelected();
38 |
39 | const index = Math.round(angle / 30) % 12;
40 | this.selected = (elem === this.items.innerClockElem
41 | ? this.items.innerClockItems
42 | : this.items.clockItems)[index];
43 |
44 | this.colorSelected();
45 | this.hours = parseInt(this.selected.innerText);
46 | const selectedAngle = Math.round(angle / 30) * 30;
47 |
48 | this.updateHours(this.hours, selectedAngle,
49 | elem === this.items.innerClockElem ? this.items.radius - 50 : this.items.radius);
50 | }
51 |
52 | colorSelected() {
53 | this.selected.style.background = this.options.handColor;
54 | this.selected.style.color = "#ffffff";
55 | }
56 |
57 | removeSelected() {
58 | this.selected.style.background = "transparent";
59 | this.selected.style.color = this.isInner()
60 | ? this.options.clockItemInnerColor
61 | : this.options.clockItemColor;
62 | }
63 |
64 | isInner() {
65 | return Array.from(this.items.innerClockItems).indexOf(this.selected) > -1;
66 | }
67 | }
--------------------------------------------------------------------------------
/src/js/face/minutesFace.js:
--------------------------------------------------------------------------------
1 | import Config, {css} from "../meta/config";
2 |
3 | export default class MinutesFace {
4 |
5 | constructor(items, initialMinutes, updateMinutes) {
6 | this.displayed = ["00", "05", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55"];
7 | this.options = items.options;
8 | this.type = Config.FaceType.MINUTES;
9 | this.selected = undefined;
10 | this.items = items;
11 | this.minutes = initialMinutes;
12 | this.updateMinutes = updateMinutes;
13 | }
14 |
15 | onEnter() {
16 | this.selected = this.findSelected(this.minutes);
17 | this.colorSelected();
18 | this.updateMinutes(this.minutes, this.minutes * 6);
19 | }
20 |
21 | onLeave() {
22 | if (this.selected) {
23 | this.removeSelected();
24 | this.selected = undefined;
25 | }
26 | }
27 |
28 | selectTime(angle) {
29 | if (this.selected)
30 | this.removeSelected();
31 |
32 | const minute = Math.round(angle / 6) % 60;
33 | this.selected = this.findSelected(minute);
34 | this.colorSelected();
35 | this.minutes = minute;
36 | this.updateMinutes(this.minutes, angle);
37 | }
38 |
39 | findSelected(minute) {
40 | return (minute % 5 === 0) ? this.items.clockItems[minute / 5] : this.items.outerClockItems[minute];
41 | }
42 |
43 | colorSelected() {
44 | if (this.isOuter()) {
45 | this.selected.classList.add(css.selected);
46 | return;
47 | }
48 | this.selected.style.background = this.options.handColor;
49 | this.selected.style.color = "whitesmoke";
50 | }
51 |
52 | removeSelected() {
53 | if (this.isOuter()) {
54 | this.selected.classList.remove(css.selected);
55 | return;
56 | }
57 | this.selected.style.background = "transparent";
58 | this.selected.style.color = this.options.clockItemColor;
59 | }
60 |
61 | isOuter() {
62 | return this.items.outerClockItems.indexOf(this.selected) > -1;
63 | }
64 | }
--------------------------------------------------------------------------------
/src/js/index.js:
--------------------------------------------------------------------------------
1 | import formatTime from "./timeFormatter";
2 | import showPicker from "./timepickerCreator";
3 |
4 | export default {
5 | showPicker: (config) => showPicker(config),
6 | format: (time) => formatTime(time)
7 | };
8 |
9 |
--------------------------------------------------------------------------------
/src/js/meta/clockHtml.js:
--------------------------------------------------------------------------------
1 | export default "\n" +
2 | " \n" +
3 | " \n" +
4 | " 21 \n" +
5 | " : \n" +
6 | " 37 \n" +
7 | " \n" +
8 | " \n" +
9 | "\n" +
10 | "\n" +
11 | " \n" +
12 | " " +
13 | "
\n" +
14 | "
\n" +
15 | "
\n" +
16 | "
\n" +
17 | " \n" +
18 | "\n" +
19 | "\n" +
20 | " \n" +
24 | "\n" +
25 | " ";
--------------------------------------------------------------------------------
/src/js/meta/config.js:
--------------------------------------------------------------------------------
1 | const clockId = "grudus-clock";
2 |
3 | const defaultConfig = {
4 | onSubmit: () => {
5 | },
6 | onCancel: () => {
7 | },
8 | headerBackground: "#1976D2",
9 | headerColor: "#c7d6e1",
10 | headerSelected: "#ffffff",
11 | wrapperBackground: "#f0fff0",
12 | footerBackground: "#f0fff0",
13 | submitColor: "#1976D2",
14 | cancelColor: "#1976D2",
15 | clockBackground: "#CFD8DC",
16 | clockItemColor: "#212121",
17 | clockItemInnerColor: "#212121",
18 | handColor: "#1976D2"
19 | };
20 |
21 | const FaceType = {HOURS: "hours", MINUTES: "minutes"};
22 |
23 | const css = {
24 | clock: "g-clock",
25 | clockItem: "g-clock-item",
26 | inner: "g-clock-inner",
27 | outer: "g-clock-outer",
28 | item: "g-clock-item",
29 | hand: "g-hand-of-a-clock",
30 | fadeOut: "g-fade-out",
31 | selected: "g-selected",
32 | active: "g-active",
33 | submit: "g-submit",
34 | cancel: "g-cancel",
35 | hour: "g-hour",
36 | minute: "g-minute"
37 | };
38 |
39 | const DOM = {
40 | headerId: "g-head",
41 | hoursId: "g-hours",
42 | minutesId: "g-minutes",
43 | clockId: "g-clock",
44 | innerId: "g-clock-inner",
45 | wrapperId: "g-clock-wrapper",
46 | dotId: "g-middle-dot",
47 | handId: "g-hand-of-a-clock",
48 | buttonsId: "g-buttons",
49 | submitId: "g-time-submit",
50 | cancelId: "g-time-cancel"
51 | };
52 |
53 | export default {clockId, clockConfig: defaultConfig, FaceType};
54 | export {css, DOM};
--------------------------------------------------------------------------------
/src/js/meta/utils.js:
--------------------------------------------------------------------------------
1 | function toRadians(angle) {
2 | return angle * (Math.PI / 180);
3 | }
4 |
5 | function toDegrees(angle) {
6 | return angle * (180 / Math.PI);
7 | }
8 |
9 | function findMousePosition(event, object) {
10 | const rect = object.getBoundingClientRect();
11 | return {
12 | x: event.clientX - rect.left,
13 | y: event.clientY - rect.top
14 | };
15 | }
16 |
17 | function delay(t) {
18 | return new Promise(function (resolve) {
19 | setTimeout(resolve, t);
20 | });
21 | }
22 |
23 | Promise.delay = function (fn, t) {
24 | if (!t) {
25 | t = fn;
26 | fn = function () {
27 | };
28 | }
29 | return delay(t).then(fn);
30 | };
31 |
32 | Promise.prototype.delay = function (fn, t) {
33 | return this.then(function () {
34 | return Promise.delay(fn, t);
35 | });
36 | };
37 |
38 | export default {toRadians, toDegrees, findMousePosition};
--------------------------------------------------------------------------------
/src/js/timeExtractor.js:
--------------------------------------------------------------------------------
1 | const hoursRegex = /^([0-1]?[0-9]|2[0-3])$/;
2 | const minutesRegex = /^([0-5]?[0-9])$/;
3 | const regex = /^([0-1]?[0-9]|2[0-3]):([0-5][0-9])$/;
4 |
5 | export default function extractTime(date) {
6 | if (!date)
7 | return fromDate(new Date());
8 | else if (date instanceof Date)
9 | return fromDate(date);
10 | else if (hoursRegex.test(date.hours) && minutesRegex.test(date.minutes))
11 | return {hours: parseInt(date.hours), minutes: parseInt(date.minutes)};
12 | else if (regex.test(date))
13 | return fromRegex(date);
14 | else
15 | throw new TypeError(`INVALID FORMAT: {${JSON.stringify(date)}}.
16 | Time must be a Date or 'hh:MM' string or object with 'hours' and 'minutes' fields`);
17 | }
18 |
19 | function fromRegex(date) {
20 | const parsed = regex.exec(date);
21 | return {hours: parseInt(parsed[1]), minutes: parseInt(parsed[2])};
22 | }
23 |
24 | function fromDate(date) {
25 | return {hours: date.getHours(), minutes: date.getMinutes()};
26 | }
--------------------------------------------------------------------------------
/src/js/timeFormatter.js:
--------------------------------------------------------------------------------
1 | import extractTime from "./timeExtractor";
2 |
3 | export default function (time) {
4 | const extractedTime = extractTime(time);
5 | return (extractedTime.hours < 10 ? "0" + extractedTime.hours : extractedTime.hours)
6 | + ":" + (extractedTime.minutes < 10 ? "0" + extractedTime.minutes : extractedTime.minutes);
7 | }
--------------------------------------------------------------------------------
/src/js/timepickerCreator.js:
--------------------------------------------------------------------------------
1 | import clockHtml from "./meta/clockHtml";
2 | import Config from "./meta/config";
3 | import Clock from "./clock";
4 | import styleColors from "./colorStylists";
5 | import getTime from "./timeExtractor";
6 |
7 |
8 | export default function showPicker(config = {}) {
9 | createDom();
10 |
11 | const options = Object.assign({}, Config.clockConfig, config);
12 | const time = getTime(options.time);
13 |
14 | const clock = new Clock(options, time);
15 | styleColors(options);
16 | clock.onStart();
17 | }
18 |
19 |
20 | function createDom() {
21 | if (document.getElementById(Config.clockId))
22 | throw Error("There is already one running grudus-timepicker instance!");
23 |
24 | const clockDiv = document.createElement("div");
25 | clockDiv.id = Config.clockId;
26 | clockDiv.innerHTML = clockHtml;
27 | document.body.appendChild(clockDiv);
28 | }
29 |
--------------------------------------------------------------------------------
/src/styles/index.css:
--------------------------------------------------------------------------------
1 | @keyframes fade-in {
2 | from {
3 | opacity: 0;
4 | }
5 | to {
6 | opacity: 1;
7 | }
8 | }
9 |
10 | @keyframes fade-out {
11 | from {
12 | opacity: 1;
13 | }
14 | to {
15 | opacity: 0;
16 | }
17 | }
18 |
19 | .g-time-wrapper {
20 | box-sizing: content-box;
21 | min-width: 300px;
22 | min-height: 450px;
23 | position: fixed;
24 | top: 50%;
25 | left: 50%;
26 | transform: translate(-50%, -50%);
27 | font-family: 'Roboto', sans-serif;
28 |
29 | display: flex;
30 | flex-direction: column;
31 | justify-content: flex-start;
32 | }
33 |
34 | .g-flex {
35 | flex-grow: 1;
36 | }
37 |
38 | .g-head {
39 | flex-grow: 1;
40 | display: flex;
41 | justify-content: center;
42 | align-items: center;
43 | }
44 |
45 | .g-head-content {
46 | font-size: 3em;
47 | display: flex;
48 | }
49 |
50 | .g-current {
51 | margin: 0 2px;
52 | }
53 |
54 | .g-clock-wrapper {
55 | flex-grow: 4;
56 | display: flex;
57 | align-items: center;
58 | justify-content: center;
59 | }
60 |
61 | .g-clock {
62 | position: relative;
63 | border-radius: 100%;
64 | height: 240px;
65 | width: 240px;
66 | cursor: default;
67 | }
68 |
69 | .g-clock.g-clock-inner {
70 | top: 50%;
71 | left: 50%;
72 | transform: translate(-50%, -50%);
73 | height: 160px;
74 | width: 160px;
75 | }
76 |
77 | .g-clock-item {
78 | position: absolute;
79 | border-radius: 100%;
80 | width: 20px;
81 | height: 20px;
82 | text-align: center;
83 | padding: 10px;
84 | user-select: none;
85 | cursor: default;
86 | font-size: 1.1em;
87 | z-index: 3;
88 | }
89 |
90 | .g-clock-item.g-clock-inner {
91 | font-size: 0.9em;
92 | z-index: 3;
93 | }
94 |
95 |
96 | .g-clock-outer {
97 | position: absolute;
98 | width: 4px;
99 | height: 4px;
100 | border: 18px solid #1976D2;
101 | background: whitesmoke;
102 | color: whitesmoke;
103 | border-radius: 100%;
104 | visibility: hidden;
105 | z-index: 2;
106 | }
107 |
108 | .g-clock-outer.g-selected {
109 | visibility: visible;
110 | }
111 |
112 | .g-middle-dot {
113 | z-index: 2;
114 | position: absolute;
115 | width: 1px;
116 | height: 1px;
117 | padding: 7px;
118 | border-radius: 100%;
119 | top: 50%;
120 | left: 50%;
121 | transform: translate(-50%, -50%);
122 | }
123 |
124 | .g-hand-of-a-clock {
125 | position: absolute;
126 | z-index: 2;
127 | top: 50%;
128 | left: 50%;
129 | transform: translateY(-50%);
130 | transform-origin: left center;
131 | height: 3px;
132 | width: 20px;
133 | }
134 |
135 | .g-buttons {
136 | display: flex;
137 | justify-content: flex-end;
138 | align-items: center;
139 | flex-grow: 0.5;
140 |
141 | }
142 |
143 | .g-button {
144 | font-weight: 600;
145 | border: none;
146 | background: transparent;
147 | margin-right: 16px;
148 | padding: 8px;
149 | }
150 |
151 | .g-button:hover {
152 | cursor: pointer;
153 | background: #CFD8DC;
154 | }
155 |
156 | .g-fade-in {
157 | animation: fade-in 0.4s;
158 | }
159 |
160 | .g-fade-out {
161 | animation: fade-out 0.4s;
162 | }
163 |
164 | .g-pointer:hover {
165 | cursor: pointer;
166 | }
--------------------------------------------------------------------------------