d4eb563b |
1 | /*! |
2 | * jQuery Feeds v0.5 |
3 | * https://camagu.github.com/jquery-feeds |
4 | * |
5 | * Copyright (c) 2013, Camilo Aguilar |
6 | * Dual licensed under the MIT and GPL licenses: |
7 | * http://www.opensource.org/licenses/mit-license.php |
8 | * http://www.gnu.org/licenses/gpl.html |
9 | * |
10 | * Includes a modified version of Simple JavaScript Templating |
11 | * http://ejohn.org/blog/javascript-micro-templating/ |
12 | * Copyright (c) John Resig (http://ejohn.org) |
13 | * MIT licensed |
14 | * |
15 | * Date: 2013-02-18 |
16 | */ |
17 | |
18 | /*jshint evil: true */\r |
19 | ( function( $ ) {\r |
20 | \r |
21 | var cache = {};\r |
22 | \r |
23 | $.fn.feeds = function( options ) {\r |
24 | \r |
25 | var engine = {\r |
26 | service: '//ajax.googleapis.com/ajax/services/feed/load?v=1.0',\r |
27 | \r |
28 | settings: {\r |
29 | loadingTemplate: '<div class="feeds-loader">Loading entries ...</div>',\r |
30 | entryTemplate: '<div class="feeds-entry feeds-source-<!=source!>">' + \r |
31 | '<a class="feeds-entry-title" target="_blank" href="<!=link!>" title="<!=title!>"><!=title!></a>' +\r |
32 | '<div class="feeds-entry-date"><!=publishedDate!></div>' + \r |
33 | '<div class="feeds-entry-contentSnippet"><!=contentSnippet!></div>' + \r |
34 | '</div>',\r |
35 | feeds: {},\r |
36 | max: -1,\r |
37 | xml: false,\r |
38 | ssl: 'auto',\r |
39 | onComplete: function( entries ) {\r |
40 | \r |
41 | },\r |
42 | preprocess: function( feed ) {\r |
43 | \r |
44 | }\r |
45 | },\r |
46 | \r |
47 | feeds: { },\r |
48 | entries: [ ],\r |
49 | \r |
50 | feedsLength: 0,\r |
51 | feedsLoaded: 0,\r |
52 | \r |
53 | $element: null,\r |
54 | $loader: null,\r |
55 | \r |
56 | init: function( element, options ) {\r |
57 | this.settings = $.extend( this.settings, options );\r |
58 | this.feeds = this.settings.feeds;\r |
59 | \r |
60 | for ( var i in this.feeds ) {\r |
61 | if ( this.feeds.hasOwnProperty( i ) ) {\r |
62 | this.feedsLength++;\r |
63 | }\r |
64 | }\r |
65 | \r |
66 | var protocol = this.settings.ssl === 'auto' ? document.location.protocol : this.settings.ssl ? 'https:' : 'http:';\r |
67 | if ( $.inArray( protocol, [ 'http:', 'https' ]) === -1 ) {\r |
68 | protocol = 'https:';\r |
69 | }\r |
70 | \r |
71 | this.service = protocol + this.service;\r |
72 | \r |
73 | this.$element = $( element );\r |
74 | \r |
75 | var render = typeof this.settings.loadingTemplate === 'function' ? this.settings.loadingTemplate : this.tmpl( this.settings.loadingTemplate );\r |
76 | this.$loader = $( render.call( this, { } ) );\r |
77 | this.$element.html( this.$loader );\r |
78 | \r |
79 | var output = this.settings.xml ? 'json_xml' : 'json';\r |
80 | \r |
81 | for ( var j in this.feeds ) {\r |
82 | this.fetchFeed( j, this.feeds[ j ], this.settings.max, output );\r |
83 | }\r |
84 | },\r |
85 | \r |
86 | fetchFeed: function( key, feed, max, output ) {\r |
87 | var self = this;\r |
88 | \r |
89 | var cacheKey = feed + '**' + max + '**' + output;\r |
90 | if ( typeof cache[ cacheKey ] !== 'undefined' ) {\r |
91 | self.processResponse( cache[ cacheKey ], key, feed );\r |
92 | return;\r |
93 | }\r |
94 | \r |
95 | $.ajax( {\r |
96 | url: this.service,\r |
97 | dataType: 'jsonp',\r |
98 | data: {\r |
99 | q: feed,\r |
100 | num: max,\r |
101 | output: output\r |
102 | },\r |
103 | beforeSend: function( ) {\r |
104 | this.feed = feed;\r |
105 | this.key = key;\r |
106 | },\r |
107 | success: function( data ) {\r |
108 | cache[ cacheKey ] = data;\r |
109 | self.processResponse( data, this.key, this.feed );\r |
110 | }\r |
111 | } );\r |
112 | },\r |
113 | \r |
114 | processResponse: function( data, key, feed ) {\r |
115 | if ( data.responseStatus !== 200 ) {\r |
116 | if ( window.console && window.console.log ) {\r |
117 | console.log( 'Unable to load feed ' + feed + ': (' + data.responseStatus + ') ' + data.responseDetails );\r |
118 | }\r |
119 | } else {\r |
120 | var currentFeed = data.responseData.feed;\r |
121 | var feedEntries = currentFeed.entries;\r |
122 | \r |
123 | var type = data.responseData.feed.type;\r |
124 | \r |
125 | if ( this.settings.xml ) {\r |
126 | var $xml = $( data.responseData.xmlString );\r |
127 | \r |
128 | if ( type.match( /^rss.*/ ) ) {\r |
129 | $xml = $xml.filter( 'rss' ).find( 'channel' );\r |
130 | } else if ( type.match( /^atom.*/ ) ) {\r |
131 | $xml = $xml.filter( 'feed' );\r |
132 | }\r |
133 | \r |
134 | currentFeed.xml = $xml;\r |
135 | }\r |
136 | \r |
137 | for ( var i in feedEntries ) {\r |
138 | var entry = $.extend( {}, feedEntries[ i ] );\r |
139 | entry.source = key;\r |
140 | entry.publishedDateRaw = entry.publishedDate;\r |
141 | \r |
142 | entry.feedUrl = currentFeed.feedUrl;\r |
143 | entry.feedTitle = currentFeed.title;\r |
144 | entry.feedLink = currentFeed.link;\r |
145 | entry.feedDescription = currentFeed.description;\r |
146 | entry.feedAuthor = currentFeed.author;\r |
147 | \r |
148 | if ( this.settings.xml ) {\r |
149 | if ( type.match( /^rss.*/ ) ) {\r |
150 | entry.xml = currentFeed.xml.find( 'item' ).eq( i );\r |
151 | } else if ( type.match( /^atom.*/ ) ) {\r |
152 | entry.xml = currentFeed.xml.find( 'entry' ).eq( i );\r |
153 | } else {\r |
154 | entry.xml = { };\r |
155 | }\r |
156 | }\r |
157 | \r |
158 | if ( this.settings.preprocess.call( entry, currentFeed ) !== false ) {\r |
159 | this.entries.push( entry );\r |
160 | }\r |
161 | }\r |
162 | }\r |
163 | \r |
164 | this.feedsLoaded++;\r |
165 | this.checkComplete();\r |
166 | },\r |
167 | \r |
168 | checkComplete: function( ) {\r |
169 | if ( this.feedsLoaded === this.feedsLength ) {\r |
170 | this.$loader.remove( );\r |
171 | \r |
172 | this.entries.sort( function( a, b) {\r |
173 | var aDate = new Date( a.publishedDateRaw ).getTime( );\r |
174 | var bDate = new Date( b.publishedDateRaw ).getTime( );\r |
175 | \r |
176 | return bDate - aDate;\r |
177 | } );\r |
178 | \r |
179 | var render = typeof this.settings.entryTemplate === 'function' ? this.settings.entryTemplate : this.tmpl( this.settings.entryTemplate );\r |
180 | \r |
181 | for ( var i in this.entries ) {\r |
182 | var entry = this.entries[ i ];\r |
183 | \r |
184 | var html = render.call( this, entry );\r |
185 | \r |
186 | this.$element.append( html );\r |
187 | }\r |
188 | \r |
189 | this.settings.onComplete.call( this.$element[ 0 ], this.entries );\r |
190 | }\r |
191 | },\r |
192 | \r |
193 | \r |
194 | // Simple JavaScript Templating (modified)\r |
195 | // John Resig - http://ejohn.org/ - MIT Licensed\r |
196 | // @see http://ejohn.org/blog/javascript-micro-templating/\r |
197 | tmplCache: {},\r |
198 | tmpl: function tmpl( str, data ) {\r |
199 | \r |
200 | var fn = !/\W/.test( str ) ? this.tmplCache[ str ] = this.tmplCache[ str ] || this.tmpl( document.getElementById( str ).innerHTML ) :\r |
201 | \r |
202 | new Function( "obj",\r |
203 | "var p=[],print=function(){p.push.apply(p,arguments);};" +\r |
204 | \r |
205 | "with(obj){p.push('" +\r |
206 | str\r |
207 | .replace( /[\r\t\n]/g, " " )\r |
208 | .split( "<!" ).join( "\t" )\r |
209 | .replace( /((^|!>)[^\t]*)'/g, "$1\r" )\r |
210 | .replace( /\t=(.*?)!>/g, "',typeof $1 != 'undefined' ? $1 : '','" )\r |
211 | .split( "\t" ).join( "');" )\r |
212 | .split( "!>" ).join( "p.push('" )\r |
213 | .split( "\r" ).join( "\\'" ) +\r |
214 | "');}return p.join('');"\r |
215 | );\r |
216 | \r |
217 | return data ? fn( data ) : fn;\r |
218 | }\r |
219 | };\r |
220 | \r |
221 | return $( this ).each( function( ) {\r |
222 | engine.init( this, options );\r |
223 | });\r |
224 | };\r |
225 | }( jQuery ) ); |