Можете ли вы определить, когда для стиля dom node установлено значение "авто"?
В примере CSS:
.thing { height: auto }
и HTML:
<div class="thing">The quick brown fox jumps over a lazy dog.</div>
Можно ли определить, что высота .thing установлена на 'auto'?
Следующие методы возвращают значения:
jQuery('.thing').height() // n
jQuery('.thing').css('height') // 'npx'
getComputedStyle(node).height // 'npx'
Есть ли какой-нибудь метод, который скажет мне, что браузер вычисляет эти значения из "auto"?
Ответы
Ответ 1
Да, есть способ, но это не смешно. Что вам нужно сделать:
- Прокрутите все
styletags
и связанные таблицы стилей.
-
Затем получите selectorText
для всех cssRules
во всех тегах стиля
styletag.sheet.cssRules.selectorText
или для IE < 9
styletag.styleSheet.cssRules.selectorText
-
Получите все ваши элементы parent id
, class
и tagName
, чтобы узнать, какие возможные пути для получения тега для атрибута.
- Найдите все возможные комбинации, которые указывают на ваш элемент в вашем
список
cssRules
- проверьте те
cssRules
на cssRules.style.width
, если он авто.
или сделать это обратным образом и найти все cssRules
с style.width == 'auto';
в любом случае, его не легко получить без большого количества кода
Ответ 2
jQuery('.thing').each(function (i,n){
console.log( $(n).style.height);// if not then just try to simply find the n.style.height
});
//this is another way // at least in ff it would work :)
window.document.styleSheets[0].cssRules[0].style.height
надеюсь, что это поможет, иначе у вас есть много рытья:)
Для второго варианта, где вы видите [0]
, вы должны зацикливаться, так как могут быть разные имена файлов и т.д. и т.д....
полный пример:
var ss = window.document.styleSheets;
for(i=0;i<ss.length;i++){
var rules = ss[i].cssRules;
for(j=0;j<rules.length;j++){//loop style sheets
var rule = rules[j];
if(rule.selectorText=='thing'){//loop each stylesheet rule
console.log(rule.style.height);
// should return height for everytime height is used with every .thing in any of your stylesheets attached :)
}
}
}
ОБРАТИТЕ ВНИМАНИЕ
Вам нужно избежать доступа из cross domain.e.g. если вы включили
<link ....="...jquery.com.../ui.css" />
он не будет работать, поскольку это может считаться угрозой безопасности (перекрестный домен)...
Ответ 3
Это не самое эффективное решение, особенно для старых версий IE, но оно должно работать очень хорошо:
- Измерение высоты элемента
- Добавить некоторый контент в элемент, например.
<div style="clear: left; height: 30px">Test</div>
- Проверьте новую высоту, если она изменила ваш элемент, высота автоматически
- Удалить содержимое
Здесь моя реализация:
$.fn.hasAutoHeight = function() {
if (this.length === 0) return;
var self = this.first();
var height = self.css("height");
var position = self.css("position");
// Check for inline elements
if (self.css("display") === "inline" && self.css("float") === "none") {
var position = self.css("position");
if (position === "static" || position === "relative") return true;
}
// Quick check to see if a style height is set
if ($.style(self[0], "height") !== "") return false;
// Otherwise use the long route
var test = $('<div style="clear: both; height: 30px">Test</div>');
self.append(test);
var hasAutoHeight = self.css("height") !== height;
test.css("color", "red").remove();
return hasAutoHeight;
};
Примечания:
- Строка "быстрой проверки" может работать некорректно, если в CSS есть правило
height: auto !important;
, и в этом случае вам всегда нужно идти по длинному маршруту.
- Это неэффективно с точки зрения взаимодействия с DOM, поэтому ваше приложение будет хотеть кэшировать этот результат, когда это возможно.
- Я не хочу кэшировать результат внутри плагина, потому что правила классов /CSS могут меняться и недействительны результат.
- Это не будет работать для элементов без тела, таких как
<img>
и <br>
Ответ 4
Здесь более полная реализация вышеуказанных предложений:
$("*").data("autoHeight", "false");
var stylesheets = window.document.styleSheets;
for (i=0; i < stylesheets.length; i++) {
var rules = stylesheets[i].cssRules;
for (j = 0; j < rules.length; j++) {
var rule = rules[j];
var style = rule.style.getPropertyValue("height");
var auto = !style || style.match(/^\s*auto\s*(!important)?$/);
$(rule.selectorText).each(function() {
var elem = $(this);
if (asSpecific(rule.selectorText, $(elem).data("autoHeightSelector"))) {
$(elem).data("autoHeight", !!auto);
$(elem).data("autoHeightSelector", rule.selectorText);
}
});
}
}
Вам нужно будет реализовать asSpecific(a, b)
, который должен работать, если css selector a
не менее определен как селектор b
, например. p#foo a#bar
более конкретно, чем p.foo
. Вы также должны учитывать флаг !important
.
Это может быть полезно: http://www.w3.org/TR/CSS2/cascade.html#specificity
Это должно добавить свойство данных для каждого элемента, определяющего, имеет ли он стиль авто height в CSS, но вам также нужно будет проверить атрибут стиля и подумать о стилях по умолчанию.