Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions assets/css/site.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@import 'tweets.css';

.addthis_toolbox {
width:250px;
}
Expand Down
23 changes: 23 additions & 0 deletions assets/css/tweets.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@


.tweet_list {
list-style: none;
margin: 0;
padding: 0;
overflow-y: hidden;
}

.tweet_list li {
overflow-y: auto;
overflow-x: hidden;
padding: 0.5em;
list-style-type: none;
}

.tweet_list .tweet_avatar {
padding-right: .5em; float: left;
}

.tweet_list .tweet_avatar img {
vertical-align: middle;
}
56 changes: 7 additions & 49 deletions assets/js/application.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,10 @@
$(document).ready(function(){

// table sort example
// ==================

$("#sortTableExample").tablesorter( { sortList: [[ 1, 0 ]] } )


// add on logic
// ============

$('.add-on :checkbox').click(function () {
if ($(this).attr('checked')) {
$(this).parents('.add-on').addClass('active')
} else {
$(this).parents('.add-on').removeClass('active')
}
})


// Disable certain links in docs
// =============================
// Please do not carry these styles over to your projects, it's merely here to prevent button clicks form taking you away from your spot on page

$('ul.tabs a, ul.pills a, .pagination a, .well .btn, .actions .btn, .alert-message .btn, a.close').click(function (e) {
e.preventDefault()
})

// Copy code blocks in docs
$(".copy-code").focus(function () {
var el = this;
// push select to event loop for chrome :{o
setTimeout(function () { $(el).select(); }, 0);
$("#tweets").tweet({
join_text: "auto",
username: "tvrb",
avatar_size: 48,
count: 4,
loading_text: "loading tweets...",
template: '{avatar}{text} {time}'
});


// POSITION STATIC TWIPSIES
// ========================

$(window).bind( 'load resize', function () {
$(".twipsies a").each(function () {
$(this)
.twipsy({
live: false
, placement: $(this).attr('title')
, trigger: 'manual'
, offset: 2
})
.twipsy('show')
})
})
});
20 changes: 20 additions & 0 deletions assets/js/tweet/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Copyright (c) 2008-2011 Todd Matthews & Steve Purcell

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
44 changes: 44 additions & 0 deletions assets/js/tweet/jquery.tweet.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
.tweet,
.query {
font: 120% Georgia, serif;
color: #085258;
}

.tweet_list {
-webkit-border-radius: 0.5em;
-moz-border-radius: 0.5em;
border-radius: 0.5em;
list-style: none;
margin: 0;
padding: 0;
overflow-y: hidden;
background-color: #8ADEE2;
}

.tweet_list .awesome,
.tweet_list .epic {
text-transform: uppercase;
}

.tweet_list li {
overflow-y: auto;
overflow-x: hidden;
padding: 0.5em;
list-style-type: none;
}

.tweet_list li a {
color: #0C717A;
}

.tweet_list .tweet_even {
background-color: #91E5E7;
}

.tweet_list .tweet_avatar {
padding-right: .5em; float: left;
}

.tweet_list .tweet_avatar img {
vertical-align: middle;
}
238 changes: 238 additions & 0 deletions assets/js/tweet/jquery.tweet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
// jquery.tweet.js - See http://tweet.seaofclouds.com/ or https://github.com/seaofclouds/tweet for more info
// Copyright (c) 2008-2011 Todd Matthews & Steve Purcell
(function($) {
$.fn.tweet = function(o){
var s = $.extend({
username: null, // [string or array] required unless using the 'query' option; one or more twitter screen names (use 'list' option for multiple names, where possible)
list: null, // [string] optional name of list belonging to username
favorites: false, // [boolean] display the user's favorites instead of his tweets
query: null, // [string] optional search query (see also: http://search.twitter.com/operators)
avatar_size: null, // [integer] height and width of avatar if displayed (48px max)
count: 3, // [integer] how many tweets to display?
fetch: null, // [integer] how many tweets to fetch via the API (set this higher than 'count' if using the 'filter' option)
page: 1, // [integer] which page of results to fetch (if count != fetch, you'll get unexpected results)
retweets: true, // [boolean] whether to fetch (official) retweets (not supported in all display modes)
intro_text: null, // [string] do you want text BEFORE your your tweets?
outro_text: null, // [string] do you want text AFTER your tweets?
join_text: null, // [string] optional text in between date and tweet, try setting to "auto"
auto_join_text_default: "i said,", // [string] auto text for non verb: "i said" bullocks
auto_join_text_ed: "i", // [string] auto text for past tense: "i" surfed
auto_join_text_ing: "i am", // [string] auto tense for present tense: "i was" surfing
auto_join_text_reply: "i replied to", // [string] auto tense for replies: "i replied to" @someone "with"
auto_join_text_url: "i was looking at", // [string] auto tense for urls: "i was looking at" http:...
loading_text: null, // [string] optional loading text, displayed while tweets load
refresh_interval: null , // [integer] optional number of seconds after which to reload tweets
twitter_url: "twitter.com", // [string] custom twitter url, if any (apigee, etc.)
twitter_api_url: "api.twitter.com", // [string] custom twitter api url, if any (apigee, etc.)
twitter_search_url: "search.twitter.com", // [string] custom twitter search url, if any (apigee, etc.)
template: "{avatar}{time}{join}{text}", // [string or function] template used to construct each tweet <li> - see code for available vars
comparator: function(tweet1, tweet2) { // [function] comparator used to sort tweets (see Array.sort)
return tweet2["tweet_time"] - tweet1["tweet_time"];
},
filter: function(tweet) { // [function] whether or not to include a particular tweet (be sure to also set 'fetch')
return true;
}
}, o);

// See http://daringfireball.net/2010/07/improved_regex_for_matching_urls
var url_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;

// Expand values inside simple string templates with {placeholders}
function t(template, info) {
if (typeof template === "string") {
var result = template;
for(var key in info) {
var val = info[key];
result = result.replace(new RegExp('{'+key+'}','g'), val === null ? '' : val);
}
return result;
} else return template(info);
}
// Export the t function for use when passing a function as the 'template' option
$.extend({tweet: {t: t}});

function replacer (regex, replacement) {
return function() {
var returning = [];
this.each(function() {
returning.push(this.replace(regex, replacement));
});
return $(returning);
};
}

function escapeHTML(s) {
return s.replace(/</g,"&lt;").replace(/>/g,"^&gt;");
}

$.fn.extend({
linkUser: replacer(/(^|[\W])@(\w+)/gi, "$1@<a href=\"http://"+s.twitter_url+"/$2\">$2</a>"),
// Support various latin1 (\u00**) and arabic (\u06**) alphanumeric chars
linkHash: replacer(/(?:^| )[\#]+([\w\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u00ff\u0600-\u06ff]+)/gi,
' <a href="http://'+s.twitter_search_url+'/search?q=&tag=$1&lang=all'+((s.username && s.username.length == 1 && !s.list) ? '&from='+s.username.join("%2BOR%2B") : '')+'">#$1</a>'),
capAwesome: replacer(/\b(awesome)\b/gi, '<span class="awesome">$1</span>'),
capEpic: replacer(/\b(epic)\b/gi, '<span class="epic">$1</span>'),
makeHeart: replacer(/(&lt;)+[3]/gi, "<tt class='heart'>&#x2665;</tt>")
});

function linkURLs(text, entities) {
return text.replace(url_regexp, function(match) {
var url = (/^[a-z]+:/i).test(match) ? match : "http://"+match;
var text = match;
for(var i = 0; i < entities.length; ++i) {
var entity = entities[i];
if (entity.url == url && entity.expanded_url) {
url = entity.expanded_url;
text = entity.display_url;
break;
}
}
return "<a href=\""+escapeHTML(url)+"\">"+escapeHTML(text)+"</a>";
});
}

function parse_date(date_str) {
// The non-search twitter APIs return inconsistently-formatted dates, which Date.parse
// cannot handle in IE. We therefore perform the following transformation:
// "Wed Apr 29 08:53:31 +0000 2009" => "Wed, Apr 29 2009 08:53:31 +0000"
return Date.parse(date_str.replace(/^([a-z]{3})( [a-z]{3} \d\d?)(.*)( \d{4})$/i, '$1,$2$4$3'));
}

function relative_time(date) {
var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
var delta = parseInt((relative_to.getTime() - date) / 1000, 10);
var r = '';
if (delta < 1) {
r = 'just now';
} else if (delta < 60) {
r = delta + ' seconds ago';
} else if(delta < 120) {
r = 'a minute ago';
} else if(delta < (45*60)) {
r = (parseInt(delta / 60, 10)).toString() + ' minutes ago';
} else if(delta < (2*60*60)) {
r = 'an hour ago';
} else if(delta < (24*60*60)) {
r = '' + (parseInt(delta / 3600, 10)).toString() + ' hours ago';
} else if(delta < (48*60*60)) {
r = 'a day ago';
} else {
r = (parseInt(delta / 86400, 10)).toString() + ' days ago';
}
return 'about ' + r;
}

function build_auto_join_text(text) {
if (text.match(/^(@([A-Za-z0-9-_]+)) .*/i)) {
return s.auto_join_text_reply;
} else if (text.match(url_regexp)) {
return s.auto_join_text_url;
} else if (text.match(/^((\w+ed)|just) .*/im)) {
return s.auto_join_text_ed;
} else if (text.match(/^(\w*ing) .*/i)) {
return s.auto_join_text_ing;
} else {
return s.auto_join_text_default;
}
}

function build_api_url() {
var proto = ('https:' == document.location.protocol ? 'https:' : 'http:');
var count = (s.fetch === null) ? s.count : s.fetch;
var common_params = '&include_entities=1&callback=?';
if (s.list) {
return proto+"//"+s.twitter_api_url+"/1/"+s.username[0]+"/lists/"+s.list+"/statuses.json?page="+s.page+"&per_page="+count+common_params;
} else if (s.favorites) {
return proto+"//"+s.twitter_api_url+"/favorites/"+s.username[0]+".json?page="+s.page+"&count="+count+common_params;
} else if (s.query === null && s.username.length == 1) {
return proto+'//'+s.twitter_api_url+'/1/statuses/user_timeline.json?screen_name='+s.username[0]+'&count='+count+(s.retweets ? '&include_rts=1' : '')+'&page='+s.page+common_params;
} else {
var query = (s.query || 'from:'+s.username.join(' OR from:'));
return proto+'//'+s.twitter_search_url+'/search.json?&q='+encodeURIComponent(query)+'&rpp='+count+'&page='+s.page+common_params;
}
}

function extract_avatar_url(item, secure) {
if (secure) {
return ('user' in item) ?
item.user.profile_image_url_https :
extract_avatar_url(item, false).
replace(/^http:\/\/[a-z0-9]{1,3}\.twimg\.com\//, "https://s3.amazonaws.com/twitter_production/");
} else {
return item.profile_image_url || item.user.profile_image_url;
}
}

// Convert twitter API objects into data available for
// constructing each tweet <li> using a template
function extract_template_data(item){
var o = {};
o.item = item;
o.source = item.source;
o.screen_name = item.from_user || item.user.screen_name;
o.avatar_size = s.avatar_size;
o.avatar_url = extract_avatar_url(item, (document.location.protocol === 'https:'));
o.retweet = typeof(item.retweeted_status) != 'undefined';
o.tweet_time = parse_date(item.created_at);
o.join_text = s.join_text == "auto" ? build_auto_join_text(item.text) : s.join_text;
o.tweet_id = item.id_str;
o.twitter_base = "http://"+s.twitter_url+"/";
o.user_url = o.twitter_base+o.screen_name;
o.tweet_url = o.user_url+"/status/"+o.tweet_id;
o.reply_url = o.twitter_base+"intent/tweet?in_reply_to="+o.tweet_id;
o.retweet_url = o.twitter_base+"intent/retweet?tweet_id="+o.tweet_id;
o.favorite_url = o.twitter_base+"intent/favorite?tweet_id="+o.tweet_id;
o.retweeted_screen_name = o.retweet && item.retweeted_status.user.screen_name;
o.tweet_relative_time = relative_time(o.tweet_time);
o.entities = item.entities ? (item.entities.urls || []).concat(item.entities.media || []) : [];
o.tweet_raw_text = o.retweet ? ('RT @'+o.retweeted_screen_name+' '+item.retweeted_status.text) : item.text; // avoid '...' in long retweets
o.tweet_text = $([linkURLs(o.tweet_raw_text, o.entities)]).linkUser().linkHash()[0];
o.tweet_text_fancy = $([o.tweet_text]).makeHeart().capAwesome().capEpic()[0];

// Default spans, and pre-formatted blocks for common layouts
o.user = t('<a class="tweet_user" href="{user_url}">{screen_name}</a>', o);
o.join = s.join_text ? t(' <span class="tweet_join">{join_text}</span> ', o) : ' ';
o.avatar = o.avatar_size ?
t('<a class="tweet_avatar" href="{user_url}"><img src="{avatar_url}" height="{avatar_size}" width="{avatar_size}" alt="@{screen_name}" title="@{screen_name}"></a>', o) : '';
o.time = t('<span class="tweet_time"><a href="{tweet_url}" title="view on twitter">{tweet_relative_time}</a></span>', o);
o.text = t('<span class="tweet_text">{tweet_text_fancy}</span>', o);
o.reply_action = t('<a class="tweet_action tweet_reply" href="{reply_url}">reply</a>', o);
o.retweet_action = t('<a class="tweet_action tweet_retweet" href="{retweet_url}">retweet</a>', o);
o.favorite_action = t('<a class="tweet_action tweet_favorite" href="{favorite_url}">favorite</a>', o);
return o;
}

return this.each(function(i, widget){
var list = $('<ul class="tweet_list">');
var intro = '<p class="tweet_intro">'+s.intro_text+'</p>';
var outro = '<p class="tweet_outro">'+s.outro_text+'</p>';
var loading = $('<p class="loading">'+s.loading_text+'</p>');

if(s.username && typeof(s.username) == "string"){
s.username = [s.username];
}

$(widget).bind("tweet:load", function(){
if (s.loading_text) $(widget).empty().append(loading);
$.getJSON(build_api_url(), function(data){
$(widget).empty().append(list);
if (s.intro_text) list.before(intro);
list.empty();

var tweets = $.map(data.results || data, extract_template_data);
tweets = $.grep(tweets, s.filter).sort(s.comparator).slice(0, s.count);
list.append($.map(tweets, function(o) { return "<li>" + t(s.template, o) + "</li>"; }).join('')).
children('li:first').addClass('tweet_first').end().
children('li:odd').addClass('tweet_even').end().
children('li:even').addClass('tweet_odd');

if (s.outro_text) list.after(outro);
$(widget).trigger("loaded").trigger((tweets.length === 0 ? "empty" : "full"));
if (s.refresh_interval) {
window.setTimeout(function() { $(widget).trigger("tweet:load"); }, 1000 * s.refresh_interval);
}
});
}).trigger("tweet:load");
});
};
})(jQuery);
Loading