Dashboard 年齢算尺Widget「CalcAge」改修事項


年齢計算や西暦・和暦の変換に便利なように,2013年頃に「CalcAge」というDashboard Widgetを作っていました。(良い公開場所があれば教えて下さい。)

改元への対応準備のついでに,(おそらくWebKitのバージョンアップに伴い)動作がおかしくなっていた部分を改修し,ついでに若干の機能変更を加えたので,その備忘録。

input[@type=range]のスライド中に値を拾う(onchange -> oninput)

従来,スライダーの値の変更は onChange イベントを拾っていました。
作成時にはこれで,スライダーを動かせばドラッグ中にリアルタイムに値が変更されていたのですが,いつの頃からか,onChangeは値の確定時(ドラッグを離した時)だけに呼び出されるようになっていました。動かしている最中に値が分からず不便。
ということで,onchangeに割り当てていたアクションをoninputに変更。

スライダーの範囲の変更と自動拡張

従来,スライダーの値は1900〜2030の幅で固定していましたが,この横幅で131段階もあると操作がシビアです。
そこで,起動時は1944〜今年+1の幅とし,スライダーが上限or下限に達した場合に,上限or下限を拡張するようにしました。1944を始点にしたのは,戦後生まれ≒団塊について拡張せずに年齢を計算できるようにする狙いです。

具体的には,値の確定時(上述のonChangeイベント)にElemet.valueElement.maxElement.minと一致するかどうかを判定し,一致する場合は,上限値は+20に,下限値は前の年号の開始年-1に,拡張します。

// スライダーが端まで行った時に処理する。
function judgeExpand(event){
    if(event.target.valueAsNumber == event.target.max){
        event.target.max = Number(event.target.max)+20;
    }else if(event.target.valueAsNumber == event.target.min){
        var i = 0;
        //↓ NENGOは[{title:年号, since:開始年}+]構造の配列。
        while(NENGO[i].since > event.target.valueAsNumber){
            i++;
        }
        event.target.min = NENGO[i].since-1;
    }
}

新年号への対応

上記コードのコメント欄にもあるように,CalcAgeでは年号を{title:年号, since:開始年}の配列の形で持っています。
なので,新しい元号が分かった時点で配列に{title:"元気モリモリご飯パワー(仮)", since:2019}を加筆すれば良いだけなのですが,もし今年の4月ごろに忙しかったりすると対応が後回しになりそうです(所詮は自分用ツールなので…)。
と思ったら,どうやら新元号のUnicode予約文字であるU+32FFをnormalize("NFKD")すれば,新しい元号の文字列を得ることができるみたいです。
→参考文献:平成の次の新元号の文字列を取得するコード via にせねこメモ
なので,「もしOS側が新元号のU+32FFに対応したら,元号のリストに新元号を書き足す」という処理をすることにしました。動作テストしてないけどたぶん大丈夫なはず…。

const NENGO = [
    {title:"平成", since:1989},
    {title:"昭和", since:1926},
    {title:"大正", since:1912},
    {title:"明治", since:1868}
];
if("\u32FF".normalize("NFKD")!="\u32FF"){ //新年号導入後
    NENGO.shift({title:"\u32FF".normalize("NFKD"), since:2019});
}

2019-06-17追記:MacOSX 10.14.5では意図どおりに動作せず😦
MacOSX 10.14.5は新元号令和に対応し,U+32FFに「㋿」(令和の合字)が追加されたのですが,normalize("NFKD")しても合字のままのようです。
"\u32FF".normalize("NFKD"); //->not "令和" but "㋿".

余談ですが,JavaScriptはconstで定義した配列であっても配列の中身は変更できます。

起動時のデフォルト値の変更(出生年を20年前に)

従来,出生年は固定値にしていましたが,現在の20年前の年とすることにしました。
これは,(今のところ)成人年齢が20歳とされているため,「現時点で成人か否か」を判断する際には操作を不要とする狙いです。

余談:CalcAgeのUIデザイン

年月日(Date)の比較ではなく,2つの「年」だけを比較することにし,「その年の誕生日前か後か」の判定はユーザーの脳内で行うことにしています。
年月日を入力するのは手間が多く,脳内判定の方が簡易迅速だからです。

背景画像が年輪っぽいのは,年齢をカウントするというwidgetの機能と,"年輪"がスライド操作の際に目印感があるためです。