Advertisement
Guest User

Untitled

a guest
Dec 12th, 2017
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (function ($) {
  2.   'use strict';
  3.  
  4.   var RSS = function (target, url, options, callback) {
  5.     this.target       = target;
  6.  
  7.     this.url          = url;
  8.     this.html         = [];
  9.     this.effectQueue  = [];
  10.  
  11.     this.options = $.extend({
  12.       ssl: false,
  13.       host: 'www.feedrapp.info',
  14.       limit: 3,
  15.       key: null,
  16.       layoutTemplate: '<div class="entries">{entries}</div>',
  17.       entryTemplate: '<div class="one-third column"><a href="{url}"><div class="entimg">{teaserImage}</div><h5>{title}</h5><p class=snippet"">{shortBodyPlain}...</p><p><span class="author">{author}</span>{date}</p></div>',
  18.       tokens: {},
  19.       outputMode: 'json',
  20.       dateFormat: 'MMMM Do',
  21.       dateLocale: 'en',
  22.       effect: 'show',
  23.       offsetStart: false,
  24.       offsetEnd: false,
  25.       error: function () {
  26.         console.log('jQuery RSS: url doesn\'t link to RSS-Feed');
  27.       },
  28.       onData: function () {},
  29.       success: function () {}
  30.     }, options || {});
  31.  
  32.     this.callback = callback || this.options.success;
  33.   };
  34.  
  35.   RSS.htmlTags = [
  36.     'doctype', 'html', 'head', 'title', 'base', 'link', 'meta', 'style', 'script', 'noscript',
  37.     'body', 'article', 'nav', 'aside', 'section', 'header', 'footer', 'h1-h6', 'hgroup', 'address',
  38.     'p', 'hr', 'pre', 'blockquote', 'ol', 'ul', 'li', 'dl', 'dt', 'dd', 'figure', 'figcaption',
  39.     'div', 'table', 'caption', 'thead', 'tbody', 'tfoot', 'tr', 'th', 'td', 'col', 'colgroup',
  40.     'form', 'fieldset', 'legend', 'label', 'input', 'button', 'select', 'datalist', 'optgroup',
  41.     'option', 'textarea', 'keygen', 'output', 'progress', 'meter', 'details', 'summary', 'command',
  42.     'menu', 'del', 'ins', 'img', 'iframe', 'embed', 'object', 'param', 'video', 'audio', 'source',
  43.     'canvas', 'track', 'map', 'area', 'a', 'em', 'strong', 'i', 'b', 'u', 's', 'small', 'abbr', 'q',
  44.     'cite', 'dfn', 'sub', 'sup', 'time', 'code', 'kbd', 'samp', 'var', 'mark', 'bdi', 'bdo', 'ruby',
  45.     'rt', 'rp', 'span', 'br', 'wbr'
  46.   ];
  47.  
  48.   RSS.prototype.load = function (callback) {
  49.     var apiProtocol = 'https' + (this.options.ssl ? 's' : '');
  50.     var apiHost     = apiProtocol + '://' + this.options.host;
  51.     var apiUrl      = apiHost + '?callback=?&q=' + encodeURIComponent(this.url);
  52.  
  53.     // set limit to offsetEnd if offset has been set
  54.     if (this.options.offsetStart && this.options.offsetEnd) {
  55.       this.options.limit = this.options.offsetEnd;
  56.     }
  57.  
  58.     if (this.options.limit !== null) {
  59.       apiUrl += '&num=' + this.options.limit;
  60.     }
  61.  
  62.     if (this.options.key !== null) {
  63.       apiUrl += '&key=' + this.options.key;
  64.     }
  65.  
  66.     $.getJSON(apiUrl, callback);
  67.   };
  68.  
  69.   RSS.prototype.render = function () {
  70.     var self = this;
  71.  
  72.     this.load(function (data) {
  73.       try {
  74.         self.feed    = data.responseData.feed;
  75.         self.entries = data.responseData.feed.entries;
  76.       } catch (e) {
  77.         self.entries = [];
  78.         self.feed    = null;
  79.         return self.options.error.call(self);
  80.       }
  81.  
  82.       var html = self.generateHTMLForEntries();
  83.  
  84.       self.target.append(html.layout);
  85.  
  86.       if (html.entries.length !== 0) {
  87.         if ($.isFunction(self.options.onData)) {
  88.           self.options.onData.call(self);
  89.         }
  90.  
  91.         var container = $(html.layout).is('entries') ? html.layout : $('entries', html.layout);
  92.  
  93.         self.appendEntriesAndApplyEffects(container, html.entries);
  94.       }
  95.  
  96.       if (self.effectQueue.length > 0) {
  97.         self.executeEffectQueue(self.callback);
  98.       } else if ($.isFunction(self.callback)) {
  99.         self.callback.call(self);
  100.       }
  101.     });
  102.   };
  103.  
  104.   RSS.prototype.appendEntriesAndApplyEffects = function (target, entries) {
  105.     var self = this;
  106.  
  107.     $.each(entries, function (idx, entry) {
  108.       var $html = self.wrapContent(entry);
  109.  
  110.       if (self.options.effect === 'show') {
  111.         target.before($html);
  112.       } else {
  113.         $html.css({ display: 'none' });
  114.         target.before($html);
  115.         self.applyEffect($html, self.options.effect);
  116.       }
  117.     });
  118.  
  119.     target.remove();
  120.   };
  121.  
  122.   RSS.prototype.generateHTMLForEntries = function () {
  123.     var self   = this;
  124.     var result = { entries: [], layout: null };
  125.  
  126.     $(this.entries).each(function () {
  127.       var entry       = this;
  128.       var offsetStart = self.options.offsetStart;
  129.       var offsetEnd   = self.options.offsetEnd;
  130.       var evaluatedString;
  131.  
  132.       // offset required
  133.       if (offsetStart && offsetEnd) {
  134.         if (index >= offsetStart && index <= offsetEnd) {
  135.           if (self.isRelevant(entry, result.entries)) {
  136.             evaluatedString = self.evaluateStringForEntry(
  137.               self.options.entryTemplate, entry
  138.             );
  139.  
  140.             result.entries.push(evaluatedString);
  141.           }
  142.         }
  143.       } else {
  144.         // no offset
  145.         if (self.isRelevant(entry, result.entries)) {
  146.           evaluatedString = self.evaluateStringForEntry(
  147.             self.options.entryTemplate, entry
  148.           );
  149.  
  150.           result.entries.push(evaluatedString);
  151.         }
  152.       }
  153.     });
  154.  
  155.     if (!!this.options.entryTemplate) {
  156.       // we have an entryTemplate
  157.       result.layout = this.wrapContent(
  158.         this.options.layoutTemplate.replace('{entries}', '<entries></entries>')
  159.       );
  160.     } else {
  161.       // no entryTemplate available
  162.       result.layout = this.wrapContent('<div><entries></entries></div>');
  163.     }
  164.  
  165.     return result;
  166.   };
  167.  
  168.   RSS.prototype.wrapContent = function (content) {
  169.     if (($.trim(content).indexOf('<') !== 0)) {
  170.       // the content has no html => create a surrounding div
  171.       return $('<div>' + content + '</div>');
  172.     } else {
  173.       // the content has html => don't touch it
  174.       return $(content);
  175.     }
  176.   };
  177.  
  178.   RSS.prototype.applyEffect = function ($element, effect, callback) {
  179.     var self = this;
  180.  
  181.     switch (effect) {
  182.       case 'slide':
  183.         $element.slideDown('slow', callback);
  184.         break;
  185.       case 'slideFast':
  186.         $element.slideDown(callback);
  187.         break;
  188.       case 'slideSynced':
  189.         self.effectQueue.push({ element: $element, effect: 'slide' });
  190.         break;
  191.       case 'slideFastSynced':
  192.         self.effectQueue.push({ element: $element, effect: 'slideFast' });
  193.         break;
  194.     }
  195.   };
  196.  
  197.   RSS.prototype.executeEffectQueue = function (callback) {
  198.     var self = this;
  199.  
  200.     this.effectQueue.reverse();
  201.  
  202.     var executeEffectQueueItem = function () {
  203.       var item = self.effectQueue.pop();
  204.  
  205.       if (item) {
  206.         self.applyEffect(item.element, item.effect, executeEffectQueueItem);
  207.       } else if (callback) {
  208.         callback();
  209.       }
  210.     };
  211.  
  212.     executeEffectQueueItem();
  213.   };
  214.  
  215.   RSS.prototype.evaluateStringForEntry = function (string, entry) {
  216.     var result = string;
  217.     var self   = this;
  218.  
  219.     $(string.match(/(\{.*?\})/g)).each(function () {
  220.       var token = this.toString();
  221.  
  222.       result = result.replace(token, self.getValueForToken(token, entry));
  223.     });
  224.  
  225.     return result;
  226.   };
  227.  
  228.   RSS.prototype.isRelevant = function (entry, entries) {
  229.     var tokenMap = this.getTokenMap(entry);
  230.  
  231.     if (this.options.filter) {
  232.       if (this.options.filterLimit && (this.options.filterLimit === entries.length)) {
  233.         return false;
  234.       } else {
  235.         return this.options.filter(entry, tokenMap);
  236.       }
  237.     } else {
  238.       return true;
  239.     }
  240.   };
  241.  
  242.   RSS.prototype.getFormattedDate = function (dateString) {
  243.     // If a custom formatting function is provided, use that.
  244.     if (this.options.dateFormatFunction) {
  245.       return this.options.dateFormatFunction(dateString);
  246.     } else if (typeof moment !== 'undefined') {
  247.       // If moment.js is available and dateFormatFunction is not overriding it,
  248.       // use it to format the date.
  249.       var date = moment(new Date(dateString));
  250.  
  251.       if (date.locale) {
  252.         date = date.locale(this.options.dateLocale);
  253.       } else {
  254.         date = date.lang(this.options.dateLocale);
  255.       }
  256.  
  257.       return date.format(this.options.dateFormat);
  258.     } else {
  259.       // If all else fails, just use the date as-is.
  260.       return dateString;
  261.     }
  262.   };
  263.  
  264.   RSS.prototype.getTokenMap = function (entry) {
  265.     if (!this.feedTokens) {
  266.       var feed = JSON.parse(JSON.stringify(this.feed));
  267.  
  268.       delete feed.entries;
  269.       this.feedTokens = feed;
  270.     }
  271.  
  272.     return $.extend({
  273.       feed:      this.feedTokens,
  274.       url:       entry.link,
  275.       author:    entry.author,
  276.       date:      this.getFormattedDate(entry.publishedDate),
  277.       title:     entry.title,
  278.       body:      entry.content,
  279.       shortBody: entry.contentSnippet,
  280.  
  281.       bodyPlain: (function (entry) {
  282.         var result = entry.content
  283.           .replace(/<script[\\r\\\s\S]*<\/script>/mgi, '')
  284.           .replace(/<\/?[^>]+>/gi, '');
  285.  
  286.         for (var i = 0; i < RSS.htmlTags.length; i++) {
  287.           result = result.replace(new RegExp('<' + RSS.htmlTags[i], 'gi'), '');
  288.         }
  289.  
  290.         return result;
  291.       })(entry),
  292.  
  293.       shortBodyPlain: entry.contentSnippet.replace(/<\/?[^>]+>/gi, ''),
  294.       index:          $.inArray(entry, this.entries),
  295.       totalEntries:   this.entries.length,
  296.  
  297.       teaserImage:    (function (entry) {
  298.         try {
  299.           return entry.content.match(/(<img.*?>)/gi)[0];
  300.         }
  301.         catch (e) {
  302.           return '';
  303.         }
  304.       })(entry),
  305.  
  306.       teaserImageUrl: (function (entry) {
  307.         try {
  308.           return entry.content.match(/(<img.*?>)/gi)[0].match(/src="(.*?)"/)[1];
  309.         }
  310.         catch (e) {
  311.           return '';
  312.         }
  313.       })(entry)
  314.     }, this.options.tokens);
  315.   };
  316.  
  317.   RSS.prototype.getValueForToken = function (_token, entry) {
  318.     var tokenMap = this.getTokenMap(entry);
  319.     var token    = _token.replace(/[\{\}]/g, '');
  320.     var result   = tokenMap[token];
  321.  
  322.     if (typeof result !== 'undefined') {
  323.       return ((typeof result === 'function') ? result(entry, tokenMap) : result);
  324.     } else {
  325.       throw new Error('Unknown token: ' + _token + ', url:' + this.url);
  326.     }
  327.   };
  328.  
  329.   $.fn.rss = function (url, options, callback) {
  330.     new RSS(this, url, options, callback).render();
  331.     return this; // Implement chaining
  332.   };
  333. })(jQuery);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement