wrap-detect.js

Allows you to style elements after they've wrapped in flexbox or grid contexts. Just add the script to the head section of your website and add the .wrap-detect class to every parent element you want to use it with.
 avatar
Netrunner
javascript
a year ago
3.5 kB
13
Indexable
Never
document.addEventListener('DOMContentLoaded', function () {
    function wrapDetect() {

        // use this class on flex and grid containers where wrap detection is needed.
        let matches = document.querySelectorAll(".wrap-detect");

        // wrap detection script
        matches.forEach((wrapper) => {

            // define variables
            let wrappables = wrapper.children;
            let wrappedCount = 0;
            let wrapTheRest = false;
            let columns = 1;
            let row = 1;
            let altColumns = 1;

            // apply "some-wrapped" to parent element containing wrapped elements, and "wrapped" class to flex and grid items that have wrapped.
            wrapper.classList.remove("some-wrapped");
            wrapper.classList.remove("all-wrapped");
            [...wrappables].forEach((element, index) => {
                element.classList.remove("wrapped");
                if (index == 0) {
                   element.classList.add("first");
                } else if (wrapTheRest == true) {
                    element.classList.add("wrapped");
                    wrappedCount += 1;
                } else if (element.offsetLeft <= element.previousElementSibling.offsetLeft) {
                    element.classList.add("wrapped");
                    wrapper.classList.add("some-wrapped");
                    wrappedCount += 1;
                    wrapTheRest = true;
                } else {
                    columns += 1;
                }
            });

            // apply "all-wrapped" class to parent container if all flex and grid items are stacked.
            if (wrappables.length - 1 == wrappedCount) {
                wrapper.classList.remove("some-wrapped");
                wrapper.classList.add("all-wrapped");
            }

            // assign column count to parent using wrap detection
            for(var i = wrapper.classList.length - 1; i >= 0; i--) {
                if(wrapper.classList[i].startsWith("cc-")) {
                    wrapper.classList.remove(wrapper.classList[i]);
                }
            }
            columnCountClassName = "cc-" + columns;
            wrapper.classList.add(columnCountClassName);

            // alternate column count using width detection
            for(var i = wrapper.classList.length - 1; i >= 0; i--) {
                if(wrapper.classList[i].startsWith("cc-alt-")) {
                    wrapper.classList.remove(wrapper.classList[i]);
                }
            }

            wrapperWidth = wrapper.getBoundingClientRect().width;
            itemWidth = wrappables[0].getBoundingClientRect().width;
            altColumns = Math.round(wrapperWidth / itemWidth);

            altColumnCountClassName = "cc-alt-" + altColumns;
            wrapper.classList.add(altColumnCountClassName);

            // assign row numbers to items
            [...wrappables].forEach((element, index) => {
                for(var i = element.classList.length - 1; i >= 0; i--) {
                    if(element.classList[i].startsWith("row-")) {
                        element.classList.remove(element.classList[i]);
                    }
                }
                row = Math.ceil((index + 1) / columns);
                element.classList.add("row-" + row);
            });
        });
    }

    // fire wrap detect script on load
    wrapDetect();

    // fire wrap detect script on screen resize
    window.addEventListener('resize', function(event) {
        wrapDetect();
    }, true);

}, false);