通过JQuery,JQueryUI和Jsplumb实现拖拽模块


Posted in jQuery onJune 18, 2019

前言

由于时间的原因。这个demo只兼容IE8,IE9。其他浏览器暂时不支持。不过jsplumb本身是支持各种浏览器的。

写这篇文章是因为我在实际开发中遇到一个需求,支持拖拽模块到指定的容器里。并且每个模块会有自己的output 和input。开始觉得很酷也很变态。经过一段时间的调研,特把结果分享给大家。不足之处,敬请指正。

看了题目里的3个J。可能有的朋友觉得头晕,需要这么多东东?我先逐一介绍一下。

第一个jquery是我们平时经常使用的jquery 库。它可以让你用很少的代码实现一些很酷的js功能(实际它封装了很多js)。

第二个JQueryUI提供了一整套核心交互插件,UI部分用jQuery的风格。灵活的造型,人性化设计的视觉效果。可以提供一些常用的很炫的功能。比如。弹出窗,日历,拖拽,折叠,日历等等。更酷的他的css是可以定制的。我们可以根据自己想要的风格很轻松的生成自己想要的样式。直接替换theme就可以改变整个站点的风格。很多人选择jquery ui的更深一层原因是,它对各个浏览器兼容性很好,支持 IE 6.0+, Firefox 3+, Safari 3.1+, Opera 9.6+和Google Chrome。

在这里,我们会用到一个它其中的drag and drop(拖拽)功能。

具体请见http://jqueryui.com/

第三个Jsplumb 是一个允许里使用箭头,线去连接UI上的元素的JS库。目前的版本是1.3.8。已经是一个成熟的产品,并且经常更新。我当时查到了很多类似的js库。调研比较之后决定使用它。他的官方网站:http://jsplumb.org/jquery/demo.html

首先我还是说说需求。UI左边是待拖拽的模块。我从左边把它拖拽到右边的容器里。大概就是下图描述的样子。

通过JQuery,JQueryUI和Jsplumb实现拖拽模块

左边三个窗体。我们给他同一的class ,方便jquery来操作。

<div id="container">
<div id="mainContent">
<div id="sidebar">
Module List
<div class="window" id="">
<strong>1</strong><br />
<br />
</div>
<br />
<div class="window" id="">
<strong>2</strong><br />
<br />
</div>
<div class="window" id="">
<strong>3</strong><br />
<br />
</div>
</div>
<div id="content">
<p>drop here!</p>
</div>
</div>
</div

在页面载入时,首先使用jquery ui里的draggable功能使得我们的3个窗体变为可以拖动的。

因为他们有共同的class “window”,我们可以这样:

$(".window").draggable({
helper: "clone"
});

helper:clone的意思是我们只是拖出这个window的副本。如果不加这个属性。我们就会把这个窗体拖走了。

上边id为content的div就是我们要放置窗体的目标容器。我们要把这个容器设置为droppable。就是标记它为可以接受拽过来的window。

$("#content").droppable({});

当content 被放入window的时候会触发drop事件。我们为drop事件定义一个function。

下边代码中入参的ui就是当前被drop进容器的元素。这里我们做一个判断,如果被放进来的元素的class包含jq-draggable-outcontainer。也就是说,这个元素是我们从左边siderbar拽过来的话。

首先判断这个元素中的innerText。根据innerText的不同在右边的窗体中render一个新的窗体。(这里使用innerText判断是不严谨的,我只是做一个demo。为大家抛砖引玉)。

$("#content").droppable({
drop: function (event, ui) {
// debugger;
if (ui.draggable[0].className.indexOf("jq-draggable-outcontainer") > 0) {
var text = ui.draggable[0].innerText
switch (text) {
case "1":
$(this)
.find("p")
.append('<div class="window jq-draggable-incontainer" id="window1"><strong>1</strong><br /><br /></div><div style="height:100px;"></div>');
SBS.UI.Views.Plumb.AddEndpoints("window1", ["BottomCenter"], []);
case "2":
$(this)
.find("p")
.append('<div class="window jq-draggable-incontainer" id="window2"><strong>2</strong><br /><br /></div><div style="height:100px;"></div>');
SBS.UI.Views.Plumb.AddEndpoints("window2", ["BottomCenter","BottomLeft"], ["TopCenter"]);
} break;
case "3":
$(this)
.find("p")
.after('<div class="window jq-draggable-incontainer" id="window3"><strong>3</strong><br /><br /></div>');
SBS.UI.Views.Plumb.AddEndpoints("window3", [], ["TopCenter", "TopLeft"]);
}
}
}
});

大家注意这个函数SBS.UI.Views.Plumb.AddEndpoints("window1", ["BottomCenter"], []);它是封装了jsplumb 为窗体加上输入和输出的功能。先不管它,一会我们再分析。

现在我们试着拖动一个窗体到右边的容器。可以看到实际已经在右边创建了一个窗体。如下图。

通过JQuery,JQueryUI和Jsplumb实现拖拽模块

蓝色的圆点就是我们刚才绘画出来的一个output点。由于我们在上边代码中指定了BottomCenter。所以这个点被画在了windows底部的中间。

现在让jsplumb是如何画出来这个点,并且需要哪些初始化过程。

// <reference path="jquery-1.5.1-vsdoc.js" />
var SBS = SBS || {};
SBS.UI = SBS.UI || {};
SBS.UI.Views = SBS.UI.Views || {};
SBS.UI.Views.Plumb = {
init: function () {
jsPlumb.importDefaults({
// default drag options
DragOptions: { cursor: 'pointer', zIndex: 2000 },
// default to blue at one end and green at the other
EndpointStyles: [{ fillStyle: '#225588' }, { fillStyle: '#558822'}],
// blue endpoints 7 px; green endpoints 11.
Endpoints: [["Dot", { radius: 7}], ["Dot", { radius: 11}]],
// the overlays to decorate each connection with. note that the label overlay uses a function to generate the label text; in this
// case it returns the 'labelText' member that we set on each connection in the 'init' method below.
ConnectionOverlays: [
["Arrow", { location: 0.9}],
["Label", {
location: 0.1,
id: "label",
cssClass: "aLabel"
}]
]
});
var connectorPaintStyle = {
lineWidth: 5,
strokeStyle: "#deea18",
joinstyle: "round"
},
// .. and this is the hover style. 
connectorHoverStyle = {
lineWidth: 7,
strokeStyle: "#2e2aF8"
};
sourceEndpoint = {
endpoint: "Dot",
paintStyle: { fillStyle: "#225588", radius: 7 },
isSource: true,
connector: ["Flowchart", { stub: 40}],
connectorStyle: connectorPaintStyle,
hoverPaintStyle: connectorHoverStyle,
connectorHoverStyle: connectorHoverStyle
};
targetEndpoint = {
endpoint: "Rectangle",
paintStyle: { fillStyle: "#558822", radius: 11 },
hoverPaintStyle: connectorHoverStyle,
maxConnections: -1,
dropOptions: { hoverClass: "hover", activeClass: "active" },
isTarget: true
};
jsPlumb.bind("jsPlumbConnection", function (connInfo, originalEvent) {
init(connInfo.connection);
});
jsPlumb.bind("click", function (conn, originalEvent) {
if (confirm("Delete connection from " + conn.sourceId + " to " + conn.targetId + "?"))
jsPlumb.detach(conn);
});
},
AddEndpoints: function (toId, sourceAnchors, targetAnchors) {
var allSourceEndpoints = [], allTargetEndpoints = [];
for (var i = 0; i < sourceAnchors.length; i++) {
var sourceUUID = toId + sourceAnchors[i];
allSourceEndpoints.push(jsPlumb.addEndpoint(toId, sourceEndpoint, { anchor: sourceAnchors[i], uuid: sourceUUID }));
}
for (var j = 0; j < targetAnchors.length; j++) {
var targetUUID = toId + targetAnchors[j];
allTargetEndpoints.push(jsPlumb.addEndpoint(toId, targetEndpoint, { anchor: targetAnchors[j], uuid: targetUUID }));
}
}
}
//Page load events
$(document).ready(
function () {
//all JavaScript that needs to be call onPageLoad can be put here.
SBS.UI.Views.Plumb.init();
}
);

上边的代码是我写的一个调用jsplumb的js类。init函数里初始化了圆点和连接的样式。具体的我们可以查看它的api http://jsplumb.org/apidocs/files/jquery-jsPlumb-1-3-8-all-js.html

我们主要看AddEndpoints 函数。它接收3个参数toId, sourceAnchors, targetAnchors。

toId就是我们要在哪个元素上加输入和输出的标记。sourceAnchors就是输出的点的集合,targetAnchors就是输入的点的集合。遍历这些点。并且调用jsplumb的方法

jsPlumb.addEndpoint()就可以把这几个点画到元素上去了。

基本的功能就完成了。但是我们新画出来的window还不能拖拽。我们要指定这几个window是可以拖拽的。

使用jquery里的draggable为其标记。并指定可以拖拽的范围(局限于我们的content容器)。如果想限制元素拖拽的范围,只需要设置它的containment属性。

$(".jq-draggable-incontainer").draggable({
containment: $( "#content" ).length ? "#content" : "document"
});

现在这几个window可以拖拽了。并且可以使用箭头来连接。

刷新元素

我发现当我拖拽了window之后,那几个点是不跟着走的。查了api找到了一个函数。 jsPlumb.repaintEverything();就是重新画所有的东西。

我们可以把它放在droppable的drop事件的最后。

这个demo做的比较糙,因为也是初步调研阶段。比如用户拽了同一个window到右边2次。就会出现错误。因为id重复了。我们可以遍历id或者把已经创建的id存起来,来创建新的id。不过我做了一个偷懒的芳芳,也符合我本身的需求。就是一种类型的window只可以拽一次。第二次就不让用户拽了。Jquery提供了很好的实现。自动弹回去的功能。

在页面第一次加载时候,我先设置几个bool值到data里。当用户拽了一个window一次之后,就把那revert值设置为true。

$(function () {
$('#tmpl1').data("revert", false);
$('#tmpl2').data("revert", false);
$('#tmpl3').data("revert", false);
。。。。}
case "1":
if ($('#tmpl1').data("revert") == true) {
$('#tmpl1').draggable({ revert: "valid" });
}
else {
$(this)
.find("p")
.append('<div class="window jq-draggable-incontainer" id="window1"><strong>1</strong><br /><br /></div><div style="height:100px;"></div>');
SBS.UI.Views.Plumb.AddEndpoints("window1", ["BottomCenter"], []);
$('#tmpl1').data("revert", true);
} break;

源码下载

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

jQuery 相关文章推荐
基于jQuery实现瀑布流页面
Apr 11 jQuery
浅谈struts1 &amp; jquery form 文件异步上传
May 25 jQuery
简单实现jQuery弹窗效果
Oct 30 jQuery
jQuery实现动态显示select下拉列表数据的方法
Feb 05 jQuery
jQuery实现定时隐藏对话框的方法分析
Feb 12 jQuery
jQuery中实现text()的方法
Apr 04 jQuery
jQuery实现数字华容道小游戏(实例代码)
Jan 16 jQuery
jquery轮播图插件使用方法详解
Jul 31 jQuery
jquery实现淡入淡出轮播图效果
Dec 13 jQuery
原生jQuery实现只显示年份下拉框
Dec 24 jQuery
jquery自定义组件实例详解
Dec 31 jQuery
jquery插件实现图片悬浮
Apr 16 jQuery
如何使用CSS3+JQuery实现悬浮墙式菜单
Jun 18 #jQuery
jquery中为什么能用$操作
Jun 18 #jQuery
js/jQuery实现全选效果
Jun 17 #jQuery
jQuery创建折叠式菜单
Jun 15 #jQuery
JS实现点击生成UUID的方法完整实例【基于jQuery】
Jun 12 #jQuery
jquery操作checkbox的常用方法总结【附测试源码下载】
Jun 10 #jQuery
基于jquery实现的tab选项卡功能示例【附源码下载】
Jun 10 #jQuery
You might like
环境会对咖啡种植有什么影响
2021/03/03 咖啡文化
php打开文件fopen函数的使用说明
2013/07/05 PHP
php输入流php://input使用示例(php发送图片流到服务器)
2013/12/25 PHP
JavaScript语句可以不以;结尾的烦恼
2007/03/08 Javascript
extjs fckeditor集成代码
2009/05/10 Javascript
JavaScript中Object和Function的关系小结
2009/09/26 Javascript
Jquery创建层显示标题和内容且随鼠标移动而移动
2014/01/26 Javascript
JavaScript的事件代理和委托实例分析
2015/03/25 Javascript
基于javascript实现窗口抖动效果
2016/01/03 Javascript
jQuery获取父元素及父节点的方法小结
2016/04/14 Javascript
Bootstrap模态框(Modal)实现过渡效果
2017/03/17 Javascript
JS仿Base.js实现的继承示例
2017/04/07 Javascript
基于layer.js实现收货地址弹框选择然后返回相应的地址信息
2017/05/26 Javascript
vue的一个分页组件的示例代码
2017/12/25 Javascript
vue2.0 element-ui中el-select选择器无法显示选中的内容(解决方法)
2018/08/24 Javascript
extjs图表绘制之条形图实现方法分析
2020/03/06 Javascript
Postman内建变量常用方法实例解析
2020/07/28 Javascript
vue中是怎样监听数组变化的
2020/10/24 Javascript
Python线程详解
2015/06/24 Python
深入分析python数据挖掘 Json结构分析
2018/04/21 Python
pytorch 实现打印模型的参数值
2019/12/30 Python
Python+OpenCV图像处理——图像二值化的实现
2020/10/24 Python
纯CSS3制作页面切换效果的实例代码
2019/05/30 HTML / CSS
HTML5 自动聚焦(autofocus)属性使用介绍
2013/08/07 HTML / CSS
Nordgreen美国官网:在线购买极简主义斯堪的纳维亚手表
2019/07/24 全球购物
护士自荐信怎么写
2013/10/18 职场文书
人力资源专员岗位职责
2014/01/30 职场文书
四年级下册教学反思
2014/02/01 职场文书
社会治安综合治理管理责任书
2014/04/16 职场文书
教育项目合作协议书格式
2014/10/17 职场文书
工程承包协议书
2014/10/20 职场文书
小学教师2014年度工作总结
2014/12/03 职场文书
2016年第十四个公民道德宣传日活动总
2016/04/01 职场文书
Spring Boot mybatis-config 和 log4j 输出sql 日志的方式
2021/07/26 Java/Android
mybatis3中@SelectProvider传递参数方式
2021/08/04 Java/Android
输入框跟随文字内容适配宽实现示例
2022/08/14 Javascript