携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情
最近工作中遇到一个需求,需要扩展h5p的按钮组,从而实现下拉菜单中多种类型的图形渲染
首先介绍一下h5p是什么:
H5P 是什么?
h5p is a free and open-source content collaboration framework based on JavaScript. H5P is an abbreviation for HTML5 Package, and aims to make it easy for everyone to create, share and reuse interactive HTML5 content.
这是一个有点历史的技术了,在那个还是php流行的时代,h5p能够很好的和php的一些流行框架结合,比如drupal、wordpress等,让开发者更加容易地复用和扩展现有的HTML5 Package,可以理解成是现代前端工程化概念中的组件,在以前前端工程化还不完善的那个时代,h5p的这种设计理念也是有一定的实践意义的
现在就来讲讲我在扩展h5p的一个包Course Presentation的过程中的一些经验
DragNBar 组件方法功能说明
addButton是添加每一个按钮项
也就是这里的
文本、表格等每一个按扭项,但图形并不是,图形属于按钮组,由addButtonGroup处理
addButtonGroup添加按钮组项,也就是上图中的图形这样的可以点击展开下拉菜单的
CoursePresentation 组件方法功能说明
addDNBButton用于添加DragNBar组件的按钮项,最终的结果会作为DragNBar组件的构造函数的参数传入addDNBButtonGroup用于添加DragNBar组件的按钮组项,最终的结果会作为DragNBar组件的构造函数的参数传入
扩展 dragnbar 中的图形项,让其支持渲染多个按钮组
对应的源码位置:
development\H5PEditor.CoursePresentation-1.22\scripts\cp-editor.js --> H5PEditor.CoursePresentation.prototype.initializeDNB
按钮组都定义在drapdownMenus数组中,这个数组中的项的数据结构只支持渲染一个按钮组,而我们现在希望的是一个下拉菜单dropdownMenu中能够有多个按钮组,也就是有多个标题 + 按钮组的结构
所以需要对其作出修改,首先找到DragNBar组件中添加每一个按扭项的入口,它在:
development\H5P.DragNBar-1.5\scripts\drag-n-bar.js -> H5P.DragNBar.prototype.addButton
其中关于按钮组的添加逻辑代码如下:
let $buttonGroup;
if (button.type === "group") {
// Create dropdown button group
$buttonGroup = this.addButtonGroup(button.buttons, $button, {
title: button.titleGroup,
});
$buttonGroup.addClass("h5peditor-dragnbar-gone");
}
可以看到,它会调用addButtonGroup去创建按钮组,addButtonGroup相关代码入口在:
development\H5P.DragNBar-1.5\scripts\drag-n-bar.js -> DragNBar构造函数中,作为一个方法存在
相关代码如下:
this.addButtonGroup = function (buttons, $button, options) {
// 创建按钮组 DOM
const $buttonGroup = H5P.jQuery(
'<li class="h5p-dragnbar-li h5p-dragnbar-button-group" data-label="Image"></li>'
);
// 有配置按钮组标题的话则添加标题
// Add optional title to the group
if (options && options.title && options.title !== "") {
H5P.jQuery(
'<div class="h5p-dragnbar-button-title">' + options.title + "</div>"
).appendTo($buttonGroup);
}
// 创建按钮组中的按钮
// Container for buttons
const $buttonGroupButtons = H5P.jQuery(
'<ul class="h5p-dragnbar-button-buttons h5p-dragnbar-ul"></ul>'
).appendTo($buttonGroup);
// Add buttons
buttons.forEach(function (button) {
self.addButton(button, $buttonGroupButtons);
});
// 将按钮组插入到容器元素中
$buttonGroup.insertAfter($button.parent());
return $buttonGroup;
};
可以看到,这里只会添加一组按钮组,不支持添加多组按钮组,现在对其进行扩展,让其支持多个按钮组,首先需要修改下拉菜单中按钮组的数据结构
dropdownMenus["shape"] = {
dropdown: {
id: "shape",
},
groups: [
{
title: "基本图形",
buttons: [
H5P.jQuery.extend(true, {}, shapeButtonBase, shapeButtonBase2D, {
id: "shape-rectangle",
params: {
type: "rectangle",
},
}),
// ...
],
},
{
title: "线条",
buttons: [
H5P.jQuery.extend(true, {}, shapeButtonBase, shapeButtonBase1D, {
id: "shape-horizontal-line",
params: {
type: "horizontal-line",
},
}),
// ...
],
},
],
};
然后修改DragNBar组件底层的对按钮组的添加逻辑
this.addButtonGroup = function (groups, $button) {
// 创建按钮组下拉菜单容器
const $buttonGroupDropdownMenu = H5P.jQuery(
'<li class="h5p-dragnbar-li h5p-dragnbar-button-group" data-label="Image"></li>'
);
// 遍历 groups 创建多个按钮组容器添加到按钮组下拉菜单容器中
groups.forEach((group) => {
// 按钮组容器 -- 用于存放按钮组的标题和按钮
const $buttonGroupContainer = H5P.jQuery(
'<div class="h5p-dragnbar-button-group-container"></div>'
);
console.log(group);
// 按钮组标题
const groupTitle = group.title;
// 按钮组按钮
const buttons = group.buttons;
// 有配置按钮组标题的话则添加标题到按钮组容器中
if (groupTitle && groupTitle !== "") {
H5P.jQuery(
'<div class="h5p-dragnbar-button-title">' + groupTitle + "</div>"
).appendTo($buttonGroupContainer);
}
// 创建按钮组中的按钮
const $buttonGroupButtons = H5P.jQuery(
'<ul class="h5p-dragnbar-button-buttons h5p-dragnbar-ul"></ul>'
).appendTo($buttonGroupContainer);
// Add buttons
buttons.forEach(function (button) {
self.addButton(button, $buttonGroupButtons);
});
// 把按钮组容器添加到按钮组下拉菜单容器中
$buttonGroupContainer.appendTo($buttonGroupDropdownMenu);
});
// 将下拉菜单容器插入到容器元素中
$buttonGroupDropdownMenu.insertAfter($button.parent());
return $buttonGroupDropdownMenu;
};
再修改调用该方法的入口处
if (button.type === "group") {
// Create dropdown button group
- $buttonGroup = this.addButtonGroup(button.buttons, $button, { title: button.titleGroup });
+ $buttonGroup = this.addButtonGroup(button.groups, $button);
$buttonGroup.addClass("h5peditor-dragnbar-gone");
}
最后,再修改cp-editor.js中的数据结构和将原来的按钮组中按钮转换逻辑移植过来即可
H5PEditor.CoursePresentation.prototype.addDNBButtonGroup = function (
library,
groupData
) {
var that = this;
var id = library.name.split(".")[1].toLowerCase();
- const buttonGroup = {
- id: id,
- title: groupData.dropdown.title || library.title,
- titleGroup: groupData.dropdown.titleGroup,
- type: "group",
- buttons: [],
- };
+ const buttonGroup = {
+ id: id,
+ title: groupData.dropdown.title || library.title,
+ type: "group",
+ groups: groupData.groups,
+ };
- // Add buttons to button group
- groupData.buttons.forEach(function (button) {
- const options = {
- id: button.id,
- title: button.title,
- width: button.width,
- height: button.height,
- action: {
- library: library.uberName,
- params: button.params || {},
- },
- };
-
- buttonGroup.buttons.push(that.addDNBButton(library, options));
+ // setup buttonGroup.groups
+ buttonGroup.groups.forEach(function (group) {
+ // Add buttons to button group
+ group.buttons.map(function (button) {
+ const options = {
+ id: button.id,
+ title: button.title,
+ width: button.width,
+ height: button.height,
+ action: {
+ library: library.uberName,
+ params: button.params || {},
+ },
+ };
+
+ return that.addDNBButton(library, options);
+ });
+ });
return buttonGroup;
};