Ответ 1
Прежде всего, такое решение, похоже, не существует в jQuery.
Доступно множество доступных javascript-решений, используйте функцию getPropertyPriority()
. Во-первых, эта функция не поддерживается IE6-IE8 (см. здесь и здесь). Во-вторых, эта функция не работает непосредственно над элементами, если их стиль не объявлен встроенным. Таким образом, мы могли бы получить важное свойство в следующем случае:
<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>
Однако, если мы можем объявить стиль #testdiv
в таблице стилей css, мы получим пустую строку. Кроме того, интерфейс CSSStyleDeclaration
недоступен в IE6-8. Конечно, это бесполезно. Нам нужен другой подход.
Я применил этот подход в JSFiddle. Мы можем прочитать важное свойство непосредственно из таблиц стилей css, которые содержатся в массиве document.styleSheets[]
. (Opera 8 и ниже не поддерживают этот массив). В Quirksmode вы можете увидеть методы, поддерживаемые для доступа к таблицам стилей. На основании этой информации мы можем сделать следующее:
- Для IE6-8 мы используем
styleSheets[].imports
для доступа к импортированным таблицам стилей (и продолжаем делать это рекурсивно, пока мы больше не найдем никаких операторов импорта), а затемstyleSheets[].rules
в основном для каждой таблицы стилей добавьте правила css в массив. - Для других браузеров мы используем
styleSheets[].cssRules
для доступа как к импортированным, так и к CSS-правилам. Мы определяем правила импорта, проверяя, реализует ли он интерфейс CSSImportRule и используют их для рекурсивного доступа к правилам CSS в импортированных таблицах стилей.
В обоих случаях мы добавляем правила css в массив только в том случае, если правила соответствуют элементу HTMLElement (в вашем случае #testdiv
). Это приводит к массиву правил CSS, которые соответствуют HTMLElement. Это в основном то, что делает функция getMatchedCSSRules()
в браузерах webkit. Однако мы пишем его здесь.
На основе этой информации мы пишем нашу функцию hasImportant(htmlNode, property)
, где htmlNode - это HTMLElement (ваш testdiv) и свойство css ( "верхний" в вашем случае). Во-первых, мы проверяем, имеет ли встроенный стиль верхнего свойства важный атрибут. Это экономит нас, просматривая таблицы стилей, если он содержит этот атрибут.
Напишем новую функцию isImportant(node, property)
, которая использует нашу добрую старую функцию node.style.getPropertyPriority(property)
. Однако, как я уже упоминал ранее в этом ответе: эта функция не поддерживается в IE6-IE8. Мы можем сами написать эту функцию: в IE свойство node.style.cssText
содержит текст блока объявления. Мы ищем свойство ('top') в этом блоке текста и проверяем, содержит ли его значение '! Important'. Мы можем повторно использовать эту функцию для каждого правила css, полученного с помощью функции getMatchedCSSRules
, путем прокрутки всех правил css, которые соответствуют htmlNode и вызова функции isImportant.
Все вышеперечисленное можно найти в коде ниже. Это базовый подход и, вероятно, должен быть дополнительно отрегулирован:
- некоторый код может быть заменен на jQuery
- некоторый код может быть упрощен
- css правила, реализующие интерфейс CSSMediaRule, и другие интерфейсы могут вызвать некоторые проблемы для этого кода и выполнить проверку ошибок
-
может быть более простой подход, но я не знаю другого способа получить этот рабочий кросс-браузер.
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'); });