2012-04-25 133 views
12

如果我有這樣的風格 -檢查CSS屬性具有重要的屬性應用於

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

我可以用jQuery查詢top值這樣的 -

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

這將返回值10px。是否有可能使用jQuery或JavaScript來檢查top屬性是否已應用!important屬性?

+0

這樣的:div.style()getPropertyPriority( '頂')?您可能感興趣:http://www.quirksmode.org/dom/tests/cssMisc.html。不過,不是jQuery解決方案。 – 2012-04-25 11:05:56

回答

8

首先,這樣的解決方案似乎並沒有在jQuery的存在。

提供了許多可用的javascript解決方案,使用函數getPropertyPriority()。首先,IE6-IE8不支持此功能(請參閱herehere)。其次,如果它們的樣式未聲明,則此功能不直接適用於元素內聯。因此,我們將能夠獲得重要的特性在下面的情況:

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

但是,如果我們能在CSS樣式表聲明的#testdiv的作風,我們將得到一個空字符串。在IE6-8中,CSSStyleDeclaration接口也不可用。當然,這種方式很沒用。我們需要一種不同的方法。

我已將這種方法放入JSFiddle。我們可以直接從數組document.styleSheets[]中包含的css樣式表中讀取!important屬性。 (Opera 8及以下版本不支持這個陣列)。在Quirksmode你可以看到支持訪問樣式表的方法。基於這些信息,我們可以做到以下幾點:

  • 對於IE6-8,我們使用styleSheets[].imports訪問導入的樣式表(並保持遞歸這樣做,直到我們沒有找到任何import語句了),然後styleSheets[].rules基本上爲每個樣式表添加css規則到一個數組。
  • 對於其他瀏覽器,我們使用styleSheets[].cssRules來訪問導入規則和css規則。我們通過檢查它是否實現了接口並使用它們來遞歸訪問導入的樣式表中的css規則來檢測導入規則。

在這兩種情況下,只要規則匹配HTMLElement(在您的案例#testdiv),我們就會將css規則添加到數組中。這會產生一個與HTMLElement匹配的css規則數組。這基本上是webkit瀏覽器中getMatchedCSSRules()函數的作用。但是,我們自己在這裏寫。

根據這些信息,我們編寫我們的hasImportant(htmlNode, property)函數,其中htmlNode是一個HTMLElement(你的testdiv)並且屬性是css屬性(在你的案例中是'top')。首先,我們檢查頂層屬性的內聯樣式是否具有重要屬性。這節省了我們查看樣式表,如果它包含此屬性的話。

我們寫了一個新功能isImportant(node, property)它使用我們的老功能node.style.getPropertyPriority(property)。但是,就像我在前面提到的那樣:IE6-IE8不支持該功能。我們可以自己編寫函數:在IE中,屬性node.style.cssText包含聲明塊文本。我們在這個文本塊中搜索屬性('top')並檢查它的值是否包含'!important'。我們可以在使用getMatchedCSSRules函數獲得的每個css規則中循環使用此函數,方法是循環所有與htmlNode匹配的css規則並調用isImportant函數。

以上所有都可以在下面的代碼中找到。這是基本的做法,而且也應該進一步微調:

  • 一些代碼可能使用jQuery來代替
  • 一些代碼可能會被簡化,實現CSSMediaRule接口和
  • CSS規則other interfaces可能會引起一些問題對於此代碼和應執行錯誤檢查
  • 可能有更簡單的方法,但我不知道有任何其他方法來獲得此工作的跨瀏覽器。

    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

很好@dennisg +1 – 2012-04-26 04:42:57

6

How to apply !important using .css()?

有一個功能那裏,你可以添加到jQuery的。然後你使用這樣的:

所有的

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

+1

這不適用於我,請參閱 - http://jsfiddle.net/74MCx/。如果我通過函數的set方法設置CSS值,但不能用CSS中聲明的樣式(返回一個空字符串),該函數將起作用。 – ipr101 2012-04-25 12:21:48

+0

像@dennisg說的那樣:它顯然只適用於元素內嵌的樣式:((即

Hello
) – Tobbe 2012-04-27 07:44:53