/* */
/* Copyright © GalaSoft Laurent Bugnion 2007 */
//*****************************************************************************
//* gslb.csslength.js
//*****************************************************************************
//* Object name : CssLength
//* Tested Targets : Firefox 2, Internet Explorer 7
//* Language/Compiler : ECMAScript V3
//* Author : Laurent Bugnion (LBu)
//* Created : 25.01.2007
//*****************************************************************************
//* Description: see constructor
//* Last Base Level: BL0003
//*****************************************************************************
//*****************************************************************************
//* Imports *******************************************************************
//*****************************************************************************
//*****************************************************************************
//* Constructor ***************************************************************
//*****************************************************************************
// Create namespace
if ( !window.gslb )
{
window.gslb = {};
}
// ----------------------------------------------------------------------------
///
/// Utility class allowing easier handling of CSS "length" strings,
/// for example "2em" or "150px". This class extracts the unit ("em", "pt", "px", ...),
/// and can also convert from the unit ("em", "pt", ...) to pixels. It can also add
/// or substract pixels, or units ("em", "pt", ...) to the current value. To assign
/// the new value to a style property, you may use the "toString" method.
///
/// A valid CSS "length" string,
/// for example "2em" or "150px".
/// The specific DOM node to which the conversion
/// will apply. If null, the CSS settings for the BODY will be used, but
/// this may lead to incorrect results, for example if the font-size has
/// been set in the node's hierarchy.
gslb.CssLength = function( strCssString, nNode )
{
//***************************************************************************
//* Attributes **************************************************************
//***************************************************************************
///
/// The unit of the CSS string (em, px...)
///
this.m_strUnit = gslb.CssLength.getUnit( strCssString );
///
/// The numeric value in the original unit (for example, for 0.8em, this attribute
/// bears the value 0.8).
///
this.m_fUnitValue = parseFloat( strCssString );
///
/// The specific DOM node to which the conversion
/// will apply. If null, the CSS settings for the BODY will be used, but
/// this may lead to incorrect results, for example if the font-size has
/// been set in the node's hierarchy.
///
this.m_nNode = nNode;
///
/// The factor used to convert the original unit in pixels, and back.
///
this.m_fPixelPerUnitFactor = gslb.CssLength.getPixelPerUnitFactor( this.m_strUnit, this.m_nNode );
// Post construction operations ---------------------------------------------
if ( isNaN( this.m_fUnitValue ) )
{
throw "Invalid CSS length string: " + strCssString;
}
}
//*****************************************************************************
//* Enums *********************************************************************
//*****************************************************************************
//*****************************************************************************
//* Constants *****************************************************************
//*****************************************************************************
///
/// This class's name.
///
gslb.CssLength._NAME = "gslb.CssLength";
///
/// This class's version.
///
gslb.CssLength._VERSION = "V1.1.1";
///
/// This class's date.
///
gslb.CssLength._DATE = "17.11.2007";
//*****************************************************************************
//* Static attributes *********************************************************
//*****************************************************************************
//*****************************************************************************
//* Static methods ************************************************************
//*****************************************************************************
// ----------------------------------------------------------------------------
///
/// Calculates the factor used to convert the given CSS unit (em, pt...) to pixels.
/// This method makes use of the browser's own CSS engine for the calculation,
/// which might fail on older browsers.
///
/// The CSS unit, for example "em".
/// The specific DOM node to which the conversion
/// will apply. If null, the CSS settings for the BODY will be used, but
/// this may lead to incorrect results, for example if the font-size has
/// been set in the node's hierarchy.
/// The factor allowing to convert the given CSS unit
/// to pixels.
gslb.CssLength.getPixelPerUnitFactor = function( strUnit, nNode )
{
if ( strUnit.toLowerCase() == "px" )
{
return 1;
}
if ( !document.createElement )
{
throw "Unsuitable platform";
}
// Create a temporary DIV. For greater precision, use a factor.
var nDivTemp = document.createElement( "div" );
nDivTemp.style.width = "10000" + strUnit;
// Set the DIV to hidden to avoid unwanted visual effects.
nDivTemp.style.visible = "hidden";
if ( !document.getElementsByTagName )
{
throw "Unsuitable platform";
}
// The value is only valid if the DIV belongs to the document
var anBody = document.getElementsByTagName( "body" );
if ( !anBody
|| !anBody.length
|| !anBody[0] )
{
throw "Unsuitable platform";
}
var nParent = anBody[0];
if ( nNode
&& nNode.parentNode )
{
// If the conversion must be applied to a
// specific node, append to this node's parent.
// This avoids errors if the parent's font size has
// been set in CSS.
nParent = nNode.parentNode;
}
if ( !nParent
|| !nParent.appendChild
|| !nParent.removeChild )
{
throw "Unsuitable platform";
}
// Even though pixelWidth is always set, if the
// temporary DIV is not appended to the BODY, the
// value will be invalid, except if font-size
// is set to 100%.
nParent.appendChild( nDivTemp );
if ( nDivTemp.style.pixelWidth != null )
{
var iPixelWidth = nDivTemp.style.pixelWidth;
nParent.removeChild( nDivTemp );
return iPixelWidth / 10000;
}
// pixelWidth is not available --> use clientWidth instead.
if ( nDivTemp.clientWidth != null )
{
var iClientWidth = nDivTemp.clientWidth;
// Once the value is saved, remove the node.
nParent.removeChild( nDivTemp );
return iClientWidth / 10000;
}
throw "Unsuitable platform";
}
// ----------------------------------------------------------------------------
/// A valid CSS "length" string,
/// for example "2em" or "150px".
/// The unit as string, for example "em" or "px".
gslb.CssLength.getUnit = function( strCssString )
{
var strUnit = null;
strCssString = strCssString.toLowerCase();
if ( strCssString.indexOf( "px" ) > 0 )
{
strUnit = "px";
}
if ( strCssString.indexOf( "em" ) > 0 )
{
strUnit = "em";
}
if ( strCssString.indexOf( "pt" ) > 0 )
{
strUnit = "pt";
}
if ( strUnit == null )
{
// Unknown unit --> parse it
strUnit = "";
var bStop = false;
var iIndex = strCssString.length - 1;
while ( !bStop )
{
if ( strCssString.charAt( iIndex ) == ';' )
{
continue;
}
if ( iIndex < 0
|| !isNaN( parseInt( strCssString.charAt( iIndex ) ) ) )
{
// Last digit of the string was met --> exit
break;
}
strUnit = strCssString.charAt( iIndex ) + strUnit;
iIndex--;
}
}
return strUnit;
}
//*****************************************************************************
//* Methods *******************************************************************
//*****************************************************************************
// ----------------------------------------------------------------------------
/// The numeric value for this instance converted in pixels.
gslb.CssLength.prototype.getPixelValue = function()
{
return this.getPixels( this.m_fUnitValue );
}
// ----------------------------------------------------------------------------
///
/// Sets the current value to the given number of pixels.
///
/// The number of pixels to set as
/// the present value.
gslb.CssLength.prototype.setPixelValue = function( iValue )
{
this.setUnitValue( this.getUnits( iValue ) );
}
// ----------------------------------------------------------------------------
/// The numeric value for this instance in original units
/// (according to the CSS string passed to the constructor of this instance).
gslb.CssLength.prototype.getUnitValue = function()
{
return this.m_fUnitValue;
}
// ----------------------------------------------------------------------------
///
/// Sets the current value to the given number of units (em, px, pt...).
///
/// The number of units to set as
/// the present value.
gslb.CssLength.prototype.setUnitValue = function( fValue )
{
this.m_fUnitValue = fValue;
}
// ----------------------------------------------------------------------------
/// The unit ("em", "px", ...) of this value.
gslb.CssLength.prototype.getUnit = function()
{
return this.m_strUnit;
}
// ----------------------------------------------------------------------------
/// A string representation of this value in original units
/// (according to the CSS string passed to the constructor of this instance).
gslb.CssLength.prototype.toString = function()
{
return this.m_fUnitValue.toString() + this.m_strUnit;
}
// ----------------------------------------------------------------------------
/// A string representation of this value converted
/// to pixels.
gslb.CssLength.prototype.toStringPixels = function()
{
return this.getPixelValue().toString() + "px";
}
// ----------------------------------------------------------------------------
///
/// Adds a number of pixels to the present value.
///
/// The number of pixels to add to
/// the present value.
gslb.CssLength.prototype.addPixels = function( iPixels )
{
this.addUnits( this.getUnits( iPixels ) );
}
// ----------------------------------------------------------------------------
///
/// Substracts a number of pixels from the present value.
///
/// The number of pixels to substract from
/// the present value.
gslb.CssLength.prototype.substractPixels = function( iPixels )
{
this.substractUnits( this.getUnits( iPixels ) );
}
// ----------------------------------------------------------------------------
///
/// Adds a number of the original units (according to the CSS string passed to
/// the constructor of this instance) to the present value.
///
/// The number of units to add to
/// the present value.
gslb.CssLength.prototype.addUnits = function( fUnits )
{
this.m_fUnitValue += fUnits;
}
// ----------------------------------------------------------------------------
///
/// Substracts a number of the original units (according to the CSS string passed to
/// the constructor of this instance) from the present value.
///
/// The number of units to substract from
/// the present value.
gslb.CssLength.prototype.substractUnits = function( fUnits )
{
this.m_fUnitValue -= fUnits;
}
// Utilities ------------------------------------------------------------------
// ----------------------------------------------------------------------------
/// A number of units to convert.
/// The number of pixels corresponding to the number of original units
/// (according to the CSS string passed to the constructor of this instance) passed
/// as parameter.
gslb.CssLength.prototype.getPixels = function( fUnitValue )
{
return Math.round( fUnitValue * this.m_fPixelPerUnitFactor );
}
// ----------------------------------------------------------------------------
/// A number of pixels to convert.
/// The number of original units (according to the CSS string passed
/// to the constructor of this instance) corresponding to the number of pixels
/// passed as parameter.
gslb.CssLength.prototype.getUnits = function( iPixelValue )
{
return iPixelValue / this.m_fPixelPerUnitFactor;
}