/*!
* 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 ) );