色々な機能を追加したタイマーを作りたい

#初めに
　Guildという名前でwebサイトを作ろうと四苦八苦しておりますが、そもそもGuildが何を目的に作成しているのか忘れかけていたところで、ギリギリで何を作ってたのが今日この頃です。
　依頼を気軽に受けれる場所をネットで作りたいなと思ってGuildを作成していたのですが、たまには息抜きもいいかなと、とにかく機能を盛りだくさんにしてタイマーを作っていこうと思います。デザインに関しては例の如く。
 因みにNode.jsをサーバーサイドで利用しています。だからせっかくなのでNode.jsのプログラムも載せておきましょう。

　最終的には、以下のを作ったよってお話です。

https://guild.click/timer
#バージョン
・Node.js　　　　　　15.11.0
・MongoDB　　　　　4.4.6
#仕様書
　考えつく限りタイマーに付けれる機能を考えていきます。
・無難にアラーム付きタイマー
・タイマーの設定
・タイマーアラームの変更
・周期的なタイマー
　あれ？案外思い浮かばないな、とりあえずこれらを作っていきましょう。思いついたら後から付け足すか、後日の記事のネタにでもしたらいいでしょう。
#Node.jsの設定
　javascriptのタイマーがみたいだけって方はスキップしてもいいと思います。
　Node.jsの環境設定はすっ飛ばします。それから以下の流れも割と記憶が曖昧なのでてきとーです。

```
$ npm install express-generator -g
$ express -e timer
$ npm install
```

 npmでexpress-generatorをインストールして、ejsの雛形を作成します。timerは名前を何にしても良いです。その後でnpm installと書いてるのは、必要な足りないパッケージをインストールするためです。

　ディレクトリ構成は以下の通りだと思います。

```
.
├── app.js
├── bin
│   └── www
├── package.json
├── public
│   ├── images
│   ├── javascripts
│   └── stylesheets
│       └── style.css
├── routes
│   ├── index.js
│   └── users.js
└── views
    └── index.ejs
```

　port番号をずらすにはbin/wwwで

```javascript
var port = normalizePort(process.env.PORT || '3000');
```

　この3000を変更するか、環境変数を変更する必要があります。

　今回はtimerを作りたいので、とりあえず、routerディレクトリにtimer.jsを作ります。viewsにはtimer.ejsを作成して、publicのjavascriptsにtimer.jsを作成して、stylesheetsにtimer.cssを作成します。
　つまり最終的なファイル構成は以下の通りになります。

```
.
├── app.js
├── bin
│   └── www
├── package.json
├── public
│   ├── javascripts
│       └── timer.js
│   └── stylesheets
│       └── timer.css
├── routes
│   └── timer.js
└── views
    └── timer.ejs
```

　routesのtimer.jsでviewsのtimer.ejsが表示できるようにしましょう。

```javascript
//routes/timer.js
var express = require('express');
var router = express.Router();

router.get('/',function(req, res, next){
  res.render('timer');
});

module.exports = router;
```

　これだけでとりあえずtimer.ejsを表示することができます。因みにejsを使っていはいますが、ほぼhtmlとしか使いません。
　routes/timer.jsだけ変更しても関数は設定されていないので、app.jsのほうも変えていきましょう。

```javascript
//app.js

//
//　略
//

var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var timerRouter = require('./routes/timer'); //追加

//
//　略
//

app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/timer',timerRouter); //追加
```

　これでURLに接続したらtimer.ejsが表示されます。
　これでようやくHTMLの編集に移れますね。
#タイマー
  /views/timer.ejsを編集します。

```html
<!DOCTYPE html>
<html>
<head>
  <title>timer</title>
  <script>
   var time = Date.parse("2021-09-17T15:04:00.000Z");
   var now = new Date();
  </script>
  <link rel='stylesheet' href='/stylesheets/timer.css' />
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="/javascripts/timer.js"></script>
</head>
<body>
  <main id="timer">
    <div id="clock">
      <p class="date">{{ date }}</p>
      <p class="time">{{ time }}</p>
      <p class="text">From<a href="https://codepen.io/gau">Toshiyuki TAKAHASHI@gau</a></p>
    </div>
  </main>
</body>
</html>
```

　デザインはこのサイトで紹介されているのをそのまま持ってこさせていただきましょう。その方がやっぱり確実ですしね。

https://goworkship.com/magazine/clock-timer-code-snippets/

　public/stylesheetsのtimer.cssを変更します。

```css
body {
  font: 20px "Lucida Grande", Helvetica, Arial, sans-serif;
  margin: 0;
}
main{
  margin: 90px 150px;
}
.userimage{
  width:50px;
}
.none{
  display: none;
}
html,
body {
  height: 100%;
}
body {
  background: #ffffff;
  background: radial-gradient(ellipse at center,#ffffff 0%,#fff 70%);
  background-size: 100%;
}
p {
  margin: 0;
  padding: 0;
}
#clock {
  font-family: 'Share Tech Mono', monospace;
  text-align: center;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%,-50%);
  color: #000000;
  text-shadow: 0 0 20px #0aafe6, 0 0 20px rgb(0 0 0 / 0%);
}
#clock .time {
  letter-spacing: 0.05em;
  font-size: 80px;
  padding: 5px 0;
}
#clock .date {
  letter-spacing: 0.1em;
  font-size: 24px;
}
#clock .text {
  letter-spacing: 0.1em;
  font-size: 20px;
  padding: 20px 0 0;
}
```

　大きくバックグラウンドの色を変えていたり、文字の色を反転させていたりして、本来のかっこよさをそこなわせてしまっていますが、自分のサーバーのヘッダーのバックグラウンドと黒と白の合わせではまったく色合いが合わなかったためです。

 public/javascriptsのtimer.jsはサイトにあったものをとりあえずそのまま持ってきました。

```javascript
//timer
$(function(){
  var clock = new Vue({
    el: '#clock',
    data: {
      time: '',
      date: ''
    }
  });
  var week = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'];
  var timerID = setInterval(updateTime, 1000);
  updateTime();
  function updateTime() {
    var cd = new Date();
    clock.time = zeroPadding(cd.getHours(), 2) + ':' + zeroPadding(cd.getMinutes(), 2) + ':' + zeroPadding(cd.getSeconds(), 2);
    clock.date = zeroPadding(cd.getFullYear(), 4) + '-' + zeroPadding(cd.getMonth()+1, 2) + '-' + zeroPadding(cd.getDate(), 2) + ' ' + week[cd.getDay()];
  };

  function zeroPadding(num, digit) {
    var zero = '';
    for(var i = 0; i < digit; i++) {
      zero += '0';
    }
    return (zero + num).slice(-digit);
  }
});
```

　いや、何となくjqueryの中に入れていますが、vue.jsを利用しているみたいなので、jqueryは必要なかったかな・・・。
　現段階の画面はこんな感じ。
![2021-09-17-211234_1024x600_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1045854/3a240cee-2dc9-22f7-353b-8864c51592b3.png)
　左側に見えるのは、Guildのヘッダーです。
　これではただのパクリ時計なので、ここに色々機能を載せて行きましょう。当初の予定通りタイマーにしましょう。
　…と、タイマーに諸機能をつけようとガンバっていたのですが。
　思いの外、基礎的なタイマー機能を作るのに手間取ってしまったので、今回では基礎的なタイマーのjavascriptだけを乗っけて、また後日諸機能を強化していこうと思います。
　僕の息抜きなんだから、こんな自由もいいよね！
#とりま完成品

```javascript
//timer
$(function(){
  //vueのインスタンス作成
  var clock = new Vue({
    el: '#clock',
    data: {
      time: '',
      date: ''
    }
  });
  var timerID = null;
  //vue.jsでhtmlのtimeを変更しています。
  clock.time = 'あと0:0:0';
  $('#start').click(function(){
    var hour = $('#hour').val();
    var minute = $('#minute').val();
    var second = $('#second').val();
    now = new Date();
    let dt = now;
    if(Number(hour))dt.setHours(dt.getHours()+Number(hour));
    if(Number(minute))dt.setMinutes(dt.getMinutes()+Number(minute));
    if(Number(second))dt.setSeconds(dt.getSeconds()+Number(second));
    if(timerID)clearInterval(timerID);
    if(hour || minute || second)timerID = setInterval(function(){
      let now = new Date();
      let time = (dt - now)/1000;
      if(time<0){
        clearInterval(timerID);
        return;
      }
      let hour = Math.floor(time/3600);
      time -= hour*3600;
      let minute = Math.floor(time/60);
      time -= minute*60;
      let second = Math.floor(time);
      clock.time = 'あと'+hour + ':' + minute + ':' + second;
    },500);
  });
  $('#stop').click(function(){
    clearInterval(timerID);
  });
  $('#reset').click(function(){
    $('#hour').val('');
    $('#minute').val('');
    $('#second').val('');
  });
});

```

　コメントをあまり書いてないので良質なプログラムとは言えませんが、しかしこれもまた息抜きのためなのですから問題ないのです。
　ちょこっと解説すると、idがhourとminuteとsecondからjqueryのvalで値を取得してきて、それをnowという今の時刻のDate型に足してます。その未来の時刻を示したものを仮置きでdtとしています。
　setIntervalで回している中では、dtとnowの差を取ってタイマーの表示を作成しています。それをtimeとして、timeが0になれば、setIntervalはclearIntervalでなかったことになります。

　流れはこんなところ。
　実物は一番上においてある僕のサイトを訪れていただければ。右クリックページのソースを表示から、短いコードを見れると思います。

#終わりに
　色々まさかのエラーで案外時間がかかってしまったのでまた後日に回ってしまったタイマー計画です。
　javascriptは数字と文字列を足し算すれば、勝手に数字に戻してくれるので、Date型でも同じ様になるんだろうなと勝手に考えてやってたら、そうならなくてエラーもしなかったから小一時間悩み通しました。