2012-04-25 32 views
12

Nếu tôi có một phong cách như thế này -tra nếu tài sản css có thuộc tính quan trọng áp dụng

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

Tôi có thể truy vấn giá trị top với jQuery như thế này -

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

mà sẽ trả về giá trị 10px. Có thể sử dụng jQuery hoặc JavaScript để kiểm tra xem thuộc tính top có thuộc tính !important được áp dụng cho nó hay không?

+0

như thế này: div.style() getPropertyPriority ('top').? Bạn có thể quan tâm: http://www.quirksmode.org/dom/tests/cssMisc.html. Không phải là một giải pháp jQuery mặc dù. –

Trả lời

8

Trước hết, một giải pháp như vậy dường như không tồn tại trong jQuery.

Nhiều giải pháp javascript có sẵn được cung cấp, sử dụng chức năng getPropertyPriority(). Đầu tiên, chức năng này không được hỗ trợ bởi IE6-IE8 (xem herehere). Thứ hai, hàm này không trực tiếp hoạt động trên các phần tử nếu kiểu của chúng không được khai báo nội tuyến. Vì vậy, chúng tôi sẽ có thể để có được những tính chất quan trọng trong trường hợp sau đây:

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

Tuy nhiên nếu chúng ta có thể tuyên bố phong cách của #testdiv trong một stylesheet css, chúng tôi sẽ nhận được một chuỗi rỗng. Giao diện CSSStyleDeclaration không khả dụng trong IE6-8. Ofcourse này là khá vô dụng theo cách này. Chúng ta cần một cách tiếp cận khác.

Tôi đã đặt phương pháp này vào một số JSFiddle. Chúng ta có thể đọc thuộc tính quan trọng trực tiếp từ các bảng định kiểu CSS, được chứa trong mảng document.styleSheets[]. (Opera 8 trở xuống không hỗ trợ mảng này). Tại Quirksmode bạn có thể xem các phương pháp mà các phương pháp được hỗ trợ để truy cập bảng định kiểu. Dựa trên thông tin này, chúng ta có thể làm như sau:

  • Đối IE6-8, chúng tôi sử dụng styleSheets[].imports để truy cập stylesheets nhập khẩu (và tiếp tục làm này một cách đệ quy cho đến khi chúng tôi không tìm thấy bất kỳ báo cáo nhập khẩu nữa) và sau đó styleSheets[].rules cơ bản cho mỗi biểu định kiểu thêm các quy tắc css vào một mảng.
  • Đối với các trình duyệt khác, chúng tôi sử dụng styleSheets[].cssRules để truy cập cả quy tắc nhập và css. Chúng tôi phát hiện các quy tắc nhập bằng cách kiểm tra xem nó có triển khai giao diện CSSImportRule hay không và sử dụng các quy tắc này để truy cập các quy tắc css trong bảng định kiểu được nhập đệ quy.

Trong cả hai trường hợp, chúng tôi chỉ thêm quy tắc css vào mảng nếu quy tắc khớp với HTMLElement (trong trường hợp của bạn là #testdiv). Điều này dẫn đến một loạt các quy tắc css được so khớp với HTMLElement. Về cơ bản, đây là chức năng của getMatchedCSSRules() trong trình duyệt webkit. Tuy nhiên, chúng tôi tự viết nó ở đây.

Dựa trên thông tin này, chúng tôi viết hàm hasImportant(htmlNode, property), trong đó htmlNode là HTMLElement (testdiv) và thuộc tính css ('top' trong trường hợp của bạn). Trước tiên, chúng tôi kiểm tra xem kiểu nội tuyến của thuộc tính trên cùng có thuộc tính quan trọng hay không. Điều này giúp chúng ta tìm kiếm thông qua các bảng định kiểu nếu nó chứa thuộc tính này.

Chúng tôi viết chức năng mới isImportant(node, property) sử dụng chức năng cũ tốt của chúng tôi node.style.getPropertyPriority(property). Tuy nhiên, như tôi đã đề cập trước đó trong câu trả lời này: chức năng này không được hỗ trợ trong IE6-IE8. Chúng ta có thể tự viết hàm: trong IE, thuộc tính node.style.cssText chứa văn bản khối khai báo. Chúng tôi tìm kiếm thuộc tính ('top') trong khối văn bản này và kiểm tra xem giá trị của nó có chứa '! Important' hay không. Chúng ta có thể tái sử dụng chức năng này trên mọi quy tắc css thu được bằng cách sử dụng hàm getMatchedCSSRules, bằng cách lặp qua tất cả các quy tắc css khớp với htmlNode và gọi hàm isImportant.

Tất cả những điều trên có thể được tìm thấy trong mã bên dưới. Đây là phương pháp cơ bản và có lẽ nên được tinh chỉnh hơn nữa:

  • một số mã có thể được thay thế bằng jQuery
  • một số mã có thể được đơn giản hóa
  • quy tắc css thực hiện giao diện CSSMediaRule và other interfaces có thể gây ra một số vấn đề đối với mã này và kiểm tra lỗi phải được thực hiện
  • có thể có cách tiếp cận đơn giản hơn, nhưng tôi không biết bất kỳ phương pháp nào khác để có trình duyệt chéo hoạt động này.

    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

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

Có một chức năng đó mà bạn có thể thêm vào jQuery. Sau đó, bạn sử dụng nó như thế này:

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

+1

Điều này không hiệu quả đối với tôi, xem - http://jsfiddle.net/74MCx/. Hàm này hoạt động nếu tôi đặt giá trị CSS thông qua phương thức set của hàm nhưng sẽ không hoạt động với các kiểu được khai báo trong CSS (một chuỗi trống được trả về). – ipr101

+0

Giống như @dennisg cho biết: nó dường như chỉ hoạt động cho các kiểu đặt nội tuyến trên phần tử: (ví dụ:

Hello
) – Tobbe

Các vấn đề liên quan