return к функциям (функции и события)
Данный раздел подразумевает, что мы вернемся к функциям и найдем им применение в событиях. Помните, следующий пример:
<html>
Видите, какой не наглядный, хотелось бы его немного сократить. Мы сможем это сделать при помощи функций, ведь это мы еще не разучились делать, а вызов функции это ведь тоже JS код и мы его можем писать в соответствующем событии. Давайте сделаем функцию, которая будет изменять поле ввода следующим образом: если оно заполнено, стандартным текстом, то этот текст будет удален. В остальных случаях ничего не произойдет:
function clean() { if (element.value == 'Введите текст') {
А теперь напишем функцию, которая будет делать все наоборот: выводить текст в текстовом поле, если оно не заполнено и предлагать заполнить его:
function fill() { if (element.value == '') {
Да, а теперь давайте привяжем данные функции к определенным событиям на странице, и это будет проще простого:
<html> if (element.value == 'Введите текст') { function fill() { if (element.value == '') {
Видите, как все стало намного проще. При загрузке страницы загружается текст, а при нажатии на текстовое поле он исчезает. А как реализуется вывод текста описано в блоке нашего скрипта. Теперь наша задача состоит в том, чтобы сократить наш код. Во-первых, мы можем воспользоваться this вместо document.getElementById. Но помните, что this создается в момент события, но не в самом обработчике-функции, поэтому this нужно передать внутрь функции. Посмотрите, как это нужно делать и возьмите себе на заметку:
<html> function fill(element) {
Единственное, что нужно сказать, это то, что в событии onLoad нельзя писать this, потому что this будет ссылкой на body, а нам нужно передать элемент text, который мы сможем получить при помощи document.getElementById.
Помните, как мы начинали тему функций: функции используются тогда, когда нужно упростить код, к примеру, если он повторяется. Если заметить, то в данном коде такое случается, при изменении свойств. Поэтому все это можно вынести в отдельную функцию. К тому же текст типа 'Введите текст' повторяется два раза и если его придется изменить не целесообразно его менять в двух местах. Лучше всего создать переменную и пользоваться значением этой переменной везде. Помните, что использовать глобальную переменную внутри функции мы можем, если не создать внутри этой функции при помощи var другую переменную. Давайте сделаем все эти изменения:
<html>
function fill(element) {
Не на много стал код меньше, но зато намного понятнее, если конечно вы в совершенстве разобрались, зачем нам нужны функции. Если же вы этого не сделали, то самое время вам это начать.
4. Еще один пример использования функций и событий
В прошлом уроке мы написали классную функцию, которая прячет элемент и показывает его, если он уже спрятан, вот она:
function toggle(elementid) {
Как вы думаете можно ли эту функцию привязать к какому-либо событию? Конечно можно. К примеру, можно заставить что-то исчезать, нажав на кнопку и появляться, нажав на ту же самую кнопку. Давайте сделаем панель, которая будет появляться, когда мы будем нажимать на кнопку. Мы сразу напишем пример и не будем его разбирать по кускам, вам нужно будет просто разобрать HTML код. А куда будет привязана данная функция и как она работает это уже должно быть понятно каждому.
<html> В этой панели вы можете разместить все, что захотите.<br>И она будет поверх всего содержимого.
</div> <span onClick="javascript: toggle('panel');">Всплывающая панель</span> </div> </div>
Самое главное – это красиво оформить страницу при помощи CSS, а эффект JS не так уж и много занимает места. И как заметили это эффект работает не так уж и сложно.
При помощи этой функции так же можно сделать и всплывающее меню. Точно так же как и в предыдущем случае, нужно красиво это меню оформить, а прицепить код выполнения – это проще простого: заставить появляться меню, когда мы наводим на пункт меню, и исчезать, когда мы от него теряем фокус. Давайте мы попробуем реализовать меню в виде списков:
<html> Видите, и опять как всегда все дело в стилях CSS, а само меню просто либо исчезает, либо появляется при помощи нашей магической функции toggle. Забавно. Так же вы можете самостоятельно сделать третий уровень меню и т.д. Кстати, если появиться еще одно выдвижное меню ему нужно давать новый идентификатор, потому что, во-первых, не может на странице присутствовать несколько идентификаторов, а во-вторых, если бы даже это было допустимо, то эти две меню одновременно скрывались и появлялись. А если вы укажете два идентификатора одинаковых, то функция document.getElementById будет находить только первый элемент с этим именем.
Если вы еще до сих пор не умеете управляться с CSS стилями, то самое время научиться это делать, а то кроме написания бесполезного кода вы ничего не добьетесь.
5. События и его свойства (Event)
В момент возникновения любого события иногда нужно прослеживать некоторые вещи, к примеру, кто вызвал это событие, в каком месте была нажата клавиша мыши, какая клавиша клавиатуры была нажата и т.д. За этим следит некий объект, который создается в момент возникновения события. Этот объект имеет имя Event. Внутри этого объекта есть несколько переменных, которые хранятся внутри объекта и чтобы обратиться к ним, нужно написать Event, затем точку, а потом написать имя переменной, которая хранит информацию о событии. Такие записи мы уже встречали, например, через точку мы обращались к свойствам стилей элемента.
В следующем примере на экран выводится некое изображение. Вы можете щелкнуть где-нибудь над ним клавишей мыши. В результате появится окошко сообщений, где будут показаны координаты той точки, где в этот момент находилась мышь. Код скрипта:
<layer>
Как видите, в тэг <a> мы поместили программу обработки событий onClick, как это мы уже делали в предшествующих версиях JavaScript. Новое здесь заключается в том, что для создания окошка с сообщением мы используем event.x и event.y. А это как раз и есть объект Event, который здесь нам нужен, чтобы узнать координаты мыши. К тому же мы поместили все команды в тэг <layer>. Благодаря этому мы получаем в сообщении координаты относительно данного слоя, т.е. в нашем случае относительно самого изображения. В противном же случае мы получили бы координаты относительно окна браузера. (инструкция return false; используется здесь для того, чтобы браузер не обрабатывал далее данную ссылку)
Объект Event получил следующие свойства (их мы рассмотрим в следующих примерах), кстати, не все свойства одинаково отображаются во всех браузерах, поэтому в таблице собраны свойства для двух типов браузеров:
Лучше всего использовать свойства, которые и работают и там и там, но в большинстве случаев так и выходит, потому что другие свойства очень редко используются.
Теперь мы можем получать подробную информацию в тот момент, когда происходит событие. Понятно, что не все свойства будут активны, когда возникнет событие, например, код нажатой кнопки не будет в событии onLoad и событии onMouseOut. В общем, по сути это логично.
5.1. Передача объекта Event внутрь обработчика события
Объект действительно создается в момент возникновения события и его нужно передавать внутрь обработчика так же, как и ссылку this, но вся проблема в том, что в IE все работает не так. В IE объект создается внутри обработчика и имеет имя window.event, но с этим легко бороться. Давайте рассмотрим это наследующем примере, заодно и проверим некоторые свойства объекта Event:
<html> //Записываем координаты мыши
Вместо clientY вы можете использовать другие координаты мыши, заодно посмотреть, чем они отличаются. Только желательно использовать их для конкретных блоков на странице, если они у вас есть.
Давайте кратко рассмотрим некоторые свойства объекта Event.
5.2. Всплывание события cancelBubble
"Всплыванием" события (bubble) называют процесс передачи события от дочернего элемента к родительскому после его обработки. В пример можно поставить ссылку на сайте – если вы на нее нажмете, то должно сработать событие onClick для ссылки и событие onClick для всех элементов, которые находятся под этой ссылкой, даже для элемента body. То есть, после того, как некоторый элемент обработает событие, оно будет передано на обработку родительскому элементу. Таким образом, событие как бы поднимается по дереву элементов вверх – всплывает. Рассмотрим этот процесс на примере:
<html>
Как следует из кода примера, на странице три элемента (<body> и два элемента <div>) обрабатывают событие одного и того же типа – onclick. При этом для его обработки они используют одну функцию – clickHandler(elem), которая меняет фоновый цвет переданного ей элемента на зеленый и выдает сообщение методом alert(). Элемент, который требуется перекрасить, передается функции обработки посредством внутреннего указателя this. Таким образом, при вызове функции clickHandler(this) для некоторого элемента, this будет указывать на сам элемент. Чтобы увидеть процесс всплывания события щелкните мышью на внутреннем прямоугольнике страницы. После щелчка он окрасится в зеленый цвет и будет выдано сообщение "Нажмите 'Ок' для продолжения". Процесс повторится для внешнего прямоугольника, а, затем, и для всей страницы. Если же щелкнуть сразу на внешнем прямоугольнике, то вы увидите уже два сообщения, а центральный прямоугольник останется неизмененным. В ряде случаев всплывание события дает нежелательный эффект и его требуется запретить. Для этого необходимо присвоить значение true свойству cancelBubble объекта event:
event.cancelBubble = true;
Перепишем пример с использованием свойства cancelBubble:
<html>
Теперь событие не всплывает и при каждом клике на элементе перекрашивается именно тот элемент, по которому вы кликнули, и событие не распространяется на элементы, находящиеся под этим элементом.
Это свойство редко когда может пригодиться, но необходимо знать, что оно есть.
5.3. Вызов стандартного обработчика
Существует ряд элементов в HTML, для которых определены некоторые обработчики событий по умолчанию или стандартные обработчики. Так для элемента <a> (гиперссылка) определен обработчик onСlick выполняющий переход на ресурс, заданный атрибутом href. Если вы желаете, чтобы после вашей обработки некоторого события стандартный обработчик не вызывался, присвойте значение false свойству returnValue объекта event.
<html>
Помните, что то же самое мы могли сделать и при помощи return false. Зачем же нам эта конструкция? Все дело в том, что return false не работает внутри функции-обработчика, и отменить действия стандартного обработчика внутри функции мы не сможем простым return false.
Давайте рассмотрим следующий пример:
<html>
Разберем пример по порядку. На странице расположена гиперссылка на web-узел Google. При щелчке на гиперссылке будет вызван обработчик события click – clickHandler, в который мы передаем объект Event и указатель на текущий элемент. Внутри обработчика вызывается функция confirm, в зависимости от кнопки, нажатой пользователем в диалоговом окне, будет возвращено значение true или false, которое будет присвоено переменной e.returnValue. Эта переменная отвечает за работу стандартного обработчика. Соответственно, если пользователь нажмет отмену, то по ссылке мы не перейдем. Таким образом, переход по гиперссылке осуществляется только в том случае, если пользователь согласится с переходом. В принципе то же самое мы можем сделать и при помощи return false, но этот вариант будет предпочтительнее, потому что всю оюработку мы ведем в функции-обработчике. 5.4. Практика работы с мышью: перетаскивание элементов
Как любой уважающий себя web разработчик, вы, наверняка стремитесь сделать свои страницы приятными для пользователей. Это означает, что, наряду с приятным оформлением, ваша страница должна обладать еще и дружественным к пользователю интерфейсом. Последним "писком" в этой области является технология перетаскивания объектов мышью – Drag and Drop. Предлагаемый для рассмотрения пример демонстрирует минимально функциональную версию реализации технологии перетаскивания объектов мышью. Это учебный пример, на базе которого, я надеюсь, вы сможете создавать собственные, более продвинутые, решения.
Предупреждение: Этот пример может показаться сложным, но постарайтесь вникнуть в то, как он работает. В дальнейшем мы сможем делать то же самое намного легче, но все равно нам нужно понять, как это можно реализовать стандартными способами.
Для начала зададимся вопросом, какие события мы будем обрабатывать для перетаскиваемого элемента? Во-первых, элемент нужно "схватить" мышью – то есть, нажать на нем левую кнопку мыши. Значит, событие "mousedown" необходимо отрабатывать. Так же дело обстоит и с "отпусканием" элемента. К списку обрабатываемых событий добавляем "mouseup", в тот момент, когда мы его отпускаем. Осталось событие перемещения курсора мыши – "mousemove", при котором мы будем менять позицию перетаскиваемого элемента. Итак, с событиями мы решили. Теперь разберемся с самими элементами. Дело в том, что задавать координаты элементов (left и top) можно только для абсолютно позиционируемых (в нашем случае) элементов. Значит – в стилевое оформление перетаскиваемых элементов должна входить строка "position: absolute;". Ниже приводится полный код примера. Обратите внимание на следующую особенность: события mousedown и mouseup обрабатываются для перетаскиваемого элемента, а событие "mousemove" – для элемента <body>. Это связано с тем, что при резком рывке курсора мы рискуем выскочить за пределы перетаскиваемого элемента и "уронить" его. Т.е. нам нужен элемент, который всегда будет следить за движением мыши, т.е. самый большой элемент – body.
<html>
После выполнения примера, вы столкнетесь (или уже столкнулись) с "маленькой" неприятностью: при "захвате" элемента его верхний левый угол "прыгает" в позицию курсора. В некоторых браузерах после этого отцепиться от элемента не представляется возможным иначе, как перезагрузкой страницы.
Исправим этот недостаток. Для этого будем при "захвате" элемента запоминать смещение курсора относительно верхнего левого угла перетаскиваемого элемента в глобальных переменных. Информация о смещении курсора хранится в свойствах offsetX и offsetY объекта event для IE и некоторых других браузерах, но для FF те же данные хранятся в свойствах layerX и layerY, которые не работают в IE. Соответственно для смещения по оси X мы используем свойство или offsetX или layerX, если они есть следующей записью: offX = e.layerX || e.offsetX, аналогично и для оси Y. Смотрим пример:
<html>
Итак, наш сценарий добросовестно реализует поддержку перетаскивания элементов мышью. Как вы и сами могли убедиться, ничего особенно сложного в этом нет. Надеюсь, пример вам понравился и вам не составит особого труда модифицировать алгоритм его работы для ваших собственных нужд.
Вот такой, мир событий JavaScript. Вам необходимо понять, что без событий и функций JavaScript станет скучным и неинтересным, ведь всякие визуальные эффекты можно делать только при помощи событий и функций. 6. Функции (нюансы)
Итак, события мы рассмотрели полностью, но в функциях существует множество нюансов, поэтому следующая тема будет посвящена именно им.
6.1. Знакомство с рекурсией. Рекурсия – это прием программирования, при котором программа вызывает саму себя либо непосредственно, либо косвенно. Как правило, неопытный программист, узнав про рекурсию, испытывает легкое недоумение. Первая мысль – это бессмысленно!!! Такой ряд вызовов превратиться в вечный цикл, похожий на змею, которая съела сама себя, или приведет к ошибке на этапе выполнения, когда программа поглотит все ресурсы памяти. Однако рекурсия – это превосходный инструмент, который при умелом и правильном использовании поможет программисту решить множество сложных задач.
Пример на рекурсию Исторически сложилось так, что в качестве первого примера на рекурсию почти всегда приводят пример вычисления факториала. Мы уже это делали при помощи циклов. Что ж, не будем нарушать традиций. Для начала, вспомним, что такое факториал. Обозначается факториал восклицательным знаком «!» и вычисляется следующим образом: N! = 1 * 2 * 3 * … * N
Другими словами, факториал представляет собой произведение натуральных чисел от 1 до N включительно. Исходя из вышеописанной формулы, можно обратить внимание наследующую закономерность: N! = N * (N-1)!
Ура!!! Мы можем найти факториал через сам факториал! Видите, что, реализуя факториал, внутри него уже есть вызов функции факториала – это и есть рекурсия. Вот здесь мы и попадаемся в ловушку. Наша находка, на первый взгляд, абсолютно бесполезна, ведь неизвестное понятие определяется через такое же неизвестное понятие, и получается бесконечный цикл. Выход из данной ситуации сразу же будет найден, если добавить к определению факториала следующий факт: 1! = 1
Теперь мы можем себе позволить вычислить значение факториала любого числа. Попробуем, например, получить 5!, несколько раз применив формулу N! = N * (N-1)! и один раз формулу 1! = 1: 5! = 5 * 4! = 5 * 4 * 3! = 5 * 4 * 3 * 2! = 5 * 4 * 3 * 2 * 1! = 5 * 4 * 3 * 2 * 1
Давайте, попробуем реализовать рекурсивную функцию, как раз посмотрите, что это:
<html>
Как видите, в момент вызова функции в нее передается значение числа, от которого нужно вычислить факториал. Внутри функции возвращается следующее значение: само число, умноженное на факториал числа меньшего на единицу, что само собой влечет за собой вычисления факториала числа меньшего на единицу. Так будет продолжаться, пока мы не доберемся до единицы, и факториал единицы вернет единицу. Сама же функция вычислит правильное значение факториала.
Рекурсии или итерации? Изучив предыдущий раздел урока – вы наверняка задались вопросом: а зачем нужна рекурсия? Ведь, реализовать вычисление факториала можно и с помощью итераций и это совсем не сложно. Такой алгоритм, наверное, будет более естественным для программистов. На самом деле, это не совсем так. С точки зрения теории, любой алгоритм, который можно реализовать рекурсивно, совершенно спокойно реализуется итеративно. Мы только что в этом убедились. Однако это не совсем так. Рекурсия производит вычисления гораздо медленнее, чем итерация. Кроме того, рекурсия потребляет намного больше оперативной памяти в момент своей работы. Значит ли это, что рекурсия бесполезна? Ни в коем случае!!! Существует ряд задач, для которых рекурсивное решение тонко и красиво, а итеративное – сложно, громоздко и неестественно. Ваша задача, в данном случае – научиться, не только оперировать рекурсией и итерацией, но и интуитивно выбирать, какой из подходов применять в конкретном случае. От себя можем сказать, что лучшее применение рекурсии – это решение задач, для которых свойственна следующая черта: решение задачи сводится к решению таких же задач, но меньшей размерности и, следовательно, гораздо легче разрешаемых. Но если вы не поняли рекурсию – не страшно – всему свое время, ведь рекурсия в JS применяется крайне редко.
6.2. Функция – это переменная. Несколько видов объявлений функций.
Сейчас мы поделимся секретом, что функция на самом деле переменная, которая хранит реализацию функции, а скобки нужны для запуска этой реализации или передачи параметров. Это означает, что если создать новую переменную и присвоить ей содержимое переменной-функции, то мы создадим копию этой функции:
<html>
Видите, что newf стала тоже функцией. Самое интересное, что после объявления функция возвращает свое значение, и мы можем записать тоже самое следующим образом:
<html>
Самое интересное, что в данном случае можно и не задавать имя нашей функции и все будет работать:
<html>
Т.е. с самого начала конструкция function () создает функцию без названия, а затем мы ее присваиваем в переменную newf. Это сделано для того, чтобы мы программно могли присваивать обработчики для событий, не создавая самой функции, вернее не задавая ей имя. В общем это нам пригодиться, но рассмотрим эти свойства немного позже.
6.3. Функция внутри функции
Мы уже убедились, что функция – это всего лишь переменная, которая хранит программный код, который выполняется в момент его вызова. А помните, что такое область видимости для переменной? Область видимости нам дает понять, что создав переменную внутри функции, мы ее будем видеть только внутри этой функции. Как вы думаете, а если мы создадим переменную-функцию внутри другой функции? Правильно, мы ее сможем вызвать только внутри этой функции:
<html>
Видите, что вторая функция, которая объявлена внутри первой, вызывается только внутри этой функции, во внешней программе ее вызвать невозможно. Это понятно из правил области видимости. Эту конструкцию никогда не употребляют, хотя это делать можно. Возможно, вы найдете этой конструкции применение.
6.4. Условная функция Точно так же, можно создавать функции внутри условных операторов. Думаю следующий пример не нужно комментировать:
<html> var func;
Объявление функций внутри условных операторов нам тоже не пригодиться, но если вы этому найдете применение, то значит, не зря эту конструкцию реализовали в JavaScript. 7. Самостоятельное задание:
В этом уроке было реализовано всплывающее меню, попробуйте сделать меню из трех уровней, в котором первый уровень – это горизонтальное меню, второй уровень – выдвижное вертикальное меню снизу, третий уровень – выдвижное вертикальное меню слева. Т.е. наведя на первый уровень меню – снизу выпадает список меню следующего уровня, а наведя на пункт меню второго уровня – выпадает меню слева третьего уровня. Если вам задача покажется легкой, то реализуйте выбор, как будет выглядеть меню первого, второго и третьего уровня: какое расположение (вертикальное или горизонтальное) и откуда выпадает меню (слева или снизу). Эти данные вы можете указать в переменные вначале скрипта, и в зависимости от этих переменных будет производиться вывод соответствующих пунктов меню. Приложение. Шпаргалка (события JavaScript)
В JavaScript определен ряд событий, связанных с элементами документа. Обработчики дают возможность организовать реакцию на возникновение событий из сценария. При этом соответствующий обработчик указывается как атрибут элемента HTML-документа; значением этого атрибута является выражение JavaScript. Например:
<div onmouseOver="this.style.bgColor='#CCCCCC'" onmouseOut="this.style.bgColor='
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|