Created
September 22, 2008 02:46
-
-
Save monjudoh/11927 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//本体 | |
Twittelien = {}; | |
Twittelien.entryFilters = {}; | |
Twittelien.template = {}; | |
Twittelien.classes = {}; | |
(function($){ | |
function TableUpdator(params){ | |
this._parseRules = params['parseRules'] || {}; | |
this._table = params['table'] || new TAFFY([]); | |
}; | |
// entriesはjQueryオブジェクト | |
TableUpdator.prototype.append = function(entries){ | |
var self = this; | |
var filter = self._filter(self._table); | |
entries = entries.filter(filter); | |
var records = this._parse(entries); | |
this._sort(records); | |
this._insert(records); | |
}; | |
TableUpdator.prototype._filter = function(index){ | |
return this; | |
}; | |
TableUpdator.prototype._parse = function(entries){ | |
var parseRules = this._parseRules; | |
var log = this._log; | |
var self = this; | |
return new TAFFY( | |
entries | |
.map(function(){ | |
var thisEntry = $(this); | |
var entry ={}; | |
for(var key in parseRules){ | |
try{ | |
entry[key] = parseRules[key](thisEntry,$); | |
}catch(e){ | |
self._log(['Parse error occurred.\n','rule name:',key,'\nhtml:',$('<div/>').append(thisEntry.clone()).html()].join('')); | |
return null; | |
} | |
} | |
if(!entry.status_id){ | |
self._log('entry id is null'); | |
return null; | |
} | |
return entry; | |
}) | |
.get() | |
); | |
}; | |
TableUpdator.prototype._sort = function(records){ | |
records.orderBy('status_id'); | |
}; | |
TableUpdator.prototype._insert = function(records){ | |
var table = this._table; | |
records | |
.forEach(function(record){table.insert(record);}); | |
}; | |
TableUpdator.prototype._log = function(){}; | |
Twittelien.TableUpdator = TableUpdator; | |
})(jQuery); | |
(function($){ | |
function Appender(params){ | |
var self = this; | |
if(typeof params.scrape != 'function'){ | |
throw new Error('scrape isn\'t function;'); | |
} | |
var scrape = params.scrape; | |
this._updator = params['updator']; | |
var isStopped = false; | |
this.stop = function(){isStopped = true;}; | |
this.start = function(){ | |
var func = arguments.callee; | |
var started = new Date(); | |
$.ajax({ | |
type:'GET', | |
url:self.url, | |
dataType:'text', | |
success:function(script){ | |
var Element = | |
{ | |
replace:function(id,html){ | |
if(id!='timeline')return; | |
this.html = html; | |
throw new Error(); | |
} | |
}; | |
try{ | |
eval(script); | |
}catch(e){} | |
var entries = scrape(Element.html); | |
self._updator.append(entries); | |
}, | |
error:function(xhr,textStatus){ | |
var win = window.open(); | |
setTimeout(function(){win.location.href=win.location.href;},10*1000); | |
}, | |
complete:function(xhr,textStatus){ | |
if(isStopped){ | |
isStopped = false; | |
return; | |
} | |
setTimeout(func,self.interval); | |
} | |
}); | |
}; | |
}; | |
Appender.prototype.log = function(){}; | |
Appender.prototype.url = 'http://twitter.com/home'; | |
Appender.prototype.interval = 30*1000; | |
Twittelien.Appender = Appender; | |
})(jQuery); | |
// 関数設定((不要なもの外してOK) | |
parseRules = { | |
'status_id' : function(entry){return entry.attr('id');}, | |
'user_name' : function(entry){return entry.find('.status-body>strong>a').text();}, | |
'nick_name' : function(entry){return entry.find('#profile-image').attr('alt');}, | |
'profile_image' : function(entry){return entry.find('#profile-image').attr('src');} | |
,'entry_content' : function(entry,$){ | |
var content = entry.find('.entry-content').get(0).childNodes; | |
content = $.map(content,function(n,i){ | |
var nodeType = n.nodeType; | |
if(nodeType == 1/*Node.ELEMENT_NODE */ && n.nodeName =='A'){ | |
var link = $(n); | |
if(link.attr('href').startsWith('/')){ | |
return {type:'reply',user_name:$.trim(link.text())}; | |
}else{ | |
return {type:'link',text:$.trim(link.text()),href:link.attr('href')}; | |
} | |
}else if(nodeType == 3/*Node.TEXT_NODE */){ | |
return {type:'text',text:$.trim(n.nodeValue)}; | |
}else{ | |
return undefined; | |
} | |
}); | |
return content; | |
} | |
,'published' : function(entry){ | |
try{ | |
var published = entry | |
.find('.published') | |
.attr('title') | |
.replace(/-/g,'/') | |
.replace('T',' ') | |
.replace('+',' GMT+'); | |
return new Date(Date.parse(published)); | |
}catch(e){ | |
return false; | |
} | |
} | |
,'twitter_client':function(entry){ | |
var link = entry.find('.entry-meta>a:not(.entry-date,[href^="http://twitter.com/"])'); | |
return link.size() ? {name:link.text(),url:link.attr('href')} : false; | |
} | |
,'is_protected':function(entry){ | |
return !!entry.find('img[alt="Icon_red_lock"]').size(); | |
} | |
,'reply-url':function(entry){ | |
var link = entry.children(':not(.entry-date)[href^="http://twitter.com/"]'); | |
return link.size() ? link.attr('href') : false; | |
} | |
}; | |
// 重複判定 | |
(function($){ | |
Twittelien.entryFilters.uniq = function(table){ | |
return function(index){ | |
return table.get({status_id:$(this).attr('id')}).length < 1; | |
}; | |
} | |
})(jQuery); | |
(function($){ | |
function scrape(html){ | |
var temp = $('<div/>'); | |
temp.get(0).innerHTML = html; | |
return temp.find('tr.hentry'); | |
}; | |
updator = new Twittelien.TableUpdator({'parseRules':parseRules}); | |
updator._filter = Twittelien.entryFilters.uniq; | |
recent = new Twittelien.Appender({'scrape':scrape,'updator':updator}); | |
var entries = $('tr'); | |
updator.append(entries); | |
$('#container #timeline').empty(); | |
recent.start(); | |
})(jQuery); | |
(function($){ | |
var tag = $.browser.opera ? '​' : '<wbr />'; | |
var pattern = new RegExp('(&[a-z]+;|.)', 'g'); | |
function linkWrapper(text) { | |
return $('<span/>').text(text).html().replace(pattern, '$1' + tag); | |
}; | |
window.linkWrapper = ($.browser.opera && parseFloat($.browser.version) >= 9.5) ? function(text){return $('<span/>').text(text).html();}: linkWrapper; | |
})(jQuery); | |
// 自動更新開始 | |
var viewHelper = [ | |
['user_url',function(data){return 'http://twitter.com/' + data['user_name'];}] | |
,['entry_id',function(data){return data['status_id'].replace('status_','');}] | |
,['entry_url',function(data){return ['http://twitter.com/',data['user_name'],'/statuses/',data['entry_id']].join('');}] | |
,['entry_content',function(data){return data['entry_content'] || {};}] | |
]; | |
(function($){ | |
contexT = { | |
'':function(elem,data){elem.attr('id',data['status_id']);} | |
,'.url':function(elem,data){elem.attr('href',data['user_url']);} | |
,'.url>img':function(elem,data){elem.attr('src',data['profile_image']).attr('alt',data['nick_name']);} | |
,'.content>strong>a':function(elem,data){elem.attr('href',data['user_url']).attr('title',data['nick_name']).text(data['user_name']);} | |
,'.entry-date':function(elem,data){elem.attr('href',data['entry_url']);} | |
,'.published':function(elem,data){ | |
elem.text([data['published'].getHours(),data['published'].getMinutes(),data['published'].getSeconds()].join(':')); | |
} | |
,'.status_actions':function(elem,data){elem.attr('id','status_actions_'+data['entry_id']);} | |
,'.entry-content':function(elem,data){ | |
jQuery.each(data['entry_content'],function(i,value){ | |
switch(value['type']){ | |
case 'text': | |
elem.append( linkWrapper( value['text'] ) ); | |
break; | |
case 'reply': | |
elem | |
.append( $('<a target="_blank"/>').html(linkWrapper( value['user_name'] )).attr('href','/'.concat(value['user_name'])) ) | |
.append( document.createTextNode(' ') ); | |
break; | |
case 'link': | |
var linkUrl = value['href']; | |
elem | |
.append( $('<a target="_blank"/>').html(linkWrapper( linkUrl ) ).attr('href',linkUrl) ) | |
.append( document.createTextNode(' ') ); | |
break; | |
} | |
}); | |
} | |
,'#__twitter_client':function(elem,data){ | |
if(data['twitter_client']){ | |
elem | |
.attr('href',data['twitter_client'].url) | |
.removeAttr('id') | |
.text(data['twitter_client'].name); | |
}else{ | |
elem.replaceWith(elem.text()); | |
} | |
} | |
}; | |
})(jQuery); | |
Twittelien.template.entry = new Templalien([ | |
'<tr class="hentry">' | |
,' <td class="thumb vcard author">' | |
,' <a class="url"><img id="profile-image" class="photo fn" style="width:48px;height:48px;"/></a>' | |
,' </td>' | |
,' <td class="content">' | |
,' <strong><a></a></strong>' | |
,' <span class="entry-content"></span>' | |
,' <span class="meta entry-meta">' | |
,' <a rel="bookmark" class="entry-date"><abbr class="published"></abbr></a>' | |
,' from <a id="__twitter_client">web</a>' | |
,' </span>' | |
,' </td>' | |
,' <td width="10" align="right">' | |
,' <div class="status_actions" >' | |
// 中身だけtoggleさせればいいんじゃね? | |
,' <a href="#">' | |
,' <img border="0" title="Favorite this update" src="http://assets2.twitter.com/images/icon_star_empty.gif" id="status_star_809356512" alt="Icon_star_empty"/>' | |
,' </a>' | |
,' <a href="#" id="__reply">' | |
,' <img border="0" title="reply to " src="http://assets1.twitter.com/images/reply.png" alt="reply to "/>' | |
,' </a>' | |
,' </div>' | |
,' </td>' | |
,'</tr>' | |
].join('') | |
,{viewHelper:viewHelper,context:contexT,events:{}} | |
); | |
//createEntryData(record) | |
//entryDataとentryTmplと値設定は一セットだと思う | |
//ただし、イベントを貼り付けるのは別 | |
Twittelien.template.entry.setEvents([ | |
[ | |
'#__reply' | |
,'click' | |
,function(e){ | |
replyTo(e.data.user_name); | |
e.preventDefault(); | |
} | |
] | |
]); | |
(function($){ | |
function recordToEntry(record){ | |
return Twittelien.template.entry.merge(record); | |
} | |
prepend = function(record){ | |
var timeline = $('#container #timeline'); | |
timeline | |
.prepend(recordToEntry(record)); | |
} | |
append = function(record){ | |
var entry = recordToEntry(record); | |
if($('tr:last').size()){ | |
$('tr:last') | |
.after(entry); | |
}else{ | |
$('#container #timeline') | |
.append(entry); | |
} | |
} | |
})(jQuery); | |
(function($){ | |
$('#timeline') | |
.nextAll().remove().end() | |
.prevAll().remove().end() | |
.after( ['<div style="text-align:right">' | |
,' <a id="prev" class="section_links" href="javascript:void(0);">prev100</a>' | |
,'</div>'].join('') ) | |
.before( ['<div style="text-align:right">' | |
,' <a id="latest" class="section_links" href="javascript:void(0);">new100</a>' | |
,' <a id="next" class="section_links" href="javascript:void(0);">next100</a>' | |
,'</div>'].join('') ); | |
})(jQuery); | |
(function($,updator){ | |
$('#next').bind('click',function(e){ | |
var entries = updator._table; | |
var statusId = $('.hentry:first').attr('id'); | |
var startIndex = 0; | |
if($('.hentry').size()){ | |
var indexes = entries.find({status_id:statusId}); | |
if(indexes.length){ | |
if(indexes[0] < entries.getLength()){ | |
startIndex = indexes[0] + 1; | |
}else{ | |
return; | |
} | |
} | |
}else{ | |
startIndex = entries.getLength() > 100 ? entries.getLength() - 100 : 0; | |
} | |
var endIndex = startIndex + 100; | |
endIndex = entries.getLength() >= endIndex ? endIndex : entries.getLength() + 1; | |
if(startIndex == endIndex){ | |
return; | |
} | |
var filterIndexes = $.map(new Array(endIndex - startIndex),function(i,n){return n + startIndex;}); | |
try{ | |
$.each(entries.get(filterIndexes),function(i,n){if(n){prepend(n);}}); | |
}catch(e){ | |
$('.hentry:gt(149)').remove(); | |
//updator._log(e); | |
} | |
$('.hentry:gt(149)').remove(); | |
if(statusId){ | |
setTimeout(function(){ | |
location.hash=statusId; | |
},100); | |
} | |
}); | |
})(jQuery,updator); | |
//latest | |
(function($,updator){ | |
var timeline = $('#container #timeline'); | |
$('#latest').bind('click',function(e){ | |
var entries = updator._table; | |
timeline.empty(); | |
var startIndex = entries.getLength(); | |
var endIndex = startIndex - 100; | |
endIndex = endIndex > 0 ? endIndex : 0; | |
var filterIndexes = $.map(new Array(startIndex - endIndex),function(i,n){return n + endIndex;}); | |
try{ | |
$.each(entries.get(filterIndexes),function(i,n){if(n){prepend(n);}}); | |
}catch(e){ | |
updator._log(e); | |
} | |
}); | |
})(jQuery,updator); | |
(function($,updator){ | |
$('#prev').bind('click',function(e){ | |
var entries = updator._table; | |
var statusId = $('tr:last').attr('id'); | |
var startIndex = 0; | |
if($('tr').size()){ | |
var indexes = entries.find({status_id:statusId}); | |
if(indexes.length){ | |
if(indexes[0] > 0){ | |
startIndex = indexes[0] - 1; | |
}else{ | |
return; | |
} | |
} | |
}else{ | |
startIndex = entries.getLength() + 1; | |
} | |
var endIndex = startIndex - 100; | |
endIndex = endIndex > 0 ? endIndex : 0; | |
if(startIndex == endIndex){ | |
return; | |
} | |
var filterIndexes = $.map(new Array(startIndex - endIndex),function(i,n){return n + endIndex;}); | |
try{ | |
$.each(entries.get(filterIndexes).reverse(),function(i,n){if(n){append(n);}}); | |
}catch(e){ | |
//updator._log(e); | |
} | |
$(['tr:eq(', $('tr').size() > 150 ? $('tr').size() - 150 : 0 ,')'].join('')).prevAll().remove(); | |
if(statusId){ | |
location.hash=statusId; | |
} | |
}); | |
})(jQuery,updator); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment