2012-04-25 9 views
12

Si tengo un estilo como este -Comprobar si la propiedad CSS tiene atributo importante aplicada

​div#testdiv {position:absolute;top:10px !important;}​ 

puedo consultar el valor top con jQuery como esto -

$("#testdiv").css("top"); 

que devolverá el valor 10px. ¿Es posible usar jQuery o JavaScript para verificar si se le ha aplicado el atributo !important a la propiedad top?

+0

así: div.style() getPropertyPriority ('superior').? Usted puede estar interesado en: http://www.quirksmode.org/dom/tests/cssMisc.html. No es una solución jQuery sin embargo. –

Respuesta

8

En primer lugar, no parece existir en jQuery tal solución.

Muchas de las soluciones de javascript disponibles, utilizan la función getPropertyPriority(). En primer lugar, IE6-IE8 no es compatible con esta función (ver here y here). En segundo lugar, esta función no funciona directamente en los elementos si su estilo no está declarado en línea. Por lo tanto, sería capaz de obtener la propiedad importante en el caso siguiente:

<div id="testdiv" style="top : 10px !important;">Some div</div> 
<script type="text/javascript"> 
// should show 'important' in the console. 
console.log(document.getElementById("testdiv").style.getPropertyPriority('top')); 
</script> 

Sin embargo, si pudiéramos declarar el estilo de #testdiv en una hoja de estilo CSS, obtendremos una cadena vacía. Además, la interfaz CSSStyleDeclaration no está disponible en IE6-8. Por supuesto, esto es bastante inútil de esta manera. Necesitamos un enfoque diferente.

He puesto este enfoque en un JSFiddle. Podemos leer la propiedad! Important directamente de las hojas de estilo css, que están contenidas en la matriz document.styleSheets[]. (Opera 8 y abajo no son compatibles con este conjunto). En Quirksmode puede ver los métodos que son compatibles con los métodos para acceder a las hojas de estilo. Sobre la base de esta información podemos hacer lo siguiente:

  • Para IE6-8, utilizamos el styleSheets[].imports acceder a las hojas de estilo importadas (y seguir haciendo esto de forma recursiva hasta que no encontramos ninguna declaración de importación más) y luego básicamente styleSheets[].rules para cada hoja de estilo, agregue las reglas css a una matriz.
  • Para otros navegadores, usamos styleSheets[].cssRules para acceder a las reglas importadas y css. Detectamos las reglas de importación comprobando si implementa la interfaz CSSImportRule y las usamos para acceder recursivamente a las reglas css en las hojas de estilo importadas.

En ambos casos agregamos las reglas css a una matriz solo si las reglas coinciden con el HTMLElement (en su caso #testdiv). Esto da como resultado una matriz de reglas css que coinciden con un HTMLElement. Esto es básicamente lo que hace la función getMatchedCSSRules() en los navegadores webkit. Sin embargo, lo escribimos nosotros aquí.

Basado en esta información, escribimos nuestra función hasImportant(htmlNode, property), donde htmlNode es un HTMLElement (su testdiv) y posee la propiedad css ('top' en su caso). Primero, verificamos si el estilo en línea de la propiedad superior tiene un atributo importante. Esto nos ahorra mirar a través de las hojas de estilo si contiene este atributo.

Escribimos una nueva función isImportant(node, property) que utiliza nuestra buena función anterior node.style.getPropertyPriority(property). Sin embargo, como mencioné anteriormente en esta respuesta: esta función no es compatible con IE6-IE8. Podemos escribir la función nosotros mismos: en IE, la propiedad node.style.cssText contiene el texto del bloque de declaración. Buscamos la propiedad ('top') en este bloque de texto y verificamos si su valor contiene '! Important'. Podemos reutilizar esta función en cada regla css obtenida usando la función getMatchedCSSRules, al recorrer todas las reglas css que coinciden con el htmlNode y llamar a la función isImportant.

Todo lo anterior se puede encontrar en el código siguiente. Este es el enfoque básico y probablemente debería estar bien afinado aún más:

  • algo de código podría ser reemplazado con jQuery
  • algo de código podría ser simplificado
  • reglas CSS que implementan la interfaz CSSMediaRule y other interfaces podrían causar algunos problemas para este código y se debe realizar una verificación de errores
  • podría haber un enfoque más simple, pero no conozco ningún otro método para obtener este navegador cruzado.

    var debug = true; 
    
    /** 
    * Get the css rules of a stylesheet which apply to the htmlNode. Meaning its class 
    * its id and its tag. 
    * @param CSSStyleSheet styleSheet 
    * @param HTMLElement htmlNode 
    */ 
    function getCssRules(styleSheet, htmlNode) { 
        if (!styleSheet) 
         return null; 
    
        var cssRules = new Array(); 
        if (styleSheet.cssRules) { 
         var currentCssRules = styleSheet.cssRules; 
         // Import statement are always at the top of the css file. 
         for (var i = 0; i < currentCssRules.length; i++) { 
          // cssRules all contains the import statements. 
          // check if the rule is an import rule. 
          if (isImportRule(currentCssRules[i])) { 
           // import the rules from the imported css file. 
           var importCssRules = getCssRules(currentCssRules[i].styleSheet, htmlNode); 
           if (importCssRules != null) { 
            // Add the rules from the import css file to the list of css rules. 
            cssRules = addToArray(cssRules, importCssRules, htmlNode); 
           } 
           // Remove the import css rule from the css rules. 
           styleSheet.deleteRule(i); 
          } 
          else { 
           // We found a rule that is not an CSSImportRule 
           break; 
          } 
         } 
         // After adding the import rules (lower priority than those in the current stylesheet), 
         // add the rules in the current stylesheet. 
         cssRules = addToArray(cssRules, currentCssRules, htmlNode); 
        } 
        else if (styleSheet.rules) { 
         // IE6-8 
         // rules do not contain the import statements. 
         var currentCssRules = styleSheet.rules; 
    
         // Handle the imports in a styleSheet file. 
         if (styleSheet.imports) { 
          // IE6-8 use a seperate array which contains the imported css files. 
          var imports = styleSheet.imports; 
          for (var i = 0; i < imports.length; i++) { 
           var importCssRules = getCssRules(imports[i], htmlNode); 
           if (importCssRules != null) { 
            // Add the rules from the import css file to the list of css rules. 
            cssRules = addToArray(cssRules, importCssRules, htmlNode); 
           } 
          } 
         } 
         // After adding the import rules (lower priority than those in the current stylesheet), 
         // add the rules in the current stylesheet. 
         cssRules = addToArray(cssRules, currentCssRules, htmlNode); 
        } 
    
        return cssRules; 
    } 
    
    /** 
    * Since a list of rules is returned, we cannot use concat. 
    * Just use old good push.... 
    * @param CSSRuleList cssRules 
    * @param CSSRuleList cssRules 
    * @param HTMLElement htmlNode 
    */ 
    function addToArray(cssRules, newRules, htmlNode) { 
        for (var i = 0; i < newRules.length; i++) { 
         if (htmlNode != undefined && htmlNode != null && isMatchCssRule(htmlNode, newRules[i])) 
          cssRules.push(newRules[i]); 
        } 
        return cssRules; 
    } 
    
    /** 
    * Matches a htmlNode to a cssRule. If it matches, return true. 
    * @param HTMLElement htmlNode 
    * @param CSSRule cssRule 
    */ 
    function isMatchCssRule(htmlNode, cssRule) { 
        // Simply use jQuery here to see if there cssRule matches the htmlNode... 
        return $(htmlNode).is(cssRule.selectorText); 
    } 
    
    /** 
    * Verifies if the cssRule implements the interface of type CSSImportRule. 
    * @param CSSRule cssRule 
    */ 
    function isImportRule(cssRule) { 
        return cssRule.constructor.toString().search("CSSImportRule") != -1; 
    } 
    
    /** 
    * Webkit browsers contain this function, but other browsers do not (yet). 
    * Implement it ourselves... 
    * 
    * Finds all matching CSS rules for the htmlNode. 
    * @param HTMLElement htmlNode 
    */ 
    function getMatchedCSSRules(htmlNode) { 
        var cssRules = new Array(); 
    
        // Opera 8- don't support styleSheets[] array. 
        if (!document.styleSheets) 
         return null; 
    
        // Loop through the stylesheets in the html document. 
        for (var i = 0; i < document.styleSheets.length; i++) { 
         var currentCssRules = getCssRules(document.styleSheets[i], htmlNode) 
         if (currentCssRules != null) 
          cssRules.push.apply(cssRules, currentCssRules); 
        } 
    
        return cssRules; 
    } 
    
    /** 
    * Checks if the CSSStyleRule has the property with 'important' attribute. 
    * @param CSSStyleRule node 
    * @param String property 
    */ 
    function isImportant(node, property) { 
        if (node.style.getPropertyPriority && node.style.getPropertyPriority(property) == 'important') 
         return true; 
        else if (node.style.cssText && getPropertyPriority(node.style.cssText, property) == 'important') { 
         // IE6-8 
         // IE thinks that cssText is part of rule.style 
         return true; 
        } 
    } 
    
    /** 
    * getPropertyPriority function for IE6-8 
    * @param String cssText 
    * @param String property 
    */ 
    function getPropertyPriority(cssText, property) { 
        var props = cssText.split(";"); 
        for (var i = 0; i < props.length; i++) { 
         if (props[i].toLowerCase().indexOf(property.toLowerCase()) != -1) { 
          // Found the correct property 
          if (props[i].toLowerCase().indexOf("!important") != -1 || props[i].toLowerCase().indexOf("! important") != -1) { 
           // IE automaticaly adds a space between ! and important... 
           return 'important'; // We found the important property for the property, return 'important'. 
          } 
         } 
        } 
        return ''; // We did not found the css property with important attribute. 
    } 
    
    /** 
    * Outputs a debug message if debugging is enabled. 
    * @param String msg 
    */ 
    function debugMsg(msg) { 
        if (debug) { 
         // For debugging purposes. 
         if (window.console) 
          console.log(msg); 
         else 
          alert(msg); 
        } 
    } 
    
    /** 
    * The main functionality required, to check whether a certain property of 
    * some html element has the important attribute. 
    * 
    * @param HTMLElement htmlNode 
    * @param String property 
    */ 
    function hasImportant(htmlNode, property) { 
    
        // First check inline style for important. 
        if (isImportant(htmlNode, property)) { 
         // For debugging purposes. 
         debugMsg("Inline contains important!"); 
         return true; 
        } 
    
        var rules = getMatchedCSSRules(htmlNode); 
    
        if (rules == null) { 
         debugMsg("This browser does not support styleSheets..."); 
         return false; 
        } 
    
        /** 
        * Iterate through the rules backwards, since rules are 
        * ordered by priority where the highest priority is last. 
        */ 
        for (var i = rules.length; i-- > 0;) { 
         var rule = rules[i]; 
    
         if (isImportant(rule, property)) { 
          // For debugging purposes. 
          debugMsg("Css contains important!"); 
          return true; 
         } 
    
        } 
        return false; 
    } 
    
    $(document).ready(function() { 
        hasImportant($('#testdiv')[0], 'top'); 
    }); 
    
+0

nice @dennisg +1 –

6

Ver How to apply !important using .css()?

Hay una función que no se puede añadir a jQuery. A continuación, se utiliza de esta manera:

console.log($('#testdiv').style().getPropertyPriority('top'));

+1

Esto no me funciona, ver - http://jsfiddle.net/74MCx/. La función funciona si configuro el valor de CSS mediante el método de configuración de la función, pero no funcionaré con los estilos que se declaran en CSS (se devuelve una cadena en blanco). – ipr101

+0

Me gusta @dennisg dice: aparentemente solo funciona para los estilos establecidos en línea en el elemento :((es decir,

Hello
) – Tobbe

Cuestiones relacionadas