【问题标题】:Check if css property has !important attribute applied检查 css 属性是否应用了 !important 属性
【发布时间】:2012-05-06 01:07:56
【问题描述】:

如果我有这样的风格-

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

我可以像这样使用 jQuery 查询 top 值 -

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

这将返回值10px。是否可以使用 jQuery 或 JavaScript 来检查 top 属性是否应用了 !important 属性?

【问题讨论】:

标签: javascript jquery


【解决方案1】:

您可以尝试直接从 css 样式表中读取它。

看看这个问题的第二个答案: get CSS rule's percentage value in jQuery

【讨论】:

    【解决方案2】:

    How to apply !important using .css()?

    那里有一个可以添加到 jQuery 的函数。然后你像这样使用它:

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

    【讨论】:

    • 这对我不起作用,请参阅 - jsfiddle.net/74MCx。如果我通过函数的 set 方法设置 CSS 值,则该函数有效,但不适用于在 CSS 中声明的样式(返回空白字符串)。
    • 就像@dennisg 说的:它显然只适用于在元素上设置的内联样式:((即
      Hello
      )
    【解决方案3】:

    首先,jQuery中似乎不存在这样的解决方案。

    提供了许多可用的 javascript 解决方案,请使用函数 getPropertyPriority()。首先,IE6-IE8 不支持此功能(请参阅herehere)。其次,如果元素的样式未声明为 inline,则此函数不会直接作用于元素。因此,我们将能够在以下情况下获得重要的属性:

    <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 访问导入的样式表(并继续递归执行此操作,直到我们不再找到任何导入语句)然后 styleSheets[].rules 基本上为每个样式表添加 css 规则到数组。
    • 对于其他浏览器,我们使用styleSheets[].cssRules 来访问导入的规则和css 规则。我们通过检查它是否实现 CSSImportRule 接口来检测导入规则,并使用它们递归地访问导入样式表中的 css 规则。

    在这两种情况下,只有当规则与 HTMLElement 匹配时(在您的情况下为 #testdiv),我们才会将 css 规则添加到数组中。这会产生一组与 HTMLElement 匹配的 css 规则。这基本上就是 webkit 浏览器中的 getMatchedCSSRules() 函数所做的。但是,我们自己在这里写。

    基于这些信息,我们编写了 hasImportant(htmlNode, property) 函数,其中 htmlNode 是一个 HTMLElement(您的 testdiv),并为 css 属性(在您的情况下为“top”)设置属性。首先,我们检查 top 属性的内联样式是否有一个重要的属性。如果样式表确实包含此属性,这可以节省我们查看样式表的时间。

    我们编写了一个新函数isImportant(node, property),它使用了我们良好的旧函数node.style.getPropertyPriority(property)。但是,就像我之前在此答案中提到的那样:IE6-IE8 不支持此功能。我们可以自己编写函数:在 IE 中属性node.style.cssText 包含声明块文本。我们在此文本块中搜索属性 ('top') 并检查其值是否包含 '!important'。我们可以在使用getMatchedCSSRules函数获得的每条css规则上重用这个函数,方法是遍历所有与htmlNode匹配的css规则并调用isImportant函数。

    以上所有内容都可以在下面的代码中找到。这是基本方法,可能应该进一步微调:

    • 某些代码可能会被 jQuery 替换
    • 某些代码可能会被简化
    • 实现 CSSMediaRule 接口和 other interfaces 的 css 规则可能会导致此代码出现一些问题,应执行错误检查
    • 可能有更简单的方法,但我不知道有任何其他方法可以让这个跨浏览器工作。

      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');
      });
      

    【讨论】:

      猜你喜欢
      • 2020-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-11
      • 2011-08-22
      • 2013-01-31
      • 2015-09-26
      相关资源
      最近更新 更多