251 lines
6.3 KiB
JavaScript
251 lines
6.3 KiB
JavaScript
/*!
|
|
* getSize v1.2.2
|
|
* measure size of elements
|
|
* MIT license
|
|
*/
|
|
|
|
/*jshint browser: true, strict: true, undef: true, unused: true */
|
|
/*global define: false, exports: false, require: false, module: false, console: false */
|
|
|
|
( function( window, undefined ) {
|
|
|
|
'use strict';
|
|
|
|
// -------------------------- helpers -------------------------- //
|
|
|
|
// get a number from a string, not a percentage
|
|
function getStyleSize( value ) {
|
|
var num = parseFloat( value );
|
|
// not a percent like '100%', and a number
|
|
var isValid = value.indexOf('%') === -1 && !isNaN( num );
|
|
return isValid && num;
|
|
}
|
|
|
|
function noop() {}
|
|
|
|
var logError = typeof console === 'undefined' ? noop :
|
|
function( message ) {
|
|
console.error( message );
|
|
};
|
|
|
|
// -------------------------- measurements -------------------------- //
|
|
|
|
var measurements = [
|
|
'paddingLeft',
|
|
'paddingRight',
|
|
'paddingTop',
|
|
'paddingBottom',
|
|
'marginLeft',
|
|
'marginRight',
|
|
'marginTop',
|
|
'marginBottom',
|
|
'borderLeftWidth',
|
|
'borderRightWidth',
|
|
'borderTopWidth',
|
|
'borderBottomWidth'
|
|
];
|
|
|
|
function getZeroSize() {
|
|
var size = {
|
|
width: 0,
|
|
height: 0,
|
|
innerWidth: 0,
|
|
innerHeight: 0,
|
|
outerWidth: 0,
|
|
outerHeight: 0
|
|
};
|
|
for ( var i=0, len = measurements.length; i < len; i++ ) {
|
|
var measurement = measurements[i];
|
|
size[ measurement ] = 0;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
|
|
|
|
function defineGetSize( getStyleProperty ) {
|
|
|
|
// -------------------------- setup -------------------------- //
|
|
|
|
var isSetup = false;
|
|
|
|
var getStyle, boxSizingProp, isBoxSizeOuter;
|
|
|
|
/**
|
|
* setup vars and functions
|
|
* do it on initial getSize(), rather than on script load
|
|
* For Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=548397
|
|
*/
|
|
function setup() {
|
|
// setup once
|
|
if ( isSetup ) {
|
|
return;
|
|
}
|
|
isSetup = true;
|
|
|
|
var getComputedStyle = window.getComputedStyle;
|
|
getStyle = ( function() {
|
|
var getStyleFn = getComputedStyle ?
|
|
function( elem ) {
|
|
return getComputedStyle( elem, null );
|
|
} :
|
|
function( elem ) {
|
|
return elem.currentStyle;
|
|
};
|
|
|
|
return function getStyle( elem ) {
|
|
var style = getStyleFn( elem );
|
|
if ( !style ) {
|
|
logError( 'Style returned ' + style +
|
|
'. Are you running this code in a hidden iframe on Firefox? ' +
|
|
'See http://bit.ly/getsizebug1' );
|
|
}
|
|
return style;
|
|
};
|
|
})();
|
|
|
|
// -------------------------- box sizing -------------------------- //
|
|
|
|
boxSizingProp = getStyleProperty('boxSizing');
|
|
|
|
/**
|
|
* WebKit measures the outer-width on style.width on border-box elems
|
|
* IE & Firefox measures the inner-width
|
|
*/
|
|
if ( boxSizingProp ) {
|
|
var div = document.createElement('div');
|
|
div.style.width = '200px';
|
|
div.style.padding = '1px 2px 3px 4px';
|
|
div.style.borderStyle = 'solid';
|
|
div.style.borderWidth = '1px 2px 3px 4px';
|
|
div.style[ boxSizingProp ] = 'border-box';
|
|
|
|
var body = document.body || document.documentElement;
|
|
body.appendChild( div );
|
|
var style = getStyle( div );
|
|
|
|
isBoxSizeOuter = getStyleSize( style.width ) === 200;
|
|
body.removeChild( div );
|
|
}
|
|
|
|
}
|
|
|
|
// -------------------------- getSize -------------------------- //
|
|
|
|
function getSize( elem ) {
|
|
setup();
|
|
|
|
// use querySeletor if elem is string
|
|
if ( typeof elem === 'string' ) {
|
|
elem = document.querySelector( elem );
|
|
}
|
|
|
|
// do not proceed on non-objects
|
|
if ( !elem || typeof elem !== 'object' || !elem.nodeType ) {
|
|
return;
|
|
}
|
|
|
|
var style = getStyle( elem );
|
|
|
|
// if hidden, everything is 0
|
|
if ( style.display === 'none' ) {
|
|
return getZeroSize();
|
|
}
|
|
|
|
var size = {};
|
|
size.width = elem.offsetWidth;
|
|
size.height = elem.offsetHeight;
|
|
|
|
var isBorderBox = size.isBorderBox = !!( boxSizingProp &&
|
|
style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' );
|
|
|
|
// get all measurements
|
|
for ( var i=0, len = measurements.length; i < len; i++ ) {
|
|
var measurement = measurements[i];
|
|
var value = style[ measurement ];
|
|
value = mungeNonPixel( elem, value );
|
|
var num = parseFloat( value );
|
|
// any 'auto', 'medium' value will be 0
|
|
size[ measurement ] = !isNaN( num ) ? num : 0;
|
|
}
|
|
|
|
var paddingWidth = size.paddingLeft + size.paddingRight;
|
|
var paddingHeight = size.paddingTop + size.paddingBottom;
|
|
var marginWidth = size.marginLeft + size.marginRight;
|
|
var marginHeight = size.marginTop + size.marginBottom;
|
|
var borderWidth = size.borderLeftWidth + size.borderRightWidth;
|
|
var borderHeight = size.borderTopWidth + size.borderBottomWidth;
|
|
|
|
var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
|
|
|
|
// overwrite width and height if we can get it from style
|
|
var styleWidth = getStyleSize( style.width );
|
|
if ( styleWidth !== false ) {
|
|
size.width = styleWidth +
|
|
// add padding and border unless it's already including it
|
|
( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );
|
|
}
|
|
|
|
var styleHeight = getStyleSize( style.height );
|
|
if ( styleHeight !== false ) {
|
|
size.height = styleHeight +
|
|
// add padding and border unless it's already including it
|
|
( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );
|
|
}
|
|
|
|
size.innerWidth = size.width - ( paddingWidth + borderWidth );
|
|
size.innerHeight = size.height - ( paddingHeight + borderHeight );
|
|
|
|
size.outerWidth = size.width + marginWidth;
|
|
size.outerHeight = size.height + marginHeight;
|
|
|
|
return size;
|
|
}
|
|
|
|
// IE8 returns percent values, not pixels
|
|
// taken from jQuery's curCSS
|
|
function mungeNonPixel( elem, value ) {
|
|
// IE8 and has percent value
|
|
if ( window.getComputedStyle || value.indexOf('%') === -1 ) {
|
|
return value;
|
|
}
|
|
var style = elem.style;
|
|
// Remember the original values
|
|
var left = style.left;
|
|
var rs = elem.runtimeStyle;
|
|
var rsLeft = rs && rs.left;
|
|
|
|
// Put in the new values to get a computed value out
|
|
if ( rsLeft ) {
|
|
rs.left = elem.currentStyle.left;
|
|
}
|
|
style.left = value;
|
|
value = style.pixelLeft;
|
|
|
|
// Revert the changed values
|
|
style.left = left;
|
|
if ( rsLeft ) {
|
|
rs.left = rsLeft;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
return getSize;
|
|
|
|
}
|
|
|
|
// transport
|
|
if ( typeof define === 'function' && define.amd ) {
|
|
// AMD for RequireJS
|
|
define( [ 'get-style-property/get-style-property' ], defineGetSize );
|
|
} else if ( typeof exports === 'object' ) {
|
|
// CommonJS for Component
|
|
module.exports = defineGetSize( require('desandro-get-style-property') );
|
|
} else {
|
|
// browser global
|
|
window.getSize = defineGetSize( window.getStyleProperty );
|
|
}
|
|
|
|
})( window );
|