使用Javascript向样式表动态添加样式,但我得到一个;无法读取属性';长度';“未定义”的定义;错误

使用Javascript向样式表动态添加样式,但我得到一个;无法读取属性';长度';“未定义”的定义;错误,javascript,css,media-queries,polyfills,Javascript,Css,Media Queries,Polyfills,我目前正在尝试制作我自己的polyfill,这将允许旧浏览器(如Internet Explorer)能够使用传统的css选择器读取和执行媒体查询。流程如下所示: <!DOCTYPE html> <head> <title>Style Manipulation VIA Javascript</title> <link rel="stylesheet" href="css/test.css" /> <link rel="styles

我目前正在尝试制作我自己的polyfill,这将允许旧浏览器(如Internet Explorer)能够使用传统的css选择器读取和执行媒体查询。流程如下所示:

<!DOCTYPE html>
<head>
<title>Style Manipulation VIA Javascript</title>

<link rel="stylesheet" href="css/test.css" />
<link rel="stylesheet" href="css/typo.css" />

</head>
<body>

<div class="wrap">
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
</div>
  • 遍历文档中找到的每个样式表
  • 在样式表中运行每个样式规则以搜索媒体查询
  • 定义我们的目标设备大小,然后应用适当的“id”
  • 将带有选择器的css行动态添加到现有样式表中
  • 其思想是polyfill将搜索媒体查询,然后将父“id”应用于与设备大小对应的主体,例如:

    #tablet .wrap { ... }
    #mobile .wrap { ... }
    #desktop .wrap { ... }
    
    以下是迄今为止javascript的外观:

    var styleSheets = document.styleSheets;
    var debug = false;
    var ruleParts = mediaPart = rules = compiledSel = className = '';
    var dimS = dimB = 0;
    var idList = Array('smallMobile','mobile','tablet','smallDesktop','desktop');
    
    // run through each stylesheet
    for( i = 0; i < styleSheets.length; i++ ) {
    
        // If uncommented will show each stylesheets rules contained therein
        if( debug ) {
            console.log( styleSheets[i].cssRules );
        }
    
        // run through each rule declaration
        for( a = 0; a < styleSheets[i].rules.length; a++ ) {
    
            if( styleSheets[i].rules[a].type == 4 ) {
    
                mediaPart = styleSheets[i].rules[a].media[0].split(' and ');
    
                dimS = parseInt( mediaPart[0].replace(/[():A-Za-z$-]/g, "") );
                dimB = parseInt( mediaPart[1].replace(/[():A-Za-z$-]/g, "") );
    
                if( dimS > 0 && dimB < 418 ) {
                    className = idList[0];
                } else if( dimS > 419 && dimB < 767 ) {
                    className = idList[1];
                } else if( dimS > 768 && dimB < 1024 ) {
                    className = idList[2];
                } else if( dimS > 1025 && dimB < 1201 ) {
                    className = idList[3];
                } else {
                    className = idList[4];
                }
    
    
                if( styleSheets[i].rules[a].cssRules.length > 1 ) {
    
                    for( b = 0; b < styleSheets[i].rules[a].cssRules.length; b++ ) {
    
                        ruleParts = styleSheets[i].rules[a].cssRules[b].cssText.split('{');
                        rules = ruleParts[1].split('}');
    
                        addCSSRule( styleSheets[i], '#'+ className +' '+ ruleParts[0], rules[0], 1 );
    
                        /*
                         *      Investigate why the .insertRule() and addRule() are failing specifically what is causing them to break
                         *      
                         */
    
                    }
    
                } else {
    
                }
    
            }
    
        }
    }
    
    function addCSSRule(sheet, selector, rules, index) {
        if(sheet.insertRule) {
            sheet.insertRule(selector + "{" + rules + "}", index);
        } else {
            sheet.addRule(selector, rules, index);
        }
    }
    
    如果删除对此行的函数调用,则不会出现错误:

    addCSSRule( styleSheets[i], '#'+ className +' '+ ruleParts[0], rules[0], 1 );
    
    因此,我不确定在函数调用和读取
    .length

    我的html如下所示:

    <!DOCTYPE html>
    <head>
    <title>Style Manipulation VIA Javascript</title>
    
    <link rel="stylesheet" href="css/test.css" />
    <link rel="stylesheet" href="css/typo.css" />
    
    </head>
    <body>
    
    <div class="wrap">
        <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
        <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
    </div>
    
    
    通过Javascript进行样式操作
    佩伦特式居住者morbi tristique Sentecus et netus et malesuada以turpis egestas闻名。前庭侵权人、世仇、别有用心者、临时诉讼人、担保人。不要让你的自由人坐在那里。我的生命是永恒的。莫里斯·普莱斯特拉特·埃利芬德·利奥。他是一个聪明的人。威斯康辛州的前庭、调味品、康茂德维塔、奥纳雷西特、威斯康辛州。埃涅亚发酵液、精粹葡萄汁调味品、红莓汁、豆豉箭叶。在turpis枕面部进行非enim治疗。乌特·费利斯。事实上,这是一个错误,是一个错误,是一个错误,是一个错误。阿利奎姆·埃拉特·帕特。Nam dui mi、tincidunt quis、accumsan porttitor、facilisis luctus、metus

    佩伦特式居住者morbi tristique Sentecus et netus et malesuada以turpis egestas闻名。前庭侵权人、世仇、别有用心者、临时诉讼人、担保人。不要让你的自由人坐在那里。我的生命是永恒的。莫里斯·普莱斯特拉特·埃利芬德·利奥。他是一个聪明的人。威斯康辛州的前庭、调味品、康茂德维塔、奥纳雷西特、威斯康辛州。埃涅亚发酵液、精粹葡萄汁调味品、红莓汁、豆豉箭叶。在turpis枕面部进行非enim治疗。乌特·费利斯。事实上,这是一个错误,是一个错误,是一个错误,是一个错误。阿利奎姆·埃拉特·帕特。Nam dui mi、tincidunt quis、accumsan porttitor、facilisis luctus、metus


    总的来说,我需要弄清楚为什么不能读取属性长度,以及是什么在
    addCSSRule
    函数调用中导致了错误。

    样式表对象的IE和W3C实现之间存在显著差异,希望下面的解释足够有帮助:

    function getStyleRules() {
        var rule, rules;
        var sheet, sheets = document.styleSheets;
        var ruleCssText = ['Rules:','',]
    
        for (var i=0, iLen=sheets.length; i<iLen; i++) {
          sheet = sheets[i];
    
          // Get the rules using:
          //
          //        W3C model        IE model
          rules = sheet.cssRules || sheet.rules;
    
          for (var j=0, jLen=rules.length; j<jLen; j++) {
            rule = rules[j];
    
            // The selector is available here in both models,
            // but uppercase in IE so set to lower case
            alert('Selector: ' + rule.selectorText.toLowerCase());
    
            // Getting the actual rule text
            // W3C model - selector and rule
            if (rule.cssText) {
              ruleCssText.push(rule.cssText);
    
            // IE model - rule only, doesn't include selector
            } else if (rule.style) {
              ruleCssText.push(rule.style.cssText.toLowerCase());
            }
          }
          alert(ruleCssText.join('\n'));
        }
    }
    
    但是IE模型没有为rules对象实现type属性(尽管MSDN文档说它实现了,但这是为IE 9和更高版本实现的W3C模型实现的)

    然后:

    请注意,介质是图纸的属性,而不是规则,因此:

          // Perhaps mediaParts (plural)?
          mediaPart = styleSheets[i].media;
    
    更糟糕的是,IE模型有一个带有字符串类型的媒体属性,但它是空的。您可以使用以下方式获取其文本:

    styleSheets[0].cssText.replace(/\s+/g,' ').match(/@media.+}[^{]+}/)
    

    在这里,你似乎期望“和”成为规则。您尚未提供您的规则示例,但如果它们类似于:

    @media screen, print { ... }
    
    然后媒体是媒体规则的列表:
    media[0]
    是屏幕,
    media[1]
    是打印,因此您需要迭代媒体规则


    无论如何,现在已经足够了。

    样式表对象的IE和W3C实现之间存在显著差异,希望下面的解释足够有帮助:

    function getStyleRules() {
        var rule, rules;
        var sheet, sheets = document.styleSheets;
        var ruleCssText = ['Rules:','',]
    
        for (var i=0, iLen=sheets.length; i<iLen; i++) {
          sheet = sheets[i];
    
          // Get the rules using:
          //
          //        W3C model        IE model
          rules = sheet.cssRules || sheet.rules;
    
          for (var j=0, jLen=rules.length; j<jLen; j++) {
            rule = rules[j];
    
            // The selector is available here in both models,
            // but uppercase in IE so set to lower case
            alert('Selector: ' + rule.selectorText.toLowerCase());
    
            // Getting the actual rule text
            // W3C model - selector and rule
            if (rule.cssText) {
              ruleCssText.push(rule.cssText);
    
            // IE model - rule only, doesn't include selector
            } else if (rule.style) {
              ruleCssText.push(rule.style.cssText.toLowerCase());
            }
          }
          alert(ruleCssText.join('\n'));
        }
    }
    
    但是IE模型没有为rules对象实现type属性(尽管MSDN文档说它实现了,但这是为IE 9和更高版本实现的W3C模型实现的)

    然后:

    请注意,介质是图纸的属性,而不是规则,因此:

          // Perhaps mediaParts (plural)?
          mediaPart = styleSheets[i].media;
    
    更糟糕的是,IE模型有一个带有字符串类型的媒体属性,但它是空的。您可以使用以下方式获取其文本:

    styleSheets[0].cssText.replace(/\s+/g,' ').match(/@media.+}[^{]+}/)
    

    在这里,你似乎期望“和”成为规则。您尚未提供您的规则示例,但如果它们类似于:

    @media screen, print { ... }
    
    然后媒体是媒体规则的列表:
    media[0]
    是屏幕,
    media[1]
    是打印,因此您需要迭代媒体规则


    无论如何,现在已经足够了。

    什么是
    样式表[i]。规则[a]。cssRules
    ?执行
    document.styleSheets[0].rules[0].cssRules
    将给出未定义的,但您正在尝试访问此属性的属性长度。@PaulS。这将遍历给定样式表中的所有样式规则。总的来说,它告诉我样式表中有多少条规则。如果您执行类似于:
    console.log(stylesheets[i].cssRules)的操作,样式表的方式有点复杂这将为您提供所有规则,但在规则中标识的媒体查询中,您还将找到另一个包含媒体查询中所有规则的规则列表。因此,通过规则迭代加密出任何不属于==4类型的内容,消除所有其他传统的非媒体查询。我承认规则子列表可能存在,但您假设存在,并不实际检查它,并且它涉及长度,这让我觉得非常可疑。在此之前记录日志,以便查看是否抛出错误。IE模型没有实现rules对象的type属性,因此上述方法在实现它的浏览器(例如IE 8)中不起作用。@PaulS。实际上,在执行循环之前,我确实签入了代码,这行代码是:
    if(样式表[I].rules[a].cssRules.length>1)
    @罗布:我不知道
    @media screen, print { ... }