Изменение текста (и оформления) страницы после её открытия в браузере иногда называют DHTML – Dynamic HTML. Справочник по DHTML найти в сети почти невозможно. Гораздо чаще способы обработки HTML страниц в браузере ищут в справочниках JavaScript. Dynamic HTML – более правильное описание вопроса. Потому что JavaScript там совсем немного, и, теоретически, может использоваться любой другой язык. Совсем правильная постановка вопроса: где найти справочник по манипуляциям с DOM – Document Object Model? Такой справочник (достаточно полный, комплексный) нам известен только один – «Справочник веб-разработчика», его автор – Юрий Лукач. Есть, конечно, известные спецификации W3C, но не всегда по-русски и с массой лишней (для практического использования) информации.
Даже основной вопрос – в каком справочнике это искать (к чёрту подробности! в каком я городе?) – сформулировать оказалось не так просто. Дальше – ещё хуже. Вопрос, заданный по-человечески (например, «как удалить прямо на странице лишние буквы из добавляемого пользователем текста?»), надо перевести в «машинные коды» спецификации (или в понятия справочника – который, в сущности, является адаптированной спецификацией).
На это, пожалуй, уходит львиная доля времени начинающего (впрочем, и продолжающего тоже) веб-разработчика – на «перевод» вопросов с естественного языка на язык спецификаций. Попробуем пособирать эти вопросы и дать на них ответы в виде строчек HTML-кода.
1. Как удалить лишние буквы из поля HTML-формы?
Код элемента:
<input name="address" onkeyup="if (this.value.length>3) this.value=this.value.substr(0,3)">
2. Как сделать, чтобы картинка всё время то появлялась, то исчезала (а лучше чтоб ещё и меняла размер), и чтобы текст выезжал слева и плавно двигался вправо?
Никак. Во всяком случае, не в этой жизни.
3. Для чего вообще надо изменять открытую HTML-страницу?
4. Ну, и как скрыть-отобразить выпадающее меню?
Для начала нарисовать схему:
div class="menutop"
Пункт верхнего уровня
div class="menuhid"
Скрытый пункт 1
Скрытый пункт 2
Скрытый пункт 3
...
menutop – главный контейнер столбца меню, в который помещается видимый всегда пункт верхнего уровня и список невидимых при открытии страницы подпунктов. Невидимые пункты помещаются в скрытый контейнер menuhid.
Потом сделать контейнер menuhid невидимым с помощью правила CSS div.menuhid {display:none;} (правило должно быть внутри элемента style или в файле *.css, связанном с данной страницей через элемент link rel='stylesheet').
Потом добавить элементу menutop атрибуты onmouseover='menushow(this,1)' и onmouseout='menushow(this,0)'. Функция menushow будет запускаться при появлении мыши над элементом menutop и должна будет делать видимыми все пункты текущего столбца меню.
Ниже (или выше, или в отдельном файле js) меню нужно поместить внутри элемента script функцию menushow:
<script type="text/javascript"> function menushow(obj,show) { var ch=obj.childNodes var display=(show)?"block":"none" for (var d in ch) { if (1==ch[d].nodeType && "menuhid"==ch[d].className) ch[d].style.display=display } return true } </script>
div class="menutop" Пункт верхнего уровня |
Вот примерно так всё и будет выглядеть (кроме форматирования, конечно, которое вы должны сделать по-своему). Мелкие детали: элементу menuhid обязательно нужно добавить правило CSS position:absolute – чтобы он, становясь видимым, не отпихивал бы нижележащий текст, а появлялся поверх него. Элементу menutop нужно добавить правило CSS position:relative (а то menuhid при абсолютном позиционировании может вылезти чёрт знает где).
Ну, ещё элементу menuhid надо добавить атрибут onclick='menushow(this.parentNode,0)', а то при уходе на другую страницу выпадающее меню останется висеть, и при возвращении, например, по стрелке Alt+Left, страница появится обратно с висящим меню, что, наверное, не очень правильно.
Несколько главных пунктов меню можно поместить в соседние ячейки обычной таблицы (так сделано в примере).
5. Как и где отображать примечания в книге (статье)?
Благодаря HTML теперь нет необходимости собирать все примечания в кучу в конце книги (или внизу каждой страницы). Примечания можно (и нужно) отображать при щелчке по ссылке прямо в том месте, где стоит ссылка (сразу за основным текстом), а скрывать текст примечания тоже можно при щелчке прямо по этому тексту. Подробно всё это описано в Учебнике HTML. Не идеально описано, так как писалось давно, но решение рабочее.
Принципиальная схема отображения примечаний проще, чем отображение скрытых пунктов меню, так как там не нужны правила position:absolute, и текст примечания должен отображаться по щелчку (а если бы по событию onmouseover, как в меню, тогда пришлось бы вкладывать элемент примечания в элемент основного текста, а то при переходе мыши с основного текста к примечанию примечание будет исчезать).
6. Как ограничить размер нескольких элементов с большим количеством текста и по команде пользователя отображать элементы целиком?
Назначить многотекстовым элементам div class="bigtext", задать CSS правило для данного класса элементов div.bigtext {height:150px; overflow:scroll;} – и забы/ить. Пользователи при желании всегда могут увидеть весь текст элемента с помощью прокрутки.
Если предположить, что у пользователей могут возникнуть другие желания (например, видеть текст всех элементов без прокрутки внутри элемента), надо запрограммировать кнопку, которая будет менять отображение элементов bigtext:
<button onclick="togglebigtext(this)">Показать элементы целиком</button>.
Функция, меняющая отображение больших элементов, должна быть примерно такой:
<script type="text/javascript"> function togglebigtext(obj) { var val=obj.firstChild.nodeValue if ("Показать элементы целиком"==val) { height="auto" overflow="visible" } else { height="100px" overflow="scroll" val="Свернуть большие абзацы" } var divs=document.getElementsByTagName("DIV") for (var i in divs) { div=divs[i] if (1==div.nodeType && "bigtext"==div.className) { div.style.height=height div.style.overflow=overflow } } } </script>
Проверьте, как это работает: . Можно вместо button использовать input type="button", тогда проще будет менять его свойство value. А ещё лучше использовать input type="checkbox".
7. Как вести поиск на странице с помощью JavaScript?
Можно как браузер: получить текст всей страницы (например, с помощью свойства body innerHTML) и затем с помощью метода replace заменить во всём тексте фрагменты искомого текста на фрагменты с выделением – что-то вроде <span style="color:red;">фрагмент</span>. Но зачем делать «как браузер», если это и так может делать (и быстрее) сам браузер?
Полезнее организовать поиск в стиле фильтрации – когда на странице остаются только те элементы текста, в которых есть искомый фрагмент. В этом случае возникает вопрос размера «элементов текста» – что это должно быть: слова, предложения, абзацы? К странице с неупорядоченным («естественным») текстом фильтрация практически неприменима (во всяком случае, с помощью JavaScript).
Применять поиск-фильтр имеет смысл лишь к более-менее упорядоченным спискам, и там он может быть очень эффективен. Списки есть на многих веб-сайтах: это списки городов, предприятий, товаров, разделов, людей... Пример работающей фильтрации списка рубрик есть, например, на странице irkutsk.ir2.ru/listrubr.htm.
7. Зачем изменять оформление элементов при наведении мыши?
Чтобы пользователь видел, что какие-то из этих элементов активные – при щелчке по ним будет что-то меняться. Самый главный из таких элементов – ссылка. Курсор меняет свою форму над ссылками сам (точнее, это делает браузер), ничего программировать специально не надо.
Поменять цвет ссылки, над которой мышь, можно без JavaScript, с помощью правила CSS: a:hover {color:red;}. Теоретически так можно поменять цвет любого элемента. Но практически – Интернет Эксплорер саботирует спцификации HTML-CSS, и в нём такое решение работает только для ссылок.
8. Как изменять оформление элементов при наведении мыши?
Используя события элемента onmouseover и onmouseout – при наступлении второго события надо возвращать элементу первоначальный цвет (или фон):
Код элемента:
<div style="color:#060; border:1px solid #999;" onmouseover="this.style.color='red'; this.style.backgroundColor='#fcc'; this.style.cursor='default'" onmouseout="this.style.color='#060'; this.style.backgroundColor='';"> Пример onmouseover </div>
9. Как делать всплывающие подсказки?
Стандартное средство – атрибут title внутри элемента:
Код элемента:
<div title="Достаточно длинный текст...">Пример title</div>
Браузеры отображают перенос строк в атрибуте title по-разному, но ещё хуже то, что они сами устанавливают время отображения title – и пользователь может просто не успеть прочитать, что там написано. Поэтому более надёжно, конечно, использовать атрибут onmouseover и отображать с помощью функции JavaScript заранее приготовленный элемент со всплывающей подсказкой какой угодно формы:
Код элемента:
<div onmouseover="this.firstChild.style.display='block'" onmouseout="this.firstChild.style.display='none'" style="position:relative;"><div style="display:none; position:absolute;"> заранее приготовленный элемент со всплывающей подсказкой </div> Пример всплывающей подсказки onmouseover</div>
Обратите особое внимание на фрагмент кода relative;"><div: между открывающим тэгом внешнего элемента и открывающим тэгом вложенной в него подсказки не должно быть ничего (ни пробела, ни разрыва строки – именно ничего!). Иначе приведённый код не будет работать, так как firstChild для внешнего элемента будет уже не заготовленная подсказка, а текст (textNode) – тот самый разрыв строки или пробел.
Ну, и при абсолютном позиционировании элемента внешний для него элемент (родительский) должен иметь позиционирование как минимум relative (то есть обязательно хоть какое-то особое, не static). Иначе позиционируемый элемент может унести неизвестно куда.
Проверку вводимых пользователем данных и некоторые другие вопросы применения DHTML мы рассмотрим в следующей статье.
Кирилл,
теперь этого я даже и знать не хочу – как вернуть первоначальный цвет с помощью конструкций типа el.style.backgroundColor=''. В этой части статья устарела, точнее, изначально опиралась на неверную технологию.
Лучше делать изменения оформления с помощью конструкций типа el.className='red'. А, поскольку в класснэйм уже может что-то находиться изначально, я написал специальные функции addclass и delclass (есть в библиотеке http://ir2.ru/static/ir2.js).
Т.е. разумная логика для раскраски элементов по событиям примерно такая: 1) создаёте в наборе CSS класс – например .onmouseo {color:red;}; 2) при событии, например, onmouseover, добавляете этот класснейм вызвавшему элементу: addclass(el, 'onmouseo'); 3) при противоположном событии удаляете класснейм: delclass(el, 'onmouseo').
Методика используется на этом сайте, например, в табличном редакторе tableedit2.aspx.
А как,все-таки, узнать первоначальный цвет кнопки, чтобы задать его для onmouseout?