1(function($) { 2 3 $.fn.tweet = function(o){ 4 var s = { 5 username: ["seaofclouds"], // [string] required, unless you want to display our tweets. :) it can be an array, just do ["username1","username2","etc"] 6 list: null, //[string] optional name of list belonging to username 7 avatar_size: null, // [integer] height and width of avatar if displayed (48px max) 8 count: 3, // [integer] how many tweets to display? 9 intro_text: null, // [string] do you want text BEFORE your your tweets? 10 outro_text: null, // [string] do you want text AFTER your tweets? 11 join_text: null, // [string] optional text in between date and tweet, try setting to "auto" 12 auto_join_text_default: "i said,", // [string] auto text for non verb: "i said" bullocks 13 auto_join_text_ed: "i", // [string] auto text for past tense: "i" surfed 14 auto_join_text_ing: "i am", // [string] auto tense for present tense: "i was" surfing 15 auto_join_text_reply: "i replied to", // [string] auto tense for replies: "i replied to" @someone "with" 16 auto_join_text_url: "i was looking at", // [string] auto tense for urls: "i was looking at" http:... 17 loading_text: null, // [string] optional loading text, displayed while tweets load 18 query: null, // [string] optional search query 19 refresh_interval: null // [integer] optional number of seconds after which to reload tweets 20 }; 21 22 if(o) $.extend(s, o); 23 24 $.fn.extend({ 25 linkUrl: function() { 26 var returning = []; 27 var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi; 28 this.each(function() { 29 returning.push(this.replace(regexp,"<a href=\"$1\">$1</a>")); 30 }); 31 return $(returning); 32 }, 33 linkUser: function() { 34 var returning = []; 35 var regexp = /[\@]+([A-Za-z0-9-_]+)/gi; 36 this.each(function() { 37 returning.push(this.replace(regexp,"<a href=\"http://twitter.com/$1\">@$1</a>")); 38 }); 39 return $(returning); 40 }, 41 linkHash: function() { 42 var returning = []; 43 var regexp = /(?:^| )[\#]+([A-Za-z0-9-_]+)/gi; 44 this.each(function() { 45 returning.push(this.replace(regexp, ' <a href="http://search.twitter.com/search?q=&tag=$1&lang=all&from='+s.username.join("%2BOR%2B")+'">#$1</a>')); 46 }); 47 return $(returning); 48 }, 49 capAwesome: function() { 50 var returning = []; 51 this.each(function() { 52 returning.push(this.replace(/\b(awesome)\b/gi, '<span class="awesome">$1</span>')); 53 }); 54 return $(returning); 55 }, 56 capEpic: function() { 57 var returning = []; 58 this.each(function() { 59 returning.push(this.replace(/\b(epic)\b/gi, '<span class="epic">$1</span>')); 60 }); 61 return $(returning); 62 }, 63 makeHeart: function() { 64 var returning = []; 65 this.each(function() { 66 returning.push(this.replace(/(<)+[3]/gi, "<tt class='heart'>♥</tt>")); 67 }); 68 return $(returning); 69 } 70 }); 71 72 function parse_date(date_str) { 73 // The non-search twitter APIs return inconsistently-formatted dates, which Date.parse 74 // cannot handle in IE. We therefore perform the following transformation: 75 // "Wed Apr 29 08:53:31 +0000 2009" => "Wed, Apr 29 2009 08:53:31 +0000" 76 return Date.parse(date_str.replace(/^([a-z]{3})( [a-z]{3} \d\d?)(.*)( \d{4})$/i, '$1,$2$4$3')); 77 } 78 79 function relative_time(time_value) { 80 var parsed_date = parse_date(time_value); 81 var relative_to = (arguments.length > 1) ? arguments[1] : new Date(); 82 var delta = parseInt((relative_to.getTime() - parsed_date) / 1000); 83 var r = ''; 84 if (delta < 60) { 85 r = delta + ' seconds ago'; 86 } else if(delta < 120) { 87 r = 'a minute ago'; 88 } else if(delta < (45*60)) { 89 r = (parseInt(delta / 60, 10)).toString() + ' minutes ago'; 90 } else if(delta < (2*60*60)) { 91 r = 'an hour ago'; 92 } else if(delta < (24*60*60)) { 93 r = '' + (parseInt(delta / 3600, 10)).toString() + ' hours ago'; 94 } else if(delta < (48*60*60)) { 95 r = 'a day ago'; 96 } else { 97 r = (parseInt(delta / 86400, 10)).toString() + ' days ago'; 98 } 99 return 'about ' + r; 100 } 101 102 function build_url() { 103 var proto = ('https:' == document.location.protocol ? 'https:' : 'http:'); 104 if (s.list) { 105 return proto+"//api.twitter.com/1/"+s.username[0]+"/lists/"+s.list+"/statuses.json?per_page="+s.count+"&callback=?"; 106 } else if (s.query == null && s.username.length == 1) { 107 return proto+'//api.twitter.com/1/statuses/user_timeline.json?screen_name='+s.username[0]+'&count='+s.count+'&include_rts=1&callback=?'; 108 } else { 109 var query = (s.query || 'from:'+s.username.join(' OR from:')); 110 return proto+'//search.twitter.com/search.json?&q='+encodeURIComponent(query)+'&rpp='+s.count+'&c
110allback=?'; 111 } 112 } 113 114 return this.each(function(i, widget){ 115 var list = $('<ul class="tweet_list">').appendTo(widget); 116 var intro = '<p class="tweet_intro">'+s.intro_text+'</p>'; 117 var outro = '<p class="tweet_outro">'+s.outro_text+'</p>'; 118 var loading = $('<p class="loading">'+s.loading_text+'</p>'); 119 120 if(typeof(s.username) == "string"){ 121 s.username = [s.username]; 122 } 123 124 if (s.loading_text) $(widget).append(loading); 125 $(widget).bind("load", function(){ 126 $.getJSON(build_url(), function(data){ 127 if (s.loading_text) loading.remove(); 128 if (s.intro_text) list.before(intro); 129 list.empty(); 130 var tweets = (data.results || data); 131 $.each(tweets, function(i,item){ 132 // auto join text based on verb tense and content 133 if (s.join_text == "auto") { 134 if (item.text.match(/^(@([A-Za-z0-9-_]+)) .*/i)) { 135 var join_text = s.auto_join_text_reply; 136 } else if (item.text.match(/(^\w+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+) .*/i)) { 137 var join_text = s.auto_join_text_url; 138 } else if (item.text.match(/^((\w+ed)|just) .*/im)) { 139 var join_text = s.auto_join_text_ed; 140 } else if (item.text.match(/^(\w*ing) .*/i)) { 141 var join_text = s.auto_join_text_ing; 142 } else { 143 var join_text = s.auto_join_text_default; 144 } 145 } else { 146 var join_text = s.join_text; 147 }; 148 149 var from_user = item.from_user || item.user.screen_name; 150 var profile_image_url = item.profile_image_url || item.user.profile_image_url; 151 var join_template = '<span class="tweet_join"> '+join_text+' </span>'; 152 var join = ((s.join_text) ? join_template : ' '); 153 var avatar_template = '<a class="tweet_avatar" href="http://twitter.com/'+from_user+'"><img src="'+profile_image_url+'" height="'+s.avatar_size+'" width="'+s.avatar_size+'" alt="'+from_user+'\'s avatar" title="'+from_user+'\'s avatar" border="0"/></a>'; 154 var avatar = (s.avatar_size ? avatar_template : ''); 155 var date = '<span class="tweet_time"><a href="http://twitter.com/'+from_user+'/statuses/'+item.id_str+'" title="view tweet on twitter">'+relative_time(item.created_at)+'</a></span>'; 156 var text = '<span class="tweet_text">' +$([item.text]).linkUrl().linkUser().linkHash().makeHeart().capAwesome().capEpic()[0]+ '</span>'; 157 158 // until we create a template option, arrange the items below to alter a tweet's display. 159 list.append('<li>' + avatar + date + join + text + '</li>'); 160 161 list.children('li:first').addClass('tweet_first'); 162 list.children('li:odd').addClass('tweet_even'); 163 list.children('li:even').addClass('tweet_odd'); 164 }); 165 if (s.outro_text) list.after(outro); 166 $(widget).trigger("loaded").trigger((tweets.length == 0 ? "empty" : "full")); 167 if (s.refresh_interval) { 168 window.setTimeout(function() { $(widget).trigger("load"); }, 1000 * s.refresh_interval); 169 }; 170 }); 171 }).trigger("load"); 172 }); 173 }; 174})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.