I help manage an escape room and what we are looking to do is to create a digital timer using a second computer monitor. A local web page will be displayed on the in-room monitor that has a countdown timer.
My main question is how can I control that clock from a different internal web page using html and javascipt or whatever you think would be the best solution? Thanks!
<! doctype html>
<head>
<title></title>
<style>
div.timer {
height:400px;
font-size:160px;
font-family:"Erbos Draco 1st Open NBP";
text-align:center;
margin:5px;
color:white;
}
.control{width: 400px;margin:auto}
body{background-color:black;}
button{
-webkit-appearance: none;
border: none;
border-radius: 5px;
padding: 10px;
color:white;
width:120px
}
button#start {background-color:green}
button#pause {background-color:orange}
button#reset {background-color:red}
</style>
<link rel="stylesheet" type="text/css" href="animate.css"/>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="HackTimer.js"></script>
</head>
<body>
<div id="timer" class="timer animated fadeIn">
<span class="hour">01</span><span id="colon">:</span><span class="minute">00</span><span id="colon2">:</span><span class="second">00</span> <span id="seconds" style="display:none">seconds</span><span class="timesup" style="display:none">Time is up!</span>
</div>
<div class="control">
<button id="start" onClick="timer.start(1000)">Start</button>
<button id="pause" onClick="timer.stop()">Pause</button>
<button id="reset" onClick="timer.reset(65)">Reset to 1 Hour</button>
</div>
<script>
function _timer(callback)
{
var time = 0; // The default time of the timer
var mode = 1; // Mode: count up or count down
var status = 0; // Status: timer is running or stoped
var timer_id; // This is used by setInterval function
// this will start the timer ex. start the timer with 1 second interval timer.start(1000)
this.start = function(interval)
{
interval = (typeof(interval) !== 'undefined') ? interval : 1000;
if(status == 0)
{
status = 1;
timer_id = setInterval(function()
{
switch(mode)
{
default:
if(time)
{
time--;
generateTime();
if(typeof(callback) === 'function') callback(time);
}
break;
case 1:
if(time < 86400)
{
time++;
generateTime();
if(typeof(callback) === 'function') callback(time);
}
break;
}
}, interval);
}
}
// Same as the name, this will stop or pause the timer ex. timer.stop()
this.stop = function()
{
if(status == 1)
{
status = 0;
clearInterval(timer_id);
}
}
// Reset the timer to zero or reset it to your own custom time ex. reset to zero second timer.reset(0)
this.reset = function(sec)
{
sec = (typeof(sec) !== 'undefined') ? sec : 0;
time = sec;
generateTime(time);
}
// Change the mode of the timer, count-up (1) or countdown (0)
this.mode = function(tmode)
{
mode = tmode;
}
// This methode return the current value of the timer
this.getTime = function()
{
return time;
}
// This methode return the current mode of the timer count-up (1) or countdown (0)
this.getMode = function()
{
return mode;
}
// This methode return the status of the timer running (1) or stoped (1)
this.getStatus
{
return status;
}
// This methode will render the time variable to hour:minute:second format
function generateTime()
{
//var millisecond = Math.floor(time / 60) % 60;
var second = time % 60;
var minute = Math.floor(time / 60) % 60;
var hour = Math.floor(time / 3600) % 60;
//millisecond = (millisecond < 10) ? '0'+millisecond : millisecond;
second = (second < 10) ? '0'+second : second;
minute = (minute < 10) ? '0'+minute : minute;
hour = (hour < 10) ? '0'+hour : hour;
//$('div.timer span.milliseconds').html(millisecond);
$('div.timer span.second').html(second);
$('div.timer span.minute').html(minute);
$('div.timer span.hour').html(hour);
document.title = hour + ':' + minute + ':' + second + ' remaining';
}
}
// example use
var timer;
$(document).ready(function(e)
{
timer = new _timer
(
function(time)
{
if(time <= 3600)
{
//$('span.hour').hide();
//$('span#colon').hide();
}
if(time >= 60)
{
$('div.timer').css('color','#32CD32');
}
if(time < 60)
{
$('span#seconds').hide();
$('span.milliseconds').show();
$('div#timer').removeClass('tada');
$('div#timer').addClass('fast');
$('div.timer').css('color','yellow');
$('span.timesup').hide();
$('span.minute').show();
$('span#colon2').show();
$('span.second').show();
$('span.milliseconds').show();
$('span.hour').show();
$('span#colon').show();
$('div#timer').css('margin','5px');
$('div#timer').css('font-size','160px');
}
if(time == 0)
{
timer.stop();
$('div.timer').css('color','red');
$('span.timesup').show();
$('span.minute').hide();
$('span#colon2').hide();
$('span.second').hide();
$('span.milliseconds').hide();
$('span.hour').hide();
$('span#colon').hide();
$('div#timer').css('font-size','100px');
}
}
);
timer.reset(0);
timer.mode(0);
});
</script>
</body>
</html>
Screenshot:
Related
I have a countdown timer:
interval;
timeJump: number = 10;
timeLength: number = 5;
timerLeft: number = this.timeLength;
startTimer() {
this.interval = setInterval(() => {
if (this.timerLeft - this.timeJump / 1000 <= 0) {
this.timerLeft = 0;
clearInterval(this.interval);
return;
setTimeout(() => this.finishedTimer(), 500);
} else {
this.timerLeft -= this.timeJump / 1000;
}
}, this.timeJump);
}
I am calling the startTimer() function in ngOnInit(), and it is running.
In the html template I have a progress bar:
<div class="progress-wrapper" style="height: 4%;">
<mat-progress-bar id="timer" mode="determinate" value="{{(timerLeft/timeLength) * 100}}"
style="height: 100%;"></mat-progress-bar>
</div>
When the timer reaches the end, about the last 10%, it goes down in value a lot quicker than it should.
Can you help me fix this?
Thanks
Is this a problem? Work perfect for me!
(except for setTimeout(() => this.finishedTimer(), 500); after return; never be used)
But, you can use RxJs for that!
HTML
<mat-progress-bar mode="determinate" [value]="progressbarValue"></mat-progress-bar>
TS
import { interval } from 'rxjs';
...
progressbarValue = 100;
curSec: number = 0;
startTimer(seconds: number) {
const time = seconds;
const timer$ = interval(1000);
const sub = timer$.subscribe((sec) => {
this.progressbarValue = 100 - sec * 100 / seconds;
this.curSec = sec;
if (this.curSec === seconds) {
sub.unsubscribe();
}
});
}
And call startTime method with progress bar timeout.
startTimer(120) // 120 seconds
References: https://stackblitz.com/edit/angular-material-progress-bar-decrease
I fixed it!
The problem was I was using too short of an interval. The progress bar couldn't keep up with the speed. Set the interval to whatever you want, but always round the value you put in the value of the progress bar to a whole number, like this:
timeLeft | number : '1.0-0'
I am trying to implement a control, using either
<input type="time"/>
or just with
<input type="text"/>
and implement a duration picker control which can have hours format more than 24, something like 000:00:00 or hhh:mm:ss, and no am/pm option ( The default input type for time has formats in am/pm format, which is not useful in my case).
The requirement is to be able to increase decrease the duration using up and down keys much like the default input type time of HTML.
Is there any native HTML, angular, or material component for this?
Or is there a way to achieve this using regular expression/patterns or something?
One way I can think of is to write your custom control (as also mentioned by #Allabakash). For Native HTML, The control can be something like this:
window.addEventListener('DOMContentLoaded', (event) => {
document.querySelectorAll('[my-duration-picker]').forEach(picker => {
//prevent unsupported keys
const acceptedKeys = ['Backspace', 'ArrowLeft', 'ArrowRight', 'ArrowDown', 'ArrowUp'];
const selectFocus = event => {
//get cursor position and select nearest block;
const cursorPosition = event.target.selectionStart;
"000:00:00" //this is the format used to determine cursor location
const hourMarker = event.target.value.indexOf(":");
const minuteMarker = event.target.value.lastIndexOf(":");
if (hourMarker < 0 || minuteMarker < 0) {
//something wrong with the format. just return;
return;
}
if (cursorPosition < hourMarker) {
event.target.selectionStart = 0; //hours mode
event.target.selectionEnd = hourMarker;
}
if (cursorPosition > hourMarker && cursorPosition < minuteMarker) {
event.target.selectionStart = hourMarker + 1; //minutes mode
event.target.selectionEnd = minuteMarker;
}
if (cursorPosition > minuteMarker) {
event.target.selectionStart = minuteMarker + 1; //seconds mode
event.target.selectionEnd = minuteMarker + 3;
}
}
const insertFormatted = (inputBox, secondsValue) => {
let hours = Math.floor(secondsValue / 3600);
secondsValue %= 3600;
let minutes = Math.floor(secondsValue / 60);
let seconds = secondsValue % 60;
minutes = String(minutes).padStart(2, "0");
hours = String(hours).padStart(3, "0");
seconds = String(seconds).padStart(2, "0");
inputBox.value = hours + ":" + minutes + ":" + seconds;
}
const increaseValue = inputBox => {
const rawValue = inputBox.value;
sectioned = rawValue.split(':');
let secondsValue = 0
if (sectioned.length === 3) {
secondsValue = Number(sectioned[2]) + Number(sectioned[1] * 60) + Number(sectioned[0] * 60 * 60);
}
secondsValue += 1;
insertFormatted(inputBox, secondsValue);
}
const decreaseValue = inputBox => {
const rawValue = inputBox.value;
sectioned = rawValue.split(':');
let secondsValue = 0
if (sectioned.length === 3) {
secondsValue = Number(sectioned[2]) + Number(sectioned[1] * 60) + Number(sectioned[0] * 60 * 60);
}
secondsValue -= 1;
if (secondsValue < 0) {
secondsValue = 0;
}
insertFormatted(inputBox, secondsValue);
}
const validateInput = event => {
sectioned = event.target.value.split(':');
if (sectioned.length !== 3) {
event.target.value = "000:00:00"; //fallback to default
return;
}
if (isNaN(sectioned[0])) {
sectioned[0] = "000";
}
if (isNaN(sectioned[1]) || sectioned[1] < 0) {
sectioned[1] = "00";
}
if (sectioned[1] > 59 || sectioned[1].length > 2) {
sectioned[1] = "59";
}
if (isNaN(sectioned[2]) || sectioned[2] < 0) {
sectioned[2] = "00";
}
if (sectioned[2] > 59 || sectioned[2].length > 2) {
sectioned[2] = "59";
}
event.target.value = sectioned.join(":");
}
const controlsDiv = document.createElement("div");
const scrollUpBtn = document.createElement("button");
const scrollDownBtn = document.createElement("button");
scrollDownBtn.textContent = " - ";
scrollUpBtn.textContent = " + ";
scrollUpBtn.addEventListener('click', (e) => {
increaseValue(picker);
});
scrollDownBtn.addEventListener('click', (e) => {
decreaseValue(picker);
});
picker.parentNode.insertBefore(scrollDownBtn, picker.nextSibling);
picker.parentNode.insertBefore(scrollUpBtn, picker.nextSibling);
picker.value = "000:00:00";
picker.style.textAlign = "right"; //align the values to the right (optional)
picker.addEventListener('keydown', event => {
//use arrow keys to increase value;
if (event.key == 'ArrowDown' || event.key == 'ArrowUp') {
if(event.key == 'ArrowDown'){
decreaseValue(event.target);
}
if(event.key == 'ArrowUp'){
increaseValue(event.target);
}
event.preventDefault(); //prevent default
}
if (isNaN(event.key) && !acceptedKeys.includes(event.key)) {
event.preventDefault(); //prevent default
return false;
}
});
picker.addEventListener('focus', selectFocus); //selects a block of hours, minutes etc
picker.addEventListener('click', selectFocus); //selects a block of hours, minutes etc
picker.addEventListener('change', validateInput);
picker.addEventListener('blur', validateInput);
picker.addEventListener('keyup', validateInput);
});
});
<input type="text" my-duration-picker></input>
Tested and working on Google Chrome 78. I will do a Angular version later.
For the Angular version, you can write your own custom Directive and just import it to your app-module-ts declarations. See this example on stackblitz:
App Demo: https://angular-xbkeoc.stackblitz.io
Code: https://stackblitz.com/edit/angular-xbkeoc
UPDATE: I developed and improved this concept over time. You can checkout the picker here 👉 https://nadchif.github.io/html-duration-picker.js/
checkout this solution , https://github.com/FrancescoBorzi/ngx-duration-picker. which provides options you are looking for.
here is the demo - https://embed.plnkr.co/1dAIGrGqbcfrNVqs4WwW/.
Demo shows Y:M:W:D:H:M:S format. you can hide the parameters using flags defined in docs.
Since you are looking for duration picker with single input, creating your own component will be handy.
You can consider the concepts formatters and parsers.
checkout this topics which helps you in achieving that.
https://netbasal.com/angular-formatters-and-parsers-8388e2599a0e
https://stackoverflow.com/questions/39457941/parsers-and-formatters-in-angular2
here is the updated sample demo - https://stackblitz.com/edit/hello-angular-6-yuvffz
you can implement the increase/decrease functionalities using keyup/keydown event functions.
handle(event) {
let value = event.target.value; //hhh:mm:ss
if(event.key === 'ArrowUp') {
console.log('increase');
} else if (event.key === 'ArrowDown') {
console.log('decrease');
} else {
//dont allow user from entering more than two digits in seconds
}
}
Validations you need to consider ::
- If user enters wrong input, show error message / block from entering anything other than numbers
- allowing only unit specific digits - (Ex :: for hr - 3 digits, mm - 2 digits etc as per your requirement)
To do something more interesting or make it look like interactive you can use the
flipclock.js which is very cool in looking and to work with it is also feasible.
Here is the link :-
http://flipclockjs.com/
You can try with number as type :
<input type="min" min="0" max="60">
demo :
https://stackblitz.com/edit/angular-nz9hrn
I created a timer that can be stoppable when the user insert a secreat code (that is 569). How can I stop the timer when the code is inserted, beacuse right now it just show "Congratulation, mission complete!"
function startTimer(duration, display) {
var timer = duration, minutes, seconds;
setInterval(function () {
minutes = parseInt(timer / 60, 10)
seconds = parseInt(timer % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
if (--timer < 0) {
document.getElementById("text").innerHTML = "You're dead";
}
}, 1000);
}
window.onload = function () {
var Minutes = 60 * 0.5,
display = document.querySelector('#time');
startTimer(Minutes, display);
};
function StopFunction() {
var code;
var rightcode=569;
code = document.getElementById("icode").value;
text = (code==rightcode) ? "Congratulation, mission complete!":"Sorry, wrong code, try again!";
if(code==rightcode){
display = document.getElementById("time").innerHTML = "Stop timer";}
document.getElementById("text2").innerHTML =text;
}
.btn {
border: none;
color: white;
padding: 14px 28px;
font-size: 16px;
cursor: pointer;
}
.success {background-color: #4CAF50;} /* Green */
.success:hover {background-color: #46a049;}
<div id="text">You have <span id="time"></span> minutes left!</div>
<p id="text2"></p>
<br>
<p>Enter the code:</p>
<input id="icode"/>
<button class="btn success" onclick="StopFunction()">Check code</button>
following code should work for you
var interval;
function startTimer(duration, display) {
var timer = duration, minutes, seconds;
interval=setInterval(function () {
minutes = parseInt(timer / 60, 10)
seconds = parseInt(timer % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
if (--timer < 0) {
document.getElementById("text").innerHTML = "You're dead";
}
}, 1000);
}
window.onload = function () {
var Minutes = 60 * 0.5,
display = document.querySelector('#time');
startTimer(Minutes, display);
};
function StopFunction() {
var code;
var rightcode=569;
code = document.getElementById("icode").value;
text = (code==rightcode) ? "Congratulation, mission complete!":"Sorry, wrong code, try again!";
if(code==rightcode){
display = document.getElementById("time").innerHTML = "Stop timer";}
document.getElementById("text2").innerHTML =text;
clearInterval(interval);
}
Say I want to tailor my application to throttle throughput when running on battery power, but go full bore when it's plugged to a wall socket.
Is there an event to plug into to detect when these things happen like when internet connection is detected?
Apparently there's this trigger you can plug in to. It only fires off when the device is plugged in.
IE and WebView http://ie.microsoft.com/testdrive/HTML5/PowerMeter/Default.html can poll the cpu power states
eg: http://apps.microsoft.com/windows/app/plugged-in/2b91b1e1-9e30-4a96-bc95-b196e46bef9d
In c#/xaml try:
XAML
<WebView x:Name="BatteryCheck_WV" Source="ms-appx-web:///Assets/JSBatteryCheck.html" Height="50" Width="50" Visibility="Collapsed" />
c#
var PeriodicTimer = ThreadPoolTimer.CreatePeriodicTimer(async (timer) =>
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low,
async () =>
{
if (Window.Current.Visible) BatteryStatus.IsOn= Convert.ToBoolean(await BatteryCheck_WV.InvokeScriptAsync("IsPluggedIn", null));
});
}, new TimeSpan(0, 0, 0, 1, 0));
html/js
<!DOCTYPE html>
<html>
<head>
<title>JSBatteryCheck</title>
<script type="text/javascript">
var batterytimeOut;
var timeOutGo = true;
var lastDisplayUpdateTime = new Date();
var MilliSeconds = 1000;
var displayUpdateInterval = 200;
var values = [];
var maxValues = displayUpdateInterval;
var PluggedIn = true;
var currentTicksPerMilliSecond = 0;
function GetTicksPerSecond() {
if ((new Date() - lastDisplayUpdateTime) >= displayUpdateInterval) {
lastDisplayUpdateTime = new Date;
currentTicksPerMilliSecond = Avg();
values = [];
if (!isNaN(currentTicksPerMilliSecond)) {
PluggedIn = (currentTicksPerMilliSecond > 9) ? false : true;
}
}
else Tick();
if (timeOutGo) batterytimeOut = setTimeout(function () { GetTicksPerSecond() }, 1);
}
function StartTimer() {
timeOutGo = true;
GetTicksPerSecond();
return "";
}
function Tick() {
if (values.length > maxValues) values.shift();
else values.push(new Date());
}
function Avg() {
if (values.length > 1) {
var earliest = values[0];
var latest = values[values.length - 1];
var elapsed = latest - earliest;
var elapsedSeconds = elapsed / MilliSeconds;
var avg = MilliSeconds / ((values.length - 1) / elapsedSeconds);
return parseInt(avg);
}
else return NaN;
}
function StopTimeOut() {
clearTimeout(batterytimeOut);
batterytimeOut = null;
timeOutGo = false;
}
function IsPluggedIn() {
return String(PluggedIn);
}
</script>
</head>
<body onload="GetTicksPerSecond()">
<div id="PowerStatus"></div>
<button onclick="StopTimeOut()">Stop timeout</button>
</body>
</html>
For background tasks SystemTriggerType.BackgroundWorkCostChange event is best but needs lock screen access
I have a countdown function (the code for which, is below) that is small and alligned to the top left corner.
I would like to be able to customize the size, allignment, back color, fore color, and also have a button to stop, start, and clear the timer.
Secondly, I want the counter to show "00:00:00" at the start, and when it reaches "00:00:59", I want it to roll over to "00:01:00" showing that 1 minute has passed.
I would think that CSS/HTML would be the most appropriate language to do this in to acheive the desired visual effect but Javascript seems to have more arithmatic/parsing functionality.
<br><script language="JavaScript">
function calcage(secs, num1, num2) {
s = ((Math.floor(secs/num1))%num2).toString();
if (LeadingZero && s.length < 2) {
s = "0" + s;
return "<b>" + s + "</b>";
}
}
function CountBack(secs) {
if (secs < 0) {
document.getElementById("cntdwn").innerHTML = FinishMessage;
return;
}
DisplayStr = DisplayFormat.replace(/%%D%%/g,calcage(secs,86400,100000));
DisplayStr = DisplayStr.replace(/%%H%%/g, calcage(secs,3600,24));
DisplayStr = DisplayStr.replace(/%%M%%/g, calcage(secs,60,60));
DisplayStr = DisplayStr.replace(/%%S%%/g, calcage(secs,1,60));
document.getElementById("cntdwn").innerHTML = DisplayStr;
if (CountActive) {
setTimeout("CountBack(" + (secs+CountStepper) + ")", SetTimeOutPeriod);
}
}
function putspan(backcolor, forecolor) {
document.write("<span id='cntdwn' style='background-color:" + backcolor + "; color:" + forecolor + "'></span>");
}
if (typeof(BackColor)=="undefined") {
BackColor = "black";
}
if (typeof(ForeColor)=="undefined") {
ForeColor= "white";
}
if (typeof(TargetDate)=="undefined") {
TargetDate = "12/31/2050 5:00 AM";
}
if (typeof(DisplayFormat)=="undefined") {
DisplayFormat = "%%H%%:%%M%%:%%S%%";
}
if (typeof(CountActive)=="undefined") {
CountActive = true;
}
if (typeof(FinishMessage)=="undefined") {
FinishMessage = "";
}
if (typeof(CountStepper)!="number") {
CountStepper = -1;
}
if (typeof(LeadingZero)=="undefined") {
LeadingZero = true;
}
CountStepper = Math.ceil(CountStepper);
if (CountStepper == 0) {
CountActive = false;
}
var SetTimeOutPeriod = (Math.abs(CountStepper)-1)*1000 + 990;
putspan(BackColor, ForeColor);
var dthen = new Date(TargetDate);
var dnow = new Date();
if(CountStepper>0) {
ddiff = new Date(dnow-dthen);
}
else {
ddiff = new Date(dthen-dnow);
}
gsecs = Math.floor(ddiff.valueOf()/1000);
CountBack(gsecs);
</script>
I would use a simpler solution, using javascript Date object, sum miliseconds on a time counter then format the miliseconds as time.
some references :
Date object and functions : http://w3schools.com/jsref/jsref_obj_date.asp