Changeset 80

User picture

Author: frojo56

(2009/03/13 21:38) Almost 3 years ago

Cleanup

Affected files

Updated twitter_fantastico.user.js Download diff

7980
7
// @require			http://iworkwithcomputers.com/dev/jquery/jquery-1.3.min.js
7
// @require			http://iworkwithcomputers.com/dev/jquery/jquery-1.3.min.js
8
// @require			http://iworkwithcomputers.com/dev/jquery/ui/minified/jquery.ui.all.min.js
8
// @require			http://iworkwithcomputers.com/dev/jquery/ui/minified/jquery.ui.all.min.js
9
// @author    		Carl Furrow
9
// @author    		Carl Furrow
10
// @version			3.12.09
10
// ==/UserScript==
11
// ==/UserScript==
11
12
12
13
//TODO: Nested Tweets seems to break this script. Why?
14
//TODO: Eliminate the website from asking for login credentials twice. Unnecessary!
15
//TODO: Set focus on textareas when shown via a reply or retweet. (Bug is thrown from some Twitter code, I believe. Focus() causes errors)
16
//TODO: Create some kind of direct message mechanism on the main page, without refresh (hover-over user image, icon shows up?)
17
//TODO: @reply helper (this will be hard. api only gets 100 users at a time, no way to filter through entire friend collection)
18
//TODO: Threaded conversations
19
//TODO: Toolbar
20
21
//FIXED(3.2.09): Removed CSS highlighting when on single tweet-page
22
//FIXED(2.27.09): HTTPS errors (via Karolis)
23
//ADDED(2.27.09): TwitPic preview, at Karolis' request (http://userscripts.org/users/26455)
24
//FIXED(2.27.09): Suspend self-highlights when viewing your own page (compare "a.profile_link:href" and ".profile-head a:href")
25
//FIXED(2.24.09): Twitter changed their reply link class to "reply" and that broke my code. Changed to "reply2" for now
26
//FIXED(2.17.09): Make embedded retweet/reply work on non-home pages (single tweet pages, or on profile pages)
27
//FIXED(2.17.09): Get username from profile link if not on home page?
28
//ADDED(2.10.09): Add update panel to page, to show user that there's a new version of the script (idea from Mislav via Endless Tweets userscript)
29
//FIXED(2.10.09): Modify "new" tweet buttons on endless tweet load (reply, retweet, favorite, delete)
30
//ADDED(2.10.09): Using jQuery.noconflict()
31
//FIXED(2.10.09): Add regex so that if on /home and there's an anchor in the url (ie "#" or "#reply", etc), still load tweets
32
//FIXED(2.10.09): Change time to actual time of post, not relative time.
33
//FIXED(2.10.09): Do regex on each status to see if @current_username is in the text. If found, make sure the li has the "to_me" css class applied
34
//FIXED(2.6.09): Clicking modified reply button still adds @reply to main status text area
35
//REMOVED: Removed modified "favorite" button, as twitter seems to have fixed it's functionality
36
//FIXED(2.6.09): Delete button no longer working--somehow, twitter overwrote previous code and javascript dialog always opens now (grrr!)
37
//ADDED: Endless tweets using JSON
38
//ADDED: Modify retweet (embedded retweet)
39
//ADDED: Modify reply (embedded reply)
40
//ADDED: Modify delete (to get it working, sometimes it doesn't work)
41
//ADDED: Modify favorite (to get it working again, sometimes it doesn't work)
42
//ADDED: slide and highlight animations
43
//ADDED: Character counter near textareas
44
//ADDED: Highlight replies to you (yellow?)
45
//ADDED: Highlight own tweets (green)
46
twitter_fantastico = function(){
13
twitter_fantastico = function(){
47
	var j=jQuery.noConflict();
14
	var j=jQuery.noConflict();
48
	var last_read_tweet_id;
15
	var last_read_tweet_id;
...
...
97
64
98
		determine_what_page_user_is_on();
65
		determine_what_page_user_is_on();
99
		j('head').append("<style type='text/css'>"+page_css()+"</style>");
66
		j('head').append("<style type='text/css'>"+page_css()+"</style>");
100
		//add_bottom_actionbar();
101
		log("Loading page data");
67
		log("Loading page data");
102
		//load_page(false,useJQXHR);
103
		load_page(useJQXHR,false);
68
		load_page(useJQXHR,false);
104
		modify_tweets(loaded_tweets[pageNumber-1],false)
69
		modify_tweets(loaded_tweets[pageNumber-1],false)
105
		log("Attaching scroll event handler");
70
		log("Attaching scroll event handler");
106
		//apply scroll event handler
71
		//apply scroll event handler
107
		j(window).scroll(function(e){
72
		j(window).scroll(function(e){
108
			//window.pageYOffset
109
			//window.innerHeight
110
			//log("Y: "+window.pageYOffset+" WindowHeight: "+window.innerHeight);
111
			lastTweetTop = j("#timeline .status:last").offset().top;
73
			lastTweetTop = j("#timeline .status:last").offset().top;
112
			currentScrollPosition = window.pageYOffset + window.innerHeight;
74
			currentScrollPosition = window.pageYOffset + window.innerHeight;
113
			//log("Loading: "+loading+" LastPage: "+lastPage+" currentScrollPosition >= lastTweetTop - 20:" + (currentScrollPosition >= lastTweetTop - 20));
114
			if( !loading && !lastPage && currentScrollPosition >= lastTweetTop - window.innerHeight/3)
75
			if( !loading && !lastPage && currentScrollPosition >= lastTweetTop - window.innerHeight/3)
115
			{
76
			{
116
				pageNumber++;
77
				pageNumber++;
...
...
251
						new_jq_tweet.find("span.actions div").append("<a class='delete' title='delete this update' href='#delete'></a>");
212
						new_jq_tweet.find("span.actions div").append("<a class='delete' title='delete this update' href='#delete'></a>");
252
						modify_delete_button(new_jq_tweet,tweets[i]);
213
						modify_delete_button(new_jq_tweet,tweets[i]);
253
					}
214
					}
254
					find_reply_to_me_in_tweet_and_set_to_me_class(new_jq_tweet);
215
					set_to_me_class(new_jq_tweet);
255
					if(j("#timeline").length>0)
216
					if(j("#timeline").length>0)
256
						new_jq_tweet.appendTo("#timeline");
217
						new_jq_tweet.appendTo("#timeline");
257
					else
218
					else
...
...
267
					add_retweet_button(jq_tweet,tweets[i]);
228
					add_retweet_button(jq_tweet,tweets[i]);
268
					modify_delete_button(jq_tweet,tweets[i]);
229
					modify_delete_button(jq_tweet,tweets[i]);
269
					add_twitpic_preview(jq_tweet,tweets[i]);
230
					add_twitpic_preview(jq_tweet,tweets[i]);
270
					find_reply_to_me_in_tweet_and_set_to_me_class(jq_tweet);
231
					set_to_me_class(jq_tweet);
271
				}
232
				}
272
233
273
			}
234
			}
274
		}
235
		}
275
		//modify_nested_twitter_replies();
276
		//log("Done modifying tweets.");
277
	}
236
	}
278
	function modify_nested_twitter_replies()
237
	function modify_nested_twitter_replies()
279
	{
238
	{
...
...
284
		if(json_tweet.user.screen_name != current_username)
243
		if(json_tweet.user.screen_name != current_username)
285
		{
244
		{
286
			tweet.find("a.retweet-link").remove();
245
			tweet.find("a.retweet-link").remove();
287
			//log("Adding retweet button for "+ json_tweet.id);
288
			//log("Adding retweet button for " + json_tweet.id);
289
			if(tweet.find(".actions div").length==0)
246
			if(tweet.find(".actions div").length==0)
290
				jq_retweet_link = j("<a class='retweet-link' href='#retweet'>RT</a>").appendTo(tweet.find(".actions"));
247
				jq_retweet_link = j("<a class='retweet-link' href='#retweet'>RT</a>").appendTo(tweet.find(".actions"));
291
			else
248
			else
...
...
296
				show_embedded_retweet(j(this).data('json_tweet'));
253
				show_embedded_retweet(j(this).data('json_tweet'));
297
				return false;
254
				return false;
298
			});
255
			});
299
			//log("Done adding retweet");
300
		}
256
		}
301
257
302
	}
258
	}
...
...
313
269
314
			jq_embedded_retweet.appendTo(jq_tweet.find(".status-body")).effect('scale',{from:{height:0},percent:100,direction:'vertical',scale:'box'},300);
270
			jq_embedded_retweet.appendTo(jq_tweet.find(".status-body")).effect('scale',{from:{height:0},percent:100,direction:'vertical',scale:'box'},300);
315
			jq_textarea = jq_embedded_retweet.find("textarea.retweet-text");
271
			jq_textarea = jq_embedded_retweet.find("textarea.retweet-text");
316
			//jq_textarea.focus(function(){
317
			//	counter_span = j(this).parent().find("span.counter");
318
			//	counter_span.html(140-parseInt(j(this).val().length));
319
			//});
320
			counter_span = jq_textarea.parent().find("span.counter");
272
			counter_span = jq_textarea.parent().find("span.counter");
321
			counter_span.html(140-parseInt(jq_textarea.val().length));
273
			counter_span.html(140-parseInt(jq_textarea.val().length));
322
274
...
...
357
	}
309
	}
358
	function modify_reply_button(tweet,json_tweet)
310
	function modify_reply_button(tweet,json_tweet)
359
	{
311
	{
360
		//log("Modifying reply button for " + json_tweet.id);
361
		tweet.find(".actions .repl").remove();
312
		tweet.find(".actions .repl").remove();
362
		tweet.find(".actions .reply").remove();
313
		tweet.find(".actions .reply").remove();
363
		tweet.find(".actions .reply2").remove();
314
		tweet.find(".actions .reply2").remove();
...
...
375
			tweet.find(".reply2").remove();
326
			tweet.find(".reply2").remove();
376
			return false;
327
			return false;
377
		}
328
		}
378
		//log("Adding reply click-event for: "+jq_reply_link.parent().parent().parent().attr("id"));
379
		jq_reply_link.click(function(){
329
		jq_reply_link.click(function(){
380
			show_embedded_reply(j(this).data('json_tweet'));
330
			show_embedded_reply(j(this).data('json_tweet'));
381
			return false;
331
			return false;
382
		});
332
		});
383
		//log("Done modifying reply");
384
	}
333
	}
385
	function show_embedded_reply(json_tweet)
334
	function show_embedded_reply(json_tweet)
386
	{
335
	{
...
...
393
			jq_embedded_reply = j("<div id='reply_"+json_tweet.id+"' class='embedded-reply'><span
class='counter'>140</span><br/><textarea class='reply-text'>@"+json_tweet.user.screen_name+"</textarea><br/><a
class='reply-submit' href='#'>Reply</a><a class='reply-cancel' href='#'>Cancel</a></div>");
342
			jq_embedded_reply = j("<div id='reply_"+json_tweet.id+"' class='embedded-reply'><span
class='counter'>140</span><br/><textarea class='reply-text'>@"+json_tweet.user.screen_name+"</textarea><br/><a
class='reply-submit' href='#'>Reply</a><a class='reply-cancel' href='#'>Cancel</a></div>");
394
			jq_embedded_reply.appendTo(jq_tweet.find(".status-body")).effect('scale',{from:{height:0},percent:100,scale:'box',direction:'vertical'},300);
343
			jq_embedded_reply.appendTo(jq_tweet.find(".status-body")).effect('scale',{from:{height:0},percent:100,scale:'box',direction:'vertical'},300);
395
			jq_textarea = jq_embedded_reply.find("textarea.reply-text");
344
			jq_textarea = jq_embedded_reply.find("textarea.reply-text");
396
			//jq_textarea.focus(function(){
345
397
			//	counter_span = j(this).parent().find("span.counter");
398
			//	counter_span.html(140-parseInt(j(this).val().length));
399
			//});
400
			//jq_textarea.focus();
401
			counter_span = jq_textarea.parent().find("span.counter");
346
			counter_span = jq_textarea.parent().find("span.counter");
402
			counter_span.html(140-parseInt(jq_textarea.val().length));
347
			counter_span.html(140-parseInt(jq_textarea.val().length));
403
			jq_reply_link = jq_embedded_reply.find("a.reply-submit");
348
			jq_reply_link = jq_embedded_reply.find("a.reply-submit");
...
...
429
				jtweet = j(this).data('json_tweet');
374
				jtweet = j(this).data('json_tweet');
430
				jq_ta = j(this).data('jq_textarea');
375
				jq_ta = j(this).data('jq_textarea');
431
				jq_ta.parent().effect('scale',{percent:0,direction:'vertical',scale:'box'},300,function(){j(this).remove();});
376
				jq_ta.parent().effect('scale',{percent:0,direction:'vertical',scale:'box'},300,function(){j(this).remove();});
432
				//jq_ta.parent().remove();
433
				return false;
377
				return false;
434
			});
378
			});
435
		}	
379
		}	
...
...
447
	{
391
	{
448
		if(current_username == json_tweet.user.screen_name)
392
		if(current_username == json_tweet.user.screen_name)
449
		{
393
		{
450
			//log("current_username==json_tweet.user.screen_name: "+current_username+" == "+json_tweet.user.screen_name);
451
			//http://twitter.com/statuses/destroy/id.json
452
			//What's going on here:
394
			//What's going on here:
453
				//I'm finding and removing Twitter's existing delete button, so as to create a new delete button that does not
395
				//I'm finding and removing Twitter's existing delete button, so as to create a new delete button that does not
454
				//use a javascript prompt. Multiple attemps to just "unbind" Twitter's delete button failed. So I had to resort
396
				//use a javascript prompt. Multiple attemps to just "unbind" Twitter's delete button failed. So I had to resort
...
...
484
		jq_tweet_li.children(".actions a.reply2").attr("class","repl");
426
		jq_tweet_li.children(".actions a.reply2").attr("class","repl");
485
		jq_tweet_li.children(".actions .retweet-link").remove();
427
		jq_tweet_li.children(".actions .retweet-link").remove();
486
		jq_tweet_li.find("a:contains('in reply to')").remove();
428
		jq_tweet_li.find("a:contains('in reply to')").remove();
487
		//log("Using "+jq_tweet_li.attr("id")+" as a template for copy.");
488
		jq_tweet_li.attr("id","status_"+json_tweet.id);
429
		jq_tweet_li.attr("id","status_"+json_tweet.id);
489
		jq_tweet_li.attr("class","hentry status u-"+json_tweet.user.screen_name+(current_username==json_tweet.user.screen_name?"
mine":""));
430
		jq_tweet_li.attr("class","hentry status u-"+json_tweet.user.screen_name+(current_username==json_tweet.user.screen_name?"
mine":""));
490
		jq_tweet_li.find("span.author a.url").attr("href","http://twitter.com/"+json_tweet.user.screen_name);
431
		jq_tweet_li.find("span.author a.url").attr("href","http://twitter.com/"+json_tweet.user.screen_name);
...
...
499
		jq_tweet_li.find("span.status-body span.entry-meta a.entry-date span.published").attr("title",format_time(json_tweet.created_at) + "
ago"); 
440
		jq_tweet_li.find("span.status-body span.entry-meta a.entry-date span.published").attr("title",format_time(json_tweet.created_at) + "
ago"); 
500
441
501
		jq_tweet_li.find("span.status-body span.entry-meta a.entry-date span.published").html( format_time(json_tweet.created_at) + " ago"); 
442
		jq_tweet_li.find("span.status-body span.entry-meta a.entry-date span.published").html( format_time(json_tweet.created_at) + " ago"); 
502
		//jq_tweet_li.find("span.status-body span.entry-meta a.entry-date span.published").timeago();
503
		jq_tweet_li.find("span.status-body span.entry-meta a.entry-date + span").html("from " + json_tweet.source + "&nbsp;");
443
		jq_tweet_li.find("span.status-body span.entry-meta a.entry-date + span").html("from " + json_tweet.source + "&nbsp;");
504
444
505
		jq_tweet_li.find("span.actions div a[id^=status_star]").unbind();
445
		jq_tweet_li.find("span.actions div a[id^=status_star]").unbind();
...
...
507
		jq_tweet_li.find("span.actions div a[id^=status_star]").attr("class",(json_tweet.favorited?"fav":"non-fav"));
447
		jq_tweet_li.find("span.actions div a[id^=status_star]").attr("class",(json_tweet.favorited?"fav":"non-fav"));
508
		jq_tweet_li.find("span.actions div a[id^=status_star]").attr("title",(json_tweet.favorited?"favorite this
update":"un-favorite this tweet"));
448
		jq_tweet_li.find("span.actions div a[id^=status_star]").attr("title",(json_tweet.favorited?"favorite this
update":"un-favorite this tweet"));
509
449
510
		//log("Adding retweet button, via convert_json method.");
511
512
513
		jq_tweet_li.find("span.actions div a.retweet-link").unbind();
450
		jq_tweet_li.find("span.actions div a.retweet-link").unbind();
514
451
515
		jq_tweet_li.find("div.embedded-reply").remove();
452
		jq_tweet_li.find("div.embedded-reply").remove();
...
...
519
		{
456
		{
520
			jq_tweet_li.find("span.entry-meta").append("&nbsp;<a
href='http://twitter.com/"+json_tweet.in_reply_to_screen_name+"/status/"+json_tweet.in_reply_to_status_id+"'>in reply to
"+json_tweet.in_reply_to_screen_name+"</a>")
457
			jq_tweet_li.find("span.entry-meta").append("&nbsp;<a
href='http://twitter.com/"+json_tweet.in_reply_to_screen_name+"/status/"+json_tweet.in_reply_to_status_id+"'>in reply to
"+json_tweet.in_reply_to_screen_name+"</a>")
521
		}
458
		}
522
		//find_reply_to_me_in_tweet_and_set_to_me_class(jq_tweet_li);
523
		return jq_tweet_li;
459
		return jq_tweet_li;
524
	}
460
	}
525
	function determine_what_page_user_is_on()
461
	function determine_what_page_user_is_on()
...
...
590
		}
526
		}
591
		return newtext;
527
		return newtext;
592
	}
528
	}
593
	//helluva function name--bad practice on my part :)
529
	function set_to_me_class(jqTweet)
594
	function find_reply_to_me_in_tweet_and_set_to_me_class(jqTweet)
595
	{
530
	{
596
		text = jqTweet.find(".status-body .entry-content").html();
531
		text = jqTweet.find(".status-body .entry-content").html();
597
		if(text != null)
532
		if(text != null)
...
...
613
			url:"http://userscripts.org/scripts/source/41387.user.js",
548
			url:"http://userscripts.org/scripts/source/41387.user.js",
614
			headers: { 'Accept-Encoding': '' }, //Thanks Mislav
549
			headers: { 'Accept-Encoding': '' }, //Thanks Mislav
615
			onload:function(response){
550
			onload:function(response){
616
				//log("Response from userscripts.org: "+response.responseHeaders);
617
				scriptLength = response.responseHeaders.match(/Content-Length: (\d+)/)[1];
551
				scriptLength = response.responseHeaders.match(/Content-Length: (\d+)/)[1];
618
				log("Got script, length: "+scriptLength);
552
				log("Got script, length: "+scriptLength);
619
				if(current_script_length != scriptLength)
553
				if(current_script_length != scriptLength)
620
				{
621
					//show update link
622
					j("<div><a href='http://userscripts.org/scripts/show/41387'>*Update to Twitter Fantastico is
available*</a></div>").prependTo("td#content .wrapper");
554
					j("<div><a href='http://userscripts.org/scripts/show/41387'>*Update to Twitter Fantastico is
available*</a></div>").prependTo("td#content .wrapper");
623
				}
624
			}
555
			}
625
		});		
556
		});		
626
	}
557
	}