Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

deployed and announced

  • Loading branch information...
commit b36fe2a8a6ff6ef8e5a53821a97eacc0f7385ef2 1 parent abd5090
Chris Anderson authored
View
88 _attachments/index.html
@@ -8,34 +8,65 @@
<body>
<div id="tweets">
<ul></ul>
- </div>
+ </div>
+ <div id="controls-wrap">
+ <div id="controls">
+ <div id="buttons">
+ <a href="#refreshTweets" title="Refresh Tweets">&#x293F</a>
+ </div>
+ <form id="updateStatus" action="#">
+ <span id="statusCount">140</span>
+ <label for="status">Status:</label>
+ <textarea name="status" rows="3" cols="52"></textarea>
+ <input type="submit" value="Tweet">
+ </form>
+ <p id="about"><a href="http://github.com/jchris/couchdb-twitter-client/tree/master">CouchDB Twitter Client</a>: another 24 hour hack by <a href="http:/jchris.mfdz.com/">J Chris Anderson</a>.</p>
+ </div>
+ </div>
</body>
<script src="/_utils/script/json2.js"></script>
<script src="/_utils/script/jquery.js?1.2.6"></script>
<script src="/_utils/script/jquery.couch.js?0.8.0"></script>
+ <script src="/_utils/script/jquery.cookies.js"></script>
<script src="user.js"></script>
+ <script src="jquery.xdompost.js"></script>
<script src="twitter-couch.js"></script>
<script type="text/javascript" charset="utf-8">
$(function() {
- // DB.view(design+"/example",{success: function(json) {
- // $("#view").html(json.rows.map(function(row) {
- // return '<li>'+row.key+'</li>';
- // }).join(''));
- // }});
-
+
+ function prettyDate(time){
+ var date = new Date(time),
+ diff = (((new Date()).getTime() - date.getTime()) / 1000),
+ day_diff = Math.floor(diff / 86400);
+
+ // if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 ) return;
+
+ return day_diff < 1 && (
+ diff < 60 && "just now" ||
+ diff < 120 && "1 minute ago" ||
+ diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
+ diff < 7200 && "1 hour ago" ||
+ diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
+ day_diff == 1 && "yesterday" ||
+ day_diff < 7 && day_diff + " days ago" ||
+ day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago" ||
+ day_diff < 730 && Math.ceil( day_diff / 31 ) + " months ago" ||
+ Math.ceil( day_diff / 365 ) + " years ago";
+ }
+
function renderTimeline(tweets) {
$("#tweets ul").html($.map(tweets, function(tweet) {
return '<li><img class="profile" src="'
+ tweet.user.profile_image_url + '" />'
- + '<h3><a class="user" title="'
+ + '<h3><a target="_blank" class="user" title="'
+ tweet.user.screen_name + '" href="http://twitter.com/'
+ tweet.user.screen_name + '">'
+ tweet.user.name
+'</a></h3>'
- + tweet.text
+ + linkify(tweet.text)
+ ' <span class="created_at">'
- // + relative_time(tweet.created_at)
+ + prettyDate(tweet.created_at)
+ ' via '
+ tweet.source
+ '</span><br class="clear"/></li>';
@@ -44,13 +75,42 @@
var db = $.couch.db(document.location.href.split('/')[3]);
var design = new CouchDesign(db, unescape(document.location.href).split('/')[5]);
-
+
+ function updateCount() {
+ var len = $('#updateStatus textarea').val().length;
+ $('#statusCount').text(140 - len);
+ };
+
+ function linkify(body) {
+ return body.replace(/https?\:\/\/\S+/g,function(a) {
+ return '<a target="_blank" href="'+a+'">'+a+'</a>';
+ }).replace(/\@([\w\-]+)/g,function(user,name) {
+ return '<a target="_blank" href="http://twitter.com/'+name+'">'+user+'</a>';
+ }).replace(/\#([\w\-]+)/g,function(word,term) {
+ term = term.split(/-/).join(' ');
+ return '<a target="_blank" href="http://search.twitter.com/search?q='+encodeURIComponent(term)+'">'+word+'</a>';
+ });
+ }
+
TwitterCouch(db, design, function(tw) {
- tw.friendsTimeline(function(tweets) {
- renderTimeline(tweets);
+ tw.friendsTimeline(renderTimeline);
+ $('a[href="#refreshTweets"]').click(function() {
+ tw.friendsTimeline(renderTimeline, true);
+ });
+
+ $('#updateStatus').submit(function(e) {
+ e.preventDefault();
+ var status = $('#updateStatus textarea').val();
+ tw.updateStatus(status);
+ $('#updateStatus textarea').val('');
+ updateCount();
});
});
-
+
+ $('#updateStatus textarea').keypress(function() {
+ setTimeout(updateCount,20);
+ });
+ updateCount();
});
</script>
</html>
View
52 _attachments/jquery.xdompost.js
@@ -0,0 +1,52 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+// Usage:
+// $.xdom.post('http://example.com/post-to-here',{"foo":"bar"});
+// Sends a POST to http://example.com/post-to-here with content foo=bar
+
+(function($) {
+ $.xdom = $.xdom || {};
+
+ function now(){
+ return +new Date;
+ }
+
+ var ifc = now();
+
+ $.fn.extend($.xdom,{
+ post : function(url, data) {
+ var ifr = "ifr" + ifc++;
+ var iid = 'xdom_' + ifr;
+ $('body').append('<iframe id="'+iid+'" name="'+iid+'"/>');
+ var iframe = $('#'+iid)[0];
+ var op8 = $.browser.opera && window.opera.version() < 9;
+ if ($.browser.msie || op8) iframe.src = 'javascript:false;document.write("");';
+ $(iframe).css({ position: 'absolute', top: '-1000px', left: '-1000px' });
+
+ var fid = 'form_' + ifr;
+ $('body').append('<form id="'+fid+'" name="'+fid
+ + '" method="POST" action="'+url+'" target="'+iid+'"/>');
+ var form = $('#'+fid)[0];
+ $(form).css({position: 'absolute', top: '-1000px', left: '-1000px' });
+
+ $.each(data, function(key, value) {
+ var inid = 'input_'+ifr+'_'+key;
+ $(form).append('<input id="' + inid + '" name="'
+ + key +'" type="text"/>');
+ $('#'+inid).val(value);
+ });
+
+ form.submit();
+ }
+ });
+})(jQuery);
View
78 _attachments/screen.css
@@ -7,10 +7,11 @@ html {
a {
text-decoration:none;
+ color: #bbf;
}
#tweets li {
- background:#444;
+ background:#333;
margin:5px;
padding:5px;
}
@@ -26,9 +27,84 @@ a {
#tweets img.profile {
float:left;
padding-right:5px;
+ width:48px;
+ height:48px;
}
br.clear {
clear:both;
height:1px;
+}
+
+#tweets .created_at {
+ float:right;
+ font-size:0.8em;
+ color:#777;
+}
+
+#tweets {
+ margin-bottom:105px;
+}
+
+#controls-wrap {
+ height:100px;
+ position:fixed;
+ bottom:0;
+ width:100%;
+ background:#000;
+}
+
+
+#controls {
+ padding:5px;
+}
+
+#buttons {
+ float:left;
+ font-size:2em;
+}
+
+#buttons a {
+ padding:2px;
+ margin:2px;
+ background:#333;
+ color:#bbb;
+ height:20px;
+ width:20px;
+ display:block;
+ text-align:center;
+ line-height:0.5em;
+}
+
+#buttons a:hover {
+ color:#c70;
+}
+
+form#updateStatus {
+ background:#222;
+ padding:5px;
+ margin:5px;
+}
+
+form#updateStatus textarea {
+ background:#444;
+ border:1px inset #000;
+ color:#eee;
+ padding:2px;
+}
+
+#statusCount {
+ float:right;
+}
+
+form#updateStatus input {
+ background:#888;
+ margin:2px;
+ position:relative;
+ top:-6px;
+}
+
+p#about {
+ float:right;
+ font-size:0.8em;
}
View
93 _attachments/twitter-couch.js
@@ -5,7 +5,7 @@ function CouchDesign(db, name) {
};
function TwitterCouch(db, design, callback) {
- var currentUser = null;
+ var currentTwitterID = null;
var host = "twitter.com";
function getJSON(path, params, cb) {
var url = "http://"+host+path+".json?callback=?";
@@ -45,36 +45,73 @@ function TwitterCouch(db, design, callback) {
});
};
- var tw = {
- friendsTimeline : function(cb) {
- viewFriendsTimeline(currentUser.id, function(storedTweets) {
+ function apiCallProceed(force) {
+ var previousCall = $.cookies.get('twitter-last-call');
+ var d = new Date;
+ var now = d.getTime();
+ if (force || !previousCall) {
+ $.cookies.set('twitter-last-call', now);
+ return true;
+ } else {
+ if (now - previousCall > 1000 * 60 * 5) {
+ $.cookies.set('twitter-last-call', now);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ };
+
+ function getFriendsTimeline(cb, opts) {
+ getJSON("/statuses/friends_timeline", opts, function(tweets) {
+ if (tweets.length > 0) {
+ var doc = {
+ tweets : tweets,
+ friendsTimelineOwner : currentTwitterID
+ };
+ db.saveDoc(doc, {success:function() {
+ viewFriendsTimeline(currentTwitterID, cb);
+ }});
+ }
+ });
+ };
+
+ function getTwitterID(cb) {
+ // todo what about when they are not logged in?
+ var cookieID = $.cookies.get('twitter-user-id');
+ if (cookieID) {
+ currentTwitterID = cookieID;
+ cb(publicMethods);
+ } else {
+ // this is hackish to get around the broken twitter cache
+ window.userInfo = function(data) {
+ currentTwitterID = data[0].user.id;
+ $.cookies.set('twitter-user-id', currentTwitterID)
+ callback(publicMethods);
+ };
+ cheapJSONP("http://"+host+"/statuses/user_timeline.json?count=1&callback=userInfo");
+ }
+ };
+
+ var publicMethods = {
+ friendsTimeline : function(cb, force) {
+ viewFriendsTimeline(currentTwitterID, function(storedTweets) {
cb(storedTweets);
- var newestTweet = storedTweets[0];
- var opts = {};
- if (newestTweet) {
- opts.since_id = newestTweet.id;
- }
- getJSON("/statuses/friends_timeline", opts, function(tweets) {
- if (tweets.length > 0) {
- var doc = {
- tweets : tweets,
- friendsTimelineOwner : currentUser.id
- };
- db.saveDoc(doc, {success:function() {
- viewFriendsTimeline(currentUser.id, cb);
- }});
+ if (apiCallProceed(force)) {
+ var newestTweet = storedTweets[0];
+ var opts = {};
+ if (newestTweet) {
+ opts.since_id = newestTweet.id;
}
- });
+ getFriendsTimeline(cb, opts);
+ }
});
+ },
+ updateStatus : function(status) {
+ // todo in_reply_to_status_id
+ $.xdom.post('http://twitter.com/statuses/update.json',{status:status});
}
};
-
- // this is hackish to get around the brokenness of twitter cache
- window.userInfo = function(data) {
- currentUser = data[0].user;
- currentUser.last_tweet = data[0];
- callback(tw);
- };
-
- cheapJSONP("http://"+host+"/statuses/user_timeline.json?count=1&callback=userInfo");
+
+ getTwitterID(callback);
};
Please sign in to comment.
Something went wrong with that request. Please try again.