Новая система тем в LS3.x
From LimeSurvey Manual
Введение
Обратите внимание: в предыдущих версиях LimeSurvey файлы, определяющие внешний вид опроса (цвета, шрифты, макет и частично поведение), назывались «шаблоном». Теперь они называются «темой», а слово «шаблон» зарезервировано за примерами опросов.
На этой странице вы узнаете, как:
- использовать новую систему тем LimeSurvey 3.0;
- использовать наследование для управления собственными темами;
- добавить изображение в тему;
- управлять настройками темы для ваших опросов и групп опросов.
LimeSurvey 3 представляет совершенно новый движок тем на основе Twig 1.29 и Bootstrap, поддерживающий наследование тем и настройки тем. Старая система ключевых слов для замены полностью удалена, поэтому теперь можно изменить 100% HTML-кода пользовательской части. Например, в старой системе тем существовало ключевое слово {ASSESSMENTS}, которое во время выполнения заменялось HTML-кодом оценки ответов. Разработчик темы не мог изменить этот HTML (кроме как с помощью JavaScript). Теперь есть файл assessments.twig, содержащий логику (написанную на Twig) для генерации этого HTML. На этих страницах мы расскажем, как использовать новый движок тем.
Редактирование через интерфейс администратора
Список тем
На панели управления администратора теперь есть блок для доступа к списку тем:

Список разделён на 5 столбцов:
- предварительный просмотр темы: это просто файл изображения «preview.png» в корне темы;
- «название» темы, указанное в манифесте (config.xml в корне темы);
- описание темы: строка, заданная в манифесте;
- тип темы: базовая тема (поставляется с LimeSurvey), пользовательская тема (добавлена в каталог upload), XML-тема (не загружена в базу данных);
- Копировать: если тема расширяет другую тему, здесь будет указано её название;
- кнопки действий:
- Установить: загружает манифест темы, добавляет её в базу данных и делает доступной для выбора на уровне опроса;
- Удалить: удаляет записи конфигурации темы из базы данных;
- Редактор темы: перенаправляет вас в редактор темы;
- Настройки темы: ведёт к глобальной конфигурации настроек темы.
Редактор темы
Редактор темы максимально приближен к исходному. Поэтому базовую тему отредактировать нельзя. Но теперь вместо кнопки «Копировать» (copy) у вас есть кнопка «Копировать» (extend).

Краткий обзор концепции наследования тем
В LS3 тема теперь может наследоваться от другой темы, то есть «расширять» её. Это означает, что каталог темы будет практически пустым: в нём будут только файлы (представления, таблицы стилей, скрипты, ресурсы и т. д.), отличающиеся от исходных. Так вам будет легко создать набор тем для разных пользователей, не поддерживая множество разных тем. Например, у вас может быть собственная тема, а затем версия для одной компании (с её логотипом, стилем, возможно, ссылкой на её сайт в нижнем колонтитуле и т. д.), другая версия для другой компании и так далее. Если затем вы обновите CSS или общий макет своей темы, все темы, наследующие от неё, обновятся автоматически. Обратите внимание, что наследование рекурсивно: тема может расширять тему, которая расширяет другую, и т. д.
Новое в пользовательском интерфейсе
Чтобы расширить тему Monochrome в LimeSurvey, перейдите в список тем и нажмите кнопку «Редактор темы» у темы Monochrome. Затем нажмите «Копировать» и подтвердите новое имя «extends_monochrome».
Если теперь вы перейдёте в каталог upload (с помощью файлового менеджера или FTP-клиента), то увидите, что создан новый каталог: upload/themes/extends_monochrome Он содержит XML-файл и каталоги, но большинство каталогов пусты. В нём нет ни представлений, ни CSS, ни JS. Однако вы по-прежнему можете выбрать эту тему для опроса как обычную, и она будет выглядеть точно так же, как тема Monochrome.

Редактор темы для темы extends_monochrome выглядит так:

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

- Главный редактор ( редактор ACE ) показывает содержимое выбранного файла. Файлы содержат не только HTML, CSS или JS, но и инструкции Twig. Эти инструкции Twig позволяют перенести часть логики в представления темы, которая раньше находилась глубоко в ядре, а теперь может быть изменена.

- Поэтому в выпадающем списке верхнего меню теперь доступно больше типов экранов. Вы заметите такие страницы, как «Список опросов», «Загрузка», «Сохранение», «Ошибка», «Регистрация», «Оценки ответов», «Печать ответов», которые раньше были недоступны или их нельзя было по-настоящему настроить.

- Ссылка «tip» внизу списка файлов показывает, как добавить изображение в HTML с помощью Twig

- Кнопка «Сохранить изменения» превращается в кнопку Копировать как локальную тему и сохранить изменения

Быстрый пример: добавление изображения
Кнопка Копировать как локальную тему и сохранить изменения делает ровно то, что написано: если вы измените что-либо в файле и нажмёте эту кнопку, файл будет скопирован в редактируемую тему, а ваши изменения сохранены.
Например: щёлкните файл layout_global.twig, затем непосредственно перед блоком content ( {% block content %}) добавьте текст «TEST» и нажмите кнопку. Вы увидите, что метка файла изменилась с «Унаследовано» на «локальный», а кнопка теперь называется просто Сохранить изменения.

Если вы откроете файловый менеджер и перейдёте в каталог upload/themes/extends_monochrome/views/, то увидите, что в нём лишь один файл — layout_global.twig, и в нём есть строка «TEST».

Теперь вместо произвольного текста добавим изображение. Если щёлкнуть ссылку tip, вы увидите:
Для вставки изображения в файл .twig:
{{ image('./files/myfile.png', 'alt-text for my file', {"class": "myclass"}) }}
Если вы читали документацию Twig (а к этому моменту вам следовало это сделать), вы знаете, что {{ function( ) }} выводит на экран результат работы функции. Здесь функция — image( ).
Если вы не понимаете код — не беспокойтесь: вам не нужно знать, как он работает, достаточно знать, зачем и как его использовать.
Функцию image() следует использовать по двум причинам:
- Функция image просматривает тему в поисках изображения. Если редактируемая вами тема расширяет другую тему, и вы скопировали локально файл, в который вставили изображение, а само изображение в локальную тему не скопировано, функция пройдёт по дереву наследования тем, чтобы найти, где находится это изображение.
- Она использует менеджер ресурсов (asset manager), поэтому повышает производительность вашей темы. Подробнее см. документацию Yii Asset Manager: http://www.yiiframework.com/wiki/148/understanding-assets/
Итак, чтобы добавить изображение в тему:
- просто загрузите его как обычно с помощью загрузчика файлов справа, а затем добавьте в нужное место в любом twig-файле:
{{ image('./files/myfile.png') }}
- Если вы хотите добавить альтернативный текст для изображения (для программ чтения с экрана и проверки HTML), добавьте:
{{ image('./files/myfile.png'), ‘my alternative text’ }}
- Если вы хотите добавить атрибут class и id:
{{ image('./files/myfile.png'), ‘my alternative text’, {“class”: “a_nice_css_class”, “id”: “any_id”} }}
Что есть в нашем списке задач
- Дать пользователям возможность загружать собственный файл предварительного просмотра прямо из редактора
- Добавить кнопку для удаления локального файла и возврата к унаследованному
- Копировать только изображения, используемые в CSS-файлах (указав их в манифесте как файлы для копирования)
- Напоминать, какую тему расширяет текущая (если она что-либо расширяет)
Настройки темы
Ещё одна новинка LS3 — страница настроек темы. Как мы увидим далее, создатели тем могут создавать собственные настройки и даже собственную страницу настроек в панели администратора. Здесь мы кратко рассмотрим, как работает страница настроек базовых тем. Чтобы открыть настройки темы на глобальном уровне, нажмите «Настройки темы» в списке тем.
Расширенные настройки
Открыв вкладку Настройки темы, вы можете выбрать редактирование либо простых настроек, либо расширенных настроек. «Расширенные настройки» — это простая форма, которая даёт доступ к основным полям конфигурации темы из базы данных. Чтобы понять, как она работает, вам также следует ознакомиться с XML-файлом и созданием темы с нуля. Поэтому этот раздел довольно сложен и предназначен для опытных пользователей.
Если вы всё же хотите изменить расширенные настройки, перейдите на вкладку Расширенные настройки.

- Файлы CSS: CSS файлы, которые должны быть добавлены к шаблону;
- Файлы Js: JS-файлы, которые должны быть добавлены к шаблону;
- Файлы CSS для печати: CSS файлы, загружаемые при печати шаблона;
- Параметры: это поле содержит параметры (и их значения), которые должны передаваться в представление шаблона;
- CssFramework Name: название загружаемого CSS-фреймворка. Пока доступен только Bootstrap или ничего;
- Cssframework Css: в этом поле вы можете заменить основной файл bootstrap.css его пользовательской версией;
- Cssframework Js: здесь можно заменить основной файл boostrap.js его пользовательской версией;
- Пакеты для загрузки: с помощью этой настройки можно загрузить некоторые основные пакеты ресурсов LimeSurvey.
Вверху вы увидите поле загрузки, которое позволяет загрузить файл в файловый каталог темы. Эти параметры можно использовать для изменения всего внешнего вида темы.
Простые настройки
Страница простых настроек предоставляется самой темой. Она создаётся с помощью twig-файла и немного JavaScript в каталоге /options темы: https://github.com/LimeSurvey/LimeSurvey/tree/develop/templates/default/options (ссылка не работает)

Страница простых настроек просто заполняет поля формы расширенных настроек. Это можно увидеть, включив или выключив параметр на странице простых настроек: соответствующее поле в форме расширенных настроек изменится соответствующим образом. Например, в простых настройках шаблона по умолчанию, если изменить тему Bootswatch на «Darkly», а затем перейти на вкладку расширенных настроек (даже без сохранения), вы увидите, что поле «Cssframework Css» изменилось с
{"replace": [["css/bootstrap.css","css/flatly.css"]]}
на
{"replace": [["css/bootstrap.css","css/darkly.css"]]}
Вот различные простые настройки для базовых тем:
- Ajax mode: должна ли следующая страница загружаться через Ajax (быстрее) или через перезагрузку страницы (лучше для отладки)
- Изображение фона: если выбрано «Да», будет загружено изображение pattern.png (в Master будет заменено выбором файла)
- Box container: если выбрано «Нет», вопросы не будут заключены в рамку (так что можно использовать большие массивы, превышающие ширину экрана)
- Brandlogo: если выбрано «Нет», название опроса будет отображаться в верхней панели, иначе можно выбрать одно из изображений в каталоге файлов для использования в качестве логотипа.
- Анимировать тело страницы: если выбрано «Да», можно выбрать одну из анимаций, которая будет применяться при загрузке тела опроса
- Анимировать вопрос: то же самое для вопросов
- Animate alerts: то же самое для предупреждений
- Bootstrap theme: здесь можно выбрать тему Bootstrap для загрузки. Темы взяты с Bootswatch https://bootswatch.com/3/
Для анимации используется библиотека animate.css: https://daneden.github.io/animate.css/
Разумеется, разработчик темы может добавить собственную библиотеку анимации или не использовать анимацию вообще.
Система наследования
В предыдущей части мы увидели, что тема может расширять другую тему. Конфигурация темы также может наследоваться от конфигурации другой темы. Это означает, что для данной темы можно задать конфигурацию на уровне
- глобальном (тот, который мы только что рассмотрели, доступный из списка тем)
- группы опросов
- и последний — уровень опроса.
Каждый параметр на определённом уровне может наследоваться от вышестоящего уровня: наследование от группы опросов. Сначала рассмотрим уровень группы опросов.
На уровне группы опросов
Одно из других важных нововведений LS3 — система групп опросов. Теперь вы можете создавать различные группы для организации своих опросов. Чтобы перейти к ним, откройте список опросов и щёлкните вкладку групп опросов:

В этом списке есть две кнопки действий. Если группа пуста, её можно удалить. В противном случае её всегда можно отредактировать. Нажав кнопку редактирования, вы попадёте на страницу конфигурации группы опросов:

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

- Наследовать всё означает, что вся конфигурация будет унаследована от глобального уровня.
- Если перейти на страницу расширенных настроек, вы увидите, что для всех полей установлено наследование.
- Если в простых настройках выбрать «Нет» для параметра «Наследовать всё», вы снова увидите страницу, очень похожую на страницу глобальных настроек. Единственное отличие в том, что для каждого поля можно выбрать «Да», «Нет» или «Наследовать», а в каждом выпадающем списке есть значение «Наследовать»'.

На уровне опроса
При редактировании опроса в меню в левой панели вы увидите новый пункт «Настройки темы». Он ведёт на страницу настроек темы, выбранной для текущего опроса. Здесь используется та же система наследования, что и в группе опросов, но на этот раз «наследовать» означает, что настройка будет унаследована от группы опросов, к которой относится опрос.

Пример использования
Допустим, вы используете одну тему для разных компаний (A и B). Вы задаёте любимые настройки на глобальном уровне (например: Ajax включён, анимация тела страницы — выезд, анимация предупреждений — пульсация). Затем вы создаёте группу опросов для каждой компании: группу опросов для компании A, в которой будут находиться все опросы этой компании, и группу для компании B, в которой будут находиться все опросы компании B. На этом уровне вы задаёте только логотип и фон, а остальные настройки оставляете наследуемыми. Таким образом, все опросы в группе A будут использовать логотип компании A, а все опросы из группы B — логотип компании B. Для одного из опросов компании A можно использовать другой фон в соответствии с темой опроса: достаточно изменить фон в настройках на уровне опроса. Если кто-то из компании B скажет, что пульсирующее предупреждение слишком навязчиво и он предпочёл бы что-то более плавное, например появление с затуханием, вы просто измените анимацию предупреждений на уровне группы опросов B, и все опросы этой группы начнут использовать эту анимацию. Если компания A сменит логотип, вы можете изменить его на уровне группы опросов A, и все опросы этой группы будут использовать новый логотип.
Часто задаваемые вопросы о настройке тем
Здесь вы найдёте ответы на вопросы, которые задавали на форуме и которые могут помочь вам в настройке темы.
Настройка CSS/JS: менеджер ресурсов («почему мои изменения не применяются?»)
Если вы пытаетесь обновить CSS/JS темы, напрямую редактируя код в любимом редакторе, вы можете удивиться, что изменения не применяются.
Начиная с версии 2.50 LimeSurvey использует менеджер ресурсов Yii:
Документация Yii о ресурсах
Он перемещает файлы CSS/JS темы во вложенный каталог tmp/ со случайной строкой в названии (например, «tmp/1ef64ml/»). Поэтому, если вы вносите изменения в файл css/js и сообщаете об этом менеджеру ресурсов, файлы копируются в новый подкаталог с новым именем, чтобы кэш браузера пользователя обновился и он увидел новые css/js. Иначе ему пришлось бы очищать кэш браузера.
Так выглядят ссылки на CSS в заголовке, когда менеджер ресурсов включён:
Как видите, все они ссылаются на подкаталоги tmp/.
Так выглядят ссылки на CSS в заголовке, когда менеджер ресурсов выключен:
Как видите, они указывают на реальные файлы темы.
Итак, при редактировании CSS/JS темы у вас есть несколько возможностей:
- Использовать редактор темы LimeSurvey: он работает с менеджером ресурсов, и вам не нужно ни о чём беспокоиться
- Включить режим отладки: это отключит менеджер ресурсов, поэтому будут вызываться реальные файлы css/js ваших тем (но тогда при каждой загрузке придётся обновлять кэш браузера)
- Обновить кэш ресурсов: в разделе Общие настройки -> Общие -> Очистить кэш ресурсов
Использование редактора темы поможет вам понять архитектуру нового движка тем.
Кроме того, если вы настраиваете тему fruity, будьте внимательны к специфичности CSS: большинство определений используют селектор «.fruity» (один из классов элемента body).
Добавление пользовательских шрифтов в тему
Простой способ: использование Google Font CDN
Тема опроса Bootswatch использует Google Font CDN. Давайте посмотрим, как это работает: https://github.com/LimeSurvey/LimeSurvey/blob/70a1d99cd2ebe411597231a8bc746b4ca9e19584/themes/survey/bootswatch/css/variations/flatly.min.css
@import url("https://fonts.googleapis.com/css?family=Lato:400,700,400italic");
Затем шрифт Lato используется через правила CSS: https://github.com/thomaspark/bootswatch/blob/master/dist/flatly/bootstrap.css#L72
body {
...
font-family: "Lato";
...
}
Таким образом вы можете использовать в своей пользовательской теме любой шрифт Google. Разумеется, следует удалить выбор шрифта из параметров вашей темы. Удалите эти строки в options.twig: https://github.com/LimeSurvey/LimeSurvey/blob/70a1d99cd2ebe411597231a8bc746b4ca9e19584/themes/survey/vanilla/options/options.twig#L209-L230
Использование локального шрифта
Разумеется, вы также можете загрузить файлы шрифтов и использовать их с локального сервера, а не из Google CDN (это лучше для конфиденциальности). В качестве примера того, как это сделать, вот наша локальная версия шрифта Noto: https://github.com/LimeSurvey/LimeSurvey/blob/70a1d99cd2ebe411597231a8bc746b4ca9e19584/assets/fonts/noto.css
@font-face {
font-family: 'Noto Sans';
font-weight: 300;
font-style: normal;
src: url('./font-src/Noto/NotoSans-Regular.ttf');
}
...
Вы можете использовать очень похожее определение в CSS-файле вашей темы, а затем скопировать файл NotoSans-Regular.ttf в папку css/font-src/ вашей темы.
Затем примените этот шрифт к body (или любому другому элементу), как показано выше, и удалите стандартный выбор шрифта в параметрах.
Создание собственного выбора шрифта в параметрах
Пока что вы не можете легко использовать встроенный выбор шрифта ядра, чтобы добавить собственный шрифт в параметры. Сначала нужно дать конечному пользователю возможность загружать пользовательские пакеты (см. следующий раздел: «Знакомство с выбором шрифта в теме Fruity»).
Порядок действий:
- Добавьте два шрифта (my_custom_font и my_custom_other_font) в свою тему, используя CDN или локальный сервер.
- Затем в вашем CSS-файле добавьте два новых класса:
.font-my_custom_font {
font-family: 'my_custom_font ';
}
.font-my_custom_other_font {
font-family: 'my_custom_other_font';
}
- В XML-файле вашей темы добавьте параметр шрифта (по умолчанию будет my_custom_font):
<options>
....
<font>my_custom_font</font>
</options>
- В option.twig добавьте выбор шрифта, вставив следующие строки (пока не проверено, так что если не заработает, напишите об этом на форуме):
<div class='row ls-space margin top-15 bottom-15 action_hide_on_inherit'>
<hr/>
</div>
<div class='row action_hide_on_inherit'>
<div class='col-sm-12'>
<div class='panel panel-default'>
<div class='panel-heading'>{{ "My custom fonts" | t }}</div>
<div class='panel-body'>
<div class='form-group row'>
<label for='simple_edit_font' class='control-label'>{{ "Select font:" | t }}</label>
<div class='col-sm-12'>
<select class='form-control selector_option_value_field' id='simple_edit_font' name='font'>
{% if templateConfiguration.sid is not empty or templateConfiguration.gsid is not empty %} //Shouldn't this be "theme" in stead of "template"?
{% set fontOptions = fontOptions ~ '<option value = "inherit" > Inherit</option>' %}
{% endif %}
<optgroup label="{{ "My Custom fonts" | t }}">
<option class="font-my_custom_font" value="custom_font" data-font-package="" >Custom</option>
<option class="font-my_custom_other_font" value="my_custom_other_font" data-font-package="" >Other</option>
</optgroup>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
Теперь ваши пользователи смогут выбирать между этими двумя шрифтами.
Знакомство с выбором шрифта в теме Fruity
В будущем мы дадим конечным пользователям возможность загружать собственные пакеты ресурсов, включая пакеты шрифтов. Это значительно упростит настройку шрифтов.
Чтобы разобраться с пакетами Yii:
http://www.yiiframework.com/doc/api/1.1/CClientScript#packages-detail
Пакеты LimeSurvey определены в разных файлах. Пакеты шрифтов определены здесь:
https://github.com/LimeSurvey/LimeSurvey/blob/4c40b61afb0dba8fd80154b50f5831045df8d814/application/config/fonts.php
Например, пакет шрифта Noto определён здесь:
https://github.com/LimeSurvey/LimeSurvey/blob/4c40b61afb0dba8fd80154b50f5831045df8d814/application/config/fonts.php#L47-L53
'font-noto' => array(
'devBaseUrl' => 'assets/fonts/',
'basePath' => 'fonts',
'css' => array(
'noto.css',
),
),
Файл noto.css, который он содержит, находится здесь:
https://github.com/LimeSurvey/LimeSurvey/blob/4c40b61afb0dba8fd80154b50f5831045df8d814/assets/fonts/noto.css
Обратите внимание на определение CSS-класса ".font-noto" в конце файла:
@font-face {
font-family: 'Noto Sans';
...
}
...
.font-noto{
font-family: 'Noto Sans';
}
Затем в теме Vanilla шрифт Noto используется путём добавления пакета noto и установки значения noto для параметра шрифта:
https://github.com/LimeSurvey/LimeSurvey/blob/70a1d99cd2ebe411597231a8bc746b4ca9e19584/themes/survey/vanilla/config.xml#L79
<packages>
....
<add>font-noto</add>
</packages>
<options>
....
<font>noto</font>
</options>
Затем класс шрифта для body определяется с использованием этого значения:
https://github.com/LimeSurvey/LimeSurvey/blob/70a1d99cd2ebe411597231a8bc746b4ca9e19584/themes/survey/vanilla/views/layout_global.twig#L76
<body class=" ... font-{{ aSurveyInfo.options.font }} ... " ... >
Разумеется, XML-файл содержит только значения по умолчанию для конфигурации вашей темы. На самом деле эти значения определяются и считываются из базы данных (таблица "template_configuration" (вопрос: "template_" или "theme_"?)) в виде строк JSON. Файл option.js просто использует значение выбора шрифта из простых параметров, чтобы изменить значение внутри формы на вкладке расширенных параметров: https://github.com/LimeSurvey/LimeSurvey/blob/70a1d99cd2ebe411597231a8bc746b4ca9e19584/themes/survey/vanilla/options/options.js#L148-L174
Когда появится функция «загрузки пакета ресурсов», будет легко добавить скрипт, который просканирует все существующие пакеты шрифтов и добавит их в список выбора.
Добавление настроек темы для управления расположением и отображением элементов опроса
В этом руководстве показано, как добавить в расширенную тему настройки для отображения элементов опроса в разных местах. В нашем случае мы создадим настройки темы, позволяющие показывать название опроса в двух разных местах.
Создание пользовательской темы
- Расширьте тему «bootswatch», как описано выше.
- Скопируйте custom.css в локальную тему, как описано выше.
Создание новых настроек темы
- Скопируйте содержимое каталога /themes/survey/bootswatch/options/ в /upload/themes/survey/yourThemeName/options/.
- Откройте /upload/themes/survey/yourThemeName/options/options.twig в редакторе и найдите «{# Bootstrap Bootswatch theme #}». Непосредственно перед его родительским элементом <div class='row'> добавьте следующее:
{# Custom survey name in navbar #} <div class='row'> <div class='col-sm-12 col-md-6'> <div class='form-group row'> <label for='simple_edit_options_surveyname1' class='control-label'>Survey name in navbar</label> <div class='col-sm-12'> <div class="btn-group" data-toggle="buttons"> <label class="btn btn-default"> <input name='surveyname1' type='radio' value='on' class='selector_option_radio_field ' data-id='simple_edit_options_surveyname1'/> Yes </label> <label class="btn btn-default"> <input name='surveyname1' type='radio' value='off' class='selector_option_radio_field ' data-id='simple_edit_options_surveyname1'/> No </label> </div> </div> </div> </div> </div> <div class='row'> <hr/> </div> {# Custom survey name below progress bar #} <div class='row'> <div class='col-sm-12 col-md-6'> <div class='form-group row'> <label for='simple_edit_options_surveyname2' class='control-label'>Survey name below progress bar</label> <div class='col-sm-12'> <div class="btn-group" data-toggle="buttons"> <label class="btn btn-default"> <input name='surveyname2' type='radio' value='on' class='selector_option_radio_field ' data-id='simple_edit_options_surveyname2'/> Yes </label> <label class="btn btn-default"> <input name='surveyname2' type='radio' value='off' class='selector_option_radio_field ' data-id='simple_edit_options_surveyname2'/> No </label> </div> </div> </div> </div> </div> <div class='row'> <hr/> </div> - Откройте /upload/themes/survey/yourThemeName/config.xml и добавьте два элемента в блок "options", чтобы он выглядел так:
<options> <ajaxmode>on</ajaxmode> ... <surveyname1>on</surveyname1> <surveyname2>on</surveyname2> </options>
- В результате на экране «Настройки темы» появятся два новых параметра:

Измененное представление названия опроса в панели навигации
- Создайте новый каталог /upload/themes/survey/yourThemeName/views/subviews/header/.
- Скопируйте /themes/survey/vanilla/views/subviews/header/nav_bar.twig в этот новый каталог.
- Откройте /themes/survey/vanilla/views/subviews/header/nav_bar.twig и найдите "{# Logo option #}". Под этой строкой измените оператор IF для логотипа/названия опроса, чтобы он выглядел так:
{# Logo option #} {% if( aSurveyInfo.options.brandlogo == "on") %} <div class="{{ aSurveyInfo.class.navbarbrand }} logo-container" {{ aSurveyInfo.attr.navbarbrand }} > {{ image(aSurveyInfo.options.brandlogofile, aSurveyInfo.name, {"class": "logo img-responsive"}) }} </div> {% endif %} {% if( aSurveyInfo.options.surveyname1 == "on") %} <div class="{{ aSurveyInfo.class.navbarbrand }}" {{ aSurveyInfo.attr.navbarbrand }} > {{ aSurveyInfo.name }} </div> {% endif %} - Добавьте что-то подобное в /upload/themes/survey/yourThemeName/css/custom.css:
.navbar-brand { line-height: 60px; font-size: 32px; }
- Переключите параметр темы "Survey name in navbar" в значение "Да"
- Вы должны увидеть следующее:

Измененное представление названия опроса под индикатором выполнения
- Создайте новый каталог /upload/themes/survey/yourThemeName/views/subviews/survey/group_subviews.
- Скопируйте /themes/survey/vanilla/views/subviews/survey/group_subviews/group_container.twig в этот новый каталог.
- Откройте /themes/survey/vanilla/views/subviews/survey/group_subviews/group_container.twig и добавьте элемент <h1> для названия опроса. Он должен выглядеть так:
<div class="{{ aSurveyInfo.class.groupcontainer }} space-col" {{ aSurveyInfo.attr.groupcontainer }}> {# Custom survey name #} {% if( aSurveyInfo.options.surveyname2 == "on") %} <h1 class="custom-survey-name">{{ aSurveyInfo.name }}</h1> {% endif %} {# Group Name #} {{ include('./subviews/survey/group_subviews/group_name.twig') }} {# Group Description #} {{ include('./subviews/survey/group_subviews/group_desc.twig') }} {# PRESENT THE QUESTIONS This is the main part. It will render each question for this group #} <!-- PRESENT THE QUESTIONS --> {% for aQuestion in aGroup.aQuestions %} {{ include('./subviews/survey/question_container.twig') }} {% endfor %} <!-- Hidden inputs --> {% if aGroup.show_last_group == true %} <input type='hidden' name='lastgroup' value='{{ aGroup.lastgroup }}' id='lastgroup' /> {% endif %} {% if aGroup.show_last_answer == true %} <input type='hidden' name='lastanswer' value='{{ aGroup.lastanswer }}' id='lastanswer' /> {% endif %} </div>
- Добавьте что-то подобное в /upload/themes/survey/yourThemeName/css/custom.css:
.navbar-brand { line-height: 60ph1.custom-survey-name { margin: 0; text-align: center; }
- Переключите параметр темы "Survey name below progress bar" в значение "Да"
- Вы должны увидеть следующее:

Загрузки
- Пример расширенной темы: Test_survey_names.zip
Создание темы с нуля
Документация скоро появится.
Пока что приведем несколько советов.
Структура темы
Файлы и каталоги
При создании темы с нуля вам не нужно придерживаться структуры файлов и каталогов, CSS и JS из темы Vanilla. Обязательные CSS/JS добавляются ядром (при необходимости вы все равно можете их удалить).
Единственные файлы, которые обязательно должны быть в вашей теме, — это файлы макетов:
- layout_global.twig : отображает страницы прохождения опроса
- layout_survey_list.twig : отображает список опросов (если эта тема установлена по умолчанию)
- layout_errors.twig : используется для отображения ошибок, блокирующих показ опроса (неверный ID опроса, пустая группа в предпросмотре группы и т. д.)
- layout_user_forms.twig: отображает пользовательские формы, например: токен (участник опроса) и регистрация.
- layout_print.twig : используется для печати опроса в PDF
- layout_printanswers.twig: печать ответов
Содержимое этих файлов и то, какие файлы они подключают, полностью зависит от вас. Все остальные файлы и каталоги, которые вы найдете в теме Vanilla, совершенно необязательны — организуйте свой код так, как вам удобно.
Содержимое
В файле layout_global.twig темы Vanilla вы увидите, что для выбора отображаемого содержимого используется переменная "include_content": https://github.com/LimeSurvey/LimeSurvey/blob/2398dda3b425da1a37d4611cd7963d39ac739987/themes/survey/vanilla/views/layout_global.twig#L114-L115
{% set sViewContent = './subviews/content/' ~ aSurveyInfo.include_content ~ '.twig' %}
{% include './subviews/content/outerframe.twig' with {'include_content': sViewContent } %}
aSurveyInfo.include_content сообщает, какое действие выполняется в данный момент: показ вопросов? показ результата отправки? показ очистки всего? и т. д. Как видите, в теме Vanilla для каждого действия создан отдельный подключаемый файл. Поэтому, чтобы узнать список действий, просто загляните в каталог views/subviews/content темы Vanilla и отбросьте расширение "twig": https://github.com/LimeSurvey/LimeSurvey/tree/2398dda3b425da1a37d4611cd7963d39ac739987/themes/survey/vanilla/views/subviews/content
- clearall.twig
- firstpage.twig
- load.twig
- mainrow.twig
- main.twig
- optin.twig
- optout.twig
- outerframe.twig
- printanswers.twig
- quotas.twig
- register.twig
- save.twig
- submit_preview.twig
- submit.twig
- userforms.twig
Если вы уже создавали тему для версий LimeSurvey 2.x, то заметите, что большинство этих файлов соответствуют старым файлам pstpl из LimeSurvey 2.x. Опять же, вы не обязаны создавать в своей теме эти файлы с такими именами в этом каталоге. Например, вы можете просто добавить в layout_global.twig огромный switch с нужным HTML для каждого действия.
Манифест config.xml
Манифест темы содержит основную информацию о вашей теме. При установке темы содержимое манифеста загружается в базу данных, в две таблицы: template и template_configuration. Поэтому каждый раз, когда вы изменяете манифест темы, необходимо удалить и заново установить ее (или просто сбросить). Поскольку при разработке темы этот процесс утомляет, вы можете принудительно использовать непосредственно XML-файл вместо записей в базе данных. Для этого в config.php включите режим отладки и установите для 'force_xmlsettings_for_survey_rendering' значение true.
Раздел metadata
Ничего сложного: просто основная информация о вашей теме. Она будет записана в таблицу templates_configuration.
<metadata>
<name>the_name_of_your_theme</name>
<title>The Title of your theme</title>
<creationDate>16/10/2017</creationDate>
<author>Your Name</author>
<authorEmail>your@email.org</authorEmail>
<authorUrl>http://www.yourwebsite.org</authorUrl>
<copyright>Your Copyright </copyright>
<license>Licence of your theme</license>
<version>version of your theme</version>
<apiVersion>3</apiVersion>
<description>Description of your theme</description>
<extends>parent_theme</extends>
</metadata>
Несколько замечаний:
- name: используется как ключ в базе данных. Поэтому оно должно быть уникальным и не должно содержать специальных символов (включая пробелы). Обратите внимание, что регистр не учитывается
- Title: используется для отображения названия вашей темы в различных списках. Может содержать специальные символы
- description: используется в главном списке тем опросов. Может содержать специальные символы и даже HTML-код, если использовать
- extends: необязательный параметр, определяет родительские темы. Если какого-либо файла (twig/js/css/jpg и т. д.) нет в этой теме, он будет искаться в родительской теме
Раздел files
Этот раздел очень важен. Он будет записан в таблицу template_configuration, в поля files_css, files_js, files_print_css в виде массивов JSON.
Например, раздел files темы Material Premium:
<files>
<css>
<add>css/bootstrap-material-design.css</add>
<add>css/ripples.min.css</add>
<replace>css/ajaxify.css</replace>
<replace>css/theme.css</replace>
<replace>css/custom.css</replace>
<remove>awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css</remove>
</css>
<js>
<replace>scripts/theme.js</replace>
<replace>scripts/ajaxify.js</replace>
<add>scripts/material.js</add>
<add>scripts/ripples.min.js</add>
<replace>scripts/custom.js</replace>
</js>
<print_css>
<add>css/print_theme.css</add>
</print_css>
</files>
Все файлы CSS/JS, указанные в этом разделе, будут загружены при запуске опроса (в режиме ajax. Если режим ajax отключен, то, конечно, все файлы перезагружаются на каждой странице).
Они будут добавлены в пакет ресурсов Yii (Asset Packet) с именем, основанным на названии темы. Поэтому, когда менеджер ресурсов включен (режим отладки отключен), эти файлы будут скопированы в каталог tmp вместе с остальной частью темы (так что вы можете использовать относительные пути в CSS и JS для доступа к файлам изображений).
О менеджере ресурсов в Yii: https://www.yiiframework.com/wiki/148/understanding-assets
О пакетах в Yii: http://www.yiiframework.com/doc/api/1.1/CClientScript#packages-detail
Они используют систему наследования. Это означает, что если вы добавляете файл CSS/JS в тему, но его нет в самой теме, то движок просмотрит все родительские темы этой темы и использует первый найденный файл. Поэтому, если пользователь расширяет вашу тему через редактор темы, все эти файлы будут унаследованы его темой. Ключевые слова относятся к этой системе наследования.
- add : добавляет файл в тему и во все темы, которые от неё наследуются
- replace: заменяет файл родительской темы
- remove: удаляет файл из любого пакета, в том числе из основного пакета (начиная с версии 3.14)
Несколько замечаний об этих ключевых словах:
Советы по наследованию
Как уже объяснялось, ключевое слово "add" может ссылаться на файл, находящийся в одной из родительских тем. Поэтому вы можете указать "add" для файла в этом разделе, даже если этого файла нет в вашей теме, а он есть в одной из родительских тем. Движок просмотрит все родительские темы и использует первый найденный файл. Если файл не найден, в config включён режим отладки, а в глобальных настройках включена отладка JS во frontend, в консоли появится предупреждение. Например, если в теме my_theme мы добавим: <add>css/unexisting.css</add>, то в консоли увидим:
(¯`·._.·(¯`·._.· Theme Configuration Error ·._.·´¯)·._.·´¯)
Can't find file 'css/unexisting.css' defined in theme 'my_theme'Если режим отладки выключен, никаких ошибок вы не увидите. Движок просто проигнорирует неверные инструкции add.
Когда использовать add, когда replace и когда можно оставить всё родительской теме?
Во-первых, add и replace — это, по сути, одно и то же ключевое слово. Можно использовать любое из них, движок выполнит одно и то же. Они различаются только для читателя, чтобы было понятно, что вы имели в виду.
Нельзя добавить файл с тем же именем, что и в родительской теме: он всегда заменит родительский. Например, если у вас есть файл "my_mother_theme/foo.css" и вы добавляете в дочерней теме файл "foo.css", в тему будет добавлен только "daughter_theme/foo.css". Если вы хотите сохранить "my_mother_theme/foo.css", выберите для "daughter_theme/foo.css" другое имя, например "daughter_theme/bar.css". Таким образом, ключевое слово "add" может работать как "replace".
Если вам интересно, почему так сделано: это значительно упрощает автоматическое создание наследуемой темы — копирование раздела файлов работает сразу, без переименования "add" в "replace" при расширении файла.
Для наглядности возьмём пример темы Fruity. Вот её раздел CSS-файлов:
<css>
<add>css/variations/sea_green.css</add>
<replace>css/animate.css</replace>
<replace>css/theme.css</replace>
<replace>css/custom.css</replace>
</css>
Если посмотреть на файл custom.css в теме Fruity, он полностью совпадает с файлом из Vanilla. Мы могли бы удалить custom.css из Fruity, и тогда был бы загружен файл из Vanilla. Мы могли бы также удалить инструкцию <replace>custom.css</replace> из манифеста Fruity, тогда использовалась бы инструкция из Vanilla и был бы загружен custom.css из Vanilla.
Так зачем же мы используем инструкцию <replace>custom.css</replace> в манифесте Fruity? Ответ прост: мы хотим, чтобы конечный пользователь мог расширить тему Fruity, изменить файл в своей локальной теме и загрузить этот изменённый файл из своей наследуемой темы. Чтобы разобраться, просто расширьте Fruity и посмотрите на расширенную тему. В ней даже нет файла custom.css, поэтому будет использоваться файл из Fruity. Но если пользователь создаст этот файл в расширенной теме (нажав «Копировать» в редакторе темы), то этот файл будет загружен из его темы.
Итак, в целом:
если вы создаёте тему с нуля, не расширяя никакую другую, просто используйте инструкцию add для добавления своих файлов CSS/JS. Проще простого.
если вы создаёте тему, расширяющую другую тему, и не хотите, чтобы пользователи могли расширять файл CSS/JS родительской темы, не используйте инструкцию add в манифесте. Файлы всё равно будут загружены из конфигурации родительской темы.
если вы создаёте тему, расширяющую другую тему, и хотите заменить файл родительской темы, используйте ключевое слово replace (ключевое слово add даст тот же результат).
если вы создаёте тему, расширяющую другую тему, не заменяете определённый файл CSS/JS, но хотите, чтобы пользователи могли расширить этот файл, используйте для него инструкцию "replace" в манифесте. Даже если вы не заменяете файл, использование ключевого слова replace в манифесте позволяет пользователю сделать это, если он захочет.
Только последний случай требует некоторой мысленной гимнастики, все остальные тривиальны.
Вы также можете регистрировать файлы CSS и JS прямо из twig-кода. Эти файлы будут загружаться только при обращении к twig-файлу. Если вы хотите, чтобы пользователи могли наследовать эти файлы JS/CSS из редактора темы, не забудьте использовать функции Template:RegisterTemplateCssFile('my style.css') и Template:RegisterTemplateScript('my script.js'). Если вы не используете эти функции, ваша тема может работать, но наследование для неё будет нарушено. Логика та же, что и у функции Template:Image('my picture.jpg')
Ключевое слово remove
Ключевое слово remove доступно только начиная с версии 3.14. С его помощью можно удалить любой CSS/JS-файл из любого пакета, даже из основных. Оно используется в теме Material Premium для удаления файлов Awesome Bootstrap Checkbox:
<remove>awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css</remove>
Поэтому следует использовать точно такой же синтаксис, как и у файла пакета (например, "awesome-bootstrap-checkbox.css" без пути к папке работать не будет). Полный список основных пакетов и их файлов можно найти в /application/config/packages.php и config/third_party.php. Например, для awesome-bootstrap-checkbox.css: https://github.com/LimeSurvey/LimeSurvey/blob/2398dda3b425da1a37d4611cd7963d39ac739987/application/config/packages.php#L54-L56
'css'=> array(
'awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css',
),
Другой способ узнать точное имя для тега remove — включить менеджер ресурсов (отключив режим отладки или задав в конфигурации 'use_asset_manager'=>true). Тогда нужный путь будет находиться сразу после случайного каталога в каталоге tmp. Например, для awesome-bootstrap-checkbox.css:
<link rel="stylesheet" type="text/css" href="/tmp/assets/cbc4e3cb/awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css" />
Файлы, которые нельзя удалять:
jquery-3.1.1.min.js : необходим
jquery-migrate-3.0.0.min.js : необходим
survey.js : необходим
moment-with-locales.min.js : необходим для типа вопроса «Дата» (и, кажется, для некоторых других)
em_javascript.js : необходим для всего JavaScript ExpressionScript
Раздел options
Этот раздел относится к параметрам вашей темы. Он используется для заполнения поля "options" таблицы template_configuration в виде JSON-массива.
Дополнительная информация
Некоторые замечания
ПРИМЕЧАНИЕ: если вы изменили XML-файл темы, необходимо удалить и заново установить тему, чтобы изменения были учтены.
ПРИМЕЧАНИЕ: чтобы этого избежать, можно принудительно использовать XML вместо базы данных. В config.php включите режим отладки и раскомментируйте строку:
'force_xmlsettings_for_survey_rendering' => true, // Uncomment if you want to force the use of the XML file rather than DB (for easy theme development)
Будьте внимательны: всё будет загружаться из XML (включая параметры и т. д.)
ПРИМЕЧАНИЕ: если вы редактируете файлы CSS/JS вручную (без использования редактора темы) и режим отладки выключен, теперь можно принудительно сбросить кэш ресурсов. В разделе "Общие настройки" на вкладке "Общие" нажмите кнопку "Очистить кэш ресурсов".
ПРИМЕЧАНИЕ: если вы удалите раздел
