Фронтенд. Чат-вікторина. JQuery

Встановлення готового шаблону.

git clone git@github.com:zdimon/marafon-js-quiz-template.git

Скопіюємо його до папки public проекту.

Сервер розробки.

Поставимо простенький сервер.

npm install lite-server

Запуск.

cd public
../node_modules/lite-server/bin/lite-server

Працюватимемо всередині файлу app.js.

Пишемо плагін.

Нам спочатку необхідно створити ізольовану область видимості змінних.

(function( $ ) {
    $.fn.quizPlugin = function() {

        console.log('my plugin');

    };
})(jQuery);

В jQuery fn - це псевдонім прототипу.

Ключове слово jQuery (або $) - це лише функція-конструктор, і всі об’єкти, створювані цим конструктором будуть успадковувати всі властивості та методи його прототипу.

$.fn.quizPlugin = function() {..}

Так ми створюємо нову властивість-функцію для об’єкта jQuery, де ім’ям нової властивості буде ім’я нашого плагіна.

Для того, щоб не було конфліктів зі знаком $ рекомендується «обернути» об’єкт jQuery в функцію-вираз, що безпосередньо виконується.

Застосовуємо плагін.

<script>
      var app = $('#myapp').quizPlugin();
</script>

Перевіряємо залогіненість.

    app.start = function() {

        if(sessionStorage.getItem('username')) { 
            this.initRoom();
        } else {
            this.loginForm()
        }
    }

    app.loginForm = function() {

    }

    app.initRoom = function() {

    }

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

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

    app.loginForm = function() {
        let form = $('#loginForm').show();
        let url = 'http://quizapi.webmonstr.com/v1/quiz/sticker/list';
        $.get( url, function( data ) {
            data.forEach((el) => {
                let img_tag = `<img width="50" src="${el.get_url}" />`;
                let parent = $('#stickers').append(img_tag);
             })
          });
    }

$.get - функція jQuery, що відсилає http запит.

data.forEach((el) => {}) - функція, що перебирає список.

$(‘#stickers’).append() - додавання html у вибраний елемент.

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

 let img_tag = `<img data-id="${el.id}" class="sticker" width="50" src="${el.get_url}" />`;
...
 $('.sticker').on('click',(event)=>{
     $('.sticker').each((indx,el)=>{
         $(el).removeClass('active-sticker');
     })
     $(event.target).addClass('active-sticker');
 })

start page

$(‘.sticker’).on(‘click’,(event)=>{}) - прив’язка подій до колббека у jQuery.

Тут ми накидаємо клас sticker на елемент img щоб далі по них пройтися циклом і прибрати клас active-sticker. Далі ми встановлюємо клас active-sticker на тому зображенні, на яке клацнув користувач.

Стилізуємо клас.

.active-sticker {
    border: 1px solid red;
}

Сабмітім форму логіну.

Створимо функцію надсилання даних методом post з передачею json у запиті.

    app.submitLogin = function() {
        let data = {
            name: $('#userName').val(),
            sticker_id: this.sticker
        };
        let url = 'http://quizapi.webmonstr.com/v1/quiz/player/join';
        $.post( url, data, ( response ) => {
            sessionStorage.setItem('username',response.name);
            let form = $('#loginForm').hide();
        });
    }

$(‘#userName’).val() - отримання даних, що вводяться користувачем елемент input.

$.post( url, data, ( response ) => {}) - передача даних POST в jQuery.

Прив’яжемо функцію натискання кнопки з id = “chat-start”.

    app.loginForm = function() {
        ...
          $('#chat-start').on('click',() => {this.submitLogin()});
    }

Отримання та відображення поточного питання.

    app.getCurrentQuestion = function() {
        let url = 'http://quizapi.webmonstr.com/v1/quiz/get_current_question';
        $.get( url, ( response ) => {
            $('#currentQuestionBlock').html(response.question);
        });

    }

$(‘…’).html(content) - забрасываение html внутрь полученного элемента.

Отримання та відображення поточного питання.

    app.getMessages = function() {
        let url = 'http://quizapi.webmonstr.com/v1/quiz/message/list';
        $.get( url, ( response ) => {
            response.forEach((el)=> {
                let tpl = `                                             <div class="chat">
                <div class="chat-user">
                   <a class="avatar m-0">
                   <img src="${el.playerimage}" alt="avatar" class="avatar-35 ">
                   </a>
                   <span class="chat-time mt-1">${el.playername}</span>
                </div>
                <div class="chat-detail">
                   <div class="chat-message">
                      <p>${el.text}</p>
                   </div>
                </div>
             </div>`;
             $('#chatContent').append(tpl);
            })
        });
    };

Веб-сокет з’єднання.

    ...

    app.socketConnection = function() {
        let webSocket = new WebSocket('ws://quizapi.webmonstr.com:7777/quiz/');

        webSocket.onerror = (evt) => {

        }

        webSocket.onmessage = (event) => {
            var payload = JSON.parse(event.data)
            console.log(payload);
        }

        webSocket.onclose =  (event) => {
            console.log('Close connection');
        };

        webSocket.onopen =  (event) => {
            console.log('Connection established');
        };
    }

При створенні об’єкта з’єднання необхідно визначити кілька обробників.

onerror - при помилці

onmessage - надходження нового повідомлення

onopen, onclose - відкриття та закриття з’єднання.

Надсилання відповіді на сервер.

    app.sendMessage = function() {
        let data = {
            message: $('#messageBox').val(),
            playername: sessionStorage.getItem('username')
        }
        let url = 'http://quizapi.webmonstr.com/v1/quiz/save_message';
        $.post( url, data, ( response ) => {
            $('#messageBox').val('');
        });
    };

$(‘#messageBox’).val(‘’) - очищення input-а.

Реагуємо на надходження повідомлення по веб-сокету.

    ....

    webSocket.onmessage = (event) => {
        var payload = JSON.parse(event.data)
        if(payload.type === 'message'){
            this.getMessages();
        }
    }

    ...

Відображаємо список гравців.

    ...
    app.getUserList = function() {
        $('#playerListBlock').empty();
        let url = 'http://quizapi.webmonstr.com/v1/quiz/player/list';
        $.get( url, ( response ) => {
            response.forEach((el) => {
                let tpl = `<div class="media-height p-3">
                <div class="media align-items-center mb-4">
                   <div class="iq-profile-avatar status-online">
                      <img class="rounded-circle avatar-50" src="${el.sticker.get_url}" alt="">
                   </div>
                   <div class="media-body ml-3">
                      <h6 class="mb-0"><a href="#">${el.name}</a></h6>
                      <p class="mb-0">${el.account}</p>
                   </div>
                </div>
             </div>`;
                $('#playerListBlock').append(tpl);
            });
        });
    };

Повна версія ініціалізації кімнати.

    app.initRoom = function() {
        this.setCurrentUser();
        this.getUserList();
        this.getCurrentQuestion();
        this.getMessages();
        this.socketConnection();
        $('#sendButton').on('click',()=>{
            this.sendMessage();
        });
    }