现在的位置: 首页 > 综合 > 正文

google个性主页的拖拽效果的js的完整注释

2012年11月20日 ⁄ 综合 ⁄ 共 6571字 ⁄ 字号 评论关闭

w一般就是刷新用,解决一些浏览器的怪癖

Util.hide 
=
 
function
 () {

    Util.rootElement.style.display 
=
 
"
none
"
;

};

//
显示Google Ig中间那个table,解释同上

Util.show 
=
 
function
 () {

    Util.rootElement.style.display 
=
 
""
;

};

 

//
移动时显示的占位虚线框

ghostElement 
=
 
null
;

//
获取这个虚线框,通过dom动态生成

getGhostElement 
=
 
function
 () {

    
if
 (
!
ghostElement) {

        ghostElement 
=
 document.createElement(
"
DIV
"
);

        ghostElement.className 
=
 
"
modbox
"
;

        ghostElement.backgroundColor 
=
 
""
;

        ghostElement.style.border 
=
 
"
2px dashed #aaa
"
;

        ghostElement.innerHTML 
=
 
"
 
"
;

    }

    
return
 ghostElement;

};

 

//
初始化可以拖拽的Element的函数,与拖拽无关的我去掉了

function
 draggable(el) {

    
//
公用的开始拖拽的函数

    
this
._dragStart 
=
 start_Drag;

    
//
公用的正在拖拽的函数

    
this
._drag 
=
 when_Drag;

    
//
公用的拖拽结束的函数

    
this
._dragEnd 
=
 end_Drag;

    
//
这个函数主要用来进行拖拽结束后的dom处理

    
this
._afterDrag 
=
 after_Drag;

    
//
是否正在被拖动,一开始当然没有被拖动

    
this
.isDragging 
=
 
false
;

    
//
将这个Element的this指针注册在elm这个变量里面,方便在自己的上下文以外调用自己的函数等,很常用的方法

    
this
.elm 
=
 el;

    
//
触发拖拽的Element,在这里就是这个div上显示标题的那个div

    
this
.header 
=
 document.getElementById(el.id 
+
 
"
_h
"
);

    
//
对于有iframe的element拖拽不同,这里检测一下并记录

    
this
.hasIFrame 
=
 
this
.elm.getElementsByTagName(
"
IFRAME
"
).length 
>
 
0
;

    
//
如果找到了header就绑定drag相关的event

    
if
 (
this
.header) {

        
//
拖拽时的叉子鼠标指针

        
this
.header.style.cursor 
=
 
"
move
"
;

        
//
将函数绑定到header和element的this上,参照那个函数的说明

        Drag.init(
this
.header, 
this
.elm);

        
//
下面三个语句将写好的三个函数绑定给这个elemnt的三个函数钩子上,也就实现了element从draggable继承可拖拽的函数

        
this
.elm.onDragStart 
=
 Util.bindFunction(
this

"
_dragStart
"
);

        
this
.elm.onDrag 
=
 Util.bindFunction(
this

"
_drag
"
);

        
this
.elm.onDragEnd 
=
 Util.bindFunction(
this

"
_dragEnd
"
);

    }

};

 

//
下面就是draggable里面用到的那4个function

//
公用的开始拖拽的函数

function
 start_Drag() {

    
//
重置坐标,实现拖拽以后自己的位置马上会被填充的效果

    Util.re_calcOff(
this
);

    
//
记录原先的邻居节点,用来对比是否被移动到新的位置

    
this
.origNextSibling 
=
 
this
.elm.nextSibling;

    
//
获取移动的时候那个灰色的虚线框

    
var
 _ghostElement 
=
 getGhostElement();

    
//
获取正在移动的这个对象的高度

    
var
 offH 
=
 
this
.elm.offsetHeight;

    
if
 (Util.isGecko) {

        
//
修正gecko引擎的怪癖吧

        offH 
-=
 parseInt(_ghostElement.style.borderTopWidth) 
*
 
2
;

    }

    
//
获取正在移动的这个对象的宽度

    
var
 offW 
=
 
this
.elm.offsetWidth;

    
//
获取left和top的坐标

    
var
 offLeft 
=
 Util.getOffset(
this
.elm, 
true
);

    
var
 offTop 
=
 Util.getOffset(
this
.elm, 
false
);

    
//
防止闪烁,现隐藏

    Util.hide();

    
//
将自己的宽度记录在style属性里面

    
this
.elm.style.width 
=
 offW 
+
 
"
px
"
;

    
//
将那个灰框设定得与正在拖动的对象一样高,比较形象

    _ghostElement.style.height 
=
 offH 
+
 
"
px
"
;

    
//
把灰框放到这个对象原先的位置上

    
this
.elm.parentNode.insertBefore(_ghostElement, 
this
.elm.nextSibling);

    
//
由于要拖动必须将被拖动的对象从原先的盒子模型里面抽出来,所以设定position为absolute,这个可以参考一下css布局方面的知识

    
this
.elm.style.position 
=
 
"
absolute
"
;

    
//
设置zIndex,让它处在最前面一层,当然其实zIndex=100是让它很靠前,如果页面里有zIndex>100的,那……

    
this
.elm.style.zIndex 
=
 
100
;

    
//
由于position=absolute了,所以left和top实现绝对坐标定位,这就是先前计算坐标的作用,不让这个模型乱跑,要从开始拖动的地方开始移动

    
this
.elm.style.left 
=
 offLeft 
+
 
"
px
"
;

    
this
.elm.style.top 
=
 offTop 
+
 
"
px
"
;

    
//
坐标设定完毕,可以显示了,这样就不会闪烁了

    Util.show();

    
//
这里本来有个ig_d.G,没搞明白干什么用的,不过没有也可以用,谁知道麻烦告诉我一声,不好意思

    
//
还没有开始拖拽,这里做个记号

    
this
.isDragging 
=
 
false
;

    
return
 
false
;

};

//
在拖拽时的相应函数,由于绑定到鼠标的move这个event上,所以会传入鼠标的坐标clientX, clientY

function
 when_Drag(clientX, clientY) {

    
//
刚开始拖拽的时候将图层变透明,并标记为正在被拖拽

    
if
 (
!
this
.isDragging) {

        
this
.elm.style.filter 
=
 
"
alpha(opacity=70)
"
;

        
this
.elm.style.opacity 
=
 
0.7
;

        
this
.isDragging 
=
 
true
;

    }

    
//
被拖拽到的新的column(当然也可以是原来那个)

    
var
 found 
=
 
null
;

    
//
最大的距离,可能是防止溢出或者什么bug

    
var
 max_distance 
=
 
100000000
;

    
//
遍历所有的可拖拽的element,寻找离当前鼠标坐标最近的那个可拖拽元素,以便后面插入

    
for
 (
var
 i 
=
 
0
; i 
<
 Util.dragArray.length; i
++
) {

        
var
 ele 
=
 Util.dragArray[i];

        
//
利用勾股定理计算鼠标到遍历到的这个元素的距离

        
var
 distance 
=
 Math.sqrt(Math.pow(clientX 
-
 ele.elm.pagePosLeft, 
2

+
 Math.pow(clientY 
-
 ele.elm.pagePosTop, 
2
));

        
//
自己已经浮动了,所以不计算自己的

        
if
 (ele 
==
 
this
) {

            
continue
;

        }

        
//
如果计算失败继续循环

        
if
 (isNaN(distance)) {

            
continue
;

        }

        
//
如果更小,记录下这个距离,并将它作为found

        
if
 (distance 
<
 max_distance) {

            max_distance 
=
 distance;

            found 
=
 ele;

        }

    }

    
//
准备让灰框落脚

    
var
 _ghostElement 
=
 getGhostElement();

    
//
如果找到了另外的落脚点

    
if
 (found 
!=
 
null
 
&&
 _ghostElement.nextSibling 
!=
 found.elm) {

        
//
找到落脚点就先把灰框插进去,这就是我们看到的那个灰框停靠的特效,有点像吸附的感觉,哈哈

        found.elm.parentNode.insertBefore(_ghostElement, found.elm);

        
if
 (Util.isOpera) {

            
//
Opera的现实问题,要隐藏/显示后才能刷新出变化

            document.body.style.display 
=
 
"
none
"
;

            document.body.style.display 
=
 
""
;

        }

    }

};

//
拖拽完毕

function
 end_Drag() {

    
//
拖拽完毕后执行后面的钩子,执行after_Drag(),如果布局发生了变动了就记录到远程服务器,保存你拖拽后新的布局顺序

    
if
 (
this
._afterDrag()) {

        
//
remote call to save the change

    }

    
return
 
true
;

};

//
拖拽后的执行钩子

function
 after_Drag() {

    
var
 returnValue 
=
 
false
;

    
//
防止闪烁

    Util.hide();

    
//
把拖拽时的position=absolute和相关的那些style都消除

    
this
.elm.style.position 
=
 
""
;

    
this
.elm.style.width 
=
 
""
;

    
this
.elm.style.zIndex 
=
 
""
;

    
this
.elm.style.filter 
=
 
""
;

    
this
.elm.style.opacity 
=
 
""
;

    
//
获取灰框

    
var
 ele 
=
 getGhostElement();

    
//
如果现在的邻居不是原来的邻居了

    
if
 (ele.nextSibling 
!=
 
this
.origNextSibling) {

        
//
把被拖拽的这个节点插到灰框的前面

        ele.parentNode.insertBefore(
this
.elm, ele.nextSibling);

        
//
标明被拖拽了新的地方

        returnValue 
=
 
true
;

    }

    
//
移除灰框,这是这个灰框的生命周期应该就结束了

    ele.parentNode.removeChild(ele);

    
//
修改完毕,显示

    Util.show();

    
if
 (Util.isOpera) {

        
//
Opera的现实问题,要隐藏/显示后才能刷新出变化

        document.body.style.display 
=
 
"
none
"
;

        document.body.style.display 
=
 
""
;

    }

    
return
 returnValue;

};

//
可拖拽Element的原形,用来将event绑定到各个钩子,这部分市比较通用的,netvibes也是基本完全相同的实现

//
这部分推荐看dindin的这个,也会帮助理解,
http://www.jroller.com/page/dindin/?anchor=pro_javascript_12

var
 Drag 
=
 {

    
//
对这个element的引用,一次只能拖拽一个Element

    obj:
null

    
//
element是被拖拽的对象的引用,elementHeader就是鼠标可以拖拽的区域

    init:
function
 (elementHeader, element) {

        
//
将start绑定到onmousedown事件,按下鼠标触发start

        elementHeader.onmousedown 
=
 Drag.start;

        
//
将element存到header的obj里面,方便header拖拽的时候引用

        elementHeader.obj 
=
 element;

        
//
初始化绝对的坐标,因为不是position=absolute所以不会起什么作用,但是防止后面onDrag的时候parse出错了

        
if
 (isNaN(parseInt(element.style.left))) {

            element.style.left 
=
 
"
0px
"
;

        }

        
if
 (isNaN(parseInt(element.style.top))) {

            element.style.top 
=
 
"
0px
"
;

        }

        
//
挂上空Function,初始化这几个成员,在Drag.init被调用后才帮定到实际的函数,可以参照draggable里面的内容

        element.onDragStart 
=
 
new
 Function();

        element.onDragEnd 
=
 
new
 Function();

        element.onDrag 
=
 
new
 Function();

    },

    
//
开始拖拽的绑定,绑定到鼠标的移动的event上

    start:
function
 (event) {

        
var
 element 
=
 Drag.obj 
=
 
this
.obj;

        
//
解决不同浏览器的event模型不同的问题

        event 
=
 Drag.fixE(event);

        
//
看看

抱歉!评论已关闭.