Стать программистом. Практика JavaScript для новичков. Занятие 6.

в прошлом году

Доброго времени суток, друзья!

В нашем прошлом занятии мы с Вами преобразовали код нашего informer’a, закрепили работу с выборкой html-элементов, используя метод getElementsByClassName() на примере кнопок нашего «Домика» для питомца. Помимо этого, мы сделали заготовки для функций, которые должны будут отработать после того как пользователь кликнет на кнопку. Для этого мы использовали метод addEventListener().

Давайте продолжим

Стать программистом. Практика JavaScript для новичков. Занятие 6.

Сейчас при клике на кнопку у нас отрабатывает функция, которая выводит сообщение в консоль:

Однако нам, это конечно не подходит. Наша задача сделать так, чтобы при нажатии нужной кнопки, специфический счетчик с характеристикой пополнялся. Давайте посмотрим, как это работает в нашем прототипе:

Видите, как к примеру, пополняется характеристика «Сытость» при нажатии на кнопку с надписью: «Покормить». Вот именно такую функциональность мы с вами и попробуем реализовать. Для этого давайте для начала определим зависимости счетчиков характеристик от конкретных кнопок.

По первоначальной задумке за пополнение счетчика с характеристикой «Усталость» отвечает кнопка «Уложить спать», за счетчик «Сытость» - кнопка «Покормить», ну а за счетчик «Настроение» будут ответственны сразу две кнопки: кнопка «Отправить гулять» и кнопка «Поиграть». Давайте представим эти зависимости графически:

Вполне сносная схема, из которой становится понятно, какая именно кнопка пополняет тот или иной счетчик. С этим разобрались. Идем дальше. Для того чтобы пополнить какой-либо счетчик нам требуется потребуется для этого функциональность. Давайте придумаем логику такой функциональности. Для этого я для начала предлагаю обратить внимание на функцию, которая уменьшает ширину наших счетчиков. Вот она:

Из скриншота следует, что основным параметром, которые является основополагающим для ширины счетчика является переменная width. C течением времени, которое мы указываем в нашем интервале, она уменьшается на единицу. Логично предположить, что именно эту переменную мы и должны возвращать к изначальному ее значению, то есть 100, которая при очередном выполнении интервала будет подставлена в значение css-свойства ширины нашего счетчика и визуально это будет выглядеть как пополнение. Как мы можем вернуть нашу переменную в изначальное значение. Первый способ мы можем остановить наш интервал по уменьшению ширины, и затем вновь запустить нашу функцию runProgressBar(). При новой инициализации переменная width снова будет равна 100 и счетчик начнёт отсчитывать ширину по новой. Это реально, но, как мне кажется немного избыточно. Другой вариант мы можем поменять значение этой переменной без остановки счетчика. В этом случае интервал продолжает свою работу без остановки, но просто в определенное время (после клика кнопки) он начнет уменьшать ширину опять со ста процентов.

Давайте попробуем реализовать эту функциональность. На пути к этому у нас есть ровно одна проблема. Наша переменная width инкапсулирована (спрятана) от прямого программного воздействия. А нам нужна величина, на которую мы сможем влиять, в любой произвольный участок времени. Что делать? Ясно что эту переменную нужно куда-то перенести, но куда? Ответ очевиден, если ширина относится к конкретному счетчику, то давайте к этому счетчику эту переменную и перенесем. Тем более что для каждого счетчика у нас есть отдельный объект, и лишнее свойство в нем не помешает.

var Booth = {
    informer: {
        selector: document.getElementById('info'),
        setText: function(text) {
            this.selector.innerText = text;
        }
    },
    timer1: {
        selector: document.getElementById('fatigue'),
        isOrange: false,
        isRed: false,
        width: 100
    },
    timer2: {
        selector: document.getElementById('satiety'),
        isOrange: false,
        isRed: false,
        width: 100
    },
    timer3: {
        selector: document.getElementById('mood'),
        isOrange: false,
        isRed: false,
        width: 100
    },
    /* добавляем события к выбранным кнопкам */
    buttons: document.getElementsByClassName('monitor__btn'),
    addButtonsEvents: function() {
        for(var i = 0; i < this.buttons.length; i+=1) {
            this.buttons[i].addEventListener('click', function() {
                console.log('вы сделали клик!');
            });
        }
    },
    /* Запускаем счетчики парметров */
    runProgressBar: function(timer, seconds) {
        
        var milliseconds = seconds*1000;
        var interval = setInterval(function() {
            if(timer.width != 0) {
                timer.width -= 1;
                timer.selector.style.width = timer.width + '%';

                /* смена цвета счетчика*/

                if(timer.isOrange == false && timer.width <= 50) {
                    timer.isOrange = true;
                    timer.selector.setAttribute('class', 'monitor-bar__progress attention');
                }

                if(timer.isRed == false && timer.width <= 25) {
                    timer.isRed = true;
                    timer.selector.setAttribute('class', 'monitor-bar__progress alarm');
                }

            } else {
                clearInterval(interval);
            }
        }, 200);
    },
}

Смотрите, мы убрали переменную width из метода runProgressBar() и перенесли ее в объект к каждому из трех наши счетчиков. Так как теперь это свойство счетчика, то в самом методе runProgressBar() мы уже должны обращаться к нему именно как свойству счетчика а не как к переменной, что мы делали раньше. Теперь свойство width уже не является инкапсулированным, и мы можем с легкостью получить к нему доступ. Давайте проверим это в консоли:

Как видим, мы легко получаем свойство нашего счетчика программным путём. А давайте теперь посмотрим, что будет, если в процессе уменьшения ширины счетчика, мы прямо в консоли поменяем значение свойства width на 100.

И вот результат. Сначала мы запускаем счетчик на уменьшение. А затем меняем его свойство width обратно на 100. И визуально это выглядит как пополнение счетчика. Что собственно нам и требуется. Теперь только остается создать функцию для пополнения счетчика в нашем объекте {Booth}.

var Booth = {
    informer: {
        selector: document.getElementById('info'),
        setText: function(text) {
            this.selector.innerText = text;
        }
    },
    timer1: {
        selector: document.getElementById('fatigue'),
        isOrange: false,
        isRed: false,
        width: 100
    },
    timer2: {
        selector: document.getElementById('satiety'),
        isOrange: false,
        isRed: false,
        width: 100
    },
    timer3: {
        selector: document.getElementById('mood'),
        isOrange: false,
        isRed: false,
        width: 100
    },
    /* добавляем события к выбранным кнопкам */
    buttons: document.getElementsByClassName('monitor__btn'),
    addButtonsEvents: function() {
        for(var i = 0; i < this.buttons.length; i+=1) {
            this.buttons[i].addEventListener('click', function() {
                console.log('вы сделали клик!');
            });
        }
    },
    /* Запускаем счетчики парметров */
    runProgressBar: function(timer, seconds) {
        
        var milliseconds = seconds*1000;
        var interval = setInterval(function() {
            if(timer.width != 0) {
                timer.width -= 1;
                timer.selector.style.width = timer.width + '%';

                /* смена цвета счетчика*/

                if(timer.isOrange == false && timer.width <= 50) {
                    timer.isOrange = true;
                    timer.selector.setAttribute('class', 'monitor-bar__progress attention');
                }

                if(timer.isRed == false && timer.width <= 25) {
                    timer.isRed = true;
                    timer.selector.setAttribute('class', 'monitor-bar__progress alarm');
                }

            } else {
                clearInterval(interval);
            }
        }, 200);
    },
    /* пополняем счетчик */
    refreshProgressBar: function(timer) {
        timer.width = 100;
    }
}

Мы создали метод refreshProgressBar() который принимает параметром timer и потом увеличивает свойство width у этого timer’a.

Давайте попробуем наш метод в браузере:

Как видим, каждый раз, когда мы вызываем метод refreshProgressBar() заданный счетчик будет возвращаться в свое изначальное состояние. Что нам и требуется. Но давайте посмотрим, как эта функция будет работать, если наш счетчик успел перейти рубеж «оранжевого» или «красного» состояния:

Как говорится: «ой!». Счетчик пополняется, но его стили в изначальное состояние не возвращаются. Почему? Потому что к моменту вызова нашего метода refreshProgressBar() наш счетчик уже успел заполучить класс attentioin который проставляется в методе runProgressBar(). Следовательно, чтобы не происходило такого казуса, нам помимо свойства width, которому мы возвращаем изначальное значение 100, возвращать и изначальное состояние, и свойство class нашего html-элемента. Давайте посмотри какое изначально состояние класса у наших счетчиков:

Как видим, изначальное состояние класса – это строка monitor-bar__progress. Задавать свойство выборке html-элемента мы уже умеем. Для этого используется метод setAttribute(). Давайте добавим эту строку в наш метод refreshProgressBar()

var Booth = {
    informer: {
        selector: document.getElementById('info'),
        setText: function(text) {
            this.selector.innerText = text;
        }
    },
    timer1: {
        selector: document.getElementById('fatigue'),
        isOrange: false,
        isRed: false,
        width: 100
    },
    timer2: {
        selector: document.getElementById('satiety'),
        isOrange: false,
        isRed: false,
        width: 100
    },
    timer3: {
        selector: document.getElementById('mood'),
        isOrange: false,
        isRed: false,
        width: 100
    },
    /* добавляем события к выбранным кнопкам */
    buttons: document.getElementsByClassName('monitor__btn'),
    addButtonsEvents: function() {
        for(var i = 0; i < this.buttons.length; i+=1) {
            this.buttons[i].addEventListener('click', function() {
                console.log('вы сделали клик!');
            });
        }
    },
    /* Запускаем счетчики парметров */
    runProgressBar: function(timer, seconds) {
        
        var milliseconds = seconds*1000;
        var interval = setInterval(function() {
            if(timer.width != 0) {
                timer.width -= 1;
                timer.selector.style.width = timer.width + '%';

                /* смена цвета счетчика*/

                if(timer.isOrange == false && timer.width <= 50) {
                    timer.isOrange = true;
                    timer.selector.setAttribute('class', 'monitor-bar__progress attention');
                }

                if(timer.isRed == false && timer.width <= 25) {
                    timer.isRed = true;
                    timer.selector.setAttribute('class', 'monitor-bar__progress alarm');
                }

            } else {
                clearInterval(interval);
            }
        }, 200);
    },
    /* пополняем счетчик */
    refreshProgressBar: function(timer) {
        timer.width = 100;
        timer.selector.setAttribute('class', 'monitor-bar__progress');
    }
}

Мы возвращаем наш класс в изначальное состояние, и теперь нам осталось проверить работает ли он в браузере:

Вот теперь мы получили то, что хотели.

А на сегодня всё, продолжение следует…

Ссылки на предыдущие занятия:

Практика JavaScript для новичков. Занятие 1,
Практика JavaScript для новичков. Занятие 2,
Практика JavaScript для новичков. Занятие 3,
Практика JavaScript для новичков. Занятие 4,
Практика JavaScript для новичков. Занятие 5

Ссылки на предыдущий курс:

Урок 1 - Окружение.,
Урок 2 - Некоторые особенности синтаксиса.,
Урок 3 - Переменные.,
Урок 4 - Типы переменных, как основа для их взаимодействия.,
Урок 5 - Операции с переменными одного типа.,
Урок 6 - Операции с переменными одного типа. Часть II.,
Урок 7 - Взаимодействие переменных с разными типами.,
Урок 8 - Взаимодействие переменных разного типа. часть II.,
Урок 9 - Взаимодействие переменных разного типа. Часть III.,
Урок 10 - Другие возможные взаимодействия между переменными.,
Урок 11 - Другие возможные взаимодействия между переменными. Часть II.,
Урок 12 - Другие возможные взаимодействия между переменными. Операторы присваивания.,
Урок 13 - Другие возможные взаимодействия между переменными. Операторы сравнения.,
Урок 14 - Сложные переменные. Array и Object.,
Урок 15 - Условные операторы.,
Урок 16 - Циклы.,
Урок 17 - Циклы. Часть II.,
Урок 18 - Функции.,
Урок 19 - Функции. Часть II.,
Урок 20 - Профилирование. Функции, часть III.,
Урок 21 - Функции, Часть IV. Аргументы.,
Урок 22 - Objects (Объекты).,
Урок 23 - Встроенные функции и объекты.,
Урок 24 - Встроенные функции и Объекты, Часть II. Глобальные функции и переменные.,
Урок 25 - Встроенные функции и Объекты, Часть III. Document Object Model.,
Урок 26 - Встроенные функции и Объекты, Часть III. Document Object Model.
Урок 27 - Встроенные объекты. Объект Style, Events, Часть II.
Урок 28 - Встроенная переменная this. Глобальная и локальная области видимости.
Урок 29 - Объектно-ориентированное Программирование. Введение.
Урок 30 - Объектно-ориентированное Программирование. Часть II. Полиморфизм.
Урок 31 - OОП. Наследование, Часть I. Оператор new.
Урок 32 - ООП. Наследование, Часть II. PROTOTYPE.
Урок 33 - ООП. Часть II. Полиморфизм.
Урок 34 - ООП. Часть III. Инкапсуляция.

Авторы получают вознаграждение, когда пользователи голосуют за их посты.
Голосующие читатели также получают вознаграждение за свой голос.
Порядок сортировки:  Популярное
73
  ·  в прошлом году

Ваш пост поддержали следующие Инвесторы Сообщества "Добрый кит":
@antino, @gromkirill, @harhor, @tom123, @exan
Поэтому я тоже проголосовал за него!
Узнать подробности о сообществе можно тут:
Разрешите представиться - Кит Добрый
Правила
Инструкция по внесению Инвестиционного взноса
Вы тоже можете стать Инвестором и поддержать проект!!!


Если Вы хотите отказаться от поддержки Доброго Кита, то ответьте на этот комментарий командой "!нехочу"