CSS (Cascading Style Sheets)
CSS — каскадные таблицы стилей, содержащие правила оформления HTML-элементов веб-документов вида селектор{свойство:значение;}. CSS-селекторы сообщают браузеру, к каким именно элементам документа следует применять объявленные правила, а свойства и значения помогают управлять оформлением этих элементов. Как и в случае с JS-сценариями, CSS-код небольшого объёма может находиться в текущем веб-документе внутри контейнера <style type="text/css">…</style>. Но для удобочитаемости кода стили оформления резонно вынести в отдельный файл, создав в папке GameDev новый текстовый документ с именем style и расширением .css, который также следует открыть с помощью текстового редактора (и расположить открывшееся окно в правой части экрана). Для подключения CSS-правил из внешнего файла в HTML-документе в разделе заголовков после мета-тегов необходимо указать ссылку на стилевой файл внутри одиночного тега <link> с добавлением служебных атрибутов: <link href="style.css" rel="stylesheet" type="text/css">. После этого, вернувшись к CSS-окну, можно приступить к модернизации дизайна интерфейса игрового веб-приложения.
Процесс создания правил оформления контента подобен форматированию текста в текстовом редакторе: для контента можно указать цвет заднего фона (background-color), установить фоновый рисунок (background-image), определить границы элементов (border), оформить шрифт текста (font), задать межстрочный интервал (line-height), добавить внешние и внутренние поля-отступы (margin; padding), выбрать способ выравнивания контента (text-align) и т.д. Учитывая, что Судоку представляет собой таблицу с 81 ячейкой, в первую очередь резонно объявить правила для элементов в игровой таблице, указав параметры дисплея, текстовых полей для ввода чисел, кнопок, ячеек и самой таблицы. При этом важно помнить, что для лучшего восприятия информации следует отделять разные смысловые блоки интерфейса с помощью цвета заднего фона, больших отступов или прорисованных линий.
Листинг-19. Объявление CSS-правила
/* Параметры дисплея */
.scr{
background-color:#aaa;
background-image:linear-gradient(#eee,transparent);
background-image:-webkit-linear-gradient(#eee,transparent);
border-radius:5px;
color:#fff;
cursor:default;
margin:0 5px 5px;
padding:6px 9px 9px;
text-align:left;
text-shadow:-1px -1px 1px #fff, 1px 1px 1px #000;
transition:2s;
-webkit-transition:2s
}
В листинге-19 объявлено правило отображения HTML-элемента с классом class="scr" (выполняющего функцию дисплея), на что указывает селектор класса .scr, записываемый с префиксом в виде точки перед именем. Как видно из примера, при необходимости в CSS-код также можно добавлять пояснительные комментарии, которые записываются подобно длинным JS-комментариям в конструкции из косых черт и звёздочек /*…*/. А правила записываются аналогично функциям или операторам JS между начальной и конечной фигурными скобками {…}. Но в CSS вместо привычного оператора присваивания = значения свойств указываются через двоеточие. При этом, если для одного селектора требуется указать несколько свойств, эти записи разделяются точкой с запятой.
В начале CSS-кода с помощью свойства background-color указывается цвет заднего фона дисплея с оттенком серого #aaa. Цветовая схема в веб-дизайне традиционно задаётся в формате RGB (от англ. Red+Green+Blue) тремя числами, регулирующими соотношение красного, зелёного и синего. Эти числа можно указывать в шестнадцатеричной системе счисления от 00 до ff, в десятичном виде от 0 до 255 и в процентом соотношении от 0% до 100%. Причём, если в группах шестнадцатеричного номера цвета используются одинаковые цифры вида #1199ff, их допустимо записывать в сокращённой форме #19f. Таким образом, номер цвета #aaa может указываться в полном шестнадцатеричном виде #aaaaaa, а также с помощью служебной функции rgb() в десятичном виде rgb(170,170,170) либо в процентах rgb(66%,66%,66%). Но сокращённый формат записи позволяет сэкономить объём документа и время, затраченное на указание таких значений!
Далее с помощью свойства background-image устанавливается фоновый рисунок в виде полупрозрачного линейного градиента linear-gradient() с начальным значением цвета #eee (светло-серый) и служебным словом transparent вместо конечного цвета заливки. Значение transparent сообщаемого браузеру о том, что в качестве конечного цвета градиента следует выбрать цвет заднего фона (то есть ранее объявленное значение #aaa). Такая заливка градиента поможет с внедрением опции для изменения цветовой схемы дисплея. Для разработки кросс-браузерных веб-приложений некоторые свойства и значения правил требуется дублировать, указывая разные служебные слова, поддерживаемые разными браузерами. В данном случае дублируется значение linear-gradient() с добавлением префикса -webkit- для совместимости с разными версиями браузеров.
После этого с помощью свойства border-radius задаются закруглённые края с радиусом в 5 пикселей (px). Затем с помощью свойства color указывается цвет текста дисплея со значением #fff (белый). Следом с помощью свойства cursor переопределяется вид курсора мыши на значение по умолчанию (default), чтобы при наведении на дисплей курсор отображался в виде стрелочки (при запуске веб-приложения на смартфоне данное правило будет проигнорировано из-за отсутствия мышки). Далее задаются внешние и внутренние поля дисплея с помощью свойств margin и padding, которым присваиваются тройные значения, перечисленные через пробел. Для внешних полей указываются нулевой верхний отступ (перед дисплеем) и одинаковые 5-пиксельные боковые (слева и справа от дисплея) и нижний отступы (после дисплея). А для внутренних полей указываются верхний отступ в 6px и одинаковые боковые и нижний отступы в 9px.
Затем с помощью свойства text-align определяется центрированный способ выравнивания контента (center). Следом с помощью свойства text-shadow задаются параметры тени текста дисплея, причём для тени указываются два разных значения, перечисленные через запятую. В первом случае устанавливается тень с 1-пиксельными сдвигами влево по горизонтали и вверх по вертикали, толщиной в 1px и с белым цветом #fff. Во втором случае устанавливается чёрная тень со сдвигами на 1px вправо и вниз. Такой способ с указанием двойных значений создаёт визуальный 3D-эффект объёмного текста!
В конце CSS-правила с помощью свойства transition в интерфейс внедряется визуальный эффект, позволяющий осуществлять плавный переход (в течение 2 секунд) при смене цветовой схемы дисплея. Как и в случае с линейным градиентом, запись со свойством transition дублируется для поддержки разными версиями браузеров, но в данном случае префикс -webkit- добавляется перед свойством, а не перед значением.
В приведённом примере цвет текста элемента указывается с помощью CSS-записи .scr{color:#fff}
, которая равнозначна HTML-записи <div class="scr" id="scr" style="color:#ffffff">!</div>
и JS-записи document.getElementById('scr').style.color='#ffffff'
. Таким образом, управлять оформлением контента веб-страниц можно и в HTML, и в JS, указывая соответствующие параметры для каждого элемента в отдельности. Но в CSS можно не только объявлять правила отображения отдельных элементов, но и создавать правила для родственных элементов одного типа (например, чтобы в браузере отображались одинаково все элементы input), а также формировать групповые классы (например, чтобы одинаково отображались элементы div и p, в которых указан родственный класс class="txt").
Для применения правила объявленного класса необходимо в начале кода JS-функции GUI() внутри тега <div> с id="scr" добавить атрибут class="scr": <div class="scr" id="scr">. Аналогично можно объявлять правила оформления с разными параметрами для разных состояний элементов или для элементов с определёнными атрибутами.
Листинг-20. Параметры игровой таблицы
table{
background-color:#ccc;
border:2px solid #777;
border-left-color:#fff;
border-top-color:#fff;
border-radius:10px;
border-spacing:0;
box-shadow:2px 2px 3px #777
}
td{
padding:0;
vertical-align:middle
}
/* Параметры ячейки с дисплеем */
td[colspan="9"]{padding:5px 0 0}
В листинге-20 представлен пример использования селекторов элементов и селектора атрибутов. В начале кода для элемента table задаётся серебристый цвет заднего фона #ccc. Затем указываются границы (border) с толщиной в 2px, со сплошным стилем прорисовки solid и с тёмно-серым цветом #777. При этом для создания объёмного 3D-эффекта цвет заливки левой и верхней границ переопределяется на белый #fff. Далее устанавливается радиус закругления углов в 10px. А с помощью свойства border-spacing задаётся нулевой интервал между ячейками таблицы (чтобы игровое поле не было слишком большим). В конце первого правила с помощью свойства box-shadow вокруг границ игровой таблицы устанавливается тень со сдвигом вправо на 1px, вниз на 2px, толщиной в 3px и с тёмно-серым цветом #777.
Во втором правиле для всех элементов td объявляются нулевые внутренние поля (padding). А с помощью свойства vertical-align и значения middle в табличных ячейках определяется способ выравнивания контента по вертикали (по центру). В конце кода используется селектор атрибута td[colspan="9"], позволяющий отдельно установить для содержащей дисплей ячейки <td> с атрибутом colspan="9" (указанным в селекторе в квадратных скобках после наименования элемента) внутренний верхний отступ в 5px.
В CSS правила отображения с селекторами элементов применяются ко всем указанным элементам документа автоматически, не требуя дополнительных манипуляций с кодом. А правила с селекторами атрибутов применяются только к элементам документа с указанными атрибутами.
Листинг-21. Параметры текстовых полей
input{
border-radius:5px;
font-family:Tahoma;
font-size:18px;
height:28px;
width:28px
}
input[disabled]{
border-style:outset;
color:#555;
font-weight:bold
}
input[id$="1"],input[id$="4"]{margin-left:5px}
input[id$="6"],input[id$="9"]{margin-right:5px}
input[id^="i4"],input[id^="i7"]{margin-top:5px}
input,td{text-align:center}
/* Параметры <input> для устройств с шириной экрана <= 360px */
@media(max-width:360px){
input{
height:25px;
width:25px
} }
В листинге-21 приведён пример с использованием особых CSS-выражений (условий) в квадратных скобках селекторов атрибутов. В первом правиле задаётся радиус закругления границ текстовых полей. Параметры самих границ при этом не указываются, чтобы использовались браузерные значения по умолчанию. Далее для текстовых полей определяются гарнитура Tahoma и размер шрифта в 18px с помощью свойств font-family и font-size. Затем с помощью свойств height и width задаются одинаковые высота и ширина текстовых полей в 28px.
Во втором правиле с помощью селектора атрибута input[disabled] элементам input с указанным атрибутом disabled задаются стиль границ (border-style) с имитацией объёмного 3D-эффекта outset, светло-чёрный цвет текста и полужирное начертание шрифта bold (font-weight).
В веб-дизайне для одних и тех же свойств разных элементов могут задаваться одинаковые значения. В таких случаях селекторы допустимо объединять в группы, перечисляя их через запятую, и указывать в фигурных скобках общие значения одинаковых свойств.
В приведённом примере по такому принципу объявляются три однотипных правила, устанавливающие внешние отступы избранных элементов input с помощью селекторов атрибутов, отделяя сгруппированные 3x3-секции. Запись внутри квадратных скобок селектора атрибута input[id$="1"] означает, что объявленное правило должно применяться ко всем элементам input, чьи id заканчиваются на 1 (то есть текстовые поля из первого столбца таблицы). Аналогично правило с input[id$="4"] должно применяться ко всем input, чьи id заканчиваются на 4 (текстовые поля из четвёртого столбца). А правило с input[id^="i4"] должно применяться ко всем input, чьи id начинаются с "i4" (текстовые поля из четвёртой строки). Таким образом, для 1 и 4 столбцов задаётся внешний левый, для 6 и 9 столбцов — внешний правый, а для 4 и 7 строк — внешний верхний отступы в 5px. Далее для текстовых полей input и табличных ячеек td объявляется общее правило с центрированным выравниванием контента.
В конце кода с помощью служебного слова @media и свойства max-width объявляется правило, которое будет применяться к элементам input только на небольших пользовательских устройствах с шириной экрана не более 360px. Данное правило уменьшает высоту (height) и ширину (width) текстовых полей до 25px, чтобы игровая таблица не выходила за рамки небольшого экрана мобильного телефона.
В CSS дополнительные ограничения с @media помогают создавать адаптивный дизайн, частично или полностью отображая контент на разных устройствах по-разному. При этом важно помнить, что в нижней части игровой таблицы расположены три кнопки, ширина которых не должна троекратно превышать минимальную ширину ячеек (3*25=75px).
Листинг-22. Оформление кнопок
div[id="bt1"]{color:#b00}
#bt2{color:#090}
div#bt3{color:#00d}
.btn{
background-color:#ddd;
border:1px outset #fff;
border-radius:50%;
cursor:pointer;
display:inline-block;
font-family:Arial;
font-weight:bold;
line-height:1.5;
text-align:center;
text-indent:0
}
/* Цвет фона кнопки при наведении курсора */
.btn:hover{background-color:#eee}
div.btn{
margin:9px auto 6px;
width:75px
}
span.btn{
margin:0;
width:50px
}
В листинге-22 представлены правила отображения кнопок с использованием селекторов идентификаторов и селекторов классов. В начале кода объявляются три однотипных правила, устанавливающих разный цвет текста для трёх кнопок.
Как видно из примера, в CSS при объявлении правил оформления элементов с указанным id можно использовать селекторы атрибутов либо специальные селекторы идентификаторов, записываемые по принципу хэштега с префиксом в виде решётки # перед именем id (при необходимости перед решёткой можно дополнительно указать конкретный элемент). Но для экономии времени и места проще всего использовать краткий вариант записи селекторов идентификаторов с решёткой и именем id (#bt1, #bt2 и #bt3). А селекторы атрибутов резонно использовать лишь в особых случаях, например, когда потребуется объявить правила для большой группы однотипных элементов со схожими значениями атрибутов (как в примере из листинга-21).
Далее для кнопок формируется правило с общим классом .btn (от англ. Button). В начале класса указывается цвет заднего фона. Затем задаются границы с 3D-стилем outset и радиус закругления в 50%. Следом устанавливается вид курсора мыши на pointer (чтобы при наведении на кнопки курсор выглядел так, как при наведении на гиперссылки). После этого с помощью свойства display указывается блочный способ отображения кнопок inline-block. А для шрифта задаются гарнитура Arial с полужирным начертанием bold. В конце класса с помощью свойств line-height, text-align и text-indent для текста кнопок задаются полуторный межстрочный интервал, центрированный способ выравнивания контента и нулевая красная строка.
Помимо объявления правил для элементов в статичных состояниях, в CSS можно управлять оформлением контента с учётом наступления разных событий-триггеров, инициируемых поведением пользователя. В приведённом примере после класса .btn объявляется псевдокласс с добавлением двоеточия и служебного слова hover, отвечающего за движение курсора мыши по кнопке или нажатие пальцем на кнопку на сенсорном экране. При наступлении одного из этих событий у используемой кнопки должен будет измениться цвет фона на более светлый.
В случаях, когда схожим элементам необходимо задать как общие, так и различные параметры, одинаковые значения можно объявлять в общем классе, а для различающихся параметров резонно формировать отдельные правила с указанием конкретных элементов. В конце кода объявляются два однотипных правила с селекторами div.btn и span.btn для отображения разных кнопок, представленных в документе в тегах <div> и <span>. Для элементов div с классом .btn задаются внешние отступы (значение auto означает, что боковые отступы должны определиться браузером автоматически), а также ширина кнопок в 75px. Для элементов span с классом .btn задаются нулевые внешние поля и укороченная ширина в 50px (поскольку в информационном блоке с кратким описанием основной акцент делается на компактности вида). Таким образом, инструментарий CSS позволяет с помощью небольших фрагментов кода управлять оформлением больших веб-документов!
Листинг-23. Дополнительные параметры веб-документа
/* Цвет текста документа */
*{color:#333}
a{
border-bottom:1px dashed #00d;
color:#00d;
text-decoration:none
}
a:hover{
border-color:#77f;
color:#77f
}
#bar{
background-color:#ddd;
background-image:linear-gradient(#eee,#ccc);
background-image:-webkit-linear-gradient(#eee,#ccc);
border-bottom:double #ddd;
cursor:default;
padding:6px 0 9px
}
#bar,#clock,#cop{text-align:right}
body{
background-color:#eee;
font-family:Verdana;
font-size:18px;
text-align:center
}
body,#cop,h1,h2{margin:0}
#clock{
color:#fff;
padding-right:15px;
text-shadow:1px 1px 1px #aaa
}
#clock,#cop{font-size:17px}
#clock,h1{display:inline-block}
#cop,#ds{padding:10px 15px}
#ds{background:#fafafa}
#game{margin:15px auto 20px}
h1{padding-left:8px}
h1,h2{
color:#777;
font-size:20px;
text-align:left
}
p{
line-height:1.5;
margin:5px 0 0;
text-align:justify
}
В листинге-23 приведён пример правил оформления для различных элементов веб-документа. В начале кода объявляется правило с универсальным селектором * для установки цвета текста документа с чёрным оттенком #333. Звёздочка * в данном случае обозначает любые элементы документа, для которых не определена другая цветовая схема.
Во втором правиле с селектором элемента a для гиперссылки задаётся цвет текста и меняется сплошное подчёркивание на штриховое. Для этого устанавливается нижняя граница в виде штрихов (dashed). А свойству text-decoration присваивается обнуляющее значение none.
В третьем правиле с селектором псевдокласса :hover переопределяется цветовая схема гиперссылки, которая будет применяться при движении курсора или при нажатии пальцем. Для этого меняются цвет нижней границы и цвет текста.
Затем объявляется правило с селектором идентификатора #bar, задающее параметры верхнего блока (содержащего заголовок первого уровня и часы). В начале правила устанавливаются цвет заднего фона и фоновый рисунок в виде линейного градиента. Далее задаётся двойная нижняя граница и переопределяется вид курсора на стрелочку по умолчанию. В конце правила указываются внутренние отступы. После этого формируется общее правило с селекторами идентификаторов #bar, #clock и #cop, устанавливающее выравнивание контента по правому краю для верхней панели и блоков с часами и копирайтом.
Далее с помощью селектора элемента body для тела документа устанавливаются цвет заднего фона, гарнитура Verdana и размер шрифта в 18px, а также центрированный способ выравнивания контента. Параметры, указанные для элемента body, должны наследоваться вложенными элементами, для которых не определены другие значения. Но при необходимости указать параметры, которые должны быть обязательно применимы ко всем элементам документа, резонно использовать универсальный селектор в виде звёздочки!
Следом формируется общее правило с группой селекторов, задающее телу документа, блоку с копирайтом и заголовкам первого и второго уровня нулевые внешние отступы. Затем объявляется правило с селектором идентификатора #clock, устанавливающее для блока с часами белый цвет текста, правый внутренний отступ и тень текста. Далее формируется общее правило для блоков с часами и копирайтом, задающее размер шрифта в 17px. Следом формируется общее правило для блока с часами и заголовка первого уровня, устанавливающее свойству display значение inline-block, чтобы эти элементы могли отображаться в браузере небольшими блоками в одной общей строке. После этого формируется общее правило с селекторами идентификаторов #cop и #ds, задающее внутренние отступы блокам с копирайтом и кратким описанием.
Затем объявляется правило с селектором идентификатора #ds, устанавливающее фон белого оттенка #fafafa. Следом для игрового блока с идентификатором #game указываются внешние отступы. Далее объявляются параметры заголовков первого и второго уровня. В правиле с селектором элемента h1 задаётся внутренний левый отступ. А в общем правиле с селекторами элементов h1 и h2 для текста заголовков устанавливаются тёмно-серый цвет, размер шрифта в 20px и выравнивание по левому краю. В конце кода объявляется правило с селектором элемента p, задающее абзацам документа межстрочный полуторный интервал, внешние отступы, а также способ выравнивания по ширине контента (justify).
После объявления правил оформления элементов документа можно добавить новые правила, которые помогут внедрить в веб-страницу всплывающее меню для персонализации настроек! Для реализации этой задачи как минимум понадобятся значок меню, который можно представить в теге <span> в виде символа в формате Юникода, например, триграммы «☰» с кодом ☰, используемой в эзотерических текстах с уклоном в Фэншуй! Для значка-кнопки следует указать id #men (от англ. Menu) и два однотипных класса .me0 (от англ. Menu+0) и .me1 (от англ. Menu+1), управляющие оформлением значка в статичном и активном состояниях. При этом значок меню должен быть хорошо заметен, поэтому его резонно расположить в начале верхнего блока слева от заголовка, объединив их в общий блок <div> с id #adj (от англ. Adjacent), чтобы было проще позиционировать эти смежные элементы в левой части верхней панели, а блок с часами — в правой. Блок со всплывающим меню можно представить в теге <div> с id="menu" сразу после верхней панели. Поскольку у блока с меню должно быть два состояния (скрытый и видимый режимы), для этого элемента также необходимо предусмотреть два однотипных класса .hid (от англ. Hidden) и .vis (от англ. Visible).
В самом блоке меню понадобятся три дополнительных текстовых поля <input> с id #r, #g, #b, с помощью которых пользователь сможет устанавливать желаемое соотношение красного, зелёного и синего цветов для заднего фона дисплея. А чтобы пользователю было проще ориентироваться в RGB-цветах, резонно добавить шаблоны с цветами радуги, которые можно представить в тегах <span> с id вида #bg7 (от англ. Background+7). Также в меню можно добавить переключатель, позволяющий пользователю отключать и включать дисплей. В качестве переключателя можно использовать тег <input> с указанием специального типа type="checkbox" (квадрат с галочкой) либо внедрить самостоятельно созданный триггер. Для внедрения триггера понадобятся два тега <span>, один из которых будет вложен в другой. Внутренний <span> будет выполнять функцию флажка оповещения, поэтому для него можно ввести id или класс с именем flg (от англ. Flag). Внешний <span> будет использоваться в качестве поля для флажка-переключателя, поэтому для него потребуются id #swi (от англ. Switch) и два однотипных класса .on и .off, управляющие разными положениями флажка. Рядом с переключателем можно добавить пояснительный текст вида «Дисплей вкл.», объединённый с переключателем в общий блок <div> с id #box. Для наглядности этот текст можно перечёркивать при отключении дисплея. Для управления оформлением текста следует добавить два однотипных класса .decThr (от англ. Decoration+Through) и .decNon (от англ. Decoration+None).
Листинг-24. Параметры элементов меню
/* Позиционирование блоков */
#adj,#menu{position:absolute}
#adj,#menu,.off{text-align:left}
/* RGB-поля */
#b,#g,#r{width:48px}
#b{color:#00d}
#g{color:#090}
#r{color:#b00}
/* Шаблоны */
.bg0{
border:1px outset #fff;
border-radius:5px;
opacity:.5
}
.bg0:hover{opacity:1}
.bg0,.flg{width:20px}
.bg0,.flg,#swi{height:20px}
.bg0,.flg,#men,#swi{display:inline-block}
#bg1{background:#b00}
#bg2{background:#ea0}
#bg3{background:#dd0}
#bg4,.on{background:#090}
#bg5{background:#6dd}
#bg6{background:#00d}
#bg7{background:#b0b}
/* Блок с переключателем */
#box{
border-bottom:1px solid #aaa;
color:#777;
font-family:Tahoma;
padding:0 0 5px
}
/* Блок с настройками цветовой схемы */
.clr{
border-top:1px solid #eee;
padding:5px 0 0
}
/* Текст без оформления */
.decNon{text-decoration:none}
/* Перечёркивание текста */
.decThr{text-decoration:line-through}
/* Флажок */
.flg{
background-image:linear-gradient(#fff,#aaa);
background-image:-webkit-linear-gradient(#fff,#aaa);
box-shadow:0px 0px 2px #555
}
.flg,.off{background-color:#ddd}
.flg,#swi{border-radius:10px}
/* Выкл. */
.hid{display:none}
/* Значок меню */
.me0,.me1:hover{color:#aaa}
.me0:hover,.me1{color:#eee}
#men{
border-right:1px solid #aaa;
padding-left:12px;
text-shadow:0 1px 1px #777;
width:30px
}
#men,#menu{cursor:pointer}
/* Вкл. */
.on{text-align:right}
/* Блок с шаблонами */
.pat{
padding-top:5px;
text-align:center
}
/* Переключатель */
#swi{
border:1px solid #aaa;
transition:1s;
-webkit-transition:1s;
vertical-align:middle;
width:39px
}
/* Всплывающее меню */
.vis{
background:#ccc;
border-bottom:double #ddd;
border-right:double #ddd;
border-radius:5px;
color:#777;
line-height:1;
padding:5px
}
В листинге-24 представлены правила оформления, позволяющие внедрить в документ всплывающее меню. В начале кода формируется общее правило с селекторами идентификаторов #adj и #menu, с помощью свойства position задающее абсолютный способ позиционирования блоков, позволяя следующим за ними элементам располагаться в браузере на тех же позициях, где и эти блоки. В первом случае абсолютное позиционирование позволяет блоку с часами отображаться в одной плоскости вместе с верхним левым блоком (со значком меню и заголовком), во втором случае — накладывать контент всплывающего меню поверх секции игровой таблицы. Далее формируется общее правило с id #adj и #menu и классом .off, устанавливающее выравнивание контента по левому краю. Затем объявляются правила с селекторами #r, #g и #b, задающие текстовым полям меню ширину в 48px и цвет текста.
После этого объявляется общий класс .bg0, задающий для шаблонов цветовой схемы в статичном состоянии границы и радиус закругления, а также эффект полупрозрачности (opacity) со значением .5, что соответствует 50%. Следом объявляется правило с псевдоклассом .bg0:hover для переопределения полупрозрачности шаблонов на 1 (100%). Затем формируются общее правило с классами .bg0 и .flg, задающее ширину в 20px, и общее правило с этими классами и id #swi, задающее высоту в 20px. Далее формируется общее правило с классами .bg0 и .flg и id #men и #swi, устанавливающее свойству display значение inline-block, чтобы эти элементы могли отображаться в браузере небольшими блоками с заданными размерами. После этого объявляются однотипные правила, устанавливающие цвет заднего фона 7 шаблонов с id #bg1–7 и поля переключателя с классом .on (во включённом режиме).
Затем объявляется правило с id #box, задающее нижнюю границу, цвет текста, гарнитуру шрифта и внутренний нижний отступ. Следом объявляется класс .clr (от англ. Color), задающий верхнюю границу и внутренний верхний отступ для блока с настройками цветовой схемы. Указанные в этих правилах параметры границ и внутренних отступов позволяют визуально отделить два разных блока меню, облегчая восприятие интерфейса!
Далее объявляются два однотипных правила с классами .decNon и .decThr, управляющие оформлением пояснительного текста. В активном режиме с включённым переключателем к блоку будет применяться класс .decNon без дополнительного оформления. В выключенном режиме — класс .decThr с оформлением текста перечёркнутой горизонтальной линией.
После этого объявляется класс .flg, устанавливающий флажку-переключателю фоновый рисунок в виде линейного градиента и тень вокруг границ (box-shadow). Затем формируются общее правило с классами .flg и .off, устанавливающее цвет заднего фона, и общее правило с классом .flg и id #swi, задающее радиус закругления. Далее объявляется класс .hid, используемый для скрытия дисплея и всплывающего меню с помощью значения none для свойства display.
Следом формируются два однотипных правила для значка меню, регулирующие цвет значка в обычном режиме с классом .me0 и активированном режиме с классом .me1. В статичном состоянии для значка меню будет применяться цвет с оттенком серого #aaa, а при наведении курсора мыши цвет будет меняться на светло-серый оттенок #eee. В нажатом состоянии — наоборот.
Затем объявляется правило с id #men, содержащее параметры значка меню, не зависящие от его состояния. В начале правила задаётся правая граница, помогающая визуально отделить значок от смежного заголовка. Далее указывается левый внутренний отступ и параметры тени значка. В конце правила задаются ширина значка в 30px. После этого формируется общее правило с id #men и #menu, устанавливающее курсор-пойнтер.
Далее объявляется класс .on, задающий выравнивание контента по правому краю. Следом объявляется класс .pat (от англ. Pattern), устанавливающий сгруппированному блоку с шаблонами верхний внутренний отступ и центрированный способ выравнивания контента.
После этого объявляется правило с id #swi, управляющее оформлением поля с переключателем. В начале правила задаются границы и эффект плавного перехода (transition) между стилями .on и .off при каждом переключении флажка. Затем задаётся центрированный способ выравнивания контента по вертикали и ширина в 39px.
В конце кода объявляется класс .vis, используемый для активации видимого режима всплывающего меню. В начале правила устанавливается серебристый цвет заднего фона. Далее задаются двойные нижняя и правая границы и радиус закругления. Затем для текста указываются тёмно-серый цвет и единичный межстрочный интервал. В конце правила задаются внутренние отступы в 5px.
Таким образом, с помощью коллаборации CSS с HTML и JS можно успешно управлять внешним видом контента веб-документа!
Листинг-25. Содержимое файла style.css
*{color:#333}
a{border-bottom:1px dashed #00d}
a,#b,#bt3{color:#00d}
a,.decNon{text-decoration:none}
a:hover{
border-color:#77f;
color:#77f
}
#adj,#menu{position:absolute}
#adj,h1,h2,#menu,.off,.scr{text-align:left}
#b,#g,#r{width:48px}
#bar{
background-image:linear-gradient(#eee,#ccc);
background-image:-webkit-linear-gradient(#eee,#ccc);
border-bottom:double #ddd;
padding:6px 0 9px
}
#bar,.btn,.flg,.off{background-color:#ddd}
#bar,#clock,#cop,.on{text-align:right}
#bar,.scr{cursor:default}
.bg0{opacity:.5}
.bg0:hover{opacity:1}
.bg0,.btn{border:1px outset #fff}
.bg0,.btn,#clock,.flg,h1,#men,#swi{display:inline-block}
.bg0,.flg{width:20px}
.bg0,.flg,#swi{height:20px}
.bg0,input,.scr,.vis{border-radius:5px}
#bg1{background:#b00}
#bg2{background:#ea0}
#bg3{background:#dd0}
#bg4,.on{background:#090}
#bg5{background:#6dd}
#bg6{background:#00d}
#bg7{background:#b0b}
body{font-family:Verdana}
body,.btn:hover{background-color:#eee}
body,.btn,input,.pat{text-align:center}
body,#cop,h1,h2{margin:0}
body,input{font-size:18px}
#box{
border-bottom:1px solid #aaa;
padding:0 0 5px
}
#box,h1,h2,.vis{color:#777}
#box,input{font-family:Tahoma}
#bt1,#r{color:#b00}
#bt2,#g{color:#090}
.btn{
border-radius:50%;
font-family:Arial;
text-indent:0
}
.btn,input[disabled]{font-weight:bold}
.btn,#men,#menu{cursor:pointer}
.btn,p{line-height:1.5}
#clock{
padding-right:15px;
text-shadow:1px 1px 1px #aaa
}
#clock,#cop{font-size:17px}
#clock,.scr{color:#fff}
.clr{border-top:1px solid #eee}
.clr,td[colspan="9"]{padding:5px 0 0}
#cop,#ds{padding:10px 15px}
.decThr{text-decoration:line-through}
div.btn{
margin:9px auto 6px;
width:75px
}
#ds{background:#fafafa}
.flg{
background-image:linear-gradient(#fff,#aaa);
background-image:-webkit-linear-gradient(#fff,#aaa);
box-shadow:0px 0px 2px #555
}
.flg,#swi,table{border-radius:10px}
#game{margin:15px auto 20px}
h1{padding-left:8px}
h1,h2{font-size:20px}
.hid{display:none}
input{
height:28px;
width:28px
}
input[disabled]{
border-style:outset;
color:#555
}
input[id$="1"],input[id$="4"]{margin-left:5px}
input[id$="6"],input[id$="9"]{margin-right:5px}
input[id^="i4"],input[id^="i7"]{margin-top:5px}
.me0,.me1:hover{color:#aaa}
.me0:hover,.me1{color:#eee}
#men{
border-right:1px solid #aaa;
padding-left:12px;
text-shadow:0 1px 1px #777;
width:30px
}
p{
margin:5px 0 0;
text-align:justify
}
.pat{padding-top:5px}
.scr{
background-color:#aaa;
background-image:linear-gradient(#eee,transparent);
background-image:-webkit-linear-gradient(#eee,transparent);
margin:0 5px 5px;
padding:6px 9px 9px;
text-shadow:-1px -1px 1px #fff, 1px 1px 1px #000;
transition:2s;
-webkit-transition:2s
}
span.btn{width:50px}
#swi{
border:1px solid #aaa;
transition:1s;
-webkit-transition:1s;
width:39px
}
#swi,td{vertical-align:middle}
table{
background-color:#ccc;
border:2px solid #777;
border-left-color:#fff;
border-top-color:#fff;
border-spacing:0;
box-shadow:1px 2px 3px #777
}
td{padding:0}
.vis{
background:#ccc;
border-bottom:double #ddd;
border-right:double #ddd;
line-height:1;
padding:5px
}
@media(max-width:360px){
input{
height:25px;
width:25px
} }
В листинге-25 приведена финальная версия CSS-кода файла style.css с упорядоченными правилами оформления элементов документа. Для применения новых CSS-правил необходимо внести изменения в скрипт и HTML-документ, добавив описанные элементы, а также JS-функции для взаимодействия с ними.
Листинг-26. Содержимое файла sudoku.html
<!doctype html>
<html lang="ru">
<head>
<title>Судоку с ИИ</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Веб-приложение для игры и обучения детей и взрослых людей…">
<link href="style.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="script.js"></script>
</head>
<body onLoad="starter()">
<div id="bar">
<div id="adj">
<span class="me0" id="men" onClick="menu()">☰</span>
<h1>Судоку</h1>
</div>
<div id="clock"></div>
</div>
<div class="hid" id="menu"></div>
<div id="game" onClick="mof()">Загрузка…</div>
<div id="ds">
<h2>Описание приложения</h2>
<p><span class="btn">!</span> — запрос подсказки;</p>
<p><span class="btn">►</span> — новая игра;</p>
<p><span class="btn">✓</span> — проверка решения.</p>
<p>Веб-приложение для игры и обучения детей и взрослых людей!</p>
</div>
<p id="cop">© Мазаяки</p>
</body>
</html>
В листинге-26 приведена финальная версия HTML-кода файла sudoku.html с новыми элементами, необходимыми для внедрения всплывающего меню.
Листинг-27. Содержимое файла script.js
var A=new Array(),C=new Array(),Cr=0,Dy,HN,Me=2,Swi=1,TC,TL=1,Tmr=0,Txt;
for(i=1;i<10;i++){A[i]=new Array()}
A[1][1]=1;A[1][2]=2;A[1][3]=4;A[1][4]=7;A[1][5]=6;A[1][6]=5;A[1][7]=8;A[1][8]=9;A[1][9]=3;
A[2][1]=6;A[2][2]=7;A[2][3]=9;A[2][4]=8;A[2][5]=4;A[2][6]=3;A[2][7]=2;A[2][8]=5;A[2][9]=1;
A[3][1]=3;A[3][2]=8;A[3][3]=5;A[3][4]=2;A[3][5]=1;A[3][6]=9;A[3][7]=7;A[3][8]=4;A[3][9]=6;
A[4][1]=4;A[4][2]=5;A[4][3]=2;A[4][4]=9;A[4][5]=8;A[4][6]=1;A[4][7]=6;A[4][8]=3;A[4][9]=7;
A[5][1]=9;A[5][2]=3;A[5][3]=8;A[5][4]=6;A[5][5]=2;A[5][6]=7;A[5][7]=4;A[5][8]=1;A[5][9]=5;
A[6][1]=7;A[6][2]=6;A[6][3]=1;A[6][4]=5;A[6][5]=3;A[6][6]=4;A[6][7]=9;A[6][8]=2;A[6][9]=8;
A[7][1]=8;A[7][2]=9;A[7][3]=3;A[7][4]=4;A[7][5]=5;A[7][6]=6;A[7][7]=1;A[7][8]=7;A[7][9]=2;
A[8][1]=5;A[8][2]=4;A[8][3]=6;A[8][4]=1;A[8][5]=7;A[8][6]=2;A[8][7]=3;A[8][8]=8;A[8][9]=9;
A[9][1]=2;A[9][2]=1;A[9][3]=7;A[9][4]=3;A[9][5]=9;A[9][6]=8;A[9][7]=5;A[9][8]=6;A[9][9]=4;
C['r']=170;C['g']=170;C['b']=170;
function cbx(){
Swi=(Swi==1)?0:1;
document.getElementById('scr').className=(Swi==0)?'hid':'scr';
document.getElementById('swi').className=(Swi==0)?'off':'on';
document.getElementById('box').className=(Swi==0)?'decThr':'decNon'
}
function chk(){
var err=0,row=0,col=0,s9=0,sc,sr;
for(i=1;i<10;i++){
sc=0;sr=0;
for(j=1;j<10;j++){
sr+=1*document.getElementById('i'+i+j).value;
sc+=1*document.getElementById('i'+j+i).value
}
if(sc!=45||sr!=45){err=1;break}
}
if(err==0){
for(i=1;i<4;i++){
for(j=1;j<4;j++){
s9+=1*document.getElementById('i'+(i+row)+(j+col)).value
}
if(i==3){
if(s9!=45){err=1;break}
s9=0;col+=3;
if(col>6){col=0;row+=3}
if(row<7){i=0}
} } }
Txt=(err==1)?'Эпик-фэйл!':'Судоку решена!';
TC=(err==1)?'b00':'090';TL=1;
if(Swi==0){alert(Txt)}
}
function clr(pt){
switch(pt){
case 1:C['r']=187;C['g']=0;C['b']=0;break;
case 2:C['r']=238;C['g']=170;C['b']=0;break;
case 3:C['r']=221;C['g']=221;C['b']=0;break;
case 4:C['r']=0;C['g']=99;C['b']=0;break;
case 5:C['r']=66;C['g']=221;C['b']=221;break;
case 6:C['r']=0;C['g']=0;C['b']=221;break;
case 7:C['r']=187;C['g']=0;C['b']=187;break;
default:C['r']=170;C['g']=170;C['b']=170
}
document.getElementById('r').value=C['r'];
document.getElementById('g').value=C['g'];
document.getElementById('b').value=C['b'];
custom()
}
function custom(){
C['r']=document.getElementById('r').value;
C['g']=document.getElementById('g').value;
C['b']=document.getElementById('b').value;
document.getElementById('scr').style.backgroundColor='rgb('+C['r']+','+C['g']+','+C['b']+')'
}
function GUI(){
var col,m=new Array(),n,row,ui='<table align="center"><tbody>';
ui+='<tr><td colspan=9><div class="';
ui+=(Swi==1)?'scr':'hid';
ui+='" id="scr">О</div></td></tr>';
HN=0;
for(i=0;i<7;i+=3){
col=tri();
for(j=1;j<10;j++){
for(l=1;l<4;l++){m[l]=A[j][l+i]}
for(l=1;l<4;l++){A[j][l+i]=m[col[l]]}
}
row=tri();
for(j=1;j<10;j++){
for(l=1;l<4;l++){m[l]=A[l+i][j]}
for(l=1;l<4;l++){A[l+i][j]=m[row[l]]}
} }
for(i=1;i<10;i++){
ui+='<tr>';
for(j=1;j<10;j++){
if(j==1){n=rnd(3)}
if(j==4){n=rnd(3)+3}
if(j==7){n=rnd(3)+6}
ui+='<td><input id="i'+i+j+'" maxLength=1 ';
if(j==n){ui+='value="'+A[i][n]+'" disabled'}
else{ui+='onKeyUp="InpChk(this)"'}
ui+='></td>'
}
ui+='</tr>'
}
ui+='<tr><td colspan=3><div class="btn" id="bt1" onClick="hint()">!</div></td><td colspan=3><div class="btn" id="bt2" onClick="GUI()">►</div></td><td colspan=3><div class="btn" id="bt3" onClick="chk()">✓</div></td></tr></tbody></table>';
document.getElementById('game').innerHTML=ui;
TC='ffffff';Txt='Обыграй ИИ';TL=1;
document.getElementById('scr').style.backgroundColor='rgb('+C['r']+','+C['g']+','+C['b']+')'
}
function hint(){
if(HN<15){
HN++;
var col=new Array(),n=0,row=new Array();
for(i=1;i<10;i++){
for(j=1;j<10;j++){
if(document.getElementById('i'+i+j).value==''){
n++;row[n]=i;col[n]=j
} } }
if(n>0){
if(n>1){n=rnd(n)}
document.getElementById('i'+row[n]+col[n]).value=A[row[n]][col[n]];
document.getElementById('i'+row[n]+col[n]).disabled=1
}else{HN=15}
} }
function inp(el){
var elv=(el.value).trim();
elv=elv.replace(/[^0-9]/g,'');
elv=(elv=='')?0:elv*1;
if(elv>255){elv=255}
el.value=elv;
custom()
}
function InpChk(el){if(isNaN(el.value)||el.value==0){el.value=''}}
function menu(){
if(Me==2){mim()}
Me=(Me==1)?0:1;
document.getElementById('menu').className=(Me==1)?'vis':'hid';
document.getElementById('men').className='me'+Me
}
function mim(){
var bk='<div class="decNon" id="box" onClick="cbx()">';
bk+='<span class="on" id="swi">';
bk+='<span class="flg"></span>';
bk+='</span> Дисплей вкл.</div>';
bk+='<div class="clr">';
bk+='<input id="r" maxLength=3 value='+C['r']+' onKeyUp="inp(this)">';
bk+='<input id="g" maxLength=3 value='+C['g']+' onKeyUp="inp(this)">';
bk+='<input id="b" maxLength=3 value='+C['b']+' onKeyUp="inp(this)">';
bk+='<div class="pat">';
for(i=1;i<8;i++){
bk+='<span class="bg0" id="bg'+i+'" onClick="clr('+i+')"></span>'
}
document.getElementById('menu').innerHTML=bk+'</div></div>'
}
function mof(){if(Me==1){menu()}}
function rnd(hi){return Math.floor(Math.random()*hi)+1}
function starter(){
GUI();timer();
Tmr=setInterval('timer()',1000);
document.getElementById('cop').innerHTML='© '+Dy+' <a href="https://mazayaki.ru/" target="_blank" title="Лайфхаки от Мазаяки">Мазаяки</a>'
}
function timer(){
var dt=new Date(),dh=dt.getHours(),dm=dt.getMinutes(),sp=':';
Dy=dt.getFullYear();
if(dh<10){dh='0'+dh}
if(dm<10){dm='0'+dm}
if(dt.getSeconds()%2==0){sp='<span style="visibility:hidden">'+sp+'</span>'}
document.getElementById('clock').innerHTML=dh+sp+dm;
if(TL>0){txt()}
}
function tri(){
var sw=rnd(6),t=new Array();
switch(sw){
case 1:t[1]=1;t[2]=3;t[3]=2;break;
case 2:t[1]=2;t[2]=1;t[3]=3;break;
case 3:t[1]=2;t[2]=3;t[3]=1;break;
case 5:t[1]=3;t[2]=2;t[3]=1;break;
default:t[1]=3;t[2]=1;t[3]=2
}
return t
}
function txt(){
document.getElementById('scr').innerHTML=Txt.substr(0,TL);
document.getElementById('scr').style.color='#'+TC;
TL=(TL<Txt.length)?TL+1:0
}
В листинге-27 приведена финальная версия JS-кода файла script.js с упорядоченными переменными и функциями, включая новые cbx(), clr(), custom(), inp(), menu(), mim(), mof(), добавленные для внедрения всплывающего меню. Перед использованием новых функций необходимо объявить глобальные переменные C (от англ. Color) для хранения массива со значениями RGB-полей, Me (от англ. Menu) для отслеживания режимов блока со всплывающим меню, Swi (от англ. Switch) для отслеживания положений переключателя.
Функция с именем cbx (от англ. Checkbox) управляет видимым и скрытым режимами дисплея и видом чекбокса. В начале функции cbx() обновляется значение глобальной переменной Swi (0 или 1). Если до вызова функции переключатель находился во включённом положении (Swi==1), в переменную Swi записывается 0, иначе — 1. Затем с помощью методов getElementById() и className переопределяются классы элементов с id #scr, #swi и #box, зависящие от нового значения Swi. Если после выполнения функции переключатель должен быть выключен (Swi==0), дисплею указывается класс .hid для активации скрытого режима, чекбоксу (полю с переключателем) — .off, а блоку с чекбоксом и пояснительным текстом — .decThr (с перечёркнутым текстом). В противном случае дисплею задаётся класс .scr (для применения видимых параметров дисплея), чекбоксу — .on, а блоку с пояснительным текстом — .decNon (без оформления текста).
Функция с именем clr (от англ. Color) отвечает за применение шаблонов цветовой схемы. В качестве аргумента pt (от англ. Pattern) функции передаётся порядковый номер шаблона цветовой схемы, нажатие по которому спровоцировало вызов функции. В теле функции с помощью switch выбираются подходящие значения глобального массива C, зависящие от аргумента pt. Далее с помощью метода getElementById() и свойства value выбранные значения записываются в RGB-поля. Затем вызывается функция custom() для обновления цветовой схемы дисплея.
Функция custom() управляет цветовой схемой дисплея. В начале функции переопределяются значения элементов массива C, которым присваиваются значения RGB-полей с помощью метода getElementById() и свойства value. В конце функции с помощью свойства backgroundColor объекта style устанавливается цвет заднего фона дисплея, заданный в RGB-формате с указанием значений из массива C.
Функция с именем inp (от англ. Input) помогает взаимодействовать с RGB-полями меню, удаляя недопустимые символы после случайного или умышленного ввода. В теле функции объявляется локальная переменная elv (от англ. Element+Value) для хранения и редактирования значения текстового поля, передаваемого через аргумент el. При объявлении в переменную elv записывается значение текстового поля, очищенное от ненужных пробелов с помощью служебной JS-функции trim(), применяемой для обработки строк (если вместо числа в поле окажутся только пробелы, в переменную elv будет записана пустая строка). Затем с помощью служебной JS-функции replace(), также применяемой для обработки строк, перезаписывается значение переменной elv с заменой недопустимых символов на пустую строку. В качестве первого аргумента функции replace() передаётся регулярное выражение с указанием того, что нужно найти и заменить, а в качестве второго аргумента — чем нужно заменить. Как видно из примера, использование регулярок помогает осуществлять (сложный) поиск с заменой при помощи всего одной строчки кода! Причём в данном случае указанное регулярное выражение способно удалить в том числе и пробелы, поэтому предварительное использование функции trim() является избыточным (и приводится исключительно в ознакомительных целях).
В JS регулярные выражения составляются подобно регуляркам языка Perl. Два слэша (косые черты) открывают и закрывают регулярное выражение. Квадратные скобки указывают на то, что выражение помогает найти заданный набор символов. Запись 0-9 задаёт диапазон числовых символов от 0 до 9. Символ «^» перед набором означает отрицание, указывая, что требуется искать не числа. Модификатор g после закрывающего слэша задаёт глобальный формат поиска (без него в RGB-полях будет заменяться только первый найденный символ).
После выполнения поиска и замены по шаблону, указанному в регулярном выражении, переопределяется значение переменной elv. Если переменная elv содержит пустую строку, её значение заменяется на 0. В противном случае в переменную elv записывается её старое значение, умноженное на 1. Такой приём помогает убирать из RGB-полей лишние нули в виде префикса перед числом (если строку '007' умножить на 1, результатом будет число 7). Далее в if проверяется обновлённое значение переменной elv. Если полученное число больше 255, в переменную записывается 255. Затем с помощью свойства value в текстовое поле записывается отредактированное значение elv. Таким образом, в текстовом поле, спровоцировавшем вызов функции, должно оказаться целое число в диапазоне от 0 до 255. В конце функции inp() после проведённой масштабной проверки вызывается функция custom() для обновления цветовой схемы дисплея.
Функция menu() управляет режимами всплывающего меню и видом значка. В начале функции в if проверяется значение глобальной переменной Me, которой при объявлении в начале сценария было присвоено число 2. Если функция запускается впервые (Me==2), вызывается вспомогательная функция mim() для прорисовки элементов меню. Далее обновляется значение Me на 0 или 1. Если до вызова функции всплывающее меню находилось в видимом режиме (Me==1), в переменную Me записывается 0, иначе — 1. Затем с помощью методов getElementById() и className переопределяются классы элементов с id #menu и #men, зависящие от нового значения Me. Если к моменту выполнения группы операторов Me содержит 1, к всплывающему меню будет применён класс .vis, а к значку меню — .me1 (всплывающее меню будет отображено на экране). В противном случае, если в Me содержится 0, к всплывающему меню будет применён класс .hid, а к значку — .me0 (всплывающее меню будет скрыто).
Функция с именем mim (от анг. Menu+Item) отвечает за формирование элементов меню. В теле функции mim() объявляется локальная переменная bk (от англ. Block) для формирования строки с HTML-кодом и обновления содержимого блока с id="menu". Изначально в bk записывается открывающий тег <div> для чекбокса с указанием трёх атрибутов: класса .decNon, id #box и обработчика события onClick для вызова функции cbx(). Следом к bk добавляется вложенный открывающий тег <span> (поле переключателя) с указанием класса .on и id #swi. Далее к переменной bk добавляется контейнер <span></span> с классом .flg (флажок-переключатель). Затем к bk добавляются тег </span>, закрывающий поле переключателя, пояснительный текст «Дисплей вкл.» и тег </div>, закрывающий блок чекбокса.
После этого к переменной bk добавляется открывающий тег <div> (блок управления цветовой схемой дисплея) с классом .clr. Далее к значению bk добавляются три тега <input> (RGB-поля) с указанием id (#r, #g, #b), максимальной длины в 3 символа (maxLength), значений массива C (value) и обработчиков события onKeyUp, вызывающих функцию inp() после каждого ввода новых значений. Следом к bk добавляется открывающий тег <div> (блок с шаблонами цветовой схемы) с классом .pat. Затем в цикле for к переменной bk добавляются 7 контейнеров <span></span> (шаблонов) с общим классом .bg0, id #bg1–7 и обработчиками события onClick, вызывающими функцию clr() при каждом нажатии по шаблону. После этого с помощью методов getElementById() и innerHTML меняется содержимое элемента с id="menu", вместо которого записывается содержимое переменной bk с добавлением двух тегов </div>, закрывающих блок с шаблонами и общий блок управления цветовой схемой.
Функция с именем mof (от анг. Menu+Off) состоит всего из одной строчки кода, вызывающей функцию menu() для сокрытия меню в случае, если в глобальной переменной Me содержится 1. Таким образом, в документе предусматривается два способа сокрытия всплывающего меню: через повторное нажатие на значок меню либо через нажатие на игровое поле. При желании, чтобы функция mof() вызывалась ещё и после нажатия по блоку с описанием, внутри тега <div id="ds"> также следует добавить обработчик события onClick="mof()"!