サブディスプレイに、タスクのメモを書いて時刻をアラーム表示できたらなぁ・・・
という思いから、ちょいと書いてみたソースコードです。
ソースコードをHTMLファイルに保存してどこかに配置して開けば使えます。ご自由に流用してください。
ここでできること
- ブラウザにアラーム付き時計を表示させる
- テキストエリアに HH:MMで始まる文字列(タスク)を入力すると、アラーム表示対象にできる
- アラームは 時計の文字 を指定の時刻より数分前までは DeepPink、指定時刻から数分後までは Red にして表現する
- アラームは 00:00 から 24:59 までを指定できる
- アラームは 10から1分前、0から5分後まで設定できる
- テキストエリアやアラームは ブラウザのローカルストレージ領域に記録できる
- 記録は値を変更したときに自動的に記録できる
- テキストエリアは枠外にフォーカスが移動すると変更した扱いになる
イメージ
ソースコード
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<title>Task Clock</title>
<style type="text/css">
.clock {background-color:#FFFFFF;text-align:center;display:inline-block;width:100%; height:18em;}
.clockMain {font-size:13em; font-weight:bold;}
.def {color:black;}
.warnBef {color:deeppink;}
.warnAft {color:red;}
.calYm {color:black; font-size:5em;}
.calAmPm {color:black; font-size:4em;}
.alarmSetting {font-size:1em; font-weight:bold;}
.setBef {float:left;margin:0px 0px 0px 10px;}
.setAft {float:left;margin:0px 0px 0px 0px;}
</style>
</head>
<body>
<div class="clock">
<div style="float:left;margin:40px 100px 0px 10px;">
<span id="calDay" class="calYm">00/00</span><br/>
<span id="calTm" class="calAmPm">PM</span>
<br/>
<div class="alarmSetting">
<div class="setBef warnBef">
Before <select id="beforeAlm"><option>1</option><option>2</option><option>3</option><option>4</option><option>5</option><option>6</option><option>7</option><option>8</option><option>9</option><option>10</option></select> min &
</div>
<div class="setAft warnAft">
After <select id="afterAlm"><option>0</option><option>1</option><option>2</option><option>3</option><option>4</option><option>5</option></select> min
</div>
</div>
</div>
<div class="clockMain" style="float:left;">
<span id="clock" style="margin:0px;" class="def">00:00:00</span>
</div>
</div>
<textarea id="todo" style="font-size:10em;width:100%;height:65vh;">
</textarea>
</body>
<script>
'use strict';
//定義
var clock = document.getElementById('clock');
var calDay = document.getElementById('calDay');
var calTm = document.getElementById('calTm');
var txtTodo = document.getElementById('todo');
var selBef = document.getElementById('beforeAlm');
var selAft = document.getElementById('afterAlm');
var timerId;
var clockDate; //時計に表示する日付オブジェクト
var alarmBefMin = 5; //アラーム(事前)
var alarmAftMin = 2; //アラーム(事後)
var alarmTimes = []; //アラームリスト(許容:00:00-24:59)
function zeroPad(value, digit) {
if(!value) {
return '0'.repeat(digit);
}
return String(value).padStart(digit, '0');
}
//時計の表示
function updateClock(){
clockDate = new Date(); //現在時刻
var dm = clockDate.getMonth()+1;
var dt = clockDate.getDate();
var h = clockDate.getHours();
var m = clockDate.getMinutes();
var s = clockDate.getSeconds();
calDay.textContent = zeroPad(dm, 2) + '/' + zeroPad(dt, 2)
clock.textContent = zeroPad(h, 2) + ':' + zeroPad(m, 2) + ':' + zeroPad(s, 2);
calTm.textContent = ( h < 13 ? "AM" : "PM");
}
//テキストエリアからアラーム対象(先頭が時刻(HH:MM))を取得
function setAlarmArray() {
alarmTimes.length = 0;
alarmTimes = new Array();
const pattern = /^(0[0-9]|1[0-9]|2[0-4])(:[0-5][0-9])/g;
const textline = txtTodo.value.split(/\r?\n/);
for ( var line of textline ) {
var hourmin = line.match(pattern);
if( hourmin != undefined ) {
if ( !alarmTimes.includes( String(hourmin) ) ) {
alarmTimes.push( String(hourmin) );
}
}
}
}
//セレクトからアラーム時間を設定
function setAlarmRange() {
alarmBefMin = selBef.value;
alarmAftMin = selAft.value;
}
//時刻から日付オブジェクトを取得
function convertToDate( hourmin, addDate ) {
var dt = new Date();
var ymd = dt.getFullYear() +'/'+ zeroPad((dt.getMonth()+1), 2) +'/'+ zeroPad(dt.getDate() + addDate, 2);
var date = new Date(ymd + ' '+ hourmin +':00.000');
return date;
}
//アラーム表示の判定
function differAlarm() {
var h = clockDate.getHours();
var alarmDiv = "def";
for(var alarm of alarmTimes) {
var baseDate;
if ( alarm.indexOf("24:") > -1 || alarm.indexOf("00:") > -1 ) {
//24時台が設定されていたら 0時 として比較する(今23時なら翌日0時)
baseDate = convertToDate( alarm.replace("24:","00:"), (h == 23) ? 1 : 0 );
}
else if ( h == 0 && alarm.indexOf("23:") > -1 ) {
//今0時の場合、23時台が設定されていたら昨日23時と比較する
baseDate = convertToDate( alarm, -1 );
}
else {
baseDate = convertToDate( alarm, 0 );
}
//時計とアラーム時刻を比較し ミリ秒 から 分 に変換する
var diffMin = Math.floor((baseDate.getTime() - clockDate.getTime()) / (60 * 1000)) + 1;
if ( diffMin <= alarmBefMin && diffMin > 0 ) {
alarmDiv = "warnBef";
break;
}
else if ( diffMin >= ( alarmAftMin * -1) && diffMin <= 0 ) {
alarmDiv = "warnAft";
}
}
clock.className = alarmDiv;
}
//時計のメイン処理
function clockMain(){
timerId = setTimeout(function(){
updateClock();
differAlarm();
clockMain();
},250);
}
//ページロード時の処理
window.addEventListener('load',function(){
// テキストエリアにストレージの内容を読み込む
const todoValue = localStorage.getItem("todo");
txtTodo.value = todoValue;
// セレクトにストレージの内容を設定する
const befAlarmValue = localStorage.getItem("alarmBefMin");
const aftAlarmValue = localStorage.getItem("alarmAftMin");
selBef.value = befAlarmValue == null ? "5" : befAlarmValue;
selAft.value = aftAlarmValue == null ? "5" : aftAlarmValue;
// アラーム対象の設定
setAlarmArray();
setAlarmRange();
// 時計のメイン処理
clockMain();
});
//テキストエリアの変更時の処理
txtTodo.addEventListener("change", function(e){
// ストレージにテキストエリアの内容を書き込む
localStorage.setItem("todo", e.target.value);
// アラーム対象の設定
setAlarmArray();
});
//
selBef.addEventListener("change", function(e){
// ストレージに選択内容を書き込む
localStorage.setItem("alarmBefMin", e.target.value);
setAlarmRange();
});
//
selAft.addEventListener("change", function(e){
// ストレージに選択内容を書き込む
localStorage.setItem("alarmAftMin", e.target.value);
setAlarmRange();
});
</script>
</html>