the-riddle
clone your own copy | download snapshot

Snapshots | iceberg

Inside this repository

collapseFootnotes.js
application/javascript

Download raw (23.0 KB)

;(function (window, document) {
    'use strict';

    Node.prototype.insertAfter = function (node, referenceNode) {
        if (referenceNode.nextSibling) {
            return this.insertBefore(node, referenceNode.nextSibling);
        } else {
            return this.appendChild(node);
        }
    }

    function paragraphIndex (node) {
        var paragraphs = document.querySelectorAll('#main > p');
        for (var i = 0; i < paragraphs.length; i++) {
            if (paragraphs[i] == node) {
                return i;
            }
        }
    }

    /**
     * Expand footnote with number n
     */
    function expandFootnote (n) {
        var ftntSpan = document.querySelector('#inlinefn' + n),
            ftntRef = document.querySelector('#fnref' + n);
        
        if (ftntSpan && ftntRef) {
            ftntSpan.classList.add('expanded');
            ftntRef.classList.add('collapsed');
        }
    }

    /**
     * Collapse footnote with number n
     */
    function collapseFootnote (n) {
        var ftntSpan = document.querySelector('#inlinefn' + n),
            ftntRef = document.querySelector('#fnref' + n);
        
        if (ftntSpan && ftntRef) {
            ftntSpan.classList.add('expanded');
            ftntRef.classList.add('collapsed');
        }
    }

    /**
     * Toggle footnote with number n
     */
    function toggleFootnote (n) {
        var ftntSpan = document.querySelector('#inlinefn' + n),
            ftntRef = document.querySelector('#fnref' + n);
        
        if (ftntSpan && ftntRef) {
            ftntSpan.classList.add('expanded');
            ftntRef.classList.add('collapsed');
        }
    }

    function expandAllFootnotes () {
        forEachNode(".footnoteRef", function (node) {
            expandFootnote(parseInt(node.id.replace(/^\D+/g, '')))
        });
    }

    function collapseAllFootnotes () {
        forEachNode(".footnoteRef", function (node) {
            collapseFootnote(parseInt(node.id.replace(/^\D+/g, '')))
        })
    }

    var directionPattern = /{{(force-start|start|previous-note|previous|up-after-image:(?:[^}]+)|up-before-image:(?:[^}]+)|down-after-image:(?:[^}]+)|up|down|afterintro|end|no-float:(?:\w+)|block-end:(?:\w+)|refer-to-end:(?:[^:]+):(?:[^}]+))}}\s*/g;

    function hasDirection(node) {
        return directionPattern.test(node.innerText);
    }

    function getDirection(node) {
        var match =  directionPattern.exec(node.innerText);

        if (match) {
            return match[1];
        } 
        
        return '';
    }

    function clearDirection (node) {
        node.innerHTML = node.innerHTML.replace(directionPattern, '');
        return node;
    }

    // Footnotes as sections before p

    function blessFootnotes () {
        var refList = document.getElementsByClassName('footnoteRef');

        for (var i=0; i < refList.length; i++) {
            var ftntEl, ftntNumEl,
                ftntRef = refList[i],
                refId   = ftntRef.id,
                ftntNum = parseInt(refId.replace(/^\D+/g, '')),
                ftntId  = 'fn' + ftntNum,
                ftnt    = document.getElementById(ftntId);

            ftntEl = document.createElement('section');
            ftntEl.setAttribute('id', 'inlinefn' + ftntNum);
            ftntEl.className = 'inlineFootnote';
            
            ftntNumEl = document.createElement('span');
            ftntNumEl.classList.add('numberFootnote');
            ftntNumEl.appendChild(document.createTextNode(ftntNum));

            ftntEl.appendChild(ftntNumEl);

            for (var f=0; f < ftnt.children.length; f++) {
                ftntEl.appendChild(ftnt.children[f].cloneNode(true));
            }

            // Remove anchor at end of footnote
            var anchors = ftntEl.querySelectorAll('a');

            if (anchors.length > 0) {
                anchors[anchors.length-1].remove();
            }

            var pIndex = paragraphIndex(ftntRef.parentNode),
                wrapper = ftntRef.parentNode,
                container = wrapper.parentNode,
                direction = getDirection(ftntEl);
        
            while (container.getAttribute('id') != 'main') {
                container = container.parentNode;
            }

            ftntEl = clearDirection(ftntEl);
            
            if (direction.match(/^no-float:(\w+)$/)) {
                ftntEl.classList.add('no-float');
                var match = direction.match(/^no-float:(\w+)$/);
                direction = match[1];
            }

            if (direction.match(/^block-end:(\w+)$/)) {
                ftntEl.classList.add('block-end');
                var match = direction.match(/^block-end:(\w+)$/);
                direction = match[1];
            }

            if (direction.match(/refer-to-end:(.+):(.+):(.+)$/)) {
                var match = direction.match(/refer-to-end:(.+):(.+):(.+)$/);
                ftntEl.classList.add(match[3]);
                direction = match[2];

                var referralElement = document.createElement('span');
                referralElement.classList.add('inlineFootnote');

                var referralNumElNumEl = document.createElement('span');
                referralNumElNumEl.classList.add('numberFootnote');
                referralNumElNumEl.appendChild(document.createTextNode(ftntNum));

                referralElement.appendChild(referralNumElNumEl);
                referralElement.appendChild(document.createTextNode(' See the end of this section'));

                var insertionPoint = findInsertionPoint(wrapper.nextElementSibling, function (n) {return (!(n.classList.contains('inlineFootnote'))); }, 'down'); 

                if (insertionPoint) {
                    container.insertBefore(referralElement, insertionPoint);
                } else {
                    container.insertAfter(referralElement, wrapper);
                }
            }
            
            if (pIndex == 0) {
                if (direction == "down") {
                    var insertionPoint = findInsertionPoint(container.querySelector('#main > p:nth-of-type(2)').nextElementSibling, function (n) { return (!(n.classList.contains('inlineFootnote'))); }, 'down');
                    if (insertionPoint.classList.contains('big-break') && insertionPoint.previousElementSibling.tagName == 'P') {
                        ftntEl.classList.add('big-break');
                    }
                    container.insertBefore(ftntEl, insertionPoint);
                } else {
                    container.insertBefore(ftntEl, wrapper);
                }
            } else if (direction == 'force-start') {
                var insertionPoint = findInsertionPoint(container.querySelector('#main > p:nth-of-type(2)'), function (n) { return (!(n.classList.contains('inlineFootnote'))); }, 'up');
                container.insertBefore(ftntEl, insertionPoint);
            } else if (pIndex == 1 || direction == 'start') {
                var insertionPoint = findInsertionPoint(container.querySelector('#main > p:nth-of-type(2)').nextElementSibling, function (n) { return (!(n.classList.contains('inlineFootnote'))); }, 'down');
                if (insertionPoint.classList.contains('big-break') && insertionPoint.previousElementSibling.tagName == 'P') {
                    ftntEl.classList.add('big-break');
                }
                container.insertBefore(ftntEl, insertionPoint);
            }  else if (direction == 'previous-note') {
                var insertionPoint = findInsertionPoint(wrapper, function (n) { return (n.classList.contains('inlineFootnote')); }, 'up'); 

                if (insertionPoint) {
                    container.insertAfter(ftntEl, insertionPoint);
                } else {
                    container.insertBefore(ftntEl, wrapper)
                }
            } else if (direction.match(/^up-before-image:(.+)$/)) {
                var match = direction.match(/^up-before-image:(.+)$/);
                if (match) {
                    var imgNum = match[1];
                    var insertionPoint = findInsertionPoint(wrapper, function (n) { 
                        if (n.classList.contains('figure')) {
                            var figImg = n.querySelector('img');
                            return (figImg.getAttribute('alt').search(imgNum.replace(/\./, '\.')) > -1);
                        }
                        return false;
                    }, 'up');
                    if (insertionPoint) {
                        container.insertBefore(ftntEl, insertionPoint);
                    }    
                }   
            } else if (direction.match(/^up-after-image:(.+)$/)) {
                var match = direction.match(/^up-after-image:(.+)$/);
                if (match) {
                    var imgNum = match[1];
                    var insertionPoint = findInsertionPoint(wrapper, function (n) { 
                        if (n.classList.contains('figure')) {
                            var figImg = n.querySelector('img');
                            return (figImg.getAttribute('alt').search(imgNum.replace(/\./, '\.')) > -1);
                        }
                        return false;
                    }, 'up');
                    if (insertionPoint) {
                        container.insertAfter(ftntEl, insertionPoint);
                    }    
                }   
            } else if (direction.match(/^down-after-image:(.+)$/)) {
                var match = direction.match(/^down-after-image:(.+)$/);
                if (match) {
                    var imgNum = match[1];
                    var insertionPoint = findInsertionPoint(wrapper, function (n) { 
                        if (n.classList.contains('figure')) {
                            var figImg = n.querySelector('img');
                            return (figImg.getAttribute('alt').search(imgNum.replace(/\./, '\.')) > -1);
                        }
                        return false;
                    }, 'down');

                    if (insertionPoint) {
                        container.insertAfter(ftntEl, insertionPoint);
                    }    
                }   
            }  else if (direction == 'previous') {
                var insertionPoint = findInsertionPoint(wrapper, function (n) { return (n.classList.contains('figure') || n.classList.contains('inlineFootnote')); }, 'up'); 

                if (insertionPoint) {
                    container.insertAfter(ftntEl, insertionPoint);
                } else {
                    container.insertBefore(ftntEl, wrapper)
                }
            } else if (direction == 'down') {
                // Travel down DOM, to add element AFTER notes which were placed there before;
                var insertionPoint = findInsertionPoint(wrapper.nextElementSibling, function (n) {return (!(n.classList.contains('inlineFootnote'))); }, 'down'); 

                if (insertionPoint) {
                    if (insertionPoint.classList.contains('big-break') && !(insertionPoint.previousElementSibling.classList.contains('figure') || insertionPoint.previousElementSibling.classList.contains('inlineFootnote'))) {
                        ftntEl.classList.add('big-break');
                    }
                    container.insertBefore(ftntEl, insertionPoint);
                } else {
                    container.insertAfter(ftntEl, wrapper);
                }
            }  else if (direction == 'before-end') {
                var insertionPoint = findInsertionPoint(document.querySelector('.footnotes').previousElementSibling, function (n) {return (!(n.classList.contains('inlineFootnote') || n.classList.contains('figure'))); }, 'up');
                container.insertAfter(ftntEl, insertionPoint);
            } else if (direction == 'end') {
                // Travel down DOM, to add element AFTER notes which were placed there before;
                container.insertBefore(ftntEl, document.querySelector('.footnotes'));
            } else {
                var ftntRects = ftntRef.getClientRects(),
                    pRects = ftntRef.parentNode.getClientRects(),
                    ftntOffset = ftntRects[0].top - pRects[0].top;
                
                if (ftntOffset > pRects[0].height * .5) {
                    var insertionPoint = findInsertionPoint(wrapper, function (n) { return (!(n.classList.contains('inlineFootnote'))); }, 'down');
                    container.insertBefore(ftntEl, insertionPoint);
                } else {
                    var insertionPoint = wrapper; 
                    container.insertBefore(ftntEl, wrapper);
                }
            }
2
            if (insertionPoint && insertionPoint.classList.contains('big-break')) {
                ftntEl.classList.add('big-break');
            }
            
            // if (direction == 'down') {
            //     var insertionPoint = ftntRef.parentNode.nextElementSibling;
            //     ftntEl.classList.add('moved-down');
            //     while (insertionPoint.classList.contains('inlineFootnote')) {
            //         insertionPoint = insertionPoint.nextElementSibling;
            //     }
            //     ftntRef.parentNode.parentNode.insertBefore(ftntEl, insertionPoint);
            // } else if (direction == 'previous') {2
            //     ftntEl.classList.add('moved-up');
            //     ftntEl.classList.add('previous');
            //     var insertionPoint = ftntRef.parentNode.previousElementSibling;
            //     while (!insertionPoint.classList.contains('inlineFootnote')) {
            //         insertionPoint = insertionPoint.previousElementSibling;
            //     }
            //     ftntRef.parentNode.parentNode.insertAfter(ftntEl, insertionPoint);
            // } else {
            //     ftntEl.classList.add('moved-up');
            //     ftntRef.parentNode.parentNode.insertBefore(ftntEl, ftntRef.parentNode);
            // }
        }

        ftntRef.addEventListener('click', function (e) {
            e.preventDefault();
            toggleFootnote(parseInt(this.id.replace(/^\D+/g, '')));
        });
        
        ftntEl.addEventListener('click', function (e) {
            if (e.target.tagName != 'IMG') {
                toggleFootnote(parseInt(this.id.replace(/^\D+/g, '')));
            }
        });

        var ftntImgList = ftntEl.getElementsByTagName('img');

        for (var ii=0; ii < ftntImgList.length; ii++) {
            ftntImgList[ii].classList.add('expanded');
        }

        var footnoteContainers = document.getElementsByClassName('footnotes');

        for (var i=0; i < footnoteContainers.length; i++) {
            footnoteContainers[i].classList.add('hidden');
        }
    }

    /**
     * Apply callback on all nodes found with querySelector
     * q string querySelector
     * callback function callback
     */
    function forEachNode (q, callback) {
        var nodes = document.querySelectorAll(q);

        for (var i=0; i < nodes.length; i++) {
            callback(nodes[i]);
        }
    }

    function toggle (node) {
        node.classList.toggle('expanded');
    }

    function expand (node) {
        node.classList.add('expanded');
    }

    function collapse(node) {
        node.classList.remove('expanded');
    }

    function validInsertionPoint (node) {
        if (node.tagName == 'SPAN') {
            return false;
        } if (node.classList.contains('inlineFootnote')) {
            return false;
        }

        return true;
    }

    function testInsertionPoint (node, testClassesList) {
        for (var i = 0; i < testClassesList.length; i++) {
            if (node.classList.contains(testClassesList[i])) {
                return true;
            }
        }

        return false;
    }

    function findInsertionPoint (candidate, test, direction) {
        if (test(candidate)) {
            return candidate;
        } else if (direction == 'up' && candidate.previousElementSibling) {
            return findInsertionPoint(candidate.previousElementSibling, test, direction);
        } else if (direction == 'down' && candidate.nextElementSibling) {
            return findInsertionPoint(candidate.nextElementSibling, test, direction);
        } else {
            return false;
        }
    }

    // 'previous-image', 'previous', 'up', 'down', 'next', 'next-image', 'end'
    function blessImages () {
        forEachNode('.figure', function (node) {
            // If a node is in a footnote do not move it

            if (! node.parentNode.classList.contains('inlineFootnote')) {
                var container = node.parentNode.parentNode,
                    wrapper = node.parentNode;

                while (container.getAttribute('id') != 'main') {
                    container = container.parentNode;
                }
                
                if (node.classList.contains('insert_before')) {
                    for (var c = 0; c < node.classList.length; c++) {
                        if (node.classList[c].match(/p--(\d+)/)) {
                            var match = node.classList[c].match(/p--(\d+)/),
                                insertionPoint = document.querySelector('#main > p:nth-of-type(' + (parseInt(match[1]) + 1) + ')');
                            
                            container.insertBefore(node, insertionPoint);
                        }
                    }
                } else if (paragraphIndex(node.parentNode) == 0) {
                    node.parentNode.parentNode.insertBefore(node, node.parentNode.nextElementSibling.nextElementSibling);
                } else if (paragraphIndex(node.parentNode) == 1 || node.classList.contains('start')){
                    var insertionPoint = findInsertionPoint(container.querySelector('#main > p:nth-of-type(2)').nextElementSibling, function (n) { return (!(n.classList.contains('inlineFootnote') || n.classList.contains('figure'))); }, 'down');
                    container.insertBefore(node, insertionPoint);
                } else if (node.classList.contains('previous-image')) {
                    var insertionPoint = findInsertionPoint(wrapper, function (n) { return (n.classList.contains('figure')); }, 'up'); 

                    if (insertionPoint) {
                        container.insertAfter(node, insertionPoint);
                    } else {
                        container.insertBefore(node, wrapper)
                    }
                } else if (node.classList.contains('previous')) {
                    var insertionPoint = findInsertionPoint(wrapper, function (n) { return (n.classList.contains('figure') || n.classList.contains('inlineFootnote')); }, 'up'); 

                    if (insertionPoint) {
                        container.insertAfter(node, insertionPoint);
                    } else {
                        container.insertBefore(node, wrapper)
                    }
                } else if (node.classList.contains('down')) {
                    // Travel down DOM, to add element AFTER notes which were placed there before;
                    var insertionPoint = findInsertionPoint(wrapper.nextElementSibling, function (n) { return (!(n.classList.contains('inlineFootnote') || n.classList.contains('figure'))); }, 'down'); 

                    if (insertionPoint) {
                        container.insertBefore(node, insertionPoint);
                    } else {
                        container.insertAfter(node, wrapper);
                    }
                }  else if (node.classList.contains('end')) {
                    // Travel down DOM, to add element AFTER notes which were placed there before;
                    container.insertBefore(node, document.querySelector('.footnotes'));
                } else {
                    node.parentNode.parentNode.insertBefore(node, node.parentNode);
                }
            }
            node.addEventListener('click', function (e) { toggle (this); }, false);
        });
    }

    function expandAllImages () {
        forEachNode('img', expand);
    }

    function collapseAllImages () {
        forEachNode('img', collapse);
    }

    function blessExcursions () {
        forEachNode('section', function (node) {
            node.addEventListener("click", function () { toggle(this); });
        });
    }

    function expandAllExcursions () {
        forEachNode('section', expand);
    }

    function collapseAllExcursions () {
        forEachNode('section', collapse);
    }

    function blessAll () {
        blessImages();
        blessExcursions();
        blessFootnotes();
    }

    function collapseAll () {
        collapseAllImages();
        collapseAllFootnotes();
        collapseAllExcursions();
    }

    function expandAll () {
        expandAllImages();
        expandAllFootnotes();
        expandAllExcursions();
    }

    // function reinsertLettrines () {
    //     var p = document.querySelector('#main > p:nth-of-type(2)');
    //     var img = document.createElement('img');
    //     p.style.position = 'relative';
    //     img.classList.add('fakeLettrines');

    //     if (document.body.id == "I-1-1") {
    //         img.src='/assets/lettrines/wrapp-letters-chap1_000.png';
    //     } else if (document.body.id == "I-1-2") {
    //         img.src='/assets/lettrines/wrapp-letters-chap1_001.png';
    //     } else if (document.body.id == "I-1-3") {
    //         img.src='/assets/lettrines/wrapp-letters-chap1_002.png';
    //     } else if (document.body.id == "I-1-4") {
    //         img.src='/assets/lettrines/wrapp-letters-chap1_003.png';
    //     } else if (document.body.id == "I-1-5") {
    //         img.src='/assets/lettrines/wrapp-letters-chap1_004.png';
    //     } else if (document.body.id == "I-1-6") {
    //         img.src='/assets/lettrines/wrapp-letters-chap1_005.png';
    //     } else if (document.body.id == "I-1-7") {
    //         img.src='/assets/lettrines/wrapp-letters-chap1_006.png';
    //     } else if (document.body.id == "I-1-8") {
    //         img.src='/assets/lettrines/wrapp-letters-chap1_007.png';
    //     } else if (document.body.id == "I-1-9") {
    //         img.src='/assets/lettrines/wrapp-letters-chap1_008.png';
    //     } else if (document.body.id == "I-2-1") {
    //         img.src='/assets/lettrines/wrapp-letters_000.png';
    //     } else if (document.body.id == "I-2-2") {
    //         img.src='/assets/lettrines/wrapp-letters_001.png';
    //     } else if (document.body.id == "I-2-2") {
    //         img.src='/assets/lettrines/wrapp-letters_002.png';
    //     } else if (document.body.id == "I-2-3") {
    //         img.src='/assets/lettrines/wrapp-letters_003.png';
    //     } else if (document.body.id == "I-2-4") {
    //         img.src='/assets/lettrines/wrapp-letters_004.png';
    //     } else if (document.body.id == "I-2-5") {
    //         img.src='/assets/lettrines/wrapp-letters_005.png';
    //     } else if (document.body.id == "I-2-6") {
    //         img.src='/assets/lettrines/wrapp-letters_006.png';
    //     } else if (document.body.id == "I-2-7") {
    //         img.src='/assets/lettrines/wrapp-letters_007.png';
    //     }
    //     p.insertBefore(img, p.children[0]);
    // }

    window.blessAll = blessAll;
    window.collapseAll = collapseAll;
    window.expandAll = expandAll;

    // document.addEventListener('storiesloaded', reinsertLettrines);
})(window, document);