﻿/**
 * An optimized box-sizing polyfill that offers significantly better performance than the
 * reference implementation in `_boxsizing.htc` in exchange for a minimal loss in rendering
 * accuracy and a larger up-front initial hit while loading.
 */
<component lightWeight="true">
<script>
//<![CDATA[

if ( window._boxSizingQueue == null ) {
	window._boxSizingQueue = {
		pending   : [],
		batchSize : 20,
		frametime : 160,
		handle    : null,
		enqueue   : function( fn ) {
			var me = this;

			me.pending.push( fn );

			if ( me.handle === null ) {
				me.handle = setTimeout( function(){ me.execute(); }, 10 );
			}
		},
		execute : function() {
			var me = this,
				part,
				n;

			// If the document is not yet ready for DOM manipulation, defer the batch a bit.
			// This helps Prevent browser crash when manipulating `element.parentNode.runtimeStyle`
			/*if ( window.document.readyState !== "interactive" && window.document.readyState !== "complete" ) {
				me.handle = setTimeout( function(){ me.execute(); }, me.frametime );
				return;
			}*/

			part = me.pending;
			me.pending = part.slice( me.batchSize );
			part = part.slice( 0, me.batchSize );

			if ( part.length === 0 ) {
				me.handle = null;
			} else {
				me.handle = setTimeout( function(){ me.execute(); }, me.frametime );

				for ( n = part.length; --n !== -1 ; ) {
					part[ n ]();
				}
			}
		}
	};
}


( function( element, undefined ) {
	var
		document = element.document,
		window = document.parentWindow,
		pending = false,
		lastKnownOffsets = {},
		DIM_HEIGHT = 0,
		DIM_WIDTH = 1;

	function getPixelValue( value, element ) {
		var
			matches = /^\s*(\d*\.?\d*)\s*(.+)\s*/.exec( String( value )),
			scalar  = matches && matches[ 1 ],
			unit    = matches && matches[ 2 ],
			style,
			runtimeStyle;

		// Pixel values correlating with IE7's border-width constants
		if ( scalar === "" ) {
			switch ( unit ) {
				case "thin"   : return 2;
				case "medium" : return 4;
				case "thick"  : return 6;
			}
		}

		if ( unit === "px" ) { return scalar; }

		// Keep backup of original values
		style = element.style.left;
		runtimeStyle = element.runtimeStyle.left;

		// Prevent reflow using runtimeStyle
		element.runtimeStyle.left = element.currentStyle.left;
		element.style.left = value || 0;

		// Extract value as pixel value using pixelLeft property
		scalar = element.style.pixelLeft;
		scalar = parseInt(element.style.pixelLeft);

		// Restore original values.
		element.style.left = style;
		element.runtimeStyle.left = runtimeStyle;

		return scalar;
	}

	function getStyleValue( element, dimension ) {
		switch (dimension)
		{
			case DIM_HEIGHT : return element.currentStyle.height;
			case DIM_WIDTH  : return element.currentStyle.width;
		}
	}

	function getOffsetValue( element, dimension ) {
		switch (dimension)
		{
			case DIM_HEIGHT : return element.offsetHeight;
			case DIM_WIDTH  : return element.offsetWidth;
		}
	}

	function getContentValue( element, dimension ) {
		var
			value = 0,
			style = element.currentStyle;

		switch (dimension)
		{
			case DIM_HEIGHT : {
				value -= style.borderTopStyle    == "none" ? 0 : getPixelValue( style.borderTopWidth   , element );
				value -= style.borderBottomStyle == "none" ? 0 : getPixelValue( style.borderBottomWidth, element );
				value -= getPixelValue( style.paddingTop   , element );
				value -= getPixelValue( style.paddingBottom, element );
				value += element.offsetHeight;
				break;
			}

			case DIM_WIDTH  : {
				value -= style.borderLeftStyle  == "none" ? 0 : getPixelValue( style.borderLeftWidth , element );
				value -= style.borderRightStyle == "none" ? 0 : getPixelValue( style.borderRightWidth, element );
				value -= getPixelValue( style.paddingLeft , element );
				value -= getPixelValue( style.paddingRight, element );
				value += element.offsetWidth;
				break;
			}
		}

		return value;
	}

	function setRuntimeValue( element, dimension, value ) {
		switch (dimension)
		{
			case DIM_HEIGHT : return element.runtimeStyle.height = value;
			case DIM_WIDTH  : return element.runtimeStyle.width = value;
		}
	}

	function applyBorderBoxSizing( dimension ) {
		var
			styleSize,
			size,
			matches,
			scalar,
			unit,
			delta;

		// Early out incase of re-firing event after adjustments.
		if ( lastKnownOffsets[ dimension ] === getOffsetValue( element, dimension )) {
			return;
		}

		setRuntimeValue( element, dimension, "" );
		styleSize = getStyleValue( element, dimension );

		matches = /^\s*(\d*\.?\d*)\s*(.+)\s*/.exec( styleSize );
		if ( !matches ) { return; }
		
		scalar = +matches[ 1 ];
		unit = matches[ 2 ];

		switch( unit ) {
			case "px" : 
				size = scalar;
				break;
			case "%" :
				size = getContentValue( element.parentNode, dimension ) * scalar / 100;
				break;
		}

		if ( isNaN( size ) || !size ) { return; }

		delta = Math.max( 0, 1 + Math.ceil( getOffsetValue( element, dimension ) - size ));
		if ( isNaN( delta )) { return; }

		switch( unit ) {
			case "px" :
				scalar = scalar - delta;
				if ( scalar >= 0 ) {
					setRuntimeValue( element, dimension, scalar + unit );
				}
				break;
			case "%" :
				scalar = scalar - scalar * delta / size;
				if ( scalar >= 0 ) {
					setRuntimeValue( element, dimension, scalar + unit );
				}
				break;
		}

		lastKnownOffsets[ dimension ] = getOffsetValue( element, dimension );
	}
	
	function getBoxSizing() {
		var boxSizing;
		
		boxSizing = false
			|| element.style.boxSizing
			|| element.style["box-sizing"]
			|| element.currentStyle.boxSizing
			|| element.currentStyle["box-sizing"]
			|| "content-box";
			
		return boxSizing;
	}

	function onResize() {
		if ( !pending ) {

			pending = true;

			window._boxSizingQueue.enqueue( function() {
				pending = false;

				if ( element.parentNode == null ) return;

				switch( getBoxSizing()) {

					case "border-box" :
						applyBorderBoxSizing( DIM_WIDTH );
						applyBorderBoxSizing( DIM_HEIGHT );
						break;

					case "content-box" :
					default :
						element.runtimeStyle.width = "";
						element.runtimeStyle.height = "";
						break;
				}
			});
		}
	}

	function onPropertyChange() {
		switch( event.propertyName ) {
			case "classname" :
			case "style.boxSizing" :
				onResize();
				break;
			default:
				break;
		}
	}

	element.attachEvent( "onpropertychange", onPropertyChange );
	element.attachEvent( "onresize", onResize );

	onResize();
	
})( element );

//]]>
</script>
</component>