简体   繁体   English

使用jQuery / Javascript合并css类

[英]Merging css classes with jQuery/Javascript

I have a problem. 我有个问题。 I have a bunch webpage that makes heavy use of multiple css classes. 我有一堆网页,大量使用多个css类。

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

Unfortunately, I have a "browser" (for lack of a better term) that can not handle multiple css classes in that manner. 不幸的是,我有一个“浏览器”(缺少一个更好的术语)无法以这种方式处理多个css类。

I can identify all the elements with multiple classes but now I need to create new classes that merge them. 我可以识别具有多个类的所有元素,但现在我需要创建合并它们的新类。 First attempt was to inline all the styles into the style attribute, however that was far too slow, and bloated the document needlessly. 第一次尝试是将所有样式内联到样式属性中,但这太慢了,并且文档不必要地膨胀。

What I now want to do is find an element with multiple classes. 我现在想要做的是找到一个包含多个类的元素。 Create a new class which is a combination, and replace the elements class with the newly created one, as well as any other elements with the same class combination. 创建一个组合的新类,并将元素类替换为新创建的类,以及具有相同类组合的任何其他元素。

Any thoughts on how best to approach this. 关于如何最好地接近这个的任何想法。

Loop through all tags. 循环遍历所有标签。 Split the class names into an array. 将类名拆分为数组。 Sort it to get it into a predictable order. 对其进行排序以使其成为可预测的顺序。 Join the string back together. 将字符串重新加入。

$(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
});

FYI, it seems really odd that you'd have a browser that supports jQuery, but doesn't support CSS styles for multiple class names. 仅供参考,你有一个支持jQuery的浏览器似乎很奇怪,但不支持多个类名的CSS样式。 You do realize that you are going to have to supply completely different stylesheets that work off the concatenated names, right? 你确实意识到你将不得不提供完全不同的样式表来解决连接的名称,对吗? And, if you can change the stylesheets, it makes me wonder why you can't change the HTML. 而且,如果您可以更改样式表,那么我会想知道为什么您无法更改HTML。

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

Summary: This function returns an ordered list of all duplicate class names, which can easily be used to merge classes. 简介:此函数返回所有重复类名的有序列表,可以轻松地用于合并类。

To start off, get a useful list of duplicates: 首先,获取有用的重复列表:

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

Execute my function, and output variable array_multi . 执行我的函数,并输出变量array_multi This will show you a map of multiple class names, so that you can replace multiple classnames, accordingly. 这将显示多个类名称的映射,以便您可以相应地替换多个类名。

Because of the special way I stored the class names, you can use $("." + array_multi[n][0]) to access all elements which have a set of classname which equals to the set as described at the n th position in array_multi . 由于我存储类名的特殊方式,您可以使用$("." + array_multi[n][0])来访问所有具有一组classname的元素,该类名等于第n个位置描述的set在array_multi

Example of readable output: 可读输出示例:

//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();

Automatic conversion 自动转换

A way to automate the merging of the classnames i by adding all separate class properties to a JavaScript string, and add it to an object. 一种通过将所有单独的类属性添加到JavaScript字符串来自动合并类名i的方法,并将其添加到对象中。 This is the most reliable way to get the exact CSS properties, because attempting to get the classnames through the document.styleSheets object can produce slightly different results. 这是获取确切CSS属性的最可靠方法,因为尝试通过document.styleSheets对象获取类名可能会产生稍微不同的结果。 Example: 例:

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"));

Does not seem to crazy to accomplish this, 完成这个似乎并不疯狂,

Loop through every element that has more than 1 class. 遍历每个具有多个类的元素。 Sort the classes (doesn't matter how as long as it is consistent) then merge them together to create the new class. 对类进行排序(只要它是一致的无关紧要)然后将它们合并在一起以创建新类。 Keep a list of all new css classes and check against them in case of duplicates. 保留所有新css类的列表,并在重复的情况下检查它们。

To get all the styles from an element see here 要从元素中获取所有样式,请参见此处

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM