Jquery, mootools, ext, and other class libraries are very difficult to implement in this part. It is very difficult to compile this part. After in-depth research on their implementation, I finally made a very concise version based on my accumulated CSS knowledge. The answer is quite similar to jquery.css cur, but it may be richer in features. According to the catering industry, the answer is "increase without price". I may also call "Increase and price reduction "...... The version is still in beta stage, because only tool functions are not made into classes.
CopyCode Code: var getstyle = function (El, style ){
If (! + "\ V1 "){
Style = style. Replace (/\-(\ W)/g, function (all, letter ){
Return letter. touppercase ();
});
Return El. currentstyle [style];
} Else {
Return document. defaultview. getcomputedstyle (El, null). getpropertyvalue (style)
}
}
This is the original state of the function. Because used value is developed by W3C, document. defaultview. getcomputedstyle can solve the problem of 99 percent even if it does not move. IE is complicated. Although Microsoft is engaged in style, currentstyle and runtimestyle, there is never any implementation similar to getcomputedstyle. The closest is currentstyle, which can only get internal styles, in addition, we need to convert the CSS attribute into a camper style. For convenience, I will separate it now. copy Code the code is as follows: vaR camelize = function (ATTR) {
return ATTR. replace (/\-(\ W)/g, function (all, letter) {
return letter. touppercase ();
});
}
Next, we will solve the issue of IE transparency separately. Basically all major libraries are doing this. We can see how tricky this problem is. I really want to thank Microsoft for its talents:Copy codeThe Code is as follows: var getieopacity = function (EL ){
VaR filter;
If (!! Window. xdomainrequest ){
Filter = El. style. Filter. Match (/progid: DXImageTransform. Microsoft. Alpha \(.? Opacity = (.*).? \)/I );
} Else {
Filter = El. style. Filter. Match (/Alpha \ (opacity = (. *) \)/I );
}
If (filter ){
VaR value = parsefloat (filter [1]);
If (! Isnan (value )){
Return Value? Values/100: 0;
}
}
Return 1;
}
Then our function becomes like this:Copy codeCode: var getstyle = function (El, style ){
If (! + "\ V1 "){
If (style = "opacity "){
Return getieopacity (EL)
}
Return El. currentstyle [camelize (style)];
} Else {
Return document. defaultview. getcomputedstyle (El, null). getpropertyvalue (style)
}
}
next, the float attribute problem occurs. In IE, stylefloat and W3C are cssfloat. Solving the problem is not a problem, but it is too troublesome to switch every time. I will cache them by referring to the ext implementation. copy Code the code is as follows: vaR propcache = [];
var propfloat =! + "\ V1 "? 'Stylefloat': 'cssfloat';
var camstme = function (ATTR) {
return ATTR. replace (/\-(\ W)/g, function (all, letter) {
return letter. touppercase ();
});
}< br> var memorize = function (PROP) {// meaning: check out form cache
return propcache [prop] | (propcache [prop] = prop = 'float '? Propfloat: camelize (PROP);
}< br> var getieopacity = function (EL) {
**************** * *****
}< br> var getstyle = function (El, style) {
If (! + "\ V1") {
If (style = "opacity") {
return getieopacity (EL)
}< br> return el. currentstyle [memorize (style)];
}else {
If (style = "float") {
style = propfloat;
}< br> return document. defaultview. getcomputedstyle (El, null ). getpropertyvalue (style)
}< BR >}
To the most difficult part-precisely obtain the height and width. If anyone who has used jquery knows that John resig handles these two attributes separately. In fact, jquery has a headache for other libraries. The cause of the problem is that if no inline style or internal style explicitly sets these two attributes, we cannot get their exact values in IE, or get the percentage, null string, auto, inhert, and other helpless things. In addition, for Chinese people, the position of PX is much higher than that of em. The total reason is that we cannot discard these two attributes. To obtain the exact values of these two attributes, we need to study the CSS Inheritance Problem. I have also written the relevant blog "CSS inhert and auto" to discuss this issue. I didn't read it. Please come back after reading it. Otherwise, I cannot read it at all.
According to the CSS classification, width and height are attributes in non-inherited property. We can see that if we do not set a value for them, the default value is auto. This auto is a magic stuff. If it is a block element, its width is equivalent to 100%, and the content zone of the parent element is full. Of course, this is not considering its padding, in the case of border and margin. If it is an inline element and does not have a box model, it makes no sense to set the width and height for it, even in Firefox, the exact value of the returned transformation is totally different from the one you see. If no value is set, auto is returned directly. In order to obtain accurate values in PX units, we need to convert ideas to shield block and inline elements, but just stare at CSS attribute conversion. At this time, Microsoft has done a good job and developed the offsetxx, clientxx, and scrollxx families. Now, they are finally included in W3C standards. But as early as this day, various browsers have followed suit.
In standard mode, offsetwidth includes padding, borderwidth, and width. If a scroll bar exists, its offsetwidth will not change. The width of the scroll bar is very consistent in different browsers and is 17px, in this case, the width is subtracted from 17px, and the missing space is filled by the scroll bar. If there is padding and padding in offsetwidth, We need to subtract padding and padding. In the geek mode, offsetwidth equals width, while width includes padding and borderwidth. The same applies to offsetheight. The clientxx family is easy to understand, that is, it does not contain borderwidth and scroll bar. The scrollxx family is not mentioned, and the five browsers are inconsistent. Therefore, in the standard mode, the clientxx family is the first choice to obtain the height and width. In the strange mode, the offsetxx family is the first choice.
At this time, I have to talk about the strange pattern. Don't think that it will be upgraded to IE8. Setting the corresponding doctype will escape. As long as you have too many webpages and do not write according to the standard, ie will also be converted into compatible mode. This compatibility mode is not equal to the geek mode, because IE8 has up to five rendering modes, ie5 geek mode, IE7 standard mode, and IE8 almost standard mode, IE7 compatibility mode and HTML5 edge mode. In this multi-mode, Do you think document. compatmode = "css1compat" alone can hold on ?! Fortunately, IE8 added a document.doc umentmode attribute while adding a new mode. Therefore, the code used to determine whether to run in the geek mode is:
Http://www.mangguo.org/x-ua-compatible-ie8-compatible-mode/ Copy code The Code is as follows: var isquirk = (document.doc umentmode )? (Document.doc umentmode = 5 )? True:
False: (document. compatmode = "css1compat ")? False: True );
So we have the following pseudo code:Copy codeThe Code is as follows: var getwidth = function (EL ){
If (isquirk ){
Return El. offsetwidth
} Else {
Return El. clientwidth-parsefloat (getstyle (El, "padding-left")-parsefloat (getstyle (El, "padding-Right "))
}
}
Compare the implementation of ext (only extract the core part ):Copy codeThe Code is as follows: getwidth: function (contentwidth ){
VaR me = This,
DOM = me. Dom,
W = math. Max (DOM. offsetwidth, Dom. clientwidth) | 0;
W =! Contentwidth? W: W-Me. getborderwidth ("LR")-Me. getpadding ("LR ");
Return W <0? 0: W;
},
A very dangerous approach is worse than prototype implementation, so it cannot be corrected in other parts, which is why its UI size is so large, the jquery implementation method is also superb. However, the implementation of jquery is quite complicated. If the element cannot obtain the exact value, start with the upper-level element. This traversal consumes a lot. It also borrowed a great hack from Dean Edwards:Copy code The Code is as follows: var convertpixelvalue = function (El, value ){
VaR style = El. style, Left = style. Left, rsleft = El. runtimestyle. Left;
El. runtimestyle. Left = El. currentstyle. Left;
Style. Left = value | 0;
VaR PX = style. pixelleft;
Style. Left = left;
El. runtimestyle. Left = rsleft;
Return PX;
}
// This function is provided by Dean Edwards. For the earliest sources, see the following link.
// Http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
// Note that the second parameter must be a unit value, such as em ', 'ex', 'cm ', 'mm', 'in', 'pt', and 'pc'
// The percentage seems to be a problem.
// In addition, do not try to use browsers other than IE
// Usage: convertpixelvalue ($ ("drag4"), '10em ')
VaR convertpixelvalue = function (El, styleval ){
// Save the original values to left and rsleft
VaR style = El. style, Left = style. Left, rsleft = El. runtimestyle. Left;
// The following step is the key,
// Place El. currentstyle. Left into El. runtimestyle. Left to activate hack.
El. runtimestyle. Left = El. currentstyle. Left;
// Place a non-Px value in style. Left, for example, 10em.
Style. Left = styleval | 0;
// You must use style. pixelleft to retrieve the image. Otherwise, the value is inaccurate.
// If we use style. pixelleft, we get 160. If we use style. Left, we get PX.
// If all of them have been converted, but style. Left is not accurate.
VaR PX = style. pixelleft;
Style. Left = left; // restore Data
El. runtimestyle. Left = rsleft; // restore Data
Return PX;
}
This hack is used to convert em, PC, PT, CM, In, ex and other units to PX, excluding the percentage.
When I look back at my getwidth function, the main problem is to get the values of padding-left and padding-right. In the standard browser, we can use getcomputedstyle to easily obtain the precise converted value, in PX. In IE, if you give it a value of 2em, it returns 2em, very lazy. In the article "CSS inherit and auto", I also pointed out that padding is a non-inherited property, so you do not need to process the value of inhert without a response header. In the auto list, padding is not included in the column, which reduces the risk of processing the Fuzzy Value of auto. In addition, it is a measurable unit, and each browser has a thick and genuine default value of 0 PX. In other words, what we need to do is to convert the unit of value to PX instead of PX. We can integrate Dean Edwards's hack into our main function getstyle. If padding-left is a percentage, We can multiply the width of its parent element by the percentage. All in all, the level and number of computations of traversal are compressed at least. In this regard, I am much better at this aspect than jquery (jquery is included in both border and margin, while border and margin have fuzzy values in IE, this forces jquery to calculate the parent element easily. In other words, the attribute of the parent element needs to be repeated for five times. I can calculate the parent element three times at most, only once in the weird mode ). Sometimes the value obtained in IE is more accurate than that of Firefox with getcomputedstyle (however, it seems that it is too accurate to adjust the accuracy with tofixed ). Copy code Code: var getstyle = function (El, style ){
If (! + "\ V1 "){
If (style = "opacity "){
Return getieopacity (EL)
}
VaR value = El. currentstyle [memorize (style)];
If (/^ (height | width) $/. Test (style )){
VaR values = (style = 'width ')? ['Left', 'right']: ['top', 'bottom '], size = 0;
If (isquirk ){
Return El [camelize ("offset-" + style)]
} Else {
VaR client = parsefloat (El [camelize ("client-" + style)]),
Paddinga = parsefloat (getstyle (El, "padding-" + values [0]),
Paddingb = parsefloat (getstyle (El, "padding-" + values [1]);
Return (client-paddinga-paddingb) + "PX ";
}
}
If (! /^ \ D + px $/. Test (value )){
// Convert measurable values
If (/(EM | Pt | mm | cm | PC | in | ex | REM | VW | VL | VM | ch | GR) $/. Test (value )){
Return convertpixelvalue (El, value );
}
// Conversion Percentage
If (/%/. Test (value )){
Return parsefloat (getstyle (El. parentnode, "width") * parsefloat (value)/100 + "PX"
}
}
Return Value; // For example, 0px
} Else {
If (style = "float "){
Style = propfloat;
}
Return document. defaultview. getcomputedstyle (El, null). getpropertyvalue (style)
}
}
Let's test it.
<Div id = "text" style = "width: 3in; Height: 180px; Background: #8080c0; padding: 2%;"> parent Element
<Div id = "text2" style = "width: 78%; Height: 4em; padding: 1%; Background: red; Border: 1px solid red"> child element </div>
</Div>
Window. onload = function (){
Alert (getstyle (_ ("text"), "width "))
Alert (getstyle (_ ("text2"), 'width '))
Alert (getstyle (_ ("text2"), 'padding-left '))
};Dir = "LTR" lang = "ZH-CN">
Parent Element
Child Element