Веб-сайт с минимальными затратами: учебник HTML

Практика JavaScript и DHTML


учебник HTML скачать
(вся книга в одном файле 3.92М)

  • Учебник HTML в одной главе (вместо пролога)
    Что мешает вам создать веб-сайт и поместить его в Интернет? Несколько страниц текста, 15-20 минут работы - и о вашем существовании сможет узнать весь мир.
  • Гл. 1. Больше одной страницы
    Сайт из пяти страниц. Минимум HTML-тэгов. Основы навигации (гиперссылки).
  • Гл. 2. Прайс-лист. Таблицы и архивы
    Перенос списка товаров из бухгалтерской программы в Excel. Надстройка Excel для сохранения в формате HTML. Упаковка в архив zip.
  • Гл. 3. Продвижение
    Поиск информации в Интернете. Заголовок страницы (title). Краткое описание (meta description). Правильная кодировка страницы. Веб-сайт как рекламоноситель.
  • Гл. 4. Обратная связь
    ...ни с кем не встречайтесь, никому не звоните, не трогайте почтовые конверты, не распечатывайте счета, вообще не прикасайтесь к бумаге, раз уж существует электронная почта!
  • Гл. 5. Испытания в полевых условиях
    Баловство с IIS на Windows. Практической цели не имеет.
  • Гл. 6. Работа с графикой
    Фотография, полиграфия и веб. Экранное разрешение. Режим «Индексированный 256», уменьшение количества цветов в палитре. Вставка изображений в HTML-страницу. Атрибут ALT.
  • Гл. 7. Оформление с помощью CSS
    Блочные HTML-элементы. Управление цветом и размером многих элементов с помощью правил. Особенности в интерпретации HTML разными браузерами. Поля. Оформление ссылок (изменение цвета при наведении мыши - hover).
  • Гл. 8. Изменение структуры. Обновление
    Каталог продукции: картинки с описаниями. Отличие элементов PRE и P. Добавление прозрачности изображениям. Выравнивание по вертикали. Обработка текстов с помощью поиска и замены символов. Немного об HTML-таблицах.
  • Гл. 9. Javascript: баловство или необходимость?
    Получение информации о браузере (интернет-обозревателе, клиенте, агенте). Оформление с помощью JS: невидимая на экране команда JavaScript вставляет в текст страницы невидимую глазом инструкцию - и вид страницы изменяется. Оптимизация кода.
  • Гл. 10. Примечания (сноски) в книге
    В HTML-странице не обязательно собирать все примечания в конце. Их можно отображать и скрывать по желанию пользователя прямо там, где стоит ссылка на сноску.
  • Гл. 11. DHTML для нашего сайта
    События onclick, oncontextmenu. Знакомство с DOM (объектной моделью HTML-документа). DHTML-шутка: сайт в одной странице.
  • Гл. 12. Электронные документы
    Скрыть или показать часть стуктуры. Создание оглавления.
  • Учебные материалы
    Файлы примеров для учебника HTML, спецификации W3C, несколько полезных программ.

Статьи

  • ООП в PHP – антипаттерн
    PHP здесь взят для простоты, как наиболее употребительный язык веб-приложений. ООП вообще не нужно в вебе, так как все его плюсы уничтожаются одним большим минусом: ООП намертво связывает логику ... 13.02.12
  • Конструктор HTML форм
    Начнём с того, что конструктор форм, как и конструктор сайтов, есть вещь принципиально невозможная. Как, впрочем, и любой конструктор вообще. Конструктор – выражение фигуральное, метафорическое. В ... 01.02.12
  • Числа прописью с рублями, минутами и метрами
    Эта тема беспокоит меня давно, с тех пор, как в нашей газете научились отправлять электронные счета электронной почтой. В счёте ведь надо было как-то превращать цифры с слова (типа «Два миллиона сто ... 15.11.11
  • Календарь javascript (datepicker)
    В сети полно чудовищных скриптов для наглядного выбора даты с помощью указателя мыши. Эти скрипты не могут быть не чудовищными по определению, так как созданы для позорной задачи: облегчить жизнь ... 15.11.11 Комментарии (2)
  • Что из чего следует в PHP-фреймворке «Friends»
    «Friends» - рабочее название маленького PHP-фреймворка (16 K кода, вместе с CSS, но пока без javascript), находящегося в сомнительных отношениях с mvc, но бодро работающего. В предыдущей статье мы ... 29.10.11 Комментарии (1)
  • PHP фреймворк, анти-MVC, без ООП
    С самого начала изучения MVC мне не понравилось слово «модель». И не зря. На громадном количестве сайтов это понятие действительно не применимо. Там есть Данные, есть какое-никакое их Отображение. ... 17.10.11 Комментарии (6)
  • Идеальная функция setCookie
    Сравнение двух интересных библиотек (http://microbasejs.ru/, http://github.com/Kolyaj/CrossJS) привело меня к озарению и созданию совершенно особой, доселе невиданной функции по установке куки (с ... 03.10.11 Комментарии (1)
  • Отображение настроек для javascript сортировки
    Очень сложная оказалась задача – дать пользователю возможность настраивать колонки таблицы не по Ctrl+click, а наглядно, как в оконных приложениях, выбором с помощью мышки. Весь моск вывернула ... 29.09.11
  • Что такое Контроллер mvc в вебе?
    MVC – Модель, Контроллер, Вью (Представление). Вместо мутного «Модель» используем «Данные». И попытаемся определить откуда у всего этого ноги растут. Данные – это что-то, что хранится в компьютере; ... 25.09.11
  • javascript сортировщики, сравнение алгоритмов
    Всякое сравнение хромает в пользу того, кто сравнивает. Попробуйте поискать в сети страницы по фразам «Сортировка HTML таблиц», «javascript сортировка», «table sorter»... Можно найти немало решений, ... 15.09.11
  • unobtrusive top.mail.ru
    Лет 5-6 назад среди веб-разработчиков распространилась мода на «unobtrusive javascript» – «ненавязчивый» javascript, который внедряется в тело HTML страницы только в виде ссылок на файлы js (а не в ... 15.09.11
  • Простой сортировщик HTML таблиц, версия 0.03
    Simple Table Sorter v 0.03 Первый Простой сортировщик HTML таблиц (версия 0), упоминаемый на этом сайте, был придуман далеко не первым по времени, а примерно через год работы над концепцией. Была ... 09.09.11
  • Подсветка строк, столбцов и значений в HTML таблице
    Это следующая версия скрипта Big Table Sorter – 1.01. Почти год назад в статье http://ir2.ru/tabsort1.aspx мы сформулировали концепцию полнофункционального сортировщика HTML таблиц. Казалось, что ... 06.09.11
  • Отложенная загрузка javascript
    Когда в очередной раз пользователи начали жаловаться на «странную» работу некоторых функций корпоративного сайта, мне пришлось вникнуть в проблему. Она оказалась очень простой: 1) после загрузки ... 16.07.11
  • Кэширование промежуточных результатов в веб-программировании
    Кэширование в php-скрипте Существует такой шаблон проектирования (или приём программирования) «Экстрактор»: создаваемая конструкция не знает о существовании или отсутствии элементов, она просто ... 28.06.11
  • javascript и php: синхронизация сущностей
    Вот форма на сайте ("вот дом, который построил Джек"). Вот кнопка submit, при щелчке по которой запускается функция валидации формы. Вроде всё, как всегда, стандартный пример. Но, если подумать, ... 24.06.11
  • Скругление углов CSS, JavaScript
    Кажется, на эту тему трудно написать что-то новое. Точнее, трудно изобрести новый метод скругления углов. А взглянуть на проблему под другим углом всегда можно. Мы попробуем доказать неизбежность и ... 04.06.11
  • Javascript и логика представления (design pattern «JS-словари»)
    В статье о генерации HTML формы для wysiwyg редактора мы привели пример небольшой автоматизации в программировании – создание формы на основе структуры mysql-таблицы и последующая обработка данных ... 29.05.11
  • Структура WYSIWYG-редактора сайта
    WYSIWYG – это наглядный редактор (прежде всего, для текста): вы выделяете фрагмент, нажимаете в управляющей панели кнопку B – и фрагмент становится жирным. Так можно делать, например, в Ворде, или в ... 07.05.11
  • Подсветка картинки при наведении мыши
    Хорошей практикой веб-строительства является создание таких гиперссылок (и других активных элементов), которые изменяются при наведении мыши. У гиперссылок, по спецификации W3C, даже существует для ... 02.05.11
  • Визуальные редакторы: для кого они?
    В давние-давние годы, когда в Иркутске только начали появляться компьютеры и про Интернет ещё никто ничего не слышал, для вёрстки использовали программу Xerox Ventura Publisher (Вентура). Вёрстка, ... 27.03.11
  • Веб/2: сайты нового поколения
    ПредысторияЧтобы дать определение новому понятию «Полувеб», надо вспомнить сначала, что такое «веб 2.0». О нём много пишут; как всегда, лучше всего в Википедии. С содержательной стороны – это ... 28.12.10 Комментарии (2)
  • Как измерить скорость работы Javascript?
    На самом деле хочется, конечно, знать общую скорость (точнее, время) вывода на экран какой-либо информации. В нашем случае – информации, получаемой с помощью браузеров (то есть скорость вывода ... 21.12.10 Комментарии (2)
  • Функция для работы с className в javascript
    Изменение атрибута class у HTML-элементов является основой, базой для управления содержимым страницы с помощью DHTML. Любое действие по оформлению проще всего производить, именно изменяя динамически ... 18.12.10
  • Сортировщик HTML таблиц, версия 1
    В предыдущей статье мы попытались определить минимально необходимые свойства сортировщика таблиц. Вряд ли произведённые определения можно сильно оспорить; другие минималистские сортировщики в общем с ... 11.12.10 Комментарии (1)
  • Сортировщик HTML таблиц: концепция и «нулевой цикл»
    У кого sorter тинее? В процессе работы над сортировщиком (как и над любой другой программой) приходится многократно обращаться к разным вариантам, существующим в виде открытых решений в Сети. И ... 09.12.10 Комментарии (32)
  • Как с очень высокой скоростью найти слово в большой таблице?
    В предыдущей статье мы показали, как два уровня (или два приёма) javascript-кэширования могут увеличить скорость поиска по списку из 400 элементов в десятки раз. Там были важны три ... 06.12.10 Комментарии (2)
  • Как в большом списке найти слово с очень высокой скоростью?
    Простой список. Прямой алгоритм Начнём с нашего любимого примера – простого (в одну колонку) списка рубрик из справочника предприятий vostsibspravka.ru: listru1.htm. Наиболее очевидный алгоритм ... 06.12.10
  • HTML база данных лучше, чем Excel
    Второй вопрос после "как сортировать и фильтровать данные в HTML-таблице?" обычно возникает у критиков: "А нафига?" Скептицизм здесь уместен: пользователи обычно получают HTML-страницы с веб-сервера, ... 05.12.10 Комментарии (1)
  • Javascript база данных
    Есть такой анекдот (или притча) о злой тётке, которая один раз в жизни пожалела нищенку и подала луковое пёрышко; а потом в аду черти тётку топили, а нищенка протянула ей то самое луковое пёрышко и ... 28.10.10
  • Сортировщик HTML-таблиц, версия 1.3
    Статья о сортировке HTML-таблиц была написана год назад. Так получилось, что описываемая технология заинтересовала некоторых начинающих программистов, и они стали задавать вопросы и высказывать ... 30.09.10 Комментарии (5)
  • Проверка условий в Javascript
    Веб-программист постоянно вынужден что-то проверять: правую кнопку мыши нажал пользователь или левую, заполнено ли в форме поле «Поиск», есть ли на странице элемент с id = "console"... Иногда это ... 25.09.10
  • Скрыть – показать HTML элементы с помощью Javascript
    Специалист – человек, который, избегая мелких ошибок, неуклонно движется к глобальному заблуждению. Закон программирования Мэрфи, ст. 17 Специалист подобен флюсу: полнота его одностороння. Козьма ... 11.09.10 Комментарии (2)
  • Таймеры в Javascript (setInterval, setTimeout)
    В программировании на скриптовых языках периодически возникает необходимость создать паузу – приостановить выполнение программы на некоторое время, а потом продолжить работу. Например, в сценариях ... 26.08.10 Комментарии (14)
  • Javascript фильтрация данных
    Сортировать HTML-таблицу мы уже научились. Вторая после сортировки задача базы данных – выборка строк из таблицы по определённому критерию. Например, чтобы поле город заканчивалось на -тск. ... 24.08.10 Комментарии (13)
  • Javascript: вопросы и ответы
    Все примеры javascript для данной страницы находятся в файле o3.js. Для правильной работы скриптов необходима также библиотека ir2.js. Как запомнить options, выбранный в элементе select? ... 18.07.10
  • Javascript: часто задаваемые вопросы
    Как удалить пробелы в Javascript с учётом  ? Речь, понятно, идёт не о всех пробелах подряд, а о лишних пробелах справа и слева, т.е. об аналоге функции trim (удаляющей справа и слева строки ... 27.02.10 Комментарии (3)
  • Редактирование таблицы MySQL: Javascript интерфейс
    В предыдущей статье мы рассмотрели предельно простой способ доступа к базе данных MySQL (редактирование таблицы без перезагрузки HTML страницы). Отправка данных на сервер производилась через ... 21.02.10 Комментарии (7)
  • Редактирование таблицы MySQL в браузере
    Заголовок, конечно, пугающий, но там (здесь), в общем, ничего необычного: редактирование таблицы MySQL происходит всё-таки с помощью серверного скрипта PHP. К тому же пользователи вообще очень часто ... 24.01.10 Комментарии (8)
  • 10 лучших функций Javascript
    Функция удаления со страницы ссылок «на себя» stripSelfHref() DOM-инспектор dom-javascript.js Функция scriptRequest() (фоновые http-запросы) Функция записи куки setCookie() ... 16.01.10 Комментарии (1)
  • Сортировка таблицы средствами JavaScript - DOM
    Вопрос когда-то с неизбежностью возникает перед любым добросовестным веб-мастером: зачем перегружать HTML страницу при сортировке таблицы? Нельзя ли перегруппировать HTML элементы таблицы прямо в ... 09.01.10 Комментарии (54)
  • DHTML: условная разметка для HTML кода
    Стили набора и форматирования Как авторы обычно оформляют текст при наборе? Например, когда надо какое-то слово сделать курсивным? Результат можно получить разными способами: Нажать мышкой в ... 05.01.10
  • DHTML: защита форума
    Как защитить фор(ум|му) от спама? Форма – это дыра, через которую сообщения пользователя отправляются на сервер. Точнее, несколько дыр: текст сообщения, автор, e-mail... Форма 1. Автор: ... 02.01.10 Комментарии (3)
  • DHTML: хранение настроек пользователя
    Для чего нужен Dynamic HTML Убрать Развернуть и запомнить ... 30.12.09
  • DHTML: проверка формы
    В предыдущей статье http://ir2.ru/dhtml.aspx мы сформулировали ряд причин, по которым бывает необходимо изменять HTML страницу после её открытия в браузере. Повторяем здесь список этих причин: ... 26.12.09 Комментарии (2)
  • DHTML
    Нечасто задаваемые вопросы Изменение текста (и оформления) страницы после её открытия в браузере иногда называют DHTML – Dynamic HTML. Справочник по DHTML найти в сети почти невозможно. ... 24.12.09 Комментарии (2)
  • JavaScript
    О популярности JavaScript в Википедии слагают легенды. Специалисты объясняют эту популярность в основном простотой языка и широкой поддержкой в прикладных программах. Такой взгляд кажется нам немного ... 13.12.09 Комментарии (1)
  • HTML таблицы
    Таблица (элемент table) является, пожалуй, самой загадочной и сложной конструкцией языка HTML. Хотя собственно HTML тут ни при чём, таблица сложна по самой своей сути, по противоречивой логике ... 07.12.09
  • Самый быстрый браузер
    В последние годы интернет-обозреватели не радуют нас разнообразием рекламы: «С новой версией NN ваш веб-сёрфинг станет ещё безопаснее!» – наиболее типичный призыв производителей. А ... 26.10.09 Комментарии (3)

Добавить статью:

*Заголовок:
Имя файла (только латинские буквы):
Автор:
*Текст:

Глава 12. Электронные документы

Договор N10

Идея «скрыть-отобразить содержимое определённого уровня» используется в различных электронных документах: например, в договоре, оформленном в MS Word с помощью заголовков разного уровня, или в MS Excel, в таблице с промежуточными итогами. В подобных документах можно представить структуру так, что около заголовков определённого уровня появляются знаки «+» или «-» - при щелчке по этим знакам на экран выводятся (или удалются с экрана) заголовки ниже лежащих уровней.

Вот html-текст очень коротенького документа, на котором мы покажем, как эту задачу можно выполнить средствами HTML:

<meta http-equiv="content-type" content="text/html; charset=windows-1251">
<script src='dog1.js'></script>
<link rel="stylesheet" href="dog1.css" type="text/css">
<style type="text/css" id="st1"></style>
<div>
<h1>Договор N10</h1>
<p>ООО "Блик" в лице директора и ОАО "Трезвость" в лице председателя 
 заключили настоящий договор о нижеследующем:</p>
<h2><span id="s1" onclick="doit('s1')">+ </span>1. Предмет договора</h2>
<h3 class="s1">1.1. ООО "Блик" оказывает некие услуги.</h3>
<h3 class="s1">1.2. ОАО "Трезвость" оплачивает услуги.</h3>
<h2><span id="s2"  onclick="doit('s2')">+ </span>2. 
 Ответственность сторон</h2>
<h3 class="s2">2.1. Если услуги не оказаны, штраф.</h3>
<h3 class="s2">2.2. Если услуги не оплачены, штраф.</h3>
</div>

ex29 Файлы примеров: dhtml4 (dhtml4)

В html-структуру документа заложена следующая идея: className ряда нижележащих заголовков назвать так же, как и идендтификатор верхнего, управляющего заголовка (вернее, части заголовка - вложенного в заголовок элемента span). В файл css для заголовков нижнего (третьего, и, если бы они были, четвёртого-пятого) уровня записано правило:

h3 {font-size: 1em; margin:.5em 0 0 2em; display:none;}

То есть при открытии документа пользователь видит только заголовки уровня 1-2. Элементы span в начале каждого заголовка второго уровня содержат текст «-» (минус) и функцию doit в качестве значения своего свойства onclick:

function doit(cls) {
 var sc=document.getElementById(cls);
 var tg=document.getElementsByTagName ("h3");
 for(i=0; i

Функция находит все элементы следующего уровня (h3), затем проверяет, имеют ли найденные элементы className, равный идентификатору текущего элемента (вызвавшего функцию). Попутно функция меняет цвет префикса заголовка: если плюс, то красный, если минус - зелёный. Можете попробовать самостоятельно добавить к тексту заголовки более низких уровней (h4) и создать систему, отображающую или скрывающую их по щелчку на заголовках h3.

Договор N10: развитие

Как всегда, после взгляда на готовый продукт возникает ощущение его несовершенства. Опять, как и в работе над сносками книги, достаточно очевидно слабое место: большое количество именованных элементов. Задача первая - попробовать упростить структуру (и тем самым сделать её надёжнее). Второй момент - попробуем всё-таки углубить уровни вложенности текста и посмотреть, насколько это всё будет работать. Третье - нельзя ли сделать автоматическую нумерацию пунктов, как в Worde?

Первую задачу решить довольно легко, если вкладывать подчинённые данному элементу подзаголовки в один общий контейнер, например, div. После заголовка 1. ставим открывающий тэг <div>, затем пишем все пункты 1.1., 1.2. и т. д., затем ставим закрывающий тэг </div>. И всё хорошо: при щелчке мышью на заголовке ищем nextSibling, и в найденном элементе div ищем всех потомков (все вложенные элементы), и делаем их видимыми. Или ещё проще: делаем видимым или невидимым сам общий элемент div.

Вторую задачу выполним просто добавив в документ текст. Третья задача, к сожалению, простым способом в HTML не решается. Существуют специальные элементы - нумерованные списки: в тэги <ol> и </ol> вкладывается несколько элементов li (то есть фрагментов текста, заключённых в тэги <li> и </li>). Попробуйте - на экране все элементы li станут пронумерованными.

<ol>
<li>Первый</li>
<li>Второй</li>
<li>Третий</li>
</ol>

Стиль нумерации можно изменять: делать латинским цифрами, буквами… Внутрь одного списка ol можно вкладывать другие списки, HTML при этом будет делать на экране новые отступы в глубину текста для каждого уровня вложенности. Всё, в общем, хорошо, кроме одного: HTML не может делать многоуровневые списки, в каждом вложенном списке нумерация будет точно такой же, как и во внешнем: 1, 2, 3 - или a) b) c)...

Поэтому наша нумерация будет полуавтоматической: с помощью вложенных друг в друга списков, в начало пунктов которых мы будем вручную добавлять префикс - номер «родительского» заголовка для данной группы пунктов:

...
<ol><li><span class="s1" onclick="doit(this)">+ </span>
Предмет договора
<ol class="hiddn">
<li><span class="s2" onclick="doit(this)">+ 1.</span>
ООО "Блик" оказывает некие услуги.
<ol class="hiddn">
<li><span class="s3" onclick="doit(this)"> 1.1.</span>
Например, обувь чистит</li>
...

В самой первой строчке примера нет в явном виде номера (на экране появится «1»), и я не знаю, можно ли его быстро получить через DOM (объектную модель документа) HTML. В любом случае, конечно, можно просто пересчитать все элементы ol, проверить наличие у них потомков и вычислить нужный номер программно. Но не сейчас.

ex30 Файлы примеров: dhtml5 (dhtml5)

У нас пока куча других проблем: как теперь окрасить плюсы и минусы в разный цвет? Как заставить префиксы (вместе с плюсами) появляться точно перед началом пункта списка?

В предыдущей версии для окраски плюса мы просто назначали всему элементу span нужный цвет. Теперь у нас кроме плюса там есть ещё и префикс из чисел и точек. Его красить не нужно. Для такой ситуации в системе CSS существуют псевдоэлементы :first-letter. Мы пишем, например, в правиле: p:first-letter {color:red} - и первая буква каждого абзаца окрашивается в красный цвет. Так же поступим и в нашем случае:

span:first-letter {color:#990000; }

99 - не самый яркий красный (самый яркий - ff). Придётся делать целую таблицу цветов для префиксов разных уровней - из-за метода, который мы выбрали для решения последней задачи - позиционирования префиксов. Вернее, не из-за самого метода как такового, а из-за сложности его доработки. Мы только наметим здесь путь решения, а желающие могут идти по этому пути дальше и сделать всё лучше.

В HTML-CSS можно позиционировать элементы весьма произвольно, если задать им правило position:absolute. После задания этого правила можно указать точные координаты элемента на странице, и он встанет на это место поверх любых других элементов (невзирая на их собственное расположение).

У нас проблема в том, что префикс располагается где-то в середине элемента li, надо его сдвинуть влево, к началу элемента. Для этого после задания абсолюной позиции надо задать элементу ещё и параметр left - сколько отступать слева (можно и отрицательное значение). От чего именно браузер будет отмерять отступ влево? В явном виде этого указать нельзя, но мы знаем, что правила CSS гласят: отступ будет делаться от границы ближайшего позиционированного предка данного элемента. Если нет ни одного позиционированного вообще - от границы элемента body.

Нам, конечно, удобнее вести отсчёт от самого ближайшего предка - элемента li, в который вложен наш span. Для этого li надо сделать позиционированным: задать какое-нибудь значение его свойству position, всё равно, какое. Как раз для «всё равно какого» в CSS есть удобное значение relative - оно предназначено для небольших смещений элемента относительно его собственной нормальной позиции; если не задавать никакого смещения, элемент так и останется на своём месте, но станет позиционированным. CSS в результате станет примерно таким:

span {cursor:pointer; font-weight:normal; position:absolute; 
  left:-3.5em; }
span.s1, span.s11 {left:-2.8em;}
span:first-letter {color:#990000; }
li.ie {list-style-type: none }
ol {margin:0 0 1em 3em; line-height:1.4em; padding:0}
li {position:relative; padding:0}

Ну, и ещё куча классов для разных span из-за того, что в разных li они почему-то смещаются по-разному (весь текст полностью в файле dog1.css) - потому что у нас объективно три разной длины варианта span: плюс без префикса (в первом уровне), плюс с префиксом (во втором), префикс без плюса (в третьем). Да ещё отдельно стоящий плюсик вверху, для показа всего текста всех уровней сразу. И на закуску самое «сладкое»: вся эта конструкция в Интернет Эксплорере версии 5 не работает. Поэтому таблицу стилей надо подключать динамически с самого начала, при загрузке страницы, и при этом определять не только типы, но и версии браузеров.

Нельзя во время загрузке страницы найти элемент llink rel="stylesheet"... по идентификатору, потому что пока страница полностью не загрузилась, браузер ещё не видит всех элементов. Можно, например, записать распознавание браузера в функцию и вызывать её по событию onload (<body onload="функция">). Но мы для разнообразия поступим сейчас по-другому (таких примеров нам ещё не встречалось): вообще ничего не напишем в html-коде про самый главный CSS-файл для нашего html-документа, а в файле dog1.js вне функций (то есть прямо в процессе загрузки страницы) сформируем динамическую запись в html-код, изменяющуюся в зависимости от типа и версии браузера:

 var agent = navigator.userAgent.toLowerCase();
 var css;
 if (agent.indexOf("msie 5") > -1 && agent.indexOf("opera") == -1) 
  css="dog1ie5.css";
 else if (agent.indexOf("msie 6") > -1 && agent.indexOf("opera") == -1) 
  css="dog1ie6.css";
 else css="dog1.css";
 document.write("<link rel='stylesheet' href='"+css+"' type='text/css' />");

Похожий код мы уже использовали в других примерах, разница в том, что мы ищем теперь в названии браузера не просто «msie», а «msie 5» или «msie 6». Ну, и не изменяем атрибут существующего элемента, а, используя метод document.write, создаём в процессе открытия страницы новый элемент link. В функции, раскрывающей очередной уровень списка, много деталей, которые нам ещё не встречались и требуют пояснения:

function doit(a) {
 var master=a.parentNode;
 var slaves=master.childNodes;
 for(var el in slaves) {
  if (slaves[el].tagName=="OL") {
   slaves[el].style.display=(slaves[el].style.display=="block")
     ?"none":"block";
  }
 }
 var s = String(a.firstChild.nodeValue);
 var clss=a.className;
 a.className=(clss.length==2)?clss+"1":clss.substr(0,2);
 a.firstChild.nodeValue=(s.charAt(0)=="+")?
   s.replace("+", "–"):s.replace("–", "+"); 
}

Во-первых, конструкция for... in: предварительно мы создаём массив из всех потомков элемента, в который вложены строки списка, записываем этот массив в переменную slaves; затем пишем волшебную формулу с for... in: «для каждого идентификатора элемента el в массиве slaves найти по этому идентификатору сам элемент массива (slaves[el]) и выполнить для него некоторые действия - сделать видимым или невидимым».

Затем мы записываем в переменную s текст текущего элемента span (по которому щёлкнули) и если первый символ этого текста (находим с помощью метода charAt(0) - нумерация символов начинается с нуля) «+», меняем его на «–» с помощью метода replace("+", "–") (и наоборот). Затем меняем имя класса текущего элемента: если длина имени (clss.length) равна двум (значит, имя имеет вид «s1», «s2» и т. д.), добавляем к этому имени единицу (и оно становится, соответственно, «s11», «s21» и т. д.), а в правилах нашего главного CSS-файла записано, как меняются в зависимости от этого цвета первого символа элемента «span». Ну, а если длина имени класса не равна двум (значит, она больше), сокращаем до длины в два символа: clss.substr(0,2) - «выбрать из переменной clss подстроку начиная с первого символа и длиной в два символа».

Функция, запускаемая отдельно стоящим вверху плюсиком, работает в точности так же, как и функция из примера omne\js5 (отображение или сокрытие всех примечаний в документе). Разумеется, в нашем последнем примере функция показа всех уровней и функция показа отдельного фрагмента противоречат друг другу по идеологии, и после нескольких щелчков по плюсам, вызывающим эти разные функции, они начинают отображать (скрывать) содержимое не так, как ожидалось. В этом случае не остаётся ничего другого, как нажать функциональную клавишу F5.

«Естественный» WYSIWYG редактор HTML

Мы уже показывали в Главе 8, как построить импровизированный визуальный редактор HTML из хорошего текстового редактора с синтаксической подсветкой и браузера. Но под «визуальностью» можно понимать разное. В том нашем случае - вписал тэг <b> и </b> в код документа, нажал в браузере «F5» - и наглядно видишь, как шрифт стал полужирным. Существует ещё другая визуальность, более высокой степени: выделил фрагмент текста мышкой, нажал какую-нибудь кнопку, и шрифт стал полужирным. Называется WYSIWYG - what you see is what you get («что вы видите, то и получите», то есть если в результате ваших действий шрифт на экране стал полужирным, он таким и останется на вашей страничке. Правда, в этом втором случае вы можете так и не узнать, что шрифт становится полужирным благодаря тэгу <b> (а может быть, и <strong>!). Но всё равно приятно бывает иногда вот так, запросто пооформлять html-страничку, без всяких там тэгов и джава скриптов. А иногда, как в нашем последнем документе (договоре), такое непосредственное редактирование бывает даже удобнее, чем правка html-кода.

На ОС Windows давно существует, так сказать, «естественный» визуальный редактор html-страниц: почтовая программа Outlook Express (мы говорили о ней в Главе 8). Если вы не меняли её настройки (в частности, формат отправляемых сообщений), то при написании письма можете делать шрифт полужирным и курсивным, менять его размер и цвет и ещё кое-какие атрибуты текста. Всё это в результате записывается и отправляется получателю в виде html-кода. Но вы можете и никуда не отправлять написанное и оформленное «письмо», а сохранить его как файл в формате html (через меню «Файл» - «Сохранить как». А потом посмотреть код в файле. Впрочем это баловство. Нам ведь надо наоборот, html-файл как-то поместить в Outlook Express и там редактировать (а уже потом сохранить обратно в файл).

Это делается с помощью такого понятия, как «Документы на бланке». Выберите в меню OE «Создать» - «Документ на бланке» - «Выбор бланка», найдите в открывшемся окне нужный вам файл - и он появится в OE, доступный для непосредственного визуального редактирования. После внесения изменений выберите пункт меню «Сохранить как» и сохраните файл в формате html с нужным именем.

Редактировать (визуально) html-файл можно и прямо в окне Интернет Эксплорера - внутренний механизм Windows тот же самый, что и при редактировании в Outook Express, только этот механизм в IE по умолчанию не доступен, его надо запустить с помощью небольшого скрипта и служебного html-файла. Мы не будем в этой книге разбирать работу скрипта, разрешающего редактирование html-файла прямо в окне IE, потому что этот скрипт использует нестандартные возможности IE (таких возможностей нет в спецификациях W3C). Однако использовать скрипт вы можете и без объяснений: сохраните к себе на компьютер архив с папки CD omne\soft\menuExt\menuext.zip (soft/menuExt/menuext.zip), распакуйте его, найдите в папке install файл menuExt.inf, щёлкните по нему правой кнопкой мыши и выберите из контекстного меню пункт «Установить». Вместе с доступом к html-редактированию будет установлено ещё несколько надстроек для IE (все они описаны в файле readme.htm, находящемся в том же архиве). Удалить установленные надстройки можно через «Панель управления» компьютера - «Установка и удаление программ» - «IEMenuExt».

После установки IEMenuExt и перезапуска IE можно щёлкнуть по странице правой кнопкой мыши, выбрать из выпавшего меню пункт «Редактировать» и работать с текстом прямо как в текстовом редакторе, только не видя html-тэгов. После окончания редактирования надо через меню «Файл» (или комбинацией клавиш Ctrl+s) сохранить документ.

ie03.gif

Мы не разбираем здесь все возможности IEMenuExt, потому что работают они только в Интернет Эксплорере, и, по сравнению с некоторыми стандартными функциями браузеров Gecko (мы упоминали уже об Инспекторе DOM), выглядят как неуклюжие костыли. Даже и визуальное редактирование гораздо лучше реализовано в одном из последних свободно распространяемых браузеров Gecko - SeaMonkey. Дистрибутив этого браузера можно скачать из Интернета (наберите в строке поиска Яндекса слова «скачать SeaMonkey»); единственный его недостаток - объём: если дистрибутив Оперы занимает 4 Мб, Firefox'а - 5 Мб, то SeaMonkey - все 12 Мб. Зато там есть этот самый Composer (визуальный редактор) и встроенная почтовая программа.

Composer SeaMonkey, несомненно, гораздо более мощный инструмент редактирования html-страниц, чем IE, однако и на солнце бывают пятна: последний документ, над которым мы работали, выглядит в Composer'е очень бледно:

edit01.gif

В нём попросту невозможно непосредственно (как, собственно, мы мечтали) редактировать пункты ниже первого уровня вложенности - их не видно на экране. В IE же при переходе в режим редактирования раскрываются (как и в Outlook Express) все скрытые объекты:

edit02.gif

И мы можем создавать новые пункты, сохраняя структуру нашего документа, с помощью обычного копирования и последующей замены текста. Выделите последний пункт в договоре, затем через меню Edit (Правка) выберите пункт Copy (Копировать).

edit03.gif

Затем отмените выделение текста, нажмите в позиции конца последнего пункта Enter и через меню Правка - Вставить вставьте скопированный текст в новое место. Затем аккуратно удалите ненужный текст (аккуратно - значит, оставив первую букву этого текста - это необходимо для сохранения структуры форматирования):

edit04.gif

Теперь напечатайте новый текст:

edit05.gif

Затем удалите оставшуюся от старого текста букву, охранявшую форматирование (отделявшую элемент span от остального текста). Теперь можете даже выделить текст и с помощью комбинаций клавиш Ctrl+B сделать его полужирным; а для выделения курсивом нажать Ctrl+I (так же работают сочетания клавиш в Outlook Express, да и в Word'е). Теперь сохраните файл через меню Файл - Сохранить, закройте его и откройте снова в браузере - новая строчка добавлена! Причём, благодаря нашей «полуавтоматике» вам не нужно ставить очередной номер пункта; а если вы удалите какую-то строчку, остальные изменят нумерацию автоматически.

edit06.gif

Создание оглавления

Оглавление для большого документа создаётся и работает по принципу примечаний, описанному в Главе 10: в нужное место текста, перед заголовком, вставляется именованная закладка вида <a name="a02t">&#60;**</a>; в текст оглавления вписывается ссылка на эту закладку, атрибут href которой имеет вид путь_к_документу#имя_закладки (файл на CD omne\htm6\wattsa.htm).

Отличие оглавления от примечаний (и, в связи этим отличием, сложность работы) заключается в том, что всё оглавление целиком должно быть доступно одновременно с текстом основного документа, что может быть достигнуто только работой с двумя открытыми окнами браузера. Проще всего такую систему организовать с помощью фреймов.

ex31 Файлы примеров: htm7 (htm7)

В примере на сайте показан простейший вариант такой системы; основной файл pframe.html, содержащий фреймы-ссылки на содержательные страницы так мал, что его текст можно привести здесь целиком:

<title>pushkin-frame</title>
<frameset  cols="29%,*">
  <frame name="toc" src="../img/toc.html">
  <frame name="main" src="../img/p1.html" >
</frameset>

Во второй строке находится важный атрибут элемента frameset- cols: в нём задаётся относительная ширина левого фрейма в 29% от общей ширины окна, а правому фрейму отдаётся всё остальное пространство - *. Каждому фрейму с помощью атрибута src назначается документ для загрузки, а также имя, которое будет использоваться в ссылках: раз у нас в одном окне теперь несколько «субокон», браузер при щелчке по ссылке должен знать, в каком именно «субокне» открывать документ (или закладку). Текст оглавления (файл toc.html, который будет загружаться в левый фрейм под именем toc) также не очень велик:

<title>pushkin-toc</title>
<meta http-equiv="content-type" content="text/html; charset=windows-1251">
<style type="text/css">a {display:block; margin-top:.7em}</style>
<a href="p1.html#toc8" target="main">Стихи</a>
<a href="p1.html#toc9" target="main">МОЯ ЭПИТАФИЯ</a>
<a href="p1.html#toc22" target="main">ЭКСПРОМПТ НА АГАРЕВУ</a>
<a href="p1.html#toc38" target="main">НАДПИСЬ НА СТЕНЕ БОЛЬНИЦЫ</a>
<a href="p1.html#toc51" target="main">ЗАВЕЩАНИЕ К<ЮХЕЛЬБЕКЕРА></a>
<a href="p1.html#toc64" target="main">Проза</a>
<a href="p1.html#toc65" target="main">ПИКОВАЯ ДАМА</a>
<a href="p1.html#toc66" target="main">I.</a>

(Мы назначили элементу a правило display:block, чтобы не вкладывать его в элементы p). В файле p1.html (который будет загружаться в правый фрейм под именем main) рядом с соответствующими заголовками расставлены все необходимые метки (закладки), имеющие атрибуты href="toc8", "toc9" и т. д.

Всю эту нудную и кропотливую работу по расстановке меток-закладок и «собиранию» оглавления можно автоматизировать. Причём, не для какого-то конкретного документа, а раз и навсегда, чтоб больше уже об этом не думать.

Автоматическое оглавление для одного документа

Сначала всё-таки попробуем автоматизировать создание оглавления для конкретного документа p1.html.

ex32 Файлы примеров: dhtml6 (dhtml6)

Мы исходим из того, что анализируемый документ будет открываться не во фрейме, а в обычном окне браузера; поэтому и оглавление будем создавать не во фрейме, а просто в новом окне. В результате у нас будет открыто два свободно болтающихся на экране окна: основной документ, и оглавление; при щелчках по ссылкам в оглавлении текст документа в основном окне должен будет прокручиваться до нужной закладки (которую надо будет ещё туда вставить).

Предположим, нам удалось сгенерировать оглавление (набор ссылок на закладки в основном документе). Как браузер узнает, в каком окне надо будет прокручивать текст (наши документы ведь не во фреймах)? По такой же методике, как и для фреймов: в атрибуте target каждой ссылки мы должны будем указать имя окна основного документа. А какое это имя, где оно записано? Вот пока нигде не записано, его и нет, оно никакое. К счастью, его можно записать в скрипте с помощью обыкновенной формулы: window.name="main", после чего задать значение атрибута ссылок target равным этому имени, то есть тоже "main".

Общий алгоритм работы скрипта по созданию оглавления будет таков: 1) назначить текущему окну имя main; 2) открыть новое окно (window.open); 3) найти все заголовки в основном документе (элементы h1-h6); 4) вставить рядом с каждым найденным заголовком метку, записать в окно оглавления соответствующую метке ссылку.

2) (Первый пункт мы, можно сказать, уже выполнили, поэтому переходим сразу ко второму). Синтаксис команды, открывающей новое окно, таков: window.open(url, name, свойства), где url - путь к файлу, который будет загружен в новое окно (у нас файла нет), name - в нашем случае какое угодно имя, свойства состоят из целого набора определений. Тут не до конца ещё всё ясно, похоже, что W3C не определяет толком в своих спецификациях объект window, поэтому его свойства надо искать в описаниях работы конкретных браузеров (например, на стр. http://www.mozilla.org/docs/dom/domref/dom_window_ref76.html#1019331). По счастью, свойства, которые нам нужны, одинаковы в Gecko и в Интернет Эксплорере - это размеры окна, его положение на экране и некоторые мелкие детали типа полос прокрутки.

Ширина и высота нового окна так и назначается: width=400, height=600 (как слышится, так и пишется). Позицию мы установим на экране - крайнюю правую, для этого надо вычислить координату левого угла окна, она будет равна разнице между общей шириной экрана и шириной самого окна: screen.availWidth-400; status - отображать строку состояния внизу окна, resizable - позволять пользователи произвольно менять размеры, scrollbars - полосы прокрутки. Целиком функция, открывающая новое окно, будет выглядеть так:

var tocwin, toc, i=0;
function maketoc(){
 var left=screen.availWidth-400;
 var args = "width=400,height=600,left="+left+",top=20,scrollbars=yes,resizable=yes,status=yes";
 tocwin = window.open('',"toc",args);
 tocwin.focus();
 toc=tocwin.document.open();
 toc.write("<meta http-equiv='content-type' content='text/html; charset=windows-1251'>");
 toc.write("<style type='text/css'>a {display:block}</style>");
 toc.close();
 window.name="main";
 testlist(document.body);
}

Часть переменных (первая строка) мы инициализируем вне функции, чтобы их значения можно было передавать от одной функции к другой. После открытия окна с заданными параметрами мы передаём ему фокус - оно становится самым верхним среди всех окон на экране. Затем мы открываем в новом окне документ для записи, записываем в него некоторую служебную информацию (мета-тэг, стиль) и закрываем документ - на экране он, конечно, останется, но записывать туда новую информацию методом document.write() после «закрытия» будет нельзя. В конце мы вызываем новую функцию, которая и будет просматривать всё содержимое текущего документа и по определённым нами правилам создавать для него оглавление:

function testlist(elem){
 var elist=elem.childNodes, al, text, j, id;
 for (var el in elist) {
 i++;
 if (elist[el].tagName=="H1" || elist[el].tagName=="H2" || elist[el].tagName=="H3" || elist[el].tagName=="H4" || elist[el].tagName=="H5" || elist[el].tagName=="H6") {
  j=elist[el].tagName.substr(1,1);
  al = document.createElement("A");
  id = "toc"+i.toString();
  al.Name=id;
  al.id=id;
  text=tocwin.document.createTextNode(elist[el].firstChild.nodeValue);
  elist[el].insertBefore(al,elist[el].firstChild);
  al = tocwin.document.createElement("A");
  al.href=tocwin.opener.location+"#"+id;
  al.target="main";
  al.style.marginLeft=j+"em";
  al.style.marginTop=(j>3)?".5em":"1em";
  al.appendChild(text);
  tocwin.document.body.appendChild(al);
  }
  else {
   if (elist[el].nodeType==1) {
    testlist(elist[el]);}
   }
 }
}

В качестве параметра elem предыдущая функция передаёт новой элемент body основного документа. Общий алгоритм работы функции таков: она выбирает всех потомков элемента, переданного в качестве параметра (в начале - body), проверяет, не является ли данный потомок заголовком (<h1> - <h6>); если является, производит манипуляции с оглавлением, иначе проверяет, является ли данный потомок элементом, могущим иметь своих потомков (вдруг в body, как у нас, вложен элемент div), и если является, вызывает для этого элемента ту же самую функцию testlist(elem) - и так, пока не будут просмотрены все вложенные друг в друга элементы в документе. Рекурсия такая (функция вызывает сама себя).

Для создания новых элементов мы используем метод document.createElement() (а также document.createTextNode() для создания текста новых элементов), для вставки вновь созданных элементов в документ - два разных метода: insertBefore (чтобы вставить закладку впереди заголовка в основном документе) и appendChild (чтобы вставить очередной пункт оглавления в конец всех существующих пунктов в новом окне).

Ссылкам в оглавлении мы назначаем отступ от левого края в зависимости от уровня заголовка: чем ниже уровень, тем больше число (максимальное - в заголовке h6), и это число мы делаем количеством единиц отступа «em». Отступ от верхнего края назначаем проще: если заголовок уровня 1-3, отступ 1em, если другого уровня - 0.5em.

Самая сложная формула получается для атрибута href ссылок: tocwin.opener.location+"#"+id. Здесь opener - окно, которое открыло данное новое окно; location - путь к файлу, открытому в окне (в данном случае - в старом окне); id состоит у нас из слова toc и некоторого числа, получаемого обычным приращением переменной i в цикле.

Вот, пожалуй, и все хитрости. Запускаем скрипт щелчком по ссылке «Создать оглавление» - открывается новое окно в правом верхнем углу экрана и в него записываются ссылки на закладки, расставляемые перед каждым заголовком в основном окне.

Остаётся мелочь: сделать так, чтобы этот скрипт мог запускаться не только в нашем «специальном» документе, но вообще в любом документе HTML. Это возможно.

Автоматическое оглавление для всех

Запускать свой собственный скрипт на произвольной странице можно с помощью меню обозревателей «Избранное» (в Gecko - «Закладки», «Bookmarks»). В Избранном находятся обыкновенные файлы url (или записи в html-документе, имеющие вид файла url). Вот типичный пример содержимого такого файла:

[InternetShortcut]
URL=http://www.large.ru/bookmarklets/

Хитрость, которую придумали люди (сейчас уже трудно установить, кто именно был первым, я сам получил информацию с сайта www.large.ru), заключается в том, чтобы после знака равенства написать вместо пути к файлу код JavaScript:

[InternetShortcut]
URL=javascript:alert("Hi!");

ex33 Файлы примеров: dhtml7 (dhtml7)

После того как вы создали файл url, его можно обычным перетаскиванием с помощью мыши поместить в меню IE Избранное (Favorits): нажать мышкой на имя файла, тащить в IE в меню «Избранное», держать мышку, не отпуская, пока не раскроется пункт меню, затем подтащить мышь куда-нибудь между другими ссылками и отпустить там. Так же можно поместить нужные url-файлы и в меню браузеров Gecko «Закладки» («Bookmarks»).

Если вы установили надстройку IEMenuExt, описанную в этой главе в разделе «Естественный» WYSIWYG редактор HTML, то в вашем меню IE «Избранное» уже находится несколько таких мелких закладок-скриптов (называемых в просторечии «закладурками»). Можно, казалось бы, записать наш скрипт для оглавления в файл url и поместить в «Избранное» очередную заклад(ур)ку. Существуют, однако, два ограничения: скрипт должен быть записан одной строкой (без переводов строк внутри файла) и иметь общую длину не более 512 символов. Первое условие (удалить в скрипте все переводы строк) выполнить несложно, а второе для нашей задачи невыполнимо вообще.

Однако это не означает невыполнимости самой задачи. Придётся немного изменить архитектуру решения: маленький скрипт будет создавать в открытом документе (любом!) ссылку (с текстом «Создать оглавление») для запуска большого скрипта. При этом большой скрипт должен будет находиться в заранее условленном месте вашего компьютера, в примере мы сделали этим местом папку C:\www (предполагая, что вы уже создали её при работе с предыдущими главами книги). Таким образом, текст «малого скрипта» в составе url-файла toc.url будет выглядеть примерно так:

[InternetShortcut]
URL=javascript:function $(w){with (w.document) {var b=body, text=createTextNode("Создать 
оглавление"), a=createElement("A"), s=createElement("SCRIPT")}; a.href="javascript:maketoc()"; 
a.appendChild(text); s.type="text/javascript"; s.src="../img/file:///C:/www/toc.js"; 
b.insertBefore(a,b.firstChild); b.insertBefore(s,b.firstChild);} $(this);

Никаких переводов строк (кроме перевода после «[InternetShortcut]») в файле быть не должно. Если вы поместите этот файл в «Избранное» IE, а затем выберете вновь появившуюся закладку «toc» в том же меню, в активном окне (в самом верху текста документа) появится надпись-ссылка «Создать оглавление». Если вы уже скопировали файл toc.js (из папки CD omne\dhml7) в нужное место - C:\www, то можете щёлкать по вновь созданной ссылке - и оглавление появится в новом окне (если в основном документе есть хотя бы один заголовок).

Запустить скрипт через «Закладки» в Опере можно даже и не пытаться. В браузерах Firefox и SeaMonkey система работает, но с некоторыми ограничениями:

  1. Лучше файл url сохранять в формате UNICODE (точнее, utf-8): открыть его в Блокноте (или редакторе Bred), выбрать в меню «Файл» пункт «Сохранить как», выбрать формат (или кодировку) utf-8 и сохранить под другим именем (в наших примерах сохранено под именем tocu.url);
  2. Найстройки безопасности браузеров Gecko не позволяют создавать оглавление для страниц, открытых прямо с сервера в Интернете (а не с локального диска). Вообще-то это логично: браузер оберегает нас от попыток любой интернет-страницы запустить какие-то программы на нашем компьютере. Правда, браузер почему-то не понимает, что мы сами же и вписали (с его помощью) в экземпляр страницы, открытый на нашем компьютере «подозрительный» код - ссылку для запуска скрипта C:\www\toc.js.

С учётом описанных ограничений можно сказать, что система создания оглавления надёжно работает в браузерах Gecko с локальными (сохранёнными на ваш компьютер) интернет-страницами.

ex34 Файлы примеров: dhtml7 (dhtml7)

Реклама: Реальные кабаны, фильмы новинки 2010 - больше чем любовь.