1(function(window, $, undefined) 2 { 3 'use strict'; 4 5 var congif = {}; 6 7 var post_types = { 8 'text': 'fas fa-sticky-note', 9 'audio/mpeg': 'fas fa-play' 10 }; 11 12 function RSSRender(config){ 13 this.config = config; 14 this.params = this.getUrlVars(); 15 16 if(this.params.feed_url){ 17 this.config.feed_url = this.params.feed_url; 18 } 19 20 this.covers = []; 21 this.timeline = []; 22 this.currentGUID = ""; 23 24 this.colors = ['#00429d', '#7ba8c6', '#a8d6c1', '#93c687', '#008000', '#ffaaa2', '#ea6372', '#c32750', '#93003a', '#1eac86', '#e2af39', '#eadac2', '#de3f27']; 25 26 if(config.colors){ 27 this.colors = config.colors; 28 } 29 30 return this; 31 } 32 33 RSSRender.prototype.parseFeed = function(callback){ 34 var self = this; 35 36 var parser = new RSSParser(); 37 38 parser.parseURL(self.config.feed_url, function(err, feed){ 39 self.feed = feed; 40 var timeline_id = 0; 41 self.timeline = []; 42 43 feed.items.forEach(function(item){ 44 var guid = item.guid; 45 46 var type = "text"; 47 48 if(item.enclosure && item.enclosure.type){ 49 type = item.enclosure.type; 50 } 51 52 //Parse out timeline data 53 var dates = item.content.match(/([1-2][0-9]{3}: [^<]*)/gm); 54 55 if(dates){ 56 dates.forEach(function(d){ 57 var p = d.split(": "); 58 59 self.timeline.push({ 60 id: timeline_id, 61 episode: item.title, 62 guid: item.guid, 63 className: "ep-" + item.itunes.episode, 64 group: parseInt(item.itunes.episode), 65 style: "background-color:" + self.colors[Math.floor(item.itunes.episode % self.colors.length)], 66 content: "<p class='ep-number'>E" + item.itunes.episode + "</p><p class='event'>" + p[1] + "</p>", 67 start: p[0] + "-01-01", 68 year: p[0] 69 }); 70 71 timeline_id++; 72 }); 73 } 74 }); 75 76 if(callback){ 77 callback(self); 78 } 79 }); 80 }; 81 82 RSSRender.prototype.renderTimeline = function(){ 83 var self = this; 84 85 if(!self.config.timeline){ 86 return false; 87 } 88 89 self.parseFeed(function(data){ 90 var container = document.getElementById(self.config.timeline.target); 91 92 // Create a DataSet (allows two way data-binding) 93 var items = new vis.DataSet(self.timeline); 94 95 var years = self.timeline.map(function(d){ 96 return d.year; 97 }); 98 99 // Configuration for the Timeline 100 var options = { 101 align: "left", 102 height: "150%", 103 max: (Math.max(...years) + 30) + "-01-01", 104 min: (Math.min(...years) - 10) + "-01-01", 105 orientation: "top" 106 }; 107 108 if(self.config.timeline.options){ 109 options = $.extend(options, self.config.timeline.options); 110 } 111 112 // Create a Timeline 113 var timeline = new vis.Timeline(container, items, options); 114 115 timeline.on('click', function(e){ 116 if(e.item != null){ 117 self.renderGUID(self.timeline[e.item].guid, "#" + (self.config.timeline.infobox || "ep-info")); 118 } 119 }); 120 }); 121 }; 122 123 RSSRender.prototype.render = function(callback){ 124 var self = this; 125 126 if(self.config.menu_items){ 127 self.config.menu_items.forEach(function(item){ 128 $("#side-menu").append( 129 '<a href="' + item.href + '" class="menu-item"><div class="row">' + 130 '<div class="col-md-4">' + 131 '<div class="icon">' + 132 '<i class="' + item.icon_class + ' fa-2x"></i>' + 133 '</div>' + 134 '</div>' + 135 '<div class="col-md-8"><div class="vertical-align">' + 136 '<span>' + item.name + '</span>' + 137 '</div></div>' + 138 '</div></a>' 139 ); 140 }); 141 } 142 143 var parser = new RSSParser(); 144 145 parser.parseURL(self.config.feed_url, function(err, feed){ 146 self.feed = feed; 147 148 $("#logo").attr("src", feed.image.url); 149 150 if(self.params.guid){ 151 feed.items = feed.items.filter(function(item){ 152 return item.guid.match(self.params.guid); 153 }); 154 }else{ 155 $("#header-content").html(feed.description); 156 } 157 158 var timeline_id = 0; 159 160 feed.items.forEach(function(item){ 161 var guid = item.guid; 162 var type = "text"; 163 164 if(item.enclosure && item.enclosure.type){ 165 type = item.enclosure.type; 166 } 167 168 if(self.covers.indexOf(item.itunes.image) < 0){ 169 self.covers.push(item.itunes.image); 170 } 171 172 if(self.params.guid){ 173 self.renderGUID(self.params.guid); 174 }else{ 175 var text = 176 "<div class='row'>" + 177 "<div class='col-md-12 item'>" + 178 "<a href='?guid=" + guid + "'>" + 179 '<h3><span><i class="' + post_types[type] + ' fa-1x"></i></span>' + item.title + "</h3>" + 180 "</a>" + 181 "<div class='item-desc'>" + item.content + "</div>" + 182 "<div class='more'><a href='?guid=" + guid + "'>More...</a></div>" + 183 "</div>" + 184 "</div>"; 185 186 $("#feed").append(text); 187 } 188 189 $("#feed iframe:last").remove(); 190 191 //Parse out timeline data 192 var dates = item.content.match(/([1-2][0-9]{3}: [^<]*)/gm); 193 194 if(dates){
195 dates.forEach(function(d){ 196 var p = d.split(": "); 197 198 self.timeline.push({ 199 id: timeline_id, 200 episode: item.title, 201 guid: item.guid, 202 link: "http://adventofcomputing.com/?guid=" + item.guid, 203 className: "ep-" + item.itunes.episode, 204 group: parseInt(item.itunes.episode), 205 style: "background-color:" + self.colors[Math.floor(item.itunes.episode % self.colors.length)], 206 content: "<p class='ep-number'>E" + item.itunes.episode + "</p><p class='event'>" + p[1] + "</p>", 207 start: p[0] + "-01-01" 208 }); 209 210 timeline_id++; 211 }); 212 } 213 }); 214 215 if(callback){ 216 callback(); 217 } 218 }); 219 }; 220 221 RSSRender.prototype.renderGUID = function(guid, target = "#feed"){ 222 var self = this; 223 224 if(guid != self.currentGUID){ 225 self.currentGUID = guid; 226 227 var item = self.feed.items.filter(function(item){ 228 return item.guid.match(guid); 229 })[0]; 230 231 $("#logo").attr("src", item.itunes.image); 232 233 var text = 234 "<div class='row'>" + 235 "<div class='col-md-12 item'>" + 236 "<h3>" + item.title + "</h3>" + 237 "<div>" + item.content + "</div>" + 238 "</div>" + 239 "</div>"; 240 241 $(target).html(text); 242 243 item.link = item.link.replace("http://", "https://"); 244 245 $.get(item.link, function(d){ 246 var player_source = $(d).find('iframe:last')[0].src; 247 player_source = player_source.replace("http://", "https://"); 248 player_source = player_source.replace("file://", "https://"); 249 player_source = player_source.replace("yes", "no"); 250 $("#header-content").html('<iframe frameborder="0" scrolling="no" src="' + player_source + '"></iframe>'); 251 $("#header-content").addClass("player"); 252 }); 253 254 //Fetch itunes stuff 255 self.getAppleData(item.title, function(episode){ 256 if(episode){ 257 $("<a href='" + episode.trackViewUrl + "'>" + 258 "<img src='./img/apple_podcasts.svg'>" + 259 "</a>").appendTo(target); 260 261 //https://plinkhq.com/i/1459202600/e/1000459702408?to=googlepod 262 $("<a href='https://plinkhq.com/i/" + episode.collectionId + "/e/" + episode.trackId + "?to=googlepod'>" + 263 "<img src='./img/google_podcasts_badge.png'>" + 264 "</a>").appendTo(target); 265 } 266 }); 267 } 268 }; 269 270 RSSRender.prototype.getAppleData = function(title, cb){ 271 var self = this; 272 //Fetch itunes stuff 273 if(!self.itunes_data){ 274 $.ajax({ 275 url: "https://itunes.apple.com/lookup?id=1459202600&entity=podcastEpisode", 276 dataType: "jsonp", 277 success: function(d){ 278 self.itunes_data = d.results; 279 self.getAppleData(title, cb); 280 } 281 }); 282 }else{ 283 var episode = self.itunes_data.filter(function(e){ 284 return e.trackName == title; 285 }); 286 287 cb(episode[0] || false); 288 } 289 }; 290 291 /** 292 * This function coverts a DOM Tree into JavaScript Object. 293 * @param srcDOM: DOM Tree to be converted. 294 */ 295 RSSRender.prototype.xml2json = function(srcDOM){ 296 let children = [...srcDOM.children]; 297 298 // base case for recursion. 299 if (!children.length) { 300 return srcDOM.innerHTML 301 } 302 303 // initializing object to be returned. 304 let jsonResult = {}; 305 306 for (let child of children) { 307 // checking is child has siblings of same name. 308 let childIsArray = children.filter(eachChild => eachChild.nodeName === child.nodeName).length > 1; 309 310 // if child is array, save the values as array, else as strings. 311 if (childIsArray) { 312 if (jsonResult[child.nodeName] === undefined) { 313 jsonResult[child.nodeName] = [xml2json(child)]; 314 } else { 315 jsonResult[child.nodeName].push(xml2json(child)); 316 } 317 } else { 318 jsonResult[child.nodeName] = xml2json(child); 319 } 320 } 321 322 return jsonResult; 323 }; 324 325 RSSRender.prototype.getUrlVars = function(){ 326 var vars = {}; 327 var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { 328 vars[key] = value; 329 }); 330 return vars; 331 } 332 333 334 window.RSSRender = RSSRender; 335 return window; 336 } 337)(window, $, undefined);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.