动态添加样式表规则
先给出函数。
var addSheet = function (){ var doc,cssCode; if (arguments.length == 1){ doc = document; cssCode = arguments[0] } else if (arguments.length == 2){ doc = arguments[0]; cssCode = arguments[1]; } else { alert( "addSheet函数最多接受两个参数!" ); } if (!+ "\v1" ){ //增加自动转换透明度功能,用户只需输入W3C的透明样式,它会自动转换成IE的透明滤镜 var t = cssCode.match(/opacity:(\d?\.\d+);/); if (t!= null ){ cssCode = cssCode.replace(t[0], "filter:alpha(opacity=" + parseFloat(t[1]) * 100+ ")" ) } } cssCode = cssCode + "\n" ; //增加末尾的换行符,方便在firebug下的查看。 var headElement = doc.getElementsByTagName( "head" )[0]; var styleElements = headElement.getElementsByTagName( "style" ); if (styleElements.length == 0){ //如果不存在style元素则创建 if (doc.createStyleSheet){ //ie doc.createStyleSheet(); } else { var tempStyleElement = doc.createElement( 'style' ); //w3c tempStyleElement.setAttribute( "type" , "text/css" ); headElement.appendChild(tempStyleElement); } } var styleElement = styleElements[0]; var media = styleElement.getAttribute( "media" ); if (media != null && !/screen/.test(media.toLowerCase()) ){ styleElement.setAttribute( "media" , "screen" ); } if (styleElement.styleSheet){ //ie styleElement.styleSheet.cssText += cssCode; } else if (doc.getBoxObjectFor){ styleElement.innerHTML += cssCode; //火狐支持直接innerHTML添加样式表字串 } else { styleElement.appendChild(doc.createTextNode(cssCode)) } } |
有时我们需要在.js文件对文档动态引入一些CSS样式。对于一些短小的CSS代码来说,这好办,我们可以调用其style方法,如
var ddd = document.getElementById( "ddd" ); ddd.style.border = "1px solid red" ; |
如果再长一点也无所谓:
var ddd = document.getElementById( "ddd" ); ddd.style.cssText = "border:1px solid red;color:#000;background:#444;float:left" ; |
本人而言,我是喜欢后者。因为前者有严重的兼容问题。如float这个样式,在IE是styleFloat,在火狐等W3C标准游览器是cssFloat。而cssText则是通吃。
如果很长,我们可以动态导入一CSS文件。如
function addSheetFile(path){ var fileref=document.createElement( "link" ) fileref.rel = "stylesheet" ; fileref.type = "text/css" ; fileref.href = path; fileref.media= "screen" ; var headobj = document.getElementsByTagName( 'head' )[0]; headobj.appendChild(fileref); } |
var oStylesheet = document.createStyleSheet ( sURL , iIndex ); |
createStyleSheet带的两个参数都是可选的。
但如果我们的样式是某个页面独有的,而且只有管理员才能使用到,而且那部分页面是动态生成的,我们需要一开始就引入它吗?需要特意弄个文件来装载它吗?最好的方法让这些样式与动态脚本捆绑在一起。我这个函数就为此而开发的。
坦白说,它最开始是为富文本编辑器而开发的。大家都知道,富文本输入框最流行的做法是把要输入的内容放到iframe中,这就涉及到两种document,一个主页面的document,另一个是iframe的document。 iframe的document又涉及到兼容问题。我们可以:
var iframe = document.createElement( 'iframe' ); //生成用于编辑的rich text editor var iframeDocument = iframe.contentDocument || iframe.contentWindow.document; …… |
嘛,扯远了。总而言之,函数最开始的判定就是为这两种document而准备。如果没有涉及到iframe,我们只传入一个参数就行了。最后一个参数永远是CSS字符串。
然后是动态生成styleSheet元素,把CSS字符串加入到此元素的问题。当然如果有现阶段的,当然就用现成的。DOM元素越多对游览器的负担就越大。我们想到document.styleSheets方法。它返回一个集合,包含style元素与link元素,还涉及一兼容问题,如:
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> < html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> < head > < meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <%# 强制IE8像IE7一样呈现网页 -%> < meta http-equiv=”X-UA-Compatible” content=”IE=EmulateIE7″ /> <%#--默认所有的链接都在本窗口打开 -%> < base target="_self" /> < title ><%= h(yield(:title)) || controller.action_name %></ title > <%= stylesheet_link_tag "screen","button","style" %> < link rel="stylesheet" href="/stylesheets/print.css" type="text/css" media="print"> <!--[if lt IE 8]> <link rel="stylesheet" href="/stylesheets/ie.css" type="text/css" media="screen"> <![endif]--> <%= javascript_tag "window._token = '#{form_authenticity_token}'" if ActionController::Base.allow_forgery_protection %> <%= javascript_include_tag :defaults %> < style type="text/css" media="print"></ style > </ head > |
上面用alert(document.styleSheets.length);测试一下,IE返回6,W3C游览器返回5。因此,否决了它。而且我们只用到style元素,不使用外联。第二部分的判定就针对head中的style元素而言,没有就创建一个。然后我们把CSS字符串加在第一个style元素就行了。
接着我们要加把保险锁,因为当media="print"时,只在页面打印时,定义的效果才有效。为了防止第一个style元素的media值不是screen,我们得改一改。
var styleElement = styleElements[0]; var media = styleElement.getAttribute( "media" ); if (media != null && !/screen/.test(media.toLowerCase()) ){ styleElement.setAttribute( "media" , "screen" ); } |
附上media的一些说明。
- screen (缺省值),提交到计算机屏幕;
- print, 输出到打印机;
- projection,提交到投影机;
- aural,扬声器;
- braille,提交到凸字触觉感知设备;
- tty,电传打字机 (使用固定的字体);
- tv,电视机;
- all,所有输出设备。
最后是如此添加的问题。分IE,火狐与其他游览器三种。判定游览器也用各自的私有属性或方法。如styleSheet是IE独用的,getBoxObjectFor是火狐独用的(当然你也可以使用(/firefox/.test(navigator.userAgent.toLowerCase())),通常DOM操作是最耗时的,能用私有就用私有!
使用方法。
addSheet( "\ .RTE_iframe{width:600px;height:300px;}\ .RTE_toolbar{width:600px;}\ .color_result{width:216px;}\ .color_view{width:110px;height:25px;}\ .color_code{text-align:center;font-weight:700;color:blue;font-size:16px;}\ div.table{width:176px;position:absolute;padding:1px;}\ div.table td{font-size:12px;color:red;text-align:center;}\ " );*/ |
最后追加几个相关的方法:
var getClass = function (ele) { return ele.className.replace(/\s+/, ' ' ).split( ' ' ); }; var hasClass = function (ele,cls) { return ele.className.match( new RegExp( '(\\s|^)' +cls+ '(\\s|$)' )); } //更快的版本 var hasClass = function (ele,cls){ return -1 < ( " " +ele.className+ " " ).indexOf( " " +cls+ " " ); } var addClass = function (ele,cls) { if (! this .hasClass(ele,cls)) ele.className += " " +cls; } var removeClass = function (ele,cls) { if (hasClass(ele,cls)) { var reg = new RegExp( '(\\s|^)' +cls+ '(\\s|$)' ); ele.className=ele.className.replace(reg, ' ' ); } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义