连接线支持单击选中,backspace 和 delete 可删除;双击可以为连接线添加 label。
完整代码:
/**
* 单击删除连线
*
*/
clickLine:function(){
var that = this;
jsPlumb.bind("click", function (conn, originalEvent) {
if(!isNew){
return false;
}
// 取消上次延时未执行的方法
clearTimeout(lineTimes);
//执行延时
lineTimes = setTimeout(function(){
jsPlumb.repaintEverything();
var target = originalEvent.toElement;
var isOuter = target.getAttribute('class') ? true : false;
if(isOuter){
return false;
}
target.setAttribute('stroke','#409eff');
$(document).keydown(function(event){
event=event||window.event
if(event.keyCode==8 || event.keyCode==46){ //8--backspace;46--delete
jsPlumb.detach(conn);
return false;
}
})
},300);
});
return this;
},
/**
* 双击给线添加label
*
*/
dblclickLine:function(){
var that = this;
jsPlumb.bind("dblclick", function (conn, originalEvent) {
if(!isNew){
return false;
}
// 取消上次延时未执行的方法
clearTimeout(lineTimes );
//如果连接线有label,则获取焦点,如果没有,则添加。
var labelInfo = that.lineIsHasLabel(conn);
if(labelInfo.isHasLabel){
labelInfo.currentLabel.removeClass('label-blur').addClass('label-focus');
var oldText = labelInfo.currentLabel.children('.label-text').html();
var inputDom = $('<input type="text" class="label-input" value="'+oldText+'"/>')
setTimeout(function(){
inputDom.focus();
},50)
labelInfo.currentLabel.append(inputDom)
return false;
}
_index++;
var left = parseInt(originalEvent.clientX-container.offset().left)
var top = parseInt(originalEvent.clientY-container.offset().top)
var id = "label"+_index;
var labelDom = $('<div class="line-label label-focus" id="' + id + '" data-path="'+conn.id+'"><span class="label-text"></span><input type="text" class="label-input"/></div>')
labelDom.css("left", left).css("top", top);
var input = labelDom.children('input.label-input');
setTimeout(function(){
input.focus();
},50)
container.append(labelDom);
labelDom.keydown(function (event) {
event=event||window.event;
if(event.keyCode==13){
var text = input.val();
if(!text){
labelDom.remove();
return false;
}
labelDom.children('span').html(input.val());
input.remove();
labelDom.removeClass('label-focus').addClass('label-blur');
return false;
}
});
// label 可以拖动
jsPlumb.draggable(id);
labelDom.draggable({ containment: "parent" });
});
return this;
},
1.单击删除连接线
jsPlumb.detach(); 可以删除连接的线。
思路:jsPlumb 允许添加事件。这里添加点击事件,之后给 document 添加键盘事件,按下 Backspace 和 Delete 时,删除连线。
jsPlumb.bind("click", function (conn, originalEvent) {
if(!isNew){
return false;
}
$(document).keydown(function(event){
event=event||window.event
if(event.keyCode==8 || event.keyCode==46){ //8--backspace;46--delete
jsPlumb.detach(conn);
return false;
}
})
});
2.双击添加 Label
思路:双击连线时,在画布中添加 div ,并且根据鼠标点击的位置,设置div 的位置。div 中包含input 输入框,可直接编辑。同时,我这里做了一个限定,即一条线只能添加一个label ,因此在添加之前,需要判断,连线是否有label,有则使原有的处于选中状态,没有则添加。
//如果连接线有lebel,则获取焦点,如果没有,则添加。
var labelInfo = that.lineIsHasLabel(conn);
if(labelInfo.isHasLabel){
labelInfo.currentLabel.removeClass('label-blur').addClass('label-focus');
var oldText = labelInfo.currentLabel.children('.label-text').html();
var inputDom = $('<input type="text" class="label-input" value="'+oldText+'"/>')
setTimeout(function(){
inputDom.focus();
},50)
labelInfo.currentLabel.append(inputDom)
return false;
}
_index++;
var left = parseInt(originalEvent.clientX-container.offset().left)
var top = parseInt(originalEvent.clientY-container.offset().top)
var id = that.judgeId("label",_index);
var labelDom = $('<div class="line-label label-focus" id="' + id + '" data-path="'+conn.id+'"><span class="label-text"></span><input type="text" class="label-input"/></div>')
labelDom.css("left", left).css("top", top);
var input = labelDom.children('input.label-input');
setTimeout(function(){
input.focus();
},50)
container.append(labelDom);
labelDom.keydown(function (event) {
event=event||window.event;
if(event.keyCode==13){
var text = input.val();
if(!text){
labelDom.remove();
return false;
}
labelDom.children('span').html(input.val());
input.remove();
labelDom.removeClass('label-focus').addClass('label-blur');
return false;
}
});
同时,label 也是可以拖动的。
// label 可以拖动
jsPlumb.draggable(id);
labelDom.draggable({ containment: "parent" });
判断连线是否有 label 的方法:
/**
* 判断连接线,是否有label
* @params conn Object 连线对象
* @return Object labelInfo
*/
lineIsHasLabel:function(conn){
var pathId = conn.id;
var lebelDoms = $('.line-label');
var isHasLabel = false;
var currentLabel;
for(var i = 0;i<lebelDoms.length;i++){
var item = lebelDoms.eq(i);
isHasLabel = item.data('path') == pathId ? true : false;
if(isHasLabel){
currentLabel = item;
break;
}
}
return {
isHasLabel:isHasLabel,
currentLabel:currentLabel
};
},
3.label 的操作
label 的操作和节点操作类似,也是单击获取焦点,可以删除,双击可以改变内容,同时支持拖动改变大小。
/**
* label 事件
*
*/
labelClick:function(id){
var currentDom = $('#'+id);
// 单击选中,可删除
currentDom.click(function(){
clearTimeout(labelTimes);
labelTimes = setTimeout(function(){
container.children('.line-label').removeClass('label-focus').addClass('label-blur');
currentDom.addClass('label-focus').removeClass('label-blur');
var input = $("<input type='text' class='hide-input'/>");
setTimeout(function(){
input.focus();
},50)
currentDom.append(input);
currentDom.keydown(function (event) {
event=event||window.event
if(event.keyCode==8 || event.keyCode==46){ //8--backspace;46--delete
currentDom.remove();
return false;
}
});
},300);
})
// 双击添加文字
currentDom.dblclick(function () {
// 取消上次延时未执行的方法
clearTimeout(labelTimes );
container.children('.line-label').removeClass('label-focus').addClass('label-blur');
currentDom.addClass('label-focus').removeClass('label-blur');
var text = currentDom.children('span').text().replace(/(^\s*)|(\s*$)/g, "") || '';
currentDom.children('span').html("");
var input = $("<input type='text' class='label-input' value='" + text + "'/>");
setTimeout(function(){
input.focus();
},50)
currentDom.append(input);
currentDom.keydown(function (event) {
if(event.keyCode==13){
currentDom.children('span').html(currentDom.children("input.label-input").val());
currentDom.children("input.label-input").remove();
currentDom.removeClass('label-focus').addClass('label-blur');
return false;
}
});
});
// 拖拽改变大小
currentDom.resizable({
autoHide: true ,
containment: "parent",
minHeight: 40,
minWidth:70,
})
},
但是这里需要注意的是,因为有了 label ,连线在删除的时候,如果此连线有 label ,则也需要把 label 删除掉;节点在删除时,也是如此。
删除连线时,删除 label
var labelInfo = that.lineIsHasLabel(conn);
if(labelInfo.isHasLabel){
labelInfo.currentLabel.remove();
}
删除节点时,删除 label
//如果连线有 label ,也得删除
var labelsDom = $('.line-label');
var paths = jsPlumb.getAllConnections();
if(labelsDom.length == 0){
return false;
}
for(var i=0;i<labelsDom.length;i++){
var currentLabelDom = labelsDom.eq(i);
var pathId = currentLabelDom.data('path');
var pathIsHave = false;
for(var j=0;j<paths.length;j++){
var currentPath = paths[j];
if(currentPath.id == pathId){
pathIsHave = true;
break;
}
}
if(!pathIsHave){
currentLabelDom.remove();
break;
}
}
项目地址:https://github.com/smile1828/demo-jsPlumb
基于 jsPlumb 的流程图编辑器的实现 (一,节点的操作)
基于 jsPlumb 的流程图编辑器的实现 (三,document的操作)
基于 jsPlumb 的流程图编辑器的实现 (四,按钮的操作)