mass Framework css模块

这里实际包含两个文件,在IE9中,它完全支持W3C那种精确获取样式的API,因此无需使用currentStyle与runtimeStyle,因此对于旧式IE的兼容单独放到一个JS文件中。

css.js


//=========================================

// 样式操作模块 by 司徒正美 2011.8.23

//=========================================

(function(global,DOC){

    var dom = global[DOC.URL.replace(/(#.+|\W)/g,'')],

    deps = global.getComputedStyle ?  "node" : "node,css_ie" ;

    dom.define("css", deps, function(){

        dom.log("已加载css模块")

        var cssFloat = dom.support.cssFloat ? 'cssFloat': 'styleFloat',rcap = /-([a-z])/g,capfn = function($0,$1){

            return $1.toUpperCase();

        },

        adapter = dom.cssAdapter = dom.cssAdapter || {};

        function cssCache(name){

            return cssCache[name] || (cssCache[name] = name == 'float' ? cssFloat : name.replace(rcap, capfn));

        }

        dom.mix(dom, {

            //http://www.cnblogs.com/rubylouvre/archive/2011/03/28/1998223.html

             cssName : function (name){

                var prefixes = ['', '-ms-','-moz-', '-webkit-', '-khtml-', '-o-','ms-']

                dom.cssName = function(name, target, test){

                    target = target || document.documentElement.style;

                    for (var i=0, l=prefixes.length; i < l; i++) {

                        test = (prefixes[i] + name).replace(rcap,capfn);

                        if(test in target){

                            return test;

                        }

                    }

                    return null;

                }

                return dom.cssName(name);

            },

            cssCache: cssCache,

            cssNumber : dom.oneObject("fontSizeAdjust,fontWeight,lineHeight,opacity,orphans,widows,zIndex,zoom"),

            css: function(nodes, name, value){

                var  props = {}, fn

                if(nodes.nodeType == 1){

                    nodes = [nodes]

                }

                if ( value === void 0 ) {//获取样式

                    try{

                        return (adapter[name+":get"] || adapter["_default:get"])( nodes[0], cssCache(name) );

                    }catch(e){

                        dom.log(e)

                    }

                }else {//设置样式

                    if(typeof name == "string"){

                        props[name] = value;

                    }else{

                        props = name;

                    }

                    for(name in props){

                        value = props[name];

                        name = cssCache(name);

                        fn = adapter[name+":set"] || adapter["_default:set"];

                        if ( isFinite( value ) && !dom.cssNumber[ name ] ) {

                            value += "px";

                        }

                        for(var i = 0, node; node = nodes[i++];){

                            if(node && node.nodeType === 1){

                                fn(node, name, value );

                            }

                        }

                    }

                }

                return nodes;

            }

        });



        dom.fn.css = function(name,value){

            return dom.css(this, name,value);

        }

        //========================= 处理 width height =========================

        var cssShow = {

            position: "absolute",

            visibility: "hidden",

            display: "block"

        }

        var cssPair = {

            width:['Left', 'Right'],

            height:['Top', 'Bottom']

        }

        function swap( node, options, callback ) {

            var old = {};

            for ( var name in options ) {

                old[ name ] = node.style[ name ];

                node.style[ name ] = options[ name ];

            }

            callback.call( node );

            for ( name in options ) {

                node.style[ name ] = old[ name ];

            }

        }

        // clientWidth         = node.style.width + padding

        // https://developer.mozilla.org/en/DOM/element.clientWidth

        // offsetWidth           = node.style.width + padding + border

        // https://developer.mozilla.org/en/DOM/element.offsetWidth

        // getBoundingClientRect = node.style.width + padding + border

        // https://developer.mozilla.org/en/DOM/element.getBoundingClientRect

        //   [CSS2.1 盒子模型] http://www.w3.org/TR/CSS2/box.html

        //       B-------border----------+ -> border

        //       |                       |

        //       |  P----padding----+    | -> padding

        //       |  |               |    |

        //       |  |  C-content-+  |    | -> content

        //       |  |  |         |  |    |

        //       |  |  |         |  |    |

        //       |  |  +---------+  |    |

        //       |  |               |    |

        //       |  +---------------+    |

        //       |                       |

        //       +-----------------------+

        //       B = event.offsetX/Y in WebKit

        //           event.layerX/Y  in Gecko

        //       P = event.offsetX/Y in IE6 ~ IE8

        //       C = event.offsetX/Y in Opera

        function getWH( node, name ) {

            var which =  cssPair[name], getter = dom.cssAdapter["_default:get"],

            val = name === "width" ? node.offsetWidth : node.offsetHeight;

            which.forEach(function(direction){

                val -= parseFloat(getter(node, 'padding' + direction)) || 0;

                val -= parseFloat(getter(node, 'border' + direction + 'Width')) || 0;

            });

            return val;

        }

        "width,height".replace(dom.rword,function(name){

            dom.cssAdapter[ name+":get" ] = function(node, name, value){

                if ( node.offsetWidth !== 0 ) {

                    value = getWH( node, name ) ;

                } else {

                    swap( node, cssShow, function() {

                        value = getWH( node, name );

                    });

                }

                return value + "px"

            }

        });

        //IE9 FF等支持getComputedStyle

        dom.mix(adapter, {

            "_default:get" :function( node, name){

                return node.style[ name ];

            },

            "_default:set" :function( node, name, value){

                return node.style[ name ] = value;

            }

        },false);



        if ( DOC.defaultView && DOC.defaultView.getComputedStyle ) {

            adapter[ "_default:get" ] = function( node, name ) {

                var ret, defaultView, computedStyle;

                if ( !(defaultView = node.ownerDocument.defaultView) ) {

                    return undefined;

                }

                var underscored = name == "cssFloat" ? "float" : name.replace( /([A-Z]|^ms)/g, "-$1" ).toLowerCase();

                if ( (computedStyle = defaultView.getComputedStyle( node, null )) ) {

                    ret = computedStyle.getPropertyValue( underscored )

                    ret = ret.replace(/\d*(?:\.\d+px)/,function(a){

                        return parseFloat(a).toFixed()+"px"

                    });

                    if ( ret === "" && !dom.contains( node.ownerDocument, node ) ) {

                        ret = node.style[name];//如果还没有加入DOM树,则取内联样式

                    }

                }

                return ret;

            };

        }

        //========================= 处理 user-select =========================

        //https://developer.mozilla.org/en/CSS/-moz-user-select

        //http://www.w3.org/TR/2000/WD-css3-userint-20000216#user-select

        //具体支持情况可见下面网址

        //http://help.dottoro.com/lcrlukea.php

        adapter[ "userSelect:set" ] = function( node, name, value ) {

            name = dom.cssName(name);

            if(typeof name === "string"){

                return node.style[name] = value

            }

            var allow = /none/.test(value||"all");

            node.unselectable  = allow ? "" : "on";

            node.onselectstart = allow ? "" : function(){

                return false;

            };

        };



        //http://msdn.microsoft.com/en-us/library/cc304082(v=vs.85).aspx

        var test = dom('<div style="background-position: 3px 5px">');

        dom.support.backgroundPosition   = test.css('backgroundPosition')  === "3px 5px" ? true : false;

        dom.support.backgroundPositionXY = test.css('backgroundPositionX') === "3px" ? true : false;

        test = null;

        //如果像IE67那样,只支持backgroundPositionXY,不支持backgroundPosition

        var XY = ["X","Y"],prefix = "backgroundPosition";

        if (!dom.support.backgroundPosition && dom.support.backgroundPositionXY) {

            adapter[prefix+":get"] = function( node, name) {

                return XY.map(function(which){

                    return adapter[ "_default:get" ](node,prefix+which)

                }).join(" ");

            }

            adapter[prefix+":set"] =function(node, name, value){

                XY.forEach(function(which,i){

                    node.style[ prefix +which ] = value.split(/\s/)[i]

                })

            }

        }

        function parseBgPos(bgPos) {

            var parts  = bgPos.split(/\s/),

            values = {

                "X": parts[0],

                "Y": parts[1]

            };

            return values;

        }

        if (dom.support.backgroundPosition && !dom.support.backgroundPositionXY) {

            XY.forEach(function(which){

                adapter[prefix+which+":get"] = function(node,name){

                    var values = parseBgPos( adapter[ "_default:get" ](node,prefix) );

                    return values[ which];

                }

                adapter[prefix+which+":set"] = function(node,name,value){

                    var values = parseBgPos( adapter[ "_default:get" ](node,prefix) ),

                    isX = which === "X";

                    node.style.backgroundPosition = (isX ? value : values[ "X" ]) + " " +

                    (isX ? values[ "Y" ] : value);

                }

            })

        }





    });



})(this,this.document);



css_ie.js




(function(global,DOC){

    var dom = global[DOC.URL.replace(/(#.+|\W)/g,'')];

    dom.define("css_ie", function(){

        dom.log("已加载css_ie模块")

        var adapter = dom.cssAdapter = {};

        //========================= 处理 opacity =========================

        var  ropacity = /opacity=([^)]*)/i,  ralpha = /alpha\([^)]*\)/i,

        rnumpx = /^-?\d+(?:px)?$/i, rnum = /^-?\d/;

        adapter["opacity:get"] = function(node,op){

            //这是最快的获取IE透明值的方式,不需要动用正则了!

            if(node.filters.alpha){

                op = node.filters.alpha.opacity;

            }else if(node.filters["DXImageTransform.Microsoft.Alpha"]){

                op = node.filters["DXImageTransform.Microsoft.Alpha"].opacity

            }else{

                op = (node.currentStyle.filter ||"opacity=100").match(ropacity)[1];

            }

            return (~~op)/100;

        }

        adapter["opacity:set"] = function(node, name, value){

            var currentStyle = node.currentStyle, style = node.style;

            if(!currentStyle.hasLayout)

                style.zoom = 1;//让元素获得hasLayout

            value = (value > 0.999) ? 1: (value < 0.001) ? 0 : value;

            if(node.filters.alpha){

                //必须已经定义过透明滤镜才能使用以下便捷方式

                node.filters.alpha.opacity = value * 100;

            }else{

                style.filter = "alpha(opacity="+((value * 100) | 0)+")";

            }

            //IE7的透明滤镜当其值为100时会让文本模糊不清

            if(value === 1){

                style.filter = currentStyle.filter.replace(ralpha,'');

            }

            style.visibility = value ? "visible" : "hidden";

            if(node.tagName === "TR"){//IE bug,TD与TH不会继承TR的透明度

                var self = arguments.callee;

                dom.slice(node.cells).forEach(function(cell){

                    self(cell,name, value);

                });

            }

        }

        var ie8 = !!global.XDomainRequest,

        border = {

            thin:   ie8 ? '1px' : '2px',

            medium: ie8 ? '3px' : '4px',

            thick: ie8 ? '5px' : '6px'

        };



        adapter[ "_default:get" ] = function(node, name){

            var ret = node.currentStyle && node.currentStyle[name];

            if ((!rnumpx.test(ret) && rnum.test(ret))) {

                // Remember the original values

                var style = node.style,

                left = style.left,

                rsLeft = node.runtimeStyle && node.runtimeStyle.left ;

                if (rsLeft) {

                    node.runtimeStyle.left = node.currentStyle.left;

                }

                style.left = name === 'fontSize' ? '1em' : (ret || 0);

                ret = style.pixelLeft + "px";

                // Revert the changed values

                style.left = left;

                if (rsLeft) {

                    node.runtimeStyle.left = rsLeft;

                }

            }

            if(ret == "medium"){

                name = name.replace("Width","Style");

                //border width 默认值为medium,即使其为0"

                if(arguments.callee(node,name) == "none"){

                    ret = "0px";

                }

            }

            return ret === "" ? "auto" : border[ret] ||  ret;

        }

    });

})(this,this.document);

//2011.9.5

//将cssName改为隋性函数,修正msTransform Bug

相关测试:


dom.define("test/css","spec,css",function(){

    dom.addTestModule("样式操作模块-css",{

        "dom.fn.css":function(){





            var el = dom('<div id="test-div" ' +

                'style="padding-left: 2pt; ' +

                'background: transparent; ' +

                'font-size:16px;' +

                'float: left; ' +

                'border: 5px solid rgb(0,0,0);">css test</div>').appendTo("body");

            el = dom("#test-div")



            expect(el.css( 'float')).eq('left');//1

            expect(el.css( 'position')).eq('static');//2

            expect(el.css( 'backgroundColor')).match(function(val){

                return val == "rgba(0, 0, 0, 0)" || val == "transparent"

            });//3

            expect(el.css( 'backgroundPosition')).eq("0% 0%");//4

            expect(el.css( 'backgroundPositionX')).eq('0%');//5

            expect(el.css( 'fontSize')).eq('16px');//6

            expect(el.css( 'border-right-width')).eq('5px');//7

            var matchFn = function(val){

                val = parseFloat(val)

                return val >= 2 && val <= 3

            }

            expect(el.css( 'paddingLeft')).match(matchFn);//8

            expect(el.css( 'padding-left')).match(matchFn);//9

            expect(el.css( 'padding-right')).eq('0px');//10

            expect(el.css( 'opacity')).eq('1');//11



            // 不加入 dom 节点,ie9,firefox 返回 auto by computedStyle

            // ie7,8 返回负数,offsetHeight 返回0

            //alert(elem.currentStyle.height);== auto

            expect(parseInt(el.css( 'height'))).match(function(val){

                val = parseFloat(val)

                return val >= 18 && val <= 20

            });//12



            el.css( 'float', 'right');



            expect(el.css( 'float')).eq('right');//13



            el.css( 'font-size', '100%');



            expect(el.css( 'font-size')).eq("16px");//14



            el.css( 'opacity', '0.2');



            expect(el.css( 'opacity')).match(function(val){

                val = parseFloat(val);

                return val >= 0.2 && val < 0.21;

            });



            el.css( 'border', '2px dashed red');



            expect(el.css( 'borderLeftWidth')).eq('2px');//16

            el.remove();



        }

    });

});



使用方法与jQuery保持一致,读写器合而为一,set all get first。


      dom.require("css",function(){

        var a = dom('<div style="width:100px;opacity:0.7;filter:alpha(opacity=50),blur(add=ture,direction=135,strength=200)">');

        dom.log( a.css("opacity"))//IE9,FF为0.7;IE6-8为0.5

      });

你可能感兴趣的:(framework)