{Управление на събития}

Списък с най-често използваните събития при действие с мишката:

  • click – when the mouse clicks on an element (touchscreen devices generate it on a tap).
  • contextmenu – when the mouse right-clicks on an element.
  • mouseover / mouseout – when the mouse cursor comes over / leaves an element.
  • mousedown / mouseup – when the mouse button is pressed / released over an element.
  • mousemove – when the mouse is moved.

В този урок ще научим как да задействаме JavaScript функция, която да се изпълнява, когато потребителят направи нещо, като например кликне върху бутон. Това ще ни позволи да променим HTML страницата в отговор на действията, предприети от потребителя на уебсайта.
Кликването върху бутон от потребителя е един от многото видове събития, поддържани от JavaScript.

Пример: промяна цвета на фона на страницата


* ще създадем страница с елемент бутон;
* ще напишем javascript функция, която променя свойствата на тага <body>;
* ще свържем бутона с функцията.

  1. Създаване на страница с бутон
<html>
    <head>
        <meta charset="utf-8">
        <title>Events</title>
    </head>
    <body style="background: lightgreen;">
        <b style="font-size: 40px;">
            Всичко забавно в живота е неморално, нелегално или те прави дебел.
        </b>
        <p>
            Винаги съветвам хората никога да не дават съвети... <br />
            Това е животът – постоянна поредица от неразбирателства и прибързани действия.<br />
            <i>П. Г. Удхаус</i>
        </p>
        <button>
            Toggle background color
        </button>
    </body>
</html>

2. Javascript функция
Забележка: каква е разликата между bodytag.style.backgroundColor и bodytag.style.background? (console.log(bodytag.style.backgroundColor), console.log(bodytag.style.background))
Защо при проверката използваме bodytag.style.backgroundColor?

<script>
    function togglebackgroundcolor() { 
        let bodytag = document.body;
        let bgrColor = bodytag.style.backgroundColor;
        if (bgrColor === 'green')
                bodytag.style.backgroundColor = 'beige';
        else if (bgrColor === 'beige')
                bodytag.style.backgroundColor = 'green';
     }
</script>

3. Свързване на бутона с функцията

<button onclick="togglebackgroundcolor()">

Манипулатори на събития (Event Handlers)

За да реагираме на събития, можем да използваме манипулатори – функции, които се изпълняват в случай на събитие.
Манипулаторите са начин да се изпълни Javascript код при потребителско действие.
Има няколко начина за указване на манипулатор:

1.Inline event handlers (Вградени манипулатори на събития)

Манипулаторът може да бъде зададен в html като атрибут с име on<event>

<input value="Click me" onclick="alert('Click!')" type="button">

Важно е да се отбележи, че в рамките на html, onclick използва двойни кавички, а функцията единични. Вариантът onclick=“alert(„Click!“)“ няма да работи!

HTML атрибутите не са удобно място за писане на много код, така че по-добре да създадем JavaScript функция и да я извикаме от атрибута.

<script>
  function countRabbits() {
    for(let i=1; i<=3; i++) {
      alert("Rabbit number " + i);
    }
  }
</script>

<input type="button" onclick="countRabbits()" value="Count rabbits!">

Тъй като html атрибутите не са чувствителни към малки и главни букви, ONCLICK ще работи добре както и onClick или onCLICK, но обичайно е манипулатора да се изписва с малки букви.

2.DOM on-event handlers(DOM манипулатори на събития)

on<click> e свойство в DOM. Можем да го изпозлваме например като: element.onclick

<input id="elem" type="button" value="Click me">
<script>
  elem.onclick = function() {
    alert('Thank you');
  };
</script>
window.onload = () => {
  //window loaded
  document.body.style.backgroundcolor = '#00ff00';
}

Ако манипулаторът е назначен с помощта на HTML атрибут, браузърът го чете, създава нова функция от съдържанието на атрибута и го записва в свойство на DOM. Така че този начин е същият като предишния.

Манипулаторът е винаги в свойство на DOM. HTML атрибутът е само един от начините за неговото инициализиране.

Следните две части от код, работят по един и същи начин:

//само html
<input type="button" onclick="alert('Click!')" value="Button">

//html + js
<input type="button" id="button" value="Button">
<script>
  button.onclick = function() {
    alert('Click!');
  };
</script>

Тъй като има само едно свойство onclick, не можем да зададем повече от един манипулатор. Добавянето на втори манипулатор, презаписва съществуващият такъв. В следващият код ще се изпълни само alert(‘After’):

<input type="button" id="elem" onclick="alert('Before')" value="Click me">
<script>
  elem.onclick = function() { // overwrites the existing handler
    alert('After'); // only this will be shown
  };
</script>

3.addEventListener()

Това е най-популярния и модерен метод. За разлика от предходните два метода, той позволява да се свържат няколко манипулатора към едно и също събитие.

Синтаксис: element.addEventListener(event, handler[, phase]);

event – име на събитието, например „click“
handler – функцията(манипулатора), която ще се изпълни ако настъпи събитието
phase – незадължителен параметър. Булева променлива. Определя режима, в който ще се изпълнява манипулатора.

  • true – манипулатора се изпълнява в capturing режим
  • false- Default. Манипулатора се изпълнява в bubbling режим

bubbling режим: Когато дадено събитие се случи на даден елемент, първо се изпълняват манипулаторите върху него, след това върху неговия родител, след това по целия път до други предци.
capturing режим: манипулаторите се изпълняват от родителския елемент, към наследниците.

Пример
Ако кликнем върху параграфа (в следващия код):

  1. HTML → BODY → FORM → DIV → P (capturing phase)
  2. P → DIV → FORM → BODY → HTML (bubbling phase)
<html>
    <head>
        <meta charset="utf-8" />
        <title>addEventListener</title>
        <style>
          body * {
                  margin: 10px;
                  border: 1px solid blue;
          }
        </style>
    </head>
    <body>
        <form>FORM
            <div>DIV
              <p>P</p>
            </div>
        </form>
        <script>
            for(let elem of document.querySelectorAll('*')) {
              elem.addEventListener("click", function(){ alert(`Capturing: ${elem.tagName}`)}, true);
              elem.addEventListener("click", function(){ alert(`Bubbling: ${elem.tagName}`)});
            }
        </script>
    </body>
</html>

Служебната дума this.

this е запазена дума в javascript. Тя служи за обръщение към текущия HTML елемент. Например:

<p onmouseover="doSomething(this)">
    ...
</p>
...
<script>
    function doSomething(element) {
        ...
    }
</script>

Когато мишката се премести над елемента <p>, тя извиква функцията doSomething () и препраща собствената си референция като параметър към функцията. Това е полезно, когато желаем да използваме една и съща JavaScript функция за редица HTML елементи. Можем да прехвърлим същата функция с ключовата дума this.

Нека видим как можем да използваме ключовата дума this.

Ще създадем нова страница със списък от 5 <b> елемента. Целта е, когато мишката се позиционира върху някой от тях, той да промени размера на шрифта и цвета си.

<html>
    <head>
        <title>Changing styles of multiple elements</title>
        <script>
            function doSomething(element, flag) {
                
            }
        </script>
    </head>
    <body style="font-size: 20px;">
        <b onmouseover="doSomething(this, true);" onmouseout="doSomething(this, false);">One</b><br>
        <b onmouseover="doSomething(this, true);" onmouseout="doSomething(this, false);">Two</b><br>
        <b onmouseover="doSomething(this, true);" onmouseout="doSomething(this, false);">Three</b><br>
        <b onmouseover="doSomething(this, true);" onmouseout="doSomething(this, false);">Four</b><br>
        <b onmouseover="doSomething(this, true);" onmouseout="doSomething(this, false);">Five</b><br>
    </body>
</html>

Функцията doSomething () има два параметъра – element и flag.
element е елементът, чиито стилове трябва да бъдат променени
flag е булева променлива. Ако flag==true, ще увеличим размера на шрифта и ще сменим цвета с червен. Ако flag==false, ще отменим тези промени.

function doSomething(element, flag) {
    if (flag) {
        element.style.fontSize = "30px";
        element.style.color = "red";
    } else {
        element.style.fontSize = "20px";
        element.style.color = "black";
    }
}

Задача 1. Използвайки кода, напишете скрипт, който при натискане на бутона променя шрифта, големината му и цвета на текста. При повторно натискане, да възстановява началните стойности на текста.

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS DOM paragraph style</title>
<style>
  p{
    font-size: 20pt;
    color: black;
    font-family: Tahoma;
  }
</style>
</head> 
<body>
<p id ='text'>JavaScript Exercises</p> 
<div>
<button id="jsstyle" onclick="js_style()">Style</button>
</div>
</body>
</html>

Задача 2. Да се напише скрипт, който вмъква елемент <h1> в елемента <div id=“wh“> на страницата и изписва в него височината и ширината на прозореца на браузъра в реално време.

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Window Size : height and width</title>
</head>
<body>
<div id="wh"> 
<!-- тук поставете размерите на прозореца в таг <h1> --> 
</div>
</body>
</html>

Задача 3. Създайте страница по шаблона, показан на кртинката. Бутона „Добави секция“ създава блок с текст (елемент <h6>) „Добави съдържание“ в страницата. При щракване върху текста, се създава допълнително текстово съдържание (елемент <p>) в новосъздадения блок.

Задача 4. Елементарен калкулатор. За назначаване на манипулаторите да се използва метода addEventListener().

Задача 5. Текстов редактор.
Упътване: Припомнете си HTML <textarea></textarea>. За стилизиране да не се използват таблици.

Задача 6. Редактирайте функциите свързани с бутони Bold, Italic и Color Blue от задача 5, така че след като е приложен стила, при повторно използване на съответния бутон, да отменя само неговото действие. Стилизирайте бутоните така, че да е видно кой от тях е използван върху текста.

Скриване на елемент

Ще разгледаме две свойства на стила, които заслужават специално внимание – display и visibility.
Ако display е настроен на none, елементът се премахва от страницата. display = none, премахва елемента от страницата и пространството, което е използвал, се попълва от елементите след него.
Свойството visibility може да бъде зададено като скрито или видимо, за да се скрие или покаже елемент.
visibility = hidden само скрива елемента, елементът все още заема същото пространство.

Нека в примера за смяна цвета на фона на страницата от началото на урока добавим функционалност, която заедно с промяна цвета на фона, скрива заглавното изречение. Ще добавим няколко реда в скрипта:

var btag = document.getElementsByTagName("b")[0];
btag.style.visibility = "hidden";
btag.style.visibility = "visible";

Скриптът сега изглежда така:

<script>
  function togglebackgroundcolor() { 
     let bodytag = document.body;
     let bgrColor = bodytag.style.backgroundColor;
     let btag = document.getElementsByTagName('b')[0];
     if (bgrColor === 'green'){
         bodytag.style.backgroundColor = 'beige';
         btag.style.visibility = "hidden";
     }
     else if (bgrColor === 'beige'){
         bodytag.style.backgroundColor = 'green';
         btag.style.visibility = "visible";
     }
   }
</script>

addEventListener

Основният проблем на посочените по-горе начини за задаване на манипулатори е, че не можем да зададем няколко манипулатора на едно събитие.

input.onclick = function() { alert(1); }
// ...
input.onclick = function() { alert(2); } // ще замени предходния манипулатор
Реклами