日時系のinput要素に対し現在日時に基づく値を初期値として設定

日時系のtypeのinput要素に対して、現在日時に基づく各typeに合った値を初期値として設定するスクリプトです。
対応するtypeは**time**, **date**, **datetime-local**, **month**, **week** 及び **text** です。
初期値を設定したい要素のタグに**data-nowDate**を追記することで初期値が設定されます。

```html:sample
<input type='date' data-nowDate>
```

既に有効な値がvalueに設定済みの要素に対しては**data-nowDate**を指定しても無視します。

ブラウザが対応していない日時系のtypeの場合は該当のtypeで本来設定されるvalue値を設定、その他の無効なtypeの場合は**text**として扱います。
typeが**text**の場合は、**data-nowDate**に書式テンプレート文字を指定できます。

####テンプレート文字一覧####
**%Y%**  西暦 4桁
**%Y2%** 西暦 下2桁
**%M%**  月 2桁
**%Ms%** 月 0埋め無し
**%D%**  日 2桁
**%Ds%** 日 0埋め無し
**%h%**  時 2桁
**%hs%** 時 0埋め無し
**%m%**  分 2桁
**%ms%** 分 0埋め無し
**%s%**  秒 2桁
**%ss%** 秒 0埋め無し
**%MS%** ミリ秒 3桁
**%MSs%** ミリ秒 0埋め無し

```html:sample
<input type='text' data-nowDate='%h%:%m%:%s%'>
```

###スクリプト###

```js:input_date_default_set.js
'use strict';
{
    window.addEventListener('DOMContentLoaded', function() {
        const d = new Date();
        d.setMinutes(d.getMinutes() - d.getTimezoneOffset());

        const
            isoLocal = d.toISOString(),
            pos = {
                time            : [11, 16],
                date            : [ 0, 10],
                month           : [ 0,  7],
                'datetime-local': [ 0, 16],
            },
            elements = document.querySelectorAll('input[data-nowdate]');

        for(let i = 0; i < elements.length; i++) {
            const e = elements[i];
            if(e.value !== '') {
                continue;
            }
            const
                t = e.attributes.type !== undefined ?
                        e.attributes.type.value.toLowerCase() : 'text',
                type = e.type === t ?
                           t : (Object.keys(pos).indexOf(t) >= 0) ? t : 'text';

            if(Object.keys(pos).indexOf(type) >= 0) {
                const r = pos[type];
                e.value = isoLocal.slice(r[0], r[1]);
            }
            else if(type === 'week') {
                const
                    d_ = new Date(Math.floor((+d + 2592e5) / 6048e5) * 6048e5),
                    y  = d_.getUTCFullYear(),
                    w  = 1 + Math.floor((d_ - new Date(y + '-01-01T00:00:00Z')) / 6048e5);
                e.value = y + '-W' + ('0' + w).slice(-2);
            }
            else if(type === 'text') {
                const p = isoLocal.match(/\d+/g);
                if(e.dataset.nowdate.trim() === '') {
                    e.dataset.nowdate = '%Y%-%M%-%D% %h%:%m%:%s%';
                }
                e.value = e.dataset.nowdate
                    .replace(/%Y%/g,    p[0])           // %Y%  西暦 4桁
                    .replace(/%Y2%/g,   p[0].slice(-2)) // %Y2% 西暦 下2桁
                    .replace(/%M%/g,    p[1])           // %M%  月 2桁
                    .replace(/%Ms%/g,  +p[1])           // %Ms% 月 0埋め無し
                    .replace(/%D%/g,    p[2])           // %D%  日 2桁
                    .replace(/%Ds%/g,  +p[2])           // %Ds% 日 0埋め無し
                    .replace(/%h%/g,    p[3])           // %h%  時 2桁
                    .replace(/%hs%/g,  +p[3])           // %hs% 時 0埋め無し
                    .replace(/%m%/g,    p[4])           // %m%  分 2桁
                    .replace(/%ms%/g,  +p[4])           // %ms% 分 0埋め無し
                    .replace(/%s%/g,    p[5])           // %s%  秒 2桁
                    .replace(/%ss%/g,  +p[5])           // %ss% 秒 0埋め無し
                    .replace(/%MS%/g,   p[6])           // %MS% ミリ秒 3桁
                    .replace(/%MSs%/g, +p[6]);          // %MSs% ミリ秒 0埋め無し
            }
        }
    });
}
```

###サンプル###
[**動作デモ**](https://akebi.jp/temp/input_date_default_set/)

```html:index.html
<!DOCTYPE html>
<html lang='ja'>
<head>
    <meta name='viewport' content='width=device-width,initial-scale=1'>
    <meta charset='utf-8'>
    <title>日時系input要素に現在日時をデフォルト設定</title>
    <script src='input_date_default_set.js'></script>
</head>
<body>
    <!-- data-nowDateを追記で現在日時に基づく各typeに合った値を設定 -->
    time<br>
    <input type='time' data-nowDate><hr>
    date<br>
    <input type='date' data-nowDate><hr>
    datetime-local<br>
    <input type='datetime-local' data-nowDate><hr>
    month<br>
    <input type='month' data-nowDate><hr>
    week<br>
    <input type='week' data-nowDate><hr>

    text<br>
    <!-- type=textの場合に限り、data-nowDateに記入した書式テンプレートを反映 -->
    <input type='text' data-nowDate='%Y%-%M%-%D% %h%:%m%:%s%.%MS%'><br>
    &emsp;書式テンプレート<br>&emsp;%Y%-%M%-%D% %h%:%m%:%s%.%MS%<hr>
    <input type='text' data-nowDate='%Y2%-%Ms%-%Ds% %hs%:%ms%:%ss% %MSs%'><br>
    &emsp;書式テンプレート<br>&emsp;%Y2%-%Ms%-%Ds% %hs%:%ms%:%ss% %MSs%<hr>
    <!-- 書式テンプレート無指定時は %Y%-%M%-%D% %h%:%m%:%s% として解釈 -->
    <input type='text' data-nowDate><br>
    &emsp;書式テンプレートなし<hr>
</body>
</html>
```

**type='week'**の要素については、私が確認できる範囲では2021年4月の時点でUIも表示されとくに問題なく使用できそうだったのはWindows/MacOS/Android版のChromeくらいでした。
非対応typeでもtextとして扱われるならまだいいのですが、iOS(14.4.2)/iPadOS(14.4.2)に至っては、typeはweekを保ったまま初期値も設定できるにも関わらず、要素をタップしても専用UIが表示されることもなく内容を変更することができない(通常のソフトウェアキーボードは表示されるが値を変更できない)状態だったので、やむなく使用する際には他のtype以上に注意が必要かな、と感じました。