Combining css classes with jQuery / Javascript

I have a problem. I have a webpage that heavily uses several CSS classes.

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

Unfortunately, I have a β€œbrowser” (due to the lack of a better term) that cannot handle multiple CSS classes this way.

I can identify all elements with multiple classes , but now I need to create new classes that combine them. The first attempt was to insert all styles into the style attribute, however it was too slow and inflated the document unnecessarily.

Now I want to find an element with several classes. Create a new class, which is a combination, and replace the element class with a new one, as well as any other elements with the same combination of classes.

Any thoughts on how best to approach this.

+4
source share
3 answers

Summary: This function returns an ordered list of all duplicate class names that can be easily used to combine classes.

To get started, select 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 the variable array_multi . This will show you a map of several class names so that you can replace multiple classes accordingly.

Due to the special way I saved the class names, you can use $("." + array_multi[n][0]) to access all elements that have a set of class names that is equal to the set as described in the nth positions in 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 merging i classes by adding all the individual properties of a class to a JavaScript string and adding it to an object. This is the most reliable way to get the exact properties of CSS, because trying to get cool names through the document.styleSheets object may give slightly different results. 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")); 
+1
source

Scroll through all the tags. Separate the class names in the array. Sort it to get it in a predictable order. Attach the string back.

 $(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 seems strange that you will have a browser that supports jQuery but does not support CSS styles for multiple class names. You understand that you have to supply completely different stylesheets that work with concatenated names, right? And, if you can change the style sheets, this makes me wonder why you cannot change the HTML.

Working implementation: http://jsfiddle.net/jfriend00/uPET7/

+2
source

It seems crazy to accomplish this,

Scroll each item with more than 1 class. Sort the classes (no matter how consistent they are), then combine them together to create a new class. Keep a list of all the new css classes and check for duplicates.

To get all styles from an element, see here .

0
source

All Articles