OSDN Git Service

changed splashscreen easings
[alterlinux/lightdm-webkit2-theme-alter.git] / js / splashscreen.js
1 const  DEF_OPT =
2 {
3         "fit": true,
4         "filter": false,
5         "vignette": true,
6         "active-timeout": 15,
7         "content": {
8                 "clock": [{
9                         "format": "dddd, MMMM Do",
10                         "css": {
11                                 "color": "white"
12                         },
13                         "parent-css": {
14                                 "margin-top": "calc(20vh - 70pt)",
15                                 "text-align": "center",
16                                 "font-size": "70pt",
17                                 "font-family": "Noto Sans",
18                                 "font-weight": "lighter",
19                                 "text-shadow": "rgba(0, 0, 0, 0.8) 0px 7px 10px",
20                         }
21                 },{
22                         "format": ["h:mm", "A"],
23                         "css": [
24                                 {"font-size": "65pt", "font-weight": 200 },
25                                 {"font-size": "30pt", "font-weight": "lighter", "margin-left": "10pt"}
26                         ],
27                         "parent-css": {
28                                 "margin-top": "20vh",
29                                 "color": "white",
30                                 "font-family": "Noto Sans",
31                                 "text-align": "center",
32                                 "text-shadow": "rgba(0, 0, 0, 0.8) 0px 7px 10px",
33                         }
34                 }],
35
36                 "html": [{
37                         "html":"<text style='display: none' class='active-appear'>Press any key to login</text>",
38                         "css": {
39
40                                 "margin-top": "5vh",
41                                 "font-weight": "200",
42                                 "font-size": "23pt",
43                                 "text-align": "center",
44                                 "color": "rgba(255, 255, 255, 0.8)"
45                         }
46                 }]
47         }
48 };
49
50 class SplashScreen {
51         constructor() {
52                 this.options = this.getUserOptions();
53                 $(this).on("init", () => this._init());
54         }
55         _init() {
56                 this.$el = $("#splash-screen");
57                 this.$content = $("#splash-screen-content");
58                 this.state = "closed";
59                 this.last_active = 0;
60                 this.active_timeout = 15;
61
62                 if (!this.$el.length)
63                         log.error("Missing-screen element.");
64
65                 // fit background image to sreen size and center
66                 this.$img = $(".splash-screen-img");
67                 if (!this.$img.length)
68                         log.warn("No background images supplied for splash screen.");
69                 this.$img.each((i, v) => adjustBackground($(v)));
70
71                 let options = this.options; // shorthand
72                 if (typeof options == "object") {
73                         // initilize global values if specfied in the config
74                         this.is_open = false;
75
76
77                         if (typeof options["active-timeout"] == "number")
78                                 this.active_timeout = options["active-timeout"];
79                         if (options.filter == true)
80                                 this.$img.addClass("filter");
81                         if (options.vignette == true)
82                                 this.$vignette = $("#vignette");
83                                 this.$vignette.show();
84                         if (typeof options.content == "object")
85                                 this.initContent(options.content);
86                         console.log("triggering ready for splash");
87                         $(this).trigger("ready");
88                 }
89
90                 /******************** Event Listeners ********************/
91                 this.clock = setInterval(() => {
92                         $(this).trigger("tick");
93
94                         if (!this.isActive())
95                                 $(this).trigger("inactive");
96                 }, 500);
97
98                 // update last active time
99                 $(this).on("active", () => this.last_active = moment());
100
101                 $(document).keyup((e) => {
102                         // handle events in seperate method
103                         this.keyHandler.call(this, e);
104                 }).keypress((e) => this.keyHandler.call(this, e));
105
106                 this.$el.click(() => {
107                         this.open();
108                 }).mousemove((e) => {
109                         if (!this.isActive())
110                                 $(this).trigger("active", e)
111                 });
112                 setTimeout(() => $(this).trigger("active"), 1);
113         }
114         /**
115          * Loops through the user specified content and adds them to the DOM in order
116          */
117         initContent(content) {
118                 for (let content_type in content) {
119                         if (content_type == "clock")
120                                 this.initClock(content[content_type]);
121                         else if (content_type == "html")
122                                 this.initHTML(content[content_type]);
123                         else
124                                 log.warn("Specified content " + content_type + " is not valid.");
125                 }
126         }
127
128         getUserOptions() {
129                 let options = {};
130                 $.extend(true, options, DEF_OPT);
131                 $.extend(true, options, {});
132                 return options;
133         }
134
135         /**
136          * open and close will toggle the screen and animate it opening and closing
137          * adds a resetTimeout function to automatically close after a period of user
138          * inactivity */
139         close(time=450)  {
140                 if (this.state == "closed" || this.state == "moving") {
141                         log.warn("Cannot close splash screen when state is: " + this.state);
142                         return;
143                 }
144
145                 this.state = "moving";
146                 this.$el.animate({
147                         top: "0",
148                         filter: "blur(20px)"
149                 }, time, "easeOutQuint", () => {
150                         this.state = "closed";
151                         clearTimeout(this.resetTimeout);
152                 });
153         }
154         open(time=400) {
155                 if (this.state == "open" || this.state == "moving") {
156                         log.warn("Cannot open splash screen when state is: " + this.state);
157                         return;
158                 }
159                 clearTimeout(this.resetTimeout);
160                 let reset_duration = 60*1000;
161
162                 if (this.state == "open" || this.state == "moving") {
163                         this.resetTimeout = setTimeout(this.reset, reset_duration);
164                         return;
165                 }
166                 this.state = "moving";
167                 this.$el.animate({
168                         top: "-100%"
169                 }, time, "easeInCirc", () => {
170                         this.state = "open";
171                         // close the screen after 1 minute of inactivty
172                         this.resetTimeout = setTimeout(() => this.reset, reset_duration);
173                 });
174         }
175         reset() {
176                 if (this.state == "open") {
177                         this.close();
178                         $(this).trigger("timeout");
179                 }
180         }
181
182         /**
183          * handles the key events for the splash
184          */
185         keyHandler(e) {
186                 switch (e.keyCode) {
187                         case 32:
188                         case 13: // Enter key
189                                 if (this.state == "closed") this.open();
190                                 break;
191                         case 27: // ESC key
192                                 if (this.state == "open") this.close();
193                                 else if (this.state == "closed") this.open();
194                                 break;
195                         default:
196                                 if (e.keyCode != 82 && e.keyCode != 17 && this.state == "closed") // for testing
197                                         this.open();
198                                 break;
199                 }
200
201                 // stop reset timeout since there has been user activity
202                 if (this.state == "open")
203                         clearTimeout(this.resetTimeout);
204
205                 if (!this.isActive())
206                         $(this).trigger("active", e);
207         }
208
209         isActive() {
210                 if (moment().diff(this.last_active, "seconds", true) > 30) {
211                         return 0;
212                 }
213                 return 1;
214         }
215
216         /**
217          *  Creates clock elements based on the usr config
218          */
219         initClock(opts) {
220                 if (typeof opts != "object") {
221                         log.error("Unable to initialize clock thats not an object");
222                         return -1;
223                 }
224                 // handle arrays and a single clock object
225                 if (!Array.isArray(opts))
226                         opts = [opts];
227
228                 for (let i in opts) {
229                         this.$clock = $("<div id='clock-" + i + "' class='clock'></div>");
230                         this.$content.append(this.$clock);
231                         this.startClock(this.$clock, opts[i]);
232                 }
233         }
234
235         /**
236          * Applys the css specfied in the argument opts to the jQuery oboject $clock.
237          * Subscribes the clock to a tick event
238          */
239         startClock($clock, opts) {
240                 if (typeof opts != "object") {
241                         log.error("Clock opts is not a valid object");
242                         return -1;
243                 }
244                 // handle multiple formats for multiple clocks on the same line
245                 if(typeof opts.format == "string")
246                         opts.format = [opts.format];
247
248                 // ensure the format is now an array
249                 if(!Array.isArray(opts.format)) {
250                         log.error(`Specfied clock format is not a valid type.
251                                 Type can be a single string or Array.`);
252                         return -1;
253                 }
254
255                 if(!Array.isArray(opts.css))
256                         opts.css = [opts.css];
257
258                 for (let i in opts.format) {
259
260                         let $format = $("<sub></sub>");
261                         // create text field in clock
262                         $clock.append($format);
263                         // apply css styles
264                         if (i < opts.css.length && typeof opts.css[i] == "object")
265                                 $format.css(opts.css[i]);
266
267                         // start clock
268                         $format.text(moment().format(opts.format[i]));
269                         $(this).on("tick", () => {
270                                 $format.text(moment().format(opts.format[i]));
271                         });
272                 }
273
274                 if (typeof opts["parent-css"] == "object")
275                         $clock.css(opts["parent-css"]);
276
277                 $clock.show();
278         }
279
280         /**
281          * Inserts HTML specified in the user config into the splash screen
282          * accepts plain strings and objects. String literals are interpreted as
283          * normal text element. Objects are set using the jQuery API
284          */
285         initHTML(opts) {
286                 // handle single objects and strings
287                 if (!Array.isArray(opts)) {
288                         opts = [opts];
289                 }
290
291                 for (let el of opts) {
292                         if (typeof el == "string") {
293                                 let $el = $("<text>");
294                                 $el.text(el);
295                                 // create simple text element
296                                 this.$content.append($el);
297                         } else if (typeof el == "object") {
298                                 // let user specify element properites in object el.
299                                 let $el = $("<div>");
300                                 for (let prop in el) {
301                                         $el[prop](el[prop]);
302                                 }
303                                 this.$content.append($el);
304
305                         } else {
306                                 log.warn("Splash screen html element is invalid type");
307                         }
308                 }
309
310         }
311 }