[..], Prototype не позволит переключать элемент в видимый, если он был объявлен невидимым (display: none
) с не встроенным CSS. Это то, что я не поняла и постоянно раздражаюсь. Любой, кто может хоть как-то это понять, получает от меня большое одобрение.
Вы, наверное, уже видели это, но документация, например, show
(есть другие связанные функции с той же заметкой), что:
Element.show
не может отображать элементы, скрытые с помощью таблиц стилей CSS. Обратите внимание, что это не ограничение Прототипа, а следствие того, как работает свойство CSS display
.
Итак, это известная проблема, и они обвиняют CSS. Однако рассмотрим следующий документ (я раньше не использовал Prototype, поэтому я не уверен, является ли это рекомендуемым способом ожидания загрузки DOM, но, похоже, он работает):
<!doctype html>
<script src="prototype.js"></script>
<script>
document.observe("dom:loaded", function() {
$("victim").show();
});
</script>
<style>
p#victim {display:none;}
</style>
<p id="victim">Hello world!
Как вы уже знаете, это не будет работать. Зачем? Ну, а как бы Prototype узнал, на что «сбрасывать» свойство display
, когда вы указываете p#victim
на show
? (Другими словами: как он может узнать, каким должно было быть значение display
, если display: none
не присутствовало в наборе правил с селектором p#victim
.) Ответ прост: это невозможно. (Подумайте об этом на секунду. Что если другой набор правил изменит значение display
, если display: none
не присутствует в нашем наборе правил с селектором p#victim
? (Т.е. мы не можем предположить, что, например, p
всегда должен быть установлен на block
, другие наборы правил могли изменить это значение.) Мы не можем удалить свойство display
из набора правил в таблице стилей и не можем удалить всю связь между элементом и набор правил, потому что он может содержать другие свойства и т. д. (даже если бы это было возможно, imho, было бы неочевидно найти , с которым набор правил можно сделать). Конечно, мы могли бы продолжить и с этим, но afaik нет никакого известного решения этой проблемы.)
Тогда почему встроенная альтернатива работает? Сначала давайте посмотрим, как реализовано show
:
show: function(element) {
element = $(element);
element.style.display = ''; // <-- the important line
return element;
}
Единственное важное, что делает эта функция, - это установить element.style.display
в пустую строку (''
), которая «удаляет» display
из style
. Большой! Но что это значит? Почему мы хотим удалить это ?! Сначала мы должны выяснить, что на самом деле element.style
представляет и изменяет, когда мы изменяем его значения.
Документация MDC для element.style
гласит:
Возвращает объект, который представляет атрибут style
элемента.
Обратите внимание на последнее слово: атрибут . element.style
≠ текущий «вычисляемый» стиль для элемента, это просто список свойств в атрибуте style
(подробное объяснение см. В MDC).
Рассмотрим следующий документ:
<!doctype html>
<script src="prototype.js"></script>
<script>
document.observe("dom:loaded", function() {
$("victim").show();
});
</script>
<p id="victim" style="display:none;">Hello world!
style="display:none;"
скрывает p#victim
, но когда DOM завершит загрузку Prototype, изменит его на style=""
, и браузер пересчитает значение для свойства display
(значение из таблицы стилей браузера по умолчанию в этом случае ).
Но , рассмотрите следующий документ:
<!doctype html>
<script src="jquery.js"></script>
<script>
$(document).ready(function(){
$("#victim").show();
});
</script>
<style>
p#victim {display:none;}
</style>
<p id="victim">Hello world!
jQuery корректно обрабатывает таблицы стилей, в любом случае, в этом случае! Это не так просто объяснить, как решение Prototype, и есть много уровней удивительности, которые я могу прочитать прямо сейчас, и во многих случаях jQuery не может вычислить правильное значение для display
. (Быстрое последнее замечание: Firebug ..., но я предполагаю, что он использует некоторые эксклюзивные материалы Firefox или что-то в этом роде.)