创建自定义元素.
每个 DXPR Builder 元素是推入 window.dxprBuilder.dxpr_elements 的 JavaScript 对象。编辑器将每个对象变成元素类,Style 和 Animation 选项卡已挂好。本页展示自带元素在 dxpr_builder/dxpr_elements.js 中如何定义、模块如何向编辑器添加自己的定义,以及生成的 HTML 什么样。元素没有服务器端 Twig 模板;元素在浏览器中渲染。
编辑器如何注册元素
编辑器按以下顺序加载六个脚本,由 dxpr_builder_library_info_build()(dxpr_builder.module 中的)定义为 dxpr_builder/editor.builder 库:
dxpr_templates.js:从dxpr_builder/templates/编译的客户端 twig.js 模板。dxpr_global.js:共享辅助函数和 CKEditor 5 集成。dxpr_events.jsdxpr_param_types.js:向window.dxprBuilder.dxpr_param_types推入每种输入类型一个对象。dxpr_elements.js:创建window.dxprBuilder.dxpr_elements数组并推入每个元素一个定义。dxpr_builder.js:编辑器。该文件执行时调用create_dxpr_elements(),遍历window.dxprBuilder.dxpr_elements并对每个定义:- 调用
register_animated_element(base, is_container, Class),让类继承AnimatedElement(Style 选项卡、Animation 选项卡、HTML ID、HTML 类和位置参数); - 将继承的参数追加到定义的
params; - 通过
make_param_type()转换每个参数,它将param.type与已注册的参数类型匹配; - 将定义的属性混入类原型。
- 调用
因此定义必须在 dxpr_elements.js 运行后、dxpr_builder.js 运行前进入数组。六个文件都带 defer 属性加载,因此 script 标签的文档顺序即执行顺序。
元素定义
这是 dxpr_builder/dxpr_elements.js 中的 Alert 元素(源码:dxpr_builder/build/dxpr-elements/elements/az_alert.js),精简到每个元素都需要的属性。原件还设置了 el_class、onCancel 处理器和 focusout 监听器。
window.dxprBuilder.dxpr_elements.push({
base: "az_alert",
name: Drupal.t("Alert"),
nameEn: "Alert",
icon: "az-custom-icon az-alert-icon",
largeSettingsWindow: true,
hidden: false,
params: [
{
type: "textarea",
heading: Drupal.t("Message"),
param_name: "content",
value: Drupal.t(
"This is a placeholder text. Your actual content will go here. Edit this to include your own information.",
),
},
{
type: "dropdown",
heading: Drupal.t("Type"),
param_name: "type",
description: Drupal.t("Select message type."),
getText: (opt) => opt.text,
getValue: (opt) => opt.value,
getDefault: (param) => param.value["alert-success"].value,
value: {
"alert-success": { text: Drupal.t("Success"), value: "alert-success" },
"alert-info": { text: Drupal.t("Info"), value: "alert-info" },
"alert-warning": { text: Drupal.t("Warning"), value: "alert-warning" },
"alert-danger": { text: Drupal.t("Danger"), value: "alert-danger" },
},
passthrough: true,
},
],
show_settings_on_create: true,
has_content: true,
render(...args) {
const state = {
class: `az-element az-alert alert ${this.attrs.type} ${this.get_el_classes()} ${this.get_content_classes()}`,
style: this.attrs.style,
message: this.attrs.content,
};
this.dom_element = this.baseclass.prototype.render_template(
"elements/alert/alert",
state,
);
this.baseclass.prototype.render.apply(this, args);
},
save_history() {
const container = this.get_my_container();
container.save_container_history(Drupal.t("Edit alert"));
},
});
| 属性 | 用途 |
|---|---|
base |
机器名。它以 data-azb="az_alert" 写入已保存 HTML,页面重新解析时用于找到类。保留 az_ 前缀。 |
name、nameEn |
元素选择器中的标签及其未翻译形式。 |
icon |
选择器图标的 CSS 类。自带图标定义在 dxpr_builder/sass/dxpr-builder-backend/components/_custom-icons.scss 中;自定义元素需要为自己的图标类写 CSS。 |
category |
选择器选项卡。布局元素用 Drupal.t("Layout");区块和视图用 "CMS"。默认内容选项卡请省略。 |
is_container |
true(元素容纳其他元素时)。 |
largeSettingsWindow |
以较大尺寸打开设置对话框。 |
hidden |
在选择器中隐藏元素,但保持可渲染。 |
params |
对话框中显示的设置。见下文。 |
show_settings_on_create |
元素放下后立即打开设置对话框。 |
has_content |
元素有可编辑内容区(dom_content_element)。 |
render(...args) |
构建 this.dom_element(从 this.attrs),再调用基础 render。 |
save_history() |
推入带标签的撤销条目。 |
parse_attrs_from_dom(element) |
可选。从已保存标记中读回参数值,与 skip_data_azb 和 skip_params 配合,供 Image 等将值存放在 <img> 属性而不是 data-azat-* 中的元素使用。 |
参数
每个 params 条目有:
| 键 | 含义 |
|---|---|
type |
已注册的参数类型之一(下一节)。 |
heading |
字段标签。 |
param_name |
键在 this.attrs 中,在已保存 HTML 中是 data-azat-<param_name> 属性。content 特殊:它是元素正文,不是属性。 |
value |
默认值。对 dropdown 是带 getText、getValue 和 getDefault 回调的选项对象。 |
description |
字段下的帮助文本。 |
tab |
将字段分组到命名折叠中,例如 Drupal.t("SEO")。 |
can_be_empty |
存放空字符串,而不是丢弃属性。 |
safe |
跳过存放值的 URL 编码。 |
参数类型是推入的 type 值,推到 window.dxprBuilder.dxpr_param_types(dxpr_builder/dxpr_param_types.js 中):boxmodel、checkbox、checkboxes、colorpicker、datetime、dropdown、dxb_slider、html、icon、image、images、link、links、numericfield、row_layout、saved_datetime、social_links、textarea、textfield 和 video。未注册的类型回退到普通文本输入框(BaseParamType)。
不要重复使用每个元素继承的 param_name,例如 color、background、el_class、hash 或 an_* 动画名。Style 选项卡已拥有 color,因此同名的第二个参数从不写入 data-azat-color。
保存的内容
update_data()(dxpr_builder.js 中的)将元素写为 HTML:
data-azb="<base>"(根元素上);data-azat-<param_name>="<value>"写入每个值与默认值不同的参数,URL 编码,除非参数设置了safe: true;- Style 选项卡的参数写为内联
style和类,从不写为data-azat-*属性; data-azcnt="true"(设置了has_content时,在内容元素上)。
没有编辑器的访客收到去掉 data-az* 属性的 HTML:DxprBuilderService::parseDocumentForCleanup() 剥离它们,只在动画元素和 Carousel 等内置动态元素上保留固定列表。如果元素需要访客端 JavaScript 或 CSS,请在根元素上放 data-dxpr-builder-libraries="<key>" 属性:parseDocumentForTemplateLibrary() 为每个不带斜杠的键附加 dxpr_builder/elements.<key>。键是 elements.* 库(dxpr_builder.libraries.yml 中的);带斜杠的键只在它是已注册图标集的 library 时有效。
最小可用示例
示例添加渲染带颜色段落的“Notice”元素。它直接构建 DOM,因为 dxpr_templates.js 中编译的 twig.js 模板是编辑器包的一部分,别的模块无法扩展。
-
创建
mymodule/js/notice-element.js:window.dxprBuilder.dxpr_elements.push({ base: "az_notice", name: Drupal.t("Notice"), nameEn: "Notice", icon: "az-custom-icon az-alert-icon", params: [ { type: "textfield", heading: Drupal.t("Text"), param_name: "text", value: Drupal.t("Notice text"), }, { type: "colorpicker", heading: Drupal.t("Colour"), param_name: "notice_color", value: "#0d6efd", }, ], show_settings_on_create: true, render(...args) { const el = document.createElement("div"); el.className = `az-element az-notice ${this.get_el_classes()}`; if (this.attrs.style) { el.setAttribute("style", this.attrs.style); } const p = document.createElement("p"); p.style.color = this.attrs.notice_color; p.textContent = this.attrs.text; el.appendChild(p); this.dom_element = el; this.baseclass.prototype.render.apply(this, args); }, save_history() { this.get_my_container().save_container_history(Drupal.t("Edit notice")); }, }); -
将文件插入
dxpr_elements.js(权重-4)与dxpr_builder.js(权重-3)之间的编辑器库(在mymodule.module中):/** * Implements hook_library_info_alter(). */ function mymodule_library_info_alter(array &$libraries, string $extension): void { if ($extension === 'dxpr_builder' && isset($libraries['editor.builder'])) { $path = '/' . \Drupal::service('extension.list.module')->getPath('mymodule'); $libraries['editor.builder']['js'][$path . '/js/notice-element.js'] = [ 'weight' => -3.5, 'preprocess' => FALSE, 'attributes' => ['defer' => TRUE], ]; } }preprocess: FALSE和defer与模块为自己文件定义的条目一致,因此无论编辑器资源来自 CDN 还是本地构建,文件在序列中的位置不变。 -
清除缓存并打开构建器页面:
drush cr -
从选择器添加元素,设置文本和颜色并保存。字段存放:
<div class="az-element az-notice" id="..." data-azb="az_notice" data-azat-text="Hello" data-azat-notice_color="%23198754"> <p style="color: #198754;">Hello</p> </div>访客得到去掉
data-az*属性的同样标记。段落保留内联颜色,因此该元素不需要访客库。
要知道的限制
- 档案不列出自定义元素。 构建器档案中的元素清单来自
src/Form/DxprBuilderProfileForm.php和src/Service/Handler/ProfileHandler.php中的固定列表。该列表外的元素从不受档案隐藏。 - 选择器的图标需要模块的 CSS;构建器自带的
az-custom-icon类只覆盖自带元素。 DxprBuilderService::getDxprElementsFolders()及其hook_dxpr_builder_elements_folders_alter()返回主题中elements文件夹的列表,但编辑器中没有任何东西读该列表。它不是注册路线。- Style 和 Animation 选项卡由
register_animated_element()为您添加;不要重定义这些参数。