// ==UserScript== // @name Nested Twitter Replies // @namespace http://blog.bcse.info/nested-twitter-replies // @include http://twitter.com/* // ==/UserScript== bcseNTR = { template: { "status": false, "content": null }, regexp: { "id": new RegExp("%id%", "g"), "text": new RegExp("%text%", "g"), "created_at": new RegExp("%created_at%", "g"), "user_screen_name": new RegExp("%user.screen_name%", "g"), "user_name": new RegExp("%user.name%", "g"), "user_profile_image_url": new RegExp("%user.profile_image_url%", "g") }, init: function() { //console.log("Locate Replies"); var thread_node = $(".hentry[id] a[href*='status']:contains('in reply to')"); if (thread_node.length > 0) { /// Generate Template var example_tweet = $(".hentry[id]:not(:has(.del)):first"); if (example_tweet.length == 0) { example_tweet = $(".hentry[id]:first"); } bcseNTR.template.content = example_tweet.clone(); bcseNTR.build_template(bcseNTR.template.content.attr("id").match(/^\D+(\d+)$/)[1]); } thread_node.each(function(){ //console.log("Get Status: #" + id); var parent = $(this).parents(".hentry[id]"); var parent_id = $(parent).attr("id").match(/^\D+(\d+)$/)[1]; //console.log("New Thread: #" + parent_id); bcseNTR.get_from_html($(this).attr("href"), parent_id); }); }, build_template: function(id) { //console.log("Build Template"); bcseNTR.template.content.find(".entry-content").text("%text%"); bcseNTR.template.content.find(".entry-meta").html('%created_at%'); bcseNTR.template.content.find("img.photo").attr("src", "%user.profile_image_url%"); var user = bcseNTR.template.content.find(".status-body strong a"); var screen_name = user.length > 0 ? user.text() : null; var full_name = user.length > 0 ? user.attr("title") : null; bcseNTR.template.content = '
  • ' + bcseNTR.template.content.html() + '
  • '; bcseNTR.template.content = bcseNTR.template.content.replace(new RegExp(id, "g"), "%id%"); bcseNTR.template.content = bcseNTR.template.content .replace(new RegExp(screen_name, "g"), "%user.screen_name%") .replace(new RegExp(full_name, "g"), "%user.name%"); //console.log("Template is Generated"); bcseNTR.template.status = true; }, get_from_html: function(url, parent_id) { var id = url.match(/\/(\d+)\/?$/); id = id[1]; /// Wait til template is generated if (bcseNTR.template.status) { //console.log("If status exists, just use it."); var reply = $("#status_" + id); if (reply.length > 0) { //console.log("Append: #" + id); $("#status_" + parent_id).after(reply.css("margin-left", "24px")); /// If this tweet is not root, try to get its parent. var in_reply_to_status_id = reply.find("a[href*='status']:contains('in reply to')").attr("href") || null; if (in_reply_to_status_id) { bcseNTR.get_from_html(in_reply_to_status_url, id); } return; } //console.log("Get Status via HTML: #" + id); $.get(url, function(tweetPage, textStatus){ tweetPage = $(tweetPage); var in_reply_to_status_url = tweetPage.find("a[href*='status']:contains('in reply to')").attr("href") || null; var in_reply_to_status_id = in_reply_to_status_url != null ? in_reply_to_status_url.match(/\/(\d+)\/?$/) : null; var tweet = { "user": { "screen_name": tweetPage.find(".screen-name").text(), "name": tweetPage.find(".full-name").text(), "profile_image_url": tweetPage.find(".thumb img").attr("src") }, "id": id, "text": tweetPage.find(".entry-content").html(), "created_at": tweetPage.find(".published").text(), "in_reply_to_status_id": in_reply_to_status_id, "in_reply_to_status_url": in_reply_to_status_url }; var html = bcseNTR.html(tweet); //console.log("Append: #" + id); $("#status_" + parent_id).after(html); /// If this tweet is not root, try to get its parent. if (tweet.in_reply_to_status_id) { bcseNTR.get_from_html(tweet.in_reply_to_status_url, id); } }, "html"); } else { window.setTimeout(function(){bcseNTR.get(id, parent_id)}, 100); } }, html: function(tweet) { //console.log("Generate HTML: #" + tweet.id); var html = bcseNTR.template.content .replace(bcseNTR.regexp.id, tweet.id) .replace(bcseNTR.regexp.text, tweet.text) .replace(bcseNTR.regexp.created_at, tweet.created_at) .replace(bcseNTR.regexp.user_screen_name, tweet.user.screen_name) .replace(bcseNTR.regexp.user_name, tweet.user.name) .replace(bcseNTR.regexp.user_profile_image_url, tweet.user.profile_image_url); return html; } } function GM_wait() { if (typeof unsafeWindow.jQuery == "undefined") { window.setTimeout(GM_wait, 100); } else { $ = unsafeWindow.jQuery; bcseNTR.init(); } } GM_wait();