В предыдущих трех постах (1, 2, 3) я описал создание шахматного поля на веб-странице с помощью языка разметки HTML и языка описания стилей CSS, с использованием входящей в CSS технологии Flexbox. Кроме этого, я добавил на шахматное поле шахматные фигуры (источник изображений). В этом посте я добавлю в проект возможность передвигать шахматные фигуры мышью с помощью скрипта на языке программирования JavaScript.

Включен ли JavaScript в браузере

В современных браузерах интерпретатор JavaScript (движок) встроен по умолчанию. Обычно в настройках браузера есть возможность отключения исполнения скриптов JavaScript с веб-страниц. Но абсолютное большинство пользователей этой настройкой не пользуется, разрешая браузеру выполнять эти скрипты.

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

Добавление скриптов на веб-страницу

Очень часто начинающие веб-программисты неправильно добавляют скрипт на языке JavaScript на веб-страницу, в результате скрипт не работает так, как ожидает веб-программист, или скрипт как будто бы вообще не запускается.

Если скрипт должен манипулировать элементами веб-страницы, то нужно обеспечить определенный порядок загрузки веб-страницы, чтобы всё работало так, как хочется. Сначала браузер должен прочитать код веб-страницы на языке HTML и создать объектную модель документа (DOM), а только затем следует запускать скрипт.

Для обеспечения такого порядка работы многие веб-программисты вставляют скрипты в конец тела (body) веб-страницы или в самый конец файла с кодом на языке HTML. Это работает, но я предпочитаю вставлять скрипты в конец элемента head веб-страницы, в котором описывается информация (метаданные) о веб-странице. Например, вот так:

  <head>
    <!-- ... -->
    <script src="movePiece.js" defer></script>
  </head>

Обратите внимание на свойство defer, без него скрипт загрузится раньше элементов тела веб-страницы. А поскольку этот мой скрипт будет использовать элементы тела веб-страницы, то без этого свойства он работать не будет. В переводе на русский «defer» означает «отложить», то есть это указание браузеру отложить запуск данного скрипта на момент после полной загрузки веб-страницы и окончания построения объектной модели документа.

Скрипт движения фигуры

Код скрипта я пишу в файле movePiece.js, который подключен на веб-страницу описанным выше способом.

Движение фигур в этом проекте можно реализовать множеством разных способов. Мне нужно было только показать студентам возможность придания веб-страницам интерактивности, поэтому я в этом проекте выбирал способы попроще, где это возможно.

Сначала я хотел использовать способ «drag and drop», при котором пользователь захватывает на веб-странице желаемый объект мышью и перетаскивает его в нужное место, где отпускает. Но в итоге я отказался от этой идеи в пользу способа попроще. Тем, кто всё же хочет попробовать способ «drag and drop», рекомендую прочесть соответствующую главу в учебнике learn.javascript.ru.

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

let piece; // передвигаемая фигура

// получить все элементы веб-страницы, представляющие шахматные поля
let chessFields = document.querySelectorAll(".square");

// назначить каждому из шахматных полей обработчик клика основной кнопкой мыши
for (let field of chessFields) {
  field.onclick = movePiece;
}

// функция-обработчик клика основной кнопкой мыши
function movePiece(event) {
  if (event.target.tagName == "IMG") {       // выбор передвигаемой фигуры
    piece = event.target;
  }
  else if (event.target.tagName == "DIV") {  // передвижение выбранной фигуры
    // если фигура выбрана
    if (piece) {
      // если на поле назначения нет фигуры
      if (!event.target.firstElementChild) {
        event.target.append(piece);
      }
    }
  }
}

Для хранения выбранной фигуры используем переменную piece.

Ранее в коде веб-страницы на языке HTML мы назначили класс square всем 64-м шахматным полям. Поэтому в скрипте легко смогли выбрать эти шахматные поля по селектору .square.

Сам алгоритм выбора и передвижения фигуры реализован в функции movePiece, но чтобы эта функция вызывалась при каждом клике основной кнопкой мыши по нужным элементам веб-страницы, нужно как-то связать функцию movePiece и нужные элементы. Это мы проделываем в цикле for с помощью свойства onclick нужных элементов веб-страницы.

Вообще, есть несколько более сложный, но более гибкий метод привязки — с помощью метода addEventListener. Я выбрал привязку с помощью свойства onclick из-за того, что это проще, но если кто-нибудь всё же хочет попробовать метод addEventListener, то рекомендую начать с чтения соответствующей главы в учебнике learn.javascript.ru. Одно из преимуществ метода addEventListener состоит в том, что он позволяет привязать к одному и тому же событию на нужном элементе несколько функций-обработчиков, а свойство onclick нужного элемента — только одну функцию-обработчик.

Как выбранный алгоритм определяет, с какой целью вы кликнули основной кнопкой мыши — для выбора фигуры или для указания поля назначения выбранной фигуры? Это зависит от названия элемента, по которому вы кликнули (IMG или DIV). Обратите внимание, что названия элементов мы получили с буквами в верхнем регистре, это важно.

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

При реализации перемещения фигуры мы написали несколько проверок с помощью условий if, убирающих несколько ненужных эффектов.

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

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

Результат

Начало демонстрации одного из вариантов детского мата черным:

1. e2-e4   e7-e5
2. Сf1-c4  Сf8-c5
3. Фd1-f3  Кb8-c6
4. Фf3×f7#

Можно посмотреть на получившееся поле и попередвигать фигуры на поле онлайн: https://textpub.neocities.org/my/chess-board/v2.2/.

Развитие проекта

Если найду время, добавлю сохранение позиции в файл и загрузку позиции из файла. Для этого имеет смысл добавить отдельные скрипты на языке JavaScript.