如何从样式表

时间:2017-07-22 20:58:15

标签: javascript jquery html css

我正在开发一个基于jQuery和javascript的项目。我正在尝试使用javascript insert / addRule属性添加CSS规则。我想做的是:

我必须创建悬停效果并使用javascript css属性将它们插入到样式表中。为此,我创建了两个类,例如:

.dummy {.... }

.dummy:hover{.....}

我希望如果我改变悬停效果,那么它必须从样式表中删除前一个(或重复)并将新规则插入样式表。

但问题是,如果我尝试使用deleteRule或removeRule删除或删除CSS规则,则仅删除

.dummy{...}但不是.dummy:hover{...}

这是我的代码,可以帮助您了解我在做什么:

function createNewStyle() {
    var style = document.createElement("style");
    style.setAttribute('id', 'd-set-stylesheet');
    style.appendChild(document.createTextNode(""));
    document.head.appendChild(style);
} // this function might be not required but included here so that you may understand the program flow.

//the main issue is with this function.
function removeIfExists(class_name) {
    var styleTag = document.getElementById("d-set-stylesheet");
    var styleRef = styleTag.sheet ? styleTag.sheet : styleTag.styleSheet;
    if (styleRef.rules) { //all browsers except IE 9-
        console.log(styleRef);
        for (var i in styleRef.cssRules) {
            if (styleRef.cssRules[i].selectorText === "." + class_name+":hover" ||styleRef.cssRules[i].selectorText === "." + class_name )
                styleRef.deleteRule(i);
        }
    } else {
        var i;
        for (i = 0; i < styleRef.rules.length; i++) {
            //if(styleRef.rules[i].selectorText === "."+class_name || styleRef.rules[i].selectorText === "."+class_name+":hover")
            styleRef.removeRule(i);
        }
    }
    return styleRef;
}

 //this function maybe not related with the issue but if it is you can check it.
function setNewClass(element, class_name, classSelector, styleObject) {
    var stylesheet = removeIfExists(class_name);
    if (element.data('hover-class') == null)
        element.data('hover-class', class_name);
    let count = 0;
    var style = [];
    var property = [{
        "append": ":hover"
    }, {
        "append": ""
    }];
    for (j = 0; j < 2; j++) {
        style.push({});
        style[j].sheet = stylesheet;
        style[j].selector = class_name;
        style[j].type = classSelector;
        style[j].property = property[j]["append"];
        style[j].style = "";
    }
    for (i in styleObject) {
        if (styleObject.hasOwnProperty(i))
            if (count % 2 == 0)
                style[0].style += styleObject[i] + ":";
            else
                style[0].style += styleObject[i] + ";";
        count++;
    }
    style[1].style = "transition:" + styleObject.t_property_value;
    addCSSRule(style);
}

function addCSSRule(styleSheet) {
    console.log(styleSheet);
    for (i = 0; i < styleSheet.length; i++)
        if (styleSheet[i].sheet.insertRule)
            styleSheet[i].sheet.insertRule(styleSheet[i].type + styleSheet[i].selector + styleSheet[i].property + "{" + styleSheet[i].style + "}", styleSheet[i].sheet.cssRules.length);
        else
            styleSheet[i].sheet.addRule(styleSheet[i].type + styleSheet[i].selector + styleSheet[i].property, styleSheet[i].sheet.style, -1);
}

以下是console.log的图像 在第一个图像中,悬停和没有悬停类被添加到CSS规则中。 Image-first: before deletion of rules only rules inserted

在第二张图像中,不删除上一个悬停类,而不删除悬停类。我想要悬停转换必须删除。在添加新规则以防止重复类之前,应该防止在悬停元素时进行多个转换。 Image-second: after deletion of rules hover effect is not removed

谢谢。

1 个答案:

答案 0 :(得分:0)

我今天找到了答案。我将解释它,以便将来可以帮助其他人理解问题和解决方案。

通过我的问题,你可以理解这个问题。问题出在这个函数上只有

function removeIfExists(class_name) {
 ......
if (styleRef.rules) { //all browsers except IE 9-
    for (var i in styleRef.cssRules) {
           .....
            styleRef.deleteRule(i); //problem is with this.
           .....
    }
   }
  .......
   return styleRef;
}

当我在一些测试的基础上检查deleteRule时,我发现当调用deleteRule时会发生以下事情:

  1. 根据索引删除css规则。
  2. (最重要的是,因为没有关于此的文档或说明或解释)内容通过索引进行更新。这样我的函数将无法再根据旧索引删除正确的规则。
  3. 为了更好地理解它,我会给你一个例子:

    假设我在css中添加了两条规则,例如:.dummy:hover{...}.dummy{...}

    现在这些规则的索引如下:

    [0]: .dummy:hover rule
    [1]: .dummy rule
    

    当我调用删除规则时会发生什么:

    // at i =0; 
    deleteRule(0);/* will be called and it will remove [0]: .dummy:hover rule
     and then it will update the rules indexing again, which means
     [1]: .dummy rule => [0]: .dummy rule */
    // now when i = 1;
    deleteRule(1); /* will be called and it will try to remove [1]: .dummy rule which is not here anymore and it will just skip the removal of [1]: .dummy rule.
    

    所以我要删除的是开始从最高索引或相反的顺序删除规则,这意味着i = 1规则将首先被删除然后i = 0;规则,以便不会有任何后果。

    并且函数将更改为:

    function removeIfExists(class_name)
    {
        ...
        var styleRef = styleTag.sheet ? styleTag.sheet : styleTag.styleSheet;
        var len = styleRef.cssRules ? styleRef.cssRules.length : styleRef.rules.length;
        if(styleRef.rules){ //all browsers except IE 9-
            for(i=len;i>0;i--)
            {
                    if (styleRef.cssRules[i-1].selectorText === "." + class_name+":hover" ||styleRef.cssRules[i-1].selectorText === "." + class_name )
                    styleRef.deleteRule(i-1);
            }
        }
        ......
        .....
        }
        return styleRef;    
    }
    

    注意:IE会遵循类似的程序,但我没有在此处包含它。