Skip to content

Instantly share code, notes, and snippets.

@elsewhat
Created June 19, 2015 07:54
Show Gist options
  • Save elsewhat/93902704f0366258f30f to your computer and use it in GitHub Desktop.
Save elsewhat/93902704f0366258f30f to your computer and use it in GitHub Desktop.

Revisions

  1. elsewhat created this gist Jun 19, 2015.
    118 changes: 118 additions & 0 deletions getAllCSSClassDefinitionsForSubtree
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,118 @@

    //Get all styles where the provided class is involved
    //Input parameters should be css selector such as .myClass or #m
    //returned as an array of tuples {selectorText:"", styleDefinition:""}
    function getStyleWithCSSSelector(cssSelector) {
    var styleSheets = window.document.styleSheets;
    var styleSheetsLength = styleSheets.length;
    var arStylesWithCSSSelector = [];

    //in order to not find class which has the current name as prefix
    var arValidCharsAfterCssSelector = [" ", ".", ",", "#",">","+",":","["];

    //loop through all the stylessheets in the bor
    for(var i = 0; i < styleSheetsLength; i++){
    var classes = styleSheets[i].rules || styleSheets[i].cssRules;
    var classesLength = classes.length;
    for (var x = 0; x < classesLength; x++) {
    //check for any reference to the class in the selector string
    if(typeof classes[x].selectorText != "undefined"){
    var matchClass = false;

    if(classes[x].selectorText === cssSelector){//exact match
    matchClass=true;
    }else {//check for it as part of the selector string
    //TODO: Optimize with regexp
    for (var j=0;j<arValidCharsAfterCssSelector.length; j++){
    var cssSelectorWithNextChar = cssSelector+ arValidCharsAfterCssSelector[j];

    if(classes[x].selectorText.indexOf(cssSelectorWithNextChar)!=-1){
    matchClass=true;
    //break out of for-loop
    break;
    }
    }
    }

    if(matchClass === true){
    //console.log("Found "+ cssSelectorWithNextChar + " in css class definition " + classes[x].selectorText);
    var styleDefinition;
    if(classes[x].cssText){
    styleDefinition = classes[x].cssText;
    } else {
    styleDefinition = classes[x].style.cssText;
    }
    if(styleDefinition.indexOf(classes[x].selectorText) == -1){
    styleDefinition = classes[x].selectorText + "{" + styleDefinition + "}";
    }
    arStylesWithCSSSelector.push({"selectorText":classes[x].selectorText, "styleDefinition":styleDefinition});
    }
    }
    }
    }
    if(arStylesWithCSSSelector.length==0) {
    return null;
    }else {
    return arStylesWithCSSSelector;
    }
    }


    function getAllCSSClassDefinitionsForSubtree(selectorOfRootElement){
    //stack in which elements are pushed and poped from
    var arStackElements = [];
    //dictionary for checking already added css class definitions
    var existingClassDefinitions = {}

    //use jquery for selecting root element
    var rootElement = $(selectorOfRootElement)[0];
    //string with the complete CSS output
    var cssString = "";

    console.log("Fetching all classes used in sub tree of " +selectorOfRootElement);
    arStackElements.push(rootElement);
    var currentElement;

    while(currentElement = arStackElements.pop()){
    currentElement = $(currentElement);
    console.log("Processing element " + currentElement.attr("id"));

    //Look at class attribute of element
    var classesString = currentElement.attr("class");
    if(typeof classesString != 'undefined'){
    var arClasses = classesString.split(" ");

    //for each class in the current element
    for(var i=0; i< arClasses.length; i++){

    //fetch the CSS Styles for a single class. Need to append the . char to indicate its a class
    var arStylesWithCSSSelector = getStyleWithCSSSelector("."+arClasses[i]);
    console.log("Processing class "+ arClasses[i]);

    if(arStylesWithCSSSelector != null){
    //console.log("Found "+ arStylesWithCSSSelector.length + " CSS style definitions for class " +arClasses[i]);
    //append all found styles to the cssString
    for(var j=0; j< arStylesWithCSSSelector.length; j++){
    var tupleStyleWithCSSSelector = arStylesWithCSSSelector[j];

    //check if it has already been added
    if(typeof existingClassDefinitions[tupleStyleWithCSSSelector.selectorText] === "undefined"){
    //console.log("Adding " + tupleStyleWithCSSSelector.styleDefinition);
    cssString+= tupleStyleWithCSSSelector.styleDefinition;
    existingClassDefinitions[tupleStyleWithCSSSelector.selectorText] = true;
    }else {
    //console.log("Already added " + tupleStyleWithCSSSelector.styleDefinition);
    }
    }
    }
    }
    }
    //push all child elments to stack
    if(currentElement.children().length>0){
    arStackElements= arStackElements.concat(currentElement.children().toArray());
    }
    }

    console.log("Found " + Object.keys(existingClassDefinitions).length + " CSS class definitions");
    return cssString;
    }