背景
在Webix中,我们使用的是经过修改的webix.protoUI
视图,我们称之为c-dashboard
(扩展了webix.ui.dashboard
)。 c-dashboard
的目的是允许我们有条件地允许或禁止panel
中的各个dashboard
对象移动
c-dashboard
:
webix.protoUI({
name:"c-dashboard",
isDragNode:function(target){
var css = (target.className || "").toString();
//check for webix header and look up
if (css.indexOf("panel_drag_icon") != -1)
return target;
if (target.parentNode && target != this.$view)
return this.isDragNode(target.parentNode);
return false;
},
$dragCreate:function(object, e){
//check for header
if (!this.isDragNode(e.target)) return false;
//if ok, call parent logic
return webix.ui.dashboard.prototype.$dragCreate.apply(this, arguments);
},
}, webix.ui.dashboard);
由于我们正在从数据库中动态加载panel
视图的列表(及其配置),因此我们从一个空的c-dashboard
视图开始:
webix.ui({
id: "dashboardView",
view:"c-dashboard",
gridColumns:48,
gridRows:48,
cellHeight: 50,
cellWidth: 50,
autoplace: false
})
要用数据库中的面板填充c-dashboard
,我们从onChange
视图的richselect
调用此方法:
let dashboardInit = function(id) {
webix.promise.all([
webix.ajax().get("/api/dashboard/" + id + "/widgets")
]).then(function(result) {
let widgets = result[0].json();
for (const widget of widgets) {
buildWidget(widget);
}
});
};
我们最终使用addView
中的c-dashboard
构建每个面板:
let buildWidget = function(widget) {
let widgetId = "widget_" + widget.id;
$$("dashboardView").addView({
view: "panel",
id: widgetId,
css: "outerWidgetPanel",
x: widget.x,
y: widget.y,
dx: widget.dx,
dy: widget.dy,
resize: true,
body: { template: panelTemplate(widgetId) },
});
// here we're loading js modules which contains code to render something interesting the `panel` that was just added.
// the module also contains code to save the panel conifg and other `panel` meta data back to the database.
(async () => {
const Module = await import("/src/js/widget/" + widget.type);
let Widget = Module.default;
let widgetInstance = new Widget(widget);
widgets.push({ id: widget.id, widgetInstance });
})();
};
上面的每个模块都扩展了小部件:
class Widget {
constructor(widget, instance = this) {
// code to init widget
this.render();
}
render() {
// code to render content inside the webix panel.
}
move(x,y) {
// ajax PUT call to save new widget position to db.
}
}
我尝试过的内容
我尝试通过向c-dashboard
或$drop
添加呼叫来扩展$dragDestroy
:
...
$drop: function(target, source, event) {
let panel = $$(event.path[1].id);
this.callEvent("onPanelDrop", [panel]);
return webix.ui.dashboard.prototype.$drop.apply(this, arguments);
}
然后将onPanelDrop
事件附加到c-dashboard
:
$$("dashboardView").attachEvent("onPanelDrop", function() {
let id = numpart(panel.config.id); // strip out text, leaving only id.
let widget = widgets.find(obj => { return obj.id === id }).widgetInstance;
widget.move(panel.config.x, panel.config.y);
})
问题是(在webix中?)有些边缘情况我不确定如何检测到,从而使$drop
中的代码不可靠。具体来说,我通常可以从event.path[1].id
获取面板对象,但有时需要使用event.path[2].id
或偶尔使用其他偏移量。
问题
在正常情况下,我可以使用onBeforeDragIn
或onAfterDrop
来检测移动面板的位置。
但是,使用dashobard
扩展webix.protoUI
会破坏此功能(至少是我这样做的方式)。相反,这两个事件永远不会触发。
使用dashboard
扩展webix.protoUI
时,检测移动面板的正确方法是什么? /如何添加功能,以便onBeforeDrag
上触发onAfterDrop
和c-dashboard
事件?
谢谢。