Вот ответ на мой собственный вопрос, который я сформулировал сегодня после игры с IE8, FF, Chrome и Safari.
Допустим, мы хотим сложить и развернуть элемент div по вертикали (поэтому мы будемговорить только о высоте для простоты) с минимально возможным JavaScript и без jQuery.Может быть встроенное окно сообщения об ошибке, которое вы хотите показать и скрыть на странице.Само окно сообщения является эластичным, и вы не знаете его фактических размеров.Здесь необходимо решить две основные проблемы:
Проблема № 1: свойства offsetHeight, clientHeight и scrollHeight общеизвестно несовместимы во всех браузерах.Вы не можете полагаться на них, особенно когда для поля margin / padding / border установлено значение, отличное от 0, и когда высота CSS отличается от значения по умолчанию (т.е. при фактическом сворачивании / разворачивании элемента).Есть getComputedStyle (), но он доступен только в нормальных браузерах, а не в IE.OTOH, свойство IE currentStyle не возвращает вычисленные значения, как вы могли ожидать (например, вы можете увидеть «auto» в качестве значения высоты).Оказывается, без полей / отступов / полей offsetHeight надежен и совместим со всеми современными браузерами.
Проблема №2: единственный способ (насколько мне известно) анимировать ваш элемент div - это изменить стиль.высота, которая, однако, не включает отступы и границы, и, таким образом, вы не можете анимировать блок до 0 или начать анимацию с 0 для элементов с ненулевым заполнением и границей.(Кроме того, IE не принимает 0px как style.height, поэтому минимальный размер в любом случае будет 1px).
Решение обеих проблем состоит в том, чтобы обернуть вашу коробку другим div с использованием стиля по умолчанию.то есть padding / margin / border все установлено в 0, что является стилем по умолчанию для нового div.Поле, которое вы хотите сложить и развернуть, должно быть внутри, и оно не должно иметь настройки полей, только отступы и границы при желании.Таким образом, вы сможете (1) надежно определить высоту вашего эластичного внутреннего блока с помощью offsetHeight и (2) анимировать высоту внешнего блока в 1 пиксель и из него.
Итак, скажем,мы хотим оживить это:
<div id="errmsg" style="display:none">
<div class="errmsg">
<div class="window-close" onClick="javascript:showErrMsg('', this.parentNode.parentNode)"></div>
<div id="errmsg.text"></div>
</div>
</div>
Ящик невидим в начале.Класс "window-close" - это небольшой прямоугольник справа с крестиком, который используется для скрытия прямоугольника при нажатии.Вызов showErrMsg () с пустой строкой сворачивает окно сообщения (см. Ниже).
Мой код JavaScript для анимации этого окна сообщения об ошибке выглядит следующим образом (я также анимирую прозрачность, которая здесь опущена для простоты):
var ANIMATE_STEPS = 10;
var ANIMATE_DELAY = 20;
function _obj(obj, parent)
{
if (typeof obj == 'string')
obj = (parent ? parent : document).getElementById(obj);
return obj;
}
function _setStyleHeight(obj, h)
{
_obj(obj).style.height = Math.round(h) + 'px';
}
function _animateVertFold(obj, cur, by, lim)
{
obj = _obj(obj);
cur += by;
if (by < 0 && cur <= 1)
{
obj.style.display = 'none';
_setStyleHeight(obj, 1); // IE doesn't accept 0
}
else if (by > 0 && cur >= lim)
{
_setStyleHeight(obj, lim);
}
else
{
_setStyleHeight(obj, cur);
setTimeout('_animateVertFold(\'' + obj.id + '\', ' +
cur + ', ' + by + ', ' + lim + ')', ANIMATE_DELAY);
}
}
function _expandElem(obj)
{
obj = _obj(obj);
if (obj.style.display == 'none')
{
obj.style.overflow = 'hidden';
_setStyleHeight(obj, 1);
obj.style.display = 'block';
var innerDiv = obj.getElementsByTagName('div')[0]; // better way?
var h = innerDiv.offsetHeight;
if (h > 0)
_animateVertFold(obj, obj.offsetHeight, h / ANIMATE_STEPS, h);
}
}
function _shrinkElem(obj)
{
obj = _obj(obj);
if (!obj.style.display || obj.style.display != 'none')
{
obj.style.display = 'block';
obj.style.overflow = 'hidden';
var h = obj.offsetHeight;
_animateVertFold(obj, h, - h / ANIMATE_STEPS, h);
}
}
function showErrMsg(msg, id)
{
id || (id = '_errmsg');
obj = _obj(id);
if (msg != '')
{
_obj(id + '.text').innerHTML = msg;
_expandElem(obj);
}
else
_shrinkElem(obj);
}
Вы можете вызвать showErrMsg (), и код позаботится обо всем остальном.Вы должны будете определить класс закрытия окна как нечто, имитирующее кнопку закрытия окна GUI.И, конечно, класс «errmsg» в виде блока с отличным цветом фона, рамкой и, возможно, шрифтом.