jquery应用-实现博客个性主页布局拖拽功能

接上一篇:js应用-实现博客个性主页布局拖拽功能 已改造成JQuery插件形式,并新增了一些效果,由于jquery强大的DOM选择器和一些封装的效果,使得代码更加清晰和精简。

引用上一篇:Jquery的Interface elements for jQuery里面的拖拽布局存在一些bug,效率也比较低,GoogleUI google_drag.js有些乱,不是很容易理解,Discuz!NT Space代码满天飞,所以自己参考GoogleUI的思想,简化和优化了一些操作代码,实现了博客系统基本的拖拽布局的效果,暂时未考虑其他浏览器的兼容性问题。下一步准备改造成Jquery的插件形式,并增加一些渐隐渐现和动画效果,并逐步实现一些ajax的添加删除操作,嵌入基于JQuery的音乐播放器,图片浏览器,文本编辑器


预览体验:
 
html代码:
下面的可拖拽模块的mid为其在数据库中的id号;
<div style="display:inline" mid="|"><div></div></div>
每td列最后都有一个,并隐藏起来,用来可以推拽元素到此隐藏元素的前面,或者某td列本来没有元素,
也可以拖拽到此列上面:

  1 <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
  2 < html  xmlns ="http://www.w3.org/1999/xhtml" >
  3 < head >
  4 < meta  http-equiv ="Content-Type"  content ="text/html; charset=gb2312"   />
  5 < title > 博客推拽布局示例 </ title >
  6 < link  href ="main2.css"  rel ="stylesheet"  type ="text/css"   />
  7 < script  src ="jquery.js"  language ="javascript" ></ script >
  8 < script  src ="dimensions.js"  language ="javascript" ></ script >
  9 < script  src ="drag2.js"  language ="javascript" ></ script >
 10 < script >
 11    $(document).ready(
 12    function () {
 13        //初始化推拽布局
 14        $("#main").DragLayout({
 15            onEnd: function(modules) {        
 16            var order = "";
 17            modules.each(function(){
 18                order += $(this).attr("mid"+ " ";
 19            }
);
 20            
 21            $("#order").text(order);
 22            //或者进行ajax提交
 23            }
    
 24        }
);
 25        //展开收缩效果
 26        $(".control .control1").click(function(){
 27            var control = $(this);
 28            control.parent().next().slideToggle("slow"function(){
 29                  control.text()=="+expend"?control.text("-expend"):control.text("+expend");
 30            }
);
 31        }
);
 32        //删除模块
 33        $(".control .control2").click(function(){
 34            var control = $(this).parent().parent();
 35            control.fadeTo(3000.5);
 36            setTimeout( function() {control.remove()}400);
 37        }
);
 38        //添加模块
 39        $("#add").click(function(){
 40            var modules = $("#main .module")
 41            var lastModule = $(modules[modules.length-1]);
 42            var newModule = lastModule.clone();
 43            newModule.children(".title").text("new module");
 44            newModule.children(".content").text("new content");
 45            newModule.attr("mid""newid");
 46            newModule.insertAfter(lastModule);
 47            newModule.fadeIn(3000.5);
 48            
 49        }
);
 50    }

 51    );
 52        
 53
 54
</ script >
 55 </ head >
 56
 57 < body >
 58 < div  id ="modules" >  
 59      < table  id ="main"  cellspacing ="10"  border ="0"  width ="98%"  align ="center" >  
 60          < tr >  
 61              < td  id ="c1" >
 62                  < div  class ="module"  mid ="1" >
 63                      < div  class ="title" > title1 </ div >
 64                      < div  class ="control" >< span  class ="control1" > +expend </ span > &nbsp; < span  class ="control2" > ×delete </ span ></ div >
 65                      < div  class ="content" > content1 </ div >
 66                  </ div >                 
 67                  < div  class ="module"  mid ="4" >
 68                      < div  class ="title" > title4 </ div >
 69                      < div  class ="control" >< span  class ="control1" > +expend </ span > &nbsp; < span  class ="control2" > ×delete </ span ></ div >
 70                      < div  class ="content" > content4 </ div >
 71                  </ div >
 72                  < div  style ="display:inline"  mid ="|" >< div ></ div ></ div >
 73              </ td >  
 74              < td  id ="c2"   >  
 75                   < div  class ="module"  mid ="2" >
 76                      < div  class ="title" > title2 </ div >
 77                      < div  class ="control" >< span  class ="control1" > +expend </ span > &nbsp; < span  class ="control2" > ×delete </ span ></ div >
 78                      < div  class ="content" > content2 </ div >
 79                  </ div >
 80                  < div  style ="display:inline"  mid ="|" >< div ></ div ></ div >
 81              </ td >  
 82              < td  id ="c3"   >  
 83                   < div  class ="module"  mid ="3" >
 84                      < div  class ="title" > title3 </ div >
 85                      < div  class ="control" >< span  class ="control1" > +expend </ span > &nbsp; < span  class ="control2" > ×delete </ span ></ div >
 86                      < div  class ="content" > content3 </ div >
 87                  </ div >
 88                  < div  style ="display:inline"  mid ="|" >< div ></ div ></ div >
 89              </ td >  
 90          </ tr >  
 91      </ table >
 92      < div  id ="ghost" ></ div >  
 93     
 94 </ div >  
 95 < div  id ="other" >
 96 < input  type ="button"  id ="add"  value ="+ add a module"   />< br />
 97 new order is: < div  id ="order"   />
 98 </ div >
 99
100
101 </ body >
102 </ html >

js代码:
主要是两个对象,dragLayout对象(table元素) 包含 dragModule对象(可拖拽的元素)
  1  ( function ($) {
  2 
  3  $.fn.DragLayout  =   function (obj) {
  4       // 得到所有可拖拽的模块
  5       this .getModules  =   function () {
  6           return   this .find( " div[@mid] " );
  7      };
  8       // 得到所有可推拽的模块的位置offset,在后面判断最近元素时候起作用
  9       this .getModulesPostion  =   function () {
 10           var  i  =   0 ;    
 11           var  modulesPostion  =  {};
 12           this .modules.each( function () {        
 13              modulesPostion[i]  =  $( this ).offset();
 14              i ++ ;
 15                      
 16          });
 17          
 18           return  modulesPostion;        
 19      };
 20       // 初始化模块和模块位置
 21       this .init  =   function () {
 22           this .modules  =   this .getModules();
 23           this .modulesPostion  =   this .getModulesPostion();
 24      };
 25       // 回调函数,完成事件
 26       this .onEnd  =  obj.onEnd;
 27       // 初始化
 28       this .init();
 29       var  _self  =   this ;
 30       // 循环创建dragModule对象            
 31       return   this .modules.each( function () {        
 32           new  dragModule( this , _self);                
 33      });
 34 
 35  }
 36 
 37 
 38  var  dragModule  =   function (ele, parent) {
 39       // 对应的div拖拽元素
 40       this .ele  =  $(ele);
 41       // 父对象,即dragLayout对象
 42       this .parent  =  parent;
 43       // 标题栏,用于鼠标拖拽
 44       this .title  =  $( this .ele.children()[ 0 ]);
 45 
 46       // 记录原先的邻居节点,用来对比是否被移动到新的位置 
 47       this .origNextSibling  =   this .ele.next();
 48       this .init.apply( this );
 49      
 50  };
 51 
 52  dragModule.prototype  =  {
 53      
 54      init :  function () {  with ( this ) {
 55           var  _self  =   this ;
 56           //  获取移动的时候那个灰色的虚线框 
 57          ghostLayer  =  $( " #ghost " );
 58           // 鼠标按下时推拽开始        
 59          title.mousedown( function  (event) {
 60                _self.dragStart(event);
 61          });
 62          
 63          title.hover( function  () {
 64                title.fadeIn( " slow " );
 65          },
 66               function  () {
 67                  
 68              }
 69          );
 70      
 71          title.css( " cursor " , " move " );
 72 
 73      }
 74      },
 75      
 76       // 开始拖拽设定一些位置信息
 77      dragStart:  function  (evt) {  with ( this ) {
 78           var  _self  =   this ;
 79          evt   =  evt ? evt:window.event;
 80 
 81           // 鼠标相对于浏览器的位置减去元素的位置
 82           // 得出鼠标相对于元素的相对位置,便于拖拽时计算元素的新位置
 83          x  =  evt.clientX  -  ele.offset().left;
 84          y  =  evt.clientY  -  ele.offset().top;
 85          
 86           // 绝对位置,top和left就起作用了,就可以推拽了
 87          ele.css( " position " , " absolute " ).css( " zIndex " , " 100 " ).css( " top " ,ele.offset().top).css( " left " ,ele.offset().left);
 88          
 89           // 将那个灰框设定得与正在拖动的对象一样高
 90          ghostLayer.css( " position " , " relative " ).css( " display " , " block " ).css( " height " ,ele.innerHeight()).css( " width " ,ele.innerWidth());
 91          
 92           // 把灰框放到这个对象原先的位置上 
 93          ghostLayer.insertBefore(ele.next());
 94 
 95           // 鼠标按下再移动的事件,鼠标移动,元素也跟着走
 96          $(document).mousemove( function  (event) { _self.drag(event);});
 97           // 释放鼠标的事件
 98          $(document).mouseup( function  (event) { _self.dragEnd(event);});
 99      }
100      },
101      
102       // 拖拽时实现元素跟鼠标走
103      drag:  function  (evt) {  with ( this ) {
104 
105           var  _self  =   this ;
106          evt   =  evt ? evt:window.event;
107           // 计算元素的新的位置
108          ele.css( " filter " , " alpha(opacity=70) " ).css( " opacity " , " 0.7 " ).css( " left " ,evt.clientX  -  x).css( " top " ,evt.clientY  -  y);
109      
110           // 被拖拽到的新的元素(当然也可以是原来那个) 
111           var  found  =   null
112           // 最大的距离
113            var  max_distance  =   10000 ;
114           //  遍历所有的可拖拽的element,寻找离当前鼠标坐标最近的那个可拖拽元素,以便前面插入
115           var  distance  =   null ;
116          
117           var  i  =   0 ;
118          
119          parent.modules.each( function () {
120               // 利用勾股定理计算鼠标到遍历到的这个元素的距离 
121              distance  =  Math.sqrt(Math.pow(evt.clientX  -  parent.modulesPostion[i].left, 2 +  Math.pow(evt.clientY  -  parent.modulesPostion[i].top,  2 ));            
122              i ++ ;
123               // 如果更小,记录下这个距离,并将它作为found 
124               if  (distance  <  max_distance) {
125                  max_distance  =  distance;
126                  found  =  $( this );
127              }
128          });
129 
130          
131           // 找到落脚点就先把灰框插进去,我们看到的那个灰框停靠的特效
132           if   (found  !=   null   &&  ghostLayer.next()  !=  found) {
133              
134              ghostLayer.insertBefore(found);            
135          }        
136      }
137      },
138      
139       // 鼠标释放时推拽完成
140      dragEnd:  function  (evt) {  with ( this ) {
141           var  _self  =   this ;
142          evt   =  evt ? evt:window.event;
143           // 卸载事件
144          $(document).unbind( " mousemove " );
145          $(document).unbind( " mouseup " );
146          
147          
148           // 把拖拽时的position=absolute和相关的那些style都消除 
149          
150          ele.css( " position " , " relative " ).css( " filter " , " alpha(opacity=100) " ).css( " opacity " , " 1 " ).css( " zIndex " , "" ).css( " left " , "" ).css( " top " , "" );
151 
152           // 将灰框隐藏起来
153          ghostLayer.css( " display " " none " );        
154          
155          
156           // 如果现在的邻居不是原来的邻居了后者邻居就是它本身 
157           if  (ghostLayer.next()  !=  origNextSibling  &&  ghostLayer.next()  !=   this .ele) {
158               // 把被拖拽的这个节点插到灰框的前面 
159              ele.insertBefore(ghostLayer.next());
160 
161               // 从新初始化可推拽元素对象,可以设定它们的新位置,为下面的拖拽操作做准备
162              parent.init();
163 
164               // 回调函数,拖拽完成可对dragArray进行处理
165              parent.onEnd.call( this , parent.modules);
166              
167          }
168          
169          ghostLayer.insertAfter(parent);            
170      }
171      }
172  }
173 
174 
175 
176  })(jQuery);

css代码:
Code

你可能感兴趣的:(jquery)