Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add the ability to load more tweets beyond the initial limit of 50.

  • Loading branch information...
commit 2c5477bcd8cc3c6881320c0f02f88aadfea5afcd 1 parent 56e215a
@yllus authored
View
3  data/timeline_moretweets.html
@@ -0,0 +1,3 @@
+<div id="div_moretweets" onclick="do_last_action(1);" style="width: 1000px; height: 40px; background-color: #F0F0F0; font-size: 24px; padding: 20px 4px 4px 15px; line-height: 24px; border-bottom: solid 1px #D9DCDE;">
+ Touch to load more tweets
+</div>
View
4 data/timeline_userinfo.html
@@ -1,5 +1,5 @@
-<div style="width: 1008px; height: 75px; background-color: #F0F0F0; font-size: 17px; padding: 7px 4px 4px 7px; line-height: 24px; border-bottom: solid 1px #D9DCDE;">
- <div style="float: left; width: 816px;">
+<div style="width: 1007px; height: 75px; background-color: #F0F0F0; font-size: 17px; padding: 7px 4px 4px 7px; line-height: 24px; border-bottom: solid 1px #D9DCDE;">
+ <div style="float: left; width: 815px;">
<b>Name:</b> ${name}
<br />
<b>Location:</b> ${location}
View
13 data/tweet_more.html
@@ -0,0 +1,13 @@
+<div data-bb-type="item" data-bb-id="${id}" class="bb-hires-image-list-item"><img src="${profile_image_url}" style="z-index: 1; margin-top: 10px;" onclick="viewUser('${screen_name_raw}');">
+ <div class="details">
+ <div style="width: 860px; height: 67px; float: left; margin-top: 10px;">
+ <span class="title">${screen_name}</span>
+ <div class="date">${created_at}</div>
+ <div id="tweet_message_${id}" class="description">${text}</div>
+ <div id="tweet_raw_message_${id}" style="display: none;">${raw_text}</div>
+ </div>
+ <div style="width: 72px; height: 86px; float: right; border-left: 1px solid rgb(217, 220, 222);">
+ <img id="actions_${id}" src="images/actions.png" onclick="show_actions('${id}', '${screen_name_raw}', '${id}');" ontouchstart="start_touch(this.id, 'images/actions-active.png');" ontouchend="end_touch(this.id, 'images/actions.png');" style="width: 30px; height: 30px; padding-left: 18px; padding-top: 30px;">
+ </div>
+ </div>
+</div>
View
1  index.html
@@ -13,6 +13,7 @@
<script type="text/javascript" src="js/datehelper.js"></script>
<script type="text/javascript" src="js/list.js"></script>
<script type="text/javascript" src="js/readability.js"></script>
+ <script type="text/javascript" src="js/bignumber.js"></script>
</head>
<body onload="do_just_launched();">
</body>
View
138 js/bignumber.js
@@ -0,0 +1,138 @@
+//+ Jonas Raoni Soares Silva
+//@ http://jsfromhell.com/classes/bignumber [rev. #4]
+
+BigNumber = function(n, p, r){
+ var o = this, i;
+ if(n instanceof BigNumber){
+ for(i in {precision: 0, roundType: 0, _s: 0, _f: 0}) o[i] = n[i];
+ o._d = n._d.slice();
+ return;
+ }
+ o.precision = isNaN(p = Math.abs(p)) ? BigNumber.defaultPrecision : p;
+ o.roundType = isNaN(r = Math.abs(r)) ? BigNumber.defaultRoundType : r;
+ o._s = (n += "").charAt(0) == "-";
+ o._f = ((n = n.replace(/[^\d.]/g, "").split(".", 2))[0] = n[0].replace(/^0+/, "") || "0").length;
+ for(i = (n = o._d = (n.join("") || "0").split("")).length; i; n[--i] = +n[i]);
+ o.round();
+};
+with({$: BigNumber, o: BigNumber.prototype}){
+ $.ROUND_HALF_EVEN = ($.ROUND_HALF_DOWN = ($.ROUND_HALF_UP = ($.ROUND_FLOOR = ($.ROUND_CEIL = ($.ROUND_DOWN = ($.ROUND_UP = 0) + 1) + 1) + 1) + 1) + 1) + 1;
+ $.defaultPrecision = 40;
+ $.defaultRoundType = $.ROUND_HALF_UP;
+ o.add = function(n){
+ if(this._s != (n = new BigNumber(n))._s)
+ return n._s ^= 1, this.subtract(n);
+ var o = new BigNumber(this), a = o._d, b = n._d, la = o._f,
+ lb = n._f, n = Math.max(la, lb), i, r;
+ la != lb && ((lb = la - lb) > 0 ? o._zeroes(b, lb, 1) : o._zeroes(a, -lb, 1));
+ i = (la = a.length) == (lb = b.length) ? a.length : ((lb = la - lb) > 0 ? o._zeroes(b, lb) : o._zeroes(a, -lb)).length;
+ for(r = 0; i; r = (a[--i] = a[i] + b[i] + r) / 10 >>> 0, a[i] %= 10);
+ return r && ++n && a.unshift(r), o._f = n, o.round();
+ };
+ o.subtract = function(n){
+ if(this._s != (n = new BigNumber(n))._s)
+ return n._s ^= 1, this.add(n);
+ var o = new BigNumber(this), c = o.abs().compare(n.abs()) + 1, a = c ? o : n, b = c ? n : o, la = a._f, lb = b._f, d = la, i, j;
+ a = a._d, b = b._d, la != lb && ((lb = la - lb) > 0 ? o._zeroes(b, lb, 1) : o._zeroes(a, -lb, 1));
+ for(i = (la = a.length) == (lb = b.length) ? a.length : ((lb = la - lb) > 0 ? o._zeroes(b, lb) : o._zeroes(a, -lb)).length; i;){
+ if(a[--i] < b[i]){
+ for(j = i; j && !a[--j]; a[j] = 9);
+ --a[j], a[i] += 10;
+ }
+ b[i] = a[i] - b[i];
+ }
+ return c || (o._s ^= 1), o._f = d, o._d = b, o.round();
+ };
+ o.multiply = function(n){
+ var o = new BigNumber(this), r = o._d.length >= (n = new BigNumber(n))._d.length, a = (r ? o : n)._d,
+ b = (r ? n : o)._d, la = a.length, lb = b.length, x = new BigNumber, i, j, s;
+ for(i = lb; i; r && s.unshift(r), x.set(x.add(new BigNumber(s.join("")))))
+ for(s = (new Array(lb - --i)).join("0").split(""), r = 0, j = la; j; r += a[--j] * b[i], s.unshift(r % 10), r = (r / 10) >>> 0);
+ return o._s = o._s != n._s, o._f = ((r = la + lb - o._f - n._f) >= (j = (o._d = x._d).length) ? this._zeroes(o._d, r - j + 1, 1).length : j) - r, o.round();
+ };
+ o.divide = function(n){
+ if((n = new BigNumber(n)) == "0")
+ throw new Error("Division by 0");
+ else if(this == "0")
+ return new BigNumber;
+ var o = new BigNumber(this), a = o._d, b = n._d, la = a.length - o._f,
+ lb = b.length - n._f, r = new BigNumber, i = 0, j, s, l, f = 1, c = 0, e = 0;
+ r._s = o._s != n._s, r.precision = Math.max(o.precision, n.precision),
+ r._f = +r._d.pop(), la != lb && o._zeroes(la > lb ? b : a, Math.abs(la - lb));
+ n._f = b.length, b = n, b._s = false, b = b.round();
+ for(n = new BigNumber; a[0] == "0"; a.shift());
+ out:
+ do{
+ for(l = c = 0, n == "0" && (n._d = [], n._f = 0); i < a.length && n.compare(b) == -1; ++i){
+ (l = i + 1 == a.length, (!f && ++c > 1 || (e = l && n == "0" && a[i] == "0")))
+ && (r._f == r._d.length && ++r._f, r._d.push(0));
+ (a[i] == "0" && n == "0") || (n._d.push(a[i]), ++n._f);
+ if(e)
+ break out;
+ if((l && n.compare(b) == -1 && (r._f == r._d.length && ++r._f, 1)) || (l = 0))
+ while(r._d.push(0), n._d.push(0), ++n._f, n.compare(b) == -1);
+ }
+ if(f = 0, n.compare(b) == -1 && !(l = 0))
+ while(l ? r._d.push(0) : l = 1, n._d.push(0), ++n._f, n.compare(b) == -1);
+ for(s = new BigNumber, j = 0; n.compare(y = s.add(b)) + 1 && ++j; s.set(y));
+ n.set(n.subtract(s)), !l && r._f == r._d.length && ++r._f, r._d.push(j);
+ }
+ while((i < a.length || n != "0") && (r._d.length - r._f) <= r.precision);
+ return r.round();
+ };
+ o.mod = function(n){
+ return this.subtract(this.divide(n).intPart().multiply(n));
+ };
+ o.pow = function(n){
+ var o = new BigNumber(this), i;
+ if((n = (new BigNumber(n)).intPart()) == 0) return o.set(1);
+ for(i = Math.abs(n); --i; o.set(o.multiply(this)));
+ return n < 0 ? o.set((new BigNumber(1)).divide(o)) : o;
+ };
+ o.set = function(n){
+ return this.constructor(n), this;
+ };
+ o.compare = function(n){
+ var a = this, la = this._f, b = new BigNumber(n), lb = b._f, r = [-1, 1], i, l;
+ if(a._s != b._s)
+ return a._s ? -1 : 1;
+ if(la != lb)
+ return r[(la > lb) ^ a._s];
+ for(la = (a = a._d).length, lb = (b = b._d).length, i = -1, l = Math.min(la, lb); ++i < l;)
+ if(a[i] != b[i])
+ return r[(a[i] > b[i]) ^ a._s];
+ return la != lb ? r[(la > lb) ^ a._s] : 0;
+ };
+ o.negate = function(){
+ var n = new BigNumber(this); return n._s ^= 1, n;
+ };
+ o.abs = function(){
+ var n = new BigNumber(this); return n._s = 0, n;
+ };
+ o.intPart = function(){
+ return new BigNumber((this._s ? "-" : "") + (this._d.slice(0, this._f).join("") || "0"));
+ };
+ o.valueOf = o.toString = function(){
+ var o = this;
+ return (o._s ? "-" : "") + (o._d.slice(0, o._f).join("") || "0") + (o._f != o._d.length ? "." + o._d.slice(o._f).join("") : "");
+ };
+ o._zeroes = function(n, l, t){
+ var s = ["push", "unshift"][t || 0];
+ for(++l; --l; n[s](0));
+ return n;
+ };
+ o.round = function(){
+ if("_rounding" in this) return this;
+ var $ = BigNumber, r = this.roundType, b = this._d, d, p, n, x;
+ for(this._rounding = true; this._f > 1 && !b[0]; --this._f, b.shift());
+ for(d = this._f, p = this.precision + d, n = b[p]; b.length > d && !b[b.length -1]; b.pop());
+ x = (this._s ? "-" : "") + (p - d ? "0." + this._zeroes([], p - d - 1).join("") : "") + 1;
+ if(b.length > p){
+ n && (r == $.DOWN ? false : r == $.UP ? true : r == $.CEIL ? !this._s
+ : r == $.FLOOR ? this._s : r == $.HALF_UP ? n >= 5 : r == $.HALF_DOWN ? n > 5
+ : r == $.HALF_EVEN ? n >= 5 && b[p - 1] & 1 : false) && this.add(x);
+ b.splice(p, b.length - p);
+ }
+ return delete this._rounding, this;
+ };
+}
View
20 js/global.js
@@ -62,6 +62,11 @@ var reply_tweet_raw = '';
// Search variables.
var search_term = '';
+// Track the last tweet ID shown on the timeline.
+var last_tweet_id = '';
+var timeline_load_more = 0;
+var current_status_count = 0;
+
// Constants.
var CONST_HOME = 0;
var CONST_LOADING = 1;
@@ -74,6 +79,7 @@ var CONST_DIRECTMESSAGES = 7;
var CONST_ACTION_READY = 0;
var CONST_ACTION_LOADING = 1;
var CONST_ACTION_BLANK = 2;
+var CONST_MAX_NUM_TWEETS = 800;
// The "traffic cop" function controlling what JS gets executed when a screen has loaded (but is not yet
// displayed), so refer to element.
@@ -222,7 +228,19 @@ function set_last_action( str_action ) {
last_view_action = str_action;
}
-function do_last_action() {
+function do_last_action( load_more ) {
+ if ( load_more != null ) {
+ timeline_load_more = 1;
+
+ // Change the message on the load more tweets DIV.
+ document.getElementById('div_moretweets').innerHTML = 'Loading, please wait...';
+
+ // Subtract 1 from last_tweet_id so we don't duplicate the last tweet (uses BigNumber due to the size of the integer).
+ var big_tweet_id = new BigNumber(last_tweet_id);
+ big_tweet_id = big_tweet_id.subtract(1);
+ last_tweet_id = String(big_tweet_id);
+ }
+
display_action_message(CONST_ACTION_LOADING);
eval(last_view_action);
View
9 js/list.js
@@ -91,7 +91,14 @@ function List( u, s ) {
this.view_list = function( id_str, name, go_back ) {
display_action_message(CONST_ACTION_LOADING);
- oauth.get('https://api.twitter.com/1/lists/statuses.json?include_rts=true&per_page=' + status_count + '&list_id=' + id_str,
+ var url = 'https://api.twitter.com/1/lists/statuses.json?include_rts=true&per_page=' + status_count + '&list_id=' + id_str;
+
+ // If we're retrieving older tweets, add that to the URL as a parameter as well.
+ if ( timeline_load_more == 1 ) {
+ url = url + '&max_id=' + last_tweet_id;
+ }
+
+ oauth.get(url,
function(data) {
var json_data = JSON.parse(data.text);
View
113 js/screens/timeline.js
@@ -2,16 +2,25 @@ function do_timeline( element, json_data, data_type, title_timeline ) {
var str_timeline = '';
var str_lastprofileimageurl = ''; // Saves the last profile image URL for when the search API fails to send a new one in the user object.
var str_title = '';
- var str_template = data_retrieve('data/tweet.html');
+ var str_template = '';
+
+ // Grab the template for new tweets or an addition to the timeline.
+ if ( timeline_load_more == 0 ) {
+ str_template = data_retrieve('data/tweet.html');
+ }
+ else {
+ str_template = data_retrieve('data/tweet_more.html');
+ }
//console.debug(json_data);
// If displaying a user, show a small information bar about the user at the top of the timeline.
- if ( data_type == CONST_USER && json_data.length > 0 ) {
+ if ( data_type == CONST_USER && json_data.length > 0 && timeline_load_more == 0 ) {
str_timeline = str_timeline + get_userinfo(json_data[0].user);
}
for ( var i = 0; i < json_data.length; i++ ) {
+ var str_id = json_data[i].id_str;
var str_instance = str_template;
var str_text = json_data[i].text;
var str_raw_text = str_text;
@@ -19,7 +28,6 @@ function do_timeline( element, json_data, data_type, title_timeline ) {
var str_profileimageurl = '';
var str_screenname = '';
var str_raw_screenname = '';
- var str_id = json_data[i].id_str;
// If the data is from the Twitter search API, get the profile image URL and screen name from the main object.
// Else retrieve it from the REST API's embedded user structure.
@@ -45,7 +53,12 @@ function do_timeline( element, json_data, data_type, title_timeline ) {
str_text = json_data[i].retweeted_status.text;
str_raw_text = str_text;
str_profileimageurl = json_data[i].retweeted_status.user.profile_image_url;
- str_screenname = json_data[i].retweeted_status.user.screen_name + ' &lt;img src=&quot;images/retweet.gif&quot; style=&quot;width: 16px; height: 10px; top: 0; margin: 2.5px 5px 0 0;&quot; /&gt; &lt;span style=&quot;font-weight: normal;&quot;&gt;by&lt;/span&gt; ' + json_data[i].user.screen_name;
+ if ( timeline_load_more == 0 ) {
+ str_screenname = json_data[i].retweeted_status.user.screen_name + ' &lt;img src=&quot;images/retweet.gif&quot; style=&quot;width: 16px; height: 10px; top: 0; margin: 2.5px 5px 0 0;&quot; /&gt; &lt;span style=&quot;font-weight: normal;&quot;&gt;by&lt;/span&gt; ' + json_data[i].user.screen_name;
+ }
+ else {
+ str_screenname = json_data[i].retweeted_status.user.screen_name + ' <img src="images/retweet.gif" style="width: 16px; height: 10px; top: 0; margin: 2.5px 5px 0 0;" /> <span style="font-weight: normal;">by</span> ' + json_data[i].user.screen_name;
+ }
str_raw_screenname = json_data[i].retweeted_status.user.screen_name;
}
}
@@ -75,16 +88,13 @@ function do_timeline( element, json_data, data_type, title_timeline ) {
str_instance = str_instance.replace(/\$\{screen_name\}/g, str_screenname);
str_instance = str_instance.replace('${text}', str_text);
str_instance = str_instance.replace('${raw_text}', str_raw_text);
- str_instance = str_instance.replace('${screen_name_raw}', str_raw_screenname);
- str_instance = str_instance.replace('${created_at}', str_date);
+ str_instance = str_instance.replace(/\$\{screen_name_raw\}/g, str_raw_screenname);
+ str_instance = str_instance.replace(/\$\{created_at\}/g, str_date);
// Add to the overall timeline string.
str_timeline = str_timeline + str_instance;
}
- // Add some white space to the bottom of the list so no tweets are blocked by the toolbar.
- //str_timeline = str_timeline + '<div style="width: 855px; height: 65px;">&nbsp;</div>';
-
// Set the title for the page.
switch( data_type ) {
case CONST_DIRECTMESSAGES:
@@ -98,27 +108,54 @@ function do_timeline( element, json_data, data_type, title_timeline ) {
break;
case CONST_LIST:
str_title = title_timeline + ' (List)';
+ str_timeline = str_timeline + get_moretweets();
break;
case CONST_USER:
str_title = title_timeline + ' (User)';
+ str_timeline = str_timeline + get_moretweets();
break;
default:
str_title = 'Home Timeline';
+ str_timeline = str_timeline + get_moretweets();
}
- if ( element.getElementsByClassName('bb-hires-screen-title').length > 0 ) {
- element.getElementsByClassName('bb-hires-screen-title')[0].innerHTML = str_title;
+
+ // If loading a fresh timeline, load the new timeline into the not yet displayed element.
+ // Else just append to the timeline DIV (and delete the old load more message).
+ if ( timeline_load_more == 0 ) {
+ // Set the title of the screen.
+ if ( element.getElementsByClassName('bb-hires-screen-title').length > 0 ) {
+ element.getElementsByClassName('bb-hires-screen-title')[0].innerHTML = str_title;
+ }
+ if ( element.getElementById('div_titlename') !== null ) {
+ element.getElementById('div_titlename').innerHTML = str_title;
+ }
+
+ // Make all of the tweets visible.
+ element.getElementById('div_timeline').innerHTML = str_timeline;
+ bb.tweetList.apply(element.querySelectorAll('[data-bb-type=tweet-list]'));
+ element.getElementById('div_timeline').style.display = 'block';
+
+ // Set the current number of tweets.
+ current_status_count = json_data.length;
+
+ // Scroll to the top of the window.
+ element.getElementById('div_timeline').scrollTop = 0;
}
- if ( element.getElementById('div_titlename') !== null ) {
- element.getElementById('div_titlename').innerHTML = str_title;
+ else {
+ // Set the current number of tweets.
+ current_status_count = current_status_count + json_data.length;
+
+ // Append the new tweets on the existing timeline.
+ element.getElementById('div_timeline').removeChild(element.getElementById('div_moretweets'));
+ element.getElementById('div_timeline').innerHTML = element.getElementById('div_timeline').innerHTML + str_timeline;
}
- display_action_message(CONST_ACTION_READY, element);
- element.getElementById('div_timeline').innerHTML = str_timeline;
- bb.tweetList.apply(element.querySelectorAll('[data-bb-type=tweet-list]'));
- element.getElementById('div_timeline').style.display = 'block';
+ // Mark the current action is complete.
+ display_action_message(CONST_ACTION_READY, element);
+
- // Scroll to the top of the window.
- element.getElementById('div_timeline').scrollTop = 0;
+ // Reset the flag to load more tweets / load a new timeline.
+ timeline_load_more = 0;
}
function do_screen_timeline_home( element ) {
@@ -127,6 +164,11 @@ function do_screen_timeline_home( element ) {
// Add the number of tweets to the URL as a parameter.
url = url + '?count=' + status_count;
+ // If we're retrieving older tweets, add that to the URL as a parameter as well.
+ if ( timeline_load_more == 1 ) {
+ url = url + '&max_id=' + last_tweet_id;
+ }
+
oauth.get(url,
function(data) {
var json_data = JSON.parse(data.text);
@@ -141,6 +183,11 @@ function do_screen_timeline_direct_messages( element ) {
var url = 'https://api.twitter.com/1/direct_messages.json?include_entities=0&count=' + status_count;
+ // If we're retrieving older tweets, add that to the URL as a parameter as well.
+ if ( timeline_load_more == 1 ) {
+ url = url + '&max_id=' + last_tweet_id;
+ }
+
oauth.get(url,
function(data) {
var json_data = JSON.parse(data.text);
@@ -155,6 +202,11 @@ function do_screen_timeline_mentions( element ) {
var url = 'https://api.twitter.com/1/statuses/mentions.json?include_rts=1&count=' + status_count;
+ // If we're retrieving older tweets, add that to the URL as a parameter as well.
+ if ( timeline_load_more == 1 ) {
+ url = url + '&max_id=' + last_tweet_id;
+ }
+
oauth.get(url,
function(data) {
var json_data = JSON.parse(data.text);
@@ -182,6 +234,11 @@ function do_screen_timeline_user_search( element ) {
display_action_message(CONST_ACTION_LOADING);
var url = 'https://api.twitter.com/1/statuses/user_timeline.json?include_rts=1&screen_name=' + search_term + '&count=' + status_count;
+
+ // If we're retrieving older tweets, add that to the URL as a parameter as well.
+ if ( timeline_load_more == 1 ) {
+ url = url + '&max_id=' + last_tweet_id;
+ }
oauth.get(url,
function(data) {
@@ -285,8 +342,13 @@ function viewUser( screen_name ) {
display_action_message(CONST_ACTION_LOADING);
set_last_action("viewUser('" + screen_name + "');");
- var url = 'https://api.twitter.com/1/statuses/user_timeline.json?include_rts=1&screen_name=' + screen_name + '&count=' + status_count;
var element = document.getElementById(str_timeline_name);
+ var url = 'https://api.twitter.com/1/statuses/user_timeline.json?include_rts=1&screen_name=' + screen_name + '&count=' + status_count;
+
+ // If we're retrieving older tweets, add that to the URL as a parameter as well.
+ if ( timeline_load_more == 1 ) {
+ url = url + '&max_id=' + last_tweet_id;
+ }
oauth.get(url,
function(data) {
@@ -363,6 +425,17 @@ function hide_modal( div_name ) {
document.getElementById(div_name).className = document.getElementById(div_name).className.replace( /(?:^|\s)show(?!\S)/ , '' );
}
+// Display the option to view more tweets for a timeline.
+function get_moretweets() {
+ var str_moretweets = '';
+
+ if ( current_status_count < CONST_MAX_NUM_TWEETS ) {
+ str_moretweets = data_retrieve('data/timeline_moretweets.html');
+ }
+
+ return str_moretweets;
+}
+
// Swap in user informatio when a user's timeline is displayed.
function get_userinfo( user ) {
var str_userinfo = data_retrieve('data/timeline_userinfo.html');
Please sign in to comment.
Something went wrong with that request. Please try again.