vr-shopxo-plugin/shopxo/public/static/common/lib/tdrag/tdrag.js

587 lines
23 KiB
JavaScript
Raw Normal View History

/*! Tdrag 0.0.1 */
/**
* Created by Tezml on 2016/5/26
* You can modify my source code, if you have a good idea or a problem can be encountered by e-mail: tezml@tezml.com to find me.
* 如果你想在项目中使用该插件请不要删除该注释
*/
;(function($,window,document,undefined){
jQuery(function() {
//插件制作
$.fn.Tdrag = function (opt) {
var call = {
scope: null,//父级
grid: null,//网格
axis:"all",//上下或者左右
pos:false,//是否记住位置
handle:null,//手柄
moveClass:"tezml",//移动时不换位加的class
dragChange:false,//是否开启拖拽换位
changeMode:"point",//point & sort
cbStart:function(){},//移动前的回调函数
cbMove:function(){},//移动中的回调函数
cbEnd:function(){},//移动结束时候的回调函数
random:false,//是否自动随机排序
randomInput:null,//点击随机排序的按钮
animation_options:{//运动时的参数
duration:800,//每次运动的时间
easing:"ease-out"//移动时的特效ease-out、ease-in、linear
},
disable:false,//禁止拖拽
disableInput:null//禁止拖拽的按钮
};
var dragfn = new Dragfn(this, opt);
if (opt && $.isEmptyObject(opt) == false) {
dragfn.options = $.extend(call, opt);
} else {
dragfn.options = call;
}
dragfn.firstRandom=true;
var ele = dragfn.$element;
dragfn.pack(ele,false);
if(dragfn.options.randomInput!=null){
$(dragfn.options.randomInput).bind("click",function(){
dragfn.pack(ele,true);
})
}
//加载拓展jquery的函数
dragfn.loadJqueryfn()
};
//依赖构造函数
var Dragfn = function (ele, opt) {
this.$element = ele;
this.options = opt;
};
//构造函数方法
Dragfn.prototype = {
init: function (obj) {
var self = this;
self.ele=self.$element;
self.handle=$(obj);//手柄
self.options = self.options;
self.disable = self.options.disable;
self._start = false;
self._move = false;
self._end = false;
self.disX = 0;
self.disY = 0;
self.zIndex=1000;
self.moving=false;
self.moves="";
//父级
self.box = $.type(self.options.scope)==="string" ? self.options.scope : null;
//手柄
if(self.options.handle!=null){
self.handle=$(obj).find(self.options.handle);
}
//三个事件
self.handle.on("mousedown", function (ev) {
self.start(ev, obj);
obj.setCapture && obj.setCapture();
return false;
});
if(self.options.dragChange) {
$(obj).on("mousemove", function (ev) {
self.move(ev, obj);
});
$(obj).on("mouseup", function (ev) {
self.end(ev, obj);
});
}else{
$(document).on("mousemove", function (ev) {
self.move(ev, obj);
});
$(document).on("mouseup", function (ev) {
self.end(ev, obj);
});
}
},
//jquery调取函数时候用
loadJqueryfn: function(){
var self=this;
$.extend({
//返回按照index排序的回调函数
sortBox:function(obj){
var arr=[];
for (var s = 0; s < $(obj).length; s++) {
arr.push($(obj).eq(s));
}
for ( var i = 0; i < arr.length; i++) {
for ( var j = i + 1; j < arr.length; j++) {
if(Number(arr[i].attr("index")) > Number(arr[j].attr("index"))){
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
return arr
},
//随机排序函数
randomfn:function(obj){
self.pack($(obj),true);
},
//开启拖拽
disable_open:function(){
self.disable=false;
},
//禁止拖拽
disable_cloose:function(){
self.disable=true;
}
});
},
toDisable: function(){
var self=this;
if(self.options.disableInput!=null){
$(self.options.disableInput).bind("click",function(){
if(self.disable==true){
self.disable=false
}else{
self.disable=true
}
})
}
},
start: function (ev, obj) {
var self = this;
self.moved=obj;
if (self.disable == true) {
return false
}
self._start = true;
var oEvent = ev || event;
self.disX = oEvent.clientX - obj.offsetLeft;
self.disY = oEvent.clientY - obj.offsetTop;
$(obj).css("zIndex",self.zIndex++);
self.options.cbStart();
},
move: function (ev, obj) {
var self = this;
if (self._start != true) {
return false
}
if(obj!=self.moved){
return false
}
self._move = true;
var oEvent = ev || event;
var l = oEvent.clientX - self.disX;
var t = oEvent.clientY - self.disY;
//有父级限制
if (self.box != null) {
var rule = self.collTestBox(obj,self.box);
if (l > rule.lmax) {
l = rule.lmax;
} else if (l < rule.lmin) {
l = rule.lmin;
}
if (t > rule.tmax) {
t = rule.tmax;
} else if (t < rule.tmin) {
t = rule.tmin;
}
}
if(self.options.axis=="all"){
obj.style.left = self.grid(obj, l, t).left + 'px';
obj.style.top = self.grid(obj, l, t).top + 'px';
}else if(self.options.axis=="y"){
obj.style.top = self.grid(obj, l, t).top + 'px';
}else if(self.options.axis=="x"){
obj.style.left = self.grid(obj, l, t).left + 'px';
}
/* if(self.options.changeWhen=="move") {
if (self.options.changeMode == "sort") {
self.sortDrag(obj);
} else if (self.options.changeMode == "point") {
self.pointmoveDrag(obj);
}
}else{
self.moveAddClass(obj);
}*/
if(self.options.pos==true){
self.moveAddClass(obj);
}
self.options.cbMove(obj,self);
},
end: function (ev, obj) {
var self = this;
if (self._start != true) {
return false
}
if(self.options.changeMode=="sort"&&self.options.pos==true){
self.sortDrag(obj);
}else if(self.options.changeMode=="point"&&self.options.pos==true){
self.pointDrag(obj);
}
if(self.options.pos==true){
self.animation(obj, self.aPos[$(obj).attr("index")]);
}
self.options.cbEnd();
if(self.options.handle!=null){
$(obj).find(self.options.handle).unbind("onmousemove");
$(obj).find(self.options.handle).unbind("onmouseup");
}else{
$(obj).unbind("onmousemove");
$(obj).unbind("onmouseup");
}
obj.releaseCapture && obj.releaseCapture();
self._start = false;
},
//算父级的宽高
collTestBox: function (obj, obj2) {
var self = this;
var l1 = 0;
var t1 = 0;
var l2 = $(obj2).innerWidth() - $(obj).outerWidth();
var t2 = $(obj2).innerHeight() - $(obj).outerHeight();
return {
lmin: l1,//取的l最小值
tmin: t1,//取的t最小值
lmax: l2,//取的l最大值
tmax: t2//取的t最大值
}
},
//算父级宽高时候干掉margin
grid: function (obj, l, t) {//cur:[width,height]
var self = this;
var json = {
left: l,
top: t
};
if ($.isArray(self.options.grid) && self.options.grid.length == 2) {
var gx = self.options.grid[0];
var gy = self.options.grid[1];
json.left = Math.floor((l + gx / 2) / gx) * gx;
json.top = Math.floor((t + gy / 2) / gy) * gy;
return json
} else if (self.options.grid == null) {
return json
} else {
console.log("grid参数传递格式错误");
return false
}
},
findNearest: function(obj){
var self=this;
var iMin=new Date().getTime();
var iMinIndex=-1;
var ele=self.ele;
for(var i=0;i<ele.length;i++){
if(obj==ele[i]){
continue;
}
if(self.collTest(obj,ele[i])){
var dis=self.getDis(obj,ele[i]);
if(dis<iMin){
iMin=dis;
iMinIndex=i;
}
}
}
if(iMinIndex==-1){
return null;
}else{
return ele[iMinIndex];
}
},
getDis: function(obj,obj2){
var self=this;
var l1=obj.offsetLeft+obj.offsetWidth/2;
var l2=obj2.offsetLeft+obj2.offsetWidth/2;
var t1=obj.offsetTop+obj.offsetHeight/2;
var t2=obj2.offsetTop+obj2.offsetHeight/2;
var a=l2-l1;
var b=t1-t2;
return Math.sqrt(a*a+b*b);
},
collTest: function(obj,obj2){
var self=this;
var l1=obj.offsetLeft;
var r1=obj.offsetLeft+obj.offsetWidth;
var t1=obj.offsetTop;
var b1=obj.offsetTop+obj.offsetHeight;
var l2=obj2.offsetLeft;
var r2=obj2.offsetLeft+obj2.offsetWidth;
var t2=obj2.offsetTop;
var b2=obj2.offsetTop+obj2.offsetHeight;
if(r1<l2 || r2<l1 || t2>b1 || b2<t1){
return false;
}else{
return true;
}
},
//初始布局转换
pack: function(ele,click){
var self=this;
self.toDisable();
if(self.options.pos==false){
for (var i = 0; i < ele.length; i++) {
$(ele[i]).css("position", "absolute");
$(ele[i]).css("margin", "0");
self.init(ele[i]);
}
}else if(self.options.pos==true) {
var arr = [];
if (self.options.random || click) {
while (arr.length < ele.length) {
var n = self.rnd(0, ele.length);
if (!self.finInArr(arr, n)) {//没找到
arr.push(n);
}
}
}
if (self.options.random == false || click != true) {
var n = 0;
while (arr.length < ele.length) {
arr.push(n);
n++
}
}
//如果是第二次以后随机列表,那就重新排序后再随机,因为我智商不够使,不会排了
if (self.firstRandom == false) {
var sortarr = [];
var n = 0;
while (sortarr.length < ele.length) {
sortarr.push(n);
n++
}
for (var i = 0; i < ele.length; i++) {
$(ele[i]).attr("index", sortarr[i]);
$(ele[i]).css("left", self.aPos[sortarr[i]].left);
$(ele[i]).css("top", self.aPos[sortarr[i]].top);
}
}
//布局转化
self.aPos = [];
if (self.firstRandom == false) {
//不是第一次
for (var j = 0; j < ele.length; j++) {
self.aPos[j] = {
left: ele[$(ele).eq(j).attr("index")].offsetLeft,
top: ele[$(ele).eq(j).attr("index")].offsetTop
};
}
} else {
//第一次
for (var j = 0; j < ele.length; j++) {
self.aPos[j] = {left: ele[j].offsetLeft, top: ele[j].offsetTop};
}
}
//第二个循环布局转化
for (var i = 0; i < ele.length; i++) {
$(ele[i]).attr("index", arr[i]);
$(ele[i]).css("left", self.aPos[arr[i]].left);
$(ele[i]).css("top", self.aPos[arr[i]].top);
$(ele[i]).css("position", "absolute");
$(ele[i]).css("margin", "0");
self.init(ele[i]);
}
self.firstRandom = false;
}
},
//移动时候加class
moveAddClass: function(obj){
var self=this;
var oNear=self.findNearest(obj);
$(self.$element).removeClass(self.options.moveClass);
if(oNear && $(oNear).hasClass(self.options.moveClass)==false){
$(oNear).addClass(self.options.moveClass);
}
},
//给li排序
sort: function(){
var self=this;
var arr_li=[];
for (var s = 0; s < self.$element.length; s++) {
arr_li.push(self.$element[s]);
}
for ( var i = 0; i < arr_li.length; i++) {
for ( var j = i + 1; j < arr_li.length; j++) {
if(Number($(arr_li[i]).attr("index")) > Number($(arr_li[j]).attr("index"))){
var temp = arr_li[i];
arr_li[i] = arr_li[j];
arr_li[j] = temp;
}
}
}
return arr_li;
},
//点对点的方式换位
pointDrag: function(obj){
var self=this;
//先拍序
var oNear=self.findNearest(obj);
if (oNear) {
self.animation(obj,self.aPos[$(oNear).attr("index")]);
self.animation(oNear, self.aPos[$(obj).attr("index")]);
var tmp;
tmp = $(obj).attr("index");
$(obj).attr("index", $(oNear).attr("index"));
$(oNear).attr("index", tmp);
$(oNear).removeClass(self.options.moveClass);
} else if (self.options.changeWhen == "end") {
self.animation(obj, self.aPos[$(obj).attr("index")]);
}
},
//排序的方式换位
sortDrag: function(obj){
var self=this;
//先拍序
var arr_li=self.sort();
//换位置
var oNear=self.findNearest(obj);
if(oNear){
if(Number($(oNear).attr("index"))>Number($(obj).attr("index"))){
//前换后
var obj_tmp=Number($(obj).attr("index"));
$(obj).attr("index",Number($(oNear).attr("index"))+1);
for (var i = obj_tmp; i < Number($(oNear).attr("index"))+1; i++) {
self.animation(arr_li[i],self.aPos[i-1]);
self.animation(obj,self.aPos[$(oNear).attr("index")]);
$(arr_li[i]).removeClass(self.options.moveClass);
$(arr_li[i]).attr("index",Number($(arr_li[i]).attr("index"))-1);
}
}else if(Number($(obj).attr("index"))>Number($(oNear).attr("index"))){
//后换前
var obj_tmp=Number($(obj).attr("index"));
$(obj).attr("index",$(oNear).attr("index"));
for (var i = Number($(oNear).attr("index")); i < obj_tmp; i++) {
self.animation(arr_li[i],self.aPos[i+1]);
self.animation(obj,self.aPos[Number($(obj).attr("index"))]);
$(arr_li[i]).removeClass(self.options.moveClass);
$(arr_li[i]).attr("index",Number($(arr_li[i]).attr("index"))+1);
}
}
}else{
self.animation(obj,self.aPos[$(obj).attr("index")]);
}
},
//运动函数(后期再加参数)
animation: function(obj,json){
var self=this;
//考虑默认值
var options=self.options.animation_options; /*|| {};
options.duration=self.options.animation_options.duration || 800;
options.easing=options.easing.duration.easing || 'ease-out';*/
var self=this;
var count=Math.round(options.duration/30);
var start={};
var dis={};
for(var name in json){
start[name]=parseFloat(self.getStyle(obj,name));
if(isNaN(start[name])){
switch(name){
case 'left':
start[name]=obj.offsetLeft;
break;
case 'top':
start[name]=obj.offsetTop;
break;
case 'width':
start[name]=obj.offsetWidth;
break;
case 'height':
start[name]=obj.offsetHeight;
break;
case 'marginLeft':
start[name]=obj.offsetLeft;
break;
case 'borderWidth':
start[name]=0;
break;
//...
}
}
dis[name]=json[name]-start[name];
}
var n=0;
clearInterval(obj.timer);
obj.timer=setInterval(function(){
n++;
for(var name in json){
switch(options.easing){
case 'linear':
var a=n/count;
var cur=start[name]+dis[name]*a;
break;
case 'ease-in':
var a=n/count;
var cur=start[name]+dis[name]*a*a*a;
break;
case 'ease-out':
var a=1-n/count;
var cur=start[name]+dis[name]*(1-a*a*a);
break;
}
if(name=='opacity'){
obj.style.opacity=cur;
obj.style.filter='alpha(opacity:'+cur*100+')';
}else{
obj.style[name]=cur+'px';
}
}
if(n==count){
clearInterval(obj.timer);
options.complete && options.complete();
}
},30);
},
getStyle: function(obj,name){
return (obj.currentStyle || getComputedStyle(obj,false))[name];
},
//随机数
rnd: function(n,m){
return parseInt(Math.random()*(m-n)+n);
},
//在数组中找
finInArr: function(arr,n){
for(var i = 0 ; i < arr.length; i++){
if(arr[i] == n){//存在
return true;
}
}
return false;
}
}
})
})(jQuery,window,document);