There are 18 previous versions of this script.
// ==UserScript==
// @name Tweetpreview
// @namespace Chilla42o
// @description Tweetpreview shows you a live-preview of what you are going to post on Twitter.
// @version 0.4.2
// @include http://twitter.com/*
// ==/UserScript==
tweetpreview = {
status: null,
currentpage: null,
profile: {},
statustext: '',
pageswitched: true,
replyto:null,
replytostatusid:null,
initialize: function() {
if (typeof unsafeWindow.jQuery == 'undefined') {
window.setTimeout(tweetpreview.initialize, 120);
return false;
}
$ = unsafeWindow.jQuery;
jQuery = $;
twttr = unsafeWindow.twttr;
tweetpreview.currentpage = $('body').attr('id');
if (!tweetpreview.currentpage.match(/(home|replies|favorites|search|direct_messages|inbox|sent|create)/)) {
return false;
}
tweetpreview.addstyle([
'textarea#status, textarea#text { height:3.5em; }',
'body#direct_messages div#tweetpreview span.source,',
'body#inbox div#tweetpreview span.source,',
'body#sent div#tweetpreview span.source,',
'body#create div#tweetpreview span.source,',
'div#tweetpreview.direct-message span.source,',
'body#direct_messages div#tweetpreview a.inreplyto,',
'body#inbox div#tweetpreview a.inreplyto,',
'body#sent div#tweetpreview a.inreplyto, ',
'body#create div#tweetpreview a.inreplyto, ',
'div#tweetpreview.direct-message a.inreplyto { display:none }',
'body#create div#tweetpreview { margin-left:105px; }',
'div#tweetpreview { display:none; border:1px dashed #d2dada; border-style:dashed none; font-size:1.2em; line-height:1.1em; margin:10px; width:518px; padding:10px 0 10px 5px; }',
'div#tweetpreview:hover { background:#fafafa; }',
'div#tweetpreview * { margin:0; padding:0; }',
'div#tweetpreview > div { display:inline-block; vertical-align:top; margin:0; padding:0; }',
'div#tweetpreview div.avatar { width:48px; margin-right:8px; }',
'div#tweetpreview div.tweet { width: 420px; margin-right:4px; }',
'div#tweetpreview div.tweet p { margin:0; padding:0; }',
'div#tweetpreview div.tweet p.info { margin-top:3px; color:#999; font-size:0.764em; }',
'div#tweetpreview div.tweet p.info a { color:#999; cursor:pointer; }',
'div#tweetpreview div.tweet p.info a.reply { display:none; }',
'div#tweetpreview div.tweet p.message { margin:0; padding:0; }',
'div#tweetpreview div.actions { width:20px; }',
'div#tweetpreview div.actions a { display:none; width:24px; height:24px; background: url(http://s.twimg.com/a/1250203207/images/icon_reply.gif) no-repeat center; }',
'div#tweetpreview div.actions a.favorite { background-image:url(http://s.twimg.com/a/1250203207/images/icon_star_empty.gif); }',
'div#tweetpreview:hover div.actions a { display:block; }',
]);
/* detect page switch */
$('body').bind('DOMAttrModified', function(e) {
if (e.target.tagName == 'BODY'&& e.attrName == 'id') {
tweetpreview.pageswitch(e.prevValue, e.newValue);
tweetpreview.pageswitched = true;
} else if (e.target.tagName == 'LI' &&
e.attrName == 'class' &&
e.target.id.slice(-4) == '_tab' &&
e.prevValue.indexOf('loading') > -1 &&
e.newValue.indexOf('loading') == -1)
{
if (!tweetpreview.pageswitched) {
tweetpreview.pagerefresh(e.target.id.slice(0,-4));
}
tweetpreview.pageswitched = false;
}
});
if (tweetpreview.currentpage != 'create') {
tweetpreview.profile = {
username: $('span#me_name').html(),
name: $('span#me_name').parent('a').attr('title'),
image: $('div#profile img:first').attr('src'),
url: $('span#me_name').parent('a').attr('href'),
linkcolor: $('a#home_link').css('color')
}
$('ol#timeline span.actions a.reply').livequery('click', function() {
if (!tweetpreview.currentpage.match(/(home|replies|favorites|search)/)) return false;
if (reply = $(this).attr('href').match(/in_reply_to_status_id=([0-9]+)\&in_reply_to=([A-Za-z0-9_]{1,15})/)) {
tweetpreview.replytostatusid = reply[1];
tweetpreview.replyto = reply[2];
tweetpreview.statustext = tweetpreview.util.encodehtml($('textarea#status').val());
tweetpreview.update();
}
});
tweetpreview.createpreview();
} else {
tweetpreview.profile = {
username: $('meta[name=session-user-screen_name]').attr('content'),
url: 'http://twitter.com/'+$('meta[name=session-user-screen_name]').attr('content'),
linkcolor: $('a#home_link').css('color')
}
if (!twttr.form_authenticity_token) {
return false;
}
$.ajax({
type: 'GET',
url: 'http://twitter.com/status/user_timeline/'+tweetpreview.profile.username+'.json?count=1',
dataType: 'json',
data: {
twttr: true,
form_authenticity_token: twttr.form_authenticity_token
},
success: function(data) {
var details = [];
if (typeof data[0] == 'undefined') return false;
var userinfo = data[0].user;
tweetpreview.profile.image = userinfo.profile_image_url;
tweetpreview.profile.name = userinfo.name;
tweetpreview.createpreview();
}
});
}
},
createpreview: function() {
if (tweetpreview.currentpage != 'create') {
var aftertarget = $('div#dm_update_box');
} else {
var aftertarget = $('form#direct_message_form');
}
aftertarget.after([
'<div id="tweetpreview">',
'<div class="avatar">',
'<a title="'+tweetpreview.profile.name+'" href="'+tweetpreview.profile.url+'">',
'<img src="'+tweetpreview.profile.image+'" alt="'+tweetpreview.profile.username+'" />',
'</a>',
'</div>',
'<div class="tweet">',
'<p class="message">',
'<strong><a href="/'+tweetpreview.profile.username+'">'+tweetpreview.profile.username+'</a></strong>',
'<span id="tweetpreview-message">',
'</span>',
'</p>',
'<p class="info"><a>less than 0 seconds ago</a><span class="source"> from web</span> <a class="inreplyto"></a></p>',
'</div>',
'<div class="actions">',
'<a href="http://userscripts.org/scripts/show/53554" class="favorite" title="Tweetpreview"></a>',
'<a class="reply" title="reply to '+tweetpreview.profile.username+'"></a>',
'</div>',
'</div>'
].join("\n"));
$('textarea#status,textarea#text').bind('focus blur click keyup change', function() {
tweetpreview.statustext = tweetpreview.util.encodehtml($(this).val());
tweetpreview.update();
});
$('div#tweetpreview a[href]').livequery('click', function() { window.open($(this).attr('href')); return false; });
tweetpreview.focustextarea();
},
focustextarea:function() {
if (tweetpreview.currentpage.match(/(inbox|outbox)/)) {
$('textarea#text').focus();
} else {
$('textarea#status').focus();
}
},
pageswitch:function(previouspage, currentpage) {
tweetpreview.currentpage = currentpage;
$('textarea#text,textarea#status').val(tweetpreview.statustext);
tweetpreview.focustextarea();
},
pagerefresh:function(currentpage) {
tweetpreview.currentpage = currentpage;
tweetpreview.focustextarea();
},
format_hashtag_links:function (statustext, space, hashtag) {
return space+'<a class="hashtag" title="#'+hashtag+'" href="/search?q=%23'+escape(hashtag)+'">#'+hashtag+'</a>'
},
format_linktext:function(url) {
if (url.length > 41) {
return 'http://bit.ly/PrEV4';
} else {
return url.length > 27 ? url.substr(0, 27)+'...' : url;
}
},
format_site_links:function(url) {
return '<a href="'+url+'">'+tweetpreview.format_linktext(url)+'</a>';
},
format_cut_links:function(url) {
tweetpreview.statuslinks.push(url);
return '<a>'+(tweetpreview.statuslinks.length-1)+'</a>';
},
format_paste_links:function(linktag, linkindex) {
return tweetpreview.statuslinks[linkindex];
},
update:function() {
if (tweetpreview.statustext.length) {
if (!$('div#tweetpreview').is(':visible')) {
$('div#tweetpreview').fadeIn('fast');
}
if (tweetpreview.currentpage.match(/(home|replies|favorites|search)/)) {
if (tweetpreview.replyto && tweetpreview.replytostatusid) {
if (tweetpreview.statustext.indexOf('@'+tweetpreview.replyto) == -1) {
$('div#tweetpreview a.inreplyto').removeAttr('href').empty().hide();
} else {
$('div#tweetpreview a.inreplyto').attr('href', 'http://twitter.com/'+tweetpreview.replyto+'/status/'+tweetpreview.replytostatusid)
.html('in reply to '+tweetpreview.replyto)
.show();
}
} else {
$('div#tweetpreview a.inreplyto').removeAttr('href').empty().hide();
}
} else {
$('div#tweetpreview a.inreplyto').removeAttr('href').empty().hide();
}
tweetpreview.statuslinks = [];
if (tweetpreview.statustext.match(/^[dD] /)) {
$('div#tweetpreview').addClass('direct-message');
} else if ($('div#tweetpreview').hasClass('direct-message')) {
$('div#tweetpreview').removeClass('direct-message');
}
var previewhtml = tweetpreview.statustext.substr(0,160)
.replace(/^[dD] /, '')
.replace(/[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&~\+\?\/.=]+(?:#[A-Za-z0-9-_:%&~\+\?\/=]+)?/g, tweetpreview.format_site_links)
.replace(/<a[^>]+>[^<]+<\/a>/gmi, tweetpreview.format_cut_links)
.replace(/(^|\s|[\?\.,;:\!\-]+)#([^#\?\./,;:`‹›«»~!\[\]\(\)%\+\-\}\{\s]+)/g, tweetpreview.format_hashtag_links)
.replace(/<a[^>]+>[^<]+<\/a>/gmi, tweetpreview.format_cut_links)
.replace(/(^|[@\?\./,;:~\!\[\]\(\)%\+\-\}\{\s])@([a-zA-Z0-9_]{1,15})/g, '$1@<a href="/$2">$2</a>')
.replace(/<a>([0-9]+)<\/a>/gmi, tweetpreview.format_paste_links);
$('span#tweetpreview-message').html(previewhtml);
} else {
$('div#tweetpreview').fadeOut('fast');
}
},
addstyle: function(styles) {
var styleelement = $('style:last');
styles = styles.join("\n");
if (!styleelement.length) {
$('head').append("\n<style type=\"text/css\">\n"+styles+"\n</style>\n");
} else {
styleelement.append("\n/*=== TweetPreview ===*/\n"+styles+"\n");
}
},
util: {
encodehtml: function(str) {
if (typeof(str) == "string") {
str = str.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
}
return str;
}
}
}
tweetpreview.initialize();
unsafeWindow.tweetpreview = tweetpreview;
