window.getComputedStyle for IE6+
IE6, IE7, IE8 用の window.getComputedStyle の実装(uu.cstyle.js)です。
uupaa.js 0.7 core の一部として開発していますが、これ自体はライブラリに依存していないため単体でも動きます。
uu.cstyle.js /*!{id:"uu.cstyle.js",license:"MIT",author:"uupaa.js@gmail.com"}*/ window.getComputedStyle || (function() { var _PT = /pt$/, _MORE, _UNIT = { m: 1, t: 2, "%": 3, o: 3 }, // em,pt,%,auto _THICK = (document.documentMode || 0) === 8 ? "5px" : "6px", _BOX_PROPS = [], _MOD_PROPS = { top: 1, left: 2, width: 3, height: 4 }; window.getComputedStyle = winstyle; // window.getComputedStyle function winstyle(node, // @param Node: pseudo, // @param String(= void 0): option) { // @param Number(= 0x0): // 0x0: enum full properties // 0x1: enum more properties // 0x2: enum some properties // @return Hash: { prop: "val", ... } if (!node.currentStyle) { return {}; } option = option || 0; var rv = {}, ns = node.style, cs = node.currentStyle, rs = node.runtimeStyle, em, rect, unit, v, w, x, i = 0, m1, m2, stock = { "0px": "0px", "1px": "1px", "2px": "2px", "5px": "5px", thin: "1px", medium: "3px", thick: _THICK }; if (!option) { // full for (w in cs) { rv[w] = cs[w]; } } else if (option & 0x1) { // more while ( (w = _MORE[i++]) ) { rv[w] = cs[w] || ""; // IE8 propertyies -> IE6, IE7 down grade trap } } em = parseFloat(cs.fontSize) * (_PT.test(cs.fontSize) ? 4 / 3 : 1); rect = node.getBoundingClientRect(); // calc border, padding and margin size i = 0; while ( (w = _BOX_PROPS[i++]) ) { v = cs[w]; if (!(v in stock)) { x = v; switch (unit = _UNIT[v.slice(-1)] || 0) { case 1: x = parseFloat(v) * em; break; // em case 2: x = parseFloat(v) * 4 / 3; break; // pt case 3: m1 = ns.left, m2 = rs.left; // %, auto rs.left = cs.left, ns.left = v; x = ns.pixelLeft, ns.left = m1, rs.left = m2; } stock[v] = unit ? x + "px" : x; } rv[w] = stock[v]; } for (w in _MOD_PROPS) { v = cs[w]; switch (unit = _UNIT[v.slice(-1)] || 0) { case 1: v = parseFloat(v) * em; break; // em case 2: v = parseFloat(v) * 4 / 3; break; // pt case 3: // %, auto switch (_MOD_PROPS[w]) { case 1: v = node.offsetTop; break; case 2: v = node.offsetLeft; break; case 3: v = (node.offsetWidth || rect.right - rect.left) - parseInt(rv.borderLeftWidth) - parseInt(rv.borderRightWidth) - parseInt(rv.paddingLeft) - parseInt(rv.paddingRight); v = v > 0 ? v : 0; break; case 4: v = (node.offsetHeight || rect.bottom - rect.top) - parseInt(rv.borderTopWidth) - parseInt(rv.borderBottomWidth) - parseInt(rv.paddingTop) - parseInt(rv.paddingBottom); v = v > 0 ? v : 0; } } rv[w] = unit ? v + "px" : v; } rv.fontSize = em + "px"; rv.cssFloat = cs.styleFloat; // compat alias return rv; } // init - make box props (function(ary, i, v) { while ( (v = ary[i++]) ) { _BOX_PROPS.push("border" + v + "Width", "margin" + v, "padding" + v); } })("Top,Left,Right,Bottom".split(","), 0); // option = 0x1, more properties (IE8 propertyies base) _MORE = ( "1Attachment,1Color,1Image,1PositionX,1PositionY,1Repeat,23Color,23Style,23W" + "idth,2LeftColor,2LeftStyle,2LeftWidth,2RightColor,2RightStyle,2RightWidth,2" + "TopColor,2TopStyle,2TopWidth,2Collapse,2Spacing,bottom,captionSide,clear,cl" + "ip3,clipLeft,clipRight,clipTop,color,cssFloat,cursor,direction,display,empt" + "yCells,fontFamily,fontSize,fontStyle,fontWeight,height,left,letterSpacing,l" + "ineBreak,lineHeight,listStyleImage,listStylePosition,listStyleType,margin3," + "marginLeft,marginRight,marginTop,maxHeight,maxWidth,minHeight,minWidth,outl" + "ineColor,outlineStyle,outlineWidth,overflow,overflowX,overflowY,padding3,pa" + "ddingLeft,paddingRight,paddingTop,position,right,styleFloat,textAlign,textA" + "utospace,textDecoration,textIndent,textJustify,textOverflow,textTransform,t" + "op,verticalAlign,visibility,whiteSpace,width,wordBreak,wordSpacing,wordWrap" + ",zIndex").replace(/1/g, "background").replace(/2/g, "border"). replace(/3/g, "Bottom").split(","); })();
HOW TO USE
<style> #hoge { position: absolute; top: 20%; left: 5em; } </style> <script src="uu.cstyle.js"></script> <script> window.onload = function() { var option = 0x0; var hash = window.getComputedStyle(document.getElementById("hoge"), null, option); alert(hash.top); // "80px" } </script> <div id="hoge">hoge</div>
情報量(サブセット)の指定
第三引数で情報量(サブセット or フルセット)を指定できます。
- window.getComputedStyle(node, null)
- window.getComputedStyle(node, null, 0x0)
- フルセットを返します
- 一部のプロパティのみ px に変換しています(option = 0x2 で登場するプロパティのみ)
accelerator, backgroundAttachment, backgroundColor, backgroundImage, backgroundPositionX, backgroundPositionY, backgroundRepeat, behavior, blockDirection, borderBottomColor, borderBottomStyle, borderBottomWidth, borderCollapse, borderColor, borderLeftColor, borderLeftStyle, borderLeftWidth, borderRightColor, borderRightStyle, borderRightWidth, borderSpacing, borderStyle, borderTopColor, borderTopStyle, borderTopWidth, borderWidth, bottom, boxSizing, captionSide, clear, clipBottom, clipLeft, clipRight, clipTop, color, cursor, direction, display, emptyCells, filter, fontFamily, fontSize, fontStyle, fontWeight, hasLayout, height, imeMode, layoutFlow, layoutGridChar, layoutGridLine, layoutGridMode, layoutGridType, left, letterSpacing, lineBreak, lineHeight, listStyleImage, listStylePosition, listStyleType, margin, marginBottom, marginLeft, marginRight, marginTop, maxHeight, maxWidth, minHeight, minWidth, msBlockProgression, msInterpolationMode, orphans, outline, outlineColor, outlineStyle, outlineWidth, overflow, overflowX, overflowY, padding, paddingBottom, paddingLeft, paddingRight, paddingTop, pageBreakAfter, pageBreakBefore, pageBreakInside, position, quotes, right, rubyAlign, rubyOverhang, rubyPosition, scrollbar3dLightColor, scrollbarArrowColor, scrollbarBaseColor, scrollbarDarkShadowColor, scrollbarFaceColor, scrollbarHighlightColor, scrollbarShadowColor, scrollbarTrackColor, styleFloat, tableLayout, textAlign, textAlignLast, textAutospace, textDecoration, textIndent, textJustify, textJustifyTrim, textKashida, textKashidaSpace, textOverflow, textTransform, textUnderlinePosition, top, unicodeBidi, verticalAlign, visibility, whiteSpace, widows, width, wordBreak, wordSpacing, wordWrap, writingMode, zIndex, zoom,
- window.getComputedStyle(node, null, 0x1)
- 速度 + 使い勝手のバランスを考慮したサブセットを返します。
- 一部のプロパティのみ px に変換しています(option = 0x2 で登場するプロパティのみ)
- bottom や right は node.currentStyle が返す値そのままです。px に変換はしていません。
- IE 独自のプロパティ(scroll〜) や 印刷系、ほぼ利用されないプロパティなどを含んでいません。
backgroundAttachment : scroll backgroundColor : transparent backgroundImage : none backgroundPositionX : 0% backgroundPositionY : 0% backgroundRepeat : repeat borderBottomColor : #000000 borderBottomStyle : none borderBottomWidth : 3px borderCollapse : separate borderLeftColor : #000000 borderLeftStyle : none borderLeftWidth : 3px borderRightColor : #000000 borderRightStyle : none borderRightWidth : 3px borderSpacing : borderTopColor : #000000 borderTopStyle : none borderTopWidth : 3px bottom : auto captionSide : top clear : none clipBottom : auto clipLeft : auto clipRight : auto clipTop : auto color : #000000 cssFloat : none cursor : auto direction : ltr display : block emptyCells : show fontFamily : Times New Roman fontSize : 16px fontStyle : normal fontWeight :400 height : 1589px left : 80px letterSpacing : normal lineBreak : normal lineHeight : normal listStyleImage : none listStylePosition : outside listStyleType : disc marginBottom : 0px marginLeft : 0px marginRight : 0px marginTop : 0px maxHeight : none maxWidth : none minHeight : auto minWidth : auto outlineColor : #000000 outlineStyle : none outlineWidth : 0px overflow : visible overflowX : visible overflowY : visible paddingBottom : 0px paddingLeft : 0px paddingRight : 0px paddingTop : 0px position : absolute right : auto styleFloat : none textAlign : left textAutospace : none textDecoration : none textIndent : 0pt textJustify : auto textOverflow : clip textTransform : none top : 126px verticalAlign : auto visibility : inherit whiteSpace : normal width : 189px wordBreak : normal wordSpacing : normal wordWrap : zIndex : auto
- window.getComputedStyle(node, null, 0x2)
- 速度重視で、最小構成のサブセットを返します。
- このサブセットでは、単位が px に統一されています。
borderBottomWidth : 16px borderLeftWidth : 16px borderRightWidth : 16px borderTopWidth : 16px cssFloat : none fontSize : 16px height : 6400px left : 88px marginBottom : 5px marginLeft : 5px marginRight : 5px marginTop : 5px paddingBottom : 1px paddingLeft : 1px paddingRight : 1px paddingTop : 1px top : 131px width : 300px
速度的なファクター
window.getComputedStyle(node, null, option) の速度比較
指定しない(0x0) | 0x1 | 0x2 | |
IE8 | 1.375ms | 0.797ms | 0.281ms |
IE6 | 1.875ms | 0.906ms | 0.313ms |
Google Chrome4(dev) | 測定不能 < 0ms | ||
Firefox3.5.3 | 0.012ms |
node.currentStyle との速度比較
IE8 | 測定不能 < 0ms |
IE6 | 0.015ms |
さっぱりテストできていないので
- 不屈の精神をお持ちでない方には、お勧めできません。
- バグがありそうだけど、網羅的なテストケースは作れそうにないので、とりあえず公開しました。
テストコード
<!doctype html><html><head><meta charset="utf-8" /> <title>window.getComputedStyle for IE</title> <style> #out { border: 1em solid green; margin: 5px; padding: 1px; } #out2 { border: 1em solid green; margin: 5px; padding: 1px; position: absolute; top: 20%; left: 88px; width: 300px; height: 400em; } </style> <script src="http://uupaa-js.googlecode.com/svn/trunk/0.7/uu.js"></script> <script src="uu.cstyle.js"></script> <script> function perf(node, loop, option) { var rv, i = 0; for (; i < loop; ++i) { if (1) { rv = window.getComputedStyle(node, null, option); } else { rv = node.currentStyle; } } return rv; } function xboot() { var node = document.getElementById("out2"); var loop = 1000; var option = 0x2; var begin = +new Date; var hash = perf(node, loop, option); var span = +new Date - begin; node.innerHTML = uu.fmt("%j", hash).replace(/,/g, "<br />").replace(/\"/g, " "); node.innerHTML += "<hr />Time: " + (span / loop) + "ms"; } </script></head><body> <div id="out">out</div> <div id="out2">out2</div> </body></html>