/VK-Intern-Task

Решение тестового задания на стажировку "Вконтакте"

Primary LanguageJavaScript

Vk-Intern-Task

Решение тестового задания на стажировку
в команду фронтенд-инфраструктуры компании "Вконтакте"

Создать модуль на JavaScript, генерирующий HTML-форму из JSON-кода.
Полный текст задания:
https://vk.com/@vkteam-testovoe-zadanie-frontend-infrastruktura

Реализованный модуль - файл module.js, который содержит все необходимые функции для работы

За основу дизайна формы взята библиотека VK UI

Документация


Быстрый старт

  1. Для того, чтобы начать использовать модуль,
    вам нужно скачать файл module.js и разместить его
    в папку с вашим проектом.

  2. Далее вам нужно импортировать из файла две функции:
    getFormFromJSON и initHandlers

  3. Выполнить функцию getFormFromJSON(json) и
    поместить её результат в контейнер.
    Функция возвращает HTML-разметку формы
    и CSS-оформление формы.
    Параметр функции - строковая переменная json
    Переменная должна хранить в себе json-код формы.

  4. Последним шагом нужно вызвать функцию
    initHandlers. Данная функция добавит обработчики
    событий на элементы формы. Параметры отсутствуют.

Пример:

// Шаг 2:
import {getFormFromJSON, initHandlers} from "./module.js";
// Шаг 3:
document.body.innerHTML = getFormFromJSON(formJSON);
// Шаг 4:
initHandlers();

Структура JSON-объекта

В примере выше мы использовали переменную formJSON
как аргумент функции getFormFromJSON

Рассмотрим структуру такого объекта:

Свойство Обязательное Тип
caption Да строка
theme Нет строка
submit Да объект
elements Да массив
объектов

JSON объект должен включать в себя все обязательные поля.
Порядок установки полей не имеет значения.


caption - заголовок формы
Заголовок отображается в виде текста в шапке формы.

Пример:

let jsonObj = {
    // ... some code
    caption: "Регистрация",
    // ... some code
}

theme - тема формы
Установка ночной или дневной темы.
Возможные значения: "day", "night".
Значение по умолчанию - "day".

Пример:

let jsonObj = {
    // ... some code
    theme: "day",
    // ... some code
}

submit - кнопка отправки
Объект, которым можно задать текст кнопки "отправить",
путь перехода после отправки формы и метод отправки формы.

Объект может иметь 3 свойства:

Свойство Обязательное Тип
text Да строка
href Нет строка
method Нет строка

text - текст, который отобразится на кнопке "Отправить"
href - обработчик формы, если требуется
(атрибут action тега <form>)
method - метод формы. Возможные значения: "get", "post"
Добавляет атрибут method тегу <form>

Пример:

let jsonObj = {
    // ... some code
    submit: {
        text: "Войти",
        method: "post",
        href: "login.php"
    },
    // ... some code
}

Элементы

elements - массив элементов формы

Каждый элемент - это объект с такими свойствами:

Свойство Обязательное Тип
type Да строка
id Да строка
label Нет строка
tip Нет строка

Таблица сверху содержит общие свойства
у всех элементов, кроме header

Всего разработано 11 элементов формы:
text, password, date, tel, email,
group, header, select, textarea,
checkbox, radio

Для того, чтобы определить элемент, нужно написать
его имя из списка выше в свойство type.

Значение свойства id попадет в HTML элемент формы
в виде значения атрибута id элемента и атрибута
name. Будьте внимательны.
Убедитесь, что каждый элемент имеет уникальный id

label - текст надписи над элементом.
tip - текст подсказки под элементом.

Пример создания текстового элемента:

let jsonObj = {
    // ... some code
    elements: [{/* .some code.*/}, {
        label: "Логин",
        type: "text",
        id: "login",
        tip: "Введите логин",
    }],
    // ... some code
}

Для типов text, password, tel, email
можно указать свойство pattern с регулярным
выражением. По данному выражению будет проходить
валидация введенных данных.

Пример создания элемента с валидацией:

let jsonObj = {
    // ... some code
    elements: [{/* .some code.*/}, {
        label: "Моб. телефон",
        type: "tel",
        id: "phoneNumber",
        tip: "Формат +7xxxxxxxxxx",
        pattern: "\\+7[0-9]{3}[0-9]{3}[0-9]{4}"
    }],
    // ... some code
}

Для типов text, password, tel, email
Для типов textarea можно указать свойство placeholder
Текст этого свойства попадет в атрибут placeholder
HTML элемента.

Пример создания элемента со свойством placeholder:

let jsonObj = {
    // ... some code
    elements: [{/* .some code.*/}, {
        type: "textarea",
        id: "about",
        label: "Расскажите о себе",
        placeholder: "Пару слов..."
    }],
    // ... some code
}

Тип date

Данный тип позволяет создать HTML элмент для установки
даты. Есть возможность добавить свойства max и min
max и min - необязательные свойства.
С их помощью можно утсановить диапазон задаваемой даты.
Значения свойств указываются в формате YYY-MM-DD.

Пример создания элемента с типом date:

let jsonObj = {
    // ... some code
    elements: [{/* .some code.*/}, {
        type: "date",
        label: "Дата рождения",
        max: "2006-07-01",
        min: "1901-01-01",
        id: "dateOfBirth",
    }],
    // ... some code
}

Тип header

header - тип, который отображает заголовок на форме.
Он имеет только одно свойство - value
Это свойство содержит текст заголовка.
Свойство id необязательно.

Пример создания заголовка формы:

let jsonObj = {
    // ... some code
    elements: [{/* .some code.*/}, {
        type: "header",
        value: "Контактная информация"
    }],
    // ... some code
}

Тип group

Группа элементов делит ширину каждого участника группы
пополам.

group - тип, который создает группу элементов
Он имеет только одно свойство - groupElements
groupElements - это массив объектов (элементов)

Пример создания группы элементов:

let jsonObj = {
    // ... some code
    elements: [{/* .some code.*/}, {
        type: "group",
        groupElements: [
            {
                label: "Фамилия",
                type: "text",
                id: "lastName",
            }, {
                label: "Имя",
                type: "text",
                id: "firstName",
            }
        ]
    }],
    // ... some code
}

Тип select

Классический элемент "выпадающий список".
Помимо стандартных свойств id, label, tip
имеет свойсто options - массив строк возможных значений
элементов списка.

В HTML разметке значения атрибута value тега <option>
заполняются числами по порядку от 0 до последнего элемента массива

Пример создания выпадающего списка:

let jsonObj = {
    // ... some code
    elements: [{/* .some code.*/}, {
        label: "Семейное положение",
        id: "maritalStatus",
        type: "select",
        options: ["женат", "холост", "вдовец"]
    }],
    // ... some code
}

Тип radio

Создание радиокнопки.
Помимо стандартных свойств id, label, tip
имеет свойсто values - массив строк возможных значений
группы радиокнопок.

В HTML разметке значения атрибута value тега
<input type="radio">
заполняются строками 'id'-0 где 'id' - id элемента;
0 - порядковый номер радиокнопки
(нумерация начинается с нуля)

Пример создания радиокнопки:

let jsonObj = {
    // ... some code
    elements: [{/* .some code.*/}, {
        type: "radio",
        label: "Пол",
        id: "sex",
        values: ["Мужской", "Женский"],
    }],
    // ... some code
}

Тип checkbox

Создание флажков.
Помимо стандартных свойств id, label, tip
имеет свойсто values - массив строк возможных значений
группы чекбоксов.

В HTML разметке значения атрибута value тега
<input type="checkbox">
заполняются строками 'id'-0 где 'id' - id элемента;
0 - порядковый номер чекбокса
(нумерация начинается с нуля)

Пример создания флажков:

let jsonObj = {
    // ... some code
    elements: [{/* .some code.*/}, {
        type: "checkbox",
        id: "fruits",
        label: "Какие фрукты Вы ели сегодня?",
        values: ["Яблоки", "Бананы", "Манго", "Мандарины"],
    }],
    // ... some code
}

Пример JSON объекта формы регистрации полета на Марс

{
  "caption": "Заявка на экскурсионный <br> полет на Марс",
  "theme": "night",
  "submit": {
    "text": "Полететь на Марс"
  },
  "elements": [
    {
      "label": "Фамилия",
      "type": "text",
      "id": "lastName_cyrillic",
      "tip": "Фамилию вводить кириллицей",
      "placeholder": "Введите фамилию"
    },
    {
      "label": "Имя",
      "type": "text",
      "id": "firstName_cyrillic",
      "placeholder": "Введите имя"
    },
    {
      "label": "Отчество",
      "type": "text",
      "id": "patronymic_cyrillic",
      "placeholder": "Введите отчество"
    },
    {
      "type": "group",
      "groupElements": [
        {
          "label": "Фамилия латиницей",
          "type": "text",
          "id": "lastName"
        },
        {
          "label": "Имя латиницей<br><br>",
          "type": "text",
          "id": "firstName"
        }
      ]
    },
    {
      "type": "date",
      "label": "Дата рождения",
      "max": "2006-07-01",
      "min": "1901-01-01",
      "id": "dateOfBirth"
    },
    {
      "type": "radio",
      "label": "Пол",
      "id": "sex",
      "values": [
        "Мужской",
        "Женский"
      ]
    },
    {
      "label": "Семейное положение",
      "id": "maritalStatus",
      "type": "select",
      "options": [
        "женат/замужем",
        "в \"гражданском браке\"",
        "разведен",
        "холост",
        "вдовец"
      ]
    },
    {
      "label": "Образование",
      "id": "education",
      "type": "select",
      "options": [
        "высшее",
        "среднее специальное",
        "среднее",
        "студент"
      ],
      "tip": "Эта информация действительно важна"
    },
    {
      "type": "header",
      "value": "Контактная информация"
    },
    {
      "label": "Моб. телефон",
      "type": "tel",
      "id": "phoneNumber",
      "tip": "Формат +7xxxxxxxxxx",
      "pattern": "\\+7[0-9]{3}[0-9]{3}[0-9]{4}"
    },
    {
      "label": "Электронная почта",
      "type": "email",
      "id": "email"
    },
    {
      "type": "checkbox",
      "id": "soberMind",
      "values": [
        "Ставя эту галочку, подтверждаю, что поставил её в трезвом уме и твёрдой памяти"
      ],
      "tip": "Обязательное поле"
    },
    {
      "type": "textarea",
      "id": "about",
      "label": "Расскажите о себе",
      "placeholder": "Пару слов..."
    }
  ]
}