Skip to content

Instantly share code, notes, and snippets.

@drublic
Forked from LeaVerou/vunits.js
Created November 19, 2011 23:03

Revisions

  1. drublic revised this gist Nov 19, 2011. 1 changed file with 155 additions and 35 deletions.
    190 changes: 155 additions & 35 deletions vunits.js
    Original file line number Diff line number Diff line change
    @@ -1,40 +1,160 @@
    /**
    * Polyfill for the vw, vh, vm units
    * Requires StyleFix from -prefix-free http://leaverou.github.com/prefixfree/
    * Polyfill for the vw, vh, vm units including StyleFix
    * @author Lea Verou
    */

    (function() {

    if(!window.StyleFix) {
    return;
    }

    // Feature test
    var dummy = document.createElement('_').style,
    units = ['vw', 'vh', 'vm'].filter(function(unit) {
    dummy.width = '';
    dummy.width = '10' + unit;
    return !dummy.width;
    });

    if(!units.length) {
    return;
    }

    StyleFix.register(function(css) {
    var w = innerWidth, h = innerHeight, m = Math.min(w,h);

    return css.replace(RegExp('\\b(\\d+)(' + units.join('|') + ')\\b', 'gi'), function($0, num, unit) {
    switch (unit) {
    case 'vw':
    return (num * w / 100) + 'px';
    case 'vh':
    return num * h / 100 + 'px';
    case 'vm':
    return num * m / 100 + 'px';
    }
    });
    });
    (function(){

    if(!window.addEventListener) {
    return;
    }

    var self = window.StyleFix = {
    link: function(link) {
    try {
    if(!/\bstylesheet\b/i.test(link.rel) || !link.sheet.cssRules) {
    return;
    }
    }
    catch(e) {
    return;
    }

    var url = link.href || link.getAttribute('data-href'),
    base = url.replace(/[^\/]+$/, ''),
    parent = link.parentNode,
    xhr = new XMLHttpRequest();

    xhr.open('GET', url);

    xhr.onreadystatechange = function() {
    if(xhr.readyState === 4) {
    var css = xhr.responseText;

    if(css && link.parentNode) {
    css = self.fix(css, true, link);

    // Convert relative URLs to absolute, if needed
    if(base) {
    css = css.replace(/url\((?:'|")?(.+?)(?:'|")?\)/gi, function($0, url) {
    if(!/^([a-z]{3,10}:|\/)/i.test(url)) { // If url not absolute
    // May contain sequences like /../ and /./ but those DO work
    return 'url("' + base + url + '")';
    }

    return $0;
    });

    // behavior URLs shoudn’t be converted (Issue #19)
    css = css.replace(RegExp('\\b(behavior:\\s*?url\\(\'?"?)' + base, 'gi'), '$1');
    }

    var style = document.createElement('style');
    style.textContent = css;
    style.media = link.media;
    style.disabled = link.disabled;
    style.setAttribute('data-href', link.getAttribute('href'));

    parent.insertBefore(style, link);
    parent.removeChild(link);
    }
    }
    };

    xhr.send(null);

    link.setAttribute('data-inprogress', '');
    },

    styleElement: function(style) {
    var disabled = style.disabled;

    style.textContent = self.fix(style.textContent, true, style);

    style.disabled = disabled;
    },

    styleAttribute: function(element) {
    var css = element.getAttribute('style');

    css = self.fix(css, false, element);

    element.setAttribute('style', css);
    },

    process: function() {
    // Linked stylesheets
    $('link[rel~="stylesheet"]:not([data-inprogress])').forEach(StyleFix.link);

    // Inline stylesheets
    $('style').forEach(StyleFix.styleElement);

    // Inline styles
    $('[style]').forEach(StyleFix.styleAttribute);
    },

    register: function(fixer, index) {
    (self.fixers = self.fixers || [])
    .splice(index === undefined? self.fixers.length : index, 0, fixer);
    },

    fix: function(css, raw) {
    for(var i=0; i<self.fixers.length; i++) {
    css = self.fixers[i](css, raw) || css;
    }

    return css;
    },

    camelCase: function(str) {
    return str.replace(/-([a-z])/g, function($0, $1) { return $1.toUpperCase(); }).replace('-','');
    },

    deCamelCase: function(str) {
    return str.replace(/[A-Z]/g, function($0) { return '-' + $0.toLowerCase() });
    }
    };

    /**************************************
    * Process styles
    **************************************/
    (function(){
    setTimeout(function(){
    $('link[rel~="stylesheet"]').forEach(StyleFix.link);
    }, 10);

    document.addEventListener('DOMContentLoaded', StyleFix.process, false);
    })();

    function $(expr, con) {
    return [].slice.call((con || document).querySelectorAll(expr));
    }


    // Feature test
    var dummy = document.createElement('_').style,
    units = ['vw', 'vh', 'vm'].filter(function(unit) {
    dummy.width = '';
    dummy.width = '10' + unit;
    return !dummy.width;
    });

    if(!units.length) {
    return;
    }

    StyleFix.register(function(css) {
    var w = innerWidth, h = innerHeight, m = Math.min(w,h);

    return css.replace(RegExp('\\b(\\d+)(' + units.join('|') + ')\\b', 'gi'), function($0, num, unit) {
    switch (unit) {
    case 'vw':
    return (num * w / 100) + 'px';
    case 'vh':
    return num * h / 100 + 'px';
    case 'vm':
    return num * m / 100 + 'px';
    }
    });
    });

    })();
  2. @LeaVerou LeaVerou revised this gist Nov 8, 2011. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions vunits.js
    Original file line number Diff line number Diff line change
    @@ -18,6 +18,10 @@ var dummy = document.createElement('_').style,
    return !dummy.width;
    });

    if(!units.length) {
    return;
    }

    StyleFix.register(function(css) {
    var w = innerWidth, h = innerHeight, m = Math.min(w,h);

  3. @LeaVerou LeaVerou revised this gist Nov 8, 2011. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions vunits.js
    Original file line number Diff line number Diff line change
    @@ -13,10 +13,10 @@ if(!window.StyleFix) {
    // Feature test
    var dummy = document.createElement('_').style,
    units = ['vw', 'vh', 'vm'].filter(function(unit) {
    dummy.width = '';
    dummy.width = '10' + unit;
    return !dummy.width;
    });
    dummy.width = '';
    dummy.width = '10' + unit;
    return !dummy.width;
    });

    StyleFix.register(function(css) {
    var w = innerWidth, h = innerHeight, m = Math.min(w,h);
  4. @LeaVerou LeaVerou revised this gist Nov 8, 2011. 1 changed file with 2 additions and 4 deletions.
    6 changes: 2 additions & 4 deletions vunits.js
    Original file line number Diff line number Diff line change
    @@ -23,12 +23,10 @@ StyleFix.register(function(css) {

    return css.replace(RegExp('\\b(\\d+)(' + units.join('|') + ')\\b', 'gi'), function($0, num, unit) {
    switch (unit) {
    case 'vh':
    return num * w / 100 + 'px';
    break;
    case 'vw':
    return (num * w / 100) + 'px';
    case 'vh':
    return num * h / 100 + 'px';
    break;
    case 'vm':
    return num * m / 100 + 'px';
    }
  5. @LeaVerou LeaVerou created this gist Nov 8, 2011.
    38 changes: 38 additions & 0 deletions vunits.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,38 @@
    /**
    * Polyfill for the vw, vh, vm units
    * Requires StyleFix from -prefix-free http://leaverou.github.com/prefixfree/
    * @author Lea Verou
    */

    (function() {

    if(!window.StyleFix) {
    return;
    }

    // Feature test
    var dummy = document.createElement('_').style,
    units = ['vw', 'vh', 'vm'].filter(function(unit) {
    dummy.width = '';
    dummy.width = '10' + unit;
    return !dummy.width;
    });

    StyleFix.register(function(css) {
    var w = innerWidth, h = innerHeight, m = Math.min(w,h);

    return css.replace(RegExp('\\b(\\d+)(' + units.join('|') + ')\\b', 'gi'), function($0, num, unit) {
    switch (unit) {
    case 'vh':
    return num * w / 100 + 'px';
    break;
    case 'vw':
    return num * h / 100 + 'px';
    break;
    case 'vm':
    return num * m / 100 + 'px';
    }
    });
    });

    })();