|
/* Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php */ |
|
(function (window, name) { |
|
// ******************************************************* |
|
// Define package |
|
// ------------------------------------------------------- |
|
var pkg = window[name] = { |
|
// blogger construct |
|
feedAPI: "http://www.blogger.com/feeds/", |
|
entryTracker: "https://blogger.googleusercontent.com/tracker/", |
|
// topsy construct |
|
topsyURI: "http://topsy.com/", |
|
topsyAPI: "http://otter.topsy.com/trackbacks.js?callback=?" |
|
}; |
|
|
|
if (!Array.indexOf) { |
|
Array.prototype.indexOf = function (o) { |
|
for (var i = 0; i < this.length; i++) { |
|
if (this[i] === o) { |
|
return i; |
|
} |
|
} |
|
return -1; |
|
}; |
|
} |
|
|
|
pkg.id = (function () { |
|
var links = document.getElementsByTagName("link"); |
|
for (var i = 0; i < links.length; i++) { |
|
if (links[i].rel == "EditURI") { |
|
return links[i].href.split("=")[1]; |
|
} |
|
} |
|
})(); |
|
|
|
pkg.init = function (id) { |
|
pkg.id = id; |
|
}; |
|
|
|
// ******************************************************* |
|
// Define package.util |
|
// ------------------------------------------------------- |
|
pkg.util = {}; |
|
|
|
// ******************************************************* |
|
// Define package.util.storage |
|
// ------------------------------------------------------- |
|
pkg.util.storage = (function () { |
|
if (!(localStorage && JSON)/* || true */) { |
|
return { |
|
get: function () { return null; }, |
|
put: function () { }, |
|
add: function () { }, |
|
remove: function () { }, |
|
contains: function () { return false; } |
|
}; |
|
} |
|
|
|
// privates |
|
var isExpiry = function (data) { |
|
if (data.expire) { |
|
var expire = new Date(data.expire); |
|
if (expire.getTime() > new Date().getTime()) return false; |
|
} else { |
|
return false; |
|
} |
|
return true; |
|
}; |
|
|
|
//publics |
|
return { |
|
get: function (key, vkey) { |
|
var data = JSON.parse(localStorage.getItem(key)); |
|
if (data) { |
|
if (!isExpiry(data)) { |
|
return data.value; |
|
} |
|
localStorage.removeItem(key); |
|
} |
|
return null; |
|
}, |
|
put: function (key, value, expire) { |
|
var data = { value: value }; |
|
var date = new Date(); |
|
if (expire) date.setTime(date.getTime() + expire); |
|
else date.setTime(date.getTime() + (60 * 60 * 24 * 7 * 1000)); |
|
data.expire = date.toString(); |
|
localStorage.setItem(key, JSON.stringify(data)); |
|
}, |
|
add: function (key, value, expire) { |
|
if (this.contains(key)) { |
|
var data = this.get(key); |
|
for (var i in value) data[i] = value[i]; |
|
this.put(key, data, expire); |
|
} else { |
|
this.put(key, value, expire); |
|
} |
|
}, |
|
remove: function (key) { |
|
localStorage.removeItem(key); |
|
}, |
|
contains: function (key) { |
|
if (!(key in localStorage)) { |
|
return false; |
|
} |
|
var data = JSON.parse(localStorage.getItem(key)); |
|
if (!isExpiry(data)) return true; |
|
else localStorage.removeItem(key); |
|
return false; |
|
} |
|
}; |
|
})(); |
|
|
|
// ******************************************************* |
|
// Define package.util.picasa |
|
// ------------------------------------------------------- |
|
pkg.util.picasa = (function () { |
|
// publics |
|
return { |
|
isPicasaImage: function (uri) { |
|
return |
|
uri.search(/^(http|https)+\:\/\/lh\d+\.googleusercontent.com\//i) == -1 && |
|
uri.search(/^(http|https)+\:\/\/\d+\.bp\.blogspot\.com\//i) == -1 && |
|
uri.search(/^(http|https)+\:\/\/lh\d+\.ggpht.com\//i) == -1; |
|
}, |
|
changeOption: function (uri, option) { |
|
if (!this.isPicasaImage) { |
|
return null; |
|
} |
|
var array = uri.split('/'); |
|
if (array.length == 9) array[7] = option; |
|
else if (array.length == 8) array[7] = option + '/' + array[7]; |
|
else return null; |
|
return array.join('/'); |
|
} |
|
}; |
|
})(); |
|
|
|
// ******************************************************* |
|
// Define package.util.topsy |
|
// ------------------------------------------------------- |
|
pkg.util.topsy = function (uri) { |
|
// privates |
|
var callback = [], option = { |
|
maxResult: 15, imgSize: 48, |
|
noTweet: "ツイートがありません", |
|
moreTweet: "全てのツイートを見る" |
|
}; |
|
var domains = []; |
|
var dateFormat = function (date) { |
|
var dt = new Date(date * 1000); |
|
var year = dt.getYear(); |
|
var month = dt.getMonth() + 1; |
|
var day = dt.getDate(); |
|
if (year < 2000) { year += 1900; } |
|
return year + "/" + month + "/" + day; |
|
}; |
|
|
|
// publics |
|
return { |
|
option: function (key, value) { |
|
option[key] = value; |
|
return this; |
|
}, |
|
count: function (e) { |
|
callback.push(function (data) { |
|
jQuery(function () { jQuery(e).text(data.response.trackback_total); }); |
|
}); |
|
return this; |
|
}, |
|
trackback: function (e) { |
|
callback.push(function (data) { |
|
var ul = jQuery("<ul />"); |
|
if (data.response.list.length == 0) { |
|
jQuery("<div />").text(option.noTweet).appendTo(e); |
|
} else { |
|
var list = data.response.list; |
|
for (var j = 0; j < list.length; j++) { |
|
var tweet = list[j]; |
|
jQuery("<li />").append( |
|
jQuery("<a />").attr("href", tweet.author.url).append( |
|
jQuery("<img />").attr({ |
|
src: tweet.author.photo_url, |
|
alt: tweet.author.name, title: tweet.author.name, |
|
width: option.imgSize, height: option.imgSize |
|
}) |
|
), |
|
jQuery("<span />").addClass("name").append( |
|
jQuery("<a />").attr("href", tweet.author.url).text(tweet.author.name) |
|
), |
|
jQuery("<span />").addClass("tweet").text(tweet.content), |
|
jQuery("<span />").addClass("date").text(dateFormat(tweet.date)) |
|
).appendTo(ul); |
|
} |
|
} |
|
ul.appendTo(e); |
|
jQuery("<div />").append( |
|
jQuery("<a />").addClass("button").attr("href", pkg.topsyURI + uri).text(option.moreTweet) |
|
).appendTo(e); |
|
}); |
|
return this; |
|
}, |
|
execute: function () { |
|
var uris = [uri]; |
|
|
|
//if (uri.indexOf("blogspot.com") != -1) { |
|
// uris.push(uri.replace("blogspot.com", "blogspot.jp")); |
|
//} |
|
//if (uri.indexOf("blogspot.jp") != -1) { |
|
// uris.push(uri.replace("blogspot.jp", "blogspot.com")); |
|
//} |
|
|
|
var r = { response: { list: [], trackback_total: 0} }; |
|
var f = function (data) { |
|
r.response.trackback_total += data.response.trackback_total; |
|
var tweets = data.response.list; |
|
for (var i = 0; i < tweets.length; i++) { |
|
r.response.list.push(tweets[i]); |
|
} |
|
if (uris.length != 0) { |
|
jQuery.getJSON(pkg.topsyAPI, { url: uris.shift(), perpage: option.maxResult }, f); |
|
} else { |
|
r.response.list.sort(function (a, b) { |
|
return b.date - a.date; |
|
}); |
|
for (var j = 0; j < callback.length; j++) { |
|
callback[j](r); |
|
} |
|
} |
|
}; |
|
|
|
jQuery.getJSON(pkg.topsyAPI, { url: uris.shift(), perpage: option.maxResult }, f); |
|
} |
|
}; |
|
}; |
|
|
|
// ******************************************************* |
|
// Define package.util.uri |
|
// ------------------------------------------------------- |
|
pkg.util.uri = function (uri) { |
|
var match = uri.match(/^(.+?):\/\/(.+?):?(\d+)?(\/.*)?$/i); |
|
var u = { protocol: match[1], domain: match[2], path: match[4] }; |
|
return { |
|
protocol: function () { return u.protocol }, |
|
domain: function () { return u.domain; }, |
|
path: function () { return u.path; }, |
|
labelUri: function (labels, option) { |
|
var r = [u.protocol, "://", u.domain, "/search/label/"]; |
|
for (var i = 0; i < labels.length; i++) |
|
r.push(labels[i] + '/'); |
|
r.push(option || ''); |
|
return r.join(''); |
|
} |
|
}; |
|
}; |
|
|
|
// ******************************************************* |
|
// Define package.util.feed |
|
// ------------------------------------------------------- |
|
pkg.util.feed = (function () { |
|
// privates |
|
var entry = function (type) { |
|
var labels = []; |
|
return { |
|
label: function (l) { |
|
labels = l; |
|
return this; |
|
}, |
|
build: function () { |
|
var r = [pkg.feedAPI, pkg.id, "/posts/", type]; |
|
if (labels.length > 0) { |
|
r.push("/-/"); |
|
for (var i = 0; i < labels.length; i++) { |
|
r.push(encodeURI(labels[i]).replace("#", "%23") + '/'); |
|
} |
|
} |
|
return r.join(''); |
|
} |
|
}; |
|
}; |
|
|
|
var comment = function (type) { |
|
var id = -1; |
|
return { |
|
entryId: function (i) { |
|
id = i; |
|
return this; |
|
}, |
|
build: function () { |
|
var r = [pkg.feedAPI, pkg.id, '/']; |
|
if (id !== -1) { |
|
r.push(id + '/'); |
|
} |
|
r.push("comment/"); |
|
r.push(type); |
|
return r.join(''); |
|
} |
|
}; |
|
}; |
|
|
|
var option = function () { |
|
// privates |
|
var params = { alt: "json" }, umax = -1, umin = -1, offset = null; |
|
|
|
var convertUTCDate = function (date, offset) { |
|
var format = function (value) { |
|
if (value < 10) value = '0' + value; |
|
return value; |
|
}; |
|
var dt = new Date(date * 1000); |
|
var year = dt.getUTCFullYear(); |
|
if (year < 2000) year += 1900; |
|
var month = format(dt.getUTCMonth() + 1); |
|
var day = format(dt.getUTCDate()); |
|
var hour = format(dt.getUTCHours()); |
|
var min = format(dt.getUTCMinutes()); |
|
var sec = format(dt.getUTCSeconds()); |
|
return [year, "-", month, "-", day, 'T', hour, ':', min, ':', sec, offset].join(''); |
|
}; |
|
|
|
// publics |
|
return { |
|
orderby: function (o) { params["orderby"] = o; return this; }, |
|
limits: function (l) { params["max-results"] = l; return this; }, |
|
utcMax: function (m) { umax = m; return this; }, |
|
utcMin: function (m) { umin = m; return this; }, |
|
utcOffset: function (o) { offset = o; return this; }, |
|
offset: function (o) { params["start-index"] = o; return this; }, |
|
path: function (uri) { |
|
params["path"] = pkg.util.uri(uri).path(); |
|
return this; |
|
}, |
|
build: function () { |
|
if (params["orderby"] != undefined) { |
|
var maxKey, minKey; |
|
if (params["orderby"] === "published") { |
|
maxKey = "published-max"; |
|
minKey = "published-min"; |
|
} else if (params["orderby"] === "updated") { |
|
maxKey = "update-max"; |
|
minKey = "update-min"; |
|
} |
|
if (umax != -1) params[maxKey] = convertUTCDate(umax, offset); |
|
if (umin != -1) params[minKey] = convertUTCDate(umin, offset); |
|
} |
|
return params; |
|
} |
|
}; |
|
}; |
|
|
|
// publics |
|
return { |
|
queryFactory: function (kind, type) { |
|
return { |
|
uri: { |
|
"entry": entry(type), |
|
"comment": comment(type) |
|
}[kind], |
|
option: option(), |
|
fetch: function (callback) { |
|
jQuery.getJSON(this.uri.build() + "?callback=?", this.option.build(), callback); |
|
//AjaxManager().request(this.uri.build() + "?callback=?", this.option.build(), callback); |
|
} |
|
}; |
|
} |
|
}; |
|
})(); |
|
|
|
// ******************************************************* |
|
// Define package.util.entryAdapter |
|
// ------------------------------------------------------- |
|
pkg.util.entryAdapter = function (entry) { |
|
return { |
|
raw: function () { return entry; }, |
|
title: function () { return entry.title.$t; }, |
|
uri: function () { |
|
for (var i = 0; i < entry.link.length; i++) { |
|
var link = entry.link[i]; |
|
if (link.rel == "alternate") return link.href; |
|
} |
|
return null; |
|
}, |
|
content: function () { return entry.content.$t; }, |
|
updated: function () { return new Date(entry.updated.$t); }, |
|
published: function () { return new Date(entry.published.$t); }, |
|
label: function () { |
|
var r = [], c = entry.category; |
|
for (var i = 0; i < c.length; i++) r.push(c[i].term); |
|
return r; |
|
}, |
|
image: function (o) { |
|
var c = entry.content.$t; |
|
var img = jQuery(c).find("img:first"); |
|
var src = img.attr("src"); |
|
if (!src || src.indexOf(pkg.entryTracker) != -1) return null; |
|
return pkg.util.picasa.changeOption(src, o || "s300-c"); |
|
} |
|
}; |
|
}; |
|
|
|
// ******************************************************* |
|
// Define package.ajax |
|
// ------------------------------------------------------- |
|
pkg.ajax = {}; |
|
|
|
// ******************************************************* |
|
// Define package.ajax.related |
|
// ------------------------------------------------------- |
|
pkg.ajax.related = function (element) { |
|
// privates |
|
var labels = [], deny = [], callback = null, max = 20; |
|
|
|
var shuffle = function (array) { |
|
var pool, target; |
|
var length = array.length; |
|
for (var i = 0; i < length * 10; i++) { |
|
target = Math.floor(Math.random() * length); |
|
pool = array[target]; |
|
array.splice(target, 1); |
|
array.push(pool); |
|
array.reverse(); |
|
} |
|
return array; |
|
}; |
|
|
|
// publics |
|
return { |
|
callback: function (c) { callback = c; return this; }, |
|
label: function (l) { if (l != "Old") labels.push(l); return this; }, |
|
deny: function (d) { deny.push(d); return this; }, |
|
max: function (m) { max = m; return this; }, |
|
execute: function () { |
|
if (labels.length == 0) return; |
|
|
|
var result = [], unique = {}; |
|
|
|
var q = pkg.util.feed.queryFactory("entry", "default"); |
|
q.uri.label(labels); |
|
q.option.limits(max); |
|
|
|
q.fetch(function (data) { |
|
var entries = data.feed.entry; |
|
var adapter = pkg.util.entryAdapter; |
|
for (var i = 0; i < entries.length; i++) { |
|
var entry = adapter(entries[i]); |
|
var uri = entry.uri(); |
|
if (uri && entry.label().indexOf('Old') == -1 && deny.indexOf(uri) == -1 && !(uri in unique)) { |
|
unique[uri] = true; |
|
result.push(entry); |
|
} |
|
} |
|
|
|
if (result.length < max && labels.length > 0) { |
|
var nl = [labels.shift()]; |
|
if (nl.length != 0) { |
|
q.uri.label(nl); |
|
q.fetch(arguments.callee); |
|
return; |
|
} |
|
} |
|
|
|
if (callback) { |
|
callback(result); |
|
return; |
|
} |
|
|
|
result = shuffle(result); |
|
var ul = jQuery("<ul />"); |
|
for (var j = 0; j < result.length && j < max; j++) { |
|
var v = result[j], li = jQuery("<li />"), src = v.image("s72-c"); |
|
if (src) { |
|
li.append( |
|
jQuery("<span />").addClass("image").append( |
|
jQuery("<img />").attr({ src: src, width: 72, height: 72 }) |
|
) |
|
); |
|
} |
|
li.append( |
|
jQuery("<span />").addClass("link").append( |
|
jQuery("<a />").attr("href", v.uri()).text(v.title()) |
|
) |
|
); |
|
|
|
var ls = v.label(); |
|
for (var k = 0; k < ls.length; k++) { |
|
var label = ls[k]; |
|
li.append( |
|
jQuery("<span />").addClass("label").append( |
|
jQuery("<a />").attr("href", pkg.util.uri(v.uri()).labelUri([label], "?max-results=5")).text(label) |
|
) |
|
); |
|
} |
|
li.appendTo(ul); |
|
} |
|
jQuery(function () { |
|
ul.appendTo(element); |
|
}); |
|
}); |
|
} |
|
}; |
|
}; |
|
|
|
// ******************************************************* |
|
// Define package.ajax.entry |
|
// ------------------------------------------------------- |
|
pkg.ajax.entry = function (uri) { |
|
// privates |
|
var callback = [], storage = pkg.util.storage; |
|
var stringWriter = function (e, str) { jQuery(function () { jQuery(e).text(str); }); }; |
|
var attributeWriter = function (e, attr) { jQuery(function () { jQuery(e).attr(attr); }); }; |
|
|
|
// publics |
|
return { |
|
title: function (e) { |
|
var data = storage.get(uri); |
|
if (data && "title" in data) { |
|
stringWriter(e, data.title); |
|
} else { |
|
callback.push(function (entry) { |
|
var title = entry.title(); |
|
storage.add(uri, { title: title }); |
|
stringWriter(e, title); |
|
}); |
|
} |
|
return this; |
|
}, |
|
label: function (e, s) { |
|
var data = storage.get(uri); |
|
if (data && "label" in data) { |
|
stringWriter(e, data.label.join(s)); |
|
} else { |
|
callback.push(function (entry) { |
|
var label = entry.label(); |
|
storage.add(uri, { label: label }); |
|
stringWriter(label.join(s)); |
|
}); |
|
} |
|
return this; |
|
}, |
|
image: function (e, o) { |
|
var data = storage.get(uri); |
|
if (data && "image" in data) { |
|
attributeWriter(e, { src: data.image }); |
|
} else { |
|
callback.push(function (entry) { |
|
var src = entry.image(); |
|
if (src) { |
|
storage.add(uri, { image: src }); |
|
attributeWriter(e, { src: src }); |
|
} |
|
}); |
|
} |
|
return this; |
|
}, |
|
|
|
callback: function (c) { callback.push(c); return this; }, |
|
|
|
execute: function () { |
|
var q = pkg.util.feed.queryFactory("entry", "default"); |
|
q.option.limits(1).path(uri); |
|
|
|
q.fetch(function (data) { |
|
var entries = data.feed.entry; |
|
var adapter = pkg.util.entryAdapter; |
|
if (entries.length == 1) { |
|
var entry = entries[0]; |
|
for (var i = 0; i < callback.length; i++) { |
|
callback[i](adapter(entry)); |
|
} |
|
} |
|
}); |
|
} |
|
}; |
|
}; |
|
})(window, "bsoup"); |