1/* 2 * Copyright 2012-2018, Theia Post Slider, WeCodePixels, https://wecodepixels.com 3 */ 4var tps = tps || {}; 5tps.slideshowsOnPage = 0; 6tps.createSlideshowDefaults = { 7 slideContainer: '', 8 nav: [], 9 navText: '%{currentSlide} of %{totalSlides}', 10 helperText: '', 11 defaultSlide: 0, 12 transitionEffect: 'none', 13 transitionSpeed: 400, 14 keyboardShortcuts: false, 15 scrollAfterRefresh: true, 16 numberOfSlides: 0, // Total number of slides, including the ones not loaded. 17 slides: [], 18 useSlideSources: false, 19 themeType: 'classic', 20 prevPost: null, 21 nextPost: null, 22 prevText: null, 23 nextText: null, 24 buttonWidth: 0, 25 prevText_post: null, 26 nextText_post: null, 27 buttonWidth_post: 0, 28 onShowPost: null, 29 postUrl: null, 30 postId: null, 31 refreshAds: false, 32 refreshAdsEveryNSlides: 1, 33 adRefreshingMechanism: 'javascript', 34 ajaxUrl: '/', 35 loopSlides: false, 36 scrollTopOffset: 0, 37 isRtl: false, 38 excludedWords: [] 39}; 40tps.createSlideshow = function (options) { 41 var i, j; 42 var me = this; 43 var $ = jQuery; 44 45 // Merge options with defaults and sanitize values. 46 me.options = $.extend(tps.createSlideshowDefaults, options); 47 for (i in me.options) { 48 // If the default is a number and the option is a string, then convert it to a number if possible. 49 if (!isNaN(tps.createSlideshowDefaults[i]) && (typeof me.options[i] == 'string')) { 50 var value = parseFloat(me.options[i]); 51 if (!isNaN(value)) { 52 me.options[i] = value; 53 } 54 } 55 } 56 57 me.slides = []; 58 me.slideContainer = $(me.options.slideContainer); 59 if (me.slideContainer.length == 0) { 60 return null; 61 } 62 63 tps.slideshowsOnPage++; 64 me.navEl = []; 65 for (i = 0; i < me.options.nav.length; i++) { 66 var e = $(me.options.nav[i]).get(); 67 for (j = 0; j < e.length; j++) { 68 me.navEl.push({ 69 container: $(e[j]) 70 }); 71 } 72 } 73 74 // Initialize variables. 75 me.currentPostId = me.options.postId; 76 me.isLoading = false; 77 me.slidesSinceLastAdRefresh = 0; 78 79 // Remote loading queue. 80 me.remoteLoadingQueue = async.queue(function (task, callback) { 81 callback(); 82 }, 1); 83 84 // The current slide. 85 me.currentSlide = null; 86 87 // The slide that is currently displayed. This may lag behind "me.currentSlide" because of the animations. 88 me.currentlyDisplayedSlide = null; 89 90 // The number of animations that are currently running. 91 me.animations = 0; 92 93 // A queue that is executed when no animation is running. 94 me.semaphore = 0; 95 me.asyncQueue = async.queue(function (task, callback) { 96 callback(); 97 }, 1); 98 99 me.incrementSemaphore = function () { 100 me.asyncQueue.pause(); 101 me.semaphore++; 102 }; 103 104 me.decrementSemaphore = function () { 105 me.semaphore--; 106 if (me.semaphore == 0) { 107 me.asyncQueue.resume(); 108 } 109 }; 110 111 // Initialization function 112 me.init = function () { 113 var i; 114 115 // Load scroll position, if available. 116 me.loadScrollTop(); 117 118 // Get slides from me.options.slides 119 for (i in me.options.slides) { 120 if ('content' in me.options.slides[i]) { 121 if (me.options.useSlideSources) { 122 me.options.slides[i].source = me.options.slides[i].content; 123 } 124 125 me.options.slides[i].content = $('<div>').html(me.options.slides[i].content); 126 } 127 128 me.slides[i] = me.options.slides[i]; 129 } 130 me.options.slides = null; 131 132 // Get slides from HTML. The first slide is considered the default one, while the rest are detached. 133 me.slideContainer.children('.theiaPostSlider_preloadedSlide').each(function (index, slide) { 134 index = me.options.defaultSlide + index; 135 slide = $(slide); 136 me.slides[index] = me.slides[index] || {}; 137 me.slides[index].title = document.title; 138 me.slides[index].permalink = document.location.href; 139 me.slides[index].content = slide; 140 141 if (index != me.options.defaultSlide) { 142 slide.detach(); 143 } 144 }); 145 146 // Count the slides. 147 me.numberOfSlides = me.options.numberOfSlides; 148 149 // Setup the navigation bars. 150 for (i = 0; i < me.navEl.length; i++) { 151 var navEl = me.navEl[i]; 152 navEl.text = navEl.container.find('._text'); 153 navEl.prev = navEl.container.find('._prev') 154 .click(function (me) { 155 return function (event) { 156 me.onNavClick(this, 'prev', event); 157 } 158 }(me)); 159 navEl.next = navEl.container.find('._next') 160 .click(function (me) { 161 return function (event) { 162 me.onNavClick(this, 'next', event); 163 } 164 }(me)); 165 166 navEl.title = navEl.container.find('._title'); 167 168 // Get the default slide's title. The title will be the same for all navigation bars, so get it only from the first. 169 if (i === 0) { 170 me.slides[me.options.defaultSlide].shortCodeTitle = navEl.title.html(); 171 } 172 173 /* 174 Add _active class on mousedown. This is a fix for IE and Opera which don't match :active on container elements. 175 Also, return false to prevent double click context menu in Opera. 176 */ 177 navEl.container.find('._prev, ._next') 178 .mousedown(function () { 179 $(this).addClass('_active'); 180 }) 181 .mouseup(function () { 182 $(this).removeClass('_active'); 183 }); 184 } 185 186 // Skip loading the slide if we're not going to display another one anyway. 187 if (me.numberOfSlides == 1 || (me.options.refreshAds && me.options.adRefreshingMechanism == 'page' && me.options.refreshAdsEveryNSlides <= 1)
187) { 188 me.currentSlide = me.options.defaultSlide; 189 } 190 else { 191 // Show the first slide 192 me.setSlide(me.options.defaultSlide); 193 194 // Add history handler. 195 var history = window.History; 196 if (history.enabled) { 197 history.Adapter.bind(window, 'statechange', function (me) { 198 return function () { 199 var state = History.getState(); 200 if (state.data.currentPostId != undefined) { 201 if (state.data.currentSlide != undefined) { 202 me.setSlide(state.data.currentSlide); 203 } 204 else { 205 me.setSlide(me.options.defaultSlide); 206 } 207 } 208 }; 209 }(me)); 210 } 211 } 212 213 // Set up touch events. 214 if (typeof Hammer !== 'undefined') { 215 me.previousTouch = 0; 216 me.minimumTimeBetweenGestures = 500; 217 218 // Eanble text selection. 219 delete Hammer.defaults.cssProps.userSelect; 220 221 // Create hammer.js instance. 222 var hammertime = new Hammer(me.slideContainer[0], { 223 inputClass: Hammer.TouchInput 224 }); 225 226 hammertime 227 .on('swipeleft', function () { 228 var t = (new Date).getTime(); 229 if (t - me.minimumTimeBetweenGestures >= me.previousTouch) { 230 me.setNext(); 231 me.previousTouch = t; 232 } 233 }) 234 .on('swiperight', function () { 235 var t = (new Date).getTime(); 236 if (t - me.minimumTimeBetweenGestures >= me.previousTouch) { 237 me.setPrev(); 238 me.previousTouch = t; 239 } 240 }); 241 } 242 243 // Enable keyboard shortcuts 244 if (me.options.keyboardShortcuts) { 245 $(document).keydown(function (me) { 246 return function (e) { 247 // Disable shortcut if there is more than one slideshow on the page. 248 if (tps.slideshowsOnPage > 1) { 249 return true; 250 } 251 252 // Disable shortcut if the target element is editable (input boxes, textareas, etc.). 253 if ( 254 this !== e.target && 255 ( 256 /textarea|select/i.test(e.target.nodeName) || 257 e.target.type === "text" || 258 ( 259 $(e.target).prop && 260 $(e.target).prop('contenteditable') == 'true' 261 ) 262 ) 263 ) { 264 return true; 265 } 266 267 switch (e.which) { 268 case 37: 269 me.navEl[0].prev[0].click(); 270 return false; 271 272 case 39: 273 me.navEl[0].next[0].click(); 274 return false; 275 } 276 277 return true; 278 }; 279 }(me)); 280 } 281 }; 282 283 // Load slides remotely 284 me.loadSlides = function (slides, callback) { 285 me.remoteLoadingQueue.push({name: ''}, function (me, slides, callback) { 286 return function (err) { 287 // Check if the slides are already loaded. 288 var allSlidesAreLoaded = true; 289 for (var i in slides) { 290 if (!(slides[i] in me.slides) || !('content' in me.slides[slides[i]])) { 291 allSlidesAreLoaded = false; 292 break; 293 } 294 } 295 if (allSlidesAreLoaded) { 296 if (callback) { 297 callback(); 298 } 299 return; 300 } 301 302 // Load the slides and don't load anything else in the meantime. 303 me.remoteLoadingQueue.concurrency = 0; 304 $.ajax({ 305 method: 'POST', 306 dataType: 'json', 307 data: { 308 action: 'tps_get_slides', 309 postId: me.currentPostId, 310 slides: slides 311 }, 312 url: me.options.ajaxUrl, 313 success: function (me) { 314 return function (data) { 315 if (!data) { 316 return; 317 } 318 if (data.postId == me.currentPostId) { 319 // Add each slide. 320 for (var i in data.slides) { 321 if (!(i in me.slides)) { 322 me.slides[i] = {}; 323 } 324 325 // Add content.
326 if ('content' in data.slides[i]) { 327 if (me.options.useSlideSources) { 328 data.slides[i].source = data.slides[i].content; 329 } 330 331 data.slides[i].content = $('<div>').html(data.slides[i].content); 332 } 333 334 // Overwrite old data with new data. 335 for (var j in data.slides[i]) { 336 me.slides[i][j] = data.slides[i][j]; 337 } 338 } 339 } 340 else { 341 console.error('Received AJAX results for a different post ID.'); 342 } 343 }; 344 }(me), 345 complete: function (me, callback) { 346 return function () { 347 if (callback) { 348 callback(); 349 } 350 me.remoteLoadingQueue.concurrency = 1; 351 me.remoteLoadingQueue.push({}); 352 }; 353 }(me, callback) 354 }); 355 }; 356 }(me, slides, callback)); 357 }; 358 359 // Set the current slide. 360 me.setSlide = function (index, isCallback) { 361 if (me.isLoading == true && isCallback != true) { 362 return; 363 } 364 365 // Is the slide already displayed? 366 if (me.currentSlide == index) { 367 return; 368 } 369 370 // Do we need to refresh the ads by refreshing the entire page? 371 if (me.needToRefreshPage() && index in me.slides) { 372 me.saveScrollTop(); 373 window.location = me.slides[index].permalink; 374 375 return; 376 } 377 378 // Fire events. 379 $(document).trigger('theiaPostSlider.willChangeSlide', [index]); 380 381 // Is the slide not yet loaded? 382 if (!me.isSlideLoaded(index)) { 383 if (!isCallback) { 384 me.showLoading(); 385 me.loadSlides([index], function (me, index) { 386 return function () { 387 me.hideLoading(); 388 me.setSlide(index, true); 389 } 390 }(me, index)); 391 392 return; 393 } 394 else { 395 // The slide could not be loaded via AJAX. Abort. 396 console.error("The slide could not be loaded via AJAX."); 397 return; 398 } 399 } 400 401 // 402 var slideContent = me.slides[index].source; 403 if (slideContent) { 404 for (i = 0; i < me.options.excludedWords.length; i++) { 405 var word = me.options.excludedWords[i]; 406 407 // Check if word is actually a string. 408 if (typeof word !== 'string') { 409 continue; 410 } 411 412 // Trim string. 413 word = word.trim(); 414 415 // Length must be at least one. 416 if (word.length == 0) { 417 continue; 418 } 419 420 // Search for string and redirect if necessary. 421 if (slideContent.indexOf(word) !== -1) { 422 me.showLoading(); 423 window.location = me.slides[index].permalink; 424 425 return; 426 } 427 } 428 } 429 430 var previousSlide = me.currentSlide; 431 me.currentSlide = index; 432 433 if (previousSlide != null) { 434 var i; 435 436 // Scroll the window up, if the beginning of the slide is out-of-view. 437 // Get the lowest offset.top 438 var scrollTop = me.slideContainer.offset().top; 439 for (i = 0; i < me.navEl.length; i++) { 440 scrollTop = Math.min(scrollTop, me.navEl[i].container.offset().top); 441 } 442 scrollTop += me.options.scrollTopOffset; 443 scrollTop = Math.max(0, scrollTop); 444 if ($(window).scrollTop() > scrollTop) { 445 $('body,html').animate({scrollTop: scrollTop}); 446 } 447 448 // Remove number class. 449 for (i = 0; i < me.navEl.length; i++) { 450 var navEl = me.navEl[i]; 451 navEl.container.removeClass('_slide_number_' + previousSlide); 452 } 453 } 454 455 // Set the title text. 456 me.updateTitleText(); 457 458 // Change URL, but only if this isn't the first slide set (i.e. the default slide). 459 var history = window.History; 460 if (history.enabled) { 461 var url = me.slides[me.currentSlide].permalink; 462 463 // Replace protocol and domain (e.g. using CloudFlare's HTTPS from an HTTP source).
464 var a = document.createElement('a'); 465 a.href = url; 466 url = window.location.protocol + '//' + window.location.host + a.pathname + a.search + a.hash; 467 468 if (url && previousSlide !== null) { 469 var f; 470 if (url == window.location) { 471 f = history.replaceState; 472 } 473 else { 474 f = history.pushState; 475 } 476 f({ 477 currentSlide: index, 478 currentPostId: me.currentPostId 479 }, me.slides[me.currentSlide].title, url); 480 } 481 } 482 483 // Show the slide. 484 me.asyncQueue.push({name: ''}, me.showSlide); 485 486 // Set the navigation bars. 487 me.updateNavigationBars(); 488 489 // Preload, but only if we don't have to refresh the page immediately after. 490 if ( 491 !( 492 me.options.refreshAds && 493 me.slidesSinceLastAdRefresh + 1 >= me.options.refreshAdsEveryNSlides && 494 me.options.adRefreshingMechanism == 'page' 495 ) 496 ) { 497 // Direction is either +1 if the user is browsing forward (i.e. using the "next" button), or -1 otherwise. 498 var direction; 499 if (previousSlide == null) { 500 direction = 1; 501 } 502 else if (me.currentSlide == 0 && previousSlide == me.numberOfSlides - 1) { 503 direction = 1; 504 } 505 else if (me.currentSlide == me.numberOfSlides - 1 && previousSlide == 0) { 506 direction = -1; 507 } 508 else { 509 direction = me.currentSlide - previousSlide; 510 direction = Math.max(Math.min(direction, 1), -1); 511 } 512 513 var slideToPreload = me.currentSlide + direction; 514 515 // If the loop-slides settings is activated, also preload the first/last slide when applicable. 516 if (slideToPreload == -1 && me.options.loopSlides) { 517 slideToPreload = me.numberOfSlides - 1; 518 } 519 else if (slideToPreload == me.numberOfSlides && me.options.loopSlides) { 520 slideToPreload = 0; 521 } 522 523 if ( 524 slideToPreload >= 0 && 525 slideToPreload < me.numberOfSlides && !me.isSlideLoaded((slideToPreload)) 526 ) { 527 me.loadSlides([slideToPreload]); 528 } 529 530 } 531 }; 532 533 // Show (display) the current slide using the chosen animation. 534 me.showSlide = function () { 535 // Don't do anything if the current slide is already shown. 536 if (me.currentlyDisplayedSlide == me.currentSlide) { 537 return; 538 } 539 540 // Track the pageview if this isn't the first slide displayed. 541 if (me.currentlyDisplayedSlide != null && me.slides[me.currentSlide]['permalink']) { 542 // URL Path 543 var path = me.slides[me.currentSlide]['permalink'].split('/'); 544 if (path.length >= 4) { 545 path = '/' + path.slice(3).join('/'); 546 547 // Global Site Tag (gtag.js) 548 // See: https://developers.google.com/analytics/devguides/collection/gtagjs/migration 549 if (typeof gtag !== 'undefined') { 550 // Search for UA tag. 551 var tag = ''; 552 for (var i = 0; i < window.dataLayer.length; i++) { 553 if (window.dataLayer[i].length >= 1 && window.dataLayer[i][0] === 'config') { 554 tag = window.dataLayer[i][1]; 555 break; 556 } 557 } 558 gtag('config', tag, { 559 'page_path': path 560 }); 561 } 562 // Google Analytics (ga.js, deprecated, but preferred if available) 563 // If using both old and new versions, the new version sometimes does not work. 564 // See http://stackoverflow.com/questions/18696998/ga-or-gaq-push-for-google-analytics-event-tracking 565 else if (typeof _gaq !== 'undefined' && typeof _gaq.pu
565sh !== 'undefined') { 566 _gaq.push(['_trackPageview', path]); 567 } 568 // Google Analytics by Yoast, which renames the "ga" variable. 569 else if (typeof __gaTracker !== 'undefined') { 570 __gaTracker('set', 'page', path); 571 __gaTracker('send', 'pageview', path); 572 } 573 // Google Analytics (Analytics.js). 574 else if (typeof ga !== 'undefined') { 575 ga('set', 'page', path); 576 ga('send', 'pageview', path); 577 } 578 // Google Analytics Traditional. 579 else if (typeof pageTracker !== 'undefined' && typeof pageTracker._trackPageview !== 'undefined') { 580 pageTracker._trackPageview(path); 581 } 582 583 // Piwik 584 if (typeof piwikTracker !== 'undefined' && typeof piwikTracker.trackPageView !== 'undefined') { 585 piwikTracker.trackPageView(path); 586 } 587 588 // StatCounter 589 if (typeof sc_project !== 'undefined' && typeof sc_security !== 'undefined') { 590 var img = new Image(); 591 img.src = '//c.statcounter.com/' + sc_project + '/0/' + sc_security + '/1/'; 592 } 593 594 // Quantcast 595 if (typeof _qacct !== 'undefined') { 596 var img = new Image(); 597 img.src = '//pixel.quantserve.com/pixel/' + _qacct + '.gif'; 598 } 599 } 600 } 601 602 var previousIndex = me.currentlyDisplayedSlide; 603 me.currentlyDisplayedSlide = me.currentSlide; 604 605 me.createSlideContentFromSource(me.slides[me.currentSlide]); 606 607 // Change the slide while applying a certain effect/animation. 608 var animationsQueue = tps.transitions[me.options.transitionEffect](me, previousIndex, me.currentlyDisplayedSlide); 609 610 // Execute all "attachAnimation" methods before starting any animation. 611 // Otherwise, we might get a race condition when one animation finishes before others are started, 612 // thus triggering unwanted events before all animations have ended. 613 for (var i = 0; i < animationsQueue.length; i++) { 614 me.incrementSemaphore(); 615 } 616 617 // This will be called after all animations finish, before any other items in the queue. 618 if (previousIndex !== null) { 619 me.asyncQueue.unshift({name: ''}, function (me, previousIndex) { 620 return function () { 621 me.onRemovedSlide(previousIndex); 622 } 623 }(me, previousIndex)); 624 } 625 626 // Start all animations. 627 for (var i = 0; i < animationsQueue.length; i++) { 628 animationsQueue[i](); 629 } 630 }; 631 632 me.createSlideContentFromSource = function (slide) { 633 if (!('content' in slide) && ('source' in slide)) { 634 slide.content = $('<div>').html(slide.source); 635 636 if (false == me.options.useSlideSources) { 637 delete slide.source; 638 } 639 } 640 }; 641 642 me.isSlideLoaded = function (index) { 643 if (!(index in me.slides)) { 644 return false; 645 } 646 647 // Only if this isn't the first slide. 648 if (me.currentlyDisplayedSlide !== null && me.options.useSlideSources && !('source' in me.slides[index])) { 649 return false; 650 } 651 652 if (!(('content' in me.slides[index]) || ('source' in me.slides[index]))) { 653 return false; 654 } 655 656 return true; 657 }; 658 659 // Function that is called right after a new slide has been added to the DOM, and right before the animation (if available) has started. 660 me.onNewSlide = function () { 661 // "BJ Lazy Load" plugin. 662 $(".lazy-hidden").not(".data-lazy-ready").one("scrollin.bj_lazy_load", { 663 distance: 200 664 }, function () { 665 var b = $(this), 666 d = b.attr("data-lazy-type"); 667 if (d == "image") { 668 b.hide().attr("src", b.attr("data-lazy-src")).removeClass("lazy-hidden").fadeIn() 669 } else if (d == "iframe") { 670 b.replaceWith(c(b.attr("data-lazy-src"))) 671 } 672 }).addClass("data-lazy-ready"); 673 674 // "Lazy Load" plugin. 675 var events = $('body').data('events'); 676 if (events && events['post-load']) { 677 for (var i = 0; i < events['post-load'].length; i++) { 678 if (events['post-load'][i].handler.name == 'lazy_load_init') { 679 events['post-load'][i].handler(); 680 } 681 } 682 } 683
684 // WordPress [audio] and [video] shortcodes. 685 if (typeof _wpmejsSettings !== 'undefined') { 686 $('.wp-audio-shortcode, .wp-video-shortcode').mediaelementplayer(_wpmejsSettings); 687 } 688 689 // Instagram embeds. 690 if (typeof instgrm !== 'undefined' && typeof instgrm.Embeds !== 'undefined' && typeof instgrm.Embeds.process !== 'undefined') { 691 instgrm.Embeds.process(); 692 } 693 694 // Fire events. 695 $(document).trigger('theiaPostSlider.changeSlide', [me.currentSlide]); 696 }; 697 698 // Function that is called right after a slide has been removed from the DOM. 699 me.onRemovedSlide = function (slideId) { 700 if (me.options.useSlideSources) { 701 me.slides[slideId].content.remove(); 702 delete me.slides[slideId].content; 703 } 704 705 // Refresh ads using JavaScript. 706 if (me.options.refreshAds) { 707 me.slidesSinceLastAdRefresh++; 708 709 if (me.slidesSinceLastAdRefresh >= me.options.refreshAdsEveryNSlides) { 710 me.slidesSinceLastAdRefresh = 0; 711 712 if (me.options.adRefreshingMechanism == 'javascript') { 713 var p = null; 714 715 if (typeof pubService === 'undefined') { 716 if (typeof googletag !== 'undefined' && typeof googletag.pubads === 'function') { 717 p = googletag.pubads(); 718 } 719 } 720 else { 721 p = pubService; 722 } 723 724 if (p && typeof p.refresh === 'function') { 725 p.refresh(); 726 } 727 728 $(document).trigger('theiaPostSlider.refreshAds'); 729 } 730 } 731 } 732 }; 733 734 // Update the title text. 735 me.updateTitleText = function () { 736 var shortCodeTitle = me.slides[me.currentSlide].shortCodeTitle; 737 if (!shortCodeTitle) { 738 shortCodeTitle = '<span class="_helper">' + me.options['helperText'] + '</span>'; 739 } 740 for (i = 0; i < me.navEl.length; i++) { 741 me.navEl[i].title.html(shortCodeTitle); 742 } 743 }; 744 745 // Update the navigation bar's text and buttons. 746 me.updateNavigationBars = function () { 747 for (var i = 0; i < me.navEl.length; i++) { 748 var navEl = me.navEl[i]; 749 var navText; 750 if (me.numberOfSlides == 1) { 751 navText = ''; 752 } 753 else { 754 navText = me.options.navText; 755 navText = navText.replace('%{currentSlide}', me.currentSlide + 1); 756 navText = navText.replace('%{totalSlides}', me.numberOfSlides); 757 } 758 navEl.text.html(navText); 759 760 // Set number class. 761 navEl.container.addClass('_slide_number_' + me.currentSlide); 762 763 // Set first and last classes. 764 navEl.container.removeClass('_first_slide _last_slide _middle_slide'); 765 if (me.currentSlide === 0) { 766 navEl.container.addClass('_first_slide'); 767 } 768 else if (me.currentSlide === me.numberOfSlides - 1) { 769 navEl.container.addClass('_last_slide'); 770 } 771 else { 772 navEl.container.addClass('_middle_slide'); 773 } 774 775 // Update buttons. 776 me.updateNavigationBarButton(navEl, false); 777 me.updateNavigationBarButton(navEl, true); 778 } 779 }; 780 781 // Update a button from a navigation bar. 782 me.updateNavigationBarButton = function (navEl, direction) { 783 var width, 784 html1 = '', 785 html2 = '', 786 html3 = '', 787 href, 788 directionName = direction ? 'next' : 'prev', 789 buttonEl = navEl[directionName]; 790 791 if (me.options.themeType == 'font') { 792 width = 0; 793 html2 = me.options[directionName + 'FontIcon']; 794 795 if (direction == false) { 796 if (me.options.prevText_post) { 797 if (me.currentSlide == 0) { 798 html3 = me.options.prevText_post; 799 } else { 800 html3 = me.options.prevText; 801 } 802 } else { 803 html3 = me.options.prevText; 804 } 805 } else { 806 if (me.options.nextText_post) { 807 if (me.currentSlide == me.numberOfSlides - 1) { 808 html1 = me.options.nextText_post; 809 } else { 810 html1 = me.options.nextText; 811 } 812 } else { 813 html1 = me.options.nextText; 814 } 815 } 816 } else { 817 width = me.options.buttonWidth; 818 819 if ( 820 (direction == false && me.options.prevPost && me.currentSlide == 0) || 821 (direction == true && me.options.nextPost && me.currentSlide == me.numberOfSlides - 1) 822 ) { 823 html2 = me.options[directionName + 'Text_post']; 824 href = direction ? me.options.nextPost : me.options.prevPost; 825 } 826 else { 827 html2 = me.options[directionName + 'Text']; 828 } 829 } 830 831 // Set link. 832 { 833 var jumpToSlide = null; 834 if (direction == false && me.options.loopSlides && me.currentSlide == 0) { 835 jumpToSlide = me.numberOfSlides - 1; 836 } 837 else if (direction == true && me.options.loopSlides && me.currentSlide == me.numberOfSlides - 1) { 838 jumpToSlide = 0; 839 } 840 else if ( 841 (direction == false && me.options.prevPost && me.currentSlide == 0) || 842 (direction == true && me.options.nextPost && me.currentSlide == me.numberOfSlides - 1) 843 ) { 844 buttonEl.addClass('_another_post'); 845 href = direction ? me.options.nextPost : me.options.prevPost; 846 } else { 847 buttonEl.removeClass('_another_post'); 848 jumpToSlide = me.currentSlide + (direction ? 1 : -1); 849 } 850 851 if (jumpToSlide !== null) { 852 if (me.needToRefreshPage()) { 853 var slide = me.slides[jumpToSlide]; 854 if (slide) { 855 href = slide.permalink; 856 } 857 } 858 else { 859 href = '#'; 860 } 861 } 862 } 863 864 buttonEl.find('._1').html(html1); 865 buttonEl.find('._2') 866 .css('width', width > 0 ? width : '') 867 .html(html2); 868 buttonEl.find('._3').html(html3); 869 870 // Disable or enable 871 if ( 872 (direction == false && me.options.prevPost == null && !me.options.loopSlides && me.currentSlide == 0) || 873 (direction == true && me.options.nextPost == null && !me.options.loopSlides && me.currentSlide == me.numberOfSlides - 1) 874 ) { 875 buttonEl.addClass('_disabled'); 876 href = '#'; 877 } 878 else { 879 buttonEl.removeClass('_disabled'); 880 } 881 882 buttonEl.attr('href', href); 883 }; 884 885 // Handler for previous and next buttons. 886 me.onNavClick = function (that, direction, event) { 887 var $that = $(that); 888 889 if (typeof $that.attr('href') === 'undefined') { 890 return; 891 } 892 893 // Jump to another page. 894 // Some 3rd party plugins misbehave and turn the '#' into '', namely https://github.com/medialize/URI.js with "Blackout Image Gallery". 895 if ($that.attr('href') != '#' && $that.attr('href') != '') { 896 me.showLoading(); 897 me.saveScrollTop(); 898 return; 899 } 900 901 if (direction == 'prev') {
902 me.setPrev(); 903 } else { 904 me.setNext(); 905 } 906 907 $that.focus(); 908 if (event) { 909 event.preventDefault(); 910 } 911 }; 912 913 me.isHtml5StorageAvailable = function () { 914 try { 915 return 'localStorage' in window && window['localStorage'] !== null; 916 } catch (e) { 917 return false; 918 } 919 }; 920 921 me.saveScrollTop = function () { 922 if (!me.options.scrollAfterRefresh) { 923 return; 924 } 925 926 if (!me.isHtml5StorageAvailable) { 927 return; 928 } 929 930 localStorage.setItem('scrollTop', JSON.stringify({ 931 postId: me.postId, 932 scrollTop: $(window).scrollTop() 933 })); 934 }; 935 936 me.loadScrollTop = function () { 937 if (!me.options.scrollAfterRefresh) { 938 return; 939 } 940 941 if (!me.isHtml5StorageAvailable) { 942 return; 943 } 944 945 var data = JSON.parse(localStorage.getItem('scrollTop')); 946 if (data && data.postId == me.postId) { 947 var scrollTop = Math.min(data.scrollTop, me.slideContainer.offset().top); 948 $(window).scrollTop(scrollTop); 949 } 950 951 localStorage.removeItem('scrollTop'); 952 }; 953 954 // Go to the previous slide. 955 me.setPrev = function () { 956 if (me.currentSlide == 0) { 957 if (me.options.loopSlides) { 958 me.setSlide(me.numberOfSlides - 1); 959 } 960 else if (me.options.prevPost) { 961 me.showPost(me.options.prevPost); 962 } 963 } 964 else { 965 me.setSlide(me.currentSlide - 1); 966 } 967 }; 968 969 // Go to the next slide. 970 me.setNext = function () { 971 if (me.currentSlide == me.numberOfSlides - 1) { 972 if (me.options.loopSlides) { 973 me.setSlide(0); 974 } 975 else if (me.options.nextPost) { 976 me.showPost(me.options.nextPost); 977 } 978 } 979 else { 980 me.setSlide(me.currentSlide + 1); 981 } 982 }; 983 984 // Go to another post. This method will be called when navigating using the keyboard shortcuts. 985 me.showPost = function (postUrl) { 986 document.location = postUrl; 987 }; 988 989 // Set the transition properties (used in Live Preview). 990 me.setTransition = function (options) { 991 var defaults = { 992 'effect': me.options.transitionEffect, 993 'speed': me.options.transitionSpeed 994 }; 995 options = $.extend(defaults, options); 996 me.options.transitionEffect = options.effect; 997 me.options.transitionSpeed = options.speed; 998 }; 999 1000 // Set the navigation bar's text template (used in Live Preview). 1001 me.setNavText = function (text) { 1002 me.options.navText = text; 1003 me.updateNavigationBars(); 1004 }; 1005 1006 // Set the title for all slides (used in Live Preview). 1007 me.setTitleText = function (text) { 1008 for (i = 0; i < me.slides.length; i++) { 1009 me.slides[i].shortCodeTitle = ''; 1010 } 1011 me.options.helperText = text; 1012 me.updateTitleText(); 1013 }; 1014 1015 me.showLoading = function () { 1016 me.isLoading = true; 1017 for (i = 0; i < me.navEl.length; i++) { 1018 me.navEl[i].container 1019 .append($('<div class="_loading"></div>')) 1020 .find('._buttons > a').addClass('_disabled'); 1021 } 1022 }; 1023 1024 me.hideLoading = function () { 1025 me.isLoading = false; 1026 for (i = 0; i < me.navEl.length; i++) { 1027 me.navEl[i].container.find('._loading').remove(); 1028 } 1029 me.updateNavigationBars(); 1030 }; 1031 1032 me.needToRefreshPage = function () { 1033 return ( 1034 me.currentSlide !== null && 1035 me.options.refreshAds && 1036 me.slidesSinceLastAdRefresh + 1 >= me.options.refreshAdsEveryNSlides && 1037 me.options.adRefreshingMechanism == 'page' 1038 ); 1039 }; 1040 1041 // Initialize the slider.
1042 me.init(); 1043 1044 return me; 1045};
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.