13

About

Timeline lets you navigate through revision history for a question and updates the page in real time. This app can be activated by clicking a bookmarklet while viewing an individual question.

This is a very basic prototype, but I do have a lot of cool ideas about how to improve this if there is an interest in the community.

Download

Create a new bookmark with the following URL location:

javascript:(function(){%20var%20API_KEY='Hi_vp0zvN0mS3ou-O1NzHA';var%20loadingMessage;var%20container;var%20revisions;var%20slider;var%20detail;var%20domain;var%20link=$("<link>");link.attr({type:'text/css',rel:'stylesheet',href:'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css'});$("head").append(link);function%20createContainer(){var%20postCell=$('#question%20.postcell');container=$('.timeline-container');if(container.length==0){container=$('<div></div>');container.attr({class:'timeline-container',style:'margin-bottom:15px;'});postCell.prepend(container);}container.children().remove();}function%20displayLoadingMessage(){loadingMessage=$('<h2></h2>');loadingMessage.html('<img%20src="http://kevinx.net/loading.gif"%20alt=""%20/>%20Loading%20timeline...');container.prepend(loadingMessage);}function%20hideLoadingMessage(){loadingMessage.remove();}function%20onSliderTick(evt,ui){var%20rev=findRevision(ui.value);if(rev!=null){updatePage(rev);}}function%20updatePage(revision){$('#question-header%20h1%20a').text(getRevisionValue(revision,'title'));$('#question%20.post-text').html(getRevisionValue(revision,'body'));showDetail(revision);}function%20getRevisionValue(revision,field){if(revision==null)return%20null;if(revision[field]==null){var%20previousRevision=findRevision(revision.revision_number-1);return%20getRevisionValue(previousRevision,field);}return%20revision[field];}function%20findRevision(revNum){for(var%20i=0;i<revisions.length;i++){if(revisions[i].revision_number==revNum){return%20revisions[i];}}return%20null;}function%20showDetail(revision){var%20creation_date=new%20Date();creation_date.setTime(revision.creation_date*1000);detail.find("img").attr('src','http://www.gravatar.com/avatar/'+revision.user.email_hash+'?s=32');detail.find(".userlink").attr('href','http://'+domain+'/users/'+revision.user.user_id);detail.find(".reputation-score").text(addCommas(revision.user.reputation));detail.find(".userlink").text(revision.user.display_name);detail.find(".revdate").text(creation_date.toDateString());detail.find(".revnote").html(revision.comment==''?'<em>no%20comment</em>':revision.comment);detail.find(".viewsource").attr('href','http://'+domain+'/revisions/'+revision.revision_guid+'/view-source');detail.show();}function%20addCommas(nStr){nStr+='';x=nStr.split('.');x1=x[0];x2=x.length>1?'.'+x[1]:'';var%20rgx=/(\d+)(\d{3})/;while(rgx.test(x1)){x1=x1.replace(rgx,'$1'+','+'$2');}return%20x1+x2;}function%20onLoad(){var%20result=/questions\/(\d+)/.exec($(location).attr('href'));if(result.length<=1){hideLoadingMessage();return;}var%20questionId=result[1];domain=$(location).attr('host');$.getJSON('http://api.'+domain+'/1.0/revisions/'+questionId+'/?key='+API_KEY+'&jsonp=?',function(data){hideLoadingMessage();revisions=new%20Array();for(var%20i=0;i<data.revisions.length;i++){if(data.revisions[i].revision_number!=null){revisions.push(data.revisions[i]);}}slider=$('<h2></h2>');container.prepend(slider);slider.slider({min:1,max:revisions.length,value:revisions.length,slide:onSliderTick});detail=$('<div></div>');detail.attr({class:'timeline-detail',style:'padding:2px;border:1px%20solid%20#999;background:#eee;border-radius:5px;-moz-border-radius:5px;margin-bottom:10px;display:none;'});detail.html('<table><tr><td%20style="padding:5px;"><img%20src=""%20alt=""%20border="0"%20style="vertical-align:top;"%20/></td><td%20style="border-right:1px%20solid%20#999;padding:5px%2010px%205px%203px;"><div%20style="margin-bottom:4px;"><a%20href=""%20class="userlink"></a></div><span%20title="reputation%20score"%20class="reputation-score"></span><br%20/><span%20class="revdate"%20style="font-size:smaller;"></span></td><td%20style="padding:5px%2010px;"><p%20class="revnote"></p><p><a%20href=""%20target="_blank"%20class="viewsource">view%20source</a></p></td></tr></table>');container.prepend(detail);showDetail(revisions[0]);var%20tbl=$('<table></table>');tbl.attr({width:'100%'});var%20tr=$('<tr></tr>');tbl.append(tr);var%20endWidth=(container.children('.ui-slider').width()/revisions.length)/2;for(var%20i=0;i<revisions.length;i++){var%20td=$('<td></td>');td.attr({align:i==0?'left':i==revisions.length-1?'right':'center',width:i==0||i==revisions.length-1?endWidth:''});td.text('^');tr.append(td);}container.append(tbl);});}createContainer();displayLoadingMessage();$.getScript('http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js',onLoad);}())

Activate Timeline by clicking the bookmark while viewing an individual question.

Source Code

Non-minified source code can be viewed here:

timeline.js

Updates

2010-7-12

  • Added revision details above slider.
  • Added tick marks below slider.

TODO

  • Add support for tags.
  • Fix error when viewing questions that have been migrated from other StackExchange sites.

Screenshot

489 KB

7
  • 2
    Now that's cool.
    – jjnguy
    Jul 10, 2010 at 23:54
  • It would be nice to have some dates for reference.
    – jjnguy
    Jul 11, 2010 at 0:00
  • 1
    I was planning to enhance the slider with additional info like datetime & editor name/avatar. I might continue working on this or try out some other proof of concepts instead. Thanks for the feedback!
    – Kevin
    Jul 11, 2010 at 0:09
  • Please consider listing this on StackList. Jul 11, 2010 at 2:52
  • 1
    @Kevin, very cool update. (Your arrows don't quite match up with the stop points on the slider.
    – jjnguy
    Jul 12, 2010 at 17:26
  • You should consider making this a greasemonkey script as well
    – jjnguy
    Jul 12, 2010 at 17:26
  • this is awesome! I wish it would work for answers as well! Dec 7, 2010 at 15:22

0

You must log in to answer this question.

Browse other questions tagged .