Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fitie isn't responsive (unless you implement something like this) #10

Open
jonascarlbaum opened this issue Sep 23, 2016 · 0 comments
Open

Comments

@jonascarlbaum
Copy link

jonascarlbaum commented Sep 23, 2016

I found out that fitie wasn't responsive, and since I needed it to be I implemented a first draft of it. Not optimized, consider it a work in progress and an idea on how to implement a more solid solution.

var fitie = function (node) {
    // restrict to valid object-fit value
    var objectFit = node.currentStyle['object-fit'];

    if (!objectFit || !/^(contain|cover|fill)$/.test(objectFit)) return;

    var setCSS = node.runtimeStyle;
    var getCSS = node.currentStyle;
    node.defaultStyle = node.defaultStyle || [];

    if (node.defaultStyle === []) {
        for (var key in getCSS) {
            node.defaultStyle[key] = getCSS[key];
        }
    }

    if (node.parentNode.nodeName.toLowerCase() === 'object-fit') {
        node.parentNode.parentNode.replaceChild(node, node.parentNode);
        for (var key in node.defaultStyle) {
            setCSS[key] = node.defaultStyle[key];
        }
    }

    // prepare container styles
    var outerWidth = node.clientWidth;
    var outerHeight = node.clientHeight;
    var outerRatio = outerWidth / outerHeight;

    var name = node.nodeName.toLowerCase();

    var addEventListener = node.addEventListener || node.attachEvent;
    var removeEventListener = node.removeEventListener || node.detachEvent;
    var on = node.addEventListener ? '' : 'on';
    var img = name === 'img';
    var type = img ? 'load' : 'loadedmetadata';

    addEventListener.call(node, on + type, onload);

    if (node.complete) onload();

    function onload() {
        removeEventListener.call(node, on + type, onload);

        // prepare container styles
        var imgCSS = {
            boxSizing: 'content-box',
            display: 'inline-block',
            overflow: 'hidden'
        };

        'backgroundColor backgroundImage borderColor borderStyle borderWidth bottom fontSize lineHeight height left opacity margin position right top visibility width'.replace(/\w+/g, function (key) {
            imgCSS[key] = getCSS[key];
        });

        // prepare image styles
        setCSS.border = setCSS.margin = setCSS.padding = 0;
        setCSS.display = 'block';
        setCSS.height = setCSS.width = 'auto';
        setCSS.opacity = 1;

        var innerWidth = node.videoWidth || node.width;
        var innerHeight = node.videoHeight || node.height;
        var innerRatio = innerWidth / innerHeight;

        // style container
        var imgx = document.createElement('object-fit');

        if (node.parentNode.nodeName.toLowerCase() !== 'object-fit') {
            imgx.appendChild(node.parentNode.replaceChild(imgx, node));

            for (var key in imgCSS) {
                node.defaultStyle[key] = imgCSS[key];
            }
        } else {
            var oldImgx = node.parentNode;
            var parent = oldImgx.parentNode;

            imgx = document.createElement('object-fit');
            imgx.appendChild(node);
            parent.replaceChild(imgx, oldImgx);
        }

        for (var key in node.defaultStyle) imgx.runtimeStyle[key] = node.defaultStyle[key];

        // style image
        var newSize;

        if (objectFit === 'fill') {
            if (img) {
                setCSS.width = outerWidth;
                setCSS.height = outerHeight;
            } else {
                setCSS['-ms-transform-origin'] = '0% 0%';
                setCSS['-ms-transform'] = 'scale(' + outerWidth / innerWidth + ',' + outerHeight / innerHeight + ')';
            }
        } else if (innerRatio < outerRatio ? objectFit === 'contain' : objectFit === 'cover') {
            newSize = outerHeight * innerRatio;

            setCSS.width = Math.round(newSize) + 'px';
            setCSS.height = outerHeight + 'px';
            setCSS.marginLeft = Math.round((outerWidth - newSize) / 2) + 'px';
        } else {
            newSize = outerWidth / innerRatio;

            setCSS.width = outerWidth + 'px';
            setCSS.height = Math.round(newSize) + 'px';
            setCSS.marginTop = Math.round((outerHeight - newSize) / 2) + 'px';
        }
    }
};
fitie.init = function () {
    if (document.body) {
        var all = document.querySelectorAll('img,video');
        var index = -1;

        while (all[++index]) fitie(all[index]);

        window.addEventListener("resize", fitie.init); //TODO: optimize to run time consuming code only if width is actually changed...
    } else {
        setTimeout(fitie.init);
    }
};

if (/MSIE|Trident/.test(navigator.userAgent)) fitie.init();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant