现在的位置: 首页 > 综合 > 正文

JavaScript DOM高级程序设计 5动态修改样式和层叠样式表2–我要坚持到底!

2012年09月06日 ⁄ 综合 ⁄ 共 9517字 ⁄ 字号 评论关闭

把样式置于DOM脚本之外

  • style属性

我们可以这样设置前景色之类的属性:

element.style.color='red';

也可以使用下面的代码设置背景颜色:

element.style.backgroundColor='red';

 将background-color转换为驼峰形式大小写形式的backgroundColor(删除连接字符串并将后续单词的首字母变成大写)是必须的,DOM2样式规范为CSSStyleDeclaration对象定义了相应的方法,比如setProperty()就使用固有的带连字符的CSS属性名称和值(但是ie不支持):

element.style.setProperty('background-color','red');

为了不针对环境,将setStyleById(),setStyleByClassName(),setStylsByTagName()方法添加到ADS库中。

/**
 *通过ID修改单个元素的样式
 */
function setStyleById(element, styles) {
    //取得对象的引用
    if(!(element = $(element))) return false;
    //循环遍历styles对象并应用每个属性
    for (property in styles) {
        if(!styles.hasOwnProperty(property)) continue;
    
        if(element.style.setProperty) {
            //DOM2样式规范方法
            element.style.setProperty(
            uncamelize(property,'-'),styles[property],null);
        } else {
            //备用方法
            element.style[camelize(property)] = styles[property];
        }
    }
    return true;
}
window['ADS']['setStyle'] = setStyleById;
window['ADS']['setStyleById'] = setStyleById;

/**
 * 通过类名修改多个元素的 样式
 */
function setStylesByClassName(parent, tag, className, styles) {
    if(!(parent = $(parent))) return false;
    var elements = getElementsByClassName(className, tag, parent);
    for (var e = 0 ; e < elements.length ; e++) {
        setStyleById(elements[e], styles);
    }
    return true;
}
window['ADS']['setStylesByClassName'] = setStylesByClassName;

/**
 * 通过标签名修改多个元素的样式
 */
function setStylesByTagName(tagname, styles, parent) {
    parent = $(parent) || document;
    var elements = parent.getElementsByTagName(tagname);
    for (var e = 0 ; e < elements.length ; e++) {
        setStyleById(elements[e], styles);
    }
}
window['ADS']['setStylesByTagName'] = setStylesByTagName;
/**实例
 ADS.setStylesByClassName(
    'findclass',
    '*',
    document,
    {'background-color':'red'}
 )
 或者

 ADS.setStylesByTagName('a',{'text-decoration':'underline'});
*/

基于className切换样式

对于中小范围的表现变化,例如只影响少数元素的颜色、边框、背景和字体,可以通过切换className来避免在代码中苦苦寻找样式属性。

使用className切换方法可以维护适当的分离,并且为CSS设计者打开了使用样式表设计网站表现的大门。下面将操纵classname的方法添加到ADS库中

/*取得包含元素类名的数组*/
function getClassNames(element) {
    if(!(element = $(element))) return false;
    //用一个空格替换多个空格,然后给予空格分割类名
    return element.className.replace(/\s+/,' ').split(' ');
};
window['ADS']['getClassNames'] = getClassNames;

/*检查元素是否存在某个类*/
function hasClassName(element, className) {
    if(!(element = $(element))) return false;
    var classes = getClassNames(element);
    for (var i = 0; i < classes.length; i++) {
       //检测className是否匹配,如果是则返回true
        if (classes[i] === className) { return true; }
    }
    return false;
};
window['ADS']['hasClassName'] = hasClassName;


/*为元素添加类*/
function addClassName(element, className) {
    if(!(element = $(element))) return false;
    //将类名添加到当前className的末尾,如果没有className,则不包含空格
    element.className += (element.className ? ' ' : '') + className;
    return true;
};
window['ADS']['addClassName'] = addClassName;

/*从元素中删除类*/
function removeClassName(element, className) {
    if(!(element = $(element))) return false;
    var classes = getClassNames(element);
    var length = classes.length
   //循环遍历数组删除匹配的项
    //因为从数组中删除项会使数组变短,所以要反响循环
    for (var i = length-1; i >= 0; i--) {
        if (classes[i] === className) { delete(classes[i]); }
    }
    element.className = classes.join(' ');
    return (length == classes.length ? false : true);
};
window['ADS']['removeClassName'] = removeClassName;


/*
方便的取得与一个元素关联的所有累
var element=document.getElementById('example');
var classes=ADS.getClassName(element);
var class;
for (var i = 0;class=class[i];i++)
{
    //对每个类进行操作
}

或者在向元素添加类名之前检查是否存在该雷鸣,以便实现切换效果
function toggleClassName(element,className)
{
    if(!)ADS.hasClassName(element,className)
    {
        ADS.addClassName(element,className);
    }
    else
    {
        ADS.removeClassName(element,className);
    }
}
ADS.addEvent('toggleButton','click',function(){
    toggleClassName(this,'active')
});

甚至还能通过使用适当的事件侦听器和hover类生成翻转效果
var element=document.getElementById('example');
ADS.addEvent(element,'mouseover',function(){ADS.addClassName(this,'hover');});
ADS.addEvent(element,'mouseout',function(){ADS.removeClassName(this,'hover')});
*/
  • 切换样式表
  1. 可以使用<link>元素的rel属性定义备用的样式表,并在他们之间进行切换。
  2. 可以为body标签应用一个类,并根据这个类修改CSS选择符--实际上是以body标签做为跟元素的className切换
  3. 可以动态添加或移除样式表
  • 使用备用样式表

如果你始终遵守表现与标记分离原则,那你一定熟悉<link>元素:<link type="text/css" href="style.css" media="screen"/>

<link>元素包含一下属性:(和我们本章开始介绍的CSSStyleSheets类似)

  • type:text/css
  • href:指定样式的位置
  • media:限制样式设备类型

这些是常用的,另外还有

  • ref:表示样式与文档之间的关系
  • disable:表示样式是否起作用
  • title:表示与样式表关联的标题

下面讲一个说一个实例,源代码在上一节的chapter5中,switcher/example.html中,在这个例子中公共CSS问津没有设置title属性,而friends of ED和Apress样式都有一个相应的样式表文件,标记中空列表元素:

  <ul id="styleSwitcher"></ul>

是由styleSwitcher.js文件通过load事件处理程序,在备用的样式表文件及其title属性的基础上动态生成的:(其实这个例子看起来听神奇的。)

ADS.addEvent(window,'load',function(){
    //取得所有link元素
    var list=ADS.$('styleSwitcher');
    var links=document.getElementsByTagName('link');
    var titles=[];

    for(var i=0;i<links.length;i++)
    {
        //跳过不带title属性的<link>元素
        if (links[i].getAttribute("rel").indexOf("style")!=-1
            &&links[i].getAttribute("title"))
        {
            //如果该样式表还未添加则想列表中添加一个新项
            var title=links[i].getAttributes("title");
            if (!titles[title])
            {
                var a = document.createElement('a');
                a.appendChild(document.createTextNode(title));
                a.setAttribute('href'.'#');
                a.setAttribute('title','Activate'+title);
                a.setAttribute('rel',title);
                ADS.addEvent(a,'click',function(){
                    //单击激活链接是激活锚的rel属性中的标题所表示的样式
                    setActiveStyleSheet(this.getAttribute('rel'));
                    ADS.preventDefault(W3CEvent);
                });

                var li = document.createElement('Li');
                li.appendChild(a);
                list.appendChild(li);

                //将title数组中的这个标题项设置为true。一边在多样式使用相同的标题跳过
                title[title]=true;
            }
        }
    }
});
  • 切换body元素的className

这种方法的知道思想和上面类似,只不过是body标签的className

/*公共样式*/

body{}
#container{}
/*AdvancED DOM Scripting 样式*/
body.ads{}
body.ads h1{}
body.ads h2{}

/*friends of ED 样式*/
body.foed{}
body.foed h1{}
body.foed h2{}

/*其他样式*/
/*Apress样式*/
body.apress{}
body.apress h1{}
body.apress h2{}

然后用本章前面的ADS库,你可以动态的勤换body标签的类名,而CSS规则会在相应的修改页面表现:

ADS.addEvent('ads-anchor','click',function(){
    ADS.addClassName(document.body,'asd');
});
ADS.addEvent('foed-anchor','click',function(){
    ADS.addClassName(document.body,'foed');
});
ADS.addEvent('apress-anchor','click',function(){
    ADS.addClassName(document.body,'apress');
});
  • 动态载入和移除样式

相当直观,使用这种技术索要做的就是通过document.createElement()及适当的属性<link>

/*添加新样式表*/
function addStyleSheet(url,media)
{
    media=media||'screen';
    var link=document.creatElement('LINK');
    link.settAttribute('rel','stylesheet');
    link.settAttribute('tyle','text/css');
    link.settAttribute('href','url');
    link.settAttribute('media','media');
    document.getElementsByTagName('head')[0].appendChild(link);
}
window['ADS']['addStyleSheet']=addStyleSheet
/*移除样式表*/
function removeStyleSheet(url,media)
{
    var styles=getStyleSheets(url,media);
    for (var i = 0;i<style.length ;i++ )
    {
        var node=styles[i].ownerNode||styles[i].owningElement;
        //禁用样式
        styles[i].disabled=ture;
        //移除节点
        node.parentNode.removeChild(node);
    }
}

window['ADS']['removeStyleSheet']=removeStyleSheet
/**实例
ADS.addStyleSheet('/path/style.css','screen');
ADS.removeStyleSheet('/path/style.css','screen');
*/
  • 修改CSS规则

在ADS库中添加方法,他能帮助你从document.styleSheets列表中查找带有适当的href和media属性的样式表:

/*通过URL取得包含所有样式表的数组*/
function getStyleSheets(url,media) {
    var sheets = [];
    for(var i = 0 ; i < document.styleSheets.length ; i++) {
        if (url &&  document.styleSheets[i].href.indexOf(url) == -1) { continue; }
        if(media) {
            //规范化media字符串
            media = media.replace(/,\s*/,',');
            var sheetMedia;
                
            if(document.styleSheets[i].media.mediaText) {
               //DOM方法
                sheetMedia = document.styleSheets[i].media.mediaText.replace(/,\s*/,',');
               //Safari会添加额外的都和和空格
                sheetMedia = sheetMedia.replace(/,\s*$/,'');
            } else {
                // MSIE
                sheetMedia = document.styleSheets[i].media.replace(/,\s*/,',');
            }
            // 如果media不匹配则跳过
            if (media != sheetMedia) { continue; }
        }
        sheets.push(document.styleSheets[i]);
    }
    return sheets;
}
window['ADS']['getStyleSheets'] = getStyleSheets;

现在找到目标样式表了,但是还需要想库中添加ADS.editCSSRule()和ADS.addCSSRule()方法才能修改其中的样式规则:

/**
 * 编辑一条样式表规则
 */
function editCSSRule(selector,styles,url,media) {
    var styleSheets = (typeof url == 'array' ? url : getStyleSheets(url,media));

    for ( i = 0; i < styleSheets.length; i++ ) {

        //取得规则表
        // DOM2样式规范方法是 styleSheets[i].cssRules
        // MSIE规范方法是styleSheets[i].rules
        var rules = styleSheets[i].cssRules || styleSheets[i].rules;
        if (!rules) { continue; }
               
        // 由于MSIE默认使用大小写故转换为大写形式
        // 如果你使用的是区分大小写的id,则可能导致冲突
        selector = selector.toUpperCase();
        
        for(var j = 0; j < rules.length; j++) {
            // 检查是否匹配
            if(rules[j].selectorText.toUpperCase() == selector) {
                for (property in styles) {
                    if(!styles.hasOwnProperty(property)) { continue; }
                    // 设置新的样式属性
                    rules[j].style[camelize(property)] = styles[property];
                }
            }
        }
    }
}
window['ADS']['editCSSRule'] = editCSSRule;
/*ADS.editCSSRule('a',{'background-color':'yellow'});*/


/**
 * 增加一条CSS样式
 */
function addCSSRule(selector, styles, index, url, media) {
    var declaration = '';

    // 根据style参数构建声明字符串
    for (property in styles) {
        if(!styles.hasOwnProperty(property)) { continue; }
        declaration += property + ':' + styles[property] + '; ';
    }

    var styleSheets = (typeof url == 'array' ? url : getStyleSheets(url,media));
    var newIndex;
    for(var i = 0 ; i < styleSheets.length ; i++) {
        // 添加规则       
        if(styleSheets[i].insertRule) {
            // DOM2样式规范的方法
            // index = length 是列表的结尾
            newIndex = (index >= 0 ? index : styleSheets[i].cssRules.length);
            styleSheets[i].insertRule(selector + ' { ' + declaration + ' } ', 
                newIndex);
        } else if(styleSheets[i].addRule) {
            // MS的方法
            // index = -1 是列表的结尾 
            newIndex = (index >= 0 ? index : -1);
            styleSheets[i].addRule(selector, declaration, newIndex);
        }
    }
}
window['ADS']['addCSSRule'] = addCSSRule;
/**
ADS.addCSSRule('a[href]:after',{
    'content':'"("attr(href)")"';
    'font-size':'40%',
    'color':'#16009b'
});
*/

 

  • 访问计算样式

 

DOM2样式规范在document.defaultView中包含了一个名叫getComputedStyle()的方法,就是为了访问计算样式而设计的。该方法返回一个制度的CSSStyleDeclaration对象。

 

在取得给定元素的计算样式之后,可以通过与操作元素的style属性一样的方式来取得信息

 

var element=ADS.$('example');
var styles=document.defaultView.getComputedStyle(element);

 

取得background-color值需要下面这样简单:

 

var color=styles.getProperty('background-color');

 

我们在库中添加如下代码:

 

/*取得一个元素的计算样式*/
function getStyle(element,property)
{
    if (!element=$(element)||!property) return false;
    
    //检测元素style属性的的值
    var value=element.style[camelize(property)];
    if(!value)
    {
        //计算取得样式的值
        if (document.defaultView&&document.defaultView.getComputedStyle)
        {
            //DOM
            var css=document.defaultView.getComputedStyle(element,null);
            value=css?css.getPropertyValue(property):null;
        }
        else if (element.currentStyle)
        {
            MSIE的方法
            value=element.currentStyle[camelize(property)];
        }
    }

    //返回空字符串而不是auto这样就不必检查auto值了
    return value=='auto'?'':value;
}
window['ADS']['getStyle']=getStyle;
window['ADS']['getStyleById']=getStyle;

 

抱歉!评论已关闭.