Changeset 3060
- Timestamp:
- 06/16/11 02:01:25 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
plugins/tweet/js/jquery.tweet.js
r2391 r3060 1 1 (function($) { 2 2 3 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 text_less_min: "less than a minute ago",// [string] text for tweets less than a minute old 20 text_one_min: "about a minute ago", // [string] text for tweets between one and two minutes old 21 text_n_mins: "%t minutes ago", // [string] text for tweets less than an hour old 22 text_one_hour: "about an hour ago", // [string] text for tweets between 60 and 90 minutes old 23 text_n_hours: "about %t hours ago", // [string] text for tweets less than a day old 24 text_one_day: "1 day ago", // [string] text for tweets between 24 and 48 hours old 25 text_n_days: "%t days ago" // [string] text for tweets more than two days old 26 }; 27 28 if(o) $.extend(s, o); 4 var s = $.extend({ 5 username: null, // [string or array] required unless using the 'query' option; one or more twitter screen names 6 list: null, // [string] optional name of list belonging to username 7 favorites: false, // [boolean] display the user's favorites instead of his tweets 8 query: null, // [string] optional search query 9 avatar_size: null, // [integer] height and width of avatar if displayed (48px max) 10 count: 3, // [integer] how many tweets to display? 11 fetch: null, // [integer] how many tweets to fetch via the API (set this higher than 'count' if using the 'filter' option) 12 retweets: true, // [boolean] whether to fetch (official) retweets (not supported in all display modes) 13 intro_text: null, // [string] do you want text BEFORE your your tweets? 14 outro_text: null, // [string] do you want text AFTER your tweets? 15 join_text: null, // [string] optional text in between date and tweet, try setting to "auto" 16 auto_join_text_default: "i said,", // [string] auto text for non verb: "i said" bullocks 17 auto_join_text_ed: "i", // [string] auto text for past tense: "i" surfed 18 auto_join_text_ing: "i am", // [string] auto tense for present tense: "i was" surfing 19 auto_join_text_reply: "i replied to", // [string] auto tense for replies: "i replied to" @someone "with" 20 auto_join_text_url: "i was looking at", // [string] auto tense for urls: "i was looking at" http:... 21 loading_text: null, // [string] optional loading text, displayed while tweets load 22 refresh_interval: null , // [integer] optional number of seconds after which to reload tweets 23 twitter_url: "twitter.com", // [string] custom twitter url, if any (apigee, etc.) 24 twitter_api_url: "api.twitter.com", // [string] custom twitter api url, if any (apigee, etc.) 25 twitter_search_url: "search.twitter.com", // [string] custom twitter search url, if any (apigee, etc.) 26 template: "{avatar}{time}{join}{text}", // [string or function] template used to construct each tweet <li> - see code for available vars 27 comparator: function(tweet1, tweet2) { // [function] comparator used to sort tweets (see Array.sort) 28 return tweet2["tweet_time"] - tweet1["tweet_time"]; 29 }, 30 filter: function(tweet) { // [function] whether or not to include a particular tweet (be sure to also set 'fetch') 31 return true; 32 }, 33 text_less_min: "less than a minute ago", // [string] text for tweets less than a minute old 34 text_one_min: "about a minute ago", // [string] text for tweets between one and two minutes old 35 text_n_mins: "%t minutes ago", // [string] text for tweets less than an hour old 36 text_one_hour: "about an hour ago", // [string] text for tweets between 60 and 90 minutes old 37 text_n_hours: "about %t hours ago", // [string] text for tweets less than a day old 38 text_one_day: "1 day ago", // [string] text for tweets between 24 and 48 hours old 39 text_n_days: "%t days ago" // [string] text for tweets more than two days old 40 }, o); 29 41 30 42 $.fn.extend({ 31 43 linkUrl: function() { 32 44 var returning = []; 33 var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi; 34 this.each(function() { 35 returning.push(this.replace(regexp,"<a href=\"$1\">$1</a>")); 45 // See http://daringfireball.net/2010/07/improved_regex_for_matching_urls 46 var regexp = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/gi; 47 this.each(function() { 48 returning.push(this.replace(regexp, 49 function(match) { 50 var url = (/^[a-z]+:/i).test(match) ? match : "http://"+match; 51 return "<a href=\""+url+"\">"+match+"</a>"; 52 })); 36 53 }); 37 54 return $(returning); … … 39 56 linkUser: function() { 40 57 var returning = []; 41 var regexp = /[\@]+( [A-Za-z0-9-_]+)/gi;42 this.each(function() { 43 returning.push(this.replace(regexp," <a href=\"http://twitter.com/$1\">@$1</a>"));58 var regexp = /[\@]+(\w+)/gi; 59 this.each(function() { 60 returning.push(this.replace(regexp,"@<a href=\"http://"+s.twitter_url+"/$1\">$1</a>")); 44 61 }); 45 62 return $(returning); … … 47 64 linkHash: function() { 48 65 var returning = []; 49 var regexp = /(?:^| )[\#]+([A-Za-z0-9-_]+)/gi; 50 this.each(function() { 51 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>')); 66 // Support various latin1 (\u00**) and arabic (\u06**) alphanumeric chars 67 var regexp = /(?:^| )[\#]+([\w\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u00ff\u0600-\u06ff]+)/gi; 68 var usercond = (s.username && s.username.length == 1) ? '&from='+s.username.join("%2BOR%2B") : ''; 69 this.each(function() { 70 returning.push(this.replace(regexp, ' <a href="http://'+s.twitter_search_url+'/search?q=&tag=$1&lang=all'+usercond+'">#$1</a>')); 52 71 }); 53 72 return $(returning); … … 70 89 var returning = []; 71 90 this.each(function() { 72 returning.push(this.replace(/(<)+[3]/gi, '<span class="heart">♥</span>'))91 returning.push(this.replace(/(<)+[3]/gi, "<tt class='heart'>♥</tt>")); 73 92 }); 74 93 return $(returning); … … 83 102 } 84 103 85 function relative_time(time_value) { 86 var parsed_date = parse_date(time_value); 104 function relative_time(date) { 87 105 var relative_to = (arguments.length > 1) ? arguments[1] : new Date(); 88 var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);106 var delta = parseInt((relative_to.getTime() - date) / 1000, 10); 89 107 if(delta < 60) { 90 108 return s.text_less_min; 91 109 } else if(delta < 120) { 92 110 return s.text_one_min; 93 } else if(delta < ( 60*60)) {111 } else if(delta < (45*60)) { 94 112 return s.text_n_mins.replace('%t', parseInt(delta / 60).toString()); 95 //return (parseInt(delta / 60)).toString() + s.text_n_mins;96 113 } else if(delta < (120*60)) { 97 114 return s.text_one_hour; 98 115 } else if(delta < (24*60*60)) { 99 116 return s.text_n_hours.replace('%t', parseInt(delta / 3600).toString()); 100 // return (parseInt(delta / 3600)).toString() + s.text_n_hours;101 117 } else if(delta < (48*60*60)) { 102 118 return s.text_one_day; 103 119 } else { 104 120 return s.text_n_days.replace('%t', parseInt(delta / 86400).toString()); 105 // return (parseInt(delta / 86400)).toString() + s.text_n_days;106 121 } 107 122 } … … 109 124 function build_url() { 110 125 var proto = ('https:' == document.location.protocol ? 'https:' : 'http:'); 126 var count = (s.fetch === null) ? s.count : s.fetch; 111 127 if (s.list) { 112 return proto+"// api.twitter.com/1/"+s.username[0]+"/lists/"+s.list+"/statuses.json?per_page="+s.count+"&callback=?";113 var from_user_full_name = item.user.name; 114 } else if (s.query == null && s.username.length == 1) {115 return proto+'//api.twitter.com/1/statuses/user_timeline.json?screen_name='+s.username[0]+'&count='+s.count+'&callback=?';116 128 return proto+"//"+s.twitter_api_url+"/1/"+s.username[0]+"/lists/"+s.list+"/statuses.json?per_page="+count+"&callback=?"; 129 } else if (s.favorites) { 130 return proto+"//"+s.twitter_api_url+"/favorites/"+s.username[0]+".json?count="+s.count+"&callback=?"; 131 } else if (s.query === null && s.username.length == 1) { 132 return proto+'//'+s.twitter_api_url+'/1/statuses/user_timeline.json?screen_name='+s.username[0]+'&count='+count+(s.retweets ? '&include_rts=1' : '')+'&callback=?'; 117 133 } else { 118 134 var query = (s.query || 'from:'+s.username.join(' OR from:')); 119 return proto+'// search.twitter.com/search.json?&q='+escape(query)+'&rpp='+s.count+'&callback=?';135 return proto+'//'+s.twitter_search_url+'/search.json?&q='+encodeURIComponent(query)+'&rpp='+count+'&callback=?'; 120 136 } 121 137 } … … 127 143 var loading = $('<p class="loading">'+s.loading_text+'</p>'); 128 144 129 if( typeof(s.username) == "string"){145 if(s.username && typeof(s.username) == "string"){ 130 146 s.username = [s.username]; 131 147 } 132 148 149 var expand_template = function(info) { 150 if (typeof s.template === "string") { 151 var result = s.template; 152 for(var key in info) { 153 var val = info[key]; 154 result = result.replace(new RegExp('{'+key+'}','g'), val === null ? '' : val); 155 } 156 return result; 157 } else return s.template(info); 158 }; 159 133 160 if (s.loading_text) $(widget).append(loading); 134 $.getJSON(build_url(), function(data){ 135 if (s.loading_text) loading.remove(); 136 if (s.intro_text) list.before(intro); 137 var tweets = (data.results || data); 138 $.each(tweets, function(i,item){ 161 $(widget).bind("load", function(){ 162 $.getJSON(build_url(), function(data){ 163 if (s.loading_text) loading.remove(); 164 if (s.intro_text) list.before(intro); 165 list.empty(); 166 167 var tweets = $.map(data.results || data, function(item){ 168 var join_text = s.join_text; 139 169 var from_user = item.from_user || item.user.screen_name; 140 170 if (s.list || (s.query == null && s.username.length == 1)) {var from_user_full_name = item.user.name} 141 171 else var from_user_full_name = from_user; 172 142 173 // auto join text based on verb tense and content 143 if (s.join_text == "auto") { 144 if (item.text.match(/^(@([A-Za-z0-9-_]+)) .*/i)) { 145 var join_text = s.auto_join_text_reply.replace('%u','<a href="http://twitter.com/'+from_user+'">'+from_user+'</a>'); 146 var join_text = s.auto_join_text_reply.replace('%U','<a href="http://twitter.com/'+from_user+'">'+from_user_full_name+'</a>'); 147 } else if (item.text.match(/(^\w+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+) .*/i)) { 148 var join_text = s.auto_join_text_url.replace('%u','<a href="http://twitter.com/'+from_user+'">'+from_user+'</a>'); 149 var join_text = s.auto_join_text_url.replace('%U','<a href="http://twitter.com/'+from_user+'">'+from_user_full_name+'</a>'); 150 } else if (item.text.match(/^((\w+ed)|just) .*/im)) { 151 var join_text = s.auto_join_text_ed.replace('%u','<a href="http://twitter.com/'+from_user+'">'+from_user+'</a>'); 152 var join_text = s.auto_join_text_ed.replace('%u','<a href="http://twitter.com/'+from_user+'">'+from_user_full_name+'</a>'); 153 } else if (item.text.match(/^(\w*ing) .*/i)) { 154 var join_text = s.auto_join_text_ing.replace('%u','<a href="http://twitter.com/'+from_user+'">'+from_user+'</a>'); 155 var join_text = s.auto_join_text_ing.replace('%U','<a href="http://twitter.com/'+from_user+'">'+from_user_full_name+'</a>'); 156 } else { 157 var join_text = s.auto_join_text_default.replace('%u','<a href="http://twitter.com/'+from_user+'">'+from_user+'</a>'); 158 var join_text = s.auto_join_text_default.replace('%U','<a href="http://twitter.com/'+from_user+'">'+from_user_full_name+'</a>'); 174 if (s.join_text == "auto") { 175 if (item.text.match(/^(@([A-Za-z0-9-_]+)) .*/i)) { 176 join_text = s.auto_join_text_reply.replace('%u','<a href="http://twitter.com/'+from_user+'">'+from_user+'</a>'); 177 join_text = join_text.replace('%U','<a href="http://twitter.com/'+from_user+'">'+from_user_full_name+'</a>'); 178 } else if (item.text.match(/(^\w+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+) .*/i)) { 179 join_text = s.auto_join_text_url.replace('%u','<a href="http://twitter.com/'+from_user+'">'+from_user+'</a>'); 180 join_text = join_text.replace('%U','<a href="http://twitter.com/'+from_user+'">'+from_user_full_name+'</a>'); 181 } else if (item.text.match(/^((\w+ed)|just) .*/im)) { 182 join_text = s.auto_join_text_ed.replace('%u','<a href="http://twitter.com/'+from_user+'">'+from_user+'</a>'); 183 join_text = join_text.replace('%U','<a href="http://twitter.com/'+from_user+'">'+from_user_full_name+'</a>'); 184 } else if (item.text.match(/^(\w*ing) .*/i)) { 185 join_text = s.auto_join_text_ing.replace('%u','<a href="http://twitter.com/'+from_user+'">'+from_user+'</a>'); 186 join_text = join_text.replace('%U','<a href="http://twitter.com/'+from_user+'">'+from_user_full_name+'</a>'); 187 } else { 188 join_text = s.auto_join_text_default.replace('%u','<a href="http://twitter.com/'+from_user+'">'+from_user+'</a>'); 189 join_text = join_text.replace('%U','<a href="http://twitter.com/'+from_user+'">'+from_user_full_name+'</a>'); 190 } 159 191 } 160 } else { 161 var join_text = s.join_text.replace('%u','<a href="http://twitter.com/'+from_user+'">'+from_user+'</a>'); 162 var join_text = s.join_text.replace('%U','<a href="http://twitter.com/'+from_user+'">'+from_user_full_name+'</a>'); 163 }; 164 165 var profile_image_url = item.profile_image_url || item.user.profile_image_url; 166 var join_template = '<span class="tweet_join"> '+join_text+' </span>'; 167 var join = ((s.join_text) ? join_template : ' '); 168 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+'"'+((s.avatar_alt) ? 'alt="'+s.avatar_alt.replace('%u', from_user)+'" title="'+s.avatar_alt.replace('%u', from_user)+'"' : '')+' /></a>'; 169 var avatar = (s.avatar_size ? avatar_template : ''); 170 var date = '<a class="tweet_date" href="http://twitter.com/'+from_user+'/statuses/'+item.id+'" title="view tweet on twitter">'+relative_time(item.created_at)+'</a>'; 171 var text = '<span class="tweet_text">' +$([item.text]).linkUrl().linkUser().linkHash().makeHeart().capAwesome().capEpic()[0]+ '</span>'; 172 173 // until we create a template option, arrange the items below to alter a tweet's display. 174 if (s.date_after) { 175 list.append('<li>' + avatar + '<span class="tweet_content">' + join + text + date + '</span></li>'); 176 } else { 177 list.append('<li>' + avatar + date + '<span class="tweet_content">' + join + text + '</span></li>'); 178 }; 179 180 list.children('li:first').addClass('tweet_first'); 181 list.children('li:odd').addClass('tweet_even'); 182 list.children('li:even').addClass('tweet_odd'); 183 }); 184 if (s.outro_text) list.after(outro); 185 $(widget).trigger("loaded").trigger((tweets.length == 0 ? "empty" : "full")); 186 }); 187 192 193 // Basic building blocks for constructing tweet <li> using a template 194 var screen_name = item.from_user || item.user.screen_name; 195 var source = item.source; 196 var user_url = "http://"+s.twitter_url+"/"+screen_name; 197 var avatar_size = s.avatar_size; 198 var avatar_url = item.profile_image_url || item.user.profile_image_url; 199 var tweet_url = "http://"+s.twitter_url+"/"+screen_name+"/status/"+item.id_str; 200 var retweet = (typeof(item.retweeted_status) != 'undefined'); 201 var retweeted_screen_name = retweet ? item.retweeted_status.user.screen_name : null; 202 var tweet_time = parse_date(item.created_at); 203 var tweet_relative_time = relative_time(tweet_time); 204 var tweet_raw_text = retweet ? ('RT @'+retweeted_screen_name+' '+item.retweeted_status.text) : item.text; // avoid '...' in long retweets 205 var tweet_text = $([tweet_raw_text]).linkUrl().linkUser().linkHash()[0]; 206 207 // Default spans, and pre-formatted blocks for common layouts 208 var user = '<a class="tweet_user" href="'+user_url+'">'+screen_name+'</a>'; 209 var join = ((s.join_text) ? ('<span class="tweet_join"> '+join_text+' </span>') : ' '); 210 var avatar = (avatar_size ? 211 ('<a class="tweet_avatar" href="'+user_url+'"><img src="'+avatar_url+ 212 '" height="'+avatar_size+'" width="'+avatar_size+ 213 '" alt="'+screen_name+'\'s avatar" /></a>') : ''); 214 var time = '<span class="tweet_time"><a href="'+tweet_url+'" title="view tweet on twitter">'+tweet_relative_time+'</a></span>'; 215 var text = '<span class="tweet_text">'+$([tweet_text]).makeHeart().capAwesome().capEpic()[0]+ '</span>'; 216 217 return { item: item, // For advanced users who want to dig out other info 218 screen_name: screen_name, 219 user_url: user_url, 220 avatar_size: avatar_size, 221 avatar_url: avatar_url, 222 source: source, 223 tweet_url: tweet_url, 224 tweet_time: tweet_time, 225 tweet_relative_time: tweet_relative_time, 226 tweet_raw_text: tweet_raw_text, 227 tweet_text: tweet_text, 228 retweet: retweet, 229 retweeted_screen_name: retweeted_screen_name, 230 user: user, 231 join: join, 232 avatar: avatar, 233 time: time, 234 text: text 235 }; 236 }); 237 238 tweets = $.grep(tweets, s.filter).sort(s.comparator).slice(0, s.count); 239 list.append($.map(tweets, 240 function(t) { return "<li>" + expand_template(t) + "</li>"; }).join('')). 241 children('li:first').addClass('tweet_first').end(). 242 children('li:odd').addClass('tweet_even').end(). 243 children('li:even').addClass('tweet_odd'); 244 245 if (s.outro_text) list.after(outro); 246 $(widget).trigger("loaded").trigger((tweets.length === 0 ? "empty" : "full")); 247 if (s.refresh_interval) { 248 window.setTimeout(function() { $(widget).trigger("load"); }, 1000 * s.refresh_interval); 249 } 250 }); 251 }).trigger("load"); 188 252 }); 189 253 };
Note: See TracChangeset
for help on using the changeset viewer.