Sortable.js拖拽排序方法,以及案例使用心得

时间:2024-04-13 07:25:10

最近有个新的需求,把点击事件改为鼠标拖拽添加我们想要的东西方便编辑部的小伙伴操作,demo如下:

Sortable.js拖拽排序方法,以及案例使用心得

 

老的版本是点击+加号,将我们输入的文本还有图片添加到空白区域,现改为拖拽的方式最左侧有一个隐藏了的垃圾筒,我们拖拽内容区的文本、视频、图片到这个隐藏的垃圾桶上方,内容区的当前脱宅的内容就会被垃圾桶回收,在这里使用到了Sorttable.js插件满足了一点小的需求,但是这个插件还是很庞大的,也上百度搜了一个大佬的使用心得,于是就拿来使用了,我们吧右侧编辑好的文本,视频,图片拖拽到内容区默认是append进去的,顾名思义就是从底部插入的,在这里我使用了Sortable.js插件实现了在内容区域可手动拖拽排序,也就是标题和文字,图片,视频的位置可以排序,这样我们输出的代码也就是按照我们排序的最终结果输出的,废话不多说了,相信你们更像看看代码吧

另外补充一点的是,一说起拖拽我们首先想到的就是h5的drop事件,完全能够解决我们现有的需求了……

 

html代码:

<div class="edit">

<div class="remove" id="remove"></div>

<div class="left block__list block__list_words" id="left"></div>

<div class="right" id="right">

<div class="add_line">

<h4>添加标题</h4>

<div class="input-line">

<input class="ipt" type="text" name="title" value="" draggable="true">

<span>+</span>

</div>

</div>

<div class="add_line">

<h4>添加文字</h4>

<div class="input-line">

<input class="ipt" type="text" name="text" value="" draggable="true">

<span>+</span>

</div>

</div>

<div class="add_line">

<h4>添加图片地址</h4>

<div class="input-line">

<input class="ipt" type="text" name="img" value="" draggable="true">

<span>+</span>

</div>

</div>

<div class="add_line">

<h4>添加视频地址</h4>

<div class="input-line">

<input class="ipt" type="text" name="video" value="" placeholder="视频地址" draggable="true">

<span>+</span>

</div>

<div class="input-line">

<input class="ipt" type="text" name="video-img" value="" placeholder="封面地址" draggable="true">

</div>

</div>

<div class="add_line">

<h4>修改参数</h4>

<div class="input-line" draggable="false">

<input type="text" name="xg" value="">

<i id="xgcs">修改</i>

</div>

</div>

<div class="btn-line">

<div class="output">输出代码</div>

<div class="fanput">反向输出</div>

</div>

</div>

</div>

<div class="upload">

<div class="text">上传图片:</div>

<input type="file" id="UpPicUrl1" name="filedata">

<span class="text_input">点击上传</span>

<input type="text" name="fileshow" value="" placeholder="已经上传的地址">

</div>

<textarea class="outline"></textarea>

style:

/*样式重置start*/

html,body,div,ul,li,h1,h2,h3,h4,h5,p,em,i,img,input,textarea {margin: 0px;padding: 0px;}

a {text-decoration: none;}

li {list-style: none;}

em,i {font-style: normal;}

body {font-family: arial, 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;}

.edit {padding-top: 30px;overflow: hidden;min-width: 1400px;}

.edit .left {float: left;width: 400px;height: 500px;border: 1px solid #333;padding-top: 10px;overflow-y: auto;}

.edit .right {float: left;overflow: hidden;padding-left: 30px;}

.edit .right .add_line {overflow: hidden;margin-bottom: 10px;}

.edit .right .add_line h4 {height: 40px;line-height: 40px;font-size: 20px;color: #333;}

.edit .right .add_line .input-line {overflow: hidden;}

.edit .right .add_line .input-line input {float: left;width: 500px;padding: 0 20px;height: 34px;background: none;border: 1px solid #aaa;}

.edit .right .add_line .input-line span {float: left;margin-right: 20px;width: 36px;height: 36px;background-color: #f9513b;text-align: center;line-height: 34px;font-size: 30px;color: #fff;cursor: pointer;}

.edit .right .add_line .input-line i {float: left;margin-right: 20px;padding: 0 15px;height: 36px;background-color: #f9513b;text-align: center;line-height: 34px;font-size: 15px;color: #fff;cursor: pointer;}

.edit .right .btn-line {height: 50px;overflow: hidden;}

.edit .right .output,.edit .right .fanput {float: left;width: 200px;height: 50px;border: 0 none;border-radius: 10px;background-color: #f9513b;text-align: center;font-size: 20px;color: #fff;line-height: 50px;cursor: pointer;margin-right: 20px;}

.edit .left .add-part {position: relative;border: 1px dashed #ccc;width: 90%;padding: 10px;margin: 0 auto 10px;cursor: pointer;}

.edit .left .add-part .close {position: absolute;top: 0;left: 0;width: 20px;height: 20px;background-color: #ccc;font-size: 15px;text-align: center;line-height: 20px;cursor: pointer;}

.edit .left .add-part .add {position: absolute;top: 0;right: 0;width: 20px;height: 20px;background-color: #ccc;font-size: 15px;text-align: center;line-height: 20px;cursor: pointer;}

.edit .left .add-part h5 {text-align: center;height: 30px;font-size: 20px;color: #333;cursor: pointer;}

.edit .left .add-part p {text-align: center;line-height: 24px;font-size: 16px;color: #333;}

.edit .left .add-part img {display: block;width: 100%;height: auto;}

.edit .left .add-part video {display: block;width: 100%;height: auto;}

.outline {display: block;width: 1180px;height: 200px;text-align: left;font-size: 16px;color: #333;margin: 0 auto;padding: 10px;}

.upload {position: relative;width: 1200px;margin: 20px auto;overflow: hidden;}

.upload .text {float: left;height: 36px;width: 100px;text-align: left;font-size: 16px;color: #333;line-height: 36px;}

.upload input[name=filedata] {position: absolute;top: 0;left: 100px;padding: 0;border: 0;height: 36px;width: 120px;float: left;opacity: 0;filter: alpha(opacity=0);}

.upload .text_input {float: left;height: 36px;width: 120px;line-height: 36px;color: #fff;background: #f40;text-align: center}

.upload input[name=fileshow] {float: left;background: none;border: 0 none;width: 600px;height: 34px;border: 1px solid #aaa;padding: 0 10px;margin-left: 20px;}

.remove {float: left;width: 24%;height: 510px;}

script:

<script src="http://cdn.temzt.cn/AppCms/CommonJs/jquery-1.8.2.min.js"></script>

<script src="http://cdn.temzt.cn/web/resource/js/common/jquery.fileupload.js"></script>

<script>

// =========================================拖拽事件==============================

var removeDom;

var G_step = 0;

//拖放开始:获取id放入dataTransfer

$(".add_line input").on("dragstart", function(e) {

e.originalEvent.dataTransfer.setData("value", e.target.value);

e.originalEvent.dataTransfer.setData("name", e.target.name);

});

 

//允许放入

$("#left").on("dragover", function(e) {

e.originalEvent.preventDefault();

})

//允许放入

$("#remove").on("dragover", function(e) {

e.originalEvent.preventDefault();

})

//放下事件

$("#left").on("drop", function(e) {

var value = e.originalEvent.dataTransfer.getData("value");

var name = e.originalEvent.dataTransfer.getData("name");

e.originalEvent.preventDefault();

var html = '';

if (!value) {

return false

};

if (name == 'title') {

var title_length = $(".add-part[data-type=title]").length;

html = '<h5 data-num="' + title_length + '">' + value + '</h5>';

$('input[name=title]').val('');

}

if (name == 'text') {

html = "<p>" + value + "</p>";

$('input[name=text]').val('');

}

if (name == 'img') {

html = "<img draggable='true' src='" + value + "' width='100%' height='auto'>";

$('input[name=img]').val('');

}

if (name == 'video') {

var img_val = $(".input-line input[name=video-img]").val();

html = "<div draggable='true' class='video-mian'><video poster='" + img_val + "' webkit-playsinline='true' x-webkit-airplay='true' playsinline='true' x5-video-player-type='h5' x5-video-player-fullscreen='true' controls='' style='width:100%; height:100%; object-fit: fill'><source draggable='true' src='" + value + "'></video></div>";

$('input[name=video]').val('');

$('input[name=video-img]').val('');

}

var targetHtml = '<div class="add-part" data-type="' + name + '" data-step="' + G_step + '">' + html + '</div>';

if ($(".add-part[data-type=null]").length != 0) {

$(".add-part[data-type=null]").attr("data-type", name);

} else {

$(this).append(targetHtml);

}

G_step++;

$('.add-part').on("dragstart", function(e) {

e.originalEvent.preventDefault;

// e.originalEvent.dataTransfer.setData("r", e.target);

removeDom = $(e.target)

})

})

 

//放下事件 用来删除

$("#remove").on("drop", function(e) {

e.originalEvent.preventDefault;

// var removeDom = e.originalEvent.dataTransfer.getData("r");

removeDom.remove();

});

此处是引用Sortable.js插件的效果,在内容区域我们可以随意拖拽目标元素进行排序,排成我们想要的效果:

Sortable.create(document.getElementById('left'), {

group: {name: "words",pull: 'clone',put: true},

animation: 150, //动画参数

});
点击内容区域的每一项内容对应加载到修改参数模块内,供我们修改:

$(".left").on("click", ".add-part", function() {

var type = $(this).attr("data-type");

var step = $(this).attr("data-step");

$("#xgcs").attr("data-step", step);

$("#xgcs").attr("data-type", type);

if (type == "title") {

$("input[name=xg]").val($(this).find("h5").html());

} else if (type == "text") {

$("input[name=xg]").val($(this).find("p").html());

} else if (type == "img") {

$("input[name=xg]").val($(this).find("img").attr("src"));

}

});

修改参数:

$("#xgcs").click(function() {

var step = $("#xgcs").attr("data-step");

var type = $("#xgcs").attr("data-type");

if (type == "title") {

$(".add-part[data-step=" + step + "]").find('h5').html($("input[name=xg]").val());

} else if (type == "text") {

$(".add-part[data-step=" + step + "]").find('p').html($("input[name=xg]").val());

} else if (type == "img") {

$(".add-part[data-step=" + step + "]").find('img').attr("src", $("input[name=xg]").val());

}

$("input[name=xg]").val("");

});

输出代码:

$(".output").click(function() {

var stringHtml = $(".left").html();

// stringHtmlN = stringHtml.replace(/<div class="add-part" [^>]+>/g, "").replace(/<span class="close">x<\/span><span class="add">\+<\/span><\/div>/g, "<!---->");

$(".outline").val(stringHtml);

});

反向输出:

$(".fanput").click(function() {

var html = $(".outline").val();

if (html) {

var htmlArry = html.split('<!---->');

var editHtml = '';

console.log(htmlArry)

for (var i = 0; i < htmlArry.length - 1; i++) {

if (htmlArry[i].indexOf('<h5') == 0) {

editHtml += '<div class="add-part" data-type="title" data-step="' + (i + 1) + '">' + htmlArry[i] + '<span class="close">x</span><span class="add">+</span></div>';

} else if (htmlArry[i].indexOf('<p>') == 0) {

editHtml += '<div class="add-part" data-type="text" data-step="' + (i + 1) + '">' + htmlArry[i] + '<span class="close">x</span><span class="add">+</span></div>';

} else if (htmlArry[i].indexOf('<img') == 0) {

editHtml += '<div class="add-part" data-type="img" data-step="' + (i + 1) + '">' + htmlArry[i] + '<span class="close">x</span><span class="add">+</span></div>';

} else {

editHtml += '<div class="add-part" data-type="video" data-step="' + (i + 1) + '">' + htmlArry[i] + '<span class="close">x</span><span class="add">+</span></div>';

}

 

}

G_step = htmlArry.length;

$(".left").html(editHtml);

}

});

 

$('#UpPicUrl1').fileupload({

dataType: "json",

url: '上传文件的接口',

acceptFileTypes: /(\.|\/)(bmp|gif|jpe?g|png)$/i,

maxFileSize: 5242880, // 5 MB=5*1024*1024

done: function(e, oData) {

if (!oData) {

dialog.alert('上传失败!');

return;

}

var oResult = oData.result;

if (oResult.StateCode == 200) {

var imgPath = oResult.result;

$("input[name=fileshow]").val(oResult.result.url);

console.log(oResult.result)

} else {

alert(oResult.Msg);

}

}

});

</script>

以上就是demo的主要代码了,接下来我们说一下Sortable.js的效果吧,我这有个小demo:

效果展示:

Sortable.js拖拽排序方法,以及案例使用心得

 

代码展示: 

Sortable.js拖拽排序方法,以及案例使用心得

 

Sortable.js拖拽排序方法,以及案例使用心得

 

就是这么简单,可以实现左侧任意拖动排序,右侧也可以任意拖动排序,同时右侧可以克隆右侧的每一行拖动到左侧并任意拖动到想要的位置。

如果是一个列表,那么就不需要其他的参数了,我们只需要设置引用下面的就欧了【实现一个列表内部的任意拖拽排序】:

Sortable.create(document.getElementById('foo'), {animation: 150, //动画参数});

sortable.js还有很多参数:

下载地址:https://github.com/RubaXa/Sortable

var defaults = {

 group: Math.random(), //产生一个随机数 //产生一个随机数 //改参数是对象有三个两个参数 pull: 拉, put:放 默认都是是true pull还有一个值是: 'clone', pull: 拉, put:放 设置为false 就不能拖拽了, 如果 pull 这种为'clone'则可以从一个列表中拖拽到另一个列表并且克隆dom节点, name:是两个或者多个列表拖拽之间的通信,两个或者三个列表的nea

 sort: true, // 类型:Boolean,值为false时,在自己的拖拽区域不能拖拽,但是可以拖拽到其他区域,true则可以做自己区域拖拽或者其他区域拖拽

 disabled: false, //类型:Boolean 是否禁用拖拽 true 则不能拖拽 默认是true

 store: null, // 用来html5 存储的 改返回 拖拽的节点的唯一id

 handle: null, //handle 这个参数是设置该标签,或者该class可以拖拽 但是不要设置 id的节点和子节点相同的tag不然会有bug

 scroll: true, //类型:Boolean,设置拖拽的时候滚动条是否智能滚动。默认为真,则智能滚动,false则不智能滚动

 scrollSensitivity: 30, //滚动的灵敏度,其实是拖拽离滚动边界的距离触发事件的距离边界+-30px的地方触发拖拽滚动事件,

 scrollSpeed: 10, //滚动速度

 draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*',//draggable 判断拖拽节点的父层是否是ou ul

 ghostClass: 'sortable-ghost', // 排序镜像class,就是当鼠标拉起拖拽节点的时候添加该class

 chosenClass: 'sortable-chosen', // //为拖拽的节点添加一个class 开始拖拽鼠标按下去的时候 添加该class

 ignore: 'a, img', //a 或者是img

 filter: null, //改参数可以传递一个函数,或者字符串,字符串可以是class或者tag,然后用于触发oFilter函数,这样可以用来自定义事件等

 animation: 0, //拖拽动画时间戳

 setData: function (dataTransfer, dragEl) { //设置拖拽传递的参数

 dataTransfer.setData('Text', dragEl.textContent);

 },

 dropBubble: false, // 发生 drop事件 拖拽的时候是否阻止事件冒泡

 dragoverBubble: false, //发生 dragover 事件 拖拽的时候是否阻止事件冒泡

 dataIdAttr: 'data-id', //拖拽元素的id 数组

 delay: 0, //延迟拖拽时间, 其实就是鼠标按下去拖拽延迟

 forceFallback: false, // 不详

 fallbackClass: 'sortable-fallback', // 排序回退class

 fallbackOnBody: false,// 是否把拖拽镜像节点ghostEl放到body上

 };

由于时间有限,就先絮叨到这吧!谢谢小伙伴们的支持与鼓励,你们的鼓励将是我最大的动力……