【问题标题】:Merging css classes with jQuery/Javascript将 css 类与 jQuery/Javascript 合并
【发布时间】:2011-10-05 05:07:06
【问题描述】:

我有问题。我有一个大量使用多个 css 类的网页。

<div class="class1 class2 class3">foo</div>

不幸的是,我有一个“浏览器”(因为没有更好的术语)不能以这种方式处理多个 css 类。

我可以用multiple classes 识别所有元素,但现在我需要创建新的类来合并它们。第一次尝试是将所有样式内联到样式属性中,但这太慢了,并且不必要地使文档膨胀。

我现在要做的是找到一个具有多个类的元素。创建一个作为组合的新类,并将元素类替换为新创建的类,以及具有相同类组合的任何其他元素。

关于如何最好地解决这个问题的任何想法。

【问题讨论】:

  • 你为什么在客户端而不是服务器上这样做??
  • 如果“浏览器”不能进行这样的基本样式设置,您是否希望它能够处理 jQuery?
  • @epascarello,因为页面最初是在真实浏览器中渲染的,然后在客户端进行了大量修改。问题在于导出到客户端上的另一个“浏览器”。它不能在服务器上完成。我只需要在导出之前修改html中的类。
  • @Lekensteyn,是的,因为执行 jQuery 的浏览器是一个真正的浏览器,它将 html 传递给另一个“浏览器”。不幸的是,第二个浏览器无法处理多个类。
  • 真的吗?否决票?为什么?这个问题符合所有准则,不是骗人的。

标签: javascript jquery html css


【解决方案1】:

遍历所有标签。将类名拆分为一个数组。对其进行排序以使其成为可预测的顺序。将字符串重新连接在一起。

$(document).ready(function() {
    var classList = {};
    $("*").each(function() {
        var temp;
        if (this.className) {
            temp = this.className.split(" "); // split into array
            temp.sort();                      // put in predictable order
            this.className = temp.join("");   // put class name back without spaces
            classList[this.className] = true; // add to list
        }
    });
    // classList object contains full list of all classNames used
});

仅供参考,你有一个支持 jQuery 的浏览器,但不支持多个类名的 CSS 样式,这似乎真的很奇怪。您确实意识到您将不得不提供完全不同的样式表来处理连接的名称,对吗?而且,如果您可以更改样式表,我想知道为什么您不能更改 HTML。

工作实施:http://jsfiddle.net/jfriend00/uPET7/

【讨论】:

  • 我也想即时创建新样式表。而IE6会有这个问题。这不是我的情况,但发生这种情况并不奇怪。
  • 我对IE6的理解和你不一样。它将处理一个对象上的多个类名。我不会在样式表中处理多个类名。它有这个问题:p.red.blue { color: magenta; },但不是class="first second"。您确定您正在尝试解决正确的问题吗?
  • 啊,是的,但是是的,我正在尝试解决正确的问题,ie6 不是我的问题。我确切地知道问题是什么,减少到元素中的一个类可以解决它。
  • 它让我成功了一半。但我还需要即时创建新样式表。
  • 您的问题并没有明确表明您希望代码也合并样式表。这是用于什么浏览器的?
【解决方案2】:

总结:这个函数返回一个所有重复类名的有序列表,可以很容易地用于合并类。

首先,获取一个有用的重复列表:

var multi = {};

$("*[class]").each(function(){
    var class = this.className.replace(/^\s+|\s+$/g,"").replace(/\s+/g,".");
    if(!/\./.test(class)) return; //Ignore single classes
    if(multi[class]){
        multi[class]++;
    } else {
        multi[class] = 1;
    }
});

//Now, merge duplicates, because .class1.class2 == .class2.class1
var multi_nodup = {};
for(var classes in multi){
    var a_classes = classes.split(".");
    var a_classes = a_classes.sort();
    var a_classes = a_classes.join(".");
    if(multi_nodup[a_classes]){
        multi_nodup[a_classes] += multi[classes];
    } else {
        multi_nodup[a_classes] = multi[classes]
    }
}
//Now, multi_npdup is a map of all duplicate classnames

var array_multi = [];
for(var classes in multi_nodup){
    array_multi.push([multi_nodup[classes], classes]);
}
array_multi.sort(function(x,y){return y[0]-x[0]});
//array_multi is an array which looks like [["class1.class2.class2", 33],
//             ["class3.class4", 30], ...]
// = A list, consisting of multiple class names, where multiple classnames
// are shown, together with the nuber of occurences, sorted according to
// the frequence

执行我的函数,并输出变量array_multi。这将向您显示多个类名的映射,以便您可以相应地替换多个类名。

由于我存储类名的特殊方式,您可以使用$("." + array_multi[n][0]) 访问具有一组类名的所有元素array_multi.

可读输出示例:

//Overwrites current document!
var list = "";
for(var i=0; i<array_multi.length; i++) list += array_multi[i][0] + "\t" + array_multi[i][1];
document.open();
document.write("<pre>"+list+"</pre>")
document.close();

自动转换

通过将所有单独的类属性添加到 JavaScript 字符串并将其添加到对象来自动合并类名 i 的方法。这是获取确切 CSS 属性的最可靠方法,因为尝试通过 document.styleSheets 对象获取类名可能会产生略微不同的结果。示例:

var classStyle = {};
classStyle["class1"] = "border:1px solid #000;";
classStyle["class2"] = "color:red";

//Make sure that each declaration ends with a semicolon:
for(var i in classStyle) if(!/;$/.test(classStyle[i])) classStyle[i] += ";";

//Initialise
var all_styles = {};
for(var i=0; i<array_multi.length; i++){
    all_styles[array_multi[i][1]] = "";
}

//This loop takes definition precedence into account
for(var currentCName in classStyle){
    var currentClass = new RegExp("(?:^|\\.)" + currentCName + "(?:\\.|$)");

    // Rare occasion of failure: url("data:image/png,base64;....")
    var separateProps = classStyle[currentCName].split(";");
    var prop_RE = {};
    for(var p=0; p<separateProps.length; p++){
        var cssProperty = separateProps[p];
        if(!/:/.test(cssProperty)) continue; //Invalid CSS property
        prop_RE[cssProperty] = new RegExp("(^|;)\\s*" + cssProperty.match(/(\S+)\s*:/gi)[1] + "\\s*:[^;]+;?", "gi");
    }

    for(var class in all_styles){
        if(currentClass.test(class)){
            for(var k in prop_RE){
                all_styles[class] = all_styles[class].replace(prop_RE[k],"$1") + k;
            }
        }
    }
}

//To finish off:
var allClassesToString = "";
for(var class in all_styles){
    var newClass = class.replace(/\./g, "_");
    $("."+class).each(function(){
        this.className = newClass;
    });
    allClassesToString += "."+newClass + "{" + all_styles[class] + "}\n";
}

// allClassesToString <------- This variable now holds a string of all duplicate CSS classes!
//Example:
var style = $("<style>");
style.text(allClassesToString);
style.appendTo($("head:first"));

【讨论】:

    【解决方案3】:

    完成这个似乎并不疯狂,

    遍历具有超过 1 个类的每个元素。对类进行排序(只要它是一致的就不管多长时间),然后将它们合并在一起以创建新类。保留所有新 css 类的列表,并检查是否有重复。

    要从元素中获取所有样式,请参阅here

    【讨论】:

    • “然后将它们合并在一起以创建新类”是我正在努力解决的部分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-18
    • 2012-04-09
    • 2013-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多