移転しました。ご近所にお立ち寄り...
ここです。http://kiri.jeez.jp/blog/
Toodledoをつかっているのだが、この記事でGoogle Calendar経由でiPhoneのカレンダーと連携できることをしった。
さっそく設定したのだが、おもいっきり文字化けする。どうやらical形式で取り込むときに、charset=utf-8などとcharsetの指定がないとばけるらしい。
というわけで、こんなふうなphpを書いた。Google Calendarにはここのスクリプトを読むように指定する。
とりあえずうまくいってる。
<?php
header('Content-Type: text/calendar; charset=utf-8');
readfile('http://www.toodledo.com/id/xxxxxxxxxxxxxxx/ical_live_gcal.ics');
?>
題名のとおり。
江東区の図書館とおなじcal950.cspをつかっているところはいくつかあるようで、少し修正すると適用できると思う。
amazon_cross_book_checkp.user.js
なぜに縁のある図書館はひとてまかかるところばかりなのでしょうか...
追記:スクリーンショットを貼ってみる。
PanasonicのDIGAを遠隔操作できるサイトがあるのだが、ここの番組表をつかってるひとはいるのだろうか。IE onlyなのは、まあいいとしても、ほかがあんまりだ。なので、番組表へのリンクを削って、広告をほどほど消した。ずいぶんすっきりした。FirefoxのStylishで。
@namespace url(http://www.w3.org/1999/xhtml);
@-moz-document domain("dimora.jp") {
/* 広告をほどほど削除する */
*[id*="ad03"] img[width="218"] {
display: none !important;
}
*[id*="adbox"] {
display: none !important;
}
#gg_logo {
display: none !important;
}
#topics_area0 {
display: none !important;
}
/* 検索ボックスの外枠を広げる */
.roundbox2 {
width : 640px !important;
background : #fff url("https://dimora.jp/dc/pc/img/common/box-bg3.gif") repeat-y !important;
}
.roundboxheaderb2 {
width : 640px !important;
background : url("https://dimora.jp/dc/pc/img/common/boxtitle-bg.gif") no-repeat !important;
}
.roundboxbottom2 {
width : 640px !important;
background : url("https://dimora.jp/dc/pc/img/common/boxbottom-bg3.gif") no-repeat !important;
}
/* タブから番組表を消す */
#TVG_tab {
display: none !important;
}
/* レイアウトを左寄せにする */
#userstatus01 {
float: left !important;
margin-left: 20px !important;
}
#userstatus02 {
float: left !important;
margin-left: 20px !important;
}
}
ちょっとなおした。ついでにbk1の検索がうまくいかないことがあるのでいじった。
// ==UserScript==
// @name Amazon Cross Book Check+Post
// @namespace http://kiri.vox.com/
// @include http://www.amazon.co.jp/*
// @include http://amazon.co.jp/*
// ==/UserScript==
//
// version: 2009.1.27
//
// オリジナルはadda氏のAmazon Cross Book Check(http://d.hatena.ne.jp/adda/20081112/1226463084)です。
//
var DEFAULT_AUTO_START = false;
var INTERVAL = 1000;
var TIMEOUT = 15000;
var SITEINFO = [
{
label: 'BOOKOFF Online',
url: 'http://www.bookoffonline.co.jp/display/L001,st=u,q=',
regexp: /\u4E2D\u53E4\u8CA9\u58F2\u4FA1\u683C<\/th>\uFFE5([\d,]+)/,
isbn13: true,
disabled: false
},
{
label: 'livedoor BOOKS',
url: 'http://books.livedoor.com/search/?v=2&word=',
afterISBN: '&type=isbn',
regexp: /\u4E2D\u53E4\u4FA1\u683C\uFF1A([\d,]+)/,
disabled: false
},
{
label: '\u53E4\u672C\u5E02\u5834', //古本市場
url: 'http://www.search.ubook.co.jp/search/search.php?category1=all&shousai_r=1&isbn=',
regexp: /span class="biggerlink">([\d,]+)[\s\S]*?<input type="checkbox"/,
disabled: false
},
{
label: 'eBOOKOFF',
url: 'http://www.ebookoff.co.jp/cmdtysearch?Ctgry=1002&hdnSearchFlg=1&chkOld=1&txtISBNCode=',
regexp: /([\d,]+)/,
isbn13: true,
disabled: false
},
{
label: 'bk1',
regexp: /info/,
url: 'http://www.bk1.jp/webap/user/SchDetailBibList.do?searchFlg=9&isbn=',
disabled: false
},
{
label: '\u6A2A\u6D5C\u5E02\u7ACB\u56F3\u66F8\u9928', //横浜市立図書館
url: 'http://www.lib.city.yokohama.jp/cgi-bin/Swissken.sh?0+-+0',
regexp: /<A HREF="\/cgi-bin\/Swwwsvis\.sh\?[^"]+"/g,
disabled: false,
// 以下はPOST処理のために追加した
method: 'post', // 'post'もしくは'get'。未定義なら"get"として処理する。
buildQuery: function(isbn) {
var fields = {tgid:'010A', kkey:'', skey:'', srs10:1, srs11:1, srs12:1, ktyp4:'SHK', key4:'', itfg4:'F'};
for (var i = 0; i < 4; i++) {
fields['ktyp'+i] = 'SHK';
fields['key'+i] = '';
fields['itfg'+i] = 'F';
fields['ron'+i] = 'm';
}
fields.tkey = isbn;
var a = [];
for (var k in fields) {
a.push(k + '=' + fields[k]);
}
return a.join('&');
},
getContentURL: function(res) {
var books = res.responseText.match(/<A HREF="\/cgi-bin\/Swwwsvis\.sh\?[^"]+"/g); //";
var url = [];
if(books) {
url = books.map(function(a){
a = a.replace(/<A HREF=\"/, 'http://www.lib.city.yokohama.jp');
return a;
});
}
return url[0];
},
},
/* template
{
label: '',
url: '',
afterISBN: '',
regexp: //,
isbn13: ,
bothISBN: ,
disabled: ,
},
*/
]
var PAGEINFO = [
{
type: 'wishlist',
urlExp: 'wishlist',
insertAfter: '//tbody[@name]/descendant::tbody[1]/tr[last()]',
asinLink: '//td[@class="small"]/strong/a',
autoStart: true
},
{
type: 'search',
urlExp: 'keywords=',
insertAfter: '//div[@class="productData"]/*[last()]',
asinLink: '//div[@class="productData"]/div[1]/a',
autoStart: true
},
{
type: 'bestsell',
urlExp: '/bestsellers/',
insertAfter: '//table[@class="priceBox"]/tbody/tr[last()]',
asinLink: '//strong[@class="sans"]/a',
autoStart: true
},
{
type: 'recommend',
urlExp: '/yourstore/',
insertAfter: '//table[@class="priceBox"]/tbody/tr[last()]',
asinLink: '//td[@width="100%"]/a',
autoStart: true
},
{
type: 'listmania',
urlExp: '/lm/',
insertAfter: '//td[@class="listItem"]/table/*[last()]',
asinLink: '//td[@class="listItem"]/a',
autoStart: true
},
{
type: 'history',
urlExp: '/history/',
insertAfter: '//table[@class="priceBox"]/tbody/tr[last()]',
asinLink: '//td[@width="100%"]/a',
autoStart: true
}
]
var STYLE = <><![CDATA[
table.ACBC {
font-size: 13px;
margin-top: 3px;
}
table.ACBC td.label {
padding-right:1em;
}
table.ACBC span.loading {
color: #39c;
}
table.ACBC a.notfound {
color: #666 !important;
text-decoration: none;
font-family: arial,verdana,helvetica,sans-serif;
}
table.ACBC a.found {
color: #900 !important;
font-weight: bold;
text-decoration: underline !important;
}
]]></>
function Checker(pageType) {
this.pageType = pageType;
this.index = 0;
}
Checker.prototype.run = function() {
GM_addStyle(STYLE);
SITEINFO = SITEINFO.filter(function(i){ return !(i.disabled) });
if (this.pageType == 'detail') {
var t = document.getElementById('handleBuy');
if (!t) return;
var target = t.lastChild.previousSibling.lastChild.lastChild;
var isbn = getISBN(document.location.href);
if (!checkISBN(isbn)) return;
var item = new Item(isbn, target);
item.load();
} else {
this.setIteration(this.pageType);
}
}
Checker.prototype.setIteration = function(pinfo) {
if (DEFAULT_AUTO_START && pinfo.autoStart) {
this.iterate(pinfo);
} else {
var self = this;
GM_registerMenuCommand('ACBC+P - start', function() {
self.iterate(pinfo);
});
}
}
Checker.prototype.iterate = function(pinfo) {
var self = this;
var f = function() {
var targets = getElementsByXPath(pinfo.insertAfter, document);
var links = getElementsByXPath(pinfo.asinLink, document);
var i = self.index, len = targets.length;
(function g(){
if (!(i < len)) return;
var isbn = getISBN(links[i].href);
if (checkISBN(isbn)) {
var item = new Item(isbn, targets[i]);
item.load();
};
i++;
setTimeout(g, INTERVAL);
})();
self.index = len;
};
f();
if (window.AutoPagerize) window.AutoPagerize.addFilter(f);
}
function Item(isbn, target) {
this.isbn = isbn;
this.target = target;
this.timers = [];
}
Item.prototype.load = function() {
this.insertTable();
var f = function(n) {
var info = SITEINFO[n];
var url = self.buildURL(info);
self.timers[n] = setTimeout(function(){
self.insertContent(n, "Timeout")
}, TIMEOUT);
if (!info.method || info.method=='get') { //get
GM_xmlhttpRequest({
method: 'get',
url: url,
onload: function(res) {
clearTimeout(self.timers[n]);
self.insertContent(n, self.getContent(res, info, url));
}
})
} else { //post
GM_xmlhttpRequest({
method: 'post',
url: url,
data: info.buildQuery(self.isbn),
onload: function(res) {
clearTimeout(self.timers[n]);
self.insertContent(n, self.getContent(res, info, !info.getContentURL? url : info.getContentURL(res)));
}
})
}
}
for (var i = 0, len = SITEINFO.length; i < len; i++) {
var self = this;
f(i);
}
}
Item.prototype.insertTable = function() {
var tr = document.createElement("tr");
var td = document.createElement("td");
var inner = "";
");
for (var i = 0, len = SITEINFO.length; i < len; i++) {
inner += (""); " + SITEINFO[i].label + " loading...
}
td.innerHTML = (inner += "
tr.appendChild(td);
this.target.parentNode.insertBefore(tr, this.target.nextSibling);
this.table = tr.firstChild.firstChild;
}
Item.prototype.buildURL = function(info) {
var url = info.url;
if (info.isbn13) {
url += conv2ISBN13(this.isbn);
} else if (info.bothISBN) {
url += (conv2ISBN13(this.isbn) + "|" + this.isbn);
} else if ( !info.method||info.method=='get' ) {
url += this.isbn;
}
if (info.afterISBN) url += info.afterISBN;
return url;
}
Item.prototype.getContent = function(res, info, url) {
if (res.responseText.match(info.regexp)) {
var price = (RegExp.$1.length > 0)? "\uFFE5 "+ RegExp.$1 : "Found";
return "" + price + "";
} else {
return "NotFound";
}
}
Item.prototype.insertContent = function(n, str) {
this.table.firstChild.childNodes[n].childNodes[1].innerHTML = str;
}
function getPageType(url) {
for (var i = 0, len = PAGEINFO.length; i < len; i++) {
var pinfo = PAGEINFO[i];
if (url.indexOf(pinfo.urlExp) != -1) return pinfo;
}
if (getISBN(url)) return 'detail';
return false;
}
function getISBN(str) {
if (str.match(/[\/\=]([\d]{9}[\dX])[^&]?/)) return RegExp.$1;
}
//----main----
var pageType = getPageType(document.location.href);
if (pageType) {
var checker = new Checker(pageType);
checker.run();
}
//----utility----
function conv2ISBN13(str) {
var result = "978" + str.substr(0,9);
var checkDigit = 38;
for (var i = 0; i < 9; i++) {
var c = str.charAt(i);
checkDigit += ( i % 2 == 0 )? c * 3 : c * 1;
}
checkDigit = (10 - (checkDigit % 10)) % 10;
result += checkDigit;
return result;
}
function getElementsByXPath(xpath, doc) {
var nodes = doc.evaluate(xpath, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var data = [];
for (var i = 0, len = nodes.snapshotLength; i < len; i++) {
data.push(nodes.snapshotItem(i));
}
return data;
}
function checkISBN(isbn){
if (!isbn) return false;
try {
isbn = isbn.toLowerCase().replace(/-/g,'').replace(/ /g,'');
if (isbn.length != 10) return false;
var sum = 0;
var weight = 10;
for (var i = 0; i < 9; i++) {
sum += (isbn[i] * weight--);
}
sum += (isbn[9] == 'x' ? 10 : isbn[9]*1);
if (sum % 11) return false;
} catch (e) { return false; }
return isbn;
}
function log(str) {
unsafeWindow.console.log(str);
}
本ではないものも検索することがあるので、ISBNかどうかチェックするようにした。
// ==UserScript==
// @name Amazon Cross Book Check+Post
// @namespace http://kiri.vox.com/
// @include http://www.amazon.co.jp/*
// @include http://amazon.co.jp/*
// ==/UserScript==
//
// version: 2009.1.14
//
// オリジナルはadda氏のAmazon Cross Book Check(http://d.hatena.ne.jp/adda/20081112/1226463084)です。
//
var DEFAULT_AUTO_START = false;
var INTERVAL = 1000;
var TIMEOUT = 15000;
var SITEINFO = [
{
label: 'BOOKOFF Online',
url: 'http://www.bookoffonline.co.jp/display/L001,st=u,q=',
regexp: /\u4E2D\u53E4\u8CA9\u58F2\u4FA1\u683C<\/th>\uFFE5([\d,]+)/,
isbn13: true,
disabled: false
},
{
label: 'livedoor BOOKS',
url: 'http://books.livedoor.com/search/?v=2&word=',
afterISBN: '&type=isbn',
regexp: /\u4E2D\u53E4\u4FA1\u683C\uFF1A([\d,]+)/,
disabled: false
},
{
label: '\u53E4\u672C\u5E02\u5834', //古本市場
url: 'http://www.search.ubook.co.jp/search/search.php?category1=all&shousai_r=1&isbn=',
regexp: /span class="biggerlink">([\d,]+)[\s\S]*?<input type="checkbox"/,
disabled: false
},
{
label: 'eBOOKOFF',
url: 'http://www.ebookoff.co.jp/cmdtysearch?Ctgry=1002&hdnSearchFlg=1&chkOld=1&txtISBNCode=',
regexp: /([\d,]+)/,
isbn13: true,
disabled: false
},
{
label: 'bk1',
regexp: /info/,
url: 'http://www.bk1.jp/webap/user/SchDetailBibList.do?isbn=',
disabled: false
},
{
label: '\u6A2A\u6D5C\u5E02\u7ACB\u56F3\u66F8\u9928', //横浜市立図書館
url: 'http://www.lib.city.yokohama.jp/cgi-bin/Swissken.sh?0+-+0',
regexp: /<A HREF="\/cgi-bin\/Swwwsvis\.sh\?[^"]+"/g,
disabled: false,
// 以下はPOST処理のために追加した
post: true,
// http://saltyduck.blog12.fc2.com/blog-entry-30.htmlを参考した
buildQuery: function(isbn) {
var fields = {tgid:'010A', kkey:'', skey:'', srs10:1, srs11:1, srs12:1, ktyp4:'SHK', key4:'', itfg4:'F'};
for (var i = 0; i < 4; i++) {
fields['ktyp'+i] = 'SHK';
fields['key'+i] = '';
fields['itfg'+i] = 'F';
fields['ron'+i] = 'm';
}
fields.tkey = isbn;
var a = [];
for (var k in fields) {
a.push(k + '=' + fields[k]);
}
return a.join('&');
},
getContentURL: function(res) {
var books = res.responseText.match(/<A HREF="\/cgi-bin\/Swwwsvis\.sh\?[^"]+"/g); //";
var url = '';
if(books) {
url = books.map(function(a){
a = a.replace(/<A HREF=\"/, 'http://www.lib.city.yokohama.jp');
return a;
});
}
return url;
},
},
/* template
{
label: '',
url: '',
afterISBN: '',
regexp: //,
isbn13: ,
bothISBN: ,
disabled: ,
},
*/
]
var PAGEINFO = [
{
type: 'wishlist',
urlExp: 'wishlist',
insertAfter: '//tbody[@name]/descendant::tbody[1]/tr[last()]',
asinLink: '//td[@class="small"]/strong/a',
autoStart: true
},
{
type: 'search',
urlExp: 'keywords=',
insertAfter: '//div[@class="productData"]/*[last()]',
asinLink: '//div[@class="productData"]/div[1]/a',
autoStart: true
},
{
type: 'bestsell',
urlExp: '/bestsellers/',
insertAfter: '//table[@class="priceBox"]/tbody/tr[last()]',
asinLink: '//strong[@class="sans"]/a',
autoStart: true
},
{
type: 'recommend',
urlExp: '/yourstore/',
insertAfter: '//table[@class="priceBox"]/tbody/tr[last()]',
asinLink: '//td[@width="100%"]/a',
autoStart: true
},
{
type: 'listmania',
urlExp: '/lm/',
insertAfter: '//td[@class="listItem"]/table/*[last()]',
asinLink: '//td[@class="listItem"]/a',
autoStart: true
},
{
type: 'history',
urlExp: '/history/',
insertAfter: '//table[@class="priceBox"]/tbody/tr[last()]',
asinLink: '//td[@width="100%"]/a',
autoStart: true
}
]
var STYLE = <><![CDATA[
table.ACBC {
font-size: 13px;
margin-top: 3px;
}
table.ACBC td.label {
padding-right:1em;
}
table.ACBC span.loading {
color: #39c;
}
table.ACBC a.notfound {
color: #666 !important;
text-decoration: none;
font-family: arial,verdana,helvetica,sans-serif;
}
table.ACBC a.found {
color: #900 !important;
font-weight: bold;
text-decoration: underline !important;
}
]]></>
function Checker(pageType) {
this.pageType = pageType;
this.index = 0;
}
Checker.prototype.run = function() {
GM_addStyle(STYLE);
SITEINFO = SITEINFO.filter(function(i){ return !(i.disabled) });
if (this.pageType == 'detail') {
var t = document.getElementById('handleBuy');
if (!t) return;
var target = t.lastChild.previousSibling.lastChild.lastChild;
var isbn = getISBN(document.location.href);
if (!checkISBN(isbn)) return;
var item = new Item(isbn, target);
item.load();
} else {
this.setIteration(this.pageType);
}
}
Checker.prototype.setIteration = function(pinfo) {
if (DEFAULT_AUTO_START && pinfo.autoStart) {
this.iterate(pinfo);
} else {
var self = this;
GM_registerMenuCommand('ACBC+P - start', function() {
self.iterate(pinfo);
});
}
}
Checker.prototype.iterate = function(pinfo) {
var self = this;
var f = function() {
var targets = getElementsByXPath(pinfo.insertAfter, document);
var links = getElementsByXPath(pinfo.asinLink, document);
var i = self.index, len = targets.length;
(function g(){
if (!(i < len)) return;
var isbn = getISBN(links[i].href);
if (checkISBN(isbn)) {
var item = new Item(isbn, targets[i]);
item.load();
};
i++;
setTimeout(g, INTERVAL);
})();
self.index = len;
};
f();
if (window.AutoPagerize) window.AutoPagerize.addFilter(f);
}
function Item(isbn, target) {
this.isbn = isbn;
this.target = target;
this.timers = [];
}
Item.prototype.load = function() {
this.insertTable();
var f = function(n) {
var info = SITEINFO[n];
var url = self.buildURL(info);
self.timers[n] = setTimeout(function(){
self.insertContent(n, "Timeout")
}, TIMEOUT);
if (!info.post) {
GM_xmlhttpRequest({
method: 'get',
url: url,
onload: function(res) {
clearTimeout(self.timers[n]);
self.insertContent(n, self.getContent(res, info, url));
}
})
} else {
GM_xmlhttpRequest({
method: 'post',
url: url,
data: info.buildQuery(self.isbn),
onload: function(res) {
clearTimeout(self.timers[n]);
self.insertContent(n, self.getContent(res, info, !info.getContentURL? url : (info.getContentURL(res))[0]));
}
})
}
}
for (var i = 0, len = SITEINFO.length; i < len; i++) {
var self = this;
f(i);
}
}
Item.prototype.insertTable = function() {
var tr = document.createElement("tr");
var td = document.createElement("td");
var inner = "";
");
for (var i = 0, len = SITEINFO.length; i < len; i++) {
inner += (""); " + SITEINFO[i].label + " loading...
}
td.innerHTML = (inner += "
tr.appendChild(td);
this.target.parentNode.insertBefore(tr, this.target.nextSibling);
this.table = tr.firstChild.firstChild;
}
Item.prototype.buildURL = function(info) {
var url = info.url;
if (info.isbn13) {
url += conv2ISBN13(this.isbn);
} else if (info.bothISBN) {
url += (conv2ISBN13(this.isbn) + "|" + this.isbn);
} else if ( !info.post ) {
url += this.isbn;
}
if (info.afterISBN) url += info.afterISBN;
return url;
}
Item.prototype.getContent = function(res, info, url) {
if (res.responseText.match(info.regexp)) {
var price = (RegExp.$1.length > 0)? "\uFFE5 "+ RegExp.$1 : "Found";
return "" + price + "";
} else {
return "NotFound";
}
}
Item.prototype.insertContent = function(n, str) {
this.table.firstChild.childNodes[n].childNodes[1].innerHTML = str;
}
function getPageType(url) {
for (var i = 0, len = PAGEINFO.length; i < len; i++) {
var pinfo = PAGEINFO[i];
if (url.indexOf(pinfo.urlExp) != -1) return pinfo;
}
if (getISBN(url)) return 'detail';
return false;
}
function getISBN(str) {
if (str.match(/[\/\=]([\d]{9}[\dX])[^&]/)) return RegExp.$1;
}
//----main----
var pageType = getPageType(document.location.href);
if (pageType) {
var checker = new Checker(pageType);
checker.run();
}
//----utility----
function conv2ISBN13(str) {
var result = "978" + str.substr(0,9);
var checkDigit = 38;
for (var i = 0; i < 9; i++) {
var c = str.charAt(i);
checkDigit += ( i % 2 == 0 )? c * 3 : c * 1;
}
checkDigit = (10 - (checkDigit % 10)) % 10;
result += checkDigit;
return result;
}
function getElementsByXPath(xpath, doc) {
var nodes = doc.evaluate(xpath, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var data = [];
for (var i = 0, len = nodes.snapshotLength; i < len; i++) {
data.push(nodes.snapshotItem(i));
}
return data;
}
// http://saltyduck.blog12.fc2.com/blog-entry-30.htmlを参考した
function checkISBN(isbn){
if (!isbn) return false;
try {
isbn = isbn.toLowerCase().replace(/-/g,'').replace(/ /g,'');
if (isbn.length != 10) return false;
var sum = 0;
var weight = 10;
for (var i = 0; i < 9; i++) {
sum += (isbn[i] * weight--);
}
sum += (isbn[9] == 'x' ? 10 : isbn[9]*1);
if (sum % 11) return false;
} catch (e) { return false; }
return isbn;
}
function log(str) {
unsafeWindow.console.log(str);
}
日記をみているときに本人のコメントが目立つようにするスクリプトMixi Owner Highlightを見つけた。
mixiのほうが変わって効かなくなってるようなので、直してつかってる。
if (allDt[i].className == 'commentTitle clearfix')
↓
'commentTitle'
あと、色が控えめだったので、調整した。
allDt[i].style.background = '#ffdad3';
↓
'#ffaaaa';

suzpanさん連写音がかっこいいですよ... read more
on QuadCameraで写真を撮ってみた