Создание эффекта изменения изображения



Теперь, имея общее представление о компоновке страницы, можно начинать ее модификацию. Начнем с создания простого эффекта изменения изображения:

<img src="button_off.gif" onmouseover="this.src='button_over.gif';"    onmousedown="this.src='button_down.gif';" onmouseout ="this.src='button_off.gif';"    onmouseup ="this.src='button_over.gif';">

В этом коде присутствуют 4 события изображения: onmouseover, onmousedown, onmouseout и onmouseup. Каждое из этих событий имеет присоединенный простой фрагмент кода JavaScript, который изменяет атрибут src изображения. Создавая три разных изображения, можно легко и быстро создать изображение с тремя сменяющими друг друга состояниями.

Добавление и удаление элементов

Одной из задач, которая становится все более распространенной в современных приложениях JavaScript, является возможность добавления или удаления элементов страницы. Предположим, что имеется форма, которая позволяет послать кому-нибудь ссылку. Обычно используется одно поле ввода для адреса e-mail и второе - для имени получателя. Если требуется послать ссылку нескольким адресатам, то либо придется посылать форму несколько раз, либо можно было бы разместить на странице более одного набора полей имя/e-mail. Но в этом случае мы все еще ограничены заданным числом контактов. Если имеется пространство для 5 контактов и необходимо послать ссылку 20 людям, то форму придется заполнять 4 раза.

JavaScript позволяет обойти эту проблему, делая возможным динамическое дополнение и удаление содержимого страницы:

1 var inputs = 0;2 function addContact(){3 var table = document.getElementById('contacts');45 var tr = document.createElement('TR');6 var td1 = document.createElement('TD');7 var td2 = document.createElement('TD');8 var td3 = document.createElement('TD');9 var inp1 = document.createElement('INPUT');10 var inp2 = document.createElement('INPUT');11 12 if(inputs>0){13  var img = document.createElement('IMG');14 img.setAttribute('src', 'delete.gif');15 img.onclick = function(){16   removeContact(tr);17 }18 td1.appendChild(img);19 }2021 inp1.setAttribute("Name", "Name" +inputs);22 inp2.setAttribute("Email", "Email"+inputs);2324 table.appendChild(tr);25 tr.appendChild(td1);26 tr.appendChild(td2);27 tr.appendChild(td3);28 td2.appendChild(inp1);29 td3.appendChild(inp2);3031 inputs++;32 }33 function removeContact(tr){34 tr.parentNode.removeChild(tr);35 }36 <table>37 <tbody id="contacts">38   <tr>39   <td colspan="3"><a href="javascript:addContact();">Добавьте контакт</a></td>40   </tr>41   <tr>42      <td></td>43      <td>Name </td>44      <td>Email</td>45   </tr>46 </tbody>47 </table>

Демонстрация

Добавьте контакт Name Email

Возможно вам не приходилось ранее использовать тег TBODY. Многие браузеры автоматически добавляют этот тег в DOM, не сообщая об этом. Если необходимо изменить содержимое таблицы, то в действительности необходимо изменить содержимое TBODY. Во избежание возможных недоразумений мы просто добавили тег TBODY, чтобы каждый мог бы его видеть. Все это может показаться достаточно сложным, но здесь очень мало нового материала.

Прежде всего здесь имеется новая функция: document.createElement. Функция createElement создает задаваемый аргументом элемент. Можно видеть, что в строках сценария с 5 по 10 создается несколько элементов. В действительности создается новая строка TR, которая вставляется в таблицу в строках 37-46. В результате новая строка TR будет выглядеть следующим образом:

<tr> <td> <img src="delete.gif"> </td> <td> <input name="Name1"> </td> <td>       <input name="Email1"> </td></tr>

Другими словами, мы создали 7 элементов: 1 TR, 3 TD, 2 INPUT и 1 IMG. Тег IMG будет использоваться как изображение кнопки " Удалить ". Так как пользователь должен всегда видеть по крайней мере 1 строку ввода, то первую строку удалить невозможно. Поэтому в 12 строке сценария проверяется, что создается первая строка. Если строка не первая, то добавляется изображение.

После создания всех этих элементов остается в действительности поместить их в документ. Каждый элемент на странице имеет встроенную функцию appendChild, которую можно использовать для добавления к этому элементу потомка. Когда добавляется потомок, то он добавляется как последний элемент, поэтому если таблица уже имеет в качестве потомков 10 тегов TR и добавляется еще один, то он будет добавлен как 11-ый тег TR. Мы начинаем с получения ссылки на таблицу (строка 3). Затем мы добавляем TR к этой таблице (строка 24) и добавляем затем 3 TD (строки 25-27). Второй и третий TD содержат поле ввода, поэтому мы добавляем эти поля ввода (28-29).

Вот и все! Теперь у нас есть новый элемент TR, и он находится на странице. Осталось пояснить еще пару моментов. Чтобы форма была обработана правильно, все поля ввода должны иметь различные имена. Поэтому мы задаем имя двух полей ввода на основе счетчика (21-22), а затем увеличиваем счетчик (31). Это делается с помощью еще одной новой функции setAttribute, которая имеет два параметра: имя атрибута и значение атрибута. Для нее существует дополнительная функция getAttribute, которая имеет только один аргумент: имя атрибута, значение которого надо получить.

element.setAttribute("name", "elementName")

по сути то же самое, что

element.name="elementName"

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

Необходимо также позаботиться о кнопке удаления. Мы уже знаем, что кнопка удаления для первой строки полей не создается, но необходимо заставить ее работать для всех остальных. Это делается в строках кода 15-16. Здесь к изображению добавлена функция onclick, которая вызывает функцию removeContact, передавая элемент TR в качестве единственного аргумента.

Взглянув на функцию removeContact, можно видеть, что сначала происходит обращение tr.parentNode к функции parentNode, которая является еще одной функцией для работы с DOM. Она просто возвращает порождающий элемент для текущего элемента. Если посмотреть на изображенное ранее дерево документа, то видно, что parentNode вернет элемент непосредственно над элементом, на котором он вызван. Поэтому, если вызвать parentNode на одиночном элементе A в этом дереве, то будет получена ссылка на элемент TD над ним.

Поэтому tr.parentNode возвращает ссылку на элемент TABLE над TR. Затем вызывается функция removeChild на этом элементе TABLE, которая просто удаляет у предка указанного потомка.

Взглянув еще раз на строку 34, можно теперь увидеть, что она просто говорит: " Удалить элемент TR у его предка " или еще проще " Удалить элемент TR ".

Элементы потомки

Ко всем потомкам элемента можно обратиться с помощью атрибута childNodes, который возвращает массив, содержащий все узлы потомки текущего элемента. Можно также использовать атрибуты firstChild и lastChild на любом элементе, чтобы получить ссылки на первый или на последний элемент.

Чтобы увидеть, как это работает, давайте напишем сценарий для раскраски чередующихся строк TR в таблице:

function setColors(tbody, color1, color2){ var colors = [color1, color2]; var counter = 0; var tr = tbody.firstChild; while(tr){ tr.style.backgroundColor = colors[counter++ % 2]; tr = tr.nextSibling; }}

Демонстрация

Row 1Row 2Row 3Row 4Row 5Row 6 Color #1: Color #2: Раскрасьте таблицу

При рассмотрении этого небольшого фрагмента кода мало что нужно пояснять в том, как можно получить этот интересный небольшой эффект. Код начинается с получения ссылки на первый элемент TR в таблице с помощью метода firstChild. Затем каждый TR раскрашивается по очереди двумя разными цветами, используя tr.style. Цвет фона задается одним из двух цветов из массива colors. Если counter имеет четное значение, то цвет фона задается как color1. Иначе он задается как color2. Это реализуется с помощью оператора деления по модулю ( % ). Для тех, кто забыл, напомним, что операция вычисляет остаток при делении. 5/2 = 2 с остатком 1. Поэтому 5 % 2 (5 по модулю 2) = 1.

Здесь не будет обсуждаться в данный момент изменение стилей, но достаточно сказать, что element.style предоставляет доступ ко всему, что можно задать с помощью таблицы стилей. Если нужно, например, задать стиль элемента, то можно прочитать/записать весь стиль с помощью element.style.cssText.

После задания цвета фона берется следующий элемент TR в таблице. Это делается с помощью функции nextSibling, которая возвращает следующий элемент в DOM, с тем же предком, что и текущий элемент. Если посмотреть на тег TABLE, то все его потомки являются элементами TR, поэтому nextSibling будет в цикле перебирать все элементы TR. Если отыскивается элемент TR с потомками, состоящими из элементов TD, то nextSibling будет циклически перебирать все элементы TD. Когда элементов TR больше не останется, цикл автоматически закончится, так как TR будет неопределенным, что в JavaScript оценивается как false.

С целью рассмотрения оператора childNodes и функции getElementsByTagName перепишем приведенный пример немного по-другому:

function setColors(tbody, color1, color2){ var colors = [color1, color2]; for(var i=0; i<tbody.childNodes.length; i++){ tbody.childNodes[i].style.backgroundColor = colors[i % 2]; }} function setColors(tbody, color1, color2){ var colors = [color1, color2]; var trs = tbody.getElementsByTagName('TR'); for(var i=0; i<trs.length; i++){ trs[i].style.backgroundColor = colors[i % 2]; }}

Обе эти функции делают то же самое, что и первая функция setColors, но написано это немного по-другому. Первая функция использует атрибут childNodes. Как ранее говорилось, childNodes содержит массив, элементами которого являются потомки. Поэтому мы циклически перебираем tbody.childNodes и изменяем цвет каждого потомка, которые все должны быть элементами TR.

Другая функция использует новую функцию getElementsByTagName, которая выдает массив всех элементов с указанным именем тега. Так как нам требуются все элементы TR, то мы просто передаем в функцию 'TR' и получаем список всех элементов TR в таблице. После этого код почти идентичен предыдущей функции.

Работа с текстом

Работа с текстом немного отличается от работы с другими элементами DOM. Первое: каждый фрагмент текста на странице помещен в невидимый узел #TEXT. Поэтому следующий код HTML

<div id="ourTest">this is <a href="link.html">a link</a> and an image: <img src="img.jpg"></div>

имеет четыре корневых элемента: текстовый узел со значением " this is ", элемент A, еще один текстовый узел со значением " and an image: " и, наконец, элемент IMG. Элемент A имеет конечный текстовый узел в качестве потомка со значением " a link ". Когда необходимо изменить текст, то прежде всего необходимо получить этот "невидимый" узел. Если мы хотим изменить текст " and an image: ", то необходимо написать:

document.getElementById('ourTest').childNodes[2].nodeValue = 'our new text';

document.getElementById('ourTest') дает нам тег div. childNodes[2] дает узел текста " and an image: " и наконец nodeValueизменяет значение этого узла текста.

Что, если требуется добавить к этому еще текст, но не в конце, а перед " a link "?

var newText = document.createTextNode('our new text');var ourDiv = document.getElementById('ourTest');ourDiv.insertBefore(newText, ourDiv.childNodes[1]);

Первая строка показывает, как создать текст с помощью document.createTextNode. Это аналогично функции использованной ранее функции document.createElement. Третья строка содержит еще одну новую функцию insertBefore, которая аналогична appendChild, за исключением того, что имеет два аргумента: добавляемый элемент и существующий элемент, перед которым надо сделать вставку. Так как мы хотим добавить новый текст перед элементом A и знаем, что элемент A является вторым элементом в div, то мы используем ourDiv.childNodes[1] в качестве второго аргумента для insertBefore.

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

 

1.7. Объект документа и объект окна.

Объект document представляет реальное содержимое страницы и поэтому имеет функции, которые помогают изменить саму страницу. Например, запись на странице происходит с помощью document.write, а обращение к форме - с помощью document.forms.

Как упоминалось в "шестой лекции" , каждый объект на странице является потомком или предком какого-то другого объекта. Все это представляет большое дерево. Объект window - корень этого дерева, а все остальное находится на нем. Объект window указывает на реальное окно браузера. Если требуется, например, открыть новое окно или изменить размер текущего, то для этого используются функции объекта window.

Объект window, кроме того, что находится в вершине DOM, является также глобальным объектом. Во "второй лекции" мы говорили о том, что любая переменная обладает глобальной или локальной областью действия. Если она имеет глобальную область действия, то она доступна в любом месте сценария JavaScript. Обладание глобальной областью действия означает также, что переменная соединена непосредственно с объектом window. Любой код JavaScript, который не находится внутри какой-то функции, находится в глобальном объекте window.

В связи с этим не требуется писать window при обращении к функциям или переменным объекта window, как в случае использования некоторых других функций, таких, как document.getElementById. alert() является примером функции, которую можно вызвать либо как window.alert(), либо просто alert().

Объект Window

Прежде всего объект window предоставляет доступ к информации об окне:

Свойство Описание
window.location возвращает текущий URL окна
window.opener Если окно было открыто другим окном (с помощью window.open ), то возвращается ссылка на открывающее окно, иначе null
MSIE: window.screenTopДругие: window.screenY Возвращает верхнюю позицию окна. Отметим, что эти значения в MSIE существенно отличаются от других браузеров. MSIE возвращает верхнюю позицию области содержимого (ниже адресной строки, кнопок, и т.д.). Другие браузеры возвращают верхнюю позицию реального окна (выше кнопки закрытия)
MSIE: window.screenLeftДругие: window.screenX Возвращает левую позицию окна с такими же различиями, как и для screenTop и screenY

Положение окна на экране пользователя редко бывает необходимо, но два других свойства, location и opener, будут очень полезны. Свойство window.location выполняет две функции. Если изменить его с помощью JavaScript, например, window.location='http://www.htmlgoodies.com', то браузер будет перенаправлен на эту страницу. Чтение window.location выдает адрес текущего документа. Зачем это нужно знать? Обычно адрес страницы не нужен, но может потребоваться строка запроса или анкер. Возьмем, например, следующий URL:

http://www.somesite.com/page.asp?action=browse&id=5#someAnchor. Этот URL можно разбить на три части:

URL: http://www.somesite.com/page.asp
Строка запроса: action=browse&id=5
Анкер: someAnchor

Так как window.location содержит всю эту информацию, то можно написать функцию, которая будет возвращать переменную querystring (строку запроса). Это аналогично request.querystring в ASP или $_GET в PHP, если вы знакомы с каким-либо из этих языков:

function queryString(val){ var q = unescape(location.search.substr(1)).split('&'); for(var i=0; i<q.length; i++){ var t=q[i].split('='); if(t[i].toLowerCase()==val.toLowerCase()) return t[1]; } return '';}

Для предыдущего URL функция queryString('action') вернет 'browse'. Мы видим здесь новую функцию window.unescape. Функция unescape, а также ее дополнительная функция escape, используются в соединении с window.location. При передаче данных в строке запроса она должна быть экранирована (escaped), чтобы она не влияла на саму строку запроса. Если, например, среди данных имеется знак амперсанд ( & ), то необходимо его экранировать, чтобы можно было различить этот знак в данных и тот &, который разделяет два различных значения. Функция escape подготавливает посылаемые данные для использования в качестве значения querystring, поэтому она используется при задании window.location. Например:

window.location='/page.asp?name='+escape(SomeInputBox.value);

Функция unescape делает обратное и позволяет получить "нормальный" текст из window.location.

Вернемся к свойствам window, где имеется свойство opener. Это свойство используется в соединении с обычно используемой функцией window.open, которая позволяет открывать новое окно браузера и, для некоторых свойств управлять его выводом. Блокировщики всплывающих окон очень часто будут препятствовать открытию окна с помощью window.open, если в этот процесс не вовлечен щелчок мышью. Поэтому, если в коде имеется вызов window.open и при этом пользователь не щелкает на ссылке или чем-то подобном, то скорее всего это не будет работать.

Функция window.open получает до 3 аргументов: URL окна, которое надо открыть, имя окна и свойства окна.

var newWindow=window.open('', 'newWindow', 'окно будет закрыто через 2 секунды');setTimeout(function(){ newWindow.close(); }, 2000);

Третий аргумент window.open получает строку аргументов. Обычно используются следующие:

· width, height - задают размеры окна;

· left, top - задают положение окна на экране;

· location, menubar, toolbar, status, titlebar, scrollbars - эти параметры выводят/скрывают свои соответствующие "панели" на окне. Задайте yes, чтобы вывести соответствующую "панель";

· resizable - если задан как yes, то размер окна можно изменять.

Полное описание window.open можно увидеть в документации Mozilla.

Так как мы открываем пустое окно, то первый аргумент будет пустым. Для открытия страницы 'test.html' вызов выглядел бы следующим образом: window.open ('test.html', 'TestWindow', '

В этом примере для объекта window, открываемого окна, задается переменная newWindow. В связи с этим для вывода содержимого в окне необходимо использовать newWindow.document.write.

Функция window.open также имеет свою противоположность, функцию window.close. Однако эта функция может успешно вызываться только на окнах, созданных JavaScript. Если попробовать закрыть окно, созданное не JavaScript, то возможны два варианта: либо появится сообщение, говорящее, что сценарий пытается закрыть окно, либо браузер просто это проигнорирует.

SetTimeout и setInterval

Можно видеть, что в этом примере используется еще одна новая функция setTimeout. Функции setTimeout и setInterval применяются для выполнения кода после указанного интервала времени и обе получают два аргумента: функцию или строку кода и период ожидания в мс. 1 мс = 1/1000 секунды, поэтому для задания выполнения кода через 5 секунд необходимо определить в этом случае для второго аргумента значение 5000.

setTimeout выполнит код один раз после завершения заданного интервала времени. setInterval будет продолжать выполнять код после завершения каждого интервала. При заданном интервале 5000 setInterval будет выполнять код каждые 5 секунд.

Существуют еще две другие функции: clearTimeout и clearInterval, которые отменяют выполнение, через заданные интервалы. Однако для этого необходимо иметь ссылку на вызов setTimeout или setInterval, например:

var myTimeout = setTimeout("alert('Hi!');", 500);clearTimeout(myTimeout);

Если не сохранить ссылку в переменной myTimeout, то не существует способа отменить заданное выполнение. Давайте посмотрим на пример этого в действии:

function createTimeout(text, time){ setTimeout("alert('"+text+"');", time);} var intervals = [];function createInterval(text, time){ // сохраняет интервал в массиве intervals   intervals.push(setInterval("alert('"+text+"');", time));} function tut5(){ if(intervals.length==0) return; // удаляет последний интервал выполнения в массиве intervals   clearInterval(intervals.pop());} Демонстрация в действии Текст для вывода: Время ожидания(в мс): setTimeout setInterval clearInterval

Существует также функция clearTimeout, которая идентична по синтаксису clearInterval.

Важно отметить, что во время ожидания выполнения заданного кода функциями setTimeout или setInterval весь остальной код JavaScript продолжает выполняться. Когда функция setTimeout или setInterval будет готова, она выполнит заданный код, но только после того, как другой код закончит выполнение. Другими словами, setTimeout и setInterval никогда не прерывают для выполнения другой код.

Window.opener

Как говорилось ранее, свойство окна 'opener' можно использовать для доступа к окну, которое открыло текущее окно, а также к любым свойствам, функциям и т.д. этого окна. Например:

<!--page1.html--><HTML><HEAD><script type="text/javascript">window.open('page2.html', 'TestWindow', 'type="text/javascript">document.write('URL окна предка будет : '+window.opener.location);</script></HEAD></HTML>

Отметим, что это работает, только если URL открываемого окна находится на том же сервере, что и текущая страница. Если необходимо открыть, например, окно на http: //www.webreference.com, то мы не получим доступ к свойствам этого окна. Это поддерживается всеми основными браузерами по соображениям безопасности.


Дата добавления: 2018-08-06; просмотров: 204; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!