Skip to content

Instantly share code, notes, and snippets.

@tkawa
Created January 16, 2011 02:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tkawa/781494 to your computer and use it in GitHub Desktop.
Save tkawa/781494 to your computer and use it in GitHub Desktop.
リプライをTL上に自動的に展開表示する twicli プラグイン
var embedReply, tweetCache = {};
(function () {
// APIが足りない時用proxy(気休め)
var proxies = [
{
url: twitterAPI + 'statuses/show/{id}.json?suppress_response_codes=true',
filter: function (d) { return d }
},
{
url: 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20twitter.status%20where%20id%3D{id}%3B&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys',
filter: function (d) {
var tw = d.query.results.status;
if (!tw) return tw; // TODO: エラー処理
for (k in tw) {
if (tw[k] == 'false') tw[k] = false;
}
for (k in tw.user) {
if (tw.user[k] == 'false') tw.user[k] = false;
}
return tw;
}
}
];
// トリガーになるボタンをつくる
function makeEmbedButton(element, tw) {
//console.log(['makeEmbedButton', element, tw]);
tw = tw.retweeted_status || tw;
if (tw.in_reply_to_status_id_str) {
// getElementsByClassName使ってるのでIEでは動かない?
var reply = element.getElementsByClassName('reply');
if (reply.length > 0) {
reply = reply[0];
var embrep = document.createElement('a');
embrep.className = 'button embrep';
embrep.setAttribute('href', '#');
/*
embrep.onclick = function () {
embedReply(tw.in_reply_to_screen_name, tw.in_reply_to_status_id_str, this);
}
*/
embrep.setAttribute('onclick',
"embedReply('"
+ tw.in_reply_to_screen_name
+ "','"
+ tw.in_reply_to_status_id_str
+ "',this);return false;"
);
embrep.innerHTML = '@';
reply.parentNode.insertBefore(embrep, reply);
} else {
console.log(['reply button not found', element]);
}
}
}
// 上でつくった埋め込みボタンを自動的に押す
function autoEmbed(tw, tw_node, nr_show) {
//console.log(['autoEmbed', tw, tw_node, nr_show]);
if (nr_show > 0) {
links = tw_node.getElementsByClassName('embrep');
//console.log(['search embrep', links]);
for (var i = 0; i < links.length; i++) {
//console.log(['click function', links[i].onclick, links[i]]);
if (getTweetDiv(links[i]).id.indexOf('emb-') == -1) { // 今のところ、2つ以上は自動で開かない
links[i].onclick(); // click()ではなぜか動かなかった(Chrome)
}
}
}
}
// ボタンから呼ばれる
embedReply = function (user, id, elem) {
//console.log(arguments);
$('loading').style.display = 'block';
fetchTweet(id, function (tw) {
//console.log(tw);
$('loading').style.display = 'none';
var el = document.createElement('div');
el.id = 'emb-'+id;
el.className = 'emb';
el.style.paddingLeft = '32px'; //とりあえずのスタイル
el.innerHTML = makeHTML(tw, false, 'emb');
el.tw = tw;
callPlugins("newMessageElement", el, tw, 'emb');
var p_elem = getTweetDiv(elem);
if (p_elem.parentNode) {
p_elem.parentNode.insertBefore(el, p_elem.nextSibling);
// twShowToNode の duplication の処理のところで呼ばれる removeChild を差し替え
// addEventListener('DOMNodeRemoved', ... ) のほうがいいんじゃないかと思いつつ
p_elem.parentNode.removeChild = removeChildAndEmbedded;
}
elem.parentNode.removeChild(elem);
});
};
// リプライもまとめて削除する差し替え用関数
function removeChildAndEmbedded (removedNode) {
var removeChild_original = $('re').removeChild; // Element.prototype.removeChild のつもり
var emb = removedNode.nextSibling;
while (emb && emb.id.indexOf('emb-') != -1) {
var emb_next = emb.nextSibling;
removeChild_original.call(this, emb);
emb = emb_next;
}
return removeChild_original.call(this, removedNode);
};
// API消費が激しい可能性があるのでできるだけキャッシュしておく
function fetchTweet(id, callback) {
if (tweetCache[id]) {
callback(tweetCache[id]);
return;
}
var d = $('tw-' + id) || $('re-' + id) || $('tw2c-' + id) || $('emb-' + id);
if (d && d.tw) {
tweetCache[id] = d.tw;
callback(d.tw);
} else {
var proxy = proxies[0]; // 0はproxyなし
var url = proxy.url.replace(/\{id\}/, id);
xds.load(url, function (tw) {
tw = proxy.filter(tw);
tweetCache[id] = tw;
callback(tw);
});
}
}
// 任意のElementから親をたどっていって、含まれるツイートのdivを得る
function getTweetDiv(elem) {
var t = elem;
while (t && !(t.tagName.toLowerCase() == 'div' && /^[a-z0-9]+-\d{10,}$/.test(t.id))) t = t.parentNode;
return t;
}
// twShowToNode関数に独自のフックポイントを追加
var twShowToNode_original = twShowToNode;
twShowToNode = function (tw, tw_node) {
var nr_show = twShowToNode_original.apply(window, arguments);
callPlugins("afterTwShowToNode", tw, tw_node, nr_show, arguments);
return nr_show;
};
registerPlugin({
newMessageElement: makeEmbedButton,
afterTwShowToNode: autoEmbed
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment