1(function ($) { 2 'use strict'; 3 4 var PopularCategoryStories = { 5 modal: null, 6 innerStories: null, 7 actionButtons: null, 8 storyArrows: null, 9 progressWrap: null, 10 categoryOrder: [], 11 activeIndex: -1, 12 cache: {}, 13 autoplaySpeed: 5000, 14 isPaused: false, 15 timer: null, 16 busy: false, 17 busyFailsafeTimer: null, 18 prefetching: {}, 19 20 setBusy: function (value) { 21 var self = this; 22 this.busy = value; 23 clearTimeout(this.busyFailsafeTimer); 24 if (value) { 25 this.busyFailsafeTimer = setTimeout(function () { 26 self.busy = false; 27 }, 4000); 28 } 29 }, 30 31 init: function () { 32 this.modal = $('.stories-cat'); 33 if (!this.modal.length) { 34 return; 35 } 36 37 this.innerStories = this.modal.find('.inner-stories'); 38 this.actionButtons = this.modal.find('.action-buttons'); 39 this.storyArrows = this.modal.find('.story-arrows'); 40 this.progressWrap = this.modal.find('.story-progress'); 41 42 var self = this; 43 $('.popular-cat-story').not('.slick-cloned').each(function () { 44 self.categoryOrder.push(String($(this).data('id'))); 45 }); 46 47 this.bindTrigger(); 48 this.bindClose(); 49 this.bindPause(); 50 this.bindArrows(); 51 this.bindTapZones(); 52 this.bindEsc(); 53 }, 54 55 bindTrigger: function () { 56 var self = this; 57 $(document).on('click', '.popular-cat-trigger', function (e) { 58 e.preventDefault(); 59 var storyEl = $(this).closest('.popular-cat-story'), 60 catId = String(storyEl.data('id')), 61 index = self.categoryOrder.indexOf(catId); 62 self.activeIndex = index > -1 ? index : 0; 63 self.open(catId); 64 }); 65 }, 66 67 open: function (catId) { 68 var self = this; 69 $('body').addClass('cat-stories--open'); 70 this.modal.addClass('open'); 71 this.isPaused = false; 72 this.setBusy(false); 73 this.actionButtons 74 .find('.action-btn.pause') 75 .removeClass('paused') 76 .find('i') 77 .removeClass('fa-play') 78 .addClass('fa-pause'); 79 this.load(catId, function () { 80 self.render(catId, false); 81 }); 82 }, 83 84 fallbackHtml: function (catId, message) { 85 return ( 86 '<div class="inner-story-wrap" data-id="' + catId + '">' + 87 '<div class="story-item no-thumb"><div class="content-wrap"><p class="no-posts">' + 88 message + 89 '</p></div></div></div>' 90 ); 91 }, 92 93 load: function (catId, callback) { 94 var self = this; 95 if (this.cache[catId]) { 96 callback(); 97 return; 98 } 99 this.modal.addClass('loading'); 100 $.ajax({ 101 url: newsmashStories.ajaxUrl, 102 method: 'POST', 103 data: { 104 action: 'newsmash_category_stories', 105 nonce: newsmashStories.nonce, 106 cat_id: catId 107 }, 108 success: function (response) { 109 if (response && response.success && response.data) { 110 self.cache[catId] = response.data; 111 } else { 112 self.cache[catId] = self.fallbackHtml(catId, newsmashStories.noPosts); 113 } 114 }, 115 error: function () { 116 self.cache[catId] = self.fallbackHtml(catId, newsmashStories.noPosts); 117 }, 118 complete: function () { 119 self.modal.removeClass('loading'); 120 callback(); 121 } 122 }); 123 }, 124 125 prefetch: function (catId) { 126 var self = this; 127 if (!catId || this.cache[catId] || this.prefetching[catId]) { 128 return; 129 } 130 this.prefetching[catId] = true; 131 $.ajax({ 132 url: newsmashStories.ajaxUrl, 133 method: 'POST', 134 data: { 135 action: 'newsmash_category_stories', 136 nonce: newsmashStories.nonce, 137 cat_id: catId 138 }, 139 success: function (response) { 140 if (response && response.success && response.data) { 141 self.cache[catId] = response.data; 142 } 143 }, 144 complete: function () { 145 delete self.prefetching[catId]; 146 } 147 }); 148 }, 149 150 prefetchNeighbors: function () { 151 this.prefetch(this.categoryOrder[this.activeIndex + 1]); 152 this.prefetch(this.categoryOrder[this.activeIndex - 1]); 153 }, 154 155 render: function (catId, startAtEnd) { 156 var self = this; 157 this.innerStories.empty().append(this.cache[catId] || this.fallbackHtml(catId, newsmashStories.noPosts)); 158 159 var wrap = this.innerStories.find('.inner-story-wrap'), 160 slideCount = wrap.find('.story-item').length, 161 initialSlide = startAtEnd ? Math.max(0, slideCount - 1) : 0; 162 163 if (!wrap.length) { 164 this.setBusy(false); 165 return; 166 } 167 168 wrap.on('init', function () { 169 self.buildProgress(wrap); 170 self.setActiveProgress(initialSlide); 171 self.setAmbient(wrap, initialSlide); 172 self.setBusy(false); 173 self.prefetchNeighbors(); 174 if (!self.isPaused) { 175 self.scheduleAdvance(); 176 } 177 }); 178 179 wrap.on('beforeChange', function (e, slick, currentSlide, nextSlide) { 180 self.setActiveProgress(nextSlide); 181 self.setAmbient(wrap, nextSlide); 182 }); 183 184 wrap.on('afterChange', function () { 185 self.setBusy(false); 186 if (!self.isPaused) { 187 self.scheduleAdvance(); 188 } 189 }); 190 191 try { 192 wrap.slick({ 193 autoplay: false, 194 fade: true, 195 infinite: false, 196 speed: 300,
197 arrows: false, 198 dots: false, 199 adaptiveHeight: false, 200 initialSlide: initialSlide 201 }); 202 } catch (e) { 203 self.setBusy(false); 204 } 205 }, 206 207 scheduleAdvance: function () { 208 var self = this; 209 clearTimeout(this.timer); 210 this.timer = setTimeout(function () { 211 self.goNext(); 212 }, this.autoplaySpeed); 213 }, 214 215 goNext: function () { 216 if (this.busy) { 217 return; 218 } 219 clearTimeout(this.timer); 220 var wrap = this.innerStories.find('.inner-story-wrap'); 221 if (wrap.hasClass('slick-initialized')) { 222 var slick = wrap.slick('getSlick'); 223 if (slick.currentSlide < slick.slideCount - 1) { 224 this.setBusy(true); 225 wrap.slick('slickNext'); 226 return; 227 } 228 } 229 this.nextCategory(); 230 }, 231 232 goPrev: function () { 233 if (this.busy) { 234 return; 235 } 236 clearTimeout(this.timer); 237 var wrap = this.innerStories.find('.inner-story-wrap'); 238 if (wrap.hasClass('slick-initialized')) { 239 var slick = wrap.slick('getSlick'); 240 if (slick.currentSlide > 0) { 241 this.setBusy(true); 242 wrap.slick('slickPrev'); 243 return; 244 } 245 } 246 this.prevCategory(true); 247 }, 248 249 buildProgress: function (wrap) { 250 var count = wrap.find('.story-item').length; 251 this.progressWrap.empty(); 252 for (var i = 0; i < count; i++) { 253 this.progressWrap.append('<span class="segment"><em></em></span>'); 254 } 255 }, 256 257 setActiveProgress: function (index) { 258 var self = this, 259 segments = this.progressWrap.find('.segment'); 260 segments.removeClass('active done'); 261 segments.find('em').css('animation', 'none'); 262 segments.each(function (i) { 263 if (i < index) { 264 $(this).addClass('done'); 265 } 266 }); 267 var active = segments.eq(index).addClass('active'); 268 if (!self.isPaused) { 269 window.requestAnimationFrame(function () { 270 active 271 .find('em') 272 .css('animation', 'newsmash-story-progress ' + self.autoplaySpeed / 1000 + 's linear forwards'); 273 }); 274 } 275 }, 276 277 setAmbient: function (wrap, index) { 278 var img = wrap.find('.story-item').eq(index).find('.story-cover img').attr('src'); 279 this.modal.find('.ambient-bg').css('background-image', img ? 'url(' + img + ')' : 'none'); 280 }, 281 282 nextCategory: function () { 283 clearTimeout(this.timer); 284 if (this.activeIndex < this.categoryOrder.length - 1) { 285 this.setBusy(true); 286 this.activeIndex++; 287 this.switchTo(this.categoryOrder[this.activeIndex], false); 288 } else { 289 this.close(); 290 } 291 }, 292 293 prevCategory: function (landOnLastPost) { 294 clearTimeout(this.timer); 295 if (this.activeIndex > 0) { 296 this.setBusy(true); 297 this.activeIndex--; 298 this.switchTo(this.categoryOrder[this.activeIndex], !!landOnLastPost); 299 } 300 }, 301 302 switchTo: function (catId, startAtEnd) { 303 var self = this, 304 wrap = this.innerStories.find('.inner-story-wrap'); 305 try { 306 if (wrap.hasClass('slick-initialized')) { 307 wrap.slick('unslick'); 308 } 309 } catch (e) {} 310 this.innerStories.empty(); 311 this.progressWrap.empty(); 312 this.load(catId, function () { 313 self.render(catId, startAtEnd); 314 }); 315 }, 316 317 bindArrows: function () { 318 var self = this; 319 this.storyArrows.on('click', '.prev-cat', function () { 320 self.goPrev(); 321 }); 322 this.storyArrows.on('click', '.next-cat', function () { 323 self.goNext(); 324 }); 325 }, 326 327 bindTapZones: function () { 328 var self = this; 329 this.innerStories.on('click', function (e) { 330 if ($(e.target).closest('a, button').length) { 331 return; 332 } 333 var offsetX = e.pageX - $(this).offset().left, 334 width = $(this).outerWidth(); 335 if (offsetX < width / 2) { 336 self.goPrev(); 337 } else { 338 self.goNext(); 339 } 340 }); 341 }, 342 343 bindPause: function () { 344 var self = this; 345 this.actionButtons.on('click', '.action-btn.pause', function () { 346 var btn = $(this); 347 self.isPaused = !self.isPaused; 348 btn.toggleClass('paused', self.isPaused); 349 btn.find('i').toggleClass('fa-pause fa-play'); 350 351 var activeEm = self.progressWrap.find('.segment.active em'); 352 if (self.isPaused) { 353 clearTimeout(self.timer); 354 activeEm.css('animation-play-state', 'paused'); 355 } else { 356 activeEm.css('animation-play-state', 'running'); 357 self.scheduleAdvance(); 358 } 359 }); 360 }, 361 362 bindClose: function () { 363 var self = this; 364 this.modal.on('click', '.action-btn.close, .stories-cat-overlay, .ambient-bg', function () { 365 self.close(); 366 }); 367 }, 368 369 bindEsc: function () { 370 var self = this; 371 $(document).on('keydown', function (e) { 372 if (e.keyCode === 27 && self.modal.hasClass('open')) { 373 self.close(); 374 } 375 }); 376 }, 377 378 close: function () { 379 clearTimeout(this.timer); 380 var wrap = this.innerStories.find('.inner-story-wrap'); 381 try { 382 if (wrap.hasClass('slick-initialized')) { 383 wrap.slick('unslick'); 384 } 385 } catch (e) {} 386 this.modal.removeClass('open'); 387 $('body').removeClass('cat-stories--open'); 388 this.innerStories.empty(); 389 this.progressWrap.empty(); 390 this.activeIndex = -1; 391 this.isPaused = false;
392 this.setBusy(false); 393 } 394 }; 395 396 $(function () { 397 PopularCategoryStories.init(); 398 }); 399})(jQuery);
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.