最近在更改以前的旧项目,老板要求新增一个拖放排序的功能。但是因为之前项目是用jquery做的,牵扯到太多的DOM结构,更改起来太麻烦了,所以只能借助插件了。
原本是打算使用jquery ui的排序组件的,但是因为当前页面已经使用了select2,jquery版本不同导致会出错,所以只好放弃,不过jquery ui还是很不错的。
最后选择了DDSort这个插件:http://www.jq22.com/jquery-info8874
插件作者还是很厉害的,可以完美的嵌套在我的当前项目中,不过有一个小瑕疵,因为我在使用的过程中发现,我拖拽了当前DIV之后,元素位置越向下偏差越大,检查代码后 发现能力不足没有找到问题。
但还是有大牛发现并完美解决了问题。
问题如下:
更改后的js代码:
;(function( $ ){
/**
* Author: https://github.com/Barrior
*
* DDSort: drag and drop sorting.
* @param {Object} options
* target[string]: 可选,jQuery事件委托选择器字符串,默认'li'
* cloneStyle[object]: 可选,设置占位符元素的样式
* floatStyle[object]: 可选,设置拖动元素的样式
* down[function]: 可选,鼠标按下时执行的函数
* move[function]: 可选,鼠标移动时执行的函数
* up[function]: 可选,鼠标抬起时执行的函数
*/
$.fn.DDSort = function( options ){
var $doc = $( document ),
fnEmpty = function(){},
settings = $.extend( true, {
down: fnEmpty,
move: fnEmpty,
up: fnEmpty,
target: 'li',
cloneStyle: {
'background-color': '#eee'
},
floatStyle: {
//用固定定位可以防止定位父级不是Body的情况的兼容处理,表示不兼容IE6,无妨
'position': 'fixed',
'box-shadow': '10px 10px 20px 0 #eee',
'webkitTransform': 'rotate(4deg)',
'mozTransform': 'rotate(4deg)',
'msTransform': 'rotate(4deg)',
'transform': 'rotate(4deg)'
}
}, options );
return this.each(function(){
var that = $( this ),
height = 'height',
width = 'width';
if( that.css( 'box-sizing' ) == 'border-box' ){
height = 'outerHeight';
width = 'outerWidth';
}
that.on( 'mousedown.DDSort', settings.target, function( e ){
//只允许鼠标左键拖动
if( e.which != 1 ){
return;
}
//防止表单元素失效
var tagName = e.target.tagName.toLowerCase();
if( tagName == 'input' || tagName == 'textarea' || tagName == 'select' ){
return;
}
var THIS = this,
$this = $( THIS ),
offset = $this.offset(),
disX = e.pageX - offset.left,
disY = e.pageY - offset.top,
clone = $this.clone()
.css( settings.cloneStyle )
.css( 'height', $this[ height ]() )
.empty(),
hasClone = 1,
//缓存计算
thisOuterHeight = $this.outerHeight(),
thatOuterHeight = that.outerHeight(),
//滚动速度
upSpeed = thisOuterHeight,
downSpeed = thisOuterHeight,
maxSpeed = thisOuterHeight * 3;
settings.down.call( THIS );
$doc.on( 'mousemove.DDSort', function( e ){
if( hasClone ){
$this.before( clone )
.css( 'width', $this[ width ]() )
.css( settings.floatStyle )
.appendTo( $this.parent() );
hasClone = 0;
}
var left = e.pageX - disX,
top = e.pageY - disY,
prev = clone.prev(),
next = clone.next().not( $this );
scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
$this.css({
left: left,
top: top-scrollTop
});
//向上排序
if( prev.length && top < prev.offset().top + prev.outerHeight()/2 ){
clone.after( prev );
//向下排序
}else if( next.length && top + thisOuterHeight > next.offset().top + next.outerHeight()/2 ){
clone.before( next );
}
/**
* 处理滚动条
* that是带着滚动条的元素,这里默认以为that元素是这样的元素(正常情况就是这样),如果使用者事件委托的元素不是这样的元素,那么需要提供接口出来
*/
var thatScrollTop = that.scrollTop(),
thatOffsetTop = that.offset().top,
scrollVal;
//向上滚动
if( top < thatOffsetTop ){
downSpeed = thisOuterHeight;
upSpeed = ++upSpeed > maxSpeed ? maxSpeed : upSpeed;
scrollVal = thatScrollTop - upSpeed;
//向下滚动
}else if( top + thisOuterHeight - thatOffsetTop > thatOuterHeight ){
upSpeed = thisOuterHeight;
downSpeed = ++downSpeed > maxSpeed ? maxSpeed : downSpeed;
scrollVal = thatScrollTop + downSpeed;
}
that.scrollTop( scrollVal );
settings.move.call( THIS );
})
.on( 'mouseup.DDSort', function(){
$doc.off( 'mousemove.DDSort mouseup.DDSort' );
//click的时候也会触发mouseup事件,加上判断阻止这种情况
if( !hasClone ){
clone.before( $this.removeAttr( 'style' ) ).remove();
settings.up.call( THIS );
}
});
return false;
});
});
};
})( jQuery );
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jQuery任意拖动页面中元素代码</title>
<style type="text/css">
#wrap{
margin: 50px auto;
padding-top: 20px;
border: 1px solid #ccc;
overflow: auto;
overflow-x: hidden;
position: relative;
}
ul{
padding: 0;
margin: 0;
}
li{
padding: 10px;
margin-bottom: 20px;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
font: 14px/1.5 "微软雅黑";
list-style: none;
cursor: move;
}
li:hover{
background-color: #f6f6f6;
}
</style>
</head>
<body>
<div id="wrap">
<ul>
<li class="qwe">
1,JQuery是继prototype之后又一个优秀的Javascript库。它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+),jQuery2.0及后续版本将不再支持IE6/7/8浏览器。
</li>
<li class="qwe">
2,jQuery是一个兼容多浏览器的javascript库,核心理念是write less,do more(写得更少,做得更多)。jQuery在2006年1月由美国人John Resig在纽约的barcamp发布,吸引了来自世界各地的众多JavaScript高手加入
</li>
<li class="qwe">
3,jQuery是免费、开源的,使用MIT许可协议。jQuery的语法设计可以使开发更加便捷,例如操作文档对象、选择DOM元素、制作动画效果、事件处理、使用Ajax以及其他功能。
</li>
<li class="qwe">
4,jQuery,顾名思义,也就是JavaScript和查询(Query),即是辅助JavaScript开发的库。
</li>
<li class="qwe">5,2006年1月,jQuery的第一个版本面世,至今已经有10年多了(注:这个时间点是截止至出书时间)。虽然过了这么久,但它依然以其简洁、灵活的编程风格让人一见倾心。</li>
</ul>
</div>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script src="js/ddsort.js"></script>
<script>
$( '#wrap' ).DDSort({
target: '.qwe',
floatStyle: {
'border': '1px solid #ccc',
'background-color': '#fff'
}
});
</script>
</body>
</html>