Сайт следит за вами: JavaScript
Очень часто на динамических сайтах нам не хватает динамики.
На сайте все может быть хорошо: и дизайн, и удобная обработка данных, и внятный интерфейс. Но — чем больше имеем, тем больше хочется.
Например, хочется не просто водить мышкой по странице, а чтобы страница реагировала на движение. В каком-то месте что-то сообщала. В каком-то загоралось предупреждение. А в каком-то простое наведение мышки инициирует сложный сценарий.
Хочется, чтобы поиск происходил не с загрузкой страницы не каждый раз, а по мере того, как слова набираются в окне запроса. Чтобы можно было уточнить запрос, и результат был бы тут же показан на экране.
Хочется, чтобы при какой-либо пользовательской ошибке страница заботливо бы предупреждала об этом и ставила бы курсор в то место страницы, где надлежит исправить ошибку.
А может, удастся реализовать стандартные характеристики интерфейсов операционных систем, когда объекты можно перетаскивать по рабочему пространству мышкой?
Наконец, не кажется ли вам, что перезагрузка страницы, нужная всего лишь для того, чтобы отправить письмо разработчику, — это уже каменный век, и после щелчка по кнопке «Отправить» посетитель должен оставаться на той же странице, где и был, просто ему должно
Сайт следит за вами: JavaScript |
|
Выдаваться сообщение, что письмо на самом деле отправлено? И перезагрузка страницы по времени для обновления строк чата — это тоже не очень удобно. Кроме того, хочется свежих веяний. Кто сказал, что переместиться на следующую страницу можно, только щелкнув по ссылке «Далее»? А не логичнее ли просто перетащить страницу влево, чтобы увидеть то, что справа? И почему, кстати, вообще сайт должен располагаться на разных страницах, если на одну страницу можно динамически подгружать разную информацию. Плавные открытия и скрытия блоков, самопроизвольные перемещения объектов по странице, возникновение из ничего продолжения рассказа, когда вы дочитываете страницу, сбор статистики и голосование только на основе ваших движений мышью, сообщение об орфографической ошибке двумя действиями — это уже не будущее, а настоящее. И это не технология Flash, при своих неоспоримых достоинствах имеющая ряд ограничений. Все перечисленное едва ли можно было реализовать, не будь в распоряжении разработчиков языков активных сценариев. Активные сценарии — терминология, принятая компанией Microsoft. Дело в том, что есть два известных языка активных сценариев, выполняющих сходные или даже идентичные задачи: JavaScript и VBScript. Однако второй из них поддерживается исключительно браузером Internet Explorer, тогда как второй является кроссбраузерным (для современных браузеров) и кроссплатформенным. Это значит, что JavaScript можно использовать в большинстве браузеров, тогда как сфера применения VBScript существенно уже. Когда Internet Explorer занимал лидирующее положение на рынке браузеров, использовать VBScript имело смысл; сейчас же все большую популярность приобретают альтернативные браузеры, где из активных языков есть только поддержка JavaScript. Несмотря на богатую функциональность, JavaScript не считается языком программирования — в первую очередь потому, что он не позволяет писать отдельные программы, а способен только встраиваться в виде сценариев и фрагментов. В качестве серверного языка он используется редко: иногда в качестве языка сценариев в составе технологии ASP (уступая пальму первенства языку VBScript). С другой стороны, среди остальных языков активных сценариев он признанный лидер как представитель клиентских технологий. Основные его возможности можно разделить на несколько групп: 1. Взаимодействие со структурой документа. В полной мере (с некоторыми оговорками) такая возможность реализована в браузерах Internet Explorer версий 5 и позднейших, Firefox, Netscape с версии 6, Opera с версии 7, в Safari и других современных браузерах. |
JS |
4 |
Программирование |
Речь идет в первую очередь о работе с DOM — объектной моделью документа, когда с помощью активных сценариев можно не только изменять текстовое и иное содержимое отдельных элементов, но также добавлять и удалять сами объекты. При этом объекты могут быть не только элементами веб-страниц, но и «абстрактными» объектами. Кроме того, с помощью DOM и языка JavaScript можно обращаться к свойствам объектов — считывать (проверять) и изменять их. В функциональных возможностях языка в версиях браузеров, чья популярность предшествовала периоду поддержки DOM, было хорошо реализовано обращение к формам и их компонентам, а также динамическое изменение содержимого некоторых тэгов. Это, пожалуй, самая важная возможность языка. 2. Дизайнерские функции, или реализация визуальных эффектов. Нет сомнения, что плавное появление объекта на веб-странице выглядит красивее и лучше замечается, чем обычное. Движение, перемещение объектов по веб-странице, их интерактивную прозрачность, скрытие и появление, изменение формы можно реализовать с помощью JavaScript. По большей части реализация визуальных эффектов является грамотным взаимодействием со структурой документа при помощи объектной модели документа. 3. Реакция на действия посетителя страницы и иные события. Любое движение мышью, нажатие и отпускание кнопки мыши или клавиши на клавиатуре, изменение размеров окна, загрузка и уход со страницы могут быть отслежены с помощью сценариев на JavaScript. К событию можно «привязать» функцию, вызов какого-либо другого действия. 4. Работа с браузером. С помощью JavaScript можно работать не только с событиями, происходящими в пределах окна браузера, но и с самим браузером: например, открывать новые окна, составляя «на лету» набор панелей, которые будут показаны в новом окне браузера; доставлять посетителю диалоговые окна и окна сообщений; влиять на некоторые компоненты окна браузера. Поскольку определенная часть таких эффектов работает только в Internet Explorer, а в книге делается упор на кроссбраузерный подход, то рассмотрены будут только те сценарии, которые будут хорошо работать в большинстве современных популярных браузеров. 5. Взаимодействие с сервером. Такая возможность появилась далеко не с первой версии языка и связана с технологией AJAX. Основы этой технологии рассмотрены в другой части книги. Сценарии на языке JavaScript могут занимать длинные файлы (в этом случае говорят о целых библиотеках), а могут состоять и из одной строчки — все зависит от конкретной задачи. |
|
326 |
Сайт следит за вами: JavaScript |
|
Существует три способа включения активных сценариев на языке JavaScript на веб-страницах. Во-первых, это способ отдельных файлов. Создается текстовый файл, ему присваивается произвольное имя (допустим, scriptl) и расширение. js (а не. txt или какое-то иное, потому что именно с этим расширением файлы сценариев можно связывать с веб-страницами). А в нужном месте кода веб-страницы включение происходит следующей директивой: <script language="JavaScript" src="script1.js"> </script> Если наступят времена, когда браузеры будут поддерживать язык HTML версии 5 в его XHTML-разновидности, то такие директивы будут звучать лаконичнее: <script src="script1.js"/> Однако сейчас такая форма записи пока не работает. Точнее, работает в отдельных браузерах, но некорректно. Например, в Opera 9 такая конструкция вызывает многочисленные ошибки отображения остального содержимого страницы, а в Firefox вызывает задержку появления на веб-странице содержимого, которое следует после такого вызова сценария. В Internet Explorer такой вызов игнорируется и не позволяет выводить на экран содержимое страницы, которое следовало в коде после вызова. Во-вторых, работает метод прямой записи сценария в коде вебстраницы. В этом случае код нужно оформить тэгами <script> ... </script>: <script language="JavaScript"> // Текст сценария // Двойным слэшем в начале строки оформляются // однострочные комментарии </script> Не допускается совмещенная запись, когда в открывающем тэге сценария, размещенного в коде страницы, указывается какой-либо внешний файл. Пожалейте браузер: он не в состоянии решить, что ему выполнять. Наконец, третий способ включения сценариев не требует тэга <script> вообще. Этот способ связан только с обработкой событий. В нужный тэг включается обработчик, в качестве значения (содержимого) которого выступает сценарий. Приведем простой пример. Допустим, |
Во избежание торопливых действий со стороны посетителя страницы на время загрузки страницы наверху страницы располагается предупреждение: «Идет загрузка». После загрузки страницы это предупреждение убирается. Сначала мы должны написать само предупреждение:
<div id="preload а1е^">Идет 3arpy3Ka</div>
Чтобы предупреждение выглядело заметно, с помощью CSS поместим его в верхний левый угол страницы с небольшими отступами поверх остального содержимого и раскрасим фон в красный цвет:
<style>
#preload alert { background-color:#CC0000; color:white; font-weight:bold; padding:5px; position:absolute; left:30px; top:30px; z-Index:100; width:17 5px; text-align:center;
}
</style>
Наконец, чтобы убрать этот блок со страницы, по окончании загрузки документа в браузер, в тэге <body> пишем небольшой сценарий:
<body onLoad="document. getElementById('preload alert'). style. display='none'">
Это, пожалуй, все. Разберем сценарий подробнее. Обработчик события load (загрузка) называется onLoad — он помещается в тэг в виде параметра. Значением этого параметра является сценарий. В данном случае сценарий присваивает блоку «preload_alert» через CSS такое значение свойства display, при котором блок становится невидимым и не занимает места. Обращение к свойству идет поступенчато, сверху вниз. Сначала сценарий обращается к документу; затем — к определенному блоку (нужному нам) внутри этого документа, но обращается посредством нахождения в документе этого элемента по его идентификатору id (document. getElementById('идентификатор элемента') — работает во всех современных браузерах, не работало в Internet Explorer и Netscape четвертых версий). Обратившись к эле-
Сайт следит за вами: JavaScript |
|
Менту документа, сценарий читает его стили (style), после чего обращается к свойству display стиля элемента документа («Вот дом, который построил Джек...»). Наконец, обратившись к свойству, сценарий присваивает (привычный знак равенства, как и в PHP, является оператором присваивания, а в качестве знака равенства выступает двойной знак равенства «==») ему значение «none» — оно обязательно должно быть заключено в кавычки. Обратите внимание на одну особенность. В большинстве браузеров событие загрузки инициализируется после действительной загрузки всех элементов документа и всего содержимого этих элементов. Но в браузере Safari это событие инициализируется чуть раньше, поэтому блок с предупреждением исчезнет с экрана еще до фактического окончания загрузки страницы. (Это позволяет разработчикам говорить о Safari как о самом быстром браузере.) Как видим, с обращениями к элементам все достаточно просто. Обращение идет иерархически: от старшего элемента к младшему, пока сценарий не достигает максимальной конкретизации. В отличие от PHP, точка является не знаком конкатенации строк (знак конкатенации — обычный плюс), а средством объединения элементов и их свойств и методов в иерархическую цепочку. Со свойствами мы уже познакомились, однако в качестве свойств могут выступать не только стили CSS, но и параметры тэгов. Например, чтобы изменить изображение наведением на нее мыши, нужно с помощью сценария изменить содержимое параметра src тэга <img>, используя обработчики событий наведение (mouseover) и уведения (mouseout) мыши с изображения: <img src="1.jpg" alt="" onMouseOver="this. src='2.jpg'" onMouseOut="this. src='1.jpg'"> Изначально должны быть подготовлены два изображения: 1.jpg и 2.jpg. В качестве изначального изображения в документе загружается первое. Поскольку обработчики события вставлены в тэг, с которым эти события и происходят, можно использовать слово-указатель this [англ. «это(т)»] — он указывает на текущий элемент страницы. Если бы событие происходило не при наведении на само изображение, то пришлось бы использовать доступ по идентификатору. Традиционно в тэге изображения использовался не идентификатор id, а параметр name — «имя». Поэтому нужно было написать тэг: <img name="picture1" src="1.jpg" alt=""> И обращаться к нему так (допустим, изменение изображения происходит при щелчке на кнопке): |
<button
OnClick="document. picture. src='2.jpg'">
Нажмите<button>
Поскольку при загрузке документа автоматически создается несколько массивов (пронумерованных наборов данных), то равноценной этой записи будет следующая:
<button onClick="document. images['picture']. src='2.jpg'">Нажмите<button>
И даже эта:
<button onClick="document. images. picture. src='2.jpg'">Нажмите<button>
Обратите внимание на употребление кавычек. Вложенные кавычки должны отличаться от кавычек первого уровня: например, первые двойные, внутренние одиночные. Если потребуется внутри употребить еще кавычки, то нужно предварять их обратными слэшами.
Кстати, если обработчик события щелчка заключается в ссылку, то нужно принять дополнительные меры, чтобы вместо инициализации сценария не произошел переход по ссылке. Например:
<a href="" onClick="document. images. picture. src='2.jpg'; return false">Нажмите</a>
Видно, что появились слова «return false» после точки с запятой в сценарии, обрабатываемом событием. Они предотвращают переход по ссылке, возвращая (return) действию ссылки ложное (false) значение, тогда как сценарий выполняется нормально.
Кроме свойств существуют еще и методы.
Метод — это та же функция, только зарезервированная языком. Например, при показе динамически появляющейся на странице поисковой формы (вы уже можете это сделать) логично было бы сделать форму еще более услужливой и в строку запроса уже поставить мигающий курсор, чтобы посетителю осталось только набрать с клавиатуры поисковый запрос и нажать клавишу «Enter» («Return»). Допустим, у нас есть форма, имя (name) которой мы дали «myform», а внутри нее поле для ввода поискового запроса, которая называется «search_item». Кроме того, что это название поля передаст в принимающий сценарий содержимое поискового запроса в переменную $search_item, оно выполнит еще одно полезное действие. После вызова самой формы мы напишем в сценарии:
Сайт следит за вами: JavaScript |
|
<script> // Предыдущий фрагмент сценария document. myform. search item. focus() </script> Метод focus() поставит курсор в указанное сценарием поле. Поскольку формы (даже если форма на странице только одна) при загрузке страницы также создают массив, то данный сценарий мог бы быть записан и так: <script> // Предыдущий фрагмент сценария document. forms['myform'].search item. focus() </script> Такая форма записи бывает удобной, когда обращение к разным формам производится в цикле. Обратите внимание: в конце строк в сценариях JavaScript можно ставить точку с запятой (как в PHP), а можно и не ставить, если это не препятствует корректному выполнению сценария. А препятствовать это может лишь тогда, когда сценарий из нескольких команд записан в одну строку. Такие сценарии часто помещаются в тэги при обработке событий. В качестве примера можно привести такой: в строке запроса поисковой формы светло-серыми буквами написаны слова «Поиск по базе»; нужно, чтобы при щелчке по строке эти слова убирались, а при наборе других слов они уже были черного цвета, но при потере фокуса даже эти слова становились бы светло-серыми. <form method="post" action=""> <input type="text" name="fld good" value=" Поиск по базе" style="color:#DDDDDD" onFocus="this. style. color='black'; if(this. value==' Поиск по базе') {this. value='';}" onBlur="this. style. color='#DDDDDD'; if(this. value==false) {this. value=' Поиск по базе';}"> <input type="submit" value="Найти"> </form> Переведем на русский язык. По событию приобретения строкой запроса фокуса (onFocus) CSS-параметр цвет данного (this) элемента становится черным, после чего идет проверка: если значение (value) текстового поля равно « Поиск по базе» (именно так, с пробелом в начале), то это значение изменяется на пустую строку ( '' ). По событию потери фокуса (onBlur) текст снова становится серым, а значе- |
Ние текстового поля, если оно пустое, становится таким: « Поиск по базе». Если же строка не пустая, а в нее введен поисковый запрос, то условие не выполняется, и замены текста не происходит. Разные команды разделяются точкой с запятой, что и требовалось доказать.
Работа с формами очень часто возлагается как раз на JavaScript. Дело в том, что часто посетители веб-страниц, заполняющие какие - либо формы, забывают заполнить некоторые поля. Проверить, пустое ли поле, серверным сценарием очень просто ^^@$переменная_ из_имени_поля==false) ), но зачем заставлять посетителя ждать, если проверить можно сразу, не загружая странице-обработчик?
Допустим, у нас есть поле для отправки письма (возможность отправки письма без использования почтовой программы средствами PHP описывается в этой книге). Его код может быть таким:
<form name="letter" method="post" action="/mail/" onSubmit="return checkFeedback()">
<р>Ваш e-mail:
<br><input type="text" name="youremail" value="" style="width:300px"></p>
<р>Тема письма:
<br><input type="text" name="yoursubj" style="width:300px" value=""></p>
<р>Текст письма:
<br><textarea name="yourletter" rows="8" cols="25" style="width:300px">
</textarea></p>
<p><input type="submit" value="OTnpabMTb"></p>
</form>
Обратите внимание на имена формы и всех трех обязательных полей, которые должен заполнить посетитель (отправитель письма). Кроме того, в открывающем тэге формы есть такой фрагмент: onSubmit="return checkFeedback()". Он сообщает о том, что по событию отправки (например, нажатию кнопки «Отправить») возвращается результат выполнения функции checkFeedback() — я написал ее, чтобы она проверяла, все ли поля заполнены. Напишем чуть выше такой сценарий, состоящий из функции checkFeedback() :
<script language="JavaScript">
Function checkFeedback()
Сайт следит за вами: JavaScript |
|
{ If(document. letter. youremail. value==false) { А1егМ"Напишите адрес вашей электронной почты, пожалуйста!"); Document. letter. youremail. focus(); return false; } Else if(document. letter. yoursubj. value==false) { If(confirm("Bbi не создали тему сообщения! Оставить без темы?")) { Document. letter. yoursubj. value="Без темы (с сайта)"; } Else { Document. letter. yoursubj. focus(); } Return false; } Else if(document. letter. yourletter. value==false) { А1егМ"Будьте так добры, напишите хотя бы пару строк, не отправляйте пустым!"); Document. letter. yourletter. focus(); return false; } } </script> Сначала проверяется поле для ввода электронного адреса. Если оно пустое или его значение составляют пробельные символы (if(document. letter. youremail. value==false) ), то посетителю выдается предупреждение (а1егМ"Текст предупреждения")), в поле ставится курсор (document. letter. youremail. focus()), а отправка отменяется (return false). То же самое происходит и с двумя остальными полями (по очереди), только проверка поля для ввода темы снабжена дополнительной функциональностью: если поле пустое, то посетителю выдается не просто предупреждение (alert()), а диалоговое окно соглашения (confirm()) с кнопками «Да» и «Нет». Если |
Посетитель соглашается оставить письмо без темы, то в поле для ввода темы помещаются слова «Без темы (с сайта)», если не соглашается (else), то в поле ввода темы просто ставится курсор.
Таким образом, если пользователь не отключил действие активных сценариев, то ему не удастся отправить письмо без обратного адреса, без темы и без текста.
Обращение к элементам не всегда производится через идентификационную запись или имя. Достаточно просто самому создать массив из элементов определенного типа и обращаться к ним по очереди. В этом случае обращение производится по имени тэга, но посредством выбора элементов из массива. Массив создается функцией getElementsByTagName() , в качестве аргумента в которую передается имя тэга. Например, иногда возникает необходимость обратиться ко всему содержимому элемента <body>, то есть считать все содержимое страницы, чтобы обработать его сценарием. Применяются два вида записи, первая из которых полная:
Body elem = document. getElementsByTagName("body")
Body content = body elem[0].innerHTML
Второй вид — более краткий:
Body content = document. getElementsByTagName("body") [0].innerHTML
Различия важны. В первом случае сначала создается переменная body_elem, значением которой становится массив всех элементов с именем тэга <body> — то, что элемент всего один (и к тому же по программистской традиции носит номер «0»), сейчас несущественно, поскольку такой метод может быть применен к любой коллекции элементов. И только после этого создается переменная body_content, значением которого является содержимое (innerHTML) нулевого (по-русски — первого) элемента массива body_elem. Во втором случае промежуточной переменной не создается, а поскольку запись document. getElement sByTagName ( "body" ) инициализирует массив элементов <body>, то к ней сразу можно обращаться, выбирая ее элементы по номерам. Первый вариант (с разделением кода на фрагменты) может пригодиться, когда с массивом элементов нужно сделать еще что-то впоследствии. Если же преследуется только одна задача, то логичнее написать сценарий в сокращенной форме. В данном случае они оба работоспособны и в конечном итоге записывают в переменную body_content содержимое тэга <body>. (Правда, с этим тэгом связана одна особенность. Все современные браузеры для настольных компьютеров и ноутбуков более или менее лояльно относятся к ошибкам верстальщика в разметке страницы.
Сайт следит за вами: JavaScript |
|
Иногда они проявляют чрезмерное усердие и оказывают медвежьи услуги. Например, в Internet Explorer, даже если расположить вышеприведенный сценарий после закрывающего </body>, браузер почитает, что кодер ошибся, и включит в содержимое переменной body content и сам сценарий, что, конечно, никому не нужно.) С помощью инструкции innerHTML можно, разумеется, не только считывать содержимое элементов, но и изменять его: <H1>Hello</H1> <button onClick="document. getElementsByTagName ('h1')[0].innerHTML='Привет'"> Перевести </button> Неважно, в каком регистре написан тэг <h1> — таким методом можно обратиться к его содержимому и присвоить новое. При нажатии (onClick) на кнопку (<button>) в данном сценарии происходит подобная замена содержимого. Такая методика (с использованием innerHTML) очень часто используется для динамического изменения содержимого целых текстовых блоков, абзацев и фрагментов текста. Часто требуется создавать динамически меняющиеся ссылки. Если ссылка звучит как «Показать настройки», а при щелчке по ней показывается блок настроек, то ссылка должна быть заменена на «Убрать настройки», потому что они уже показаны. После скрытия настроек ссылка должна приобрести первоначальный вид. <a href="" onClick="return false"><span onClick="this. innerHTML=(this. innerHTML=='noKa3aTb настройки') ? 'Убрать настройки' : 'Показать настройки'">Показать настройки<^рап></а> Разберем конструкцию подробнее, поскольку она включает проверку условия, сокращенную форму условного ветвления и замену содержимого. Для простоты я убрал из ссылки обращение к функции, поскольку сейчас это не играет существенной роли. Кроме ссылки, слова «Показать настройки» заключены в тэг <span>...</span> — именно содержимое этого блока будет меняться (это обеспечит корректную работу во всех браузерах, поддерживающих JavaScript). Сокращенная запись условного ветвления имеет такой формат: Переменная или свойство объекта объект = (условие) ? "результат, если условие истинно" : "результат, если условие ложно" Или, чтобы выразить это абстрактно, можно записать так: |
Abc = (bcd == 3) ? "result 1” : "result 2”
Если же использовать полную форму условного ветвления, то же самое может быть записано так:
If(bcd == 3)
{
Abc = "result 1”
}
Else
{
Abc = "result 2"
}
Первая форма явно компактнее, но она не позволяет использовать множественное ветвление и оператор else if (аналогичный elseif в PHP и elif в SSI). Результат в данном случае один и тот же: если переменная bcd (ее обязательно нужно инициализировать ранее, чтобы не возникло ошибки) равна трем, переменная abc будет содержать строку «result 1», если же не равна, — строку «result 2».
В данном случае результатом проверки условия будет присвоение значения не переменной, а свойству innerHTML (внутренний HTML) кодового слова this (оно обозначает текущий <span>). Условием является проверка на соответствие this. innerHTML строке «Показать настройки» (соответствие, или равенство, обозначается знаком ==). Если соответствие правильно, в качестве содержимому <span>^ назначается строка «Убрать настройки», в противном случае возвращается на место строка «Показать настройки». Заменять таким образом можно содержимое любого блока, содержащего текст, например, обращаясь к нему по идентификатору. В качестве примера можно привести такую ситуацию: существует блок для подсказок. При наведении на ссылки с непонятными словами в этот блок записывается содержимое подсказки, хранящееся в переменной, элементе массива или где-то еще. При отведении курсора мышки в блок записывается пустая строка, чтобы подсказка не оставалась:
<div id="info"></div>
<a href="ccbmKa" onMouseOver="document. getElementById('info').innerHTML='TeKCT подсказки, соответствующий тематике ссылки'" onMouseOut^'document. getElementByld^info'). innerHTML=' '">
Естественно, при большом количестве повторений лучше увести часть кода в функцию.
Сайт следит за вами: JavaScript |
|
Функция определяется так же, как и в PHP: после кодового слова function приводится название функции, при необходимости в скобках приводятся аргументы (параметры, передаваемые в функцию). После этого в фигурных скобках описывается функция: Function infotext(text) { Document. getElementById("info").innerHTML = text } В этом случае приведенный выше пример со ссылкой может быть записан значительно лаконичнее: <a href="ccbmKa" onMouseOver="infotext('TeKCT подсказки, соответствующий тематике ссылки')" onMouse Out="infotext(,,)"> Если таких ссылок хотя бы три или пять, код значительно уменьшается в объеме, да и работать с ним в дальнейшем становится гораздо проще. Обратите внимание, что переменные в JavaScript не предваряются знаком доллара, как в PHP, но при инициализации переменной можно предварить имя переменной кодовым словом var: Var abc = ""; Но это необязательно, как и кавычки в концах строк. Достаточно полезной бывает функция открытия и скрытия определенных блоков (с текстом, изображением и другим содержимым, это не особенно важно). Построить ее можно так же лаконично: Function opCl(elem id) { Document. getElementById(elem id).style. display = (document. getElementById(elem id).style. display=="block") ? "none" : "block"; } Теперь для того, чтобы показать на странице блок (или абзац, или колонку таблицы, или что-то другое), достаточно вызвать эту функцию посредством ссылки: <a href="" опС^ск="орС1('идентификатор открываемого элемента'); return false"> Текст ссылки </a> |
Хорошим правилом является оставлять элементам ту функциональность, на которую они рассчитаны. Например, ссылка является средством перехода на другую страницу, и использовать ее для активизации сценария, по логике вещей, нежелательно. Дело в том, что при щелчке по таким ссылкам не происходит никакого перехода, хотя в статусной строке или всплывающей подсказке появляется адрес. Компромиссным вариантом может быть создание специального стиля для ссылок, отвечающих только за активизацию сценария. Идеологии HTML это противоречит, но внешние отличия бросятся в глаза. Оптимальным вариантом является использование фрагмента <span> с назначенным классом, описанным в стилевой таблице. Как дополнительный плюс — не требуется усложнения «ссылки» словами «return false»:
<span class="activator"
ОпС1іск="орС1('идентификатор открываемого
Элемента')">Текст «ссылки»<^рап>
Сам же класс для таких «ссылок» следует описать так, чтобы он максимально походил на обычную ссылку (то есть вызывал рефлекторное желание нажать), но имел отличия. Например, сейчас принято делать прерывистое подчеркивание при сохранении остальных атрибутов ссылок:
.activator { color:blue;
Border-bottom:1px dashed blue; cursor:pointer;
}
Наконец, желательно снабжать такие псевдоссылки всплывающими подписями (title=""), чтобы посетитель, подведя мышь к подчеркнутому тексту и увидев характерный «ссылочный» курсор в виде перста указующего, не впал в панику, не обнаружив адреса ссылки.
Определенным минусом такого подхода является то, что пользователь, отключив JavaScript в браузере (таких пользователей, по некоторым данным, около 10%), не сможет воспользоваться псевдоссылками. С одной стороны, он сам же и ограничивает себя в просмотре сайта, и, отключив JavaScript, не сможет воспользоваться в принципе никакими эффектами и удобствами, которые реализованы на сайте с помощью активных сценариев; с другой же — не хочется сужать его возможности. Например, он не может воспользоваться формой для входа на сайт (после заполнения полей логина и пароля), потому что она, предположим, выезжает из-за границы документа — а это, скорее всего, реализовано именно на JavaScript — но можно предоставить ему доступ к странице
Сайт следит за вами: JavaScript |
|
Login. php, на которой те же поля доступны без всяких сценариев. Тут как раз пригодится компромиссный вариант, но несколько модернизированный: <a href="login. php" class="pseudolink" onClick="opCl('login form'); return false" ^^е="Форма для ввода логина и пароля"> Войти на сайт</а> Здесь собрано все вместе: и ссылка, и сценарий, открывающий форму с id="login form" и свойством style="display:block", и указание класса, модифицирующего вид ссылки, и всплывающее пояснение. При включенных активных сценариях форма будет открываться на данной странице (при условии, что она существует) по щелчку на этой ссылке, а при отключенном JavaScript не будут работать не только сценарии, но и инструкция return false, которая запрещает переход по ссылке, а значит, загрузится страница для тех пользователей, что отключают сценарии. Наконец-то все довольны. Преимущество JavaScript, как видим, в легкости встраивания в страницу. Недостаток — в возможности отключения. Если бы разработчики не позаботились о возможности управления браузером с помощью активных сценариев, не было бы необходимости отключать сценарии. Например, простая функция alert() позволяет активировать окошко предупреждения. Оно не является элементом веб-страницы, и браузер нельзя закрыть, пока не будет нажата кнопка «ОК» на этом окошке. Этим пользуются для создания простейших взломов, например, гостевых книг, где любой посетитель сайта может оставить свое сообщение. Если веб-мастер не позаботился о предварительной обработке сообщений перед их помещением на сервер, то в сообщении можно оставить вредоносный код. Например, такой: <script language="JavaScript"> var i = 1 while(i==1) { Alert("y веб-мастера кривые руки") } </script> Суть сценария простая. Сначала инициализируется переменная i, которой присваивается значение «1». Затем начинается цикл while, который, как известно, повторяется, пока условие, заключенное в скобках, истинно. Поскольку никакой другой сценарий не поменяет значение переменной (во время выполнения этого кода не будут выполняться другие сценарии), условие вечно будет истинным, а значит, постоянно будет выскакивать окошко с обидной надписью. Пока окошко актив- |
Но, нельзя закрыть браузер, нажать ссылку и уйти со страницы иным способом, а также зайти в меню, чтобы отключить активные сценарии. Единственный выход — принудительно завершение работы браузера по Ctrl+Alt+Delete, а это завершит работу не только открытого окна, но и всех остальных окон этого браузера, что неприятно, если их было открыто больше десятка. И если Opera после аварийного завершения работы программы восстанавливает все окна, то другие браузеры такого не умеют. И такие неприятности причинил сценарий в три строчки! Остерегайтесь таких глупых взломов, используйте серверную проверку и замену скобок тэгов на подстановки < и >.
С аналогичным окном confirm(), но предлагающим две возможности, мы познакомились ранее. Помните, что на оба результата нажатий кнопок можно «повесить» совсем непредсказуемые действия.
Кроме этого, JavaScript позволяет управлять самим окном браузера. Есть функции для записи своего текста в статусной строке (window. status='TeKCT'), есть функции для динамического изменения окна браузера и т. п., но ими не стоит злоупотреблять, чтобы пользователь не терял контроль над теми интерфейсными элементами, над которыми он должен иметь контроль.
Всплывающие окна стали уже притчей во языцех. Чаще всего они содержат рекламу, они стали непременными атрибутами порносайтов и т. п. На самом деле, сложно придумать ситуацию, где использование самопроизвольно всплывающих окон было бы действительно оправдано. Однако можно открывать новые окна по щелчку на ссылке: это может не нравится определенной части посетителей, но логично, если дизайн страницы сконструирован только под определенный размер окна.
Предположим, что некоторые ссылки открывают окна именно в новом окне, но нам нужно, чтобы эти новые окна были фиксированного размера (предположим, 660 пикселей) и располагались строго по центру экрана (по горизонтали). Для вызова новых окон напишем функцию:
<script language="JavaScript">
Function owind(obj)
{
Left one = (screen. width-660)/2
Window. open(obj, "inf", config='width=660, height= 34 0,top=150,left='+left one+',toolbar=0,scrollbars=1')
}
<script>
Как следует из параметров функции, новое окно будет фиксированной ширины (width=660) и высоты (height=34 0), откроется на высоте 150 пикселей от верхней границы экрана или от меню брау-
Сайт следит за вами: JavaScript |
|
Зера (в разных браузерах top=150 расценивается по-разному), панели инструментов у окна не будет (toolbar=0), а полосы прокрутки будут видны (scrollbars = 1). Поскольку в функции window. open нет параметра выравнивания по центру, приходится прибегать к хитрости. Берется объект screen (экран), из его ширины (screen. width) вычитается ширина открываемого окна. Получается ширина пространства, которое остается по бокам нового окна. Эта ширина делится пополам, и получается нужное число — количество пикселей, которое будет отступом от левого края экрана. Для этих манипуляций пришлось ввести переменную left one, которая в настройках вставляется не просто так, а конкатенируется с помощью плюсов (строка конфигурации, заключенная в кавычки, разрывается, чтобы можно было вставить не текст, а переменную). Формат функции можно было понять по примеру, но стоит записать его в абстрактном виде: Window. open("адрес страницы", "имя окна", сопйд='параметры открываемого окна') Поскольку команда открытия нового окна заключена в пользовательскую (то есть написанную самостоятельно) функцию, то, во-первых, в ней используется переменная, которая содержит передаваемый функции адрес страницы, а во-вторых, функцию можно вызвать по ссылке: <a href="project. html" target=" blank" onClick="owind('project. html'); return false"> О проекте</а> В данном случае ссылка откроет новое окно в любом случае: с JavaScript или без него. Но в первом случае размер окна будет проконтролирован, а во втором — нет. Выше был упомянут цикл while — его синтаксис понятен без объяснений. Он служит для повторения каких-либо операций, пока действует заданное условие. Как только условие прекращает действовать, прекращается и действие цикла. Приведем пример: <script language="JavaScript"> now = new Date() seconds = now. getSeconds() while(seconds<30) { А1егМ"Щелкать в течение 30 секунд") } </script> |
Сценарий представляет собой щадящую модификацию ранее приведенного сценария. Сначала вводится переменная (now), которая вызывает из памяти компьютера информацию о времени и дате с помощью функции Date() — строго говоря, мы инициализируем объект now, который содержит информацию о времени и дате. Новый объект инициализируется с помощью кодового слова new. (Например, чтобы инициализировать массив, нужно написать: имя_переменной = new Array() .)
В отличие от while, цикл for манипулирует числами. С его помощью очень удобно перебирать пронумерованные данные, например, элементы массива или переменные, содержащие в имени числа. При этом JavaScript позволяет изначально не знать длину массива, а оперировать свойством length, которое считает элементы.
Например, стоит такая задача: найти в документе все элементы <span> и сообщить им название класса, при этом выделить только один <span>, выявленный по идентификатору, и сообщить ему название другого стиля. Таким образом, получится, что HTML-разметка в документе присутствует, а CSS — нет, а только назначается по сценарию.
<script language="JavaScript"> function span colorize(elem)
{
Spcol = document. getElementsByTagName("span") for(i=0; i<spcol. length; i++)
{
Spcol[i].className="spanlink"
}
Document. getElementById(elem).className = "spanunlink"
}
</script>
В переменную spcol заносится динамически генерируемый функцией getElementsByTagName() массив, состоящий из элементов <span>. Количество этих элементов не важно: оно подсчитывается конструкцией spcol. length. Синтаксис параметров цикла таков:
1. i=0 обозначает, что нумерация начата с нуля. В цикле переменная i будет обозначать номер элемента, увеличивающийся на единицу при каждом новом прохождении цикла: во второй проход переменная i будет равна единице. Переменную можно назвать как угодно; i — это просто традиция.
2. i<spcol. length определяет последнее число, при котором будет выполняться цикл. Длина массива всегда на единицу больше,
Сайт следит за вами: JavaScript |
|
Чем номер его последнего элемента, потому что нумерация начинается с нуля. Например, если элементов четыре, то номер последнего элемента — 3, а первого — 0. Поэтому на русский язык это можно перевести так: последнее число для прохождения цикла — то, которое на единицу меньше длины массива spcol; или так: цикл выполняется до тех пор, пока i меньше длины массива spcol. 3. Если бы последнего условия (i++) не было, то число, скрытое под переменной i, не менялось бы. Двойной плюс обозначает инкремент, то есть увеличение числа i на единицу. Если бы тут был двойной минус, то происходило бы уменьшение числа на единицу (декремент), но при этом первое число должно быть больше второго, иначе цикл не будет выполняться в принципе. Далее при каждом проходе цикла берется очередной элемент массива (spcol[i] — его номер скрыт под переменной i), а его свойство — «имя класса» (className) — изменяется на «spanlink» (естественно, имя класса произвольное, «spanlink» приведено в качестве примера). Таким образом, при завершении цикла у каждого элемента <span> имя класса теперь «spanlink». И после окончания цикла с помощью одной строчки document. getElementByld(elem). className = "spanunlink" элементу, идентификатор которого передан в функцию с помощью переменной elem, присваивается имя класса «spanunlink» — строго говоря, этому элементу присваивается сначала имя класса «spanlink» (в цикле), а потом «spanunlink» (отдельной инструкцией), однако последние присвоение имеет, конечно, больший приоритет перед первым. Использовать в цикле можно и статические массивы, и явно выводить номера тоже можно: <script language="JavaScript"> Fruits = new Аггау("яблоко", "груша", "персик", "манго", "слива", "гранат") For(f=0; f<fruits. length; f++) { Fnum = f+1 Document. write("<p>"+fnum+". "+fruits[i]+"</p>") } </script> Сценарий напечатает названия фруктов, правильно (начиная с единицы) пронумеровав их, каждый в отдельном абзаце. Обратите внимание на конструкцию document. write (). Она тоже является средством вывода данных на экран, но, в отличие |
От свойства innerHTML, выводит данные не в тот блок, который указан сценарию, а прямо в том месте, где располагается сценарий. Так, если сценарий расположен сразу после <body>, то вывод будет напечатан в начале страницы, поэтому пользуйтесь методом write ( ) с осторожностью.
Чтобы при выводе нумерация начиналась не с нуля, а выглядела по-человечески, к переменной f, получаемой при каждом проходе цикла, прибавляется единица, а полученное значение переменной fnum и выводится в виде номера.
Оператор for...in выполняет заданные действия для каждого свойства объекта или для каждого элемента массива. Он имеет вид:
For (переменная in выражение) оператор
Здесь переменная — это декларация (объявление) переменной, выражение — любое выражение, значением которого является объект или массив.
<script language="JavaScript">
Var ob = {"а" : "Архангельск", "б" : "Баку", "в" :
"Воронеж"};
For (var key in ob)
Document. write(key + ": " + ob[key] + "<BR>");
</script>
На экране появится текст
А: Архангельск б: Баку в: Воронеж
Объекты, соответствующие ассоциативным массивам в PHP, создаются просто:
Var cat = {name : "Мурка", age : "3 года", color :
"серая"} ;
Обратиться к элементу объекта можно, например, так:
Alert("Имя кошки — "+cat. name)
Возможен и другой вариант:
Function Browser(name, version) {
Сайт следит за вами: JavaScript |
|
This. name = name; this. version = version; } В этом случае объект и его свойства передаются через функцию. Теперь для создания новых объектов класса Browser достаточно вызвать этот конструктор в операции new, например: Var myBrowser = new Browser("Microsoft Internet Explorer", "5.5"); Массивы достаточно часто используются в JavaScript. Те данные, которые можно было бы выводить и напрямую, можно организовывать в виде массивов, потому что в таком формате с ними удобнее работать. Данные массива можно выводить и не прямым перебором: циклы использовать совсем не обязательно: <script language="JavaScript"> sls = new Array( "Деепричастный обормот", "Киберквазиэкзистенциальная футуристическая псевдосущность", "Кидальго (бесчестный испанский рыцарь, из словаря)", "Не все так просто, как на самом деле", "А есть еще язык бурушаски", "Все страньше и страньше", "После нас хоть потом", "Шумерский букварь весом 34 кг", "Новости будут к старости" ) Now = new Date(); Num sls = (now. getSeconds())%sls. length; document. write(sls[num sls]); </script> Рассмотрим сценарий. Во-первых, массив выглядит не совсем так, как было показано в примере ранее: для JavaScript нет ничего критичного в том, чтобы выводить элементы на отдельных строках. Более того, массив можно не записывать целиком сразу, потому что строки, формирующие его, могут быть совсем отдельными: Sls = new Array() Sls[] = "Деепричастный обормот" |
Sls[] = "Киберквазиэкзистенциальная футуристическая псевдосущность"
Sls[] = "Кидальго (бесчестный испанский рыцарь, из словаря)"
Sls[] = "Не все так просто, как на самом деле"
// Тут, допустим, комментарий
Sls[] = "А есть еще язык бурушаски"
Sls[] = "Все страньше и страньше"
Sls[] = "После нас хоть потом"
Sls[] = "Шумерский букварь весом 34 кг"
Sls[] = "Новости будут к старости"
Дальше начинается самое интересное. Чтобы реализовать псевдослучайный выбор числа, возьмем из памяти компьютера (уже известным способом) текущее количество секунд. Как вы уже догадались, полученное число можно использовать в качестве индекса для того, чтобы взять какой-то элемент из массива. Но число секунд в минуте явно больше длины массива, поэтому с помощью конструкции (now. getSeconds())%sls. length ограничиваем число секунд, которые могут применяться для этой цели, числом, соответствующим длине массива. Полученное число записывается в переменную num_sls, которая и используется как индекс.
Операция a % b, строго говоря, возвращает остаток по модулю, то есть целый остаток от деления левого операнда на правый (причем плавающие числа перед операцией округляются до целых). Поскольку такой остаток (например, при делении 52 на 7 он будет равен трем, 55 на 7 — шести) всегда как минимум на единицу меньше второго операнда (в данном случае длины массива), он как раз подходит в качестве чисел — случайных индексов для выбора элементов из массива.
Кроме секунд, объект Date() предоставляет доступ и к другим единицам измерения времени:
GetSeconds() — секунды getMinutes() — минуты getHours() — часы getDay() — день недели getDate() — число getMonth() — месяц
GetYear() — год (две цифры, в Opera обрабатывается неправильно)
GetFullYear() — год (4 цифры)
Каждая функция на выводе дает число, причем в случае с месяцами и днями недели нумерация, конечно, начинается с нуля: это крест программистов, который они должны нести.
Сайт следит за вами: JavaScript |
|
Старайтесь не просто использовать эти числа, а стараться, чтобы вывод был красивым. Сравните, что удобнее: 12.06.2007 или «12 июня 2007 года»? А ведь такого результата добиться совсем просто: <script language="JavaScript"> abc = new Date() chislo = abc. getDate() mesiac = abc. getMonth() god = abc. getFullYear() Mesiaca = new Аггау("января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря") Document. write(chislo + mesiaca[mesiac] + god + " года") </script> И еще помните: просто так выводить на страницу дату не стоит. Для этого у посетителя есть часы в правом нижнем или верхнем углу экрана, наручные час и мобильный телефон. Используйте дату, если она действительно нужна. Массивы можно не только создавать и считывать. Вот несколько полезных функций, используемых при работе с массивами: Concat() Объединяет два массива в один новый и возвращает его Join(разделитель) Объединяет все элементы массива в текстовую строку Pop() Удаляет последний элемент массива Push(элемент 1, элемент 2, ...) Добавляет элементы в конец массива Reverse() Изменяет порядок элементов массива на противоположный Shift() Удаляет первый элемент массива и возвращает его Slice(начало, конец) Извлекает часть массива и возвращает новый массив. Начало и конец — числа либо числовые выражения |
4 |
Программирование |
Sort() Сортирует элементы массива ToString() Преобразует массив в строку, при этом разделителями между бывшими элементами массива является запятая Unshift() Добавляет элементы в начало массива В JavaScript есть несколько полезных функций, которые работают со строками. Как и в других языках, строки в JavaScript можно выводить не напрямую, а предварительно обработав их. Вот основные функции: ^агА^число) Возвращает символ, находящийся в данной позиции строки. Например, вызов string. charAt(2) возвратит символ «а», если переменная string будет содержать в себе слово «красный». IndexOf(подстрока) Возвращает позицию первого вхождения заданной подстроки. Вызов document. write(string. indexOf("a") ) возвратит число 2. LastIndexOf(подстрока) Возвращает позицию последнего вхождения заданной подстроки. Действует аналогично предыдущей функции, но ищет с конца. Та^Мрегулярное выражение) Сопоставляет строку с регулярным выражением (о регулярных выражениях — чуть позже). Гер1асе(регулярное выражение, подстрока) Сопоставляет строку с регулярным выражением и заменяет найденную подстроку новой подстрокой. Действует как функция «Найти и заменить» в Windows-приложениях, но исключительно с использованием регулярных выражений. Search(регулярное выражение) Ищет сопоставление строки с регулярным выражением. Возвращает позицию первого вхождения подстроки. Slice(начало, конец) Извлекает часть строки и возвращает новую строку. В качестве аргументов в функцию передаются числа, обозначающие позиции относительно начала строки. Вызов document. write("ABCDEF". |
|
348 |
Сайт следит за вами: JavaScript |
|
Slice(2,-1)) выведет на экран обозревателя строку CDE. Отрицательные аргументы трактуются как смещения от конца строки. Split(разделитель) Разбивает строку на массив подстрок. В качестве разделителя может выступать как обычная текстовая строка, так и регулярное выражение. Если разделитель не задан, то все равно получится массив, но из одного элемента. Substr(позиция [, длина]) Возвращает подстроку, заданную позицией и длиной. Вызов "abcdef".substr(1, 3) возвратит «bcd», поскольку чтение начинается с символа с индексом «1» (это символ «b»), после которого извлекается строка длиной 3 символа. Substring(начало [,конец]) Возвращает подстроку, заданную начальной и конечной позициями. Если конечная позиция не задана, то возвращается подстрока, начиная с позиции начало и до конца исходной строки. ToLowerCase() Преобразует все буквы строки в строчные. ToUpperCase() Преобразует все буквы строки в прописные. Все эти функции обращаются к строкам в таком формате: стро- ка. функция(). В качестве строки удобнее всего использовать переменные. Регулярные выражения используются в самых разных языках, и JavaScript не исключение. Их смысл в том, чтобы производить операции с тем текстом, который заранее неизвестен. Чаще всего с ними используется функция replace(). Сама замена может иметь два формата записи. Во-первых, в одну строку: String = string. replace(/&/g,"&") Где string — это обычная строка (ее содержимым может быть и один символ, и нуль символов, и текст, и содержимое текстового поля, и все содержимое документа...). В качестве искомой строки в косые скобки заключен амперсанд, в качестве параметра — глобальный поиск (g), который означает, что поиск заменит все вхождения подстроки, а в качестве результирующей строки дано мнемоническое представление спецсимвола амперсанда. Все знаки «&» заменятся в документе на «& ». |
Во-вторых, используется такая запись, когда сложное регулярное выражение в первой записывается в переменную, а вторая строка производит замену:
Para = "<p>"
Thispattern = new RegExp(para+"rn"+para, "g")
String = string. replace(thispattern, para)
В качестве искомой строки мы имеем два тэга абзаца, разделенные переводом каретки и символом новой строки, параметр глобального поиска в этом случае заключается в кавычки. В примере ищутся все двойные тэги абзаца и заменяются на одиночные.
Как видим, в качестве регулярного выражения может выступать и обычный текст, но часто встречаются и собственно выражения:
Dashvar = "—"
Thispattern = new RegExp("([A ])"+dashvar, "g")
String = string. replace(thispattern,
"$1 "+dashvar)
Данный пример ищет отрезки текста, где перед тире забыли поставить пробел, и расставляет эти пробелы. Регулярное выражение [А ] говорит о том, что ищется любой символ, кроме (А) пробела, оно заключено в скобки, чтобы этот символ, каким бы он ни был, можно было вернуть на место в результирующей строке в виде сочетания $1 (это не переменная, а так называемый «карман», куда было записано содержимое найденной регулярным выражением подстроки). Всего может быть до девяти таких последовательностей, заключенных в круглые скобки, и их содержимое возвращается с помощью последовательностей от $1 до $9. Последовательность [А ] + отвечала бы за любое количество непробельных символов больше нуля, а [А ]* — за любое количество непробельных символов, включая нуль. Любой символ обозначается точкой. Чтобы использовать в регулярном выражении точку, ее надо экранировать обратным слэшем:
String = string. replace(/T.K./g,"T. K.")
В этом примере последовательность «т. к.» заменится на «т. к.», причем пробел между ними будет неразрывный.
Хороший и лаконичный справочник по регулярным выражениям располагается по адресу: Http://Wdh.Suncloud.Ru/Js05.Htm.
JavaScript также способен почти самостоятельно оформлять фрагменты текста тэгами. Существуют функции, которые присваивают тексту параметры, аналогичные тому, как если бы текст был оформлен
Сайт следит за вами: JavaScript |
|
Различными тэгами. Естественно, в коде не происходит никаких изменений — после действия сценария они отображаются на веб-странице. Среди таких функций — link() , bold() , italic() и другие (упомянутые делают текст ссылкой, полужирным и курсивным соответственно), однако они используются только в сочетании с конструкцией document. write() , что снижает ценность подобных функций почти до нуля. То есть подобная конструкция работать будет: <script language="JavaScript"> Document. write("Мой TeKCT".link("Http://www. ya. ru")) </script> А такие — не будут: <p onMouseOver="this. innerHTML. link('Http://www. уа. ги')">Мой текст</р> <p onMouseOver="this. link('Http://www. уа. ги')">Мой текст</р> Получается, что фактически нельзя обратиться к строке динамически. Поэтому в современных сценариях подобные функции практически не используются. В JavaScript можно работать не только со строками, но и с числами: <script language="JavaScript"> Function convert(inches) { cm = inches * 2.54; meters = inches / 39.37; } </script> Данная функция преобразует дюймы (inches) в сантиметры и метры, инициализирую соответствующие переменные. Сначала нужно вызвать функцию с определенным числом дюймов, а потом печатать полученные значения вызовами document. write() или object. innerHTML. В JavaScript употребляются следующие математические операторы: A < b Меньше |
4 |
Программирование |
А > Ь Больше А <= Ь Не больше; меньше или равно А => Ь Не меньше; больше или равно А == Ь Равно А!= Ь Не равно А === Ь Тождественно (равно с учетом типа данных) А !== Ь Не тождественно (не равно с четом типа данных) Эти операторы чаще всего используются при сравнении, например, в условных операторах. Есть и обычные арифметические операции: А + Ь Сложение А - Ь Вычитание А * Ь Умножение А / Ь Деление А % Ь Остаток по модулю (возвращает целый остаток от деления левого операнда на правый. Плавающие числа перед операцией округляются до целых) ++ Инкремент [увеличивает значение переменной на 1. Если используется как префикс (++а), возвращает значение операнда после |
|
352 |
Сайт следит за вами: JavaScript |
|
Увеличения его на 1. Если используется как постфикс (a++), возвращает значение операнда перед увеличением его на 1] Декремент [уменьшает значение переменной на 1. Если используется как префикс (--a), возвращает значение операнда после уменьшения его на 1. Если используется как постфикс (a--), возвращает значение операнда перед уменьшением его на 1] -а Смена знака Обратите внимание, что JavaScript (в отличие, например, от Python) лояльно относится к пробелам. То есть «a+b» и «а + b» для языка JavaScript — одно и то же. В JavaScript есть три логических оператора: А && b Логическое «и» (оператор возвращает true, если оба операнда истинны. Если первый операнд ложен, то возвращает false, не вычисляя значение второго операнда) А || b Логическое «или» (возвращает true, если хотя бы один операнд истинен. Если первый операнд истинен, то возвращает true, не вычисляя значение второго операнда) !а Логическое «не» (возвращает true, если операнд ложен) В JavaScript есть операторы присваивания. С оператором a=b мы уже несколько раз имели дело, но есть и сложные операторы, которые аналогичны операции присваивания, совмещенной с арифметическими операциями: A += b аналогично a = a + b a -= b аналогично a = a - b a *= b аналогично a = a * b a /= b аналогично a = a / b a %= b аналогично a = a % b Помимо этого, в JavaScript существует встроенный объект Math, который используется для доступа к различным операциям с числами. Например, Math. round ( число ) возвращает результат округления числа, переданного в функцию, Math. sin( число ) возвращает синус и т. п. |
|
353 |
Наконец, чтобы картина получилась более полной, перечислим еще несколько операторов, которые употребляются в разных случаях и не относятся к одному типу.
Условный оператор формата var = test? valuel : value2 уже рассматривался в одном из примеров. Он позволяет присваивать значение не только переменной, но и свойствам объектов.
Оператор «запятая» позволяет группировать действия. Например, в цикле for:
<script language="JavaScript">
Abc = new Array("nepBbrn", "Второй", "Третий") for(i=0,j=1; i<abc. length; i++,j++)
{
Document. write("<p>"+j+". "+abc[i]+"</p>")
}
</script>
Вместо того, чтобы каждый раз прибавлять к переменной i единицу, чтобы получить корректное значение переменной j, мы увеличиваем значение j прямо в условиях цикла, там же и назначив ей первое значение — все это одновременно с присвоением значения и инкрементом i, через запятую.
Оператор delete может удалять свойство объекта или элемент из массива, а также переменную (если она не была назначена с использованием кодового слова var):
Langs = new Array("HTML", "CSS", "JavaScript", "Java")
Delete langs[2]
Оператор in возвращает «истину», если левый операнд является свойством правого операнда (или левый операнд является элементом массива, указанного в качестве правого операнда).
Оператор with призван сократить объем кода: если происходит многократное обращение к одному объекту с целью изменить его свойства, можно включить этот объект в оператор with, а в фигурных скобках указать его свойства. Допустим, у нас есть абзац:
<p id="special">123</p>
Можно традиционно изменить его свойства:
<script language="JavaScript"> document. getElementById("special").style. color="red"
Сайт следит за вами: JavaScript |
|
Document. getElementById("special").style. FontWeight="bold" Document. getElementById("special").style. BorderBottomWidth="1px" Document. getElementById("special").style. BorderBottomStyle="dashed" Document. getElementById("special").style. BorderBottomColor="red" </script> В результате этого сценария абзац, к которому произошло обращение по идентификатору, стал красным и полужирным, а также обрел прерывистое подчеркивание красного цвета снизу по всей ширине страницы (даже если текст меньше). Но код можно написать лаконичнее: <script language="JavaScript"> With(document. getElementById("special").style) { Color="red" FontWeight="bold" BorderBottomWidth="1px" BorderBottomStyle="dashed" BorderBottomColor="red" } </script> В качестве дополнительного материала можно рассмотреть несколько работающих примеров, где сценарии на JavaScript применяются для визуальных эффектов. Поясняться будут только те фрагменты, которые могут быть непонятными из всего предшествующего материала. Пример 1. Печатающийся текст Задача: в текстовом блоке один за другим появляются символы, пока текст не напечатается до конца. <div id="info"></div> <script language="JavaScript"> Text = "Какой-то очень длинный текст, в данном случае приводимый в качестве тестового, чтобы можно было сполна насладиться эффектом." i = 0 Function printIt() { |
I++
If(i <= text. length)
{
Document. getElementById("info").innerHTML = text. substr(0,i)
}
SetTimeout("printIt()",25)
}
PrintIt()
</script>
Пояснения. Из переменной text берется сначала первый символ, при втором выполнении функции — первый и второй и т. п.; после такого извлечения в пустой блок с идентификатором «info» записывается получившийся отрезок текста. Выполнение функции повторяется благодаря функции setTimeout(функция, задержка) , которая вызывает переданную ей функцию еще раз с задержкой в 25 миллисекунд. Поскольку вызов setTimeout() помещен внутрь функции (более того, внутрь условия), он будет вызываться снова и снова, пока условие (i меньше или равно длине массива) не перестанет быть истинным. Все это создает иллюзию печатающегося текста, хотя фактически содержимое блока перезаписывается сценарием со все увеличивающимся количеством символов.
Пример 2. Блок, выезжающий из-за границы экрана
Задача: при нажатии на ссылку или кнопку из-за боковой границы веб-страницы выезжает блок с каким-то содержимым и останавливается в определенном месте.
<div id="searcher" style="position:absolute; left:-350px; top:245px; width:300px; background- color:#9CEB91; border-width:1px; border-style: solid; border-color:#FDECB8 black black #FDECB8; padding:10px">
Содержимое блока поисковой системы </div>
<script language="JavaScript"> sta = -350 re = 1
Function load search()
{
If(sta<=255)
Сайт следит за вами: JavaScript |
|
{ Sta = sta+10 Document. getElementById("searcher").style. left = Sta SetTimeout("load search()",10) } Else { Re = 2 } } Function load search back() { If(sta>=-350) { Sta = sta-10 Document. getElementById("searcher").style. left = Sta SetTimeout("load search back()",10) } Else { Re = 1 } } </script> <p><a href="/search/" onClick="if(sta<=55) {load search();} else {load search back();} return false">Поиск</a></p> Пояснений особых не требуется: для передвижения по экрану использована такая же функция задержки, а в качестве исходного размещения блока указано отрицательное значение по горизонтали. При повторном нажатии на ссылку поисковый блок уедет обратно. Пример 3. Системное сообщение на сайте Задача: при нажатии на кнопку или ссылку вся веб-страница затемняется, элементы становятся едва видны, а на этом фоне четко видно системное сообщение. <script language="JavaScript"> function opCl(dvname) |
|
357 |
{
Document. getElementById(dvname).style. display = (document. getElementById(dvname).style. display=="block") ? "none" : "block";
}
</script>
<button onClick="opCl('darkener')></button>
<div id="darkener" style="display:none; position: absolute; left:0px; top:0px; width:100%; height:100%; background-color:#777777; text-align:center; filter: progid:DXImageTransform. Microsoft. Alpha(opacity=90); - moz-opacity: 0.9; - khtml-opacity: 0.9; opacity: 0.9; color:white">
Содержимое системного сообщения </div>
Пояснения. Об особенностях реализации полупрозрачности на веб-страницах было написано в разделе про язык CSS. Приведенная функция открытия блока уже рассматривалась выше. Не забудьте только на самом системном сообщении сделать кнопку, закрывающую затемняющий блок.
Пример 4. Переход подсветки по пунктам меню
Задача: сделать эффект плавного подсвечивания пунктов меню определенным цветом, причем чтобы это подсвечивание «двигалось» по меню: сначала был подсвечен первый пункт меню, затем второй и т. п., вне зависимости от количества пунктов. Соседние пункты меню должны иметь переходный цвет. При наведении на пункт меню оно меняется (как обычно, псевдоклассом a:hover), что не мешает движению динамического подсвечивания. Сами же пункты меню располагаются в виде «лесенки» сверху вниз справа налево, уступами.
<style type="text/css"> body, td, div, p, pre { font-size:10pt;
Font-family:Arial, Helvetica, Sans-Serif;
}
A:link, a:visited, a:active, .pseudolink { color:#4 9587 9;
}
.cat1:link, .cat1:visited, .cat1:active { text-decoration:none; font-size:110%;
Сайт следит за вами: JavaScript |
|
Color:#4 9587 9; } .cat2:link, .cat2:visited, .cat2:active { Text-decoration:none; Font-size:110%; Color:#CC0000; } A:hover, .pseudohover { color:#355DB5; } .cat3:link, .cat3:visited, .cat3:active { Text-decoration:none; Font-size:110%; Color:#683456; } A:hover, .pseudohover { color:#355DB5; } .cat1:hover, .cat2:hover, .cat3:hover { font-size:12 0%; color:#CC0000; Border-left:3px solid #B8C2CE; border-bottom:1px solid #B8C2CE; } </style> <script language="JavaScript"> items = new Агму^Тазораспределительные станции", "Подогреватели газа", "Газорегуляторные пункты блочные", "Газорегуляторные пункты шкафные", "Газорегуляторные пункты НОРД", "Газорегуляторные пункты с узлом учета", "Пункты учета газа автономные", "Регуляторы давления газа", "Предохранительно-сбросные клапаны", "Предохранительно-запорные клапаны", "Клапаны электромагнитные", "Клапаны предохранительные полуавтоматические", "Краны шаровые газовые", "Фильтры газовые", "Блочно-модульные котельные", "Подогреватели нефти"); Itemsl = new Array(); itemsll = new Array(); For(i=0; i<items. length; i++) { Zi = 102+i Itemsl[i] = "div"+i; |
Itemsll[i] = "lin"+i; posit = i+1; leftstop = 430-(i*11); topstop = 20+(i*20); document. write("<div id='div"+i+"' style='height:25px; width:400px; position:absolute; left:"+leftstop+"; top:"+topstop+"; padding:1px; z - Index:"+zi+"'><A id='lin"+i+"' HREF="/?catalogue/ "+posit+"/" class="cat1">"+items[i]+"</A></div>"); // конец цикла }
Ii=0
Function change()
{
If(ii<itemsl. length)
{
Iipre = ii-1;
If(iipre < 0) {iipre=itemsl. length-1;} iipost = ii+1;
If(iipost >= itemsl. length) {iipost=0;} for(j=0; j<itemsl. length; j++)
{
Document. getElementById(itemsll[j]).className =
"cat1"
}
Document. getElementById(itemsll[ii]).className = "cat2"
Document. getElementById(itemsll[iipre]).className = "cat3"
Document. getElementById(itemsll[iipost]). className = "cat3" ii++
If(ii==itemsl. length)
{
Ii = 0;
}
}
SetTimeout("change()",800)
}
Change()
</script>
Сайт следит за вами: JavaScript |
|
Пояснения. Меню генерируется динамически, поэтому его пункты содержатся в массиве. (На самом деле стоит предусмотреть, что JavaScript в браузере может быть отключен, и создать на этот случай статическое меню, заключив его в тэги <noscript>...</noscript>.) Циклом также генерируются имена блоков <div> и идентификационные названия ссылок, чтобы и к тем, и к другим можно было впоследствии обращаться с помощью getElementById(). В этом же цикле динамически вычисляются координаты для жестко позиционированных блоков, заключающих пункты меню. Поскольку стиль псевдокласса hover (видный при наведении мыши) такой, что ссылка становится крупнее, нужно проследить, чтобы она не перекрывалась соседними ссылками. За это отвечает CSS. Функция change(), описываемая в сценарии, отвечает не только за применение нового имени класса к очередной ссылке, но и за применение имени особого «промежуточного» класса к соседним ссылкам, причем, если «красная», то есть наиболее ярко подсвеченная ссылка оказывается на краю меню (первым или последним элементом), то соседними считаются не только второй или предпоследний пункты меню соответственно, но и крайние с противоположного конца меню: для первого пункта меню соседними считаются второй и последний. Для движения цвета по элементам используется небольшая задержка, реализованная с помощью функции setTimeout(), которая находится в теле функции, а значит, будет выполняться, пока истинно условие — значение числовой переменной меньше, чем длина массива. Чтобы это условие всегда оставалось истинным, при достижении последнего допустимого значения числовая переменная обнуляется, и все начинается сначала. Пример 5. Расписание Задача. Сделать так, чтобы в браузере было видно расписание на сегодня и на завтра. <script language="JavaScript"> Daysname = new Аггау("Воскресенье","Понедельник", "Вторник","Среда","Четверг","Пятница","Суббота") days = new Array() days[0] = 'Выходной' // Воскр. Days[1] = 'Математика — 2 пары <БИ>Прикладное домоводство' // Понед. Days[2] = 'Общая типология <БИ>Кибернетика <БИ>История татарской культуры' // Вт. Days[3] = 'История вьетнамского языка <БИ>Рисование <БИ>Трехмерное моделирование' // Ср. Days[4] = 'Традиционный буддизм <БК>Углубленное сисадминство' // Чт. |
Days[5] = 'Литературоведение <ВК>Шрифты и визуальные коммуникации' // Птн. days[6] = 'Выходной' // Суб.
Now = new Date() thisday = now. getDay() tomorrow = now. getDay()+1 if(tomorrow>6) tomorrow=0
Document. write("<P><B>"+daysname[thisday]+"
(сегодня)</В><ВИ>")
Document. write(days[thisday] + "</P>")
Document. write("<P><B>"+daysname[tomorrow]+"
(завтра)</В><ВИ>")
Document. write(days[tomorrow]+ "</P>")
</script>
Пояснений тут не требуется вообще, поскольку все и так ясно: один массив отвечает за дни недели, другой за образовательные предметы, выводятся актуальные предметы и предметы, которые будут актуальны завтра.
Пример 6. Перетаскивание объектов по веб-странице
Интерфейсы сайта богаче интерфейсов обычных программ по внешнему виду, но намного беднее по возможностям — только потому, что имеет место несовместимость с разными версиями браузеров, а основное количество действий, совершаемых на странице в режиме реального времени, осуществляется с помощью языков активных сценариев — наиболее уязвимая технология с точки зрения браузерной совместимости.
Например, перетаскивание объектов мышью по странице две или три версии браузеров назад было практически неосуществимой задачей. Ныне с помощью таблицы стилей и JavaScript реализовать это стало возможно. (К слову, если браузеры будут поддерживать HTML 5, то никаких сценариев не понадобится: возможность перетаскивания элементов будет активироваться добавлением одного атрибута.)
Для этого достаточно сделать следующее: создать файл со сценарием (например, drag. js — от английского drag «тащить») и сделать на него ссылку в коде страницы, где будет происходить перетаскивание: <script language="JavaScript" src="/scripts/drag. js"></script>; в каждом тэге блока, который будет перемещаться мышкой по странице, сделать указание на класс, определенный в глобальной таблице, идентифицировать этот блок с помощью параметра id, указать первоначальные координаты и инициализировать выполнение скрипта:
Сайт следит за вами: JavaScript |
|
<div class="draggable" id="block1" style="left:17 5px; top:100px" onmousedown="StartDrag( event, this, PutBack)">nepeTac^BaeMbra блок</div> Класс «draggable» следует определить заранее: <style> .draggable { Cursor: pointer; z-index: 2; width: 180px; padding: 5px; position: absolute; background-color: white; border:1px solid #C6C9DD } </style> Разумеется, стиль курсора, ширину, отступы и оформление фона и рамок можно оставить на свое усмотрение. Наконец, содержание файла «/scripts/drag. js» таково: //--------------------------------------------------------------------------- /* Author — Andrew Shitov (Ash@design. ru) | 20052006 Additions — Erlang (Www. erlang. com. ru) | 2006 May Original drag mechanics was written by Mike Hall (Http://www. brainjar. com/dhtml/drag/) in 2001. */ Var isMSIE = document. attachEvent!= null; var isGecko = !document. attachEvent && document. addEventListener; Var Draggingltem = new Object(); Function StartDrag (event, this, afteraction) { Draggingltem. This = this; Draggingltem. AfterAction = afteraction; Var position = new Object(); if (isMSIE) { Position. x = window. event. clientX + document. |
DocumentElement. scrollLeft + document. body. scrollLeft;
Position. y = window. event. clientY + document. documentElement. scrollTop + document. body. scrollTop;
}
If (isGecko)
{
Position. x = event. clientX + window. scrollX; position. y = event. clientY + window. scrollY;
}
Draggingltem. cursorStartX = position. x; Draggingltem. cursorStartY = position. y;
Draggingltem. StartLeft = parseInt (Draggingltem. This. style. left);
Draggingltem. StartTop = parseInt (Draggingltem. This. style. top);
If (isNaN (Draggingltem. StartLeft)) Draggingltem. StartLeft = 0;
If (isNaN (Draggingltem. StartTop)) Draggingltem. StartTop = 0;
If (isMSIE)
{
Document. attachEvent ("onmousemove",
ProceedDrag);
Document. attachEvent ("onmouseup", StopDrag); window. event. cancelBubble = true; window. event. returnValue = false;
}
If (isGecko)
{
Document. addEventListener ("mousemove", ProceedDrag, true);
Document. addEventListener ("mouseup", StopDrag, true);
Event. preventDefault();
}
}
Function ProceedDrag (event)
{
Document. getElementById("restorer").style.
Display="block";
Сайт следит за вами: JavaScript |
|
Var position = new Object(); if (isMSIE) { Position. x = window. event. clientX + document. documentElement. scrollLeft + document. body. scrollLeft; Position. y = window. event. clientY + document. documentElement. scrollTop + document. body. scrollTop; } If (isGecko) { Position. x = event. clientX + window. scrollX; position. y = event. clientY + window. scrollY; } Var nextX = DraggingItem. StartLeft + position. x - DraggingItem. cursorStartX; If (nextX < 9) nextX = 9; DraggingItem. This. style. left = nextX + "px"; if (nextX > 800) nextX = 800; DraggingItem. This. style. left = nextX + "px"; Var nextY = DraggingItem. StartTop + position. y - DraggingItem. cursorStartY; If (nextY < 12) nextY = 12; DraggingItem. This. style. top = nextY + "px"; If (nextY > 421) nextY = 421; DraggingItem. This. style. top = nextY + "px"; If (isMSIE) { Window. event. cancelBubble = true; window. event. returnValue = false; } If (isGecko) event. preventDefault(); } Function StopDrag (event) { If (isMSIE) { Document. detachEvent ("onmousemove", ProceedDrag); Document. detachEvent ("onmouseup", StopDrag); |
}
If (isGecko)
{
Document. removeEventListener ("mousemove", ProceedDrag, true);
Document. removeEventListener ("mouseup",
StopDrag, true);
}
If (DraggingItem. AfterAction) DraggingItem. AfterAction (DraggingItem. This);
}
Zeta = 100
Function PutBack (item)
{
Zeta = zeta+1 item. style. zIndex = zeta;
}
//--------------------------------------------------------------------------
Резюме
Несмотря на эти десять процентов пользователей, которые отключают активные сценарии в своем браузере, не стоит отказываться от использования JavaScript совсем. Во-первых, процент таких поль- зователей-перестраховщиков стремительно падает. Если человек путешествует по интернету с умом, не открывая все ссылки подряд, то вероятность инфицирования компьютера сценариями исчезающее мала. Некоторые браузеры позволяют применять индивидуальные настройки для каждого сайта. Например, по умолчанию отключать активные сценарии, а для сайтов, чье содержимое вызывает доверие, включать. Во - вторых, JavaScript позволяет делать с содержимым веб-страницы массу полезных вещей, которые было бы просто жалко не использовать.
Единственная рекомендация, которую можно было бы дать, — использовать сценарии на JavaScript там, где они действительно необходимы. Не нужно с помощью активных сценариев выводить текущую дату на страницу. Полезнее была бы информация о том, сколько времени посетитель провел на ней, — да и то, эта информация скорее нужна владельцам сайта, так что можно заносить ее в статистику, а на экран выводить совсем не обязательно. Полезно было бы показывать, сколько времени осталось до того или иного события — эту информацию, если она должна динамически обновляться на экране, иначе как с помощью активных сценариев и не отобразишь. Не стоит делать выпадающее
Сайт располагается на одной странице
4.5 |
Меню там, где можно обойтись простым иерархическим, — еще не все браузеры в состоянии отобразить действующие выпадающие меню, построенные только на CSS (имеются в виду не списки <select>, а динамически формирующиеся блоки ссылок). Однако и ударяться в обратную крайность — делать только статические страницы — тоже не стоит.