/** * draggable - jQuery EasyUI * * Licensed under the GPL: * http://www.gnu.org/licenses/gpl.txt * * Copyright 2010 stworthy [ stworthy@gmail.com ] */ (function($){ function drag(e){ var opts = $.data(e.data.target, 'draggable').options; var dragData = e.data; var left = dragData.startLeft + e.pageX - dragData.startX; var top = dragData.startTop + e.pageY - dragData.startY; if (opts.deltaX != null && opts.deltaX != undefined){ left = e.pageX + opts.deltaX; } if (opts.deltaY != null && opts.deltaY != undefined){ top = e.pageY + opts.deltaY; } if (e.data.parnet != document.body) { if ($.boxModel == true) { left += $(e.data.parent).scrollLeft(); top += $(e.data.parent).scrollTop(); } } if (opts.axis == 'h') { dragData.left = left; } else if (opts.axis == 'v') { dragData.top = top; } else { dragData.left = left; dragData.top = top; } } function applyDrag(e){ var opts = $.data(e.data.target, 'draggable').options; var proxy = $.data(e.data.target, 'draggable').proxy; if (proxy){ proxy.css('cursor', opts.cursor); } else { proxy = $(e.data.target); $.data(e.data.target, 'draggable').handle.css('cursor', opts.cursor); } proxy.css({ left:e.data.left, top:e.data.top }); } function doDown(e){ var opts = $.data(e.data.target, 'draggable').options; var droppables = $('.droppable').filter(function(){ return e.data.target != this; }).filter(function(){ var accept = $.data(this, 'droppable').options.accept; if (accept){ return $(accept).filter(function(){ return this == e.data.target; }).length > 0; } else { return true; } }); $.data(e.data.target, 'draggable').droppables = droppables; var proxy = $.data(e.data.target, 'draggable').proxy; if (!proxy){ if (opts.proxy){ if (opts.proxy == 'clone'){ proxy = $(e.data.target).clone().insertAfter(e.data.target); } else { proxy = opts.proxy.call(e.data.target, e.data.target); } $.data(e.data.target, 'draggable').proxy = proxy; } else { proxy = $(e.data.target); } } proxy.css('position', 'absolute'); drag(e); applyDrag(e); opts.onStartDrag.call(e.data.target, e); return false; } function doMove(e){ drag(e); if ($.data(e.data.target, 'draggable').options.onDrag.call(e.data.target, e) != false){ applyDrag(e); } var source = e.data.target; $.data(e.data.target, 'draggable').droppables.each(function(){ var dropObj = $(this); var p2 = $(this).offset(); if (e.pageX > p2.left && e.pageX < p2.left + dropObj.outerWidth() && e.pageY > p2.top && e.pageY < p2.top + dropObj.outerHeight()){ if (!this.entered){ $(this).trigger('_dragenter', [source]); this.entered = true; } $(this).trigger('_dragover', [source]); } else { if (this.entered){ $(this).trigger('_dragleave', [source]); this.entered = false; } } }); return false; } function doUp(e){ drag(e); var proxy = $.data(e.data.target, 'draggable').proxy; var opts = $.data(e.data.target, 'draggable').options; if (opts.revert){ if (checkDrop() == true){ removeProxy(); $(e.data.target).css({ position:e.data.startPosition, left:e.data.startLeft, top:e.data.startTop }); } else { if (proxy){ proxy.animate({ left:e.data.startLeft, top:e.data.startTop }, function(){ removeProxy(); }); } else { $(e.data.target).animate({ left:e.data.startLeft, top:e.data.startTop }, function(){ $(e.data.target).css('position', e.data.startPosition); }); } } } else { $(e.data.target).css({ position:'absolute', left:e.data.left, top:e.data.top }); removeProxy(); checkDrop(); } opts.onStopDrag.call(e.data.target, e); function removeProxy(){ if (proxy){ proxy.remove(); } $.data(e.data.target, 'draggable').proxy = null; } function checkDrop(){ var dropped = false; $.data(e.data.target, 'draggable').droppables.each(function(){ var dropObj = $(this); var p2 = $(this).offset(); if (e.pageX > p2.left && e.pageX < p2.left + dropObj.outerWidth() && e.pageY > p2.top && e.pageY < p2.top + dropObj.outerHeight()){ if (opts.revert){ $(e.data.target).css({ position:e.data.startPosition, left:e.data.startLeft, top:e.data.startTop }); } $(this).trigger('_drop', [e.data.target]); dropped = true; this.entered = false; } }); return dropped; } $(document).unbind('.draggable'); return false; } //构造函数 $.fn.draggable = function(options){ //如果传参是一个字符串,就根据字符串去执行命令 if (typeof options == 'string'){ switch(options){ case 'options': //如果是'option',就取出来缓存到第一个元素上的draggable属性的对象的options属性对象 return $.data(this[0], 'draggable').options; case 'proxy': //如果是'proxy',就取出来缓存到第一个元素上的draggable属性的对象的proxy属性对象 return $.data(this[0], 'draggable').proxy; case 'enable': //如果是'enable',就针对每一个选中了的元素重新调用该方法,传参改为{disabled:false} return this.each(function(){ $(this).draggable({disabled:false}); }); case 'disable': //如果是'enable',就针对每一个选中了的元素重新调用该方法,传参改为{disabled:true} //外面的this是一个jquery对象(类数组) return this.each(function(){ //下面的this是dom元素对象 $(this).draggable({disabled:true}); }); } } //对于每一个选中了的dom元素执行操作 return this.each(function(){ // $(this).css('position','absolute'); var opts; //首先取出绑定到了dom元素draggable属性上的对象,注意这里是直接绑定到了dom元素上,而不是绑定jquery对象上,dom元素能保证两次拿到的是一个(由document维护),但是jquery对象会每次使用选择器的时候都会重建一个,所以js脚本中一般缓存数据也是绑定到dom元素上的 var state = $.data(this, 'draggable'); if (state) { //如果dom元素上缓存了'draggable'属性,那么就首先给操作句柄解绑所有的拖拽事件 state.handle.unbind('.draggable'); //使用现在的参数对象去覆盖以前的参数 opts = $.extend(state.options, options); } else { //如果dom元素上没有缓存'draggable'属性,说明是第一次开启拖拽功能,那么就直接用现在的参数去覆盖默认的参数 opts = $.extend({}, $.fn.draggable.defaults, options || {}); } if (opts.disabled == true) { //如果参数中有设置{disabled:true}的,那么就把光标恢复到默认,并直接返回 $(this).css('cursor', 'default'); return; } //拖拽对象的句柄,也是一个jquery对象 var handle = null; if (typeof opts.handle == 'undefined' || opts.handle == null){ //如果没有定义handle对象就使用dom元素自身 handle = $(this); } else { //如果是个字符串,就当成选择器字符串在这个dom元素中查找 handle = (typeof opts.handle == 'string' ? $(opts.handle, this) : handle); } //缓存参数对象模型和操作句柄对象 $.data(this, 'draggable', { options: opts, handle: handle }); //绑定鼠标按下和鼠标移动事件,都在命名空间draggable下,传递的参数target是一个dom元素对象 // bind mouse event using event namespace draggable handle.bind('mousedown.draggable', {target:this}, onMouseDown); handle.bind('mousemove.draggable', {target:this}, onMouseMove); function onMouseDown(e) { //这鼠标按下事件作为拖拽的触发事件 if (checkArea(e) == false) return; var position = $(e.data.target).position(); var data = { startPosition: $(e.data.target).css('position'), startLeft: position.left, startTop: position.top, left: position.left, top: position.top, startX: e.pageX, startY: e.pageY, target: e.data.target,//要被拖拽的dom元素对象 parent: $(e.data.target).parent()[0]//target的父元素dom对象 }; //分别绑定鼠标按下事件、鼠标移动事件、鼠标松开事件 $(document).bind('mousedown.draggable', data, doDown); $(document).bind('mousemove.draggable', data, doMove); $(document).bind('mouseup.draggable', data, doUp); } function onMouseMove(e) { //这个鼠标的移动事件作为基础事件,只负责处理光标显示,具体的拖动过程绑定的处理方法是在鼠标按下触发拖拽时临时绑定的 if (checkArea(e)){ $(this).css('cursor', opts.cursor); } else { $(this).css('cursor', 'default'); } } // check if the handle can be dragged function checkArea(e) { var offset = $(handle).offset(); var width = $(handle).outerWidth(); var height = $(handle).outerHeight(); var t = e.pageY - offset.top; var r = offset.left + width - e.pageX; var b = offset.top + height - e.pageY; var l = e.pageX - offset.left; return Math.min(t,r,b,l) > opts.edge; } }); }; $.fn.draggable.defaults = { proxy:null, // 'clone' or a function that will create the proxy object, // the function has the source parameter that indicate the source object dragged. revert:false, cursor:'move', deltaX:null, deltaY:null, handle: null, disabled: false, edge:0, axis:null, // v or h onStartDrag: function(e){}, onDrag: function(e){}, onStopDrag: function(e){} }; })(jQuery);
easyui之draggable控件分析,待完善
最新推荐文章于 2019-09-05 09:14:00 发布