通过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正则表达式在页面验证url网址输入是否正确
Apr 04 jQuery
vue中如何引入jQuery和Bootstrap
Apr 10 jQuery
jQuery实现动态生成表格并为行绑定单击变色动作的方法
Apr 17 jQuery
jQuery使用bind函数实现绑定多个事件的方法
Oct 11 jQuery
jQuery图片加载失败替换默认图片方法汇总
Nov 29 jQuery
基于jQuery Ajax实现下拉框无刷新联动
Dec 06 jQuery
jQuery实现的上传图片本地预览效果简单示例
Mar 29 jQuery
jQuery实现table表格checkbox全选的方法分析
Jul 04 jQuery
jQuery实现提交表单时不提交隐藏div中input的方法
Oct 08 jQuery
jQuery 函数实例分析【函数声明、函数表达式、匿名函数等】
May 19 jQuery
jquery html添加元素/删除元素操作实例详解
May 20 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
mysql中存储过程、函数的一些问题
2007/02/14 PHP
laravel实现查询最后执行的一条sql语句的方法
2019/10/09 PHP
在一个浏览器里呈现所有浏览器测试结果的前端测试工具的思路
2010/03/02 Javascript
javascript写的简单的计算器,内容很多,方法实用,推荐
2011/12/29 Javascript
jQuery中unwrap()方法用法实例
2015/01/16 Javascript
Node.js与Sails ~项目结构与Mvc实现及日志机制
2015/10/14 Javascript
JavaScript实现页面跳转的方式汇总
2016/05/16 Javascript
React创建组件的三种方式及其区别
2017/01/12 Javascript
基于vue.js的分页插件详解
2017/11/27 Javascript
vue通过cookie获取用户登录信息的思路详解
2018/10/30 Javascript
jQuery的ztree仿windows文件新建和拖拽功能的实现代码
2018/12/05 jQuery
Vue中多个元素、组件的过渡及列表过渡的方法示例
2019/02/13 Javascript
JavaScript实现的弹出遮罩层特效经典示例【基于jQuery】
2019/07/10 jQuery
vue 实现购物车总价计算
2019/11/06 Javascript
小程序如何定位所在城市及发起周边搜索
2020/02/11 Javascript
vue动态设置页面title的方法实例
2020/08/23 Javascript
Vue js with语句原理及用法解析
2020/09/03 Javascript
vuex刷新后数据丢失的解决方法
2020/10/18 Javascript
[02:39]DOTA2英雄基础教程 天怒法师
2013/11/29 DOTA
python使用点操作符访问字典(dict)数据的方法
2015/03/16 Python
Python:Scrapy框架中Item Pipeline组件使用详解
2017/12/27 Python
Python无损音乐搜索引擎实现代码
2018/02/02 Python
Python运维自动化之nginx配置文件对比操作示例
2018/08/29 Python
python对html过滤处理的方法
2018/10/21 Python
Django为窗体加上防机器人的验证码功能过程解析
2019/08/14 Python
Python中的list与tuple集合区别解析
2019/10/12 Python
基于python3生成标签云代码解析
2020/02/18 Python
canvas绘制文本内容自动换行的实现代码
2019/01/14 HTML / CSS
Omio西班牙:全欧洲低价大巴、火车和航班搜索和比价
2017/02/11 全球购物
英国儿童图书网站:Scholastic
2017/03/26 全球购物
Foot Locker加拿大官网:美国知名运动产品零售商
2019/07/21 全球购物
大学生工作推荐信范文
2013/12/02 职场文书
市场营销管理毕业生自荐信
2014/03/03 职场文书
2014年党员承诺书范文
2014/05/20 职场文书
恶魔之树最顶端的三颗果实 震震果实上榜,第一可以制造岩浆
2022/03/18 日漫
《极主夫道》真人电影正式预告 定档6月3日上映
2022/04/05 日漫