3 * Creates a splash screen with custom generated content,
4 * diplays when the user inactive.
6 * A Plugin for the LoginManager class
9 * -----------------------------------------------------------------------------
11 * 'load' signifies that SplashScreen has finished asyncrhonously
12 * loading its config files.
14 * 'ready' emitted once the SplashScreen has finished creating its content
17 * 'init' causes the SplashScreen content to be generated
21 if (window.navigator.language === "en" || window.navigator.language === "en-US" ||window.navigator.language === "fr" ||window.navigator.language === "es-ES" ) {
22 text[0]="Press any key to login"
23 text[1]="Welcome Back"
24 text[2]="Select Session"
29 text[0]="任意のキーを押すとログインできます。"
35 document.onkeydown = function (e){
36 document.getElementById("inputPassword").focus();
38 selectSession = LocalStorage.getItem('access_count');
39 selectSession = window.LocalStorage.getItem('access_count');
40 selectSession = LocalStorage.access_count
44 /* Speed of SplashScreen transitions */
45 this._ANIMATION_DUR = 300;
47 /* Default options for the splash screen */
57 // "format": "dddd, MMMM Do",
62 // "margin-top": "calc(20vh - 70pt)",
63 // "text-align": "center",
64 // "font-size": "70pt",
65 // "font-family": "Noto Sans",
66 // "font-weight": "lighter",
67 // "text-shadow": "rgba(0, 0, 0, 0.25) 0px 3px 3px",
70 "format": ["h:mm", "A"],
72 {"font-size": "65pt", "font-weight": 200 },
73 {"font-size": "30pt", "font-weight": "lighter", "margin-left": "10pt"}
78 "font-family": "MyFont",
79 "text-align": "center",
80 "text-shadow": "rgba(0, 0, 0, 0.25) 0px 3px 3px",
85 "html":"<text style='display: none' class='active-appear'>"+text[0]+"</text>",
90 "text-align": "center",
91 "color": "rgba(255, 255, 255, 0.8)"
96 this.template = `<!-- Autogenerated SplashScreen -->
97 <div id="splash-screen">
98 <div class="vignette"></div>
99 <div id="splash-screen-content"></div>
101 <!-- End Autogenerated SplashScreen -->`;
102 this.$el = $(this.template);
103 $("body").prepend(this.$el);
106 // listen to the init event
107 $(this).on("init", () => this._init());
111 * Generates the content specified by the user config.
112 * Should be called after the load event has been triggered.
115 this.$content = $("#splash-screen-content");
116 this._state = "closed";
117 this._last_active = 0;
118 this._active_timeout = 15;
120 let options = this._options; // shorthand
121 if (typeof options == "object") {
123 // initilize global values if specfied in the config
124 if (typeof options.img == "string") {
125 this.$img = $(`<img class="splash-screen-img" src="${options.img}">`);
127 this.$el.prepend(this.$img);
128 this.$img.one("load", () => {
129 // fit background image to sreen size and center
130 adjustBackground($(".splash-screen-img"))
134 if (typeof options["active-timeout"] == "number")
135 this._active_timeout = options["active-timeout"];
137 if (options.filter == true)
138 this.$img.addClass("filter");
140 if (options.vignette == true) {
141 this.$vignette = $("#vignette");
142 this.$vignette.show();
145 if (typeof options.transition == "string")
146 this.transition = options.transition;
148 if (typeof options.content == "object")
149 this._initContent(options.content);
151 $(this).trigger("ready");
154 /******************** Event Listeners ********************/
155 this.clock = setInterval(() => {
156 $(this).trigger("tick");
158 if (!this._isActive())
159 $(this).trigger("inactive");
162 // update last active time
163 $(this).on("active", () => this._last_active = moment());
165 $(document).keyup((e) => {
166 // handle events in seperate method
167 this._keyHandler.call(this, e);
168 }).keypress((e) => this._keyHandler.call(this, e));
170 /* Bind event listners to trigger activity event. This can be used on the
171 front end to implement spcific behaivours while the user is active */
172 this.$el.click(() => {
174 }).mousemove((e) => {
175 if (!this._isActive())
176 $(this).trigger("active", e)
178 setTimeout(() => $(this).trigger("active"), 1);
182 * Loops through the user specified content and appends them to the DOM
183 * in the order specified by the user config
185 _initContent(content) {
186 for (let content_type in content) {
187 if (content_type == "clock")
188 this._initClock(content[content_type]);
189 else if (content_type == "html")
190 this._initHTML(content[content_type]);
192 log.warn("Specified content " + content_type + " is not valid.");
197 * Asyncrhonously reads JSON config file from json/SplashScreen.json
198 * and overwrites the default options with those specified by the config.
200 * Triggers: 'load' on completion. Caller (LoginManager) must listen for this
201 * event to then trigger 'init'
205 $.extend(true, options, this._DEF_OPT);
207 $.getJSON("json/SplashScreen.json", (data) => {
208 $.extend(true, options, data);
209 this._options = options;
210 $(this).trigger("load");
212 $.extend(true, options, {});
213 this._options = options;
214 $(this).trigger("load");
219 * Closes the splash screen if there has been no user activity
222 if (this._state == "open") {
224 $(this).trigger("timeout");
229 * Determines if there was user acitivty within in a given amount
231 * Returns 1 if splash screen is active, else 0
234 if (moment().diff(this._last_active, "seconds", true) > 30) {
241 * Creates clock elements based on the usr config.
242 * Appends each clock to the DOM and binds update events using _startClock
245 if (typeof opts != "object") {
246 log.error("Unable to initialize clock thats not an object");
249 // handle arrays and a single clock object
250 if (!Array.isArray(opts))
253 /* loop through each clock in the config and add it to the dom,
254 then initialize an update event using start clock */
255 for (let i in opts) {
256 this.$clock = $("<div id='clock-" + i + "' class='clock'></div>");
257 this.$content.append(this.$clock);
258 this._startClock(this.$clock, opts[i]);
263 * Applys the css specfied in the argument opts to the jQuery oboject $clock.
264 * Subscribes the clock to a tick event
266 _startClock($clock, opts) {
267 if (typeof opts != "object") {
268 log.error("Clock opts is not a valid object");
271 // handle multiple formats for multiple clocks on the same line
272 if(typeof opts.format == "string")
273 opts.format = [opts.format];
275 // ensure the format is now an array
276 if(!Array.isArray(opts.format)) {
277 log.error(`Specfied clock format is not a valid type.
278 Type can be a single string or Array.`);
282 if(!Array.isArray(opts.css))
283 opts.css = [opts.css];
285 for (let i in opts.format) {
287 let $format = $("<sub></sub>");
288 // create text field in clock
289 $clock.append($format);
291 if (i < opts.css.length && typeof opts.css[i] == "object")
292 $format.css(opts.css[i]);
295 $format.text(moment().format(opts.format[i]));
296 $(this).on("tick", () => {
297 $format.text(moment().format(opts.format[i]));
301 if (typeof opts["parent-css"] == "object")
302 $clock.css(opts["parent-css"]);
308 * Inserts HTML specified in the user config into the splash screen
309 * accepts plain strings and objects. String literals are interpreted as
310 * normal text element. Objects are set using the jQuery API
313 // handle single objects and strings
314 if (!Array.isArray(opts)) {
318 for (let el of opts) {
319 if (typeof el == "string") {
320 let $el = $("<text>");
322 // create simple text element
323 this.$content.append($el);
324 } else if (typeof el == "object") {
325 // let user specify element properites in object el.
326 let $el = $("<div>");
327 for (let prop in el) {
330 this.$content.append($el);
333 log.warn("Splash screen html element is invalid type");
340 * Handles the key events for the SplachScreen and active-inactive events
345 case 13: // Enter key
346 if (this._state == "closed")
350 if (this._state == "open")
352 else if (this._state == "closed")
356 if (this._state == "closed")
361 // stop reset timeout since there has been user activity
362 if (this._state == "open")
363 clearTimeout(this.resetTimeout);
365 // trigger active event if the user has been inactive long enough
366 if (!this._isActive())
367 $(this).trigger("active", e);
371 * _open and _close will toggle the screen and animate it opening and closing
372 * adds a resetTimeout function to automatically close after a period of user
375 * Uses a _state machine consisting of {'open', 'closed', 'moving'}.
376 * Transitions are not possible while the _state == moving. This prevents
377 * fillUserSelect from trigger concurrernt transitions which would lead to
378 * undefined behaivour.
381 if (this._state != "open") {
382 log.warn("Cannot close splash screen when _state is: " + this._state);
386 this._state = "moving";
387 if (this.transition == "fade") {
388 this.$el.fadeIn("slow", () => {
389 this._state = "closed";
390 this.$content.fadeIn("slow");
391 clearTimeout(this.resetTimeout);
393 } else if (this.transition == "slide") {
396 },"slow", "easeOutQuint", () => {
397 this._state = "closed";
398 clearTimeout(this.resetTimeout);
405 if (this._state != "closed") {
406 log.warn("Cannot open splash screen when _state is: " + this._state);
409 clearTimeout(this.resetTimeout);
410 let reset_duration = 60*1000;
412 if (this._state == "open" || this._state == "moving") {
413 this.resetTimeout = setTimeout(this.reset, reset_duration);
416 this._state = "moving";
418 if (this.transition == "fade") {
419 this.$content.fadeOut("fast", () => {
420 this.$el.fadeOut(this._ANIMATION_DUR, () => {
421 this._state = "open";
425 } else if (this.transition == "slide") {
428 }, "slow", "easeInCubic", () => {
429 this._state = "open";