平日WEB系SE 週末時々自転車屋

WEB系の技術ネタや大好きなお酒、週末手伝う自転車屋の話などを書きます。

はてなブログの記事下にサムネイル付きの関連記事を出して回遊性をUP!!!(6/10に別記事で修正版を公開しました)

※2015 6/10に一部バグの修正とCSSjavascriptの分離を行ったので、別記事にまとめました。 

jitenshaya-se.hatenablog.com

 

 

先日関連記事を出せるようにしましたが、色々なニュースサイトを見ているうちにやっぱりサムネイルが出したかったので改造してみました。

 

先日の記事はこちら  

jitenshaya-se.hatenablog.com

 

 関連記事表示の仕組みを実装している記事を探した

改めて関連記事表示の仕組みを実装している記事を探してみたのですが、外部サービスを使っていないものとしては「あわせて読みたいG」というスクリプトしてかありませんでした。

bulldra.hatenablog.com

 

内部的に外部サービスを使っていた

こちらのスクリプトを組み込んでいるブログは思った以上に表示が早かったので、参考にさせていただくためにjavascriptを読んだところ、内部的にyahooのマッシュアップツール「Yahoo!Pipesを使っていました。

スピードは魅力だったのですが、今後こちらのサービスを止められた場合の影響が大きいので、やはり独自に組み込むことにしました。

 

サムネイルURLの入手先はカテゴリ別ページ

一番大事なサムネイルのURLですが、はてなブログが出力しているRSSフィードには結局サムネイルのURLはなさそうなので、思い切ってカテゴリ別のページ(HTML)を読み込んで、こちらからタイトルやURL、サムネイルを取得することにしました

 

思ったより簡単に実装できて、速度的にも悪くは無いかも

元のロジックを流用したところ、思ったより簡単に実装できました。

速度もそれほど遅く無いですし、表示をブロックするわけではないので、記事の下に表示する分にはぜんぜん問題ありません。

 

PC版の見た目はこんな感じです。

f:id:jitenshaya_se:20150604225225p:plain

 

スマホの見た目はこんな感じです。

f:id:jitenshaya_se:20150604225232p:plain

 

ソースコード

思ったより見た目がきれ位にできたので、ソースを公開します。
※ソース自体は適当に作ってしまったので汚いですが、ちゃんと動きます。 

<!-- jquery読み込み -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

<script type="text/javascript">
(function ($) {
var defaultConfig = {
parentSelector: 'article',
maxEntries: 3, // or -1 for unlimited
style: [
'.same-category-entries {',
'font-size: 90%;',
'}',
'.same-category-entry-summary {',
'color: #666;',
'}',
'a.same-category-entries-category-name, a.same-category-entries-category-name:visited {',
'color: inherit;',
'}',
'.same-category-entries-category-name:before {',
'content: "【";',
'}',
'.same-category-entries-category-name:after {',
'content: "】";',
'}',
'.same-category-entry-meta {',
'color: #CCC;',
'margin-top: 0.5em;',
'}',
'.same-category-entries-category-title{',
'border-bottom: 1px solid #000;',
'margin-bottom:5px;',
'}',
'.same-category-entries-list{',
'list-style: outside none none;',
'padding-left: 0;',
'margin-bottom:0;',
'}',
'.same-category-entries-entry {',
'border-bottom: 0.1em solid #000;',
'padding-left: 0;',
'margin: 1em 0em;',
'}',
'.same-category-entries-entry-thum{',
'float:left;',
'margin-right: 10px;',
'}',
'.same-category-entries-entry a{',
'color: #333333;',
'position: relative;',
'display: inline-block;',
'}',
'.same-category-entries-entry-title{',
'margin: 0;',
'text-decoration: underline;',
'}',
'.same-category-entries-entry-date{',
'color: #696969;',
'}',
].join('\n'),
template: [
'<div class="same-category-entries">',
'<% _.each(categories, function (category) { %>',
'<% if (category.entries.length > 0) { %>',
'<div class="same-category-entries-category">',
'<h2 class="same-category-entries-category-title"><a class="same-category-entries-category-name" href="/category/<%- category.name %>"><%- category.name %></a>カテゴリの他のエントリ</h2>',
'<ul class="same-category-entries-list">',
'<% _.each(category.entries, function (entry) { %>',
'<li class="same-category-entries-entry">',
'<a href="<%- entry.url %>"><span class="same-category-entries-entry-thum" ><img src ="<%- entry.thumnailurl %>"></span><span class="same-category-entries-entry-title" ><%- entry.title %></span><div class="same-category-entries-entry-date"><%- entry.published.getFullYear() %>/<%- entry.published.getMonth() + 1 %>/<%- entry.published.getDate() %></div></a>',
'</li>',
'<% }) %>',
'</ul>',
'</div>',
'<% } %>',
'<% }) %>',
'</div>'
].join('')
};
var config = $.extend(defaultConfig, window.__hatenablog_show_same_category_entries);

var origin = location.protocol + '//' + location.host;
var categoryMetas = $('meta[property="article:tag"]').toArray();
var $entry = $('article');
var $entry = $("footer.entry-footer");

var startFetchCategoryEntries = function (d, categories) {
d = d || $.Deferred();
categories = categories || [];

var categoryMeta = categoryMetas.shift();

if (!categoryMeta) {
d.resolve(categories);
return d;
}

var category = {
name: $(categoryMeta).attr('content'),
entries: []
};

$.ajax(origin + '/archive/category/' + encodeURIComponent(category.name)).done(function (feed) {
$(feed).find('section').each(function () {
var $feedEntry = $(this);

var entry = $feedEntry.find('h1').find('a');
var thum = $feedEntry.find('.entry-thumb').css('background-image');
var thum1 = thum.substr(0,thum.length-1);
var thum2 = thum1.substr(4);
var desc = $feedEntry.find('.entry-description');
var entry = {
title: entry.text(),
url: entry.attr('href'),
thumnailurl: thum2,
summary: desc.text().substr(0,100)+"...",
published: new Date($feedEntry.find('time').attr('datetime'))
};

if (entry.url === origin + location.pathname) return;
entry.url = entry.url + "?recommend=" + location.pathname;

category.entries.push(entry);

if (category.entries.length >= config.maxEntries && config.maxEntries !== -1) {
return false;
}
});

categories.push(category);

startFetchCategoryEntries(d, categories);
}).fail(function (xhr) {
(console.error || console.log).call(console, xhr);
});

return d;
};

startFetchCategoryEntries().done(function (categories) {
var html = _.template(config.template, { categories: categories });
var $html = $($.parseHTML(html));
$entry.before($html);

if (config.style) {
$('<style type="text/css">').html(config.style).appendTo('head');
}
});
});
</script>

このままフッターに貼り付けていただければ動きます。

CSSを本来の配置先のデザインCSSに移動するなどすればもう少し見やすくなると思います。

 

カスタマイズしてほしいところ

CSSが私のサイト用になっているので文字の色など自分のサイトに合わせて修正してください。

記事数はmaxEntriesの数字を変えれば増やせます。

 

注意していただきたい点

最後にやり方上の問題ですが、カテゴリページを無理やりjavascriptで取得しているので、はてなブログのアクセス解析の数字に影響があるかもしれません。

(はてなブログのアクセス解析がログ解析型のシステムの場合は影響が出ます)

ここまで改造しようという人は大抵使っていると思いますが、GoogleAnalyticsを使っていれば2重にカウントされないので、そちらでアクセス数などは見てください。