普段会話しなくても、諍いなく存在を肯定できるご近所さん。
平穏のありがたみを感じる。
***
「ブログを一週間更新していないと叱ってくれるプラグイン」を作るには、ブログのフィードを取得する必要がある。
前回は、XMLHttpRequestクラスとJSONクラスを用いて、ローカルのJSONファイルを読み込んで解析したが、今回は応用として、実際に本ブログのフィードを取得する。
ポイント
- アイコンのクリックでHTMLのポップアップを表示するには、マニフェストのbrowser_action.default_popupに呼び出すHTMLを指定する
- 拡張機能のJavaScriptから外部URLのソースを取得する際には、マニフェストのpermissionsにURLを追加するだけでよい(クロスドメインリクエストの問題に頭を抱える必要はない)
- 「ブロガー支援プラグイン」として、クリックで一覧表示+記事へのリンクを表示する機能などを加えたら面白いかもしれない(感想)
開発・実行環境
バージョン: 78.0.3904.70(Official Build) (64 ビット)
起動時オプション:
--flag-switches-begin --flag-switches-end
PC
プロセッサ: Intel(R) Core(TM) i5-5200U CPU @2.20GHz
メモリ: 8.00 GB
OS: Windows 8.1 (64bit)
compiler: Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86
Visual Studio: 14.0
フォルダ構成
├── icon
│ └── icon.png
├── load.js
├── manifest.json
└── popup.html
load.js には popup.html の読み込み時に起動されるイベントハンドラを実装した。
コード
manifest.json
{
"name": "Blogger feed JSON parser",
"description" : "Base Level Extension",
"manifest_version": 2,
"version": "1.0",
"permissions": [
"http://*/*", "https://*/*"
],
"browser_action": {
"default_popup": "./popup.html"
},
"icons": {
"16": "./icon/icon.png",
"32": "./icon/icon.png",
"48": "./icon/icon.png",
"128": "./icon/icon.png"
}
}
browser_action.default_popup にHTMLを指定する。これにより、拡張機能アイコンを左クリックした際にpopup.html に記述されるポップアップを表示できる[1]。
permissionsに "http://*/*", "https://*/*" を指定することでCORSのエラーを回避できる[2][3]。
調べていて、拡張機能としてではなく、純粋にWEBページに組み込むJavaScriptからURLにアクセスする場合には、いろいろ大変そうだと思った[3]。
マニフェストを弄るだけでクロスドメインリクエストの問題に頭を抱えずに済むのだから、とてもありがたい。
popup.html
<!DOCTYPE html>
<html>
<head>
<meta charser="utf-8" />
<title>Odonata Bug Hunt Blog</title>
<!-- <link rel="manifest" href="/manifest.json"> -->
<script type="text/javascript" src="load.js"></script>
</head>
<body>
<div>About</div>
title: <span id="id_title"></span><br />
subtitle: <span id="id_subtitle"></span><br />
authors: <span id="id_authors"></span><br />
<br />
<div>Posts</div>
total posts: <span id="id_total_post"></span><br />
<ul id="id_post_list"></ul>
</body>
</html>
ブログのタイトル、サブタイトル、著者、投稿本数は数が決まっている項目なので、spanタグを指定する。一方で、投稿本数は変化するので、各投稿の情報の表示にはulタグを利用する。
load.js
window.onload = function() {
var xhr = createXMLHttpRequest();
var url = 'https://mamorunoblog.blogspot.com/feeds/posts/default?alt=json&orderby=published';
xhr.onreadystatechange = function() {
switch (xhr.readyState) {
case 4: // DONE
if (xhr.status != 200) {
return;
}
console.log('xhr.readyState: ' + xhr.readyState);
console.log('xhr.status: ' + xhr.status);
console.log('xhr.responseText:\n' + xhr.responseText);
// Parsing JSON.
var data = JSON.parse(xhr.responseText);
// title.
var elem = document.getElementById('id_title');
elem.innerText = data.feed.title.$t;
// subtitle.
var elem = document.getElementById('id_subtitle');
elem.innerText = data.feed.subtitle.$t;
// authors.
var authors = '';
var i = 0;
for (i = 0; i < data.feed.author.length; i++) {
authors = authors + data.feed.author[i].name.$t + '(' +
data.feed.author[i].email.$t + '), ';
}
var elem = document.getElementById('id_authors');
elem.innerText = authors;
// total posts.
var elem = document.getElementById('id_total_post');
elem.innerText = data.feed.entry.length;
// entry.
var list = document.getElementById('id_post_list');
while (list.firstChild) {
// Clear last result.
list.removeChild(list.firstChild);
}
var i = 0;
var show_max = 10;
for (i = 0; i < data.feed.entry.length; i++) {
if (i > show_max) {
var li = document.createElement('li');
list.appendChild(li);
var node = document.createTextNode('omitted more ' +
(data.feed.entry.length - show_max) + 'posts.');
li.appendChild(node);
break;
}
// title.
var li = document.createElement('li');
list.appendChild(li);
var node = document.createTextNode(data.feed.entry[i].title.$t);
li.appendChild(node);
// sublist.
var subList = document.createElement('ul');
li.appendChild(subList);
// published
var subLi = document.createElement('li');
subList.appendChild(subLi);
var node = document.createTextNode(
'published: ' + data.feed.entry[i].published.$t);
subLi.appendChild(node);
// updated
var subLi = document.createElement('li');
subList.appendChild(subLi);
var node = document.createTextNode(
'updated: ' + data.feed.entry[i].updated.$t);
subLi.appendChild(node);
// authors.
var authors = '';
var j = 0;
for (j = 0; j < data.feed.entry[i].author.length; j++) {
authors = authors + data.feed.entry[i].author[j].name.$t + '(' +
data.feed.entry[i].author[j].email.$t + '), ';
}
var node = document.createTextNode('authors: ' + authors);
var subLi = document.createElement('li');
subList.appendChild(subLi);
subLi.appendChild(node);
// categories
var categories = '';
var j = 0;
for (j = 0; j < data.feed.entry[i].category.length; j++) {
categories =
categories + data.feed.entry[i].category[j].term + ', ';
}
var node = document.createTextNode('categories: ' + categories);
var subLi = document.createElement('li');
subList.appendChild(subLi);
subLi.appendChild(node);
}
break;
default:
// none.
break;
}
}
xhr.open('GET', url);
xhr.send();
}
function createXMLHttpRequest() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
}
if (window.ActiveXObject) {
try {
return new ActiveXObject('Msxml2.XMLHTTP.6.0');
} catch (e) {
// none.
}
try {
return new ActiveXObject('Msxml2.XMLHTTP.3.0');
} catch (e) {
// none.
}
try {
return new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {
// none.
}
}
return false;
}
フィードを取得しHTMLを更新するスクリプトである。createXMLHttpRequest関数でXMLHttpRequestクラスを作成するところは前回と一緒だが、今度は引数に指定するURLがローカルのJSONから本ブログのフィードになった。
著者とカテゴリ、投稿はJSONに配列として記述されているため、ループで処理する。
実行結果

アイコン(星印)をクリックすると、ポップアップで本ブログの投稿情報が表示される。
これでフィードが取得できることが確かめられた!
改善点
ほんのテストで実装したにしては、便利ツールに化けそうだ。
私はブロガーとして過去の自分の投稿を参照することが結構あるので、ブックマークとは別に素早いジャンプ機構を持つことはよいことだ。
リンクを張るだけなら、簡単な改造で済むだろう。
問題は表示する情報の選択と、表示方法の最適化だな。
投稿期間の設定とか、表示件数の上限とか、設定を変えられるようにできたらいいな。
まあ、そういう欲を出すのはアルファ版ができてからでも遅くはない。
まとめ
感想
漠然と「ブログを一週間更新していないと叱ってくれるプラグイン」を作りたいと考えてきたが、「ブロガー支援プラグイン」として、より便利なツールにしたいと考え始めている。
付録
参考文献
- Google Chrome 拡張機能を開発する 〜 ポップアップを表示するまで 〜
- Chrome拡張でCORS対応
- クロス ドメイン リクエスト (Cross-Domain Requests, XDR) の問題を理解する
- What does “http://*/*”, “https://*/*” and “<all_urls>” mean in the context of Chrome extension's permissions
0 件のコメント:
コメントを投稿
コメント表示は承認制に設定しています