?

Вітаю!

(Натисніть пробіл, щоб продовжити)

Сьогодні ми дізнаємося, як створити інтерактивну галерею зображень за допомогою JavaScript.

(натисніть, щоб переглянути демо)

Структура і зовнішній вигляд галереї (HTML та CSS) уже готові.

(Натисніть тут, щоб переглянути)

Наше завдання буде оживити його, додавши код JavaScript.

До речі, ці слайди приємні, правда? :-) Якщо ви загубитесь в будь-якому місці курсу, натисніть ESC щоб переглянути його повністю. Чи знаєте ви, що всі анімації та переходи між ними закодовані в JavaScript?

Зелений позначає питання для обговорення у групах.

Синій позначає важливу інформацію, яка допоможе нам у вирішенні завдань .

Фіолетовий позначає завдання для спільного виконання.

Наш інструктор(ка) буде постійно стежити за нами і з радістю відповість на всі ваші запитання.

Натиснувши значок запитання у верхньому правому кутку, знайдемо шпаргалку з усіма термінами, які використовуються в цьому курсі.

Чи готові? Тоді ми починаємо!

Робоче середовище

  • Текстовий редактор - до написання нашаго коду. Якщо у вас немає улюбленого, можна встановити Visual Studio Code (також працює на основі JavaScript!)
  • Інтернет-браузер - у вас напевно є улюблений. Якщо у вас його немає, рекомендуємо Chrome.
  • інструменти для розробників - ви вже маєте їх у своєму браузері! Натисніть F12 (Ctrl + Option + I на MacBook), щоб переконатися.

Джерела

Звідси ви завантажите пакет з вихідним кодом

Після розпакування ви знайдете два HTML файли в головній папці - наприклад, файл demo.html, послужить нам прикладом, файл index.html, над ним ми будемо працювати.

Розпакуйте наші джерела та відкрийте demo.html файл у браузері.

Остаточний ефект складається з трьох шарів:

Структура документа

Які елементи відображаються на сторінці?

Картинки, текст, абзаци, заголовки, іконки тощо
- HTML відповідає за все це.

Презентація

Як виглядають окремі елементи?

Розмір, форма, колір, тип шрифту, положення відносно інших елементів - на ці питання відповідає CSS.

Взаємодія з користувачем

Що відбувається на сайті?

Яка взаємодія з користувачем? Що буде тоді? - Для цього потрібен JavaScript - і ми з ним розберемося за мить.

Тепер перейдемо до файлу index.html у своєму браузері.

З яких елементів складається наша галерея? Звідки ми можемо знати, як вони побудовані?

Інструменти розробника!

Майже кожен веб-браузер має потужні інструменти, які допоможуть нам зрозуміти, з чого складається сторінка і як вона працює.

Опція обстеження дозволяє нам переглянути деталі.

Виділення вибраного елемента

Класи, стилі та можливість їх змінювати

Консоль JavaScript


Час для експериментів! Використовуючи ці інструменти, давайте спробуємо взяти клас show з елемента, який його зараз має, і додати його до іншого зображення.

Вийшло? Клас show показує додаткові стилі CSS, тому елемент із цим класом відображається поверх інших.

Якщо вам цікаво, як це працює, наш інструктор(ка) буде радий пояснити це більш точно.

Нашим завданням буде знайти спосіб переключити цей клас за допомогою коду і тим самим автоматично змінювати слайди.

Як комп'ютер знає, що робити?

Давайте напишемо інструкції, необхідні для показу слайда 5.

Ймовірно, виглядає приблизно так:

1. Знайдіть слайд 5 у документі.
2. Додайте йому клас `show`

Нам потрібен об'єкт документа, щоб знайти елементи у document.

Відкрийте інструменти розробника, введіть слово в document консолі і подивіться, що станеться.

Об'єкт document містить всю структуру HTML-файлу. Завдяки цьому ми можемо знайти будь-який елемент документа та змінити його за допомогою коду.

Цікаво, як це працює - читайте згодом: Що таке DOM? - на трюках CSS

Об'єкт document має ряд metod для маніпулювання елементами сторінки. На цьому етапі ми пізнаємо одну з них:

querySelector( стан ) - вибирає перший елемент, який відповідає умовам.

Якщо ви знаєте CSS, це чудово. Селектори в цьому випадку працюють точно так само, наприклад:

// вибирає перший 3-рівневий заголовок
document.querySelector( 'h3' )
// вибирає першу статтю
document.querySelector( 'article' )
// вибирає перший елемент з класу my-class
document.querySelector( '.my-class' )
// вибирає елемент з ID article-1
document.querySelector( '#article-1' ) 

Якщо ви не знаєте CSS, нічого страшного. У інструменті розробника натисніть праву кнопку Копіювати > Копіювати селектор.

Відкрийте консоль і на основі прикладів з попереднього слайда напишіть код, який знайде нам слайд 5.

document.querySelector( '#slide5' )

Те, що ми отримали, є елементом дерева документів. Тепер ми хочемо знайти методи, які додадуть або видалять клас CSS.

Для цього нам допоможуть:

  • classList.add( class-name ) - додає клас з даною назвою,
  • classList.remove( class-name ) - усуває клас з елемента.

Вставимо в консоль код, необхідний для показу слайда 5 - шукаємо його за допомогою querySelector, а потім викликаємо на ньому метод classList.add з назвою класу (у цьому випадку show). Переконуємося, щоб величина літер була відповідна і закінчуємо команду цим символом - ";"

Готові?

document.querySelector( '#slide5' ).classList.add( 'show' );

Працює? Тепер зробимо те ж саме для слайда 4.

document.querySelector( '#slide4' ).classList.add( 'show' );

Код для слайда 4 не запрацював, хоча він побудований практично так само, як і попередній. Будь-які ідеї, чому так сталося?

Треба сховати слайд 5, який прикриває інші.

Давайте напишемо в консолі код, який це зробить.

document.querySelector( '#slide5' ).classList.remove( 'show' );

Супер! Давайте cкопіюємо всі три фрагменти у наш файл gallery.js. Вони будуть нам корисні незабаром при програмуванні навігації.

У нижній частині у нас є 5 білих кнопок. Запрограмуємо кожен з них так, щоб він відображав відповідний слайд.

Ми можемо подивитися на demo.html, щоб побачити, як воно повинно виглядати.

Давайте подумаємо та напишемо словами, як написати наступний алгоритм: коли хтось натискає кнопку 5 мишкою, покажи слайд із цим номером.

Готові?

Ми, мабуть, придумали щось на зразок цього:

1. Знайдіть п'яту кнопку.
2. Перевірте, коли це буде натиснуто.
3. При натисканні на неї виконайте дію::
    3.1. Сховати поточний слайд.
    3.2. Покажіть п'ятий слайд.

Цього разу ми почнемо з кінця. Останні дві інструкції слід виконувати разом, тому нам потрібно знайти спосіб їх зв’язку.

Для цього нам потрібні функції.

Функція це послідовність декількох команд, які утворюють логічне ціле і повинні виконуватись один за одним.

У JavaScript ми можемо будувати функції кількома різними способами, найпростішими з яких є:

function myFunction( ) {
   /* вміст функції */
}

У файлі gallery.js створіть функцію з ім'ям showSlide5. Всередині функції (в тілі функції) додайте код, який показує п'ятий слайд (як це було на попередньому кроці).

function showSlide5( ) {
  document.querySelector( '#slide5' ).classList.add( 'show' );
}

У нас є перша функція! Тепер ми хочемо зв'язати її з кнопкою №5, щоб ця функція виконувалась кожного разу, коли хтось натискає на кнопку.

Ви пам’ятаєте, як нам вдалося знайти певний слайд на попередньому етапі? Як ми можемо зробити те ж саме зараз за допомогою кнопки?

document.querySelector( '#pin5' )

Тепер нам потрібен якийсь метод, який дозволить нам пов’язати нашу функцію з натисканням на цей елемент.

Усі елементи документа мають цей метод, і це:

  • addEventListener( подія, action-to-execute ) - виконує задану дію, коли з елементом відбувається щось конкретне.

Подія може бути будь-чим, що відбувається на сторінці: те, що користувач робить (клацання, переміщення мишки по елементу, натискання клавіші, збільшення вікна, прокручування тощо), а також речі, що відбуваються автоматично, наприклад завантаження сторінки.

У цьому випадку нам знадобиться тип події 'click', який відповідає за натискання на предмет.

У файлі gallery.js ви вже маєте код для кнопки 5. Використовуючи метод addEventListener поєднайте натискання на кнопку (подія клацання - 'click') з функцією showSlide5, написаною раніше.

document.querySelector( '#pin5' ).addEventListener( 'click', showSlide5 );

А що тепер? Оновлюємо сторінку і перевіряємо, чи працює ;-)

У нас вже є код, який показує слайд 5. Тепер, перш ніж ми його покажемо, було б добре знайти поточний слайд і приховати його.

Як ми можемо знайти поточний слайд? Чи є щось, що відрізняє його від інших?

Поточний слайд, на відміну від інших, має доданий клас show. Коли ми додаємо крапку до назви класу, ми отримуємо селектор, який дозволяє шукати його. Використовуючи ці знання та попередні приклади, додайте код на початку showSlide5, який знайде поточний слайд та приховує його.

Після приховання поточного слайду, функція виглядатиме так:

function showSlide5( ) {
   document.querySelector( '.show' ).classList.remove( 'show' );
   document.querySelector( '#slide5' ).classList.add( 'show' );
}
document.querySelector( '#pin5' ).addEventListener( 'click', showSlide5 );

Працює? На цій основі ми можемо створити код для інших слайдів і кнопок. Найпростішим способом буде метод копіювання-вставлення-зміна того, що вам потрібно :-)

Час для тестів!

Що потрібно перевірити, щоб переконатися, що все в порядку?

Навігація попередній / наступний слайд

Наступним кроком буде програмування стрілок праворуч і ліворуч, які перенесуть нас до наступного / попереднього зображення.

Традиційно, почнемо з написання українською мовою того, що нам потрібно зробити, щоб отримати наступний слайд, після натискання кнопки >>.

Є кілька способів записати це. Ось приклад:

1. Знайдіть стрілку праворуч -> ,
2. Перевірте, коли вона натиснута.
3. Коли ви натискаєте то відбуваються наступні дії:
    3.1. Знайдіть слайд, який в даний час призначений для класу `show`,
    3.2. Забери від слайда цей клас (видали),
    3.3. Знайдіть наступний елемент у порядку,
    3.4. Додайте його до класу `show`.

Якщо ваш спосіб дуже відрізняється від прикладу, інструктор буде радий вам пояснити, що робити далі.

Багато хто з цих чи подібних інструкцій вже обговорювалися:

  • 1. Знайдіть стрілку праворуч,
  • 2. Перевірте, коли вона натиснута.
  • 3. Після натискання виконайте подію:
    • 3.1. Знайдіть слайд, в якому наразі є призначений клас show,
    • 3.2. Усуньте від слайда цей клас,
    • 3.3. Знайдіть наступний елемент у порядку.
    • 3.4. Додайте йому класу show.

Ви сумніваєтесь, як зробити одну з виділених речей? Зараз саме час пояснити це.

Використовуючи те, що ми вже знаємо, у файлі gallery.js створіть функцію showNextSlide і додайте до неї приховування поточного елементу. Пов’яжіть цю функцію клацанням правої стрілки.

Приклад рішення:

function showNextSlide( ) {
   document.querySelector( '.show' ).classList.remove( 'show' );
    // тут буде решта нашого коду
}
document.querySelector( '#next' ).addEventListener( 'click', showNextSlide );

Давайте перевіримо, як це працює!

Найважче на цьому етапі - це знайти наступний предмет у порядку. Які є ідеї, як це зробити?

Нам потрібно десь запам'ятати, який слайд востаннє відображався, і порахувати, який буде наступний.

Для цього нам знадобляться змінні.

Змінна це контейнер, в якому ми можемо зберігати інформацію та читати її пізніше в іншому місці. У JavaScript у будь-якій змінній може зберігатися практично будь-що - текст, число, елемент документа, складний об'єкт і навіть функція.

Для створення змінної в JavaScript ми використовуємо ключове слово let:

// текстова змінна
let courseTitle = 'Galeria JavaScript';

Створена таким чином змінна може бути використана далі в коді, просто надавши її ім'я, наприклад:

// числова змінна - довжина тексту
let titleLength = courseTitle.length;

Як ми вже згадували, змінна може зберігати все. Давайте подумаємо, у якій формі найпростіше буде запам'ятати поточний слайд, а потім обчислимо наступний на його основі.

Найпростіше буде запам’ятати номер поточного елемента. Це дозволить нам позначити наступний / попередній елемент шляхом додавання і віднімання.

Спробуємо вдосконалити наш алгоритм для стрілки праворуч, знаючи, що ми будемо читати і записувати номер поточного елемента.

Мабуть, це виглядає приблизно так:

1. Знайдіть стрілку праворуч,
2. Перевірте, коли вона натиснута.
3. Після натискання виконуйте подію:
    3.1. Знайдіть слайд, який наразі має клас `show`,,
    3.2. Заберіть у нього дану класу, // до цих пір без змін
    3.3. Прочитайте номер поточного елемента, збереженого у змінній,
    3.4. Додайте до неї `1`,
    3.5. Знайдіть елемент з новим номером,
    3.6. Додайте до нього класу `show`.
    3.7. Збережіть новий номер як поточний елемент.

Все зрозуміло? Зараз настав час для питань, перш ніж продовжувати.

Як ми можемо прочитати поточний номер на кроці 3.3?

Нам потрібно зберегти його перед функцією, бажано на початку файлу.

Яке значення ми хочемо надати йому на початку?

Після завантаження сторінки, з'являється перший слайд, тому спочатку поточний номер повинен бути 1.

Тепер, коли ми знаємо, що робити, давайте зреалізуємо це на практиці. На початку файлу gallery.js створіть змінну з ім'ям currentNumber і надайте йому значення 1.

let currentNumber = 1;

Відмінно, ми маємо нашу першу змінну!

Тепер ми хочемо додати до неї 1 і запам'ятати цю вартістю. Для цього ми можемо створити додаткову змінну для допомоги.

Наприкінці функції showNextSlide створіть нову змінну з назвою newNumber, і призначимо його вартість на 1 більше, ніж currentNumber.

let newNumber = currentNumber + 1;

Дуже добре. Тепер, коли ми обчислили нове число, нам потрібно знайти елемент з цим числом.

Всі наші слайди мають ідентифікатор #slide + послідовний номера (1, 2, 3, ...).

Таким чином, ми можемо використовувати силу JavaScript і склеювати текст з номером, використовуючи той самий знак +, наприклад:

'#slide' + 1

Використовуючи це властивість, додамо в кінці функції showNextSlide код, який знаходить елемент з номером newNumber і додає йому клас show.

    document.querySelector( '#slide' + newNumber ).classList.add( 'show' );

Залишилося ще одне - збереження нового номера як поточного.

В кінці функції showNextSlide ми зберігаємо новий поточний номер слайда в змінній currentNumber. (Зараз він зберігається в newNumber).

Якщо все пішло за планом, наш код повинен виглядати приблизно так:

let currentNumber = 1;

function showNextSlide( ) {
    document.querySelector( '.show' ).classList.remove( 'show' );
    let newNumber = currentNumber + 1;
    document.querySelector( '#slide' + newNumber ).classList.add( 'show' );
    currentNumber = newNumber;
}
document.querySelector( '#next' ).addEventListener( 'click', showNextSlide );

Все готово? Час для тестів! :-)

Ви помітили це? Коли ми досягнемо кінця, з’являється чорний екран.

Чому це відбувається і як ми можемо це виправити?

У нас є лише 5 слайдів, тому після досягнення кінця скрипт намагається завантажити нам слайд 6, який не існує.

Щоб це виправити, після додавання ми можемо перевірити поточний номер. Якщо він більше 5, тоді потрібно змінити його на 1.

Як ми можемо вдосконалити наш алгоритм, написаний українською мовою, щоб включити його?

3.1. Знайдіть слайд, який в даний час призначений для класу `show`,
3.2. Усунь від слайда цей клас,
3.3. Прочитайте номер поточного елемента, збереженого в змінній,
3.4. Додати до нього 1,
3.5. Якщо новий номер більше 5, змініть його на 1.
3.6. Знайти елемент з новим номером,
3.7. Додайте його до класу `show`.
3.8. Збережіть новий номер як поточний елемент.

Для досягнення цього ефекту, нам будуть корисні умовні інструкції.

Умовний перехід - фрагменти коду, які виконуються лише тоді, коли умова виконується.

Найпростіший з них виглядає так:

if ( умова ) {
    // виконує код, який знаходиться тут.
}

Для порівняння, яке число є більше чи менше, ми використовуємо символи > і <.

Якщо щось незрозуміло, зараз настав час запитати.

У відповідному місці функції showNextSlide ми додаємо умовний перехід, який перевіряє чи newNumber більше від 5, і, якщо це так, присвоюєм значення 1.

На цьому етапі наш код виглядає приблизно так:

let currentNumber = 1;

function showNextSlide( ) {
    document.querySelector( '.show' ).classList.remove( 'show' );
    let newNumber = currentNumber + 1;
    if( newNumber > 5 ) {
        newNumber = 1;
    }
    document.querySelector( '#slide' + newNumber ).classList.add( 'show' );
    currentNumber = newNumber;
}
document.querySelector( '#next' ).addEventListener( 'click', showNextSlide );

Час для тестів!

Якщо все працює так, як слід, ми можемо створити і пов'язувати аналогічну функцію для лівої стрілки. Назвемо її showPreviousSlide. Більшу частину коду можна скопіювати з функції стрілки праворуч, нам просто потрібно змінити додавання до віднімання, а також умову досягнення кінця. Після закінчення роботи давайте перевіримо, як це працює.

Зразок коду функції showPreviousSlide:

function showPreviousSlide( ) {
    document.querySelector( '.show' ).classList.remove( 'show' );
    let newNumber = currentNumber - 1;
    if( newNumber < 1 ) {
        newNumber = 5;
    }
    document.querySelector( '#slide' + newNumber ).classList.add( 'show' );
    currentNumber = newNumber;
}
document.querySelector( '#prev' ).addEventListener( 'click', showPreviousSlide );

Вийшло! Маємо вже запрограмовані основні функції галереї.

Хочеш більше? Для бажаючих є кілька бонусів.

Бонус 1 - з'єднати все разом

У нас є два способи навігації по галереї - кнопки внизу та стрілки. Пора перевірити, як виглядає співпраця між ними.

Якщо ми використовуємо кнопки та стрілки для зміни, порядок зображень не зовсім правильний. Що саме не так? Будь-які ідеї, чому це відбувається?

Функції showNextSlide та showPreviousSlide отримують з currentNumber поточний номер слайда, а потім вибирають наступний.

На жаль, функції, для кнопок (showSlide1 ... showSlide5) не оновлюють це значення, тому наш код містить погані дані про те, який слайд зараз вгорі.

Ура! У нас є перший побічний ефект ;-) Такі речі часто трапляються при додаванні нової функціональності до старого коду. Щоб цього не допустити, тестування та спрощення коду є максимально корисними.

Як ми можемо виправити нашу проблему та запобігти подібним ситуаціям у майбутньому?

Найпростішим рішенням було б зберегти значення currentNumber у всіх функціях, призначених для кнопок.

Таким чином, кожна з функцій showSlide1 ... showSlide5 записувала б відповідний номер від 1 до 5.

На жаль, це рішення має серйозний недолік. Кожного разу, коли ми змінюємо щось у нашому коді, нам потрібно буде перевірити всі існуючі функції та переконатися, що вони все ще актуальні. Якщо ні, доведеться покращувати кожну з них індивідуально.

Набагато кращим рішенням буде створення універсальної функції, яка покаже будь-який слайд з заданим номером. Завдяки цьому логіка показу слайда завжди буде однаковою, і будь-які зміни доведеться вносити лише один раз.

Для цього будуть корисні параметри функції.

Як ви, напевно, пам'ятаєте, функція - цілісна послідовність команд, які можна викликати з будь-якої точки коду, щоб вони виконувалися один за іншим. Якщо ми передамо параметри до функції, одні й ті ж команди можуть працювати над різними даними щоразу.

Простий приклад - функція, яка приймає ім'я як параметр і записує в консолі привітання для людини з вказаним іменем:

function hi( name ) {
    console.log( 'Привіт ' + name + '! Приємно бачити вас!' );
}

Тепер ми можемо назвати цю функцію, наприклад:

hi( 'Магда' );

Що станеться, якщо ми запустимо функцію hi таким чином?

Кінець відступу, ми повертаємося до нашого слайд-шоу :-)

Виходячи з функцій, які ми вже маємо, давайте подумаємо, які спільні частини? Як ми можемо написати українською мовою, що має робити універсальна функція?

1. Для даного номера слайда
1.1. Знайдіть предмет, який зараз відображається,
1.2. Усуньте йому клас `show`,
1.3. Знайти елемент із зазначеним номером,
1.4. Додайте йому класу `show`,
1.5. Збережіть вказаний номер, як поточний номер слайда.

Якщо у вас є сумніви, зараз настав час для питань.

У файлі gallery.js додайте нову функцію showSlide, яка приймає номер слайда для показу (newNumber) як параметр. Додайте всі необхідні інструкції в тіло функції: приховати поточний слайд, знайти слайд з новим номером і показати його, зберегти поточний номер.

Приклад коду, як це можна зробити:

function showSlide( newNumber ) {
    document.querySelector( '.show' ).classList.remove( 'show' );
    document.querySelector( '#slide' + newNumber ).classList.add( 'show' );
    currentNumber = newNumber;
}

Що далі? Нам потрібно змінити функції, які ми вже маємо, щоб вони використовували цю універсальну.

У файлі gallery.js знайдіть функції showSlide1 до showSlide5. Замініть їх поточний вміст на універсальний виклик функції showSlide з відповідним параметром.

Код для кнопки 1 - інші виглядають аналогічно:

function showSlide1( ) {
  showSlide( 1 );
}
document.querySelector( '#pin1' ).addEventListener( 'click', showSlide1 );

Тепер давайте зробимо те саме для функцій, які працюють на стрілках.

У файлі gallery.js знайдіть функції showPreviousSlide та showNextSlide. Приберіть з них все, що є у універсальній функції showSlide, натомість викличіть цю функцію відповідним параметром.

Код для стрілки праворуч після зміни:

function showNextSlide( ) {
  let newNumber = currentNumber + 1;
  if( newNumber > 5 ) {
    newNumber = 1;
  }
  showSlide( newNumber );
}
document.querySelector( '#next' ).addEventListener( 'click', showNextSlide );

Все зрозуміло? Час для тестів!

Гарна робота!

І гарна новина - ще більше бонусів!

Бонус 2 - підсвічування кнопок

Наступна класна річ, яку варто було б зробити - виділити кнопку, яка відповідає поточному зображенню.

Ми можемо побачити, як це виглядає на нашому демо.

Як активна кнопка виділена на демо сайті? Що показують інструменти програміста?

Ми бачимо, що в поточній виділеній кнопці є додатковий selected клас. На підставі функції showSlide, додайте нову функцію selectPin в файл gallery.js яка прийматиме номер кнопки, щоб виділити її як параметр, скидає підсвітлення активної в даний момент, і виділяє з вказаним номером.

Готово? Ось приклад того, як може виглядати ця функція:

function selectPin( newNumber ) {
  document.querySelector( '.selected' ).classList.remove( 'selected' );
  document.querySelector( '#pin' + newNumber ).classList.add( 'selected' );
}

Де найкращий спосіб викликати цю функцію? Чому ми цього разу не зберігаємо значення? currentNumber?

Ми хочемо виділити кнопку кожного разу, коли ми перемикаємо слайди, тому найкраще викликати цю функцію всередині функції showSlide.

Номер виділеної кнопки завжди той самий, що і номер показаного слайда, тому нам не доведеться запам'ятовувати одне і те ж значення вдруге.

Всередині функції showSlide додати виділення кнопки - викликати функцію selectPin з відповідним параметром.

Наша функція showSlide тепер виглядає:

function showSlide( newNumber ) {
  document.querySelector( '.show' ).classList.remove( 'show' );
  document.querySelector( '#slide' + newNumber ).classList.add( 'show' );
  currentNumber = newNumber;
  selectPin( newNumber );
}

Традиційно - тестуємо! :-)

Ой, щось пішло не так! Будь-які ідеї, що сталося, і як ми можемо це виправити?

Нам допоможе консоль браузера. Клацнувши ім'я файлу у повідомленні про помилку, ми бачимо, який саме фрагмент нашого коду викликає проблеми:

Ми бачимо, що наш скрипт має проблеми з властивістю classList, тому що об'єкт, з якого він намагається прочитати, просто не існує.

Чому це сталося? Коли сторінка запускається, жодна з кнопок не має класу selected, тому пошук за цим класом повернув порожній набір.

Як ми можемо вирішити цю проблему?

Переконаймося, що під час завантаження сторінки ми правильно показали перший слайд та першу кнопку. Для цього додайте код, який це зробить на початку файлу gallery.js.

Ось приклад розв'язання:

let currentNumber = 1;
document.querySelector( '#slide' + currentNumber ).classList.add( 'show' );
document.querySelector( '#pin' + currentNumber ).classList.add( 'selected' );

Як пройшли тести цього разу?

Якщо вам ще не надоїло, ми запрошуємо вас після перерви :-)

Бонус 3 - цикли

Бонус 3 - Цикли

Бонус 3 - Цикли

Бонус 3 - Цикли

Що зробити, щоб не повторювати без сенсу?

Зараз у нашому коді є п'ять фрагментів коду, які дуже схожі між собою

function showSlide1 ( ) {
     showSlide( 1 );
}
document.querySelector('#pin1').addEventListener( 'click', showSlide1 );
function showSlide2 ( ) {
     showSlide( 2 );
}
document.querySelector('#pin2').addEventListener( 'click', showSlide2 );

...

Уявіть, як виглядав би наш код, якби у нашій галереї було більше п'яти зображень

function showSlide312 ( ) {
   showSlide( 312 );
}
document.querySelector('#pin312').addEventListener( 'click', showSlide312 );

Аж проситься якось автоматизувати цей процес.

Зрештою, для цього є комп'ютери, щоб полегшити нам життя! ;-)

Уявіть щось подібне:

Замінюючи вартість numerPinu від 1 до 5, хочу виконати наступну дію: {
  document
    .querySelector('#pin' + pinNumber)
    .addEventListener( 'click', showSlide(pinNumber) );
}

У JavaScript ми можемо розбивати довгі інструкції на кілька рядків для кращої читабельності.

Як виявляється, це дуже просто!

Ми будемо використовувати для цього цикл for:

for (let pinNumber = 1; pinNumber <= 5; pinNumber++) {
  document
    .querySelector('#pin' + pinNumber)
    .addEventListener( 'click', showSlide(pinNumber) );
}

Давайте перевіримо!

Щось не так :(

Відразу показується останнє зображення, а кнопки не працюють...

Давайте знову подивимося на наш цикл:

for (let pinNumber = 1; pinNumber <= 5; pinNumber++) {
  document
    .querySelector('#pin' + pinNumber)
    .addEventListener( 'click', showSlide(pinNumber) );
}

Проблемою є функція showSlide(), яка викликається, коли цикл виконується, а не після натискання кнопки

Давайте згадаємо, як виглядав наш оригінальний код

function showSlide1 ( ) {
  showSlide( 1 );
}
document.querySelector('#pin1').addEventListener( 'click', showSlide1 );

Виклик функції showSlide був закритий у функції showSlide1, що дозволило нам викликати її в потрібний момент (тобто після натискання)

Цей код:

function showSlide1 ( ) {
  showSlide( 1 );
}
document.querySelector('#pin1').addEventListener( 'click', showSlide1 );

Можемо записати трохи по-іншому

document.querySelector('#pin1').addEventListener( 'click', function () {
  showSlide( 1 );
} );

Ми перемістили визначення функції безпосередньо до місця, де ми хочемо присвоїти його до слухача подій

Крім того, ми видалили її назву. Тепер це анонімна функція!

Повернемося до нашого циклу зараз. З нещодавно набутими знаннями ми повинні могти написати його правильно.

for (let pinNumber = 1; pinNumber <= 5; pinNumber++) {
  document
    .querySelector('#pin' + pinNumber)
    .addEventListener( 'click', function () {
      showSlide(pinNumber);
    });
}

Подивимося, як вийшло

Кнопки працюють, і у нас (+ -) в п'ять разів менше коду!

Бонус 4 - автозапуск!

Цього разу спробуємо додати режим автовідтворення до нашого слайд-шоу.

Традиційно, ми можемо побачити, як це працює на нашій демо, натиснувши кнопку у нижньому правому куті.

Цього разу, винятково, ми не враховуємо все, що відбувається на сайті, і наразі створимо максимально загальну картину ситуації. Ми бачимо, що автозапуск включається і вимикається поперемінно, коли ми кілька разів натискаємо кнопку play. Як ми можемо написати на найбільш загальному рівні, що тут відбувається?

Вийшло щось подібне:

1. Знайдіть кнопку відтворення,
2. Перевір, коли це буде натиснуто.
3. Після натискання виконайте подію:
  3.1. Перевірте, чи слайд-шоу зараз відтворюється:
        3.1.1. Якщо так, вимкніть його
      3.1.2. Якщо ні, увімкніть його.

Настав час розпочати створення функції, яка буде керувати нашим слайд-шоу. Як ми можемо перевірити, чи слайд-шоу зараз відтворюється?

Таким же чином ми запам'ятовуємо поточний номер слайда - використовуючи змінну.

У цьому випадку наша змінна матиме лише два значення (включене /виключене), тому найкраще призначити логічне значення

Ви пам’ятаєте, що в JavaScript змінною може бути практично всім, що завгодно? Серед іншого, ми можемо призначити логічне значення (правда або неправда).

Ми пишемо правду в JavaScript як істину true, а для неправди ми використовуємо слово false:

let isJavaScriptAwesome = true;
let isJavaScriptComplicated = false;

Ми порівнюємо логічні значення за допомогою потрійного знаку рівності, наприклад:

if ( isJavaScriptAwesome === true ) {
    let doWeHaveEnoughYet = false;
}

У початку файлу gallery.js створіть змінну playing, яка зберігатиме поточний стан слайд-шоу. Спочатку шоу має бути вимкнено, тому встановіть його на false.

let playing = false;

Відмінно! Тепер ми можемо йти до тіла нашої функції. Давайте швидко подивимося на код, написаний в попередніх кроках, щоб нагадати вам, як пов'язати цю функцію з клацання мишкою по елементі.

У файлі gallery.js додайте нову функцію playButtonClicked і пов’язати її з натисканням на кнопку відтворення (play). У тілі функції перевірте поточний стан слайд-шоу, збереженого у змінній, playing. Наразі цього достатньо, щоб ви змінили його на протилежне (від правди до неправди, від неправди до правди).

Ми, швидше за все, отримаємо щось подібне:

function playButtonClicked( ) {
    if ( playing === true ) {
        playing = false;
    } else {
        playing = true;
    }
}
document.querySelector( '#play' ).addEventListener( 'click', playButtonClicked );

Як ми можемо перевірити на цьому етапі, чи працює наш код правильно?

Hайпростіший спосіб - ввести назву нашої змінної в консолі - ми повернемо її поточну вартість.

Давайте подивимось на кнопку play. Ми бачимо, що вона змінює значок залежно від того, скільки разів було натиснуто. Що змінює цю кнопку?

Звичайно, це клас CSS. Цього разу це класа on.

Ми бачимо, що кількість дій, які потрібно зробити при включенні / вимкненні слайд-шоу, повільно збільшується. Може, можна виділити окремі функції від них?

У файлі gallery.js додамо дві нові функції: startSlideshow і stopSlideshow. Функція start додає клас on до кнопки play та зберігає в змінній playing, що показує слайд-шоу. Функція stop робить зворотне. Функція playButtonClicked викликає кожну з цих двох функцій у потрібних місцях.

Багато нового коду! Давайте подивимося, як вийшло цього разу:

function playButtonClicked( ) {
    if ( playing === true ) {
        stopSlideshow();
    } else {
        startSlideshow();
    }
}
document.querySelector( '#play' ).addEventListener( 'click', playButtonClicked );

function startSlideshow( ) {
    document.querySelector( '#play' ).classList.add( 'on' );
    playing = true;
}

function stopSlideshow( ) {
    document.querySelector( '#play' ).classList.remove( 'on' );
    playing = false;
}

Все зрозуміло? Як так, то тестуємо.

Якщо все працює добре, тоді ми переходимо до найскладнішої частини - включення і вимкнення слайд-шоу.

Що саме являє собою слайд-шоу? Як ми можемо написати його алгоритм українською мовою? Частину ми вже описали у функції startSlideshow, тому ми повинні думати про решту.

Існує кілька способів записати це, але ідея є більш-менш однаковою:

Функція Увімкнення слайд-шоу:
1. Додайте клас playing до кнопки play
2. Записати стан слайд-шоу в змінній playing
3. Зачекайте 3 секунди,
4. Змінить слайд на наступний,
5. Поверніться до кроку 3.

На наступному етапі ми потребуємо певного способу вимірювання часу.

Інтервали будуть корисні для цього.

Інтервал повторює вказівки, що даються йому циклічно, в заданий часовий проміжок.

Його можна створити за допомогою функції:

  • setInterval( akcja, odstep ) - ввиконує дію щоразу, коли проходить визначений часовий інтервал (дані в мілісекундах).

У функції startSlideshow створимо інтервал, який перемикає слайд на наступний кожні 3000 мілісекунд. Пам'ятайте, що у нас є готова функція для перемикання слайда на наступний :-)

Після додавання нового коду функція виглядає приблизно так:

function startSlideshow( ) {
    document.querySelector( '#play' ).classList.add( 'on' );
    playing = true;
    setInterval( showNextSlide, 3000 );
}

Що показують нам тести цього разу?

Ми можемо бачити, що показ слайдів починається правильно. Тепер нам потрібно якийсь спосіб його вимкнути.

Як ми можемо вимкнути запущений інтервал ?

Це було досить підступне питання. Як ми, напевно, пам'ятаємо, змінні в JavaScript можуть записати все.

Що станеться, якщо ми збережемо результат функції setInterval в змінній? Ми можемо використовувати його пізніше, щоб вимкнути цей інтервал.

Близько початку файлу gallery.js створіть нову змінну з назвою slideshowInterval. У відповідному місці в коді збережіть результат функції setInterval у цій змінній.

Цього разу ми повинні отримати щось подібне:

let slideshowInterval;
// (...)

function startSlideshow( ) {
    document.querySelector( '#play' ).classList.add( 'on' );
    playing = true;
    slideshowInterval = setInterval( showNextSlide, 3000 );
}

Тепер все, що нам потрібно зробити, - це вимкнути інтервал.

У цьому нам допоможе функція:

  • clearInterval( interval ) - вимикає інтервал, попередньо збережений у змінній.

Спробуємо використати це на практиці.

У функції stopSlideshow ми очистимо раніше збережений інтервал. Для цього викличемо функцію clearInterval з відповідним параметром.

Вся функція stopSlideshow тепер виглядає так:

function stopSlideshow( ) {
    document.querySelector( '#play' ).classList.remove( 'on' );
    playing = false;
    clearInterval( slideshowInterval );
}

Що нам показують тести?

Вітаємо!

Це кінець нашого курсу. Ми зробили хорошу роботу, але це лише початок можливостей мови JavaScript.

За мить ми познайомимо вас із цікавими проектами, побудованими цією мовою.

Але ви, напевно, вже замислюєтесь "що далі?".

Гарні новини: Інтернет наповнений безкоштовними матеріалами для самостійного вивчення JavaScript!

Кілька ідей, з чого почати:

Ми також рекомендуємо відвідувати сторінку Facebook, де ми повідомляємо про наступні курси.

Дякуємо, що разом проведений час і до зустрічі!

переклад: Руслан Халілов