Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
   <dl>
                    <dt class="sticky">A</dt>
                    <dd>Andrew W.K.</dd>
                    <dd>Apparat</dd>
                    <dd>Arcade Fire</dd>
                    <dd>At The Drive-In</dd>
                    <dd>Aziz Ansari</dd>
                </dl>
                <dl>
                    <dt class="sticky">B</dt>
                    <dd>Battles</dd>
                    <dd>Biz Markie</dd>
                    <dd>The Black Keys</dd>
                    <dd>Blakroc</dd>
                    <dd>Broken Social Scene</dd>
                </dl>
                <dl>
                    <dt class="sticky">C</dt>
                    <dd>Chromeo</dd>
                    <dd>Common</dd>
                    <dd>Converge</dd>
                    <dd>Crystal Castles</dd>
                    <dd>Cursive</dd>
                </dl>
                <dl>
                    <dt class="sticky">D</dt>
                    <dd>Daft Punk</dd>
                    <dd>David Bazan</dd>
                    <dd>Death from Above 1979</dd>
                    <dd>Delorean</dd>
                </dl>
                <dl>
                    <dt class="sticky">E</dt>
                    <dd>Explosions In The Sky</dd>
                </dl>
                <dl>
                    <dt class="sticky">F</dt>
                    <dd>Fear Before The March Of Flames</dd>
                    <dd>The Fire Theft</dd>
                    <dd>Flight of the Conchords</dd>
                    <dd>Foo Fighters</dd>
                </dl>
                <dl>
                    <dt class="sticky">G</dt>
                    <dd>The Get Up Kids</dd>
                    <dd>Girl Talk</dd>
                    <dd>godspeed you! black emperor</dd>
                    <dd>Guns N' Roses</dd>
                </dl>
</body>
</html>
 
/*!
 * Stickyfill -- `position: sticky` polyfill
 * v. 1.1.3 | https://github.com/wilddeer/stickyfill
 * Copyright Oleg Korsunsky | http://wd.dizaina.net/
 *
 * MIT License
 */
(function(doc, win) {
    var watchArray = [],
        scroll,
        initialized = false,
        html = doc.documentElement,
        noop = function() {},
        checkTimer,
        //visibility API strings
        hiddenPropertyName = 'hidden',
        visibilityChangeEventName = 'visibilitychange';
    //fallback to prefixed names in old webkit browsers
    if (doc.webkitHidden !== undefined) {
        hiddenPropertyName = 'webkitHidden';
        visibilityChangeEventName = 'webkitvisibilitychange';
    }
    //test getComputedStyle
    if (!win.getComputedStyle) {
        seppuku();
    }
    //test for native support
    var prefixes = ['', '-webkit-', '-moz-', '-ms-'],
        block = document.createElement('div');
    for (var i = prefixes.length - 1; i >= 0; i--) {
        try {
            block.style.position = prefixes[i] + 'sticky';
        }
        catch(e) {}
        if (block.style.position != '') {
            seppuku();
        }
    }
    updateScrollPos();
    //commit seppuku!
    function seppuku() {
        init = add = rebuild = pause = stop = kill = noop;
    }
    function mergeObjects(targetObj, sourceObject) {
        for (var key in sourceObject) {
            if (sourceObject.hasOwnProperty(key)) {
                targetObj[key] = sourceObject[key];
            }
        }
    }
    function parseNumeric(val) {
        return parseFloat(val) || 0;
    }
    function updateScrollPos() {
        scroll = {
            top: win.pageYOffset,
            left: win.pageXOffset
        };
    }
    function onScroll() {
        if (win.pageXOffset != scroll.left) {
            updateScrollPos();
            rebuild();
            return;
        }
        
        if (win.pageYOffset != scroll.top) {
            updateScrollPos();
            recalcAllPos();
        }
    }
    //fixes flickering
    function onWheel(event) {
        setTimeout(function() {
            if (win.pageYOffset != scroll.top) {
                scroll.top = win.pageYOffset;
                recalcAllPos();
            }
        }, 0);
    }
    function recalcAllPos() {
        for (var i = watchArray.length - 1; i >= 0; i--) {
            recalcElementPos(watchArray[i]);
        }
    }
    function recalcElementPos(el) {
        if (!el.inited) return;
        var currentMode = (scroll.top <= el.limit.start? 0: scroll.top >= el.limit.end? 2: 1);
        if (el.mode != currentMode) {
            switchElementMode(el, currentMode);
        }
    }
    //checks whether stickies start or stop positions have changed
    function fastCheck() {
        for (var i = watchArray.length - 1; i >= 0; i--) {
            if (!watchArray[i].inited) continue;
            var deltaTop = Math.abs(getDocOffsetTop(watchArray[i].clone) - watchArray[i].docOffsetTop),
                deltaHeight = Math.abs(watchArray[i].parent.node.offsetHeight - watchArray[i].parent.height);
            if (deltaTop >= 2 || deltaHeight >= 2) return false;
        }
        return true;
    }
    function initElement(el) {
        if (isNaN(parseFloat(el.computed.top)) || el.isCell || el.computed.display == 'none') return;
        el.inited = true;
        if (!el.clone) clone(el);
        if (el.parent.computed.position != 'absolute' &&
            el.parent.computed.position != 'relative') el.parent.node.style.position = 'relative';
        recalcElementPos(el);
        el.parent.height = el.parent.node.offsetHeight;
        el.docOffsetTop = getDocOffsetTop(el.clone);
    }
    function deinitElement(el) {
        var deinitParent = true;
        el.clone && killClone(el);
        mergeObjects(el.node.style, el.css);
        //check whether element's parent is used by other stickies
        for (var i = watchArray.length - 1; i >= 0; i--) {
            if (watchArray[i].node !== el.node && watchArray[i].parent.node === el.parent.node) {
                deinitParent = false;
                break;
            }
        };
        if (deinitParent) el.parent.node.style.position = el.parent.css.position;
        el.mode = -1;
    }
    function initAll() {
        for (var i = watchArray.length - 1; i >= 0; i--) {
            initElement(watchArray[i]);
        }
    }
    function deinitAll() {
        for (var i = watchArray.length - 1; i >= 0; i--) {
            deinitElement(watchArray[i]);
        }
    }
    function switchElementMode(el, mode) {
        var nodeStyle = el.node.style;
        switch (mode) {
            case 0:
                nodeStyle.position = 'absolute';
                nodeStyle.left = el.offset.left + 'px';
                nodeStyle.right = el.offset.right + 'px';
                nodeStyle.top = el.offset.top + 'px';
                nodeStyle.bottom = 'auto';
                nodeStyle.width = 'auto';
                nodeStyle.marginLeft = 0;
                nodeStyle.marginRight = 0;
                nodeStyle.marginTop = 0;
                break;
            case 1:
                nodeStyle.position = 'fixed';
                nodeStyle.left = el.box.left + 'px';
                nodeStyle.right = el.box.right + 'px';
                nodeStyle.top = el.css.top;
                nodeStyle.bottom = 'auto';
                nodeStyle.width = 'auto';
                nodeStyle.marginLeft = 0;
                nodeStyle.marginRight = 0;
                nodeStyle.marginTop = 0;
                break;
            case 2:
                nodeStyle.position = 'absolute';
                nodeStyle.left = el.offset.left + 'px';
                nodeStyle.right = el.offset.right + 'px';
                nodeStyle.top = 'auto';
                nodeStyle.bottom = 0;
                nodeStyle.width = 'auto';
                nodeStyle.marginLeft = 0;
                nodeStyle.marginRight = 0;
                break;
        }
        el.mode = mode;
    }
    function clone(el) {
        el.clone = document.createElement('div');
        var refElement = el.node.nextSibling || el.node,
            cloneStyle = el.clone.style;
        cloneStyle.height = el.height + 'px';
        cloneStyle.width = el.width + 'px';
        cloneStyle.marginTop = el.computed.marginTop;
        cloneStyle.marginBottom = el.computed.marginBottom;
        cloneStyle.marginLeft = el.computed.marginLeft;
        cloneStyle.marginRight = el.computed.marginRight;
        cloneStyle.padding = cloneStyle.border = cloneStyle.borderSpacing = 0;
        cloneStyle.fontSize = '1em';
        cloneStyle.position = 'static';
        cloneStyle.cssFloat = el.computed.cssFloat;
        el.node.parentNode.insertBefore(el.clone, refElement);
    }
    function killClone(el) {
        el.clone.parentNode.removeChild(el.clone);
        el.clone = undefined;
    }
    function getElementParams(node) {
        var computedStyle = getComputedStyle(node),
            parentNode = node.parentNode,
            parentComputedStyle = getComputedStyle(parentNode),
            cachedPosition = node.style.position;
        node.style.position = 'relative';
        var computed = {
                top: computedStyle.top,
                marginTop: computedStyle.marginTop,
                marginBottom: computedStyle.marginBottom,
                marginLeft: computedStyle.marginLeft,
                marginRight: computedStyle.marginRight,
                cssFloat: computedStyle.cssFloat,
                display: computedStyle.display
            },
            numeric = {
                top: parseNumeric(computedStyle.top),
                marginBottom: parseNumeric(computedStyle.marginBottom),
                paddingLeft: parseNumeric(computedStyle.paddingLeft),
                paddingRight: parseNumeric(computedStyle.paddingRight),
                borderLeftWidth: parseNumeric(computedStyle.borderLeftWidth),
                borderRightWidth: parseNumeric(computedStyle.borderRightWidth)
            };
        node.style.position = cachedPosition;
        var css = {
                position: node.style.position,
                top: node.style.top,
                bottom: node.style.bottom,
                left: node.style.left,
                right: node.style.right,
                width: node.style.width,
                marginTop: node.style.marginTop,
                marginLeft: node.style.marginLeft,
                marginRight: node.style.marginRight
            },
            nodeOffset = getElementOffset(node),
            parentOffset = getElementOffset(parentNode),
            
            parent = {
                node: parentNode,
                css: {
                    position: parentNode.style.position
                },
                computed: {
                    position: parentComputedStyle.position
                },
                numeric: {
                    borderLeftWidth: parseNumeric(parentComputedStyle.borderLeftWidth),
                    borderRightWidth: parseNumeric(parentComputedStyle.borderRightWidth),
                    borderTopWidth: parseNumeric(parentComputedStyle.borderTopWidth),
                    borderBottomWidth: parseNumeric(parentComputedStyle.borderBottomWidth)
                }
            },
            el = {
                node: node,
                box: {
                    left: nodeOffset.win.left,
                    right: html.clientWidth - nodeOffset.win.right
                },
                offset: {
                    top: nodeOffset.win.top - parentOffset.win.top - parent.numeric.borderTopWidth,
                    left: nodeOffset.win.left - parentOffset.win.left - parent.numeric.borderLeftWidth,
                    right: -nodeOffset.win.right + parentOffset.win.right - parent.numeric.borderRightWidth
                },
                css: css,
                isCell: computedStyle.display == 'table-cell',
                computed: computed,
                numeric: numeric,
                width: nodeOffset.win.right - nodeOffset.win.left,
                height: nodeOffset.win.bottom - nodeOffset.win.top,
                mode: -1,
                inited: false,
                parent: parent,
                limit: {
                    start: nodeOffset.doc.top - numeric.top,
                    end: parentOffset.doc.top + parentNode.offsetHeight - parent.numeric.borderBottomWidth -
                        node.offsetHeight - numeric.top - numeric.marginBottom
                }
            };
        return el;
    }
    function getDocOffsetTop(node) {
        var docOffsetTop = 0;
        while (node) {
            docOffsetTop += node.offsetTop;
            node = node.offsetParent;
        }
        return docOffsetTop;
    }
    function getElementOffset(node) {
        var box = node.getBoundingClientRect();
            return {
                doc: {
                    top: box.top + win.pageYOffset,
                    left: box.left + win.pageXOffset
                },
                win: box
            };
    }
    function startFastCheckTimer() {
        checkTimer = setInterval(function() {
            !fastCheck() && rebuild();
        }, 500);
    }
    function stopFastCheckTimer() {
        clearInterval(checkTimer);
    }
    function handlePageVisibilityChange() {
        if (!initialized) return;
        if (document[hiddenPropertyName]) {
            stopFastCheckTimer();
        }
        else {
            startFastCheckTimer();
        }
    }
    function init() {
        if (initialized) return;
        updateScrollPos();
        initAll();
        win.addEventListener('scroll', onScroll);
        win.addEventListener('wheel', onWheel);
        //watch for width changes
        win.addEventListener('resize', rebuild);
        win.addEventListener('orientationchange', rebuild);
        //watch for page visibility
        doc.addEventListener(visibilityChangeEventName, handlePageVisibilityChange);
        startFastCheckTimer();
        initialized = true;
    }
    function rebuild() {
        if (!initialized) return;
        deinitAll();
        
        for (var i = watchArray.length - 1; i >= 0; i--) {
            watchArray[i] = getElementParams(watchArray[i].node);
        }
        
        initAll();
    }
    function pause() {
        win.removeEventListener('scroll', onScroll);
        win.removeEventListener('wheel', onWheel);
        win.removeEventListener('resize', rebuild);
        win.removeEventListener('orientationchange', rebuild);
        doc.removeEventListener(visibilityChangeEventName, handlePageVisibilityChange);
        stopFastCheckTimer();
        initialized = false;
    }
    function stop() {
        pause();
        deinitAll(); 
    }
    function kill() {
        stop();
        //empty the array without loosing the references,
        //the most performant method according to http://jsperf.com/empty-javascript-array
        while (watchArray.length) {
            watchArray.pop();
        }
    }
    function add(node) {
        //check if Stickyfill is already applied to the node
        for (var i = watchArray.length - 1; i >= 0; i--) {
            if (watchArray[i].node === node) return;
        };
        var el = getElementParams(node);
        watchArray.push(el);
        if (!initialized) {
            init();
        }
        else {
            initElement(el);
        }
    }
    function remove(node) {
        for (var i = watchArray.length - 1; i >= 0; i--) {
            if (watchArray[i].node === node) {
                deinitElement(watchArray[i]);
                watchArray.splice(i, 1);
            }
        };
    }
    //expose Stickyfill
    win.Stickyfill = {
        stickies: watchArray,
        add: add,
        remove: remove,
        init: init,
        rebuild: rebuild,
        pause: pause,
        stop: stop,
        kill: kill
    };
})(document, window);
//if jQuery is available -- create a plugin
if (window.jQuery) {
    (function($) {
        $.fn.Stickyfill = function(options) {
            this.each(function() {
                Stickyfill.add(this);
            });
            return this;
        };
    })(window.jQuery);
}
var stickyElements = document.getElementsByClassName('sticky');
for (var i = stickyElements.length - 1; i >= 0; i--) {
    Stickyfill.add(stickyElements[i]);
}
Output

This bin was created anonymously and its free preview time has expired (learn why). — Get a free unrestricted account

Dismiss x
public
Bin info
anonymouspro
0viewers