Перемещение блоков по веб-странице.
Рассмотрим простой пример: перенесем форму поиска со всем ее содержимым из правой колонки в "шапку" этой страницы. Функциональность формы при этом останется прежней. Исходный код документа также не изменится. Изменится лишь структура дерева документа и внешний вид веб-страницы.
Чтобы был понятен именно принцип, не будем усложнять скрипт различными проверками наличия или отсутствия элементов, поддержки методов и пр. Условимся, что "шапку" в документе представляет <div id="header">, у формы поиска: id="searchform", а браузер достаточно современный и поддерживает DOM (объектную модель документа).
Так как проверка наличия элементов в рассматриваемом примере отсутствует, прошу дождаться загрузки формы. И, если вы видите ее над меню в правой колонке, можете проверить как это работает. Кликните по ссылке:
Получилось? Посмотрим исходный HTML-код примера.
<body>
<div id="header">
..."шапка"...
</div>
<div id="content">
<div id="left">
..."левая колонка"...
</div>
<div id="right">
..."правая колонка"...
<form id="searchform">
<input type="text" name="s" />
<input type="submit" value="найти" />
</form>
...
</div>
</div>
...
</body>
После клика по ссылке исходный код останется прежним, а страница в окне браузера изменится и станет такой, как если бы он был таким:
<body>
<div id="header">
<form id="searchform">
<input type="text" name="s" />
<input type="submit" value="найти" />
</form>
..."шапка"...
</div>
<div id="content">
<div id="left">
..."левая колонка"...
</div>
<div id="right">
..."правая колонка"...
...
</div>
</div>
...
</body>
Далее рассмотрим JavaScript примера.
<script type="text/javascript"><!--
function replaceBlock() {
var mBlock = document.getElementById("searchform");
var newPlace = document.getElementById("header");
// клонируем перемещаемый блок
var clonedBlock = mBlock.cloneNode(true);
// и вставляем его в начало "шапки"
newPlace.insertBefore(clonedBlock, newPlace.firstChild);
// убираем старый блок
mBlock.parentNode.removeChild(mBlock);
}
// --></script>
Клик по ссылке <a href="#" onclick="replaceBlock(); return false;">переместить форму поиска!</a> вызывает функцию перемещения блока.
Как видите, скрипт получился не таким уж большим, почти половина строк — комментарии. Его можно немного изменить. Например, сделать более универсальным и передавать функции в качестве аргументов значения ID узлов, которыми нужно оперировать. Цель примера показать именно принцип перемещения узлов, поэтому далее я лучше подробнее расскажу, что делает скрипт.
В первой строке в переменной mBlock оставим узел документа, который будем перемещать.
Переменная newPlace — место, в которое переместим форму.
Клонируем узел, т.е. в нашем случае форму. Метод cloneNode() возвращает копию данного узла. Если значение параметра глубина равно true, вместе с узлом клонируется и его поддерево. Таким образом в переменную clonedBlock помещаем форму со всеми полями, кнопками т.е. со всем, что размещено внутри <form>...</form>.
Теперь нужно определиться, в какое место "шапки" поместим форму. Дело в том, что <div id="header"> не пустой, в нем уже есть какое-то содержимое. Поэтому выбираем один из двух методов DOM: appendChild или insertBefore.
Первый разместит блок в конец узла id="header", после его содержимого, т.е. перемещаемый узел окажется lastChild — последним дочерним по отношению к целевому. Зная заранее, что целевой узел пуст, лучше использовать именно этот метод.
Второй метод более интересен. Он позволяет вставить новый узел перед любым уже существующим. Из известнных и легко определяемых узлов это могут быть, например, firstChild (первый дочерний узел) и lastChild (последний дочерний). Итак, в описанном выше примере форма будет размещена перед первым дочерним узлом узла id="header".
В последней строке скрипта удалим исходный блок. Делаем это по двум причинам. Первая — целью примера было перемещение, хотя ничто не мешает так же копировать узлы документа. Вторая — в корректном XHTML-документе не может быть нескольких элементов с одинаковым ID. При копировании узлов не стоит об этом забывать. Нужно обязательно изменить ID либо исходному, либо скопированному узлу.
Таким образом, не изменяя исходный код XHTML-документа и порядок его загрузки, можно совершенно спокойно изменить структуру дерева документа и внешний вид страницы.
Это может быть особенно полезным при внедрении на страницу чего-либо с другого сервера. Например, различные информеры или баннеры. Если они в исходном коде размещены раньше контента, а загружаются с чужого сервера с перебоями или задержками и тормозят отображение страницы, то их спокойно можно спрятать в невидимый контейнер, например, перед закрывающим </body>. А после загрузки всего докумета (событие onload) переместить в определенное дизайном место на странице и сделать видимым.
круто!!!
2005-10-31 at 1:38 am
Не совсем понятно для чего делается клонирование блока, если используется всего один экземпляр этого блока? На мой взгляд следующая реализация скрипта будет работать аналогично приведённой в статье.
function replaceBlock() {
var mBlock = document.getElementById(”searchform”);
var newPlace = document.getElementById(”header”);
mBlock.parentNode.removeChild(mBlock);
newPlace.insertBefore(mBlock, newPlace.firstChild);
}
2005-10-31 at 12:10 pm
Для Дмитрий К.: не проверял, но должно работать.
В рассматриваемом примере предусмотрен вариант, когда может возникнуть необходимость оставить еще и начальный блок на прежнем месте.
В этом случае последняя строка mBlock.parentNode.removeChild(mBlock); в функции не нужна. Но нужно изменить значение ID какому-либо из блоков: исходному или клонированному. Т.е. примерно так:
mBlock.id = “newID”; – для начального блока или
clonedBlock.id = “newID”; – для клонированного.
2005-10-31 at 12:35 pm
Интересно…
Жаль нету примеров реальной пользы подобного метода, прикладного, так сказать, применения.
Где с пользой можно использовать подобную функцию?
2005-10-31 at 1:19 pm
Для Даниил Зильберман: подобный подход я использовал для переключения между простым и расширенным отображением формы фильтров. Я генерировал в HTML страницу изображение двух форм: простой и расширенной, после этого через myNode.parentNode.removeChild(myNode) “выкусывал” расширенную форму и сохранял её в переменной на странице. А по клику на “расширенном виде фильтров”, вставлял сохранённую расширенную форму и “выкусывал” упрощённый вид формы.
В отличие от управления видимостью своством display, в данном случае взаимозаменяемые части HTML документа могут содержать пересекающийся набор input-ов внутри form-ы.
и если не убрать один из div-ов с помощью removeChild, а просто спрятать по display: none, то данные всё-равно будут посылаться на сервер из двух наборов input-ов и поле username прийдёт дважды.
2005-10-31 at 1:59 pm
Для Дмитрий К., который писал для Даниил Зильберман.
Думаю в данном случае гораздо быстрее работало бы просто скрытие блока с расширенной информацией или восстановление видимости обратно, а для решения проблемы с одинаковыми именами input-ов выставлять свойство disabled для input-ов невидимой формы в true, а для видимой в false. Если input disabled, то при submit’е его данные на сервер не едут, что и решает проблему с дублированием.
Best, Ed.
2005-11-01 at 1:39 pm
Может пригодится, спасибо
Оффтопик:
Щелкнул на баннер валидатора:
http://xhtml.ru/ Failed validation, 72 errors
2005-11-07 at 2:02 pm
http://www.google.com/ig?hl=en
персоналайз ё хомпейдж.. это оно?)
2005-12-03 at 9:12 am