読者です 読者をやめる 読者になる 読者になる

つばさのーと

つばさの日常を綴るのーと

リライト好きな方へおススメしたい最終更新日を自動で表示するカスタマイズ

f:id:tsubasa123:20161219202036j:plain

 

こんにちは、つばさ(@tsubasa123)です。

 

結構温めていたカスタマイズネタです。二週間ほど寝かせて様子を見ましたが問題なさそうなのでご紹介。これはぜひ皆さまに使っていただきたい。

 

【2017/03/27 追記】アップデートしました

 

www.tsubasa-note.blog

 

レスポンシブデザインのテーマを利用していると表示が崩れる問題がありましたので、アップデート版を公開しました。上記記事を参照してください。

 

WordPressにはプラグインがあるけれど

 

はてなブログの標準機能では更新日を自動で表示することができないみたいですね。これ欲しい人多いと思うんですよ、ブログを運営する立場の人も、ブログを閲覧する立場の人も。情報の鮮度って気になりますので。私もできれば表示されていて欲しいと思う派です。

 

ないものは仕方ない。標準機能でないなら作ればいいよね、きっと誰かの役に立つよね。

 

仕様と実装と設定

 

今回のカスタマイズはJavaScriptの記事下への追記と表示デザインを調整するためのCSSの追記の2つの設定が必要です。ちなみに、PC・スマホ両対応です。後述しますが、Proじゃなくてもできる方法とProじゃなきゃできない方法の2つがあります。

 

記事タイトル上、投稿日の表示エリアの横に最終更新日が自動で表示されます。

f:id:tsubasa123:20161219202922j:plain

当ブログの場合はこんな感じで表示されています。左が投稿日で右が更新日です。アイコンはCSSで変更可能です。

 

現時点では表示場所の指定はできません。「記事下にも置きたいものかな?」とも考えましたが、考えすぎるとあれこれ機能を盛り込みたくなってしまうのでとりあえず固定で。

 

もし表示する場所を自分で決めたいという要望があればそのうち対応してもいいかなと思います。

 

JavaScriptの追記

 

<!--[if lt IE 9]>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.12.3.min.js"></script>
<![endif]-->
<!--[if gte IE 9]><!-->
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.2.3.min.js"></script>
<!--<![endif]-->
<script>
/*
 * Show lastmod for Hatena Blog v1.0.0
 * Date: 2016-12-20
 * Copyright (c) 2016 http://www.tsubasa-note.blog/
 * Released under the MIT license:
 * http://opensource.org/licenses/mit-license.php
 */
;(function($) {
'use strict';
var urls = [], opts = {cache: false, dataType: 'xml'}, p,
_ua = (function(u){
  return {
    Tablet:(u.indexOf("windows") != -1 && u.indexOf("touch") != -1 && u.indexOf("tablet pc") == -1) 
      || u.indexOf("ipad") != -1
      || (u.indexOf("android") != -1 && u.indexOf("mobile") == -1)
      || (u.indexOf("firefox") != -1 && u.indexOf("tablet") != -1)
      || u.indexOf("kindle") != -1
      || u.indexOf("silk") != -1
      || u.indexOf("playbook") != -1,
    Mobile:(u.indexOf("windows") != -1 && u.indexOf("phone") != -1)
      || u.indexOf("iphone") != -1
      || u.indexOf("ipod") != -1
      || (u.indexOf("android") != -1 && u.indexOf("mobile") != -1)
      || (u.indexOf("firefox") != -1 && u.indexOf("mobile") != -1)
      || u.indexOf("blackberry") != -1
  }
})(window.navigator.userAgent.toLowerCase()),
//url = 'http://www.tsubasa-note.blog/sitemap.xml'; // URLの入力例
url = ''; // ここにサイトマップへのURLを入力してください。
 
function parseSitemapXML(url) {
    var d = new $.Deferred;
    $.ajax($.extend(opts, {
        url: url
    })).done(function(xml) {
        $(xml).find('sitemap').each(function() {
            urls.push($(this).find('loc').text());
        });
        d.resolve();
    }).fail(function() {
        d.reject();
    });
    return d.promise();
}
  
function findURL(url) {
    $.ajax($.extend(opts, {
        url: url
    })).done(function(xml) {
        var isMatched = false;
        $(xml).find('url').each(function() {
            var $this = $(this);
            if ($this.find('loc').text() === location.href) {
                isMatched = true;
                appendLastmod($this.find('lastmod').text());
                return false;
            }
        });
        if (!isMatched) nextURL();
    }).fail(function() {});
}
  
function nextURL() {
    urls.shift();
    if (urls.length) findURL(urls[0]);
}
  
function appendLastmod(lastmod) {
    var $container = $('<div></div>', {'class': 'lastmod'});
    $container.append($('<span></span>', {'class': 'date-year'}).text(lastmod.split('-')[0]));
    $container.append($('<span></span>', {'class': 'hyphen'}).text('-'));
    $container.append($('<span></span>', {'class': 'date-month'}).text(lastmod.split('-')[1]));
    $container.append($('<span></span>', {'class': 'hyphen'}).text('-'));
    $container.append($('<span></span>', {'class': 'date-day'}).text(lastmod.split('-')[2]));
    if (_ua.Mobile) {
        $('.entry-title').before($container);
    } else {
        $('.entry-date').append($container);
    }
}
  
p = parseSitemapXML(url);
p.done(function() {findURL(urls[0])});
p.fail(function(error) {});
})(jQuery);
</script>

 

調子に乗ってライセンス表記とか入れてみました。

 

今回のカスタマイズでは一箇所だけ修正していただく必要があります。

 

//url = 'http://basanote.hatenablog.com/sitemap.xml'; // URLの入力例
url = ''; // ここにサイトマップへのURLを入力してください。

この部分です。上の行のような形式で、自分のブログのsitemap.xmlのURLを下の行の「'」と「'」の間に入力してください。sitemap.xmlのURLは自分のブログのURL+「sitemap.xml」か「sitemap_index.xml」になっていると思います。

 

どっちかわからん、という方は両方のURLをブラウザのURL欄に入力して、XMLのコード(HTMLみたいなやつ)が表示された方を利用してください。多分、どちらでも大丈夫だと思いますが。

 

ちなみに私のブログの場合は、「http://basanote.hatenablog.com/sitemap.xml」このようなURLになっています。クリックするとXMLファイルが表示されますので、確認の確認にご利用ください。

 

URLの指定が終わりましたら、ソースコードをカスタマイズから記事の下に追記してください。設定される際には念のためバックアップをとることをおススメします。

 

CSSの追記(PC)

 

.lastmod {
    color: #f0f0f0;
    background-color: #111;
    padding: 5px 6px;
    text-decoration: none;
    font-size: 90%;
    display: inline;
    margin-left: 10px;
}
.lastmod::before {
    margin-right: 5px;
    padding-left: 3px;
    font-family: FontAwesome;
    content: '\f021';
}
.entry-date a {
    padding: 5px 6px !important;
}
.entry-date a::before {
    margin-right: 5px;
    padding-left: 3px;
    font-family: FontAwesome;
    content: '\f017';
}

 

CSSに関しては当ブログで利用している「Brooklyn」というテーマに合わせて作成しています。導入される際にはご利用のテーマに合わせて調整してください。

 

アイコンを変更したい場合は、

 

fontawesome.io

 

こちらからお好きなものを選んでいただき、CSSを書き換えてください。

 

アイコンが表示されない場合はWEBフォントの設定がされていない可能性があります。その場合は、

 

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">

 

上記の1行も追加してください。追加する場所は「設定 > 詳細設定 > headに要素を追加」になります。

 

CSSの追記(SP)

 

span.date::before {
    margin-right: 5px;
    font-family: FontAwesome;
    content: '\f017';
}
.lastmod {
    font-size: 80%;
    padding: 0px 10px;
    margin-left: 15px;
    display: inline;
    font-weight: 700;
}
.lastmod::before {
    margin-right: 6px;
    font-family: FontAwesome;
    content: '\f021';
}

 

CSSに関しては(ry

 

スマホの場合はタイトル下にCSSを書くことになると思いますので、上記コードを<style>タグで囲うのを忘れないようにお気を付けください。

 

課題と懸念点

 

ちょっと技術的な話になりますが当カスタマイズの悪い点を記載しております。導入していただける際にはこちらも一読してください。

 

今回のカスタマイズはJavaScriptを利用してsitemap.xmlファイルに記述されている更新時間を取得して表示するような仕組みになっています。

 

はてなブログのsitemap.xmlは1ファイルにつき100記事分の情報を保持するようになっています。なので総記事数が100件以内なら1回の通信で日付を取得できますが、それ以上の場合は記事の数に応じて複数回の通信が必要になります。

 

sitemap.xmlを辿って行く際も、新しい記事の情報から順番に取得していくため、記事数が多くても新しい記事であれば通信回数は少なくて済みますが、古い記事になると通信の回数も増えてしまいます。

 

計算上、1000記事あるサイトに導入すると、最大で10回、日付を取得するための通信が必要になります。正直なところ無駄な通信は避けたいのですが、まぁ仕方ない。広告バナーに比べればそこまで遅くもないと思う。

 

実は本カスタマイズもブログアドバイザーのポジ熊さんに二週間ほど先行して実装をお願いして挙動を確認させていただきました。ポジ熊さん規模の記事数(私が見たときは800記事以上あったかな)、ポジ熊さんのような人気のあるブログでも今のところは問題なく動作しているようですので負荷的な問題は大丈夫だろうと判断しました。

 

ポジ熊さんいつもありがとうございます。まだお話していませんが、次のカスタマイズも控えておりますのでよろしければまたお付き合いください。

 

後から知ったこと

 

割と満足のいくカスタマイズができたと思って上機嫌だった私ですが、他にも同じようなことをやっている人がいないかチェックすると衝撃の結果に。

 

psn.hatenablog.jp

 

否定、とまではいきませんが、色々面倒と書かれていました。まぁ、そうですよね、私もそう思っています。やっちゃいましたけどね。

 

で、AMPに対応しているブログであればそっちから最終更新日の日付を取得できるようです。なにそれ知らなかった。AMP対応ははてなブログProの契約が必要なので、全てのユーザーにとはいきませんが、こっちのほうが断然コードがスッキリします。

 

勉強になりました、ありがとうございます。

 

AMPバージョンも一応作成

 

二番煎じではございますが、AMPを利用したカスタマイズコードも置いておきます。せっかくPro契約したのでそりゃ試したくもなりますよね。

 

<!--[if lt IE 9]>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.12.3.min.js"></script>
<![endif]-->
<!--[if gte IE 9]><!-->
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.2.3.min.js"></script>
<!--<![endif]-->
<script>
/*
 * Show lastmod for Hatena Blog2 v1.0.0
 * Date: 2016-12-20
 * Copyright (c) 2016 http://www.tsubasa-note.blog/
 * Released under the MIT license:
 * http://opensource.org/licenses/mit-license.php
 */
;(function($) {
'use strict';
var html = '', p,
_ua = (function(u){
  return {
    Tablet:(u.indexOf("windows") != -1 && u.indexOf("touch") != -1 && u.indexOf("tablet pc") == -1) 
      || u.indexOf("ipad") != -1
      || (u.indexOf("android") != -1 && u.indexOf("mobile") == -1)
      || (u.indexOf("firefox") != -1 && u.indexOf("tablet") != -1)
      || u.indexOf("kindle") != -1
      || u.indexOf("silk") != -1
      || u.indexOf("playbook") != -1,
    Mobile:(u.indexOf("windows") != -1 && u.indexOf("phone") != -1)
      || u.indexOf("iphone") != -1
      || u.indexOf("ipod") != -1
      || (u.indexOf("android") != -1 && u.indexOf("mobile") != -1)
      || (u.indexOf("firefox") != -1 && u.indexOf("mobile") != -1)
      || u.indexOf("blackberry") != -1
  }
})(window.navigator.userAgent.toLowerCase());

function getAmpHtml() {
    var d = new $.Deferred;
    $.ajax({
        dataType: 'html',
        cache: false,
        url: location.origin + location.pathname + "?amp=1"
    }).done(function (data) {
        html = data;
        d.resolve();
    }).fail(function () {
        d.reject('Error');
    });
    return d.promise();
}

function parseAmpHtml() {
    var m = html.match(/<script type="application\/ld\+json">(.*?)<\/script>/);
    if (m === null) return;
    appendLastmod(JSON.parse(m[1]).dateModified.split('T')[0]);
}

function appendLastmod(lastmod) {
    var $container = $('<div></div>', {'class': 'lastmod'});
    $container.append($('<span></span>', {'class': 'date-year'}).text(lastmod.split('-')[0]));
    $container.append($('<span></span>', {'class': 'hyphen'}).text('-'));
    $container.append($('<span></span>', {'class': 'date-month'}).text(lastmod.split('-')[1]));
    $container.append($('<span></span>', {'class': 'hyphen'}).text('-'));
    $container.append($('<span></span>', {'class': 'date-day'}).text(lastmod.split('-')[2]));
    if (_ua.Mobile) {
        $('.entry-title').before($container);
    } else {
        $('.entry-date').append($container);
    }
}

p = getAmpHtml();
p.done(parseAmpHtml);
p.fail(function(error) {});
})(jQuery);
</script>

 

こっちはURLを入れる必要がないのもいいですね。こちらのほうが通信の回数を減らすことができるのでPro契約済み、そしてAMP設定済みの方はご利用いただける場合はこちらの方がおすすめになります。

 

さいごに

 

またしても「はてはブログ初のカスタマイズ」という称号を逃してしまいました。なかなか難しいものです。とはいえ、まだまだ私にもできることはありそうなので、これからも皆さんにちょっと便利をお届けできるようがんばります。

 

ではでは、最後までお付き合いいただきありがとうございました。

 

関連記事

コピペでどうぞ。CSSでカエレバ・ヨメレバのデザインをカスタマイズしました

スマホサイト対応完了!はてなブログ公式目次のデザインカスタマイズ

レスポンシブデザイン向け、はてなブログ公式目次のデザインカスタマイズ