LS3.x 中的新模板系统
From LimeSurvey Manual
简介
请注意:在 LimeSurvey 的早期版本中,用于定义调查外观(颜色、字体、布局以及部分行为)的文件被称为“模板”。出于新的考虑,现在将其称为“主题”,而“模板”则专用于示例调查。
在本页中,您将学习如何:
- 使用 LimeSurvey 3.0 的新主题系统。
- 使用继承来管理您自己的主题。
- 向主题中添加图片
- 管理调查和调查组的主题选项
LimeSurvey 3 引入了全新的主题引擎系统,基于 Twig 1.29 和 Bootstrap,支持主题继承和主题选项。它完全移除了旧的替换关键字系统,因此现在前端 100% 的 HTML 都可以自定义。例如,在旧的主题系统中,有一个关键字 {ASSESSMENTS},会在运行时被替换为评估的 HTML。主题设计者无法自定义这段 HTML(除非使用 JavaScript)。现在,有一个名为 assessments.twig 的文件,其中包含生成这段 HTML 的逻辑(使用 Twig 编写)。在这些页面中,我们将为您说明如何使用这个新的主题引擎。
使用管理界面进行编辑
主题列表
在管理仪表板上,现在有一个用于访问主题列表的框:

列表分为 5 列:
- 主题的预览:它只是位于主题根目录下名为“preview.png”的图片文件
- 主题的“标题”,如清单文件中所指定(位于主题根目录中的 config.xml)
- 主题的描述:在其清单文件中设置的字符串
- 主题的类型:内置主题(随 LimeSurvey 提供)、用户主题(添加到 upload 目录中)、XML 主题(未加载到数据库中)
- 扩展:如果该主题扩展了另一个主题,其名称将显示在此处
- 一些操作按钮:
- 安装:将加载主题的清单文件,把它添加到数据库中,并使其可在调查级别被选择
- 卸载:将删除数据库中该主题的配置条目
- 主题编辑器:将跳转到主题编辑器
- 主题选项:将进入主题选项的全局配置
主题编辑器
主题编辑器尽可能与原来的保持一致。因此,当您打开内置主题时,无法对其进行编辑。但现在,您看到的不再是“复制”按钮,而是“扩展”按钮。

主题继承概念速览
在 LS3 中,一个主题现在可以继承另一个主题,即可以“扩展”另一个主题。这意味着该主题目录几乎是空的,只包含与原主题不同的文件(视图、样式表、脚本、资源等)。这样,您就可以轻松地为不同用户创建一系列主题,而无需维护大量不同的主题。例如:您可以拥有自己制作的主题,然后为某家公司制作一个版本(带有其徽标、样式,或许还在页脚中加入其网站链接等),再为另一家公司制作另一个版本,等等。之后,如果您更新自定义主题的 CSS 或全局布局,所有继承它的主题都会自动更新。请注意,继承是递归的:一个主题可以扩展另一个已扩展其他主题的主题,依此类推。
用户界面中的新特性
要扩展 LimeSurvey 的 Monochrome 主题,请前往主题列表,点击 Monochrome 主题的“主题编辑器”按钮。然后点击“扩展”,并确认新名称“extends_monochrome”。
现在,如果您(使用文件/FTP 客户端)进入 upload 目录,会看到已创建了一个新目录:upload/themes/extends_monochrome 它包含一个 XML 文件和若干目录,但大多数目录都是空的。它既没有视图,也没有 CSS 或 JS。不过,您仍然可以像选择普通主题一样在调查中选择该主题,其外观将与 monochrome 主题完全相同。

extends_monochrome 主题的主题编辑器如下所示:

与旧的主题编辑器相比没有太大差别。下面列出主要的不同之处:
- 文件列表中的关键字inherited。它表示该文件不在主题目录中,将使用原主题中的文件。

- 主编辑器( ACE 编辑器 )显示所选文件的内容。这些文件中不仅包含 HTML、CSS 或 JS,还包含 Twig 语句。借助这些 Twig 语句,我们可以将以前深藏在核心中的一些逻辑放入主题视图,并且现在可以对其进行自定义。

- 因此,现在顶部菜单的下拉选择器中提供了更多的屏幕类型。您会注意到诸如“调查列表”、“Load”、“Save”、“Error”、“Registration”、“Assessments”、“打印答案”等以前不可用或无法真正自定义的页面。

- 文件列表底部的“tip”链接会告诉您在 HTML 中添加图片的 Twig 方式

- “保存更改”按钮变成了复制为本地主题并保存更改按钮

简单示例:添加图片
复制为本地主题并保存更改按钮的作用正如其名:如果您编辑了文件中的任何内容,然后点击该按钮,它会将该文件复制到您正在编辑的主题中,并保存您的更改。
例如:点击文件 layout_global.twig,然后在 content 块( {% block content %})之前添加文本“TEST”,并点击该按钮。您会看到该文件的标签从“inherited”变为“local”,而现在按钮变成了普通的保存更改按钮。

如果您打开文件资源管理器并进入目录 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 资源管理器文档: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 名称:要加载的 CSS 框架名称。目前仅支持 Bootstrap 或不加载;
- Cssframework Css:您可以在此字段中用自定义版本替换核心 bootstrap.css;
- Cssframework Js:可在此处用自定义版本替换核心 boostrap.js 字段;
- 需加载的包:您可以通过此设置加载 LimeSurvey 的一些核心资源包。
您会注意到顶部有一个上传输入框,可让您将文件上传到主题的文件目录中。 这些参数可用于更改主题的整体外观。
简单选项
简单选项页面来自模板本身。它通过主题 /options 目录中的一个 twig 文件和一些 JavaScript 实现: 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 模式: 下一页是通过 ajax 加载(更快)还是通过页面重新加载(更便于调试)
- 背景图像: 如果设置为“是”,将加载名为 pattern.png 的图片(在 Master 版本中将由文件选择器取代)
- Box container(框容器): 如果设置为“否”,问题将不会包含在框内(这样您就可以使用比屏幕宽度更大的宽数组)
- Brandlogo(品牌标志): 如果设置为“否”,调查名称将显示在顶栏中;否则,您可以从文件目录中选择一张图片用作标志图片。
- 主体动画: 如果设置为“是”,您可以选择在加载调查主体时应用的动画
- 问题动画: 问题的设置方式相同
- 警告动画: 警告的设置方式相同
- Bootstrap 主题: 在此可以选择要加载的 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 起,LS 使用 Yii 资源管理器:
关于资源的 Yii 文档
它会将主题的 CSS/JS 文件移动到 tmp/ 子目录中,并使用一个随机字符串命名(例如:“tmp/1ef64ml/”)。因此,如果您更改了某个 css/js 文件并通知资源管理器,这些文件将被复制到一个新名称的子目录中,从而更新用户浏览器的缓存,使他们看到新的 css/js。否则,他们就必须清除浏览器缓存。
以下是启用资源管理器时页眉中的 CSS 链接:
如您所见,它们都指向 tmp/ 子文件夹。
以下是关闭资源管理器时页眉中的 CSS 链接:
如您所见,它们指向主题的实际文件。
因此,在编辑主题的 CSS/JS 时,您有多种选择:
- 您可以使用 LS 主题编辑器: 它会处理资源管理器,您无需担心任何事情
- 您可以开启调试模式: 这将关闭资源管理器,从而调用主题的实际 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");
然后通过 CSS 规则使用 Lato 字体: 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 字体选择器详解)
操作步骤如下:
- 使用 CDN 或本地服务器,将两种字体(my_custom_font 和 my_custom_other_font)添加到您的主题中
- 然后,在您的 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 包并将 font 选项定义为 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 文件只包含您的佈景主題配置的默认值。实际上,这些值是以 JSON 字符串的形式定义并读取于数据库中的(表“template_configuration”(问题:应该是“template_”还是“theme_”?))。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
从零开始创建佈景主題
文档即将推出。
目前仅提供一些小提示。
佈景主題结构
文件和目录
从零开始创建佈景主題时,您不必遵循 Vanilla 的文件/目录结构以及 css/js。 必需的 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 中的所有其他文件和目录都是纯粹可选的,您可以按自己的方式自由组织代码。
内容
在 Vanilla 的 layout_global.twig 中,您会看到我们使用一个名为“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 中,我们为每个操作创建了一个要包含的文件。因此,如果您想了解操作列表,只需查看 vanilla 的目录 views/subviews/content,并去掉“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 版本创建过佈景主題,您会注意到其中大多数对应于 LimeSurvey 2.x 的旧 pstpl 文件。 同样,您的佈景主題并不一定要在此目录中创建这些文件或使用这些名称。例如,您可以直接在 layout_global.twig 中添加一个大型 switch,为每个操作提供所需的 HTML。
清单文件 config.xml
主题的清单文件(manifest)包含有关您的主题的主要信息。安装主题时,清单文件的内容会被加载到数据库的两个不同的表中:template 和 template_configuration。因此,每次修改主题的清单文件后,您都必须卸载并重新安装该主题(或仅重置它)。由于在开发主题时这个过程比较繁琐,您可以强制直接使用 XML 文件,而不是数据库中的条目。为此,请在 config.php 中开启调试模式,并将 'force_xmlsettings_for_survey_rendering' 设置为 true。
元数据部分
并不复杂:只是有关您的主题的主要信息。这些信息将被写入 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 等),系统会在父主题中查找该文件。
文件部分
这一部分非常重要。它将以 JSON 数组的形式写入 template_configuration 表的 files_css、files_js、files_print_css 字段中。
例如: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)中。因此,当资源管理器(Asset Manager)开启时(调试模式关闭),这些文件将与主题的其余部分一起被复制到 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" 一个文件,而该文件并不在您的主题中,而是在其某个上级主题中。引擎将查找其所有上级主题,并使用找到的第一个文件。如果找不到该文件,并且在配置中开启了调试模式,同时在全局设置中开启了前端 JS 调试模式,控制台中将显示警告消息。例如:如果我们在 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>
如果您查看 Fruity 中的 custom.css 文件,会发现它与 Vanilla 中的完全相同。我们可以删除 Fruity 中的 custom.css 文件,这样就会加载 Vanilla 的文件。我们也可以从 Fruity 的清单文件中删除语句 <replace>custom.css</replace>,这样将使用 Vanilla 中的语句,并加载 Vanilla 的 custom.css。
那么,为什么我们还要在 Fruity 的清单文件中使用语句 <replace>custom.css</replace> 呢?答案很简单:因为我们希望最终用户能够扩展 Fruity 主题,在其本地主题中修改该文件,并从其继承的主题中加载这个修改后的文件。要理解这一点,只需扩展 Fruity 并查看扩展后的主题。扩展后的主题甚至没有 custom.css 文件,因此将使用 Fruity 的文件。但是:如果用户在扩展主题中创建了该文件(通过在主题编辑器中点击 "扩展"),则该文件将从其主题中加载。
总的来说:
如果您从头创建一个不扩展任何主题的主题,只需使用 add 语句添加您的 CSS/JS 文件即可。非常简单。
如果您创建了一个扩展其他主题的主题,并且不希望用户能够扩展上级主题的 CSS/JS 文件:请不要在清单文件中使用 add 语句。这些文件仍将从上级主题的配置中加载。
如果您创建了一个扩展其他主题的主题,并且想替换上级主题的某个文件:请使用 replace 关键字(add 关键字将产生相同的结果)。
如果您创建了一个扩展其他主题的主题,并且没有替换某个 CSS/JS 文件,但希望用户能够扩展该文件:请在清单文件中对该文件使用 "replace" 语句。即使您没有替换该文件,通过在清单文件中使用 replace 关键字,您也允许用户在需要时这样做。
只有最后这种情况需要稍微动动脑筋才能理解,其他所有情况都很简单。
您也可以直接在 Twig 代码中注册 CSS 和 JS 文件。这些文件仅在请求该 Twig 文件时才会加载。如果您希望用户能够通过主题编辑器继承这些 JS/CSS 文件,请记得使用函数 Template:RegisterTemplateCssFile('my style.css') 和 Template:RegisterTemplateScript('my script.js')。如果您不使用这些函数,您的主题可能仍能正常工作,但其继承功能将会失效。其逻辑与 Template:Image('my picture.jpg') 函数相同。
remove 关键字
remove 关键字自 3.14 起才可用。使用它,您可以从任何包(甚至是核心包)中删除任何 CSS 文件。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:所有 ExpressionScript JavaScript 都需要
选项部分
本部分与您的主题选项相关。它将以 JSON 数组的形式填充 template_configuration 表的 "options" 字段。
更多信息
一些说明
注意:如果您编辑了主题的 XML 文件,则必须卸载并重新安装该主题,更改才会生效。
注意:为避免这种情况,您可以强制使用 XML 而不是数据库。在 config.php 中开启调试模式,并取消注释:
'force_xmlsettings_for_survey_rendering' => true, // 如果您想强制使用 XML 文件而不是数据库(便于主题开发),请取消注释
请注意:所有内容(包括选项等)都将从 XML 中加载
注意:如果您手动编辑 CSS/JS 文件(未使用主题编辑器),且调试模式已关闭,现在可以强制刷新资源。在“全局设置”的“常规”选项卡中,点击“清除资源缓存”按钮。
注意:如果您删除该部分
