/*! * jQuery Feeds v0.5 * https://camagu.github.com/jquery-feeds * * Copyright (c) 2013, Camilo Aguilar * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * * Includes a modified version of Simple JavaScript Templating * http://ejohn.org/blog/javascript-micro-templating/ * Copyright (c) John Resig (http://ejohn.org) * MIT licensed * * Date: 2013-02-18 */ /*jshint evil: true */ ( function( $ ) { var cache = {}; $.fn.feeds = function( options ) { var engine = { service: '//ajax.googleapis.com/ajax/services/feed/load?v=1.0', settings: { loadingTemplate: '
Loading entries ...
', entryTemplate: '
' + '' + '
' + '
' + '
', feeds: {}, max: -1, xml: false, ssl: 'auto', onComplete: function( entries ) { }, preprocess: function( feed ) { } }, feeds: { }, entries: [ ], feedsLength: 0, feedsLoaded: 0, $element: null, $loader: null, init: function( element, options ) { this.settings = $.extend( this.settings, options ); this.feeds = this.settings.feeds; for ( var i in this.feeds ) { if ( this.feeds.hasOwnProperty( i ) ) { this.feedsLength++; } } var protocol = this.settings.ssl === 'auto' ? document.location.protocol : this.settings.ssl ? 'https:' : 'http:'; if ( $.inArray( protocol, [ 'http:', 'https' ]) === -1 ) { protocol = 'https:'; } this.service = protocol + this.service; this.$element = $( element ); var render = typeof this.settings.loadingTemplate === 'function' ? this.settings.loadingTemplate : this.tmpl( this.settings.loadingTemplate ); this.$loader = $( render.call( this, { } ) ); this.$element.html( this.$loader ); var output = this.settings.xml ? 'json_xml' : 'json'; for ( var j in this.feeds ) { this.fetchFeed( j, this.feeds[ j ], this.settings.max, output ); } }, fetchFeed: function( key, feed, max, output ) { var self = this; var cacheKey = feed + '**' + max + '**' + output; if ( typeof cache[ cacheKey ] !== 'undefined' ) { self.processResponse( cache[ cacheKey ], key, feed ); return; } $.ajax( { url: this.service, dataType: 'jsonp', data: { q: feed, num: max, output: output }, beforeSend: function( ) { this.feed = feed; this.key = key; }, success: function( data ) { cache[ cacheKey ] = data; self.processResponse( data, this.key, this.feed ); } } ); }, processResponse: function( data, key, feed ) { if ( data.responseStatus !== 200 ) { if ( window.console && window.console.log ) { console.log( 'Unable to load feed ' + feed + ': (' + data.responseStatus + ') ' + data.responseDetails ); } } else { var currentFeed = data.responseData.feed; var feedEntries = currentFeed.entries; var type = data.responseData.feed.type; if ( this.settings.xml ) { var $xml = $( data.responseData.xmlString ); if ( type.match( /^rss.*/ ) ) { $xml = $xml.filter( 'rss' ).find( 'channel' ); } else if ( type.match( /^atom.*/ ) ) { $xml = $xml.filter( 'feed' ); } currentFeed.xml = $xml; } for ( var i in feedEntries ) { var entry = $.extend( {}, feedEntries[ i ] ); entry.source = key; entry.publishedDateRaw = entry.publishedDate; entry.feedUrl = currentFeed.feedUrl; entry.feedTitle = currentFeed.title; entry.feedLink = currentFeed.link; entry.feedDescription = currentFeed.description; entry.feedAuthor = currentFeed.author; if ( this.settings.xml ) { if ( type.match( /^rss.*/ ) ) { entry.xml = currentFeed.xml.find( 'item' ).eq( i ); } else if ( type.match( /^atom.*/ ) ) { entry.xml = currentFeed.xml.find( 'entry' ).eq( i ); } else { entry.xml = { }; } } if ( this.settings.preprocess.call( entry, currentFeed ) !== false ) { this.entries.push( entry ); } } } this.feedsLoaded++; this.checkComplete(); }, checkComplete: function( ) { if ( this.feedsLoaded === this.feedsLength ) { this.$loader.remove( ); this.entries.sort( function( a, b) { var aDate = new Date( a.publishedDateRaw ).getTime( ); var bDate = new Date( b.publishedDateRaw ).getTime( ); return bDate - aDate; } ); var render = typeof this.settings.entryTemplate === 'function' ? this.settings.entryTemplate : this.tmpl( this.settings.entryTemplate ); for ( var i in this.entries ) { var entry = this.entries[ i ]; var html = render.call( this, entry ); this.$element.append( html ); } this.settings.onComplete.call( this.$element[ 0 ], this.entries ); } }, // Simple JavaScript Templating (modified) // John Resig - http://ejohn.org/ - MIT Licensed // @see http://ejohn.org/blog/javascript-micro-templating/ tmplCache: {}, tmpl: function tmpl( str, data ) { var fn = !/\W/.test( str ) ? this.tmplCache[ str ] = this.tmplCache[ str ] || this.tmpl( document.getElementById( str ).innerHTML ) : new Function( "obj", "var p=[],print=function(){p.push.apply(p,arguments);};" + "with(obj){p.push('" + str .replace( /[\r\t\n]/g, " " ) .split( ")[^\t]*)'/g, "$1\r" ) .replace( /\t=(.*?)!>/g, "',typeof $1 != 'undefined' ? $1 : '','" ) .split( "\t" ).join( "');" ) .split( "!>" ).join( "p.push('" ) .split( "\r" ).join( "\\'" ) + "');}return p.join('');" ); return data ? fn( data ) : fn; } }; return $( this ).each( function( ) { engine.init( this, options ); }); }; }( jQuery ) );