Skip to content

Instantly share code, notes, and snippets.

@joshlevinson
Created September 2, 2015 20:35
Show Gist options
  • Save joshlevinson/c8f909d74ceb8f779b17 to your computer and use it in GitHub Desktop.
Save joshlevinson/c8f909d74ceb8f779b17 to your computer and use it in GitHub Desktop.

Revisions

  1. joshlevinson created this gist Sep 2, 2015.
    158 changes: 158 additions & 0 deletions fixed-block.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,158 @@
    (function () {
    define('redesign/ninemsn/portal/news/stickyElementController',['jquery', 'redesign/ninemsn/portal/news/helper'], function ($, helper) {

    var bufferY = 56; // Offset for fixed positioning

    var windowTop,
    startY,
    blockY,
    stopY,
    offset;

    // Methods
    var prepareFixedElements,
    updateFixedElements,
    applyStopped,
    applyFixed,
    applyDefault,
    updateBufferHeight,
    resetFixedElements,
    notDesktop;

    prepareFixedElements = function () {

    $('.js-fixed-block').each(function () {
    $(this).wrap('<div class="js-wrapper fixed-block-wrapper" style="position: relative"></div>');
    applyDefault($(this));
    });
    };

    updateFixedElements = function () {

    var $stopper;

    if ($(window).width() < 900) {
    resetFixedElements();
    } else {

    $('.js-fixed-block').each(function () {

    if ($(this).hasClass('fixed-disabled')) {
    applyDefault($(this));
    $(this).removeClass('fixed-disabled');
    }

    windowTop = $(window).scrollTop();
    startY = $(this).parent().offset().top;
    blockY = $(this).outerHeight();
    $stopper = $($(this).attr('data-stopper'));

    stopY = 9e9;

    if ($stopper.length) {
    stopY = ($stopper.offset().top - blockY - bufferY);
    }

    if (windowTop > stopY) {
    offset = (stopY - $(this).parent().offset().top + bufferY);
    applyStopped($(this), offset);
    } else if (windowTop > (startY - bufferY)) {
    applyFixed($(this));
    } else {
    applyDefault($(this));
    }

    });

    }
    };

    applyStopped = function (element, offset) {

    var y = element.outerHeight();

    if (offset < 0) offset = 0;

    element.css({
    'position': 'absolute',
    'top': offset + 'px'
    });

    updateBufferHeight(element.parent(), y);
    };

    applyFixed = function (element) {

    var y = element.outerHeight();

    element.css({
    'position': 'fixed',
    'top': bufferY + 'px',
    'width': element.parent().width() + 'px',
    'height': 'auto'
    });

    updateBufferHeight(element.parent(), y);
    };

    applyDefault = function (element) {

    // Default is the original block inside a wrapper to preserve
    // the space when the fixed block is removed from the flow.

    var y = element.outerHeight();
    var x = element.outerWidth();

    element.css({
    'position': 'absolute',
    'width': x + 'px',
    'top': 0
    });

    updateBufferHeight(element.parent(), y);
    };

    updateBufferHeight = function (element, y) {
    element.css({
    'height': y + 'px',
    'position': 'relative'
    });
    };

    resetFixedElements = function () {
    $('.js-fixed-block, .js-wrapper').attr('style', '');
    $('.js-wrapper, .js-fixed-block').addClass('fixed-disabled');
    };

    notDesktop = function () {
    return navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i);
    };

    return {
    init: function () {
    // Disabled for touch devices using user agent, as checking for touch events is unreliably buggy for windows 8 + chrome
    if (notDesktop()) {
    return false;
    }

    // We need to wait until the assets are loaded to determine the rendered height.
    prepareFixedElements();
    updateFixedElements();

    // We must listen to resize for responsiveness...
    $(window).resize(function () {
    updateFixedElements();
    });

    $(window).scroll(function () {
    updateFixedElements();
    });

    // check for loaded ads
    $('body').on('ad.loaded', function () {
    updateFixedElements();
    });
    }
    };
    });
    }).call(this);