mrmartineau
3/15/2016 - 11:18 AM

Feature detect Flexbox support with JavaScript

Feature detect Flexbox support with JavaScript

define(function(){function e(e){return e.replace(/([a-z])-([a-z])/g,function(e,t,r){return t+r.toUpperCase()}).replace(/^-/,"")}function t(e){return e.replace(/([A-Z])/g,function(e,t){return"-"+t.toLowerCase()}).replace(/^ms-/,"-ms-")}function r(e,r){var n=e.length
if("CSS"in window&&"supports"in window.CSS){for(;n--;)if(window.CSS.supports(t(e[n]),r))return!0
return!1}if("CSSSupportsRule"in window){for(var o=[];n--;)o.push("("+t(e[n])+":"+r+")")
o=o.join(" or ")
var i="@supports ("+o+") { #modernizr { position: absolute; } }"
return injectElementWithStyles(i,function(e){return"absolute"==getComputedStyle(e,null).position})}}function n(t,n,o,i){function l(){f&&(delete s.style,delete s.modElem)}if(i=void 0===i?!1:i,void 0!==o){var u=r(t,o)
if(void 0!==u)return u}for(var f,p,a,c,d,m=["modernizr","tspan"];!s.style;)f=!0,s.modElem=document.createElement(m.shift()),s.style=s.modElem.style
for(a=t.length,p=0;a>p;p++)if(c=t[p],d=s.style[c],~(""+c).indexOf("-")&&(c=e(c)),void 0!==s.style[c]){if(i||void 0===o)return l(),"pfx"==n?c:!0
try{s.style[c]=o}catch(y){}if(s.style[c]!=d)return l(),"pfx"==n?c:!0}return l(),!1}function o(e,t,r,o){var l=e.charAt(0).toUpperCase()+e.slice(1),s=(e+" "+i.join(l+" ")+l).split(" ")
return n(s,t,r,o)}var i="Moz O ms Webkit".split(" "),l={elem:document.createElement("modernizr")},s={style:l.elem.style}
return{flexbox:o("flexBasis","1px"),legacy:o("boxDirection","reverse"),tweener:o("flexAlign","end"),wrap:o("flexWrap","wrap")}})
define(function() {

    var cssomPrefixes = 'Moz O ms Webkit'.split(' ');
    var modElem = {
        elem: document.createElement('modernizr')
    };
    var mStyle = {
        style: modElem.elem.style
    };

    function cssToDOM(name) {
        return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) {
            return m1 + m2.toUpperCase();
        }).replace(/^-/, '');
    }

    function domToCSS(name) {
        return name.replace(/([A-Z])/g, function(str, m1) {
            return '-' + m1.toLowerCase();
        }).replace(/^ms-/, '-ms-');
    }

    function nativeTestProps(props, value) {
        var i = props.length;
        if ('CSS' in window && 'supports' in window.CSS) {
            while (i--) {
                if (window.CSS.supports(domToCSS(props[i]), value)) {
                    return true;
                }
            }
            return false;
        } else if ('CSSSupportsRule' in window) {
            var conditionText = [];
            while (i--) {
                conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')');
            }
            conditionText = conditionText.join(' or ');
            var query = '@supports (' + conditionText + ') { #modernizr { position: absolute; } }';
            return injectElementWithStyles(query, function(node) {
                return getComputedStyle(node, null).position == 'absolute';
            });
        }
        return undefined;
    }

    function testProps(props, prefixed, value, skipValueTest) {
        skipValueTest = typeof skipValueTest === 'undefined' ? false : skipValueTest;
        if (typeof value !== 'undefined') {
            var result = nativeTestProps(props, value);
            if (typeof result !== 'undefined') {
                return result;
            }
        }
        var afterInit, i, propsLength, prop, before;
        var elems = ['modernizr', 'tspan'];
        while (!mStyle.style) {
            afterInit = true;
            mStyle.modElem = document.createElement(elems.shift());
            mStyle.style = mStyle.modElem.style;
        }

        function cleanElems() {
            if (afterInit) {
                delete mStyle.style;
                delete mStyle.modElem;
            }
        }
        propsLength = props.length;
        for (i = 0; i < propsLength; i++) {
            prop = props[i];
            before = mStyle.style[prop];
            if (!!~('' + prop).indexOf('-')) {
                prop = cssToDOM(prop);
            }
            if (mStyle.style[prop] !== undefined) {
                if (!skipValueTest && typeof value !== 'undefined') {
                    try {
                        mStyle.style[prop] = value;
                    } catch (e) {}
                    if (mStyle.style[prop] != before) {
                        cleanElems();
                        return prefixed == 'pfx' ? prop : true;
                    }
                } else {
                    cleanElems();
                    return prefixed == 'pfx' ? prop : true;
                }
            }
        }
        cleanElems();
        return false;
    }

    function testAllProps(prop, prefixed, value, skipValueTest) {
        var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1);
        var props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
        return testProps(props, prefixed, value, skipValueTest);
    }

    return {
        flexbox: testAllProps('flexBasis', '1px'),
        legacy:  testAllProps('boxDirection', 'reverse'),
        tweener: testAllProps('flexAlign', 'end'),
        wrap:    testAllProps('flexWrap', 'wrap')
    };

});