$(function() { // ************************** // // Section Jump functionality // // ************************** // var jumping = false; // Adjust dropdown state $('.section-jump').on('click', function() { $('.section-jump-overlay').show(); }) $('.jump-arrow, .section-jump-label').on('click', function() { if ($('.section-jump-state').prop('checked')) { $('.section-jump-label').show(); $('.section-jump-state').prop('checked', false); } else { $('.section-jump-label').hide(); $('.section-jump-state').prop('checked', true); } }) $('.section-jump-overlay, .section-jump-dropdown a').on('click', function() { $('.section-jump-state').prop('checked', false); $('.section-jump-overlay').hide(); }) var headings = $('.product-section h1, .product-section h2:not([data-nojump])'); $('.section-jump .section-jump-dropdown').on('click', 'li', function(e) { e.preventDefault(); if (!jumping) { jumping = true; $('.section-jump-label').show(); $('.section-jump-dropdown .selected').removeClass('selected'); $(this).parent().addClass('selected'); $('.section-jump-label span').text($(this).text()); $('.section-jump-state').prop('checked', false); // Scroll animations var sectionJumpTo = $(this).index(); var sectionJumpPos = headings.eq(sectionJumpTo).offset().top; // Adjust for nav elements sectionJumpPos -= 190; // Disabled until "menu position adjusted on scroll" feature is reimplemented // sectionJumpPos -= 88; $('html, body').animate({ scrollTop: sectionJumpPos }, 1000, function() { jumping = false; $('.section-jump-overlay').hide(); }); } }) // Get page co-ordinates of each title and add to array if ($('.section-jump').length > 0) { headings.each(function(index) { $(this).attr('data-section-jump-id', index); // Dont include element with data-nojump if ($(this).is('[data-nojump]')) { return; } else { $('.section-jump-dropdown').append('
  • ' + $(this).text() + '
  • '); var el = $(this); var scrollDirection; // Future proof for menuUp functionality var windowPosOffset; var adjustPosOffset; if ($('body').hasClass('menuUp')) { windowPosOffset = $('.gn-sub').height() + 40; } else { windowPosOffset = $('.global-nav').height() + 40; } // Scroll direction requires different offsets $(this).waypoint({ handler: function(direction) { if (direction === 'down' && !jumping) { $('.section-jump-label span').text(el.text()); $('.section-jump-dropdown li.selected').removeClass('selected'); $('.section-jump-dropdown li').eq(index).addClass('selected'); } }, offset: windowPosOffset }).waypoint({ handler: function(direction) { if (direction === 'up' && !jumping) { $('.section-jump-label span').text(el.text()); $('.section-jump-dropdown li.selected').removeClass('selected'); $('.section-jump-dropdown li').eq(index).addClass('selected'); } }, offset: function() { return 130; } }); } }) $('.section-jump-dropdown li:first-child').addClass('selected'); } // Section Jump fade transitions $(window).on('resize', function() { if (window.innerWidth <= 560) { $('.section-jump').show(); } else { $('.section-jump').hide(); } }) var timeOut; $(window).on('touchstart, click', function(e) { if (window.innerWidth <= 560) { $('.section-jump').fadeIn(); clearTimeout(timeOut); fadeDropdown(); } }) function fadeDropdown() { if (window.innerWidth <= 560 && window.pageYOffset != 0) { timeOut = setTimeout(function() { if (!$('.section-jump-state').prop('checked') && window.pageYOffset != 0) { $('.section-jump').fadeOut(); } }, 2000); }; } // While scrolling activate and disable interval // When scrolling stops - interval is active var sectionJumped = false; $(window).scroll(function() { if (window.innerWidth <= 560) { // updatePos(); $('.section-jump').fadeIn(); clearTimeout($.data(this, 'scrollTimer')); $.data(this, 'scrollTimer', setTimeout(function() { if (!$('.section-jump-state').prop('checked') && window.pageYOffset != 0) { $('.section-jump').fadeOut(); sectionJumped = false; } }, 2000)); }; }); /** * Disabled until "menu position adjusted on scroll" feature is reimplemented */ // Hide Global Nav on Scroll Down // Reveal Global Nav on Scroll Up // var setPos; // var startPos = $(window).scrollTop(); // var posArray = []; // function updatePos() { // setPos = setInterval(function(){ // startPos = $(window).scrollTop(); // posArray.push(startPos); // if (posArray.length > 3) { // posArray.splice(0, 1); // } // if (posArray[2] > posArray[0] && window.pageYOffset > 85 || sectionJumped === true) { // $('body').addClass('menuUp'); // } // if (posArray[2] < posArray[0] || window.pageYOffset < 85 && sectionJumped === false) { // $('body').removeClass('menuUp'); // } // }, 33); // } // $('.section-jump-dropdown a, .models-menu a').on('click', function(){ // sectionJumped = true; // }) }); /** * A helper function to dynamically select images on a page. * * To allow for a greater flexibility a "data-selector-id" and a "data-selectable-id" attribute * should be used respectively on the buttons and on the dynamicly controlled content. * * Example: *
    *
    * * * * *
    *
    *

    AAA

    *

    BBB

    *

    CCC

    *

    DDD

    *
    *
    * * makeImgSelector(".my-custom-selector-class", "my-custom-image-container-class", "active") * * @param {String} buttonsContainerSelector A CSS selector used to find the buttons triggering the image change. (ie: ".my-control-class") * @param {String} imageContainerSelector A CSS selector used to find the image container. (ie: ".my-section my-container") * @param {String} activeClass (Optional) The class used to represent the active state (ie/default: "active") * @param {Bool} dissolve (Optional) Enable animation * @param {Bool} autoplay (Optional) Enable automatic switching only availabe if "dissolve" is true */ var makeImgSelector = function(buttonsContainerSelector, imagesContainerSelector, activeClass, dissolve, autoplay) { activeClass = activeClass || 'active'; var multipleSelectables = false; var $buttonsContainer = $(buttonsContainerSelector); var $imageContainer = $(imagesContainerSelector); var $buttons = $buttonsContainer.find("[data-selector-id]"); var $imageSelector = $imageContainer.find("[data-selectable-id]"); var isAnimationPlaying = false; var defaultTimer = 3000; if ($buttons.length === 0) { console.error('No nodes with "data-selector-id" attribute found.'); } if($.isArray(imagesContainerSelector)) { multipleSelectables = true; var $imagesContainer = $(imagesContainerSelector); var $images = []; for(i = 0; i < imagesContainerSelector.length; i++) { $(imagesContainerSelector[i]).each(function() { $(this).find("[data-selectable-id]").each(function(){ $images.push(this); }); }) } } else { var $imagesContainer = $(imagesContainerSelector); var $images = $imagesContainer.find("[data-selectable-id]"); if ($images.length === 0) { console.error('No nodes with "data-selectable-id" attribute found.'); } } if (autoplay && dissolve) { var timer = setInterval(function () { $($imageSelector).css({'zIndex' : '1', 'position' : 'absolute'}) var activeButton = $buttons.filter("." + activeClass); var activeImage = $imageSelector.filter("." + activeClass); var activeButtonIndex = activeButton.index(); var buttonLength = $buttons.length; var nextId = activeButtonIndex+1; if(nextId == buttonLength-1) { nextId = 0; $(activeImage).removeClass(activeClass).css({'zIndex' : '1'}) $($imageSelector[activeButtonIndex]).addClass(activeClass) $($imageSelector[nextId]).removeClass(activeClass) } $(activeImage).addClass(activeClass).css({'zIndex' : '2'}) // console.log("next id = " + nextId) // console.log("active ID = " + activeButtonIndex) $($imageSelector[nextId]).css({'opacity' : 0, 'zIndex' : '3', 'position' : 'relative'}).animate({ 'opacity': 1 }, defaultTimer, function() { $($imageSelector[nextId]).addClass(activeClass); $(activeImage).removeClass(activeClass); activeButton.removeClass(activeClass); $($buttons[nextId]).addClass(activeClass); }); }, defaultTimer); } // Listen for click events $buttons.on("click", function(e) { e.preventDefault(); clearInterval(timer); if (!isAnimationPlaying && !$(this).hasClass(activeClass)) { $this = $(this); // Remove active class on the currently active button $buttons.filter("." + activeClass).removeClass(activeClass); // Add active class on new active button $this.addClass(activeClass); if(multipleSelectables) { var $prevImage = []; var $nextImage = []; for(i = 0; i < $images.length; i++) { if($($images[i]).hasClass(activeClass)) { $prevImage.push($images[i]) } } for(i = 0; i < $imagesContainer.length; i++) { $nextImage.push($($imagesContainer[i]).find("[data-selectable-id=" + $this.get(0).dataset.selectorId + "]")); } } else { var $prevImage = $images.filter('.' + activeClass); var $nextImage = $imagesContainer.find("[data-selectable-id=" + $this.get(0).dataset.selectorId + "]"); } if (dissolve) { isAnimationPlaying = true; if(multipleSelectables) { for(i = 0; i < $prevImage.length; i++) { $($prevImage[i]).css('zIndex', $($prevImage[i]).css('zIndex') - 1); } for(i = 0; i < $nextImage.length; i++) { $($nextImage[i]).css('opacity', 0); // Add active class on new active image $($nextImage[i]).css('zIndex', '2').animate({ 'opacity': 1 }, 250, function() { $($nextImage[i]).addClass(activeClass); for(i = 0; i < $prevImage.length; i++) { isAnimationPlaying = false; $($prevImage).css('zIndex', ''); // Remove active class on the currently active image $($prevImage).removeClass(activeClass); } }); } } else { // Move all images to bottom layer $imagesContainer.find('[data-selectable-id]').css('zIndex', 1); // Move the image to the middle layer $prevImage.css('zIndex', 2); // Move the image to the top and fade in // and add active class on new active image $nextImage.css({'zIndex': 3, 'opacity': 0}).animate({ 'opacity': 1 }, 1000, function() { isAnimationPlaying = false; $prevImage.css('zIndex', ''); $nextImage.addClass(activeClass); // Remove active class on the currently active image $prevImage.removeClass(activeClass); }); } } else { if(multipleSelectables) { for(i = 0; i < $prevImage.length; i++) { // Remove active class on the currently active image $($prevImage[i]).removeClass(activeClass); } for(i = 0; i < $nextImage.length; i++) { // Add active class on new active image $($nextImage[i]).addClass(activeClass); } } else { // Remove active class on the currently active image $prevImage.removeClass(activeClass); // Add active class on new active image $nextImage.addClass(activeClass); } } } }); }; // -------------------------------------------------- // Reveal Image - Slider // -------------------------------------------------- /** * A helper function to dynamically create an image slider * * To allow for a greater flexibility a "data-selector-id" and a "data-selectable-id" attribute * should be used respectively on the buttons and on the dynamicly controlled content. * * Example: *
    *
    * alt *
    * alt *
    * Drag *
    *
    * * makeImgSlider(".compare", "30%"); * * @param {String} sliderContainer A CSS selector used to find the container of the images overlaid on eachother * @param {String} initialReveal (Optional) A percentage value setting the initial amount the image is revealed */ var makeImgSlider = function(sliderContainer, initialReveal) { initialReveal = initialReveal || '50%'; var container = $(sliderContainer); var slider = container.find('.slider'); var reveal = container.find('.reveal'); var revealImg = reveal.children('img'); var startPos = container.offset().left; var totalWidth = container.width(); // Set initial reveal revealImg.width(totalWidth); reveal.css('width', initialReveal); slider.css('left', initialReveal); // Update values on resize $(window).on('resize', function() { startPos = container.offset().left; totalWidth = container.width(); revealImg.width(totalWidth); }) // Desktop functionality var clicking = false; slider.on('mousedown', function(e) { clicking = true; e.preventDefault(); }); container.on('mousemove', function(e) { if (clicking == false) { return; }; var revealWidth = ((e.clientX - startPos) / totalWidth) * 100; revealSlide(revealWidth); }); $(document).on('mouseup', function(e) { clicking = false; }); // Device functionality container.on('touchstart', function(e) { var revealWidth = ((e.originalEvent.touches[0].clientX - startPos) / totalWidth) * 100; revealSlide(revealWidth); }) container.on('touchmove', function(e) { var revealWidth = ((e.originalEvent.touches[0].clientX - startPos) / totalWidth) * 100; revealSlide(revealWidth); e.preventDefault(); }) // Reveal logic function revealSlide(value) { if (value < 0) { value = 0; } if (value > 100) { value = 100; } slider.css('left', value + '%'); container.find('.reveal').width(value + '%'); } }