This repository has been archived by the owner on Apr 20, 2023. It is now read-only.
/
Length.js
131 lines (117 loc) · 4.23 KB
/
Length.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
* Wrapper for length and percentage style values
* @constructor
* @param {string} val The CSS string representing the length. It is assumed that this will already have
* been validated as a valid length or percentage syntax.
*/
PIE.Length = (function() {
var lengthCalcEl = doc.createElement( 'length-calc' ),
s = lengthCalcEl.style,
numCache = {},
unitCache = {};
s.position = 'absolute';
s.top = s.left = -9999;
function Length( val ) {
this.val = val;
}
Length.prototype = {
/**
* Regular expression for matching the length unit
* @private
*/
unitRE: /(px|em|ex|mm|cm|in|pt|pc|%)$/,
/**
* Get the numeric value of the length
* @return {number} The value
*/
getNumber: function() {
var num = numCache[ this.val ],
UNDEF;
if( num === UNDEF ) {
num = numCache[ this.val ] = parseFloat( this.val );
}
return num;
},
/**
* Get the unit of the length
* @return {string} The unit
*/
getUnit: function() {
var unit = unitCache[ this.val ], m;
if( !unit ) {
m = this.val.match( this.unitRE );
unit = unitCache[ this.val ] = ( m && m[0] ) || 'px';
}
return unit;
},
/**
* Determine whether this is a percentage length value
* @return {boolean}
*/
isPercentage: function() {
return this.getUnit() === '%';
},
/**
* Resolve this length into a number of pixels.
* @param {Element} el - the context element, used to resolve font-relative values
* @param {(function():number|number)=} pct100 - the number of pixels that equal a 100% percentage. This can be either a number or a
* function which will be called to return the number.
*/
pixels: function( el, pct100 ) {
var num = this.getNumber(),
unit = this.getUnit();
switch( unit ) {
case "px":
return num;
case "%":
return num * ( typeof pct100 === 'function' ? pct100() : pct100 ) / 100;
case "em":
return num * this.getEmPixels( el );
case "ex":
return num * this.getEmPixels( el ) / 2;
default:
return num * Length.conversions[ unit ];
}
},
/**
* The em and ex units are relative to the font-size of the current element,
* however if the font-size is set using non-pixel units then we get that value
* rather than a pixel conversion. To get around this, we keep a floating element
* with width:1em which we insert into the target element and then read its offsetWidth.
* But if the font-size *is* specified in pixels, then we use that directly to avoid
* the expensive DOM manipulation.
* @param el
*/
getEmPixels: function( el ) {
var fs = el.currentStyle.fontSize,
px;
if( fs.indexOf( 'px' ) > 0 ) {
return parseFloat( fs );
} else {
lengthCalcEl.style.width = '1em';
el.appendChild( lengthCalcEl );
px = lengthCalcEl.offsetWidth;
if( lengthCalcEl.parentNode !== el ) { //not sure how this happens but it does
el.removeChild( lengthCalcEl );
}
return px;
}
}
};
Length.conversions = (function() {
var units = [ 'mm', 'cm', 'in', 'pt', 'pc' ],
vals = {},
parent = doc.documentElement,
i = units.length, unit;
parent.appendChild( lengthCalcEl );
while( i-- ) {
unit = units[i];
lengthCalcEl.style.width = '100' + unit;
vals[ unit ] = lengthCalcEl.offsetWidth / 100;
}
parent.removeChild( lengthCalcEl );
return vals;
})();
Length.ZERO = new Length( '0' );
return Length;
})();