/*! * jQuery Lifestream Plug-in * Show a stream of your online activity * @version 0.5.5 * @author Christian Vuerings et al. * @copyright Copyright 2014, Christian Vuerings - http://denbuzze.com * @license https://github.com/christianvuerings/jquery-lifestream/blob/master/LICENSE MIT */ /*global jQuery */ ;(function( $ ){ "use strict"; /** * Initialize the lifestream plug-in * @param {Object} config Configuration object */ $.fn.lifestream = function( config ) { // Make the plug-in chainable return this.each(function() { // The element where the lifestream is linked to var outputElement = $(this), // Extend the default settings with the values passed settings = jQuery.extend({ // The name of the main lifestream class // We use this for the main ul class e.g. lifestream // and for the specific feeds e.g. lifestream-twitter classname: "lifestream", // Callback function which will be triggered when a feed is loaded feedloaded: null, // The amount of feed items you want to show limit: 10, // An array of feed items which you want to use list: [] }, config), // The data object contains all the feed items data = { count: settings.list.length, items: [] }, // We use the item settings to pass the global settings variable to // every feed itemsettings = jQuery.extend( true, {}, settings ), /** * This method will be called every time a feed is loaded. This means * that several DOM changes will occur. We did this because otherwise it * takes to look before anything shows up. * We allow 1 request per feed - so 1 DOM change per feed * @private * @param {Array} inputdata an array containing all the feeditems for a * specific feed. */ finished = function( inputdata ) { // Merge the feed items we have from other feeds, with the feeditems // from the new feed $.merge( data.items, inputdata ); // Sort the feeditems by date - we want the most recent one first data.items.sort( function( a, b ) { return ( b.date - a.date ); }); var items = data.items, // We need to check whether the amount of current feed items is // smaller than the main limit. This parameter will be used in the // for loop length = ( items.length < settings.limit ) ? items.length : settings.limit, i = 0, item, // We create an unordered list which will create all the feed // items ul = $('<ul class="' + settings.classname + '"/>'); // Run over all the feed items + add them as list items to the // unordered list for ( ; i < length; i++ ) { item = items[i]; if ( item.html ) { $('<li class="'+ settings.classname + '-' + item.config.service + '">').data( "name", item.config.service ) .data( "url", item.url || "#" ) .data( "time", item.date ) .append( item.html ) .appendTo( ul ); } } // Change the innerHTML with a list of all the feeditems in // chronological order outputElement.html( ul ); // Trigger the feedloaded callback, if it is a function if ( $.isFunction( settings.feedloaded ) ) { settings.feedloaded(); } }, /** * Fire up all the feeds and pass them the right arugments. * @private */ load = function() { var i = 0, j = settings.list.length; // We don't pass the list array to each feed because this will create // a recursive JavaScript object delete itemsettings.list; // Run over all the items in the list for( ; i < j; i++ ) { var config = settings.list[i]; // Check whether the feed exists, if the feed is a function and if a // user has been filled in if ( $.fn.lifestream.feeds[config.service] && $.isFunction( $.fn.lifestream.feeds[config.service] ) && config.user) { // You'll be able to get the global settings by using // config._settings in your feed config._settings = itemsettings; // Call the feed with a config object and finished callback $.fn.lifestream.feeds[config.service]( config, finished ); } } }; // Load the jQuery templates plug-in if it wasn't included in the page. // At then end we call the load method. if( !jQuery.tmpl ) { jQuery.getScript( '//ajax.aspnetcdn.com/ajax/jquery.templates/beta1/' + 'jquery.tmpl.min.js', load); } else { load(); } }); }; /** * Create a valid YQL URL by passing in a query * @param {String} query The query you want to convert into a valid yql url * @return {String} A valid YQL URL */ $.fn.lifestream.createYqlUrl = function( query ) { return ( ('https:' === document.location.protocol ? 'https' : 'http') + '://query.yahooapis.com/v1/public/yql?q=__QUERY__' + '&env=' + 'store://datatables.org/alltableswithkeys&format=json') .replace( "__QUERY__" , encodeURIComponent( query ) ); }; /** * A big container which contains all available feeds */ $.fn.lifestream.feeds = $.fn.lifestream.feeds || {}; /** * Add compatible Object.keys support in older environments that do not natively support it * https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys#section_6 */ if(!Object.keys) { Object.keys = function(o){ if (o !== Object(o)) { throw new TypeError('Object.keys called on non-object'); } var ret=[],p; for(p in o) { if(Object.prototype.hasOwnProperty.call(o,p)) { ret.push(p); } } return ret; }; } }( jQuery )); (function($) { $.fn.lifestream.feeds.atom = function( config, callback ) { var template = $.extend({}, { posted: 'posted <a href="${link.href}">${title.content}</a>' }, config.template), /** * Parse the input from atom feed */ parseAtom = function( input ) { var output = [], list = [], i = 0, j = 0; if(input.query && input.query.count && input.query.count > 0) { list = input.query.results.feed.entry; j = list.length; for( ; i<j; i++) { var item = list[i]; output.push({ url: item.link.href, date: new Date( item.updated ), config: config, html: $.tmpl( template.posted, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where url="' + config.user + '"'), dataType: 'jsonp', success: function( data ) { callback(parseAtom(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.bitbucket = function( config, callback ) { var template = $.extend({}, { commit: '<a href="http://bitbucket.org/${owner}/${name}/changeset/${node}/">committed</a> at <a href="http://bitbucket.org/${owner}/${name}/">${owner}/${name}</a>', pullrequest_fulfilled: 'fulfilled a pull request at <a href="http://bitbucket.org/${owner}/${name}/">${owner}/${name}</a>', pullrequest_rejected: 'rejected a pull request at <a href="http://bitbucket.org/${owner}/${name}/">${owner}/${name}</a>', pullrequest_created: 'created a pull request at <a href="http://bitbucket.org/${owner}/${name}/">${owner}/${name}</a>', create: 'created a new project at <a href="http://bitbucket.org/${owner}/${name}/">${owner}/${name}</a>', fork: 'forked <a href="http://bitbucket.org/${owner}/${name}/">${owner}/${name}</a>' }, config.template), supported_events = [ "commit", "pullrequest_fulfilled", "pullrequest_rejected", "pullrequest_created", "create", "fork" ], parseBitbucketStatus = function( status ) { if ($.inArray(status.event, supported_events) !== -1) { //bb generates some weird create events, check for repository if (status.repository) { if (status.event === "commit") { return $.tmpl( template.commit, { owner: status.repository.owner, name: status.repository.name, node: status.node }); } else { return $.tmpl( template[status.event], { owner: status.repository.owner, name: status.repository.name }); } } } }, parseBitbucket = function( input ) { var output = []; if (input.query && input.query.count && input.query.count > 0) { $.each(input.query.results.json, function () { output.push({ date: new Date(this.events.created_on.replace(/-/g, '/')), config: config, html: parseBitbucketStatus(this.events) }); }); } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select events.event,' + 'events.node, events.created_on,' + 'events.repository.name, events.repository.owner ' + 'from json where url = "https://api.bitbucket.org/1.0/users/' + config.user + '/events/"'), dataType: 'jsonp', success: function( data ) { callback(parseBitbucket(data)); } }); return { 'template' : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.bitly = function( config, callback ) { var template = $.extend({}, { created: 'created URL <a href="${short_url}" title="${title}">' + '${short_url}</a>' }, config.template); $.ajax({ url: $.fn.lifestream.createYqlUrl('select data.short_url, data.created, '+ 'data.title from json where url="' + 'http://bitly.com/u/' + config.user + '.json"'), dataType: "jsonp", success: function( input ) { var output = [], i = 0, j, list; if ( input.query && input.query.count && input.query.results.json ) { list = input.query.results.json; j = list.length; for( ; i < j; i++) { var item = list[i].data; output.push({ date: new Date(item.created * 1000), config: config, html: $.tmpl( template.created, item ) }); } } callback(output); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.blogger = function( config, callback ) { var template = $.extend({}, { posted: 'posted <a href="${origLink}">${title}</a>' }, config.template), parseBlogger = function ( input ) { var output = [], list, i = 0, j, item, k, l; if ( input.query && input.query.count && input.query.count > 0 && input.query.results.feed.entry ) { list = input.query.results.feed.entry; j = list.length; for ( ; i < j; i++) { item = list[i]; if( !item.origLink ) { k = 0; l = item.link.length; for ( ; k < l ; k++ ) { if( item.link[k].rel === 'alternate' ) { item.origLink = item.link[k].href; } } } // ignore items that have no link. if ( item.origLink ){ if( item.title.content ) { item.title = item.title.content; } output.push({ date: new Date( item.published ), config: config, html: $.tmpl( template.posted, item ) }); } } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where url="http://' + config.user + '.blogspot.com/feeds/posts/default"'), dataType: "jsonp", success: function ( data ) { callback(parseBlogger(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.citeulike = function( config, callback ) { var template = $.extend({}, { saved: 'saved <a href="${href}">${title}</a> by ${authors}' }, config.template), parseCiteulike = function( data ) { var output = [], i = 0, j; if(data && data.length && data.length > 0) { j = data.length; for( ; i<j; i++) { var item = data[i]; output.push({ date: new Date(item.date), config: config, url: 'https://www.citeulike.org/user/' + config.user, html: $.tmpl( template.saved, item ) }); } } return output; }; $.ajax({ url: 'https://www.citeulike.org/json/user/' + config.user, dataType: 'jsonp', success: function( data ) { callback(parseCiteulike(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.dailymotion = function( config, callback ) { var template = $.extend({}, { uploaded: 'uploaded a video <a href="${link}">${title[0]}</a>' }, config.template), parseDailymotion = function( input ) { var output = [], list, i = 0, j, item; if ( input.query && input.query.count && input.query.count > 0 && input.query.results.rss.channel.item ) { list = input.query.results.rss.channel.item; j = list.length; for ( ; i < j; i++) { item = list[i]; output.push({ date: new Date ( item.pubDate ), config: config, html: $.tmpl( template.uploaded, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where ' + 'url="http://www.dailymotion.com/rss/user/' + config.user + '"'), dataType: "jsonp", success: function( data ) { callback(parseDailymotion(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.delicious = function( config, callback ) { var template = $.extend({}, { bookmarked: 'bookmarked <a href="${u}">${d}</a>' }, config.template); $.ajax({ url: "https://api.del.icio.us/v2/json/" + config.user, dataType: "jsonp", success: function( data ) { var output = [], i = 0, j; if (data && data.length && data.length > 0) { j = data.length; for( ; i < j; i++) { var item = data[i]; output.push({ date: new Date(item.dt), config: config, html: $.tmpl( template.bookmarked, item ) }); } } callback(output); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.deviantart = function( config, callback ) { var template = $.extend({}, { posted: 'posted <a href="${link}">${title}</a>' }, config.template); $.ajax({ url: $.fn.lifestream.createYqlUrl( 'select title,link,pubDate from rss where ' + 'url="http://backend.deviantart.com/rss.xml?q=gallery%3A' + encodeURIComponent(config.user) + '&type=deviation' + '" | unique(field="title")' ), dataType: 'jsonp', success: function( resp ) { var output = [], items, item, i = 0, j; if (resp.query && resp.query.count > 0) { items = resp.query.results.item; j = items.length; for ( ; i < j; i++) { item = items[i]; output.push({ date: new Date(item.pubDate), config: config, html: $.tmpl( template.posted, item ) }); } } callback(output); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.disqus = function( config, callback ) { var template = $.extend({}, { post: 'commented on <a href="${url}">${thread.title}</a>', thread_like: 'liked <a href="${url}">${thread.title}</a>' }, config.template), parseDisqus = function( input ) { var output = [], i = 0, j, item; if(input) { j = input.length; for( ; i<j; i++) { item = input[i]; // replies to your comments are included by default if (item.type !== 'reply') { output.push({ date: new Date( item.createdAt ), config: config, html: $.tmpl( template[item.type], item.object ) }); } } } return output; }; $.ajax({ url: "https://disqus.com/api/3.0/users/listActivity.json", data: { user: config.user, api_key: config.key }, dataType: 'jsonp', success: function( data ) { if (data.code === 2) { callback([]); // log error to console if not on IE if (console && console.error) { console.error('Error loading Disqus stream.', data.response); } return; } else { callback(parseDisqus(data.response)); } } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.dribbble = function( config, callback ) { var template = $.extend({}, { posted: 'posted a shot <a href="${url}">${title}</a>' }, config.template); $.ajax({ url: "https://api.dribbble.com/players/" + config.user + "/shots", dataType: "jsonp", success: function( data ) { var output = [], i = 0, j; if(data && data.total) { j = data.shots.length; for( ; i<j; i++) { var item = data.shots[i]; output.push({ date: new Date(item.created_at), config: config, html: $.tmpl( template.posted, item ) }); } } callback(output); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { "use strict"; $.fn.lifestream.feeds.facebook_page = function( config, callback ) { var template = $.extend({}, { wall_post: 'posted <a href="${url}">${text}</a>' }, config.template); /** * Parse the input from facebook */ var parseFacebooky = function(response) { var output = []; if (!response.posts || !response.posts.length) { return output; } for (var i = 0 ;i < response.posts.length; i++){ var post = response.posts[i]; output.push({ "date": new Date(post.time * 1000), "config": config, "html": $.tmpl(template.wall_post, post) }); } callback(output); }; $.ajax({ url: 'https://facebooky.herokuapp.com/page/' + config.user, success: parseFacebooky }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { 'use strict'; $.fn.lifestream.feeds.fancy = function( config, callback ) { var template = $.extend({}, { fancied: 'fancy\'d <a href="${link}">${title}</a>' }, config.template), parseFancy = function( input ) { var output = [], i = 0, j; if(input.query && input.query.count && input.query.count > 0) { j = input.query.count; for( ; i<j; i++) { var item = input.query.results.item[i]; output.push({ date: new Date(item.pubDate), config: config, html: $.tmpl( template.fancied, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('SELECT * FROM xml ' + 'WHERE url="http://www.fancy.com/rss/' + config.user + '" AND itemPath="/rss/channel/item"'), dataType: 'jsonp', success: function( data ) { callback(parseFancy(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.flickr = function( config, callback ) { var template = $.extend({}, { posted: 'posted a photo <a href="${link}">${title}</a>' }, config.template); $.ajax({ url: "https://api.flickr.com/services/feeds/photos_public.gne?id=" + config.user + "&lang=en-us&format=json", dataType: "jsonp", jsonp: 'jsoncallback', success: function( data ) { var output = [], i = 0, j; if(data && data.items && data.items.length > 0) { j = data.items.length; for( ; i<j; i++) { var item = data.items[i]; output.push({ date: new Date( item.published ), config: config, html: $.tmpl( template.posted, item ) }); } } callback(output); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.foomark = function( config, callback ) { var template = $.extend({}, { bookmarked: 'bookmarked <a href="${url}">${url}</a>' }, config.template); $.ajax({ url: "http://api.foomark.com/urls/list/", data: { format: "jsonp", username: config.user }, dataType: "jsonp", success: function( data ) { var output = [], i=0, j; if( data && data.length && data.length > 0 ) { j = data.length; for( ; i < j; i++ ) { var item = data[i]; output.push({ date: new Date( item.created_at.replace(/-/g, '/') ), config: config, html: $.tmpl( template.bookmarked, item ) }); } } callback( output ); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.formspring = function( config, callback ) { var template = $.extend({}, { answered: 'answered a question <a href="${link}">${title}</a>' }, config.template); var parseFormspring = function ( input ) { var output = [], list, i = 0, j, item; if ( input.query && input.query.count && input.query.count > 0 && input.query.results.rss.channel.item ) { list = input.query.results.rss.channel.item; j = list.length; for ( ; i < j; i++) { item = list[i]; output.push({ date: new Date( item.pubDate ), config: config, html: $.tmpl( template.answered, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where ' + 'url="http://www.formspring.me/profile/' + config.user + '.rss"'), dataType: "jsonp", success: function ( data ) { callback(parseFormspring(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.forrst = function( config, callback ) { var template = $.extend({}, { posted: 'posted a ${post_type} <a href="${post_url}">${title}</a>' }, config.template); $.ajax({ url: "https://forrst.com/api/v2/users/posts?username=" + config.user, dataType: "jsonp", success: function( data ) { var output = [], i=0, j; if( data && data.resp.length && data.resp.length > 0 ) { j = data.resp.length; for( ; i < j; i++ ) { var item = data.resp[i]; output.push({ date: new Date( item.created_at.replace(' ', 'T') ), config: config, html: $.tmpl( template.posted, item ) }); } } callback( output ); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.foursquare = function( config, callback ) { var template = $.extend({}, { checkedin: 'checked in @ <a href="${link}">${title}</a>' }, config.template), parseFoursquare = function( input ) { var output = [], i = 0, j; if(input.query && input.query.count && input.query.count >0) { j = input.query.count; for( ; i<j; i++) { var item = input.query.results.item[i]; output.push({ date: new Date(item.pubDate), config: config, html: $.tmpl( template.checkedin, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from rss where url=' + '"https://feeds.foursquare.com/history/' + config.user + '.rss"'), dataType: 'jsonp', success: function( data ) { callback(parseFoursquare(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.gimmebar = function( config, callback ) { var template = $.extend({}, { bookmarked: 'bookmarked <a href="${short_url}">${title}</a>' }, config.template); $.ajax({ url: "https://gimmebar.com/api/v0/public/assets/" + config.user + ".json?jsonp_callback=?", dataType: "json", success: function( data ) { data = data.records; var output = [], i = 0, j; if (data && data.length && data.length > 0) { j = data.length; for( ; i < j; i++) { var item = data[i]; output.push({ date: new Date(item.date * 1000), config: config, html: $.tmpl( template.bookmarked, item ) }); } } callback(output); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.github = function( config, callback ) { var template = $.extend({}, { commitCommentEvent: 'commented on <a href="http://github.com/' + '${status.repo.name}">${status.repo.name}</a>', createBranchEvent: 'created branch <a href="http://github.com/' + '${status.repo.name}/tree/${status.payload.ref}">' + '${status.payload.ref}</a> at <a href="http://github.com/' + '${status.repo.name}">${status.repo.name}</a>', createRepositoryEvent: 'created repository ' + '<a href="http://github.com/' + '${status.repo.name}">${status.repo.name}</a>', createTagEvent: 'created tag <a href="http://github.com/' + '${status.repo.name}/tree/${status.payload.ref}">' + '${status.payload.ref}</a> at <a href="http://github.com/' + '${status.repo.name}">${status.repo.name}</a>', deleteBranchEvent: 'deleted branch ${status.payload.ref} at ' + '<a href="http://github.com/${status.repo.name}">' + '${status.repo.name}</a>', deleteTagEvent: 'deleted tag ${status.payload.ref} at ' + '<a href="http://github.com/${status.repo.name}">' + '${status.repo.name}</a>', followEvent: 'started following <a href="http://github.com/' + '${status.payload.target.login}">${status.payload.target.login}</a>', forkEvent: 'forked <a href="http://github.com/${status.repo.name}">' + '${status.repo.name}</a>', gistEvent: '${status.payload.action} gist ' + '<a href="http://gist.github.com/${status.payload.gist.id}">' + '${status.payload.gist.id}</a>', issueCommentEvent: 'commented on issue <a href="http://github.com/' + '${status.repo.name}/issues/${status.payload.issue.number}">' + '${status.payload.issue.number}</a> on <a href="http://github.com/' + '${status.repo.name}">${status.repo.name}</a>', issuesEvent: '${status.payload.action} issue ' + '<a href="http://github.com/${status.repo.name}/issues/' + '${status.payload.issue.number}">${status.payload.issue.number}</a> '+ 'on <a href="http://github.com/${status.repo.name}">' + '${status.repo.name}</a>', pullRequestEvent: '${status.payload.action} pull request ' + '<a href="http://github.com/${status.repo.name}/pull/' + '${status.payload.number}">${status.payload.number}</a> on ' + '<a href="http://github.com/${status.repo.name}">' + '${status.repo.name}</a>', pushEvent: 'pushed to <a href="http://github.com/${status.repo.name}' + '/tree/${status.payload.ref}">${status.payload.ref}</a> at ' + '<a href="http://github.com/${status.repo.name}">' + '${status.repo.name}</a>', watchEvent: 'started watching <a href="http://github.com/' + '${status.repo.name}">${status.repo.name}</a>' }, config.template), parseGithubStatus = function( status ) { if (status.type === 'CommitCommentEvent' ) { return $.tmpl( template.commitCommentEvent, {status: status} ); } else if (status.type === 'CreateEvent' && status.payload.ref_type === 'branch') { return $.tmpl( template.createBranchEvent, {status: status} ); } else if (status.type === 'CreateEvent' && status.payload.ref_type === 'repository') { return $.tmpl( template.createRepositoryEvent, {status: status} ); } else if (status.type === 'CreateEvent' && status.payload.ref_type === 'tag') { return $.tmpl( template.createTagEvent, {status: status} ); } else if (status.type === 'DeleteEvent' && status.payload.ref_type === 'branch') { return $.tmpl( template.deleteBranchEvent, {status: status} ); } else if (status.type === 'DeleteEvent' && status.payload.ref_type === 'tag') { return $.tmpl( template.deleteTagEvent, {status: status} ); } else if (status.type === 'FollowEvent' ) { return $.tmpl( template.followEvent, {status: status} ); } else if (status.type === 'ForkEvent' ) { return $.tmpl( template.forkEvent, {status: status} ); } else if (status.type === 'GistEvent' ) { if (status.payload.action === 'create') { status.payload.action = 'created'; } else if (status.payload.action === 'update') { status.payload.action = 'updated'; } return $.tmpl( template.gistEvent, {status: status} ); } else if (status.type === 'IssueCommentEvent' ) { return $.tmpl( template.issueCommentEvent, {status: status} ); } else if (status.type === 'IssuesEvent' ) { return $.tmpl( template.issuesEvent, {status: status} ); } else if (status.type === 'PullRequestEvent' ) { return $.tmpl( template.pullRequestEvent, {status: status} ); } else if (status.type === 'PushEvent' ) { status.payload.ref = status.payload.ref.split('/')[2]; return $.tmpl( template.pushEvent, {status: status} ); } else if (status.type === 'WatchEvent' ) { return $.tmpl( template.watchEvent, {status: status} ); } }, parseGithub = function( input ) { var output = [], i = 0, j; if (input.query && input.query.count && input.query.count >0) { j = input.query.count; for ( ; i<j; i++) { var status = input.query.results.json[i].json; output.push({ date: new Date(status.created_at), config: config, html: parseGithubStatus(status), url: 'https://github.com/' + config.user }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select ' + 'json.type, json.actor, json.repo, json.payload, json.created_at ' + 'from json where url="https://api.github.com/users/' + config.user + '/events/public?per_page=100"'), dataType: 'jsonp', success: function( data ) { callback(parseGithub(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.googleplus = function( config, callback ) { var template = $.extend({}, { posted: '<a href="${actor.url}">${actor.displayName}</a>' + ' has posted a new entry <a href="${url}" ' + 'title="${id}">${title}</a> <!--With--> ' + '${object.replies.totalItems} replies, ' + '${object.plusoners.totalItems} +1s, ' + '${object.resharers.totalItems} Reshares' }, config.template), parseGooglePlus = function( input ) { var output = [], i = 0, j, item; if(input && input.items) { j = input.items.length; for( ; i<j; i++) { item = input.items[i]; output.push({ date: new Date( item.published ), config: config, html: $.tmpl( template.posted, item ) }); } } return output; }; $.ajax({ url: "https://www.googleapis.com/plus/v1/people/" + config.user + "/activities/public", data: { key: config.key }, dataType: 'jsonp', success: function( data ) { if (data.error) { callback([]); if (console && console.error) { console.error('Error loading Google+ stream.', data.error); } return; } else { callback(parseGooglePlus(data)); } } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.hypem = function( config, callback ) { if( !config.type || config.type !== "history" || config.type !== "loved" ) { config.type = "loved"; } var template = $.extend({}, { loved: 'loved <a href="http://hypem.com/item/${mediaid}">${title}</a> by <a href="http://hypem.com/artist/${artist}">${artist}</a>', history: 'listened to <a href="http://hypem.com/item/${mediaid}">${title}</a> by <a href="http://hypem.com/artist/${artist}">${artist}</a>' }, config.template); $.ajax({ url: "http://hypem.com/playlist/" + config.type + "/" + config.user + "/json/1/data.js", dataType: "json", success: function( data ) { var output = [], i = 0, j = -1; for (var k in data) { if (data.hasOwnProperty(k)) { j++; } } if (data && j > 0) { for( ; i < j; i++) { var item = data[i]; output.push({ date: new Date( (config.type === "history" ? item.dateplayed : item.dateloved) * 1000 ), config: config, html: $.tmpl( (config.type === "history" ? template.history : template.loved) , item ) }); } } callback(output); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.instapaper = function( config, callback ) { var template = $.extend({}, { loved: 'loved <a href="${link}">${title}</a>' }, config.template), parseInstapaper = function( input ) { var output = [], list, i = 0, j, item; if(input.query && input.query.count && input.query.count > 0 && input.query.results.rss.channel.item) { list = input.query.results.rss.channel.item; j = list.length; for( ; i<j; i++) { item = list[i]; output.push({ date: new Date( item.pubDate ), config: config, html: $.tmpl( template.loved, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where url=' + '"http://www.instapaper.com/starred/rss/' + config.user + '"'), dataType: 'jsonp', success: function( data ) { callback(parseInstapaper(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.iusethis = function( config, callback ) { var template = $.extend({}, { global: '${action} <a href="${link}">${what}</a> on (${os})' }, config.template); var parseIusethis = function( input ) { var output = [], list, i, j, k, l, m = 0, n, item, title, actions, action, what, os, oss = ["iPhone", "OS X", "Windows"]; if (input.query && input.query.count && input.query.count > 0 && input.query.results.rss) { n = input.query.results.rss.length; actions = ['started using', 'stopped using', 'stopped loving', 'Downloaded', 'commented on', 'updated entry for', 'started loving', 'registered']; l = actions.length; for( ; m < n; m++) { os = oss[m]; list = input.query.results.rss[m].channel.item; i = 0; j = list.length; for ( ; i < j; i++) { item = list[i]; title = item.title.replace(config.user + ' ', ''); k = 0; for( ; k < l; k++) { if(title.indexOf(actions[k]) > -1) { action = actions[k]; break; } } what = title.split(action); output.push({ date: new Date(item.pubDate), config: config, html: $.tmpl( template.global, { action: action.toLowerCase(), link: item.link, what: what[1], os: os } ) }); } } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where ' + 'url="http://iphone.iusethis.com/user/feed.rss/' + config.user + '" or ' + 'url="http://osx.iusethis.com/user/feed.rss/' + config.user + '" or ' + 'url="http://win.iusethis.com/user/feed.rss/' + config.user + '"'), dataType: "jsonp", success: function( data ) { callback(parseIusethis(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.lastfm = function( config, callback ) { var template = $.extend({}, { loved: 'loved <a href="${url}">${name}</a> by ' + '<a href="${artist.url}">${artist.name}</a>' }, config.template), parseLastfm = function( input ) { var output = [], list, i = 0, j; if(input.query && input.query.count && input.query.count > 0 && input.query.results.lovedtracks && input.query.results.lovedtracks.track) { list = input.query.results.lovedtracks.track; j = list.length; for( ; i<j; i++) { var item = list[i], itemDate = item.nowplaying ? new Date() : item.date.uts; output.push({ date: new Date(parseInt((itemDate * 1000), 10)), config: config, html: $.tmpl( template.loved, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where url=' + '"http://ws.audioscrobbler.com/2.0/user/' + config.user + '/lovedtracks.xml"'), dataType: 'jsonp', success: function( data ) { callback(parseLastfm(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.librarything = function( config, callback ) { var template = $.extend({}, { book: 'added <a href="http://www.librarything.com/work/book/${book.book_id}"' + ' title="${book.title} by ${book.author_fl}">' + '${book.title} by ${book.author_fl}</a> to my library' }, config.template), parseLibraryThing = function( input ) { var output = [], i = ""; if(input.books) { // LibraryThing returns a hash that maps id to Book objects // which leads to the following slightly weird for loop. for (i in input.books) { if (input.books.hasOwnProperty(i)) { var book = input.books[i]; output.push({ date : new Date(book.entry_stamp * 1000), config : config, html : $.tmpl(template.book, {book : book}), url : 'http://www.librarything.com/profile/' + config.user }); } } } return output; }; $.ajax({ url: 'https://www.librarything.com/api_getdata.php?booksort=entry_REV&userid=' + config.user, dataType: 'jsonp', success: function( data ) { callback(parseLibraryThing(data)); } }); return { "template" : template }; }; })(jQuery); (function($) { 'use strict'; $.fn.lifestream.feeds.linkedin = function( config, callback ) { var template = $.extend({}, { 'posted': '<a href="${link}">${title}</a>' }, config.template), jsonpCallbackName = 'jlsLinkedinCallback' + config.user, createYql = function(){ var query = 'SELECT * FROM feed WHERE url="' + config.url + '"'; // I bet some will not read the instructions if(config.user) { query += ' AND link LIKE "%' + config.user + '%"'; } return query; }, parseLinkedinItem = function(item) { return { 'date': new Date(item.pubDate), 'config': config, 'html': $.tmpl(template.posted, item) }; }; // !!! Global function for jsonp callback window[jsonpCallbackName] = function(input) { var output = [], i = 0; if(input.query && input.query.count && input.query.count > 0) { if (input.query.count === 1) { output.push(parseLinkedinItem(input.query.results.item)); } else { for(i; i < input.query.count; i++) { var item = input.query.results.item[i]; output.push(parseLinkedinItem(item)); } } } callback(output); }; $.ajax({ 'url': $.fn.lifestream.createYqlUrl(createYql()), 'cache': true, 'data': { // YQL will cache this for 5 minutes '_maxage': 300 }, 'dataType': 'jsonp', // let YQL cache 'jsonpCallback': jsonpCallbackName }); // Expose the template. // We use this to check which templates are available return { 'template': template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.mendeley = function( config, callback ) { var template = $.extend({}, { flagged1: 'flagged <a href="http://www.mendeley.com${link}">${title}</a>', flagged2: 'flagged <a href="${link}">${title}</a>' }, config.template), parseMendeley = function( input ) { var output = [], list, i = 0, j; if(input.query && input.query.count && input.query.count > 0) { list = input.query.results.rss.channel.item; j = list.length; for( ; i<j; i++) { var item = list[i]; var tmplt = ( (item.link.charAt(0) === '/') ? template.flagged1 : template.flagged2 ); output.push({ date: new Date(item.pubDate), config: config, url: 'http://mendeley.com/groups/' + config.user, html: $.tmpl( tmplt, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where url=' + '"http://www.mendeley.com/groups/' + config.user + '/feed/rss/"'), dataType: 'jsonp', success: function( data ) { callback(parseMendeley(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.miso = function( config, callback ) { var template = $.extend({}, { watched: 'checked in to <a href="${link}">${title}</a>' }, config.template), /** * Parse the input from rss feed */ parseMiso = function( input ) { var output = [], list, i = 0, j; if(input.query && input.query.count && input.query.count > 0) { list = input.query.results.rss.channel.item; j = list.length; for( ; i<j; i++) { var item = list[i]; output.push({ url: 'http://www.gomiso.com/feeds/user/' + config.user + '/checkins.rss', date: new Date( item.pubDate ), config: config, html: $.tmpl( template.watched, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where url="' + 'http://www.gomiso.com/feeds/user/' + config.user + '/checkins.rss"'), dataType: 'jsonp', success: function( data ) { callback(parseMiso(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.mlkshk = function( config, callback ) { var template = $.extend({}, { posted: 'posted <a href="${link}">${title}</a>' }, config.template); var parseMlkshk = function ( input ) { var output = [], list, i = 0, j, item; if ( input.query && input.query.count && input.query.count > 0 && input.query.results.rss.channel.item ) { list = input.query.results.rss.channel.item; j = list.length; for ( ; i < j; i++) { item = list[i]; output.push({ date: new Date( item.pubDate ), config: config, html: $.tmpl( template.posted, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where ' + 'url="http://mlkshk.com/user/' + config.user + '/rss"'), dataType: "jsonp", success: function ( data ) { callback(parseMlkshk(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.pinboard = function( config, callback ) { var template = $.extend({}, { bookmarked: 'bookmarked <a href="${link}">${title}</a>' }, config.template); var parsePinboard = function( input ) { var output = [], list, i = 0, j, item; if (input.query && input.query.count && input.query.count > 0) { list = input.query.results.RDF.item; j = list.length; for ( ; i < j; i++) { item = list[i]; output.push({ date: new Date(item.date), config: config, html: $.tmpl( template.bookmarked, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where ' + 'url="http://feeds.pinboard.in/rss/u:' + config.user + '"'), dataType: "jsonp", success: function( data ) { callback(parsePinboard(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.pocket = function( config, callback ) { var template = $.extend({}, { pocketed: 'pocketed <a href="${link}">${title}</a>' }, config.template), parsePocket = function( input ) { var output = [], list, i = 0, j; if(input.query && input.query.results) { list = input.query.results.rss.channel.item; j = list.length; for( ; i<j; i++) { var item = list[i]; var tmplt = template.pocketed; output.push({ date: new Date(item.pubDate), config: config, url: 'http://getpocket.com', html: $.tmpl( tmplt, item ), }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where url=' + '"http://www.getpocket.com/users/' + config.user + '/feed/all/"'), dataType: 'json', success: function( data ) { callback(parsePocket(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.posterous = function( config, callback ) { var template = $.extend({}, { posted: 'posted <a href="${link}">${title}</a>' }, config.template); var parsePosterous = function ( input ) { var output = [], list, i = 0, j, item; if ( input.query && input.query.count && input.query.count > 0 && input.query.results.rss.channel.item ) { list = input.query.results.rss.channel.item; j = list.length; for ( ; i < j; i++) { item = list[i]; output.push({ date: new Date( item.pubDate ), config: config, html: $.tmpl( template.posted, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where ' + 'url="http://' + config.user + '.posterous.com/rss.xml"'), dataType: "jsonp", success: function ( data ) { callback(parsePosterous(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.quora = function( config, callback ) { var template = $.extend({}, { posted: '<a href="${link}">${title}</a>' }, config.template), /** * Get the link * Straigth copy from RSS * * @param {Object} channel * @return {String} */ getChannelUrl = function(channel){ var i = 0, j = channel.link.length; for( ; i < j; i++) { var link = channel.link[i]; if( typeof link === 'string' ) { return link; } } return ''; }, /** * Parse the input from quora feed */ parseRSS = function( input ) { var output = [], list = [], i = 0, j = 0, url = ''; if(input.query && input.query.count && input.query.count > 0) { list = input.query.results.rss.channel.item; j = list.length; url = getChannelUrl(input.query.results.rss.channel); for( ; i<j; i++) { var item = list[i]; output.push({ url: url, date: new Date( item.pubDate ), config: config, html: $.tmpl( template.posted, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where ' + 'url="http://www.quora.com/' + config.user + '/rss"'), dataType: 'jsonp', success: function( data ) { callback(parseRSS(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.reddit = function( config, callback ) { var template = $.extend({}, { commented: '<a href="http://www.reddit.com/r/${item.data.subreddit}' + '/comments/${item.data.link_id.substring(3)}/u/' + '${item.data.name.substring(3)}?context=3">commented ' + '(${score})</a> in <a href="http://www.reddit.com/r/' + '${item.data.subreddit}">${item.data.subreddit}</a>', created: '<a href="http://www.reddit.com${item.data.permalink}">' + 'created new thread (${score})</a> in ' + '<a href="http://www.reddit.com/r/${item.data.subreddit}">' + '${item.data.subreddit}</a>' }, config.template); /** * Parsed one item from the Reddit API. * item.kind == t1 is a reply, t2 is a new thread */ var parseRedditItem = function( item ) { var score = item.data.ups - item.data.downs, pass = { item: item, score: (score > 0) ? "+" + score : score }; // t1 = reply, t3 = new thread if (item.kind === "t1") { return $.tmpl( template.commented, pass ); } else if (item.kind === "t3") { return $.tmpl( template.created, pass ); } }, /** * Reddit date's are simple epochs. * seconds*1000 = milliseconds */ convertDate = function( date ) { return new Date(date * 1000); }; $.ajax({ url: "https://pay.reddit.com/user/" + config.user + ".json", dataType: "jsonp", jsonp:"jsonp", success: function( data ) { var output = [], i = 0, j; if(data && data.data && data.data.children && data.data.children.length > 0) { j = data.data.children.length; for( ; i<j; i++) { var item = data.data.children[i]; output.push({ date: convertDate(item.data.created_utc), config: config, html: parseRedditItem(item), url: 'http://reddit.com/user/' + config.user }); } } callback(output); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.rss = function( config, callback ) { var template = $.extend({}, { posted: 'posted <a href="${link}">${title}</a>' }, config.template), /** * Get the link * @param {Object} channel * @return {String} */ getChannelUrl = function(channel){ var i = 0, j = channel.link.length; for( ; i < j; i++) { var link = channel.link[i]; if( typeof link === 'string' ) { return link; } } return ''; }, /** * Parse the input from rss feed */ parseRSS = function( input ) { var output = [], list = [], i = 0, j = 0, url = ''; if(input.query && input.query.count && input.query.count > 0) { list = input.query.results.rss.channel.item; j = list.length; url = getChannelUrl(input.query.results.rss.channel); for( ; i<j; i++) { var item = list[i]; output.push({ url: url, date: new Date( item.pubDate ), config: config, html: $.tmpl( template.posted, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where url="' + config.user + '"'), dataType: 'jsonp', success: function( data ) { callback(parseRSS(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.slideshare = function( config, callback ) { var template = $.extend({}, { uploaded: 'uploaded a presentation <a href="${link}">${title}</a>' }, config.template); var parseSlideshare = function( input ) { var output = [], list, i = 0, j, item; if (input.query && input.query.count && input.query.count > 0) { list = input.query.results.rss.channel.item; j = list.length; for ( ; i < j; i++) { item = list[i]; output.push({ date: new Date(item.pubDate), config: config, html: $.tmpl( template.uploaded, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where ' + 'url="http://www.slideshare.net/rss/user/' + config.user + '"'), dataType: "jsonp", success: function( data ) { callback(parseSlideshare(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.snipplr = function( config, callback ) { var template = $.extend({}, { posted: 'posted a snippet <a href="${link}">${title}</a>' }, config.template); var parseSnipplr = function ( input ) { var output = [], list, i = 0, j, item; if ( input.query && input.query.count && input.query.count > 0 && input.query.results.rss.channel.item ) { list = input.query.results.rss.channel.item; j = list.length; for ( ; i < j; i++) { item = list[i]; output.push({ date: new Date( item.pubDate ), config: config, html: $.tmpl( template.posted, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where ' + 'url="http://snipplr.com/rss/users/' + config.user + '"'), dataType: "jsonp", success: function ( data ) { callback(parseSnipplr(data)); } }); }; })(jQuery);(function($) { $.fn.lifestream.feeds.stackoverflow = function( config, callback ) { var template = $.extend({}, { global: '<a href="${link}">${text}</a> - ${title}' }, config.template); var parseStackoverflowItem = function( item ) { var text="", title="", link="", stackoverflow_link = "http://stackoverflow.com/users/" + config.user, question_link = "http://stackoverflow.com/questions/"; if(item.timeline_type === "badge") { link = stackoverflow_link + "?tab=reputation"; } text = item.timeline_type; title = item.title || item.detail || ""; link = link || question_link + item.post_id; return { link: link, title: title, text: text }; }, convertDate = function( date ) { return new Date(date * 1000); }; $.ajax({ url: "https://api.stackexchange.com/2.1/users/" + config.user + "/timeline?site=stackoverflow", dataType: "jsonp", jsonp: 'jsonp', success: function( data ) { var output = []; if(data && data.items) { for(var i = 0 ; i < data.items.length; i++) { var item = data.items[i]; output.push({ date: convertDate(item.creation_date), config: config, html: $.tmpl( template.global, parseStackoverflowItem(item) ) }); } } callback(output); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.tumblr = function( config, callback ) { var template = $.extend({}, { posted: 'posted a ${type} <a href="${url}">${title}</a>' }, config.template), limit = config.limit || 20, getImage = function( post ) { switch(post.type) { case 'photo': var images = post['photo-url']; return $('<img width="75" height="75"/>') .attr({ src: images[images.length - 1].content, title: getTitle(post), alt: getTitle(post) }).wrap('<div/>').parent().html(); // generate an HTML string case 'video': var videos = post['video-player']; var video = videos[videos.length - 1].content; // Videos hosted on Tumblr use JavaScript to render the // video, but the JavaScript doesn't work when we call it // from a lifestream - so don't try to embed these. if (video.match(/<\s*script/)) { return null; } return video; case 'audio': // Unlike photo and video, audio gives you no visual indication // of what it contains, so we append the "title" text. return post['audio-player'] + ' ' + // HTML-escape the text. $('<div/>').text(getTitle(post)).html(); default: return null; } }, getFirstElementOfBody = function( post, bodyAttribute ) { return $(post[bodyAttribute]).filter(':not(:empty):first').text(); }, getTitleForPostType = function( post ) { var title; switch(post.type) { case 'regular': return post['regular-title'] || getFirstElementOfBody(post, 'regular-body'); case 'link': title = post['link-text'] || getFirstElementOfBody(post, 'link-description'); if (title === '') { title = post['link-url']; } return title; case 'video': return getFirstElementOfBody(post, 'video-caption'); case 'audio': return getFirstElementOfBody(post, 'audio-caption'); case 'photo': return getFirstElementOfBody(post, 'photo-caption'); case 'quote': return '"' + post['quote-text'].replace(/<.+?>/g, ' ').trim() + '"'; case 'conversation': title = post['conversation-title']; if (!title) { title = post.conversation.line; if (typeof(title) !== 'string') { title = title[0].label + ' ' + title[0].content + ' ...'; } } return title; case 'answer': return post.question; default: return post.type; } }, /** * get title text */ getTitle = function( post ) { var title = getTitleForPostType(post) || ''; // remove tags return title.replace( /<.+?>/gi, " "); }, createTumblrOutput = function( config, post ) { return { date: new Date(post.date), config: config, html: $.tmpl( template.posted, { type: post.type.replace('regular', 'blog entry'), url: post.url, image: getImage(post), title: getTitle(post) } ) }; }, parseTumblr = function( input ) { var output = [], i = 0, j, post; if(input.query && input.query.count && input.query.count > 0) { // If a user only has one post, post is a plain object, otherwise it // is an array if ( $.isArray(input.query.results.posts.post) ) { j = input.query.results.posts.post.length; for( ; i < j; i++) { post = input.query.results.posts.post[i]; output.push(createTumblrOutput(config, post)); } } else if ( $.isPlainObject(input.query.results.posts.post) ) { output.push( createTumblrOutput(config,input.query.results.posts.post) ); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select *' + ' from tumblr.posts where username="' + config.user + '"' + ' and num="' + limit + '"'), dataType: 'jsonp', success: function( data ) { callback(parseTumblr(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { "use strict"; $.fn.lifestream.feeds.twitter = function(config, callback) { var template = $.extend({}, { "posted": '{{html tweet}}' }, config.template); /** * Add links to the twitter feed. * Hashes, @ and regular links are supported. * @private * @param {String} tweet A string of a tweet * @return {String} A linkified tweet */ var linkify = function( tweet ) { var link = function( t ) { return t.replace( /([a-z]+:\/\/)([-A-Z0-9+&@#\/%?=~_|(\)!:,.;]*[-A-Z0-9+&@#\/%=~_|(\)])/ig, function( m, m1, m2 ) { return $("<a></a>").attr("href", m).text( ( ( m2.length > 35 ) ? m2.substr( 0, 34 ) + '...' : m2 ) )[0].outerHTML; } ); }, at = function( t ) { return t.replace( /(^|[^\w]+)\@([a-zA-Z0-9_]{1,15})/g, function( m, m1, m2 ) { var elem = ($("<a></a>") .attr("href", "https://twitter.com/" + m2) .text("@" + m2))[0].outerHTML; return m1 + elem; } ); }, hash = function( t ) { return t.replace(/(pic\.twitter\.com\/.*)/g, '').replace( /<a.*?<\/a>|(^|\r?\n|\r|\n|)(#|\$)([a-zA-Z0-9ÅåÄäÖöØøÆæÉéÈèÜüÊêÛûÎî_]+)(\r?\n|\r|\n||$)/g, function( m, m1, m2, m3, m4 ) { if (typeof m3 == "undefined") return m; var elem = ""; if (m2 == "#") { elem = ($("<a></a>") .attr("href", "https://twitter.com/hashtag/" + m3 + "?src=hash") .text("#" + m3))[0].outerHTML; } else if (m2 == "$") { elem = ($("<a></a>") .attr("href", "https://twitter.com/search?q=%24" + m3 + "&src=hash") .text("$" + m3))[0].outerHTML; } return (m1 + elem + m4); } ); }; return hash(at(link(tweet))); }, /** * Parse the input from twitter * @private * @param {Object[]} items * @return {Object[]} Array of Twitter status messages. */ parseTwitter = function(response) { var output = []; if (!response.tweets) { return output; } for(var i = 0; i < response.tweets.length; i++ ) { var status = response.tweets[i]; output.push({ "date": new Date(status.createdAt * 1000), // unix time "config": config, "html": $.tmpl( template.posted, { "tweet": linkify($('<div/>').html(status.text).text()), "complete_url": 'https://twitter.com/' + config.user + "/status/" + status.id } ), "url": 'https://twitter.com/' + config.user }); } callback(output); }; $.ajax({ "url": 'https://twittery.herokuapp.com/' + config.user, "cache": false }).success(parseTwitter); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.vimeo = function( config, callback ) { var template = $.extend({}, { liked: 'liked <a href="${url}" title="${description}">${title}</a>', posted: 'posted <a href="${url}" title="${description}">${title}</a>' }, config.template), parseVimeo = function( input, item_type ) { var output = [], i = 0, j, item, type = item_type || 'liked', date, description; if (input) { j = input.length; for( ; i < j; i++) { item = input[i]; if (type === 'posted') { date = new Date( item.upload_date.replace(' ', 'T') ); } else { date = new Date( item.liked_on.replace(' ', 'T') ); } if (item.description) { description = item.description.replace(/"/g, "'").replace( /<.+?>/gi, ''); } else { description = ''; } output.push({ date: date, config: config, html: $.tmpl( template[type], { url: item.url, description: item.description ? item.description .replace(/"/g, "'") .replace( /<.+?>/gi, '') : '', title: item.title }) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('SELECT * FROM xml WHERE ' + 'url="http://vimeo.com/api/v2/' + config.user + '/likes.xml" OR ' + 'url="http://vimeo.com/api/v2/' + config.user + '/videos.xml"'), dataType: 'jsonp', success: function( response ) { var output = []; // check for likes & parse if ( response.query.results.videos[0] != null && response.query.results.videos[0].video.length > 0 ) { output = output.concat(parseVimeo( response.query.results.videos[0].video )); } // check for uploads & parse if ( response.query.results.videos[1] != null && response.query.results.videos[1].video.length > 0 ) { output = output.concat( parseVimeo(response.query.results.videos[1].video, 'posted') ); } callback(output); } }); // Expose the template. // We use this to check which templates are available return { 'template' : template }; }; })(jQuery);(function($) { $.fn.lifestream.feeds.wikipedia = function( config, callback ) { // default to english if no language was set var language = config.language || 'en', template = $.extend({}, { contribution: 'contributed to <a href="${url}">${title}</a>' }, config.template); $.ajax({ url: "https://" + language + ".wikipedia.org/w/api.php?action=query&ucuser=" + config.user + "&list=usercontribs&ucdir=older&format=json", dataType: "jsonp", success: function( data ) { var output = [], i = 0, j; if(data && data.query.usercontribs) { j = data.query.usercontribs.length; for( ; i<j; i++) { var item = data.query.usercontribs[i]; // Fastest way to get the URL. // Alternatively, we'd have to poll wikipedia for the pageid's link item.url = 'http://' + language + '.wikipedia.org/wiki/' + item.title.replace(' ', '_'); output.push({ date: new Date( item.timestamp ), config: config, html: $.tmpl( template.contribution, item ) }); } } callback(output); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.wordpress = function( config, callback ) { var template = $.extend({}, { posted: 'posted <a href="${link}">${title}</a>' }, config.template); var parseWordpress = function ( input ) { var output = [], list, i = 0, j, item; if ( input.query && input.query.count && input.query.count > 0 && input.query.results.rss.channel.item ) { list = input.query.results.rss.channel.item; j = list.length; for ( ; i < j; i++) { item = list[i]; output.push({ date: new Date( item.pubDate ), config: config, html: $.tmpl( template.posted, item ) }); } } return output; }; var url = ""; if ( config.user ){ // If the config.user property starts with http:// we assume that is the // full url to the user his blog. We append the /feed to the url. url = (config.user.indexOf('http://') === 0 ? config.user + '/feed' : 'http://' + config.user + '.wordpress.com/feed'); $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where ' + 'url="' + url + '"'), dataType: "jsonp", success: function ( data ) { callback(parseWordpress(data)); } }); } // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);(function($) { "use strict"; $.fn.lifestream.feeds.youtube = function( config, callback ) { var template = $.extend({}, { "uploaded": 'uploaded <a href="https://www.youtube.com/watch?v=${id}">${title}</a>' }, config.template); var parseYoutube = function(response) { var output = []; if(!response.videos) {return output;} for (var i=0; i<response.videos.length;i++){ var video = response.videos[i]; output.push({ "date": new Date(video.datePublished), "config": config, "html": $.tmpl(template.uploaded, video) }); } callback(output); }; $.ajax({ "url": "https://youtuby-1.herokuapp.com/" + config.user, "cache": false }).success(parseYoutube); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery); (function($) { $.fn.lifestream.feeds.zotero = function( config, callback ) { var template = $.extend({}, { flagged: 'flagged <a href="${id}">${title}</a> by ${creatorSummary}' }, config.template), parseZotero = function( input ) { var output = [], list, i = 0, j; if(input.query && input.query.count && input.query.count > 0) { list = input.query.results.feed.entry; j = list.length; for( ; i<j; i++) { var item = list[i]; output.push({ date: new Date(item.updated), config: config, url: 'http://zotero.com/users/' + config.user, html: $.tmpl( template.flagged, item ) }); } } return output; }; $.ajax({ url: $.fn.lifestream.createYqlUrl('select * from xml where url=' + '"https://api.zotero.org/users/' + config.user + '/items"'), dataType: 'jsonp', success: function( data ) { callback(parseZotero(data)); } }); // Expose the template. // We use this to check which templates are available return { "template" : template }; }; })(jQuery);