【ブログ】jQueryで最新記事一覧にサムネイル画像を表示する方法【JavaScript】
前回、サムネイル付き最新記事一覧についての記事を書きました。
⇒【FC2ブログ】最新記事一覧にサムネイル画像を表示する方法
内容はFC2ブログの「テンプレート変数」が前提でしたが、今回はそれを使用しなくても実現する方法を書いてみたいと思います。
(FC2以外でも参考になるかと思います)
前回の記事にも書きましたが、始まりはもう少しカスタマイズができないか、、からで、個人的にやりたかった事は
・サムネイル用の画像ファイル名をファイル名を固定にしなくても表示させたい
・最新記事の数を増やしたいが、全部画像付きだと冗長なので、最初の数件は画像付き、それ以降は画像無しの一覧にしたい
そこで、自サイトのRSSに着目。
RSSなら最新記事を配信しているので、RSSを解析して表示ができれば、スクリプトで自由度にカスタマイズできるはず。
RSSの解析方法ですが、調べてみたらjQueryのajaxメソッドを利用して簡単に行えることが判明。まずは、サンプルソースをご覧ください。
使い方
※本プログラムによって発生した問題に関して一切責任を負えませんので、あくまで使用は自己責任でお願いします。
ソースコード
<script type="text/javascript">
jQuery(function($){
var recEle = $('#[一覧を読み込ませたい位置のタグ]');
$.ajax({
dataType: 'xml',
url: '[RSSのパスID]',
success: function(data) {
if( $('item', data).length <= 0 ) {
return false;
}
$('item', data).each(function() {
// 記事リンクの作成
recEle.append('<a href="'+$('link',$(this)).text()+'" title="'+$('title',$(this)).text()+'"></a>');
$(this).children().each(function() {
if ($(this)[0].tagName == "content:encoded") {
// 本文から画像のパスを抽出
imgSrc = $(this).text().match(/src="(.*?)"/igm);
if(imgSrc != null) {
for(var j = 0; j < imgSrc.length; j++) {
// 画像の拡張子だったらimgタグに設定して、記事リンクに追加
if(imgSrc[j].search(/\.jpg|\.jpeg|\.gif|\.png/i) >= 0) {
$('a:last-child', recEle).append('<img '+imgSrc[j]+'/>');
break;
}
}
}
}
});
// 記事リンクにタイトルを追加
$('a:last-child', recEle).append('<p>' + $('title',$(this)).text() + '</p>');
});
}
});
});
</script>
- まず、一覧を作成したい位置に「#[一覧を読み込ませたい位置のタグID]」の idを持ったタグを記述しておきます。(id名はなんでも構いません。)
- [RSSのパス]にサイトのRSSのパスを入力。
- スクリプトをheadタグに記入。
基本はこれだけ。後はデザインに応じてタグの内容を変えてみてください。
内容としては、実行するとRSSが解析されたデータが返り'item'ノードが記事単位なので、'item'でループさせて、その中の'title'と'link'を参照して、aタグを作成しています。
画像ファイルは、'content'からパスを正規表現にて抽出し、最初に見つかったパスをimgタグのsrcに設定して、サムネイル画像としています。
(iframeなどのsrc属性も取れてしまうので、その後で拡張子をチェックしています)
ただしこの'content'タグが簡単に取れず、悩みました。
こちらで紹介されているテクニックを参考にして解決。
→jqueryでブログのフィードを表示する(IEも見れるよ)
※画像ファイルは'content'から探しているので、そこの中の範囲で画像ファイルをを含めておく必要があります。
FC2ブログでは、環境設定の「RSSの設定」で「全文表示」となっているか確認ください。
(省略する場合だと、本文の後ろの方に画像がある場合に検索できないためです)
サンプルでは記載していませんが、これなら'item'のループをカウントして、ある閾値の前後で画像の有り無しを分岐させることもできますね。
あと、読み込みに若干ラグがあるので、初期表示はブログで用意されている最新記事一覧を表示しておき、読み込めたら差し替える、と言う方法も良いかと思います。
(その際は、重なって表示されてしまうので、元の要素はempty()メソッドなどで消しておいてください。)
ちなみに、この方法だとクロスドメイン※の制約でブラウザによっては外部のRSSは参照できません。
クロスドメイン
基本的には、XMLHttpRequestは同一ドメインとしか通信ができないが、XMLHttpRequest Level 2には、異なるドメインと通信する機能が追加になっており、Firefox 3.5以降、Google Chrome、Safari 4以降で利用可能である。また、Internet Explorer 8には、非標準の XDomainRequest があり、似たようなことが可能である。Opera は10.7現在、未実装。 - Wikipediaより
その場合、Google Feed APIを利用する方法もあります。
詳細は割愛しますが、使い方のサンプルだけ載せておきます。
本ブログのサイドバーに、FC2ブログでやっているまとめサイトの最新記事一覧を表示させていますが、これはこの仕組みで表示させています。
ソースコード
<script type="text/javascript">
google.load("feeds", "1");
function initialize() {
var feed = new google.feeds.Feed("[RSSのパス]");
feed.setNumEntries([読み込ませたいfeed数]);
feed.load(function(result) {
if (!result.error) {
// 読み込み成功
for (var i = 0; i < result.feed.entries.length; i++) {
// エントリー単位で処理
}
}
else {
// 読み込みエラー
}
});
}
google.setOnLoadCallback(initialize);
</script>
[RSSのパス]と[読み込ませたいfeed数]を入力してください。
google.loadで、Feed APIをロード。
処理内容「initialize」を定義しておき、「setOnLoadCallback」に登録。
非同期で実行されるので、そのコールバックを受けて「initialize」が実行される、と言う仕組み。
loadされると解析結果が「result.feed.entries」に格納され、「result.feed.entries[i].title」が記事タイトル、「result.feed.entries[i].link」が記事リンク、「result.feed.entries[i].content」が記事内容となるので、これらを参照すれば上記と同じように処理が行えます。
これなら、自前で相互RSSのブログロールを作成することもできますね。
※注意点としては、外部のAPIを実行しているので 少し処理の実行にタイムラグがでるのと、Google側で読み込んだRSSをキャッシュしているらしく、最新のRSSがすぐに反映されない、と言うことでしょうか。(強制的に読み込む方法はあるようですがそれではキャッシュの意味をなさなくなってしまうのであまりよろしくはないかと。。)
是非ご参考ください。
誤りなどありましたら、ご指摘お願いします。m(_ _)m