From: jaekuk, lee Date: Tue, 24 Oct 2017 02:35:58 +0000 (+0900) Subject: [Extension] Add App Timer extension X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F42%2F157242%2F20;p=platform%2Fframework%2Fweb%2Fcrosswalk-tizen.git [Extension] Add App Timer extension This extension sets the timer for App. version 1.0.1 Change-Id: Ibacc85fce3bbe78534ab99a4012967ddc47e72a6 Signed-off-by: jaekuk, lee --- diff --git a/wrt/wrt_support/extensions_repo/app_timer/background.js b/wrt/wrt_support/extensions_repo/app_timer/background.js new file mode 100755 index 0000000..8b08974 --- /dev/null +++ b/wrt/wrt_support/extensions_repo/app_timer/background.js @@ -0,0 +1,102 @@ +var js = document.createElement("script"); +js.type = "text/javascript"; +js.src = "lib/clock.js"; +document.body.appendChild(js); + +var TimerState = { + time: { + hours: 0, + minutes: 1, + seconds: 0 + }, + displayTime: { + hours: '00', + minutes: '01', + seconds: '00', + }, + defaultTime: { + hours: 0, + minutes: 1, + seconds: 0 + }, + defaultDisplayTime: { + hours: '00', + minutes: '01', + seconds: '00', + } +}; + +var thisclock; + +chrome.runtime.onConnect.addListener(function(port) { + + (function () { + thisclock = new Clock({ + second: function (clock) { + update(clock); + }, + finish: function (clock) { + port.postMessage({background: "timer-finish"}); + } + }); +})(); + + + function init() { + port.postMessage({background: "timer-init", value:TimerState}); + } + + function reset() { + TimerState.time = TimerState.defaultTime; + update(TimerState.time); + } + + function setTime(time) { + if (time.hours != TimerState.time.hours || + time.minutes != TimerState.time.minutes || + time.seconds != TimerState.time.seconds) { + TimerState.defaultTime = time; + TimerState.defaultDisplayTime = _getDisplayableTime(time); + } + TimerState.time = time; + TimerState.displayTime = _getDisplayableTime(time); + } + + function _getDisplayableTime(time) { + var dh = (time.hours < 10 ? '0' : '') + String(time.hours), + dm = (time.minutes < 10 ? '0' : '') + String(time.minutes), + ds = (time.seconds < 10 ? '0' : '') + String(time.seconds) + return {hours: dh, minutes: dm, seconds: ds}; + } + + function start() { + thisclock.start(TimerState.time.hours, TimerState.time.minutes, TimerState.time.seconds); + } + + function stop() { + thisclock.stop(); + } + + function update(time) { + setTime(time); + port.postMessage({background: "timer-update", value:TimerState}); + } + + port.onMessage.addListener(function(msg) { + if (msg.contentscript == "timer-init") { + init(); + } + else if (msg.contentscript == "timer-start") { + start(); + } + else if (msg.contentscript == "timer-stop") { + stop(); + } + else if (msg.contentscript == "timer-reset") { + reset(); + } + else if (msg.contentscript == "timer-setTime") { + setTime(msg.value); + } + }); +}); diff --git a/wrt/wrt_support/extensions_repo/app_timer/contentscript.js b/wrt/wrt_support/extensions_repo/app_timer/contentscript.js new file mode 100755 index 0000000..f8a5040 --- /dev/null +++ b/wrt/wrt_support/extensions_repo/app_timer/contentscript.js @@ -0,0 +1,267 @@ +const EXIT_HTML = '\ +
\ +\ +
\ +\ +

Exit App?

\ +
\ + \ +
\ +
\ + \ + \ +
\ +\ +
\ +\ +
'; +//" + +const SET_HTML = '\ +
\ +\ +
\ +\ +
'; +//" + +var timerStart = false; +var defaultDisplayTime = {hours: 0, minutes: 1, seconds: 0}; +var f1Key = false; +var port = chrome.runtime.connect({name: "contentscript"}); + +port.onMessage.addListener(function(msg) { + console.log('from background : ' + msg.background); + if (msg.background == "timer-init") { + setTime(msg.value); + } + else if (msg.background == "timer-update") { + console.log('value, '+msg.value.displayTime.hours+' : '+msg.value.displayTime.minutes+' : '+msg.value.displayTime.seconds); + setTime(msg.value); + } + else if (msg.background == "timer-finish") { + exitPopup(); + } +}); + +document.body.insertAdjacentHTML('beforeend', SET_HTML); +initialize(); + +function exitPopup() { + hideModal(); + document.body.insertAdjacentHTML('beforeend', EXIT_HTML); + + document.getElementById('yes-button').onclick= function(event) { + console.log('exitPopup: yes'); + reset(); + stop(); + var launcher = require('electron').remote.getCurrentWindow(); + launcher.close(); + }; + + document.getElementById('no-button').onclick= function(event) { + console.log('exitPopup: no'); + document.body.removeChild(document.getElementById('exit-popup')); + document.getElementById('hours-digit').innerHTML = defaultDisplayTime.hours; + document.getElementById('minutes-digit').innerHTML = defaultDisplayTime.minutes; + document.getElementById('seconds-digit').innerHTML = defaultDisplayTime.seconds; + reset(); + start(); + }; +} + +window.onkeydown = function(event) { + if (event.keyCode != 112) // F1 key + return; + if (f1Key) { + hideModal(); + f1Key = false ; + } else { + showModal(); + f1Key = true ; + } +} + +function initialize() { + port.postMessage({contentscript: "timer-init"}); + if (!timerStart) { + pauseMode(); + } else { + runningMode(); + } + bindAll(); +} + +function showModal() { + document.getElementById('main-popup').style.display = 'block'; +} + +function hideModal() { + document.getElementById('main-popup').style.display = 'none'; +} + +function bindAll() { + document.getElementById('sme_switch').addEventListener("change", function(event){ + if(event.srcElement.checked){ + document.querySelector(".action").style.display = "block"; + } else{ + reset(); + stop(); + document.querySelector(".action").style.display = "none"; + }; + }); + + document.getElementById('start-button').onclick= function(event) { + if (timerStart == false) { + start(); + } else { + stop(); + } + }; + + document.getElementById('reset-button').onclick= function(event) { + if (!timerStart) { + reset(); + } + }; + + document.getElementById('hours-digit').onclick= function(event) { + event.stopPropagation(); + if (timerStart) + return; + document.getElementById('hours-digit').setAttribute("contenteditable", true); + document.getElementById('hours-digit').addEventListener('mouseout', hoursMouseoutHandler ); + }; + +function hoursMouseoutHandler(e){ + document.getElementById('hours-digit').removeEventListener('mouseout', hoursMouseoutHandler); + var value = document.getElementById('hours-digit').innerHTML; + if (value.length == 0 || Number(value) == 0) { + document.getElementById('hours-digit').innerHTML = '00'; + } else if (!/^[0-9]{1,2}$/.test(value)) { + value = value.replace(/[^0-9]/,'').substr(0,2); + document.getElementById('hours-digit').innerHTML = value; + } else { + value = ((Number(value) < 10) ? '0' : '') + Number(value); + document.getElementById('hours-digit').innerHTML = value; + } + } + + document.getElementById('minutes-digit').onclick= function(event) { + event.stopPropagation(); + if (timerStart) + return; + document.getElementById('minutes-digit').setAttribute("contenteditable", true); + document.getElementById('minutes-digit').addEventListener('mouseout', minutesMouseoutHandler ); + }; + + function minutesMouseoutHandler(e){ + document.getElementById('minutes-digit').removeEventListener('mouseout', minutesMouseoutHandler); + var value = document.getElementById('minutes-digit').innerHTML; + if (value.length == 0 || Number(value) == 0) { + document.getElementById('minutes-digit').innerHTML = '00'; + } else if (!/^[0-9]{1,2}$/.test(value)) { + value = value.replace(/[^0-9]/,'').substr(0,2); + document.getElementById('minutes-digit').innerHTML = value; + } else { + value = ((Number(value) < 10) ? '0' : '') + Number(value); + document.getElementById('minutes-digit').innerHTML = value; + } + } + + document.getElementById('seconds-digit').onclick= function(event) { + event.stopPropagation(); + if (timerStart) + return; + document.getElementById('seconds-digit').setAttribute("contenteditable", true); + document.getElementById('seconds-digit').addEventListener('mouseout', secondsMouseoutHandler ); + }; + + function secondsMouseoutHandler(e){ + document.getElementById('seconds-digit').removeEventListener('mouseout', secondsMouseoutHandler); + var value = document.getElementById('seconds-digit').innerHTML; + if (value.length == 0 || Number(value) == 0) { + document.getElementById('seconds-digit').innerHTML = '00'; + } else if (!/^[0-9]{1,2}$/.test(value)) { + value = value.replace(/[^0-9]/,'').substr(0,2); + document.getElementById('seconds-digit').innerHTML = value; + } else { + value = ((Number(value) < 10) ? '0' : '') + Number(value); + document.getElementById('seconds-digit').innerHTML = value; + } + } +} + +function start() { + timerStart = true; + var time = {hours: 0, minutes: 0, seconds: 0}; + time.hours = Number(document.getElementById('hours-digit').innerHTML); + time.minutes = Number(document.getElementById('minutes-digit').innerHTML); + time.seconds = Number(document.getElementById('seconds-digit').innerHTML); + console.log('start, '+time.hours+' : '+time.minutes+' : '+time.seconds); + if (time.hours + time.minutes + time.seconds > 0) { + runningMode(); + port.postMessage({contentscript: "timer-setTime", value:time}); + port.postMessage({contentscript: "timer-start"}); + } +} + +function reset() { + port.postMessage({contentscript: "timer-reset"}); +} + +function stop() { + timerStart = false; + pauseMode(); + port.postMessage({contentscript: "timer-stop"}); +} + +function setTime(time) { + console.log('setTime, '+time.displayTime.hours+' : '+time.displayTime.minutes+' : '+time.displayTime.seconds); + document.getElementById('hours-digit').innerHTML = time.displayTime.hours; + document.getElementById('minutes-digit').innerHTML = time.displayTime.minutes; + document.getElementById('seconds-digit').innerHTML = time.displayTime.seconds; + defaultDisplayTime.hours = time.defaultDisplayTime.hours; + defaultDisplayTime.minutes = time.defaultDisplayTime.minutes; + defaultDisplayTime.seconds = time.defaultDisplayTime.seconds; +} + +function runningMode() { + document.getElementById('start-button').innerHTML = 'stop'; +} + +function pauseMode() { + document.getElementById('start-button').innerHTML = 'start'; +} diff --git a/wrt/wrt_support/extensions_repo/app_timer/icon.png b/wrt/wrt_support/extensions_repo/app_timer/icon.png new file mode 100755 index 0000000..5515365 Binary files /dev/null and b/wrt/wrt_support/extensions_repo/app_timer/icon.png differ diff --git a/wrt/wrt_support/extensions_repo/app_timer/images/exit.png b/wrt/wrt_support/extensions_repo/app_timer/images/exit.png new file mode 100755 index 0000000..6500ffd Binary files /dev/null and b/wrt/wrt_support/extensions_repo/app_timer/images/exit.png differ diff --git a/wrt/wrt_support/extensions_repo/app_timer/lib/clock.js b/wrt/wrt_support/extensions_repo/app_timer/lib/clock.js new file mode 100755 index 0000000..533642b --- /dev/null +++ b/wrt/wrt_support/extensions_repo/app_timer/lib/clock.js @@ -0,0 +1,187 @@ +// a simple countdown clock. + +(function (window, undefined) { +'use strict'; + +var TIMER_FINISHED = 0, + TIMER_RUNNING = 1, + TIMER_PAUSED = 2, + ticks_per_second = 5, + cb, + callbacks = ['tick', 'second', 'finish'], + debug = function (message) { + if (window.console !== undefined && window.console.log !== undefined && window.DEBUG) { + window.console.log.apply(window.console, arguments); + } + }, + error = function (message) { + if (window.console !== undefined && window.console.error !== undefined) { + window.console.error.apply(window.console, arguments); + } + }; + +/*** + * Constructor. + * + * Takes callbacks object. + * + * callbacks can be: + * tick: function (clock) {} + * called on every tick. up to 5 times per second if tab is in the + * foreground, probably zero to one times per second if tab is + * backgrounded. + * + * second: function (clock) {} + * called at most once per second, but time between calls may be greater if + * tab is backgrounded or browser gets lazy or busy. + * + * finish: function (clock) {} + * called once when the clock finishes counting down. + */ +var Clock = function (callbacks) { + this.callbacks = (callbacks || {}); + this.status = TIMER_PAUSED; +}; + +/*** + * private: + * + * step forwards through time, one tick at a ... time + */ +Clock.prototype.next_tick = function () { + if (!(this.status === TIMER_FINISHED || this.status === TIMER_PAUSED)) { + var self = this; + + this.timeout = window.setTimeout(function () { self.next_tick() }, 1000 / ticks_per_second); + this.call_tick(); + this.countdown(); + } +} + +/*** + * private: + * + * populate zero padded strings version of time + */ +Clock.prototype.zero_pad = function () { + this.zero_padded = (this.zero_padded || {}); + this.zero_padded.hours = (this.hours < 10 ? '0' : '') + String(this.hours); + this.zero_padded.minutes = (this.minutes < 10 ? '0' : '') + String(this.minutes); + this.zero_padded.seconds = (this.seconds < 10 ? '0' : '') + String(this.seconds); + + // dupe property for camel-casers + this.zeroPadded = this.zero_padded; + + return this.zero_padded; +} + +/** + * private: + * + * generate the callback calling functions with appropriate error handling. + */ +for (var i=0; i < 3; i++) { + cb = callbacks[i]; + Clock.prototype['call_' + cb] = (function (callbackType) { + return function () { + try { + if (this.callbacks[callbackType] !== undefined) + this.callbacks[callbackType](this); + } catch (ex) { + // don't crash because of lame callbacks + error('[clock.js] Failed ' + callbackType + ' callback!', ex.message) + } + }; + })(cb); +} + +/*** + * private: + * + * run every tick, check to see whether a second has passed + */ +Clock.prototype.countdown = function () { + var whole_minutes, elapsed_seconds = Math.floor((new Date().getTime() - this.start_time) / 1000); + + // how much time has actually passed + this.remaining_seconds = this.requested_seconds - elapsed_seconds; + + // separate remaining_seconds into time components + this.seconds = this.remaining_seconds % 60; + whole_minutes = Math.floor(this.remaining_seconds / 60); + this.minutes = whole_minutes % 60; + this.hours = Math.floor(whole_minutes / 60); + + this.zero_pad(); + + // at least a second has passed, trigger callbacks + if (this.seconds != this.previous.seconds || this.minutes != this.previous.minutes || this.hours != this.previous.hours) { + if (this.hours <= 0 && this.minutes <= 0 && this.seconds <= 0) { + this.call_second(); + this.call_finish(); + this.stop(); + } else { + // call second callback + this.call_second(); + } + + this.previous = { + hours: this.hours, + minutes: this.minutes, + seconds: this.seconds + } + } +} + +/*** + * Start the clock. + */ +Clock.prototype.start = function (hours, minutes, seconds) { + this.hours = hours || 0; + this.minutes = minutes || 0; + this.seconds = seconds || 0; + + debug( + "[clock.js] starting clock at " + + this.hours + ":" + + this.minutes + ":" + + this.seconds + ); + + // make sure we can check when the clock has rolled over + this.previous = {h: 0, m: 0, s: 0}; + + // total countown seconds + this.remaining_seconds = this.hours * 3600 + this.minutes * 60 + this.seconds; + this.requested_seconds = this.remaining_seconds; + + // clock is now in a prepared-but-paused state, we just have to unpause + this.unpause(); +} + +Clock.prototype.unpause = function () { + this.running = true; + this.status = TIMER_RUNNING; + this.start_time = new Date().getTime(); + + // set requested_seconds to remaining so that unpausing doesn't reset the clock + this.requested_seconds = this.remaining_seconds; + + this.next_tick(); +} + +/*** + * Stop the clock. + */ +Clock.prototype.stop = function () { + this.status = TIMER_PAUSED; + this.running = false; +} + +// alias `stop` to `pause` +Clock.prototype.pause = Clock.prototype.stop; + +window.Clock = Clock; + +})(window); + diff --git a/wrt/wrt_support/extensions_repo/app_timer/manifest.json b/wrt/wrt_support/extensions_repo/app_timer/manifest.json new file mode 100755 index 0000000..eb5907b --- /dev/null +++ b/wrt/wrt_support/extensions_repo/app_timer/manifest.json @@ -0,0 +1,15 @@ +{ + "name": "app_timer", + "version": "1.0.1", + "manifest_version": 1, + "background": { + "scripts": ["background.js"] + }, + "content_scripts": [ + { + "matches": [""], + "js": ["contentscript.js"], + "css": ["style.css"] + } + ] +} diff --git a/wrt/wrt_support/extensions_repo/app_timer/style.css b/wrt/wrt_support/extensions_repo/app_timer/style.css new file mode 100755 index 0000000..d1fb9bc --- /dev/null +++ b/wrt/wrt_support/extensions_repo/app_timer/style.css @@ -0,0 +1,240 @@ +/*----------------------------------------------------*/ +#main-popup { + display: none; /* Hidden by default */ + position: fixed; + z-index: 1; /* Sit on top */ + left: 0; + top: 0; + width: 100%; /* Full width */ + height: 100%; /* Full height */ + overflow: auto; /* Enable scroll if needed */ + background-color: rgb(0,0,0); /* Fallback color */ + background-color: rgba(0,0,0,0.4); /* Black w/ opacity */ +} +#popup-container { + margin: auto; + margin-top: 20%; + border: 1px solid #888; + height: auto; + width: 350px; + background-color: rgb(255,255,255); +} +#title { + line-height: 24px; + font-weight: bold; + text-shadow:0 0 10px white; + position: relative; + margin-top: 5%; +} +.line { + width:90%; + height: 1%; + border-top: 1px solid rgba(175, 154, 110, 0.51); + padding: 0 0 5px; + position: relative; + margin-top: 5%; +} +/*----------------------------------------------------*/ +.switch { + position: relative; + display: inline-block; + vertical-align: top; + width: 85px; + height: 30px; + padding: 3px; + background-color: white; + border-radius: 18px; + box-shadow: inset 0 -1px white, inset 0 1px 1px rgba(0, 0, 0, 0.05); + cursor: pointer; + background-image: -webkit-linear-gradient(top, #eeeeee, white 25px); + background-image: -moz-linear-gradient(top, #eeeeee, white 25px); + background-image: -o-linear-gradient(top, #eeeeee, white 25px); + background-image: linear-gradient(to bottom, #eeeeee, white 25px); +} +.switch .switch_input { + position: absolute; + top: 0; + left: 0; + opacity: 0; +} +.switch .switch_label { + position: relative; + display: block; + height: inherit; + font-size: 15px; + text-transform: uppercase; + background: #FF5D1F; + border-radius: inherit; + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.12), inset 0 0 2px rgba(0, 0, 0, 0.15); + -webkit-transition: 0.15s ease-out; + -moz-transition: 0.15s ease-out; + -o-transition: 0.15s ease-out; + transition: 0.15s ease-out; + -moz-transition-property: opacity background; + -o-transition-property: opacity background; +} +.switch .switch_label:before, .switch_label:after { + position: absolute; + top: 50%; + margin-top: -.5em; + line-height: 1; + -webkit-transition: inherit; + -moz-transition: inherit; + -o-transition: inherit; + transition: inherit; +} +.switch .switch_label:before { + content: attr(data-off); + right: 11px; + color: white; + text-shadow: 0 1px rgba(255, 255, 255, 0.5); +} +.switch .switch_label:after { + content: attr(data-on); + left: 11px; + color: white; + text-shadow: 0 1px rgba(0, 0, 0, 0.2); + opacity: 0; +} +.switch .switch_input:checked ~ .switch_label { + background: #47a8d8; + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15), inset 0 0 3px rgba(0, 0, 0, 0.2); +} +.switch .switch_input:checked ~ .switch_label:before { + opacity: 0; +} +.switch .switch_input:checked ~ .switch_label:after { + opacity: 1; +} +.switch .switch_handle { + position: absolute; + top: 5px; + left: 4px; + width: 35px; + height: 26px; + background: white; + border-radius: 10px; + box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.2); + background-image: -webkit-linear-gradient(top, white 40%, #f0f0f0); + background-image: -moz-linear-gradient(top, white 40%, #f0f0f0); + background-image: -o-linear-gradient(top, white 40%, #f0f0f0); + background-image: linear-gradient(to bottom, white 40%, #f0f0f0); + -webkit-transition: left 0.15s ease-out; + -moz-transition: left 0.15s ease-out; + -o-transition: left 0.15s ease-out; + transition: left 0.15s ease-out; +} +.switch .switch_handle .switch_pix{ + content: ''; + position: absolute; + top: 50%; + left: 50%; + margin: -6px 0 0 -6px; + width: 12px; + height: 12px; + background: #f9f9f9; + border-radius: 6px; + box-shadow: 0px 0px 15px #D5D5D5; + background-color: #FF5D1F; +} +.switch .switch_input:checked ~ .switch_handle { + left: 51px; + box-shadow: -1px 1px 5px rgba(0, 0, 0, 0.2); +} +.switch .switch_input:checked ~ .switch_handle .switch_pix{ + content: ''; + position: absolute; + top: 50%; + left: 50%; + margin: -6px 0 0 -6px; + width: 12px; + height: 12px; + background: #f9f9f9; + border-radius: 6px; + box-shadow: 0px 0px 15px #D5D5D5; + background-color: #4fb845; +} +.switch > .switch_input:checked ~ .switch_label { + background: #4fb845; +} +/*----------------------------------------------------*/ +.action { + display: block; + position: relative; +} +/*----------------------------------------------------*/ +.timer-group { + margin-top: 5%; +} +.editable { + display: inline-block; + font-size: 80px; + overflow: hidden; + white-space: nowrap; + cursor: pointer; +} +.editable:focus { + outline: none; +} +.colon { + display: inline-block; + font-size: 70px; + vertical-align: top; +} +.digit { + vertical-align: middle; +} +/*----------------------------------------------------*/ +.btn-group { + margin-top: 25%; + margin-bottom: 10%; +} +.button { + width: 100px; + height: 50px; + font-size: 30px; + margin-left: 5%; + margin-right: 5%; + cursor: pointer; +} +/*----------------------------------------------------*/ +/*----------------------------------------------------*/ +#exit-popup { + position: fixed; + z-index: 1; /* Sit on top */ + left: 0; + top: 0; + width: 100%; /* Full width */ + height: 100%; /* Full height */ + overflow: auto; /* Enable scroll if needed */ + background-color: rgb(0,0,0); /* Fallback color */ + background-color: rgba(0,0,0,0.4); /* Black w/ opacity */ +} +#exit-popup-container { + margin: auto; + margin-top: 20%; + border: 1px solid #888; + height: auto; + width: 350px; + background-color: rgb(255,255,255); +} +#exit-title { + line-height: 24px; + font-weight: bold; + text-shadow:0 0 10px white; + position: relative; + margin-top: 5%; +} +/*----------------------------------------------------*/ +.exit-button-group { + margin-top: 25%; + margin-bottom: 10%; +} +.exit-button { + width: 100px; + height: 50px; + font-size: 30px; + margin-left: 5%; + margin-right: 5%; + cursor: pointer; +} \ No newline at end of file