Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
343 changes: 343 additions & 0 deletions examples/jQuery RSS multiple feeds
Original file line number Diff line number Diff line change
@@ -0,0 +1,343 @@

<script src="http://code.jquery.com/jquery-1.8.3.js"></script>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<script src="../src/jquery.rss.js"></script>



<script>

(function ($) {
"use strict";

var RSS = function (target, url, options, callback) {
this.target = target
this.url = url
this.html = []
this.effectQueue = []
//added
this.loadQueue = 0
this.rssBatch = []

this.options = $.extend({
ssl: false,
limit: null,
key: null,
layoutTemplate: '<ul>{entries}</ul>',
entryTemplate: '<li><a href="{url}">[{author}@{date}] {title}</a><br/>{shortBodyPlain}</li>',
tokens: {},
outputMode: 'json',
effect: 'show',
error: function () {
console.log("jQuery RSS: url doesn't link to RSS-Feed");
},
success: function () {}
}, options || {})

this.callback = callback || this.options.success
}

RSS.htmlTags = ["doctype", "html", "head", "title", "base", "link", "meta", "style", "script", "noscript", "body", "article", "nav", "aside", "section", "header", "footer", "h1-h6", "hgroup", "address", "p", "hr", "pre", "blockquote", "ol", "ul", "li", "dl", "dt", "dd", "figure", "figcaption", "div", "table", "caption", "thead", "tbody", "tfoot", "tr", "th", "td", "col", "colgroup", "form", "fieldset", "legend", "label", "input", "button", "select", "datalist", "optgroup", "option", "textarea", "keygen", "output", "progress", "meter", "details", "summary", "command", "menu", "del", "ins", "img", "iframe", "embed", "object", "param", "video", "audio", "source", "canvas", "track", "map", "area", "a", "em", "strong", "i", "b", "u", "s", "small", "abbr", "q", "cite", "dfn", "sub", "sup", "time", "code", "kbd", "samp", "var", "mark", "bdi", "bdo", "ruby", "rt", "rp", "span", "br", "wbr"]

//added
RSS.prototype.load = function () {
if (typeof this.url === 'string') {
$.getJSON(this.getApiUrl(this.url), $.proxy(this.parseRSS, this));
} else if (Object.prototype.toString.call(this.url) === '[object Array]') {
this.loadQueue = this.url.length;
for (var counter = 0; counter < this.url.length; counter++) {
$.getJSON(this.getApiUrl(this.url[counter]), $.proxy(this.collectRSS, this));
}
}
}
//added
RSS.prototype.collectRSS = function (data) {
try {
this.entries = data.responseData.feed.entries
} catch (e) {
this.entries = []
return this.options.error.call(this)
}
this.rssBatch = this.rssBatch.concat(this.entries);

this.loadQueue--;
if (this.loadQueue == 0) {
this.sortRSSBatchOnDate();
this.parseRSS(this.immitateXMLResponse(this.rssBatch));
}
}
//added
RSS.prototype.immitateXMLResponse = function (rss) {
return {
'responseData': {
'feed': {
'entries': this.rssBatch
}
}
};
}

//added
RSS.prototype.sortRSSBatchOnDate = function () {
this.rssBatch.sort(function (a, b) {
a = new Date(a.publishedDate);
b = new Date(b.publishedDate);
return a < b ? -1 : a > b ? 1 : 0;
});
}

//added
RSS.prototype.getApiUrl = function (url) {
var apiProtocol = "http" + (this.options.ssl ? "s" : ""),
apiHost = apiProtocol + "://ajax.googleapis.com/ajax/services/feed/load",
apiUrl = apiHost + "?v=1.0&output=" + this.options.outputMode + "&callback=?&q=" + encodeURIComponent(url)
if (this.options.limit != null) apiUrl += "&num=" + this.options.limit;
if (this.options.key != null) apiUrl += "&key=" + this.options.key;
return apiUrl;
}

//changed anonymous function to parseRSS
RSS.prototype.parseRSS = function (data) {
console.log(data);
try {
this.entries = data.responseData.feed.entries
} catch (e) {
this.entries = []
return this.options.error.call(this)
}

var html = this.generateHTMLForEntries()

this.target.append(html.layout)

if (html.entries.length !== 0) {
this.appendEntriesAndApplyEffects($("entries", html.layout), html.entries)
}

if (this.effectQueue.length > 0) {
this.executeEffectQueue(this.callback)
} else {
$.isFunction(this.callback) && this.callback.call(this);
}
}

RSS.prototype.appendEntriesAndApplyEffects = function (target, entries) {
var self = this

$.each(entries, function (idx, entry) {
var $html = self.wrapContent(entry)

if (self.options.effect === 'show') {
target.before($html)
} else {
$html.css({
display: 'none'
})
target.before($html)
self.applyEffect($html, self.options.effect)
}
})

target.remove()
}

RSS.prototype.generateHTMLForEntries = function () {
var self = this,
result = {
entries: [],
layout: null
}

$(this.entries).each(function () {
var entry = this

if (self.isRelevant(entry)) {
var evaluatedString = self.evaluateStringForEntry(self.options.entryTemplate, entry)
result.entries.push(evaluatedString)
}
})

if ( !! this.options.entryTemplate) {
// we have an entryTemplate
result.layout = this.wrapContent(this.options.layoutTemplate.replace("{entries}", "<entries></entries>"))
} else {
// no entryTemplate available
result.layout = this.wrapContent("<div><entries></entries></div>")
}

return result
}

RSS.prototype.wrapContent = function (content) {
if ($.trim(content).indexOf('<') !== 0) {
// the content has no html => create a surrounding div
return $("<div>" + content + "</div>")
} else {
// the content has html => don't touch it
return $(content)
}
}

RSS.prototype.applyEffect = function ($element, effect, callback) {
var self = this

switch (effect) {
case 'slide':
$element.slideDown('slow', callback)
break
case 'slideFast':
$element.slideDown(callback)
break
case 'slideSynced':
self.effectQueue.push({
element: $element,
effect: 'slide'
})
break
case 'slideFastSynced':
self.effectQueue.push({
element: $element,
effect: 'slideFast'
})
break
}
}

RSS.prototype.executeEffectQueue = function (callback) {
var self = this

this.effectQueue.reverse()

var executeEffectQueueItem = function () {
var item = self.effectQueue.pop()

if (item) {
self.applyEffect(item.element, item.effect, executeEffectQueueItem)
} else {
callback && callback()
}
}

executeEffectQueueItem()
}

RSS.prototype.evaluateStringForEntry = function (string, entry) {
var result = string,
self = this

$(string.match(/(\{.*?\})/g)).each(function () {
var token = this.toString()
result = result.replace(token, self.getValueForToken(token, entry))
})

return result
}

RSS.prototype.isRelevant = function (entry) {
var tokenMap = this.getTokenMap(entry)

if (this.options.filter) {
if (this.options.filterLimit && (this.options.filterLimit == this.html.length)) {
return false
} else {
return this.options.filter(entry, tokenMap)
}
} else {
return true
}
}

RSS.prototype.getTokenMap = function (entry) {
return $.extend({
url: entry.link,
author: entry.author,
date: entry.publishedDate,
title: entry.title,
body: entry.content,
shortBody: entry.contentSnippet,

bodyPlain: (function (entry) {
var result = entry.content.replace(/<script[\\r\\\s\S]*<\/script>/mgi, '')
.replace(/<\/?[^>]+>/gi, '')

for (var i = 0; i < RSS.htmlTags.length; i++) {
result = result.replace(new RegExp('<' + RSS.htmlTags[i], 'gi'), '')
}

return result
})(entry),

shortBodyPlain: entry.contentSnippet.replace(/<\/?[^>]+>/gi, ''),
index: $.inArray(entry, this.entries),
totalEntries: this.entries.length,

teaserImage: (function (entry) {
try {
return entry.content.match(/(<img.*?>)/gi)[0]
} catch (e) {
return ""
}
})(entry),

teaserImageUrl: (function (entry) {
try {
return entry.content.match(/(<img.*?>)/gi)[0].match(/src="(.*?)"/)[1]
} catch (e) {
return ""
}
})(entry)
}, this.options.tokens)
}

//changed render to load since render is deleted
RSS.prototype.getValueForToken = function (_token, entry) {
var tokenMap = this.getTokenMap(entry),
token = _token.replace(/[\{\}]/g, ''),
result = tokenMap[token]

if (typeof result != 'undefined') return ((typeof result == 'function') ? result(entry, tokenMap) : result)
else throw new Error('Unknown token: ' + _token)
}

$.fn.rss = function (url, options, callback) {
new RSS(this, url, options, callback).load()
return this; //implement chaining
}

})(jQuery)

$('#rss-feeds')
.rss(['http://holistichealthprovider.com/feed/','https://drchrisogilvie.wordpress.com/feed/'], {
limit: 4,
layoutTemplate: '<ul>{entries}</ul>',
entryTemplate: '<li><a href="{url}" target="rss_{index}">{title}</a><br /><p>{shortBodyPlain}</p></li>'
})
.bind('loaded', function () {
console.log('loaded');
var $ul = $(this).find('ul'),
ticker = function () {
setTimeout(

function () {
$ul.find('li:first').animate({
marginTop: '-4em'
}, 500, function () {
$(this).detach().appendTo($ul).removeAttr('style');
});
ticker();
},
8000);
};
ticker();
});
setTimeout(function () {
console.log('triggering RSS load');
$('#rss-feeds').trigger('loaded').find('ul').append('<li>' + $('#initial_note').remove().html() + '</li>');
}, 200);</script>

<div class="widget span4">
<h4>Latest News</h4>
<div id="rss-feeds"></div>
</div>