Skip to content

Instantly share code, notes, and snippets.

@heygrady
Created December 24, 2011 09:14
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save heygrady/1516965 to your computer and use it in GitHub Desktop.
Save heygrady/1516965 to your computer and use it in GitHub Desktop.
(function(window, document, undefined){
"use strict";
// create a test element
var testElem = document.createElement('test'),
docElement = document.documentElement,
defaultView = document.defaultView,
getComputedStyle = defaultView && defaultView.getComputedStyle,
computedValueBug,
runit = /^(-?[\d+\.\-]+)([a-z]+|%)$/i,
convert = {},
conversions = [1/25.4, 1/2.54, 1/72, 1/6],
units = ['mm', 'cm', 'pt', 'pc', 'in', 'mozmm'],
i = 6; // units.length
// add the test element to the dom
docElement.appendChild(testElem);
// test for the WebKit getComputedStyle bug
// @see http://bugs.jquery.com/ticket/10639
if (getComputedStyle) {
// add a percentage margin and measure it
testElem.style.marginTop = '1%';
computedValueBug = getComputedStyle(testElem).marginTop === '1%';
}
// pre-calculate absolute unit conversions
while(i--) {
convert[units[i] + "toPx"] = conversions[i] ? conversions[i] * convert.inToPx : toPx(testElem, '1' + units[i]);
}
// remove the test element from the DOM and delete it
docElement.removeChild(testElem);
testElem = undefined;
// convert a value to pixels
function toPx(elem, value, prop, force) {
// use width as the default property, or specify your own
prop = prop || 'width';
var style,
inlineValue,
ret,
unit = (value.match(runit)||[])[2],
conversion = unit === 'px' ? 1 : convert[unit + 'toPx'],
rem = /r?em/i;
if (conversion || rem.test(unit) && !force) {
// calculate known conversions immediately
// find the correct element for absolute units or rem or fontSize + em or em
elem = conversion ? elem : unit === 'rem' ? docElement : prop === 'fontSize' ? elem.parentNode || elem : elem;
// use the pre-calculated conversion or fontSize of the element for rem and em
conversion = conversion || parseFloat(curCSS(elem, 'fontSize'));
// multiply the value by the conversion
ret = parseFloat(value) * conversion;
} else {
// begin "the awesome hack by Dean Edwards"
// @see http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
// remember the current style
style = elem.style;
inlineValue = style[prop];
// set the style on the target element
try {
style[prop] = value;
} catch(e) {
// IE 8 and below throw an exception when setting unsupported units
return 0;
}
// read the computed value
// if style is nothing we probably set an unsupported unit
ret = !style[prop] ? 0 : parseFloat(curCSS(elem, prop));
// reset the style back to what it was or blank it out
style[prop] = inlineValue !== undefined ? inlineValue : null;
}
// return a number
return ret;
}
// return the computed value of a CSS property
function curCSS(elem, prop) {
var value,
pixel,
unit,
rvpos = /^top|bottom/,
outerProp = ["paddingTop", "paddingBottom", "borderTop", "borderBottom"],
innerHeight,
parent,
i = 4; // outerProp.length
if (getComputedStyle) {
// FireFox, Chrome/Safari, Opera and IE9+
value = getComputedStyle(elem)[prop];
} else if (pixel = elem.style['pixel' + prop.charAt(0).toUpperCase() + prop.slice(1)]) {
// IE and Opera support pixel shortcuts for top, bottom, left, right, height, width
// WebKit supports pixel shortcuts only when an absolute unit is used
value = pixel + 'px';
} else if (prop === 'fontSize') {
// correct IE issues with font-size
// @see http://bugs.jquery.com/ticket/760
value = toPx(elem, '1em', 'left', 1) + 'px';
} else {
// IE 8 and below return the specified style
value = elem.currentStyle[prop];
}
// check the unit
unit = (value.match(runit)||[])[2];
if (unit === '%' && computedValueBug) {
// WebKit won't convert percentages for top, bottom, left, right, margin and text-indent
if (rvpos.test(prop)) {
// Top and bottom require measuring the innerHeight of the parent.
innerHeight = (parent = elem.parentNode || elem).offsetHeight;
while (i--) {
innerHeight -= parseFloat(curCSS(parent, outerProp[i]));
}
value = parseFloat(value) / 100 * innerHeight + 'px';
} else {
// This fixes margin, left, right and text-indent
// @see https://bugs.webkit.org/show_bug.cgi?id=29084
// @see http://bugs.jquery.com/ticket/10639
value = toPx(elem, value);
}
} else if ((value === 'auto' || (unit && unit !== 'px')) && getComputedStyle) {
// WebKit and Opera will return auto in some cases
// Firefox will pass back an unaltered value when it can't be set, like top on a static element
value = 0;
} else if (unit && unit !== 'px' && !getComputedStyle) {
// IE 8 and below won't convert units for us
// try to convert using a prop that will return pixels
// this will be accurate for everything (except font-size and some percentages)
value = toPx(elem, value) + 'px';
}
return value;
}
// expose the conversion function to the window object
window.Length = {
toPx: toPx
};
}(this, this.document));
(function(r,a,n){function i(b,j,c,d){var c=c||"width",e;e=(j.match(o)||[])[2];var a="px"===e?1:k[e+"toPx"],g=/r?em/i;if(a||g.test(e)&&!d)b=a?b:"rem"===e?l:"fontSize"===c?b.parentNode||b:b,a=a||parseFloat(m(b,"fontSize")),b=parseFloat(j)*a;else{d=b.style;e=d[c];try{d[c]=j}catch(f){return 0}b=!d[c]?0:parseFloat(m(b,c));d[c]=e!==n?e:null}return b}function m(b,a){var c,d,e=/^top|bottom/,f=["paddingTop","paddingBottom","borderTop","borderBottom"],h=4;c=g?g(b)[a]:(d=b.style["pixel"+a.charAt(0).toUpperCase()+
a.slice(1)])?d+"px":"fontSize"===a?i(b,"1em","left",1)+"px":b.currentStyle[a];d=(c.match(o)||[])[2];if("%"===d&&p)if(e.test(a)){for(e=(d=b.parentNode||b).offsetHeight;h--;)e-=parseFloat(m(d,f[h]));c=parseFloat(c)/100*e+"px"}else c=i(b,c);else("auto"===c||d&&"px"!==d)&&g?c=0:d&&"px"!==d&&!g&&(c=i(b,c)+"px");return c}var f=a.createElement("test"),l=a.documentElement,g=(a=a.defaultView)&&a.getComputedStyle,p,o=/^(-?[\d+\.\-]+)([a-z]+|%)$/i,k={},a=[1/25.4,1/2.54,1/72,1/6],q="mm,cm,pt,pc,in,mozmm".split(","),
h=6;l.appendChild(f);if(g)f.style.marginTop="1%",p="1%"===g(f).marginTop;for(;h--;)k[q[h]+"toPx"]=a[h]?a[h]*k.b:i(f,"1"+q[h]);l.removeChild(f);f=n;r.a={c:i}})(this,this.document);
(function(window, document, undefined){
"use strict";
var testElem,
docElement = document.documentElement,
defaultView = document.defaultView,
getComputedStyle = defaultView && defaultView.getComputedStyle,
computedValueBug,
runit = /^(-?[\d+\.\-]+)([a-z]+|%)$/i;
// test for the WebKit getComputedStyle bug
// @see http://bugs.jquery.com/ticket/10639
if (getComputedStyle) {
// create a test element
testElem = document.createElement('test');
// add the test element to the dom
docElement.appendChild(testElem);
// add a percentage margin and measure it
testElem.style.marginTop = '1%';
computedValueBug = getComputedStyle(testElem).marginTop === '1%';
// remove the test element from the DOM and delete it
docElement.removeChild(testElem);
testElem = undefined;
}
// convert a value to pixels
function toPx(elem, value, prop) {
// use width as the default property, or specify your own
prop = prop || 'width';
// begin "the awesome hack by Dean Edwards"
// @see http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
// remember the current style
var style = elem.style,
inlineValue = style[prop],
ret;
// set the style on the target element
try {
style[prop] = value;
} catch(e) {
// IE 8 and below throw an exception when setting unsupported units
return 0;
}
// read the computed value
// if style is nothing we probably set an unsupported unit
ret = !style[prop] ? 0 : curCSS(elem, prop);
// reset the style back to what it was or blank it out
style[prop] = inlineValue !== undefined ? inlineValue : null;
// remove the unit and return a number
return parseFloat(ret);
}
// return the computed value of a CSS property
function curCSS(elem, prop) {
var value,
pixel,
unit,
rvpos = /^top|bottom/,
outerProp = ["paddingTop", "paddingBottom", "borderTop", "borderBottom"],
innerHeight,
parent,
i = 4; // outerProp.length
if (getComputedStyle) {
// FireFox, Chrome/Safari, Opera and IE9+
value = getComputedStyle(elem)[prop];
} else if (pixel = elem.style['pixel' + prop.charAt(0).toUpperCase() + prop.slice(1)]) {
// IE and Opera support pixel shortcuts for top, bottom, left, right, height, width
// WebKit supports pixel shortcuts only when an absolute unit is used
value = pixel + 'px';
} else if (prop === 'fontSize') {
// correct IE issues with font-size
// @see http://bugs.jquery.com/ticket/760
value = toPx(elem, '1em', 'left') + 'px';
} else {
// IE 8 and below return the specified style
value = elem.currentStyle[prop];
}
// check the unit
unit = (value.match(runit)||[])[2];
if (unit === '%' && computedValueBug) {
// WebKit won't convert percentages for top, bottom, left, right, margin and text-indent
if (rvpos.test(prop)) {
// Top and bottom require measuring the innerHeight of the parent.
innerHeight = (parent = elem.parentNode || elem).offsetHeight;
while (i--) {
innerHeight -= parseFloat(curCSS(parent, outerProp[i]));
}
value = parseFloat(value) / 100 * innerHeight + 'px';
} else {
// This fixes margin, left, right and text-indent
// @see https://bugs.webkit.org/show_bug.cgi?id=29084
// @see http://bugs.jquery.com/ticket/10639
value = toPx(elem, value);
}
} else if ((value === 'auto' || (unit && unit !== 'px')) && getComputedStyle) {
// WebKit and Opera will return auto in some cases
// Firefox will pass back an unaltered value when it can't be set, like top on a static element
value = 0;
} else if (unit && unit !== 'px' && !getComputedStyle) {
// IE 8 and below won't convert units for us
// try to convert using a prop that will return pixels
// this will be accurate for everything (except font-size and some percentages)
value = toPx(elem, value) + 'px';
}
return value;
}
// expose the conversion function to the window object
window.Length = {
toPx: toPx
};
}(this, this.document));
(function(window, document, undefined){
"use strict";
var runit = /^(-?[\d+\.\-]+)([a-z]+|%)$/i;
// convert a value to pixels
function toPx(elem, value, prop) {
// use width as the default property, or specify your own
prop = prop || 'width';
// begin "the awesome hack by Dean Edwards"
// @see http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
// remember the current style
var style = elem.style,
inlineValue = style[prop],
ret;
// set the style on the target element
try {
style[prop] = value;
} catch(e) {
// IE 8 and below throw an exception when setting unsupported units
return 0;
}
// read the computed value
// if style is nothing we probably set an unsupported unit
ret = !style[prop] ? 0 : currCSS(elem, prop);
// reset the style back to what it was or blank it out
style[prop] = inlineValue !== undefined ? inlineValue : null;
// remove the unit and return a number
return parseFloat(ret);
}
// return the computed value of a CSS property
function currCSS(elem, prop) {
var value,
pixel,
getComputedStyle = document.defaultView && document.defaultView.getComputedStyle,
unit;
if (getComputedStyle) {
// FireFox, Chrome/Safari, Opera and IE9+
value = getComputedStyle(elem)[prop];
} else if (pixel = elem.style['pixel' + prop.charAt(0).toUpperCase() + prop.slice(1)]) {
// IE and Opera support pixel shortcuts for top, bottom, left, right, height, width
// Chrome supports pixel shortcuts for those properties only when an absolute unit is used
value = pixel + 'px';
} else {
// IE 8 and below won't convert units for us
value = elem.currentStyle[prop];
// check the unit
unit = (value.match(runit)||[])[2];
if (unit && unit !== 'px') {
// try to convert using a prop that will return pixels
// this will be accurate for everything (except font-size and some percentages)
value = toPx(elem, value) + 'px';
}
}
return value;
}
// expose the conversion function to the window object
window.Length = {
toPx: toPx
};
}(this, this.document));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment