2012-04-25 16 views
12

Se ho uno stile come questo -Controllare se la proprietà CSS ha attributo importante applicato

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

posso interrogare il valore top con jQuery come questo -

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

che restituirà il valore 10px. È possibile utilizzare jQuery o JavaScript per verificare se alla proprietà top è stato applicato l'attributo !important?

+0

come questo: div.style() getPropertyPriority ('top').? Potresti essere interessato a: http://www.quirksmode.org/dom/tests/cssMisc.html. Non una soluzione jQuery però. –

risposta

8

Prima di tutto, una tale soluzione non sembra esistere in jQuery.

Molte soluzioni javascript disponibili offerte, utilizzare la funzione getPropertyPriority(). Innanzitutto, questa funzione non è supportata da IE6-IE8 (vedere here e here). In secondo luogo, questa funzione non funziona direttamente sugli elementi se il loro stile non è dichiarato in linea. Quindi, saremmo in grado di ottenere l'importante proprietà nel seguente caso:

<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> 

Tuttavia se potessimo dichiarare lo stile di #testdiv in un foglio di stile CSS, otterremo una stringa vuota. Anche l'interfaccia CSSStyleDeclaration non è disponibile in IE6-8. Ovviamente questo è abbastanza inutile in questo modo. Abbiamo bisogno di un approccio diverso.

Ho inserito questo approccio in JSFiddle. Possiamo leggere la proprietà! Important direttamente dai fogli di stile css, che sono contenuti nell'array document.styleSheets[]. (Opera 8 e seguenti non supportano questo array). A Quirksmode è possibile visualizzare i metodi con cui i metodi sono supportati per accedere ai fogli di stile. Sulla base di queste informazioni siamo in grado di effettuare le seguenti operazioni:

  • Per IE6-8, usiamo il styleSheets[].imports per accedere ai fogli di stile importati (e continuare a fare questo in modo ricorsivo finché non troviamo più alcuna dichiarazione di importazione) e poi in fondo styleSheets[].rules per ogni foglio di stile aggiungi le regole CSS ad un array.
  • Per altri browser, utilizziamo styleSheets[].cssRules per accedere sia alle regole importate che a quelle css. Rileviamo le regole di importazione controllando se implementa l'interfaccia CSSImportRule e le utilizza per accedere in modo ricorsivo alle regole css nei fogli di stile importati.

In entrambi i casi, aggiungeremo le regole css a un array solo se le regole corrispondono a HTMLElement (nel tuo caso #testdiv). Ciò si traduce in una serie di regole css che corrispondono a un HTMLElement. Questo è fondamentalmente ciò che fa la funzione getMatchedCSSRules() nei browser Webkit. Tuttavia, lo scriviamo noi stessi qui.

Sulla base di queste informazioni scriviamo la nostra funzione hasImportant(htmlNode, property), dove htmlNode è un HTMLElement (il tuo testdiv) e la proprietà css ('top' nel tuo caso). Per prima cosa, controlliamo se lo stile in linea della proprietà superiore ha un attributo importante. Questo ci risparmia guardando attraverso i fogli di stile se contiene questo attributo.

Scriviamo una nuova funzione isImportant(node, property) che utilizza la nostra buona vecchia funzione node.style.getPropertyPriority(property). Tuttavia, come accennato in precedenza in questa risposta: questa funzione non è supportata in IE6-IE8. Possiamo scrivere la funzione da soli: in IE la proprietà node.style.cssText contiene il testo del blocco di dichiarazione. Cerchiamo la proprietà ('top') in questo blocco di testo e controlliamo se il suo valore contiene '! Important'. Possiamo riutilizzare questa funzione su ogni regola css ottenuta utilizzando la funzione getMatchedCSSRules, eseguendo il ciclo di tutte le regole css che corrispondono a htmlNode e chiamando la funzione isImportant.

Tutto ciò è riportato nel codice sottostante. Questo è l'approccio di base e, probabilmente, dovrebbe essere messo a punto ulteriormente:

  • po 'di codice potrebbe essere sostituito con jQuery
  • po' di codice potrebbe essere semplificata
  • regole css che implementano l'interfaccia CSSMediaRule e other interfaces potrebbero causare alcuni problemi per questo codice e un controllo di errore dovrebbe essere eseguita
  • potrebbe esserci un approccio più semplice, ma non sono a conoscenza di nessun altro metodo per ottenere questo browser cross funzionante.

    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

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

C'è una funzione lì che è possibile aggiungere a jQuery. Poi lo si utilizza in questo modo:

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

+1

Questo non funziona per me, vedi - http://jsfiddle.net/74MCx/. La funzione funziona se imposto il valore CSS tramite il metodo set della funzione, ma non funzionerà con gli stili dichiarati in CSS (viene restituita una stringa vuota). – ipr101

+0

Come @dennisg dice: apparentemente funziona solo per gli stili impostati in linea sull'elemento :((ad esempio

Hello
) – Tobbe

Problemi correlati