にせねこメモ

はてなダイアリーがUTF-8じゃないので移ってきました。

ins/delタグのdatetimeで指定された追記/削除時間を表示する

HTML文書を書いているとき、<ins>や<del>などのタグで追記や削除を行う場合に、その追記や削除を行った時間を表示しておけたらいいと思うことがある。これらのタグにはdatetime属性で時間が指定できるので、そこで指定された日時に追記あるいは削除された、ということを自動で表示できるようにしたい。

要するに、例えば、

<ins class="test" datetime="2017-10-28T01:23:45+09:00">こんばんは。</ins>

と書かれた場合、

(2017年10月28日追記)こんばんは。

などと表示できたらうれしい。


ここで、タグの前に文字列を挿入するのはCSSの擬似要素を使えばできるのだが、固定テキストやタグに指定された属性の内容等を挿入することはできる一方、それらを組み合わせたり複雑な処理を行うことはCSSのみではできないようだ。


次掲のページによると、Javascriptで直接擬似要素をいじることはできないが、擬似要素に適当な属性を指定しておくとそれ経由でJavascriptで動的に表示を変更できるらしい。


というわけで、作ってみた。

実行例

おはようございます。こんばんは。今朝今晩もいい天気です。今日も頑張っていきもう寝ましょう。

datetimeに何も指定しない場合は特に何も挿入しないようにした。

ソース

<style type="text/css">
ins::before {
  content: attr(data-before);
}
ins{
  text-decoration-line: underline;
  text-decoration-style: dashed;
}
del::before {
  content: attr(data-before);
}
</style>

<script type="text/javascript">
//forEachに渡すdata-before要素を書き換える関数を返す関数。
//追記と削除で同形式だから統合した。
function getRewriteAttrFunc(inserttext){
  return function(elem){
    datestr = elem.getAttribute('datetime');
    if (datestr){ //datetime要素が空でない場合
      t = new Date(datestr); //Date型に変換
      writestr = "("+t.toLocaleDateString()+inserttext+") "; 
                                            //(2017/10/28に追記) とか
      elem.setAttribute('data-before', writestr);
    }
  }
}
//HTMLのロード完了時に実行
document.addEventListener("DOMContentLoaded", function(event) {
  Array.prototype.forEach.call(document.getElementsByTagName("ins"), 
                               getRewriteAttrFunc("追記"));
  Array.prototype.forEach.call(document.getElementsByTagName("del"), 
                               getRewriteAttrFunc("削除"));
});
</script>

<del datetime="2017-10-30T01:27:42+09:00">おはようございます。</del><ins 
datetime="2017-10-30T01:27:42+09:00">こんばんは。</ins><del>今朝</del><ins
>今晩</ins>もいい天気です。<del datetime="2017-10-30T01:27:42+09:00"
>今日も頑張っていき</del><ins datetime="2017-10-30T01:27:42+09:00">もう寝</ins
>ましょう。

日付を表す文字列を用意するのにtoLocaleDateStringを使ってるけど、要するにロケール異なるとまた違う出力になりそうなので、代わりにgetFullYear, getMonth, getDateあたりのメソッドから泥臭く作る方がrobustかも。

datetime属性の指定が壊れてる場合に“(Invalid Date追記)”などという表示になる。対応したほうが良いかもしれない。

あと、window.onload使うのも、他に使用しているJavascriptライブラリと競合してしまってよくない場合があるかもしれない。jQueryなどのライブラリを使ってる場合はそちらに投げてしまったほうがいい気がする。
コメントでご指摘いただいたように、window.onloadの代わりにdocument.addEventListener("DOMContentLoaded", function(event){ … });を使うように書き換えた。