frontend-helpers 0.0.1.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/Gemfile +18 -0
  2. data/Gemfile.lock +108 -0
  3. data/LICENSE.txt +20 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +97 -0
  6. data/Rakefile +53 -0
  7. data/config/services.yml +95 -0
  8. data/config/settings.yml +24 -0
  9. data/frontend-helpers.gemspec +117 -0
  10. data/lib/.DS_Store +0 -0
  11. data/lib/asset-helpers/rails.rb +4 -0
  12. data/lib/frontend-helpers/html5_helper.rb +19 -0
  13. data/lib/frontend-helpers/metatag_helper.rb +58 -0
  14. data/lib/frontend-helpers/services_helper.rb +89 -0
  15. data/lib/frontend-helpers.rb +16 -0
  16. data/lib/generators/frontend/install/install_generator.rb +27 -0
  17. data/lib/tasks/frontend-helpers_tasks.rake +4 -0
  18. data/script/rails +6 -0
  19. data/test/dummy/Rakefile +7 -0
  20. data/test/dummy/app/assets/javascripts/application.js +9 -0
  21. data/test/dummy/app/assets/stylesheets/application.css +7 -0
  22. data/test/dummy/app/controllers/application_controller.rb +3 -0
  23. data/test/dummy/app/helpers/application_helper.rb +2 -0
  24. data/test/dummy/app/mailers/.gitkeep +0 -0
  25. data/test/dummy/app/models/.gitkeep +0 -0
  26. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  27. data/test/dummy/config/application.rb +42 -0
  28. data/test/dummy/config/boot.rb +10 -0
  29. data/test/dummy/config/database.yml +25 -0
  30. data/test/dummy/config/environment.rb +5 -0
  31. data/test/dummy/config/environments/development.rb +27 -0
  32. data/test/dummy/config/environments/production.rb +54 -0
  33. data/test/dummy/config/environments/test.rb +39 -0
  34. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  35. data/test/dummy/config/initializers/inflections.rb +10 -0
  36. data/test/dummy/config/initializers/mime_types.rb +5 -0
  37. data/test/dummy/config/initializers/secret_token.rb +7 -0
  38. data/test/dummy/config/initializers/session_store.rb +8 -0
  39. data/test/dummy/config/initializers/wrap_parameters.rb +12 -0
  40. data/test/dummy/config/locales/en.yml +5 -0
  41. data/test/dummy/config/routes.rb +58 -0
  42. data/test/dummy/config.ru +4 -0
  43. data/test/dummy/log/.gitkeep +0 -0
  44. data/test/dummy/public/404.html +26 -0
  45. data/test/dummy/public/422.html +26 -0
  46. data/test/dummy/public/500.html +26 -0
  47. data/test/dummy/public/favicon.ico +0 -0
  48. data/test/dummy/script/rails +6 -0
  49. data/test/frontend-helpers_test.rb +11 -0
  50. data/test/test_helper.rb +10 -0
  51. data/vendor/assets/javascripts/backbone/backbone.js +1149 -0
  52. data/vendor/assets/javascripts/backbone/index.js +2 -0
  53. data/vendor/assets/javascripts/backbone/underscore.js +807 -0
  54. data/vendor/assets/javascripts/ie/dd_belatedpng.js +13 -0
  55. data/vendor/assets/javascripts/ie/index.js +2 -0
  56. data/vendor/assets/javascripts/ie/reverse_zindex.js +1 -0
  57. data/vendor/assets/javascripts/jquery.async.js +77 -0
  58. data/vendor/assets/javascripts/jquery.cookie.js +89 -0
  59. data/vendor/assets/javascripts/jquery.lifestream.js +1516 -0
  60. data/vendor/assets/javascripts/jquery.validate.js +1166 -0
  61. data/vendor/assets/javascripts/log.js +8 -0
  62. data/vendor/assets/javascripts/modernizr.js +1116 -0
  63. data/vendor/assets/javascripts/shortcut.js +223 -0
  64. data/vendor/assets/javascripts/swfobject.js +4 -0
  65. data/vendor/assets/stylesheets/reset.css.sass +183 -0
  66. data/vendor/assets/stylesheets/variables.css.sass +21 -0
  67. metadata +175 -0
@@ -0,0 +1,1516 @@
1
+ /*!
2
+ * jQuery Lifestream Plug-in
3
+ * @version 0.1.2
4
+ * Show a stream of your online activity
5
+ *
6
+ * Copyright 2011, Christian Vuerings - http://denbuzze.com
7
+ */
8
+ /*globals jQuery, $ */
9
+ ;(function( $ ){
10
+
11
+ /**
12
+ * Create a valid YQL URL by passing in a query
13
+ * @param {String} query The query you want to convert into a valid yql url
14
+ * @return {String} A valid YQL URL
15
+ */
16
+ var createYqlUrl = function( query ) {
17
+ return ( "http://query.yahooapis.com/v1/public/yql?q=__QUERY__&env=" +
18
+ "store://datatables.org/alltableswithkeys&format=json")
19
+ .replace( "__QUERY__" , encodeURIComponent( query ) );
20
+ };
21
+
22
+ /**
23
+ * Initialize the lifestream plug-in
24
+ * @param {Object} config Configuration object
25
+ */
26
+ $.fn.lifestream = function( config ) {
27
+
28
+ // Make the plug-in chainable
29
+ return this.each(function() {
30
+
31
+ // The element where the lifestream is linked to
32
+ var outputElement = $(this),
33
+
34
+ // Extend the default settings with the values passed
35
+ settings = jQuery.extend({
36
+ // The name of the main lifestream class
37
+ // We use this for the main ul class e.g. lifestream
38
+ // and for the specific feeds e.g. lifestream-twitter
39
+ classname: "lifestream",
40
+ // Callback function which will be triggered when a feed is loaded
41
+ feedloaded: null,
42
+ // The amount of feed items you want to show
43
+ limit: 10,
44
+ // An array of feed items which you want to use
45
+ list: []
46
+ }, config),
47
+
48
+ // The data object contains all the feed items
49
+ data = {
50
+ count: settings.list.length,
51
+ items: []
52
+ },
53
+
54
+ // We use the item settings to pass the global settings variable to
55
+ // every feed
56
+ itemsettings = jQuery.extend( true, {}, settings ),
57
+
58
+ /**
59
+ * This method will be called every time a feed is loaded. This means
60
+ * that several DOM changes will occur. We did this because otherwise it
61
+ * takes to look before anything shows up.
62
+ * We allow 1 request per feed - so 1 DOM change per feed
63
+ * @private
64
+ * @param {Array} inputdata an array containing all the feeditems for a
65
+ * specific feed.
66
+ */
67
+ finished = function( inputdata ) {
68
+
69
+ // Merge the feed items we have from other feeds, with the feeditems
70
+ // from the new feed
71
+ $.merge( data.items, inputdata );
72
+
73
+ // Sort the feeditems by date - we want the most recent one first
74
+ data.items.sort( function( a, b ) {
75
+ return ( b.date - a.date );
76
+ });
77
+
78
+ var items = data.items,
79
+
80
+ // We need to check whether the amount of current feed items is
81
+ // smaller than the main limit. This parameter will be used in the
82
+ // for loop
83
+ length = ( items.length < settings.limit ) ?
84
+ items.length :
85
+ settings.limit,
86
+ i = 0, item,
87
+
88
+ // We create an unordered list which will create all the feed
89
+ // items
90
+ ul = $('<ul class="' + settings.classname + '"/>');
91
+
92
+ // Run over all the feed items + add them as list items to the
93
+ // unordered list
94
+ for ( ; i < length; i++ ) {
95
+ item = items[i];
96
+ if ( item.html ) {
97
+ $('<li class="'+ settings.classname + '-'
98
+ + item.config.service + '">').append( item.html )
99
+ .appendTo( ul );
100
+ }
101
+ }
102
+
103
+ // Change the innerHTML with a list of all the feeditems in
104
+ // chronological order
105
+ outputElement.html( ul );
106
+
107
+ // Trigger the feedloaded callback, if it is a function
108
+ if ( $.isFunction( settings.feedloaded ) ) {
109
+ settings.feedloaded();
110
+ }
111
+
112
+ },
113
+
114
+ /**
115
+ * Fire up all the feeds and pass them the right arugments.
116
+ * @private
117
+ */
118
+ load = function() {
119
+
120
+ var i = 0, j = settings.list.length;
121
+
122
+ // We don't pass the list array to each feed because this will create
123
+ // a recursive JavaScript object
124
+ delete itemsettings.list;
125
+
126
+ // Run over all the items in the list
127
+ for( ; i < j; i++ ) {
128
+
129
+ var config = settings.list[i];
130
+
131
+ // Check whether the feed exists, if the feed is a function and if a
132
+ // user has been filled in
133
+ if ( $.fn.lifestream.feeds[config.service] &&
134
+ $.isFunction( $.fn.lifestream.feeds[config.service] )
135
+ && config.user) {
136
+
137
+ // You'll be able to get the global settings by using
138
+ // config._settings in your feed
139
+ config._settings = itemsettings;
140
+
141
+ // Call the feed with a config object and finished callback
142
+ $.fn.lifestream.feeds[config.service]( config, finished );
143
+ }
144
+
145
+ }
146
+
147
+ };
148
+
149
+ // Load the jQuery templates plug-in if it wasn't included in the page.
150
+ // At then end we call the load method.
151
+ if( !jQuery.tmpl ) {
152
+ jQuery.getScript(
153
+ "https://raw.github.com/jquery/jquery-tmpl/master/"
154
+ + "jquery.tmpl.min.js",
155
+ load);
156
+ } else {
157
+ load();
158
+ }
159
+
160
+ });
161
+
162
+ };
163
+
164
+ /**
165
+ * A big container which contains all available feeds
166
+ */
167
+ $.fn.lifestream.feeds = $.fn.lifestream.feeds || {};
168
+
169
+ $.fn.lifestream.feeds.blogger = function( config, callback ) {
170
+
171
+ var template = $.extend({},
172
+ {
173
+ posted: 'posted <a href="${origLink}">${title}</a>'
174
+ },
175
+ config.template),
176
+
177
+ parseBlogger = function ( input ) {
178
+ var output = [], list, i = 0, j, item;
179
+
180
+ if ( input.query && input.query.count && input.query.count > 0
181
+ && input.query.results.feed.entry ) {
182
+ list = input.query.results.feed.entry;
183
+ j = list.length;
184
+ for ( ; i < j; i++) {
185
+ item = list[i];
186
+
187
+ output.push({
188
+ date: new Date( item.published ),
189
+ config: config,
190
+ html: $.tmpl( template.posted, item )
191
+ });
192
+ }
193
+ }
194
+
195
+ return output;
196
+ };
197
+
198
+ $.ajax({
199
+ url: createYqlUrl('select * from xml where url="http://'
200
+ + config.user + '.blogspot.com/feeds/posts/default"'),
201
+ dataType: "jsonp",
202
+ success: function ( data ) {
203
+ callback(parseBlogger(data));
204
+ }
205
+ });
206
+
207
+ // Expose the template.
208
+ // We use this to check which templates are available
209
+ return {
210
+ "template" : template
211
+ };
212
+
213
+ };
214
+
215
+ $.fn.lifestream.feeds.dailymotion = function( config, callback ) {
216
+
217
+ var template = $.extend({},
218
+ {
219
+ uploaded: 'uploaded a video <a href="${link}">${title[0]}</a>'
220
+ },
221
+ config.template),
222
+
223
+ parseDailymotion = function( input ) {
224
+
225
+ var output = [], list, i = 0, j, item;
226
+
227
+ if ( input.query && input.query.count && input.query.count > 0
228
+ && input.query.results.rss.channel.item ) {
229
+ list = input.query.results.rss.channel.item;
230
+ j = list.length;
231
+ for ( ; i < j; i++) {
232
+ item = list[i];
233
+ output.push({
234
+ date: new Date ( item.pubDate ),
235
+ config: config,
236
+ html: $.tmpl( template.uploaded, item )
237
+ });
238
+ }
239
+ }
240
+
241
+ return output;
242
+
243
+ };
244
+
245
+ $.ajax({
246
+ url: createYqlUrl('select * from xml where '
247
+ + 'url="http://www.dailymotion.com/rss/user/' + config.user + '"'),
248
+ dataType: "jsonp",
249
+ success: function( data ) {
250
+ callback(parseDailymotion(data));
251
+ }
252
+ });
253
+
254
+ // Expose the template.
255
+ // We use this to check which templates are available
256
+ return {
257
+ "template" : template
258
+ };
259
+
260
+ };
261
+
262
+ $.fn.lifestream.feeds.delicious = function( config, callback ) {
263
+
264
+ var template = $.extend({},
265
+ {
266
+ bookmarked: 'bookmarked <a href="${u}">${d}</a>'
267
+ },
268
+ config.template);
269
+
270
+ $.ajax({
271
+ url: "http://feeds.delicious.com/v2/json/" + config.user,
272
+ dataType: "jsonp",
273
+ success: function( data ) {
274
+ var output = [], i = 0, j;
275
+ if (data && data.length && data.length > 0) {
276
+ j = data.length;
277
+ for( ; i < j; i++) {
278
+ var item = data[i];
279
+ output.push({
280
+ date: new Date(item.dt),
281
+ config: config,
282
+ html: $.tmpl( template.bookmarked, item )
283
+ });
284
+ }
285
+ }
286
+ callback(output);
287
+ }
288
+ });
289
+
290
+ // Expose the template.
291
+ // We use this to check which templates are available
292
+ return {
293
+ "template" : template
294
+ };
295
+
296
+ };
297
+
298
+ $.fn.lifestream.feeds.deviantart = function( config, callback ) {
299
+
300
+ var template = $.extend({},
301
+ {
302
+ posted: 'posted <a href="${link}">${title}</a>'
303
+ },
304
+ config.template);
305
+
306
+ $.ajax({
307
+ url: createYqlUrl(
308
+ 'select title,link,pubDate from rss where '
309
+ + 'url="http://backend.deviantart.com/rss.xml?q=gallery%3A'
310
+ + encodeURIComponent(config.user)
311
+ + '&type=deviation'
312
+ + '" | unique(field="title")'
313
+ ),
314
+ dataType: 'jsonp',
315
+ success: function( resp ) {
316
+ var output = [],
317
+ items, item,
318
+ i = 0, j;
319
+ if (resp.query && resp.query.count > 0) {
320
+ items = resp.query.results.item;
321
+ j = items.length;
322
+ for ( ; i < j; i++) {
323
+ item = items[i];
324
+ output.push({
325
+ date: new Date(item.pubDate),
326
+ config: config,
327
+ html: $.tmpl( template.posted, item )
328
+ });
329
+ }
330
+ }
331
+ callback(output);
332
+ }
333
+ });
334
+
335
+ // Expose the template.
336
+ // We use this to check which templates are available
337
+ return {
338
+ "template" : template
339
+ };
340
+
341
+ };
342
+
343
+ $.fn.lifestream.feeds.dribbble = function( config, callback ) {
344
+
345
+ var template = $.extend({},
346
+ {
347
+ posted: 'posted a shot <a href="${url}">${title}</a>'
348
+ },
349
+ config.template);
350
+
351
+ $.ajax({
352
+ url: "http://api.dribbble.com/players/" + config.user + "/shots",
353
+ dataType: "jsonp",
354
+ success: function( data ) {
355
+ var output = [], i = 0, j;
356
+
357
+ if(data && data.total) {
358
+ j = data.shots.length;
359
+ for( ; i<j; i++) {
360
+ var item = data.shots[i];
361
+ output.push({
362
+ date: new Date(item.created_at),
363
+ config: config,
364
+ html: $.tmpl( template.posted, item )
365
+ });
366
+ }
367
+ }
368
+
369
+ callback(output);
370
+ }
371
+ });
372
+
373
+ // Expose the template.
374
+ // We use this to check which templates are available
375
+ return {
376
+ "template" : template
377
+ };
378
+
379
+ };
380
+
381
+ $.fn.lifestream.feeds.flickr = function( config, callback ) {
382
+
383
+ var template = $.extend({},
384
+ {
385
+ posted: 'posted a photo <a href="${link}">${title}</a>'
386
+ },
387
+ config.template);
388
+
389
+ $.ajax({
390
+ url: "http://api.flickr.com/services/feeds/photos_public.gne?id="
391
+ + config.user + "&lang=en-us&format=json",
392
+ dataType: "jsonp",
393
+ jsonp: 'jsoncallback',
394
+ success: function( data ) {
395
+ var output = [], i = 0, j;
396
+
397
+ if(data && data.items && data.items.length > 0) {
398
+ j = data.items.length;
399
+ for( ; i<j; i++) {
400
+ var item = data.items[i];
401
+ output.push({
402
+ date: new Date( item.published ),
403
+ config: config,
404
+ html: $.tmpl( template.posted, item )
405
+ });
406
+ }
407
+ }
408
+
409
+ callback(output);
410
+ }
411
+ });
412
+
413
+ // Expose the template.
414
+ // We use this to check which templates are available
415
+ return {
416
+ "template" : template
417
+ };
418
+
419
+ };
420
+
421
+ $.fn.lifestream.feeds.foomark = function( config, callback ) {
422
+
423
+ var template = $.extend({},
424
+
425
+ {
426
+ bookmarked: 'bookmarked <a href="${url}">${url}</a>'
427
+
428
+ },
429
+ config.template);
430
+
431
+ $.ajax({
432
+ url: "http://api.foomark.com/urls/list/",
433
+ data: {
434
+ format: "jsonp",
435
+ username: config.user
436
+ },
437
+ dataType: "jsonp",
438
+ success: function( data ) {
439
+
440
+ var output = [], i=0, j;
441
+ if( data && data.length && data.length > 0 ) {
442
+ j = data.length;
443
+ for( ; i < j; i++ ) {
444
+ var item = data[i];
445
+ output.push({
446
+ date: new Date( item.created_at.replace(' ', 'T') ),
447
+ config: config,
448
+ html: $.tmpl( template.bookmarked, item )
449
+ });
450
+ }
451
+ }
452
+ callback( output );
453
+ }
454
+ });
455
+
456
+ // Expose the template.
457
+ // We use this to check which templates are available
458
+ return {
459
+ "template" : template
460
+ };
461
+
462
+ };
463
+
464
+ $.fn.lifestream.feeds.formspring = function( config, callback ) {
465
+
466
+ var template = $.extend({},
467
+ {
468
+ answered: 'answered a question <a href="${link}">${title}</a>'
469
+ },
470
+ config.template);
471
+
472
+ var parseFormspring = function ( input ) {
473
+ var output = [], list, i = 0, j, item;
474
+
475
+ if ( input.query && input.query.count && input.query.count > 0
476
+ && input.query.results.rss.channel.item ) {
477
+ list = input.query.results.rss.channel.item;
478
+ j = list.length;
479
+ for ( ; i < j; i++) {
480
+ item = list[i];
481
+
482
+ output.push({
483
+ date: new Date( item.pubDate ),
484
+ config: config,
485
+ html: $.tmpl( template.answered, item )
486
+ });
487
+ }
488
+ }
489
+
490
+ return output;
491
+ };
492
+
493
+ $.ajax({
494
+ url: createYqlUrl('select * from xml where '
495
+ + 'url="http://www.formspring.me/profile/' + config.user + '.rss"'),
496
+ dataType: "jsonp",
497
+ success: function ( data ) {
498
+ callback(parseFormspring(data));
499
+ }
500
+ });
501
+
502
+ // Expose the template.
503
+ // We use this to check which templates are available
504
+ return {
505
+ "template" : template
506
+ };
507
+
508
+ };
509
+
510
+ $.fn.lifestream.feeds.forrst = function( config, callback ) {
511
+
512
+ var template = $.extend({},
513
+ {
514
+ posted: 'posted a ${post_type} '
515
+ + '<a href="${post_url}">${title}</a>'
516
+ },
517
+ config.template);
518
+
519
+ $.ajax({
520
+ url: "http://forrst.com/api/v2/users/posts?username=" + config.user,
521
+ dataType: "jsonp",
522
+ success: function( data ) {
523
+ var output = [], i=0, j;
524
+ if( data && data.resp.length && data.resp.length > 0 ) {
525
+ j = data.resp.length;
526
+ for( ; i < j; i++ ) {
527
+ var item = data.resp[i];
528
+ output.push({
529
+ date: new Date( item.created_at.replace(' ', 'T') ),
530
+ config: config,
531
+ html: $.tmpl( template.posted, item )
532
+ });
533
+ }
534
+ }
535
+ callback( output );
536
+ }
537
+ });
538
+
539
+ // Expose the template.
540
+ // We use this to check which templates are available
541
+ return {
542
+ "template" : template
543
+ };
544
+
545
+ };
546
+
547
+ $.fn.lifestream.feeds.foursquare = function( config, callback ) {
548
+
549
+ var template = $.extend({},
550
+ {
551
+ checkedin: 'checked in @ <a href="${link}">${title}</a>'
552
+ },
553
+ config.template),
554
+
555
+ parseFoursquare = function( input ) {
556
+ var output = [], i = 0, j;
557
+
558
+ if(input.query && input.query.count && input.query.count >0) {
559
+ j = input.query.count;
560
+ for( ; i<j; i++) {
561
+ var item = input.query.results.item[i];
562
+ output.push({
563
+ date: new Date(item.pubDate),
564
+ config: config,
565
+ html: $.tmpl( template.checkedin, item )
566
+ });
567
+ }
568
+ }
569
+
570
+ return output;
571
+ };
572
+
573
+ $.ajax({
574
+ url: createYqlUrl('select * from rss where url='
575
+ + '"https://feeds.foursquare.com/history/'
576
+ + config.user + '.rss"'),
577
+ dataType: 'jsonp',
578
+ success: function( data ) {
579
+ callback(parseFoursquare(data));
580
+ }
581
+ });
582
+
583
+ // Expose the template.
584
+ // We use this to check which templates are available
585
+ return {
586
+ "template" : template
587
+ };
588
+
589
+ };
590
+
591
+ $.fn.lifestream.feeds.github = function( config, callback ) {
592
+
593
+ var template = $.extend({},
594
+ {
595
+ pushed: '<a href="${status.url}" title="{{if title}}${title} '
596
+ +'by ${author} {{/if}}">pushed</a> to '
597
+ +'<a href="http://github.com/${repo}">${repo}</a>',
598
+ gist: '<a href="${status.payload.url}" title="'
599
+ +'${status.payload.desc || ""}">${status.payload.name}</a>',
600
+ commented: '<a href="${status.url}">commented</a> on '
601
+ +'<a href="http://github.com/${repo}">${repo}</a>',
602
+ pullrequest: '<a href="${status.url}">${status.payload.action}</a> '
603
+ +'pull request on <a href="http://github.com/${repo}">${repo}</a>',
604
+ created: 'created ${status.payload.ref_type || status.payload.object}'
605
+ +' <a href="${status.url}">${status.payload.ref || '
606
+ +'status.payload.object_name}</a> for '
607
+ +'<a href="http://github.com/${repo}">${repo}</a>',
608
+ createdglobal: 'created ${status.payload.object} '
609
+ +'<a href="${status.url}">${title}</a>',
610
+ deleted: 'deleted ${status.payload.ref_type} '
611
+ +'<a href="http://github.com/${status.repository.owner}/'
612
+ +'${status.repository.name}">status.payload.ref</a>'
613
+ },
614
+ config.template);
615
+
616
+ var returnRepo = function( status ) {
617
+ return status.payload.repo
618
+ || ( status.repository ? status.repository.owner + "/"
619
+ + status.repository.name : null )
620
+ || status.url.split("/")[3] + "/" + status.url.split("/")[4];
621
+ },
622
+ parseGithubStatus = function( status ) {
623
+ var repo, title;
624
+ if(status.type === "PushEvent") {
625
+ title = status.payload && status.payload.shas
626
+ && status.payload.shas.json
627
+ && status.payload.shas.json[2];
628
+ repo = returnRepo(status);
629
+
630
+ return $.tmpl( template.pushed, {
631
+ status: status,
632
+ title: title,
633
+ author: title ? status.payload.shas.json[3] : "",
634
+ repo: returnRepo(status)
635
+ } );
636
+ }
637
+ else if (status.type === "GistEvent") {
638
+ return $.tmpl( template.gist, status );
639
+ }
640
+ else if (status.type === "CommitCommentEvent" ||
641
+ status.type === "IssueCommentEvent") {
642
+ repo = returnRepo(status);
643
+ return $.tmpl( template.commented, {
644
+ repo: repo,
645
+ status: status
646
+ } );
647
+ }
648
+ else if (status.type === "PullRequestEvent") {
649
+ repo = returnRepo(status);
650
+ return $.tmpl( template.pullrequest, {
651
+ repo: repo,
652
+ status: status
653
+ } );
654
+ }
655
+ // Github has several syntaxes for create tag events
656
+ else if (status.type === "CreateEvent" &&
657
+ (status.payload.ref_type === "tag" ||
658
+ status.payload.ref_type === "branch" ||
659
+ status.payload.object === "tag")) {
660
+ repo = returnRepo(status);
661
+ return $.tmpl( template.created, {
662
+ repo: repo,
663
+ status: status
664
+ } );
665
+ }
666
+ else if (status.type === "CreateEvent") {
667
+ title = (status.payload.object_name === "null")
668
+ ? status.payload.name
669
+ : status.payload.object_name;
670
+ return $.tmpl( template.createdglobal, {
671
+ title: title,
672
+ status: status
673
+ } );
674
+ }
675
+ else if (status.type === "DeleteEvent") {
676
+ return $.tmpl( template.deleted, status );
677
+ }
678
+
679
+ },
680
+ parseGithub = function( input ) {
681
+ var output = [], i = 0, j;
682
+
683
+ if(input.query && input.query.count && input.query.count >0) {
684
+ j = input.query.count;
685
+ for( ; i<j; i++) {
686
+ var status = input.query.results.json[i].json;
687
+ output.push({
688
+ date: new Date(status.created_at),
689
+ config: config,
690
+ html: parseGithubStatus(status)
691
+ });
692
+ }
693
+ }
694
+
695
+ return output;
696
+
697
+ };
698
+
699
+ $.ajax({
700
+ url: createYqlUrl('select json.repository.owner,json.repository.name'
701
+ + ',json.payload,json.type'
702
+ + ',json.url, json.created_at from json where url="http://github.com/'
703
+ + config.user + '.json"'),
704
+ dataType: 'jsonp',
705
+ success: function( data ) {
706
+ callback(parseGithub(data));
707
+ }
708
+ });
709
+
710
+ // Expose the template.
711
+ // We use this to check which templates are available
712
+ return {
713
+ "template" : template
714
+ };
715
+
716
+ };
717
+
718
+ $.fn.lifestream.feeds.googlereader = function( config, callback ) {
719
+
720
+ var template = $.extend({},
721
+ {
722
+ starred: 'starred post <a href="${link.href}">${title.content}</a>'
723
+ },
724
+ config.template),
725
+
726
+ /**
727
+ * Parse the input from google reader
728
+ */
729
+ parseReader = function( input ) {
730
+ var output = [], list, i = 0, j;
731
+
732
+ if(input.query && input.query.count && input.query.count >0) {
733
+ list = input.query.results.feed.entry;
734
+ j = list.length;
735
+ for( ; i<j; i++) {
736
+ var item = list[i];
737
+ output.push({
738
+ date: new Date(parseInt(item["crawl-timestamp-msec"], 10)),
739
+ config: config,
740
+ html: $.tmpl( template.starred, item )
741
+ });
742
+ }
743
+ }
744
+ return output;
745
+ };
746
+
747
+ $.ajax({
748
+ url: createYqlUrl('select * from xml where url="'
749
+ + 'www.google.com/reader/public/atom/user%2F'
750
+ + config.user + '%2Fstate%2Fcom.google%2Fstarred"'),
751
+ dataType: 'jsonp',
752
+ success: function( data ) {
753
+ callback(parseReader(data));
754
+ }
755
+ });
756
+
757
+ // Expose the template.
758
+ // We use this to check which templates are available
759
+ return {
760
+ "template" : template
761
+ };
762
+
763
+ };
764
+
765
+ $.fn.lifestream.feeds.iusethis = function( config, callback ) {
766
+
767
+ var template = $.extend({},
768
+ {
769
+ global: '${action} <a href="${link}">${what}</a> on (${os})'
770
+ },
771
+ config.template);
772
+
773
+ var parseIusethis = function( input ) {
774
+ var output = [], list, i, j, k, l, m = 0, n, item, title, actions,
775
+ action, what, os, oss = ["iPhone", "OS X", "Windows"];
776
+
777
+ if (input.query && input.query.count && input.query.count > 0
778
+ && input.query.results.rss) {
779
+ n = input.query.results.rss.length;
780
+ actions = ['started using', 'stopped using', 'stopped loving',
781
+ 'Downloaded', 'commented on', 'updated entry for',
782
+ 'started loving', 'registered'];
783
+ l = actions.length;
784
+
785
+ for( ; m < n; m++) {
786
+
787
+ os = oss[m];
788
+ list = input.query.results.rss[m].channel.item;
789
+ i = 0;
790
+ j = list.length;
791
+
792
+ for ( ; i < j; i++) {
793
+ item = list[i];
794
+ title = item.title.replace(config.user + ' ', '');
795
+ k = 0;
796
+
797
+ for( ; k < l; k++) {
798
+ if(title.indexOf(actions[k]) > -1) {
799
+ action = actions[k];
800
+ break;
801
+ }
802
+ }
803
+
804
+ what = title.split(action);
805
+
806
+ output.push({
807
+ date: new Date(item.pubDate),
808
+ config: config,
809
+ html: $.tmpl( template.global, {
810
+ action: action.toLowerCase(),
811
+ link: item.link,
812
+ what: what[1],
813
+ os: os
814
+ } )
815
+ });
816
+ }
817
+ }
818
+ }
819
+
820
+ return output;
821
+ };
822
+
823
+ $.ajax({
824
+ url: createYqlUrl('select * from xml where '
825
+ + 'url="http://iphone.iusethis.com/user/feed.rss/' + config.user
826
+ + '" or '
827
+ + 'url="http://osx.iusethis.com/user/feed.rss/' + config.user
828
+ + '" or '
829
+ + 'url="http://win.iusethis.com/user/feed.rss/' + config.user + '"'),
830
+ dataType: "jsonp",
831
+ success: function( data ) {
832
+ callback(parseIusethis(data));
833
+ }
834
+ });
835
+
836
+ // Expose the template.
837
+ // We use this to check which templates are available
838
+ return {
839
+ "template" : template
840
+ };
841
+
842
+ };
843
+
844
+ $.fn.lifestream.feeds.lastfm = function( config, callback ) {
845
+
846
+ var template = $.extend({},
847
+ {
848
+ loved: 'loved <a href="${url}">${name}</a> by '
849
+ + '<a href="${artist.url}">${artist.name}</a>'
850
+ },
851
+ config.template),
852
+
853
+ parseLastfm = function( input ) {
854
+ var output = [], list, i = 0, j;
855
+
856
+ if(input.query && input.query.count && input.query.count > 0
857
+ && input.query.results.lovedtracks
858
+ && input.query.results.lovedtracks.track) {
859
+ list = input.query.results.lovedtracks.track;
860
+ j = list.length;
861
+ for( ; i<j; i++) {
862
+ var item = list[i];
863
+ output.push({
864
+ date: new Date(parseInt((item.date.uts * 1000), 10)),
865
+ config: config,
866
+ html: $.tmpl( template.loved, item )
867
+ });
868
+ }
869
+ }
870
+ return output;
871
+ };
872
+
873
+ $.ajax({
874
+ url: createYqlUrl('select * from xml where url='
875
+ + '"http://ws.audioscrobbler.com/2.0/user/'
876
+ + config.user + '/lovedtracks.xml"'),
877
+ dataType: 'jsonp',
878
+ success: function( data ) {
879
+ callback(parseLastfm(data));
880
+ }
881
+ });
882
+
883
+ // Expose the template.
884
+ // We use this to check which templates are available
885
+ return {
886
+ "template" : template
887
+ };
888
+
889
+ };
890
+
891
+ $.fn.lifestream.feeds.picplz = function( config, callback ) {
892
+
893
+ var template = $.extend({},
894
+ {
895
+ uploaded: 'uploaded <a href="${url}">${title}</a>'
896
+ },
897
+ config.template);
898
+
899
+ $.ajax({
900
+ url: "http://picplz.com/api/v2/user.json?username="
901
+ + config.user + "&include_pics=1",
902
+ dataType: "jsonp",
903
+ success: function( data ) {
904
+ var output = [], i=0, j, images;
905
+ images = data.value.users[0].pics;
906
+ if( images && images.length && images.length > 0 ) {
907
+ j = images.length;
908
+ for( ; i < j; i++ ) {
909
+ var item = images[i];
910
+ output.push({
911
+ date: new Date( ( item.date ) * 1000 ),
912
+ config: config,
913
+ html: $.tmpl( template.uploaded, {
914
+ url: item.pic_files["640r"].img_url,
915
+ title: item.caption || item.id
916
+ } )
917
+ });
918
+ }
919
+ }
920
+ callback( output );
921
+ }
922
+ });
923
+
924
+ // Expose the template.
925
+ // We use this to check which templates are available
926
+ return {
927
+ "template" : template
928
+ };
929
+
930
+ };
931
+
932
+ $.fn.lifestream.feeds.pinboard = function( config, callback ) {
933
+
934
+ var template = $.extend({},
935
+ {
936
+ bookmarked: 'bookmarked <a href="${link}">${title}</a>'
937
+ },
938
+ config.template);
939
+
940
+ var parsePinboard = function( input ) {
941
+ var output = [], list, i = 0, j, item;
942
+
943
+ if (input.query && input.query.count && input.query.count > 0) {
944
+ list = input.query.results.RDF.item;
945
+ j = list.length;
946
+ for ( ; i < j; i++) {
947
+ item = list[i];
948
+
949
+ output.push({
950
+ date: new Date(item.date),
951
+ config: config,
952
+ html: $.tmpl( template.bookmarked, item )
953
+ });
954
+
955
+ }
956
+ }
957
+
958
+ return output;
959
+ };
960
+
961
+ $.ajax({
962
+ url: createYqlUrl('select * from xml where '
963
+ + 'url="http://feeds.pinboard.in/rss/u:' + config.user + '"'),
964
+ dataType: "jsonp",
965
+ success: function( data ) {
966
+ callback(parsePinboard(data));
967
+ }
968
+ });
969
+
970
+ // Expose the template.
971
+ // We use this to check which templates are available
972
+ return {
973
+ "template" : template
974
+ };
975
+
976
+ };
977
+
978
+ $.fn.lifestream.feeds.posterous = function( config, callback ) {
979
+
980
+ var template = $.extend({},
981
+ {
982
+ posted: 'posted <a href="${link}">${title}</a>'
983
+ },
984
+ config.template);
985
+
986
+ var parsePosterous = function ( input ) {
987
+ var output = [], list, i = 0, j, item;
988
+
989
+ if ( input.query && input.query.count && input.query.count > 0
990
+ && input.query.results.rss.channel.item ) {
991
+ list = input.query.results.rss.channel.item;
992
+ j = list.length;
993
+ for ( ; i < j; i++) {
994
+ item = list[i];
995
+
996
+ output.push({
997
+ date: new Date( item.pubDate ),
998
+ config: config,
999
+ html: $.tmpl( template.posted, item )
1000
+ });
1001
+ }
1002
+ }
1003
+
1004
+ return output;
1005
+ };
1006
+
1007
+ $.ajax({
1008
+ url: createYqlUrl('select * from xml where '
1009
+ + 'url="http://' + config.user + '.posterous.com/rss.xml"'),
1010
+ dataType: "jsonp",
1011
+ success: function ( data ) {
1012
+ callback(parsePosterous(data));
1013
+ }
1014
+ });
1015
+
1016
+ // Expose the template.
1017
+ // We use this to check which templates are available
1018
+ return {
1019
+ "template" : template
1020
+ };
1021
+
1022
+ };
1023
+
1024
+ $.fn.lifestream.feeds.reddit = function( config, callback ) {
1025
+
1026
+ var template = $.extend({},
1027
+ {
1028
+ commented: '<a href="http://www.reddit.com/r/${item.data.subreddit}'
1029
+ + '/comments/${item.data.link_id.substring(3)}/u/'
1030
+ + '${item.data.name.substring(3)}?context=3">commented '
1031
+ + '(${score})</a> in <a href="http://www.reddit.com/r/'
1032
+ + '${item.data.subreddit}">${item.data.subreddit}</a>',
1033
+ created: '<a href="http://www.reddit.com${item.data.permalink}">'
1034
+ + 'created new thread (${score})</a> in '
1035
+ + '<a href="http://www.reddit.com/r/${item.data.subreddit}">'
1036
+ + '${item.data.subreddit}</a>'
1037
+ },
1038
+ config.template);
1039
+
1040
+ /**
1041
+ * Parsed one item from the Reddit API.
1042
+ * item.kind == t1 is a reply, t2 is a new thread
1043
+ */
1044
+ var parseRedditItem = function( item ) {
1045
+
1046
+ var score = item.data.ups - item.data.downs,
1047
+ pass = {
1048
+ item: item,
1049
+ score: (score > 0) ? "+" + score : score
1050
+ };
1051
+
1052
+ // t1 = reply, t3 = new thread
1053
+ if (item.kind === "t1") {
1054
+ return $.tmpl( template.commented, pass );
1055
+ }
1056
+ else if (item.kind === "t3") {
1057
+ return $.tmpl( template.created, pass );
1058
+ }
1059
+
1060
+ },
1061
+ /**
1062
+ * Reddit date's are simple epochs.
1063
+ * seconds*1000 = milliseconds
1064
+ */
1065
+ convertDate = function( date ) {
1066
+ return new Date(date * 1000);
1067
+ };
1068
+
1069
+ $.ajax({
1070
+ url: "http://www.reddit.com/user/" + config.user + ".json",
1071
+ dataType: "jsonp",
1072
+ jsonp:"jsonp",
1073
+ success: function( data ) {
1074
+ var output = [], i = 0, j;
1075
+
1076
+ if(data && data.data && data.data.children
1077
+ && data.data.children.length > 0) {
1078
+ j = data.data.children.length;
1079
+ for( ; i<j; i++) {
1080
+ var item = data.data.children[i];
1081
+ output.push({
1082
+ date: convertDate(item.data.created),
1083
+ config: config,
1084
+ html: parseRedditItem(item)
1085
+ });
1086
+ }
1087
+ }
1088
+
1089
+ callback(output);
1090
+ }
1091
+ });
1092
+
1093
+ // Expose the template.
1094
+ // We use this to check which templates are available
1095
+ return {
1096
+ "template" : template
1097
+ };
1098
+
1099
+ };
1100
+
1101
+ $.fn.lifestream.feeds.slideshare = function( config, callback ) {
1102
+
1103
+ var template = $.extend({},
1104
+ {
1105
+ uploaded: 'uploaded a presentation <a href="${link}">${title}</a>'
1106
+ },
1107
+ config.template);
1108
+
1109
+ var parseSlideshare = function( input ) {
1110
+ var output = [], list, i = 0, j, item;
1111
+
1112
+ if (input.query && input.query.count && input.query.count > 0) {
1113
+ list = input.query.results.rss.channel.item;
1114
+ j = list.length;
1115
+ for ( ; i < j; i++) {
1116
+ item = list[i];
1117
+
1118
+ output.push({
1119
+ date: new Date(item.pubDate),
1120
+ config: config,
1121
+ html: $.tmpl( template.uploaded, item )
1122
+ });
1123
+
1124
+ }
1125
+ }
1126
+
1127
+ return output;
1128
+ };
1129
+
1130
+ $.ajax({
1131
+ url: createYqlUrl('select * from xml where '
1132
+ + 'url="http://www.slideshare.net/rss/user/' + config.user + '"'),
1133
+ dataType: "jsonp",
1134
+ success: function( data ) {
1135
+ callback(parseSlideshare(data));
1136
+ }
1137
+ });
1138
+
1139
+ // Expose the template.
1140
+ // We use this to check which templates are available
1141
+ return {
1142
+ "template" : template
1143
+ };
1144
+
1145
+ };
1146
+
1147
+ $.fn.lifestream.feeds.stackoverflow = function( config, callback ) {
1148
+
1149
+ var template = $.extend({},
1150
+ {
1151
+ global: '<a href="${link}">${text}</a> - ${title}'
1152
+ },
1153
+ config.template);
1154
+
1155
+ var parseStackoverflowItem = function( item ) {
1156
+ var text="", title="", link="",
1157
+ stackoverflow_link = "http://stackoverflow.com/users/" + config.user,
1158
+ question_link = "http://stackoverflow.com/questions/";
1159
+
1160
+ if(item.timeline_type === "badge") {
1161
+ text = item.timeline_type + " " + item.action + ": "
1162
+ + item.description;
1163
+ title = item.detail;
1164
+ link = stackoverflow_link + "?tab=reputation";
1165
+ }
1166
+ else if (item.timeline_type === "revision"
1167
+ || item.timeline_type === "comment"
1168
+ || item.timeline_type === "accepted"
1169
+ || item.timeline_type === "askoranswered") {
1170
+ text = item.post_type + " " + item.action;
1171
+ title = item.detail || item.description || "";
1172
+ link = question_link + item.post_id;
1173
+ }
1174
+ return {
1175
+ link: link,
1176
+ title: title,
1177
+ text: text
1178
+ };
1179
+ },
1180
+ convertDate = function( date ) {
1181
+ return new Date(date * 1000);
1182
+ };
1183
+
1184
+ $.ajax({
1185
+ url: "http://api.stackoverflow.com/1.1/users/" + config.user
1186
+ + "/timeline?"
1187
+ + "jsonp",
1188
+ dataType: "jsonp",
1189
+ jsonp: 'jsonp',
1190
+ success: function( data ) {
1191
+ var output = [], i = 0, j;
1192
+
1193
+ if(data && data.total && data.total > 0 && data.user_timelines) {
1194
+ j = data.user_timelines.length;
1195
+ for( ; i<j; i++) {
1196
+ var item = data.user_timelines[i];
1197
+ output.push({
1198
+ date: convertDate(item.creation_date),
1199
+ config: config,
1200
+ html: $.tmpl( template.global, parseStackoverflowItem(item) )
1201
+ });
1202
+ }
1203
+ }
1204
+
1205
+ callback(output);
1206
+ }
1207
+ });
1208
+
1209
+ // Expose the template.
1210
+ // We use this to check which templates are available
1211
+ return {
1212
+ "template" : template
1213
+ };
1214
+
1215
+ };
1216
+
1217
+ $.fn.lifestream.feeds.tumblr = function( config, callback ) {
1218
+
1219
+ var template = $.extend({},
1220
+ {
1221
+ posted: 'posted a ${type} <a href="${url}">${title}</a>'
1222
+ },
1223
+ config.template),
1224
+
1225
+ /**
1226
+ * get title text
1227
+ */
1228
+ getTitle = function( post ) {
1229
+ var title = post["regular-title"]
1230
+ || post["quote-text"]
1231
+ || post["conversation-title"]
1232
+ || post["photo-caption"]
1233
+ || post["video-caption"]
1234
+ || post["audio-caption"]
1235
+ || post["regular-body"]
1236
+ || post["link-text"]
1237
+ || post.type
1238
+ || "";
1239
+
1240
+ // remove tags
1241
+ return title.replace( /<.+?>/gi, " ");
1242
+ },
1243
+ createTumblrOutput = function( config, post ) {
1244
+ return {
1245
+ date: new Date(post.date),
1246
+ config: config,
1247
+ html: $.tmpl( template.posted, {
1248
+ type: post.type,
1249
+ url: post.url,
1250
+ title: getTitle(post)
1251
+ } )
1252
+ };
1253
+ },
1254
+ parseTumblr = function( input ) {
1255
+ var output = [], i = 0, j, post;
1256
+ if(input.query && input.query.count && input.query.count > 0) {
1257
+ // If a user only has one post, post is a plain object, otherwise it
1258
+ // is an array
1259
+ if ( $.isArray(input.query.results.posts.post) ) {
1260
+ j = input.query.results.posts.post.length;
1261
+ for( ; i < j; i++) {
1262
+ post = input.query.results.posts.post[i];
1263
+ output.push(createTumblrOutput(config, post));
1264
+ }
1265
+ }
1266
+ else if ( $.isPlainObject(input.query.results.posts.post) ) {
1267
+ output.push(createTumblrOutput(config,input.query.results.posts.post));
1268
+ }
1269
+ }
1270
+ return output;
1271
+ };
1272
+
1273
+ $.ajax({
1274
+ url: createYqlUrl('select *'
1275
+ + ' from tumblr.posts where username="'+ config.user +'"'),
1276
+ dataType: 'jsonp',
1277
+ success: function( data ) {
1278
+ callback(parseTumblr(data));
1279
+ }
1280
+ });
1281
+
1282
+ // Expose the template.
1283
+ // We use this to check which templates are available
1284
+ return {
1285
+ "template" : template
1286
+ };
1287
+
1288
+ };
1289
+
1290
+ $.fn.lifestream.feeds.twitter = function( config, callback ) {
1291
+
1292
+ var template = $.extend({},
1293
+ {
1294
+ posted: '{{html tweet}}'
1295
+ },
1296
+ config.template),
1297
+
1298
+ /**
1299
+ * Add links to the twitter feed.
1300
+ * Hashes, @ and regular links are supported.
1301
+ * @private
1302
+ * @param {String} tweet A string of a tweet
1303
+ * @return {String} A linkified tweet
1304
+ */
1305
+ linkify = function( tweet ) {
1306
+
1307
+ var link = function( t ) {
1308
+ return t.replace(
1309
+ /[a-z]+:\/\/[a-z0-9-_]+\.[a-z0-9-_:~%&\?\/.=]+[^:\.,\)\s*$]/ig,
1310
+ function( m ) {
1311
+ return '<a href="' + m + '">'
1312
+ + ( ( m.length > 25 ) ? m.substr( 0, 24 ) + '...' : m )
1313
+ + '</a>';
1314
+ }
1315
+ );
1316
+ },
1317
+ at = function( t ) {
1318
+ return t.replace(
1319
+ /(^|[^\w]+)\@([a-zA-Z0-9_]{1,15})/g,
1320
+ function( m, m1, m2 ) {
1321
+ return m1 + '<a href="http://twitter.com/' + m2 + '">@'
1322
+ + m2 + '</a>';
1323
+ }
1324
+ );
1325
+ },
1326
+ hash = function( t ) {
1327
+ return t.replace(
1328
+ /(^|[^\w'"]+)\#([a-zA-Z0-9_]+)/g,
1329
+ function( m, m1, m2 ) {
1330
+ return m1 + '<a href="http://search.twitter.com/search?q=%23'
1331
+ + m2 + '">#' + m2 + '</a>';
1332
+ }
1333
+ );
1334
+ };
1335
+
1336
+ return hash(at(link(tweet)));
1337
+
1338
+ },
1339
+ /**
1340
+ * Parse the input from twitter
1341
+ */
1342
+ parseTwitter = function( input ) {
1343
+ var output = [], i = 0, j;
1344
+
1345
+ if(input.query && input.query.count && input.query.count >0) {
1346
+ j = input.query.count;
1347
+ for( ; i<j; i++) {
1348
+ var status = input.query.results.statuses[i].status;
1349
+ output.push({
1350
+ date: new Date(status.created_at),
1351
+ config: config,
1352
+ html: $.tmpl( template.posted, {
1353
+ tweet: linkify(status.text)
1354
+ } )
1355
+ });
1356
+ }
1357
+ }
1358
+ return output;
1359
+ };
1360
+
1361
+ $.ajax({
1362
+ url: createYqlUrl('select status.id, status.created_at, status.text'
1363
+ + ' from twitter.user.timeline where screen_name="'+ config.user +'"'),
1364
+ dataType: 'jsonp',
1365
+ success: function( data ) {
1366
+ callback(parseTwitter(data));
1367
+ }
1368
+ });
1369
+
1370
+ // Expose the template.
1371
+ // We use this to check which templates are available
1372
+ return {
1373
+ "template" : template
1374
+ };
1375
+
1376
+ };
1377
+
1378
+ $.fn.lifestream.feeds.vimeo = function( config, callback ) {
1379
+
1380
+ var template = $.extend({},
1381
+ {
1382
+ posted: 'posted <a href="${url}" title="${description}">${title}</a>'
1383
+ },
1384
+ config.template),
1385
+
1386
+ parseVimeo = function( input ) {
1387
+ var output = [], i = 0, j, item;
1388
+
1389
+ if (input) {
1390
+ j = input.length;
1391
+ for( ; i < j; i++) {
1392
+ item = input[i];
1393
+ output.push({
1394
+ date: new Date( item.upload_date.replace(' ', 'T') ),
1395
+ config: config,
1396
+ html: $.tmpl( template.posted, {
1397
+ url: item.url,
1398
+ description: item.description.replace(/"/g, "'")
1399
+ .replace( /<.+?>/gi, ""),
1400
+ title: item.title
1401
+ } )
1402
+ });
1403
+ }
1404
+ }
1405
+
1406
+ return output;
1407
+ };
1408
+
1409
+ $.ajax({
1410
+ url: "http://vimeo.com/api/v2/" + config.user + "/videos.json",
1411
+ dataType: "jsonp",
1412
+ crossDomain: true,
1413
+ success: function( data ) {
1414
+ callback(parseVimeo(data));
1415
+ }
1416
+ });
1417
+
1418
+ // Expose the template.
1419
+ // We use this to check which templates are available
1420
+ return {
1421
+ "template" : template
1422
+ };
1423
+
1424
+ };
1425
+
1426
+ $.fn.lifestream.feeds.wordpress = function( config, callback ) {
1427
+
1428
+ var template = $.extend({},
1429
+ {
1430
+ posted: 'posted <a href="${link}">${title}</a>'
1431
+ },
1432
+ config.template);
1433
+
1434
+ var parseWordpress = function ( input ) {
1435
+ var output = [], list, i = 0, j, item;
1436
+
1437
+ if ( input.query && input.query.count && input.query.count > 0
1438
+ && input.query.results.rss.channel.item ) {
1439
+ list = input.query.results.rss.channel.item;
1440
+ j = list.length;
1441
+ for ( ; i < j; i++) {
1442
+ item = list[i];
1443
+
1444
+ output.push({
1445
+ date: new Date( item.pubDate ),
1446
+ config: config,
1447
+ html: $.tmpl( template.posted, item )
1448
+ });
1449
+ }
1450
+ }
1451
+
1452
+ return output;
1453
+ };
1454
+
1455
+ $.ajax({
1456
+ url: createYqlUrl('select * from xml where '
1457
+ + 'url="http://' + config.user + '.wordpress.com/feed"'),
1458
+ dataType: "jsonp",
1459
+ success: function ( data ) {
1460
+ callback(parseWordpress(data));
1461
+ }
1462
+ });
1463
+
1464
+ // Expose the template.
1465
+ // We use this to check which templates are available
1466
+ return {
1467
+ "template" : template
1468
+ };
1469
+
1470
+ };
1471
+
1472
+ $.fn.lifestream.feeds.youtube = function( config, callback ) {
1473
+
1474
+ var template = $.extend({},
1475
+ {
1476
+ favorited: 'favorited <a href="${video.player.default}" '
1477
+ + 'title="${video.description}">${video.title}</a>'
1478
+ },
1479
+ config.template),
1480
+
1481
+ parseYoutube = function( input ) {
1482
+ var output = [], i = 0, j, item;
1483
+
1484
+ if(input.data && input.data.items) {
1485
+ j = input.data.items.length;
1486
+ for( ; i<j; i++) {
1487
+ item = input.data.items[i];
1488
+ output.push({
1489
+ date: new Date(item.created),
1490
+ config: config,
1491
+ html: $.tmpl( template.favorited, item )
1492
+ });
1493
+ }
1494
+ }
1495
+
1496
+ return output;
1497
+ };
1498
+
1499
+ $.ajax({
1500
+ url: "http://gdata.youtube.com/feeds/api/users/" + config.user
1501
+ + "/favorites?v=2&alt=jsonc",
1502
+ dataType: 'jsonp',
1503
+ success: function( data ) {
1504
+ callback(parseYoutube(data));
1505
+ }
1506
+ });
1507
+
1508
+ // Expose the template.
1509
+ // We use this to check which templates are available
1510
+ return {
1511
+ "template" : template
1512
+ };
1513
+
1514
+ };
1515
+
1516
+ }( jQuery ));