작성자: Tin
출처: http://www.blogjava.net/iamtin/archive/2006/04/27/43668.html
코드: http://www.blogjava.net/Files/iamtin/ google_drag.rar
// 손쉬운 관리를 위해 Util의 네임스페이스를 사용하는 도구 클래스
var Util = new Object()
// http 헤더에서 UserAgent 및 브라우저 정보 가져오기
Util. navigator.userAgent;
// Mozila, Firefox 등 Gecko의 핵심 브라우저인지 여부
Util.isGecko = Util.getUserAgent.indexOf( " Gecko " ) != - 1 ; Opera인지
Util.isOpera = Util.getUserAgent.indexOf( " Opera " ) != - 1 ;
// 실제로 패딩 내 절대 좌표인 요소의 오프셋 정보를 가져옵니다. Body
// 후자의 매개변수가 true이면 offsetLeft, false이면 offsetTop
// 오프셋, 스타일, 클라이언트 및 기타 좌표에 대한 정의는 이 게시물을 참조하세요. dindin: http://www.jroller.com/page/dindin /?anchor=pro_javascript_12
Util.getOffset = function (el, isLeft) {
var retValue = 0
while (el ! = null) {
retValue = el[ " offset " (isLeft ? " Left " : " Top " )]
el = el.offsetParent;
}
return retValue; 요소에 바인딩되어 이 요소의 컨텍스트에서 실행됩니다. 이는 실제로 일종의 상속입니다.
Util.bindFunction = function (el, fucName) {
return function ( ) {
return el[fucName].apply(el, 인수);
}
}// 동일한 항목에 대해 드래그 가능한 모든 요소의 좌표를 다시 계산합니다. 열 아래의 드래그 가능한 레이어를 다시 계산합니다. 중첩을 방지하기 위해 새 좌표를 얻기 위한 높이
// 계산된 좌표는 pagePosLeft 및 pagePosTop 두 가지 속성에 기록됩니다.
Util.re_calcOff = function ( el) {
for ( var i = 0 ; i < ; Util.dragArray.length; i ) {
var ele = Util.dragArray[i];
ele.elm.pagePosLeft = Util.getOffset (ele.elm, true ); pagePosTop = Util.getOffset(ele.elm, false );
}
var nextSib = el.elm.nextSibling;
while (nextS ib ) {
nextSib.pagePosTop -= el.elm. offsetHeight;
nextSib.nextSibling;
}
};
// Google Ig 중간에 있는 테이블도 드래그 앤 드롭 방식입니다. 일반적으로 일부 브라우저 문제를 해결하기 위해 show와 함께 사용할 때 새로 고치는 데 사용됩니다.
Util.rootElement.style.display = " none "
}; /Google Ig 중간에 테이블을 표시하면 설명은 위와 같습니다.
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;
};
// 드래그 가능한 요소를 초기화하는 함수 드래그와 관련 없음
function draggable(el) {
// 일반적인 드래그 기능
this ._dragStart = start_Drag; 🎜> this ._dragEnd = when_Drag> // 일반적인 드래그 종료 기능
this ._dragEnd = end_Drag;
// 이 함수는 주로 드래그 후 DOM 처리에 사용됩니다.
this ._afterDrag = after_Drag
// 드래그되는지 여부는 물론 드래그되지 않았습니다. 시작 부분에
this .isDragged = false;
// 이 요소의 this 포인터를 elm 변수에 등록합니다. 자신의 컨텍스트 외부에서 자신의 함수를 호출하는 데 편리하며 매우 일반적인 방법입니다.
this .elm = el;
// 드래그를 실행하는 요소, 여기에 이 div의 제목을 표시하는 div가 있습니다.
this .header = document.getElementById(el.id " _h " )
// 드래그 iframe을 사용하는 요소 삭제는 다릅니다. 여기에서 확인하고 기록하세요.
this .hasIFrame = this .elm.getElementsByTagName( " IFRAME " ).length > 0
// 헤더가 발견되면 바인딩합니다. 드래그 관련 이벤트
if (this .header) {
// 드래그 시 포크 마우스 포인터
this .header.style.cursor = " move "
// 함수를 바인딩합니다. 헤더와 요소의 this, 해당 함수의 설명 참조
Drag.init(this .header, this .elm)
// 다음 세 가지 문은 작성된 세 가지 함수를 this의 세 가지 함수 후크에 바인딩합니다. elementnt는 요소가 draggable에서 드래그 가능한 기능을 상속한다는 것을 인식합니다 Util.bindFunction( this , " _dragStart " )
this .elm.onD rag = Util.bindFunction( this , " _drag " )
this .elm .onDragEnd = Util.bindFunction( this , " _dragEnd " )
}
};
// 다음은 draggable에 사용되는 4가지 함수입니다.
// 드래그를 시작하는 일반적인 함수
function start_Drag() {
// 좌표를 재설정하여 위치를 변경하는 효과 드래그 후 즉시 채워짐
Util.re_calcOff( this )
// 원래 이웃 노드를 기록하여 새 위치로 이동했는지 비교
this .origNextSibling = this .elm.nextSibling;
// 이동할 때 회색 점선 프레임 가져오기
var _ghostElement = getGhostElement()
// 움직이는 객체의 높이 가져오기
var offH = this .elm.offsetHeight; (Util.isGecko) {
// 게코 엔진의 단점 수정
offH -=parseInt(_ghostElement.style.borderTopWidth) * 2
}
// 이동 너비를 가져옵니다. object
var offW = this .elm.offsetWidth;
// 왼쪽과 위쪽의 좌표를 가져옵니다.
var offLeft = Util.getOffset(this .elm, true)
var offTop = Util. getOffset(this .elm, false);
// 깜박임 방지, 이제 숨김
Util.hide()
// 스타일 속성 " px "에 너비를 기록합니다. 이 객체의 원래 위치에 있는 회색 상자
this .elm.parentNode.insertBefore(_ghostElement, this .elm.nextSibling)
// 드래그하고 싶기 때문에 드래그한 객체는 다음에서 추출됩니다. 원래 상자 모델이므로 위치를 절대값으로 설정하세요.
이 .elm.style.position = "absolute"
// zIndex를 그렇게 설정하세요. 물론, zIndex=100은 페이지에 zIndex>100이 있다는 의미입니다.
this .elm.style.zIndex = 100 ;
// 위치=절대이므로 왼쪽과 위쪽이 절대 좌표 위치를 얻습니다. 이는 이전에 계산된 좌표의 함수입니다. from 드래그를 시작한 곳에서 이동 시작
this .elm.style.left = offLeft " px " ;
this .elm.style.top = offTop " px "
// 좌표가 설정되었습니다. can 표시되므로 깜박이지 않습니다.
Util.show();
// ig_d.G가 있는데 무슨 용도인지는 모르겠습니다. 아시는 분 계시나요? 죄송합니다
// 드래그가 아직 시작되지 않았습니다.
this .isDraging = false
return false
// 드래그 중 해당 함수, 마우스 이동 이벤트에 바인딩되므로 마우스 좌표 clientX, clientY가 전달됩니다.
function when_Drag(clientX, clientY) {
// 레이어를 투명하게 만듭니다. 먼저 드래그를 시작합니다.
if ( ! this .isDragged) {
this .elm.style.filter = " alpha(opacity=70) "
this .elm.style. opacity = 0.7 ;
this .isDragged = true ;
}
// 드래그되는 새 열(물론 원래 열일 수도 있음)
varfound = null ; 오버플로 또는 일부 버그를 방지하기 위한 최대 거리
var max_distance = 100000000;
// 드래그 가능한 모든 요소를 탐색하고 나중에 삽입하기 위해 현재 마우스 좌표에 가장 가까운 드래그 가능한 요소를 찾습니다.
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 (distance < max_distance) {
max_distance = 거리; 발견 = ele
}
} // 발판을 찾아 회색 프레임을 먼저 삽입합니다. 이것이 우리가 보는 회색 프레임의 특수 효과입니다.
~ > ~ 드래그 후 , 다음 Hook을 실행하고 after_Drag()를 실행합니다. 레이아웃이 변경되면 원격 서버에 기록되고 드래그한 후 새 레이아웃 순서가 저장됩니다. // 변경 사항을 저장하기 위한 원격 호출
}
return true ;
}
//드래그 후 실행 후크
function after_Drag() {
var returnValue = false ; > // 깜박임 방지
Util.hide();
// 드래그 시 position=absolute 및 관련 스타일 제거
this .elm.style.position = ""
this .elm.style .width = "" ;
this .elm.style.zIndex = "" ;
this .elm.style.filter = "" ;
this .elm.style. > // 회색 상자 가져오기
var ele = getGhostElement();
// 현재 이웃이 원래 이웃이 아닌 경우
if (ele.nextSibling != this .origNextSibling ) {
// 회색 상자 앞에 드래그한 노드를 삽입합니다.
ele.parentNode.insertBefore( this .elm, ele.nextSibling)
// 새 노드가 드래그되었음을 나타냅니다. Place
returnValue = true }
// 이 회색 상자의 수명 주기를 종료해야 하는 회색 상자를 제거합니다.
ele.parentNode.removeChild(ele)
//수정이 완료된 후 Util을 표시합니다. .show ();
If (Util.isopera) {
// Opera의 현실적인 문제는 변경 사항을 새로 고치려면 숨기거나 표시해야 합니다.
documen.body.style.display = " none " ; 🎜> document.body.style.display = "" ;
}
return Value
};
// 각 후크에 이벤트를 바인딩하는 데 사용되는 드래그 가능한 요소입니다. 이 부분은 시장에서 비교적 일반적이며 netvibes도 기본적으로 동일한 방식으로 구현합니다.
// 이 내용을 읽어 보는 것이 좋습니다. http://www.jroller.com/page/dindin/?anchor=pro_javascript_12
var Drag = {
// 이 요소에 대한 참조는 하나만 드래그할 수 있습니다. 한 번에 요소
obj: null ,
// 요소는 드래그되는 개체에 대한 참조, elementHeader는 마우스로 드래그할 수 있는 영역
init: function (elementHeader, element) {
// 시작을 onmousedown 이벤트에 바인딩하고 마우스를 누르면 시작이 시작됩니다.
elementHeader.onmousedown = Drag.start
//헤더가 실행될 때 참조할 수 있도록 요소를 헤더의 obj에 저장합니다. 드래그 앤 드롭
elementHeader.obj = element;
// 절대 좌표를 초기화합니다. position=absolute가 아니므로 아무런 역할도 하지 않지만 나중에 onDrag 중에 구문 분석 오류를 방지합니다. ~ " ;
}
이 멤버를 초기화하면 실제 기능은 Drag.init 호출 후 결정되며 드래그 가능 항목에서 내용을 참조할 수 있습니다. ~ . > element.onDragEnd = new Function()
element.onDrag = new Function ();
},
// 마우스 이동 이벤트에 대한 드래그 및 바인딩 시작
start: function (event) {
var element = Drag.obj = this .obj> / / 다양한 브라우저에서 다양한 이벤트 모델 문제 해결
event = Drag.fixE(event); ~ / 이 함수에 대한 설명을 참조하여 후크를 연결하여 드래그를 시작하세요.
element.onDragStart( );
// 마우스 좌표를 기록합니다.
event .clientY; // 드래그한 요소에 전역 이벤트 바인딩
document.onmouseup =
document.onmousemove; 드래그.드래그
반환 false
;,
// 드래그되는 요소의 함수
drag: function (event) {
// 브라우저마다 다른 이벤트 모델의 문제 해결
event = Drag.fixE(event);
// 왼쪽 버튼 클릭 여부 확인
if (event.which == 0) {
// 왼쪽 버튼 외에는 동작하지 않음
Return drag.end ();
}
// 드래그 중인 요소
var element = Drag.obj;
// 마우스 좌표
var _clientX = event.clientY
var _clientY = event.clientX; 🎜> // 마우스가 움직이지 않으면 아무 작업도 수행하지 않음 ~
var _lastX =parseInt(element.style.top);
var _lastY =parseInt(element.style.left)
// 새 좌표
var newX , newY
// 새 좌표 계산: 원래 좌표 간의 마우스 움직임 차이
newX = _lastY _clientY - element.lastMouseX // 요소의 표시 좌표 수정
element; .style.left = newX " px " ;
element.style.top = newY " px " ;
// 다음 이동을 위한 요소의 현재 좌표를 기록합니다.
element.lastMouseX = _clientY ;
element.lastMouseY = _clientX;
// Drag를 연결하려면 이 함수에 대한 설명을 참조하세요.
element.onDrag(newX, newY)
return false ;,
// Element가 해제되는 함수, 드래그 중지
end: function (event) {
// 브라우저마다 다른 이벤트 모델 문제 해결
event = Drag.fixE( event );
// 전역 이벤트 바인딩 해제
document.onmousemove = null ;
document.onmouseup = null
// onDragEnd 후크를 먼저 기록합니다. Obj를 쉽게 제거할 수 있습니다.
var _onDragEndFuc = Drag.obj.onDragEnd();
// 드래그 후 obj가 지워집니다.
Drag.obj = null
return _onDrag EndFuc; 다양한 브라우저의 다양한 이벤트 모델
fixE: function (ig_) {
if ( typeof ig_ == " unjust " ) {
ig_ = window.event }
if ( typeof ig_.layerX = = " 정의되지 않음 " ) {
ig_.layerX = ig_.offsetX;
}
if ( typeof ig_.layerY == " 정의되지 않음 " ) {
ig_.layerY = ig_.offsetY; > }
if ( typeof ig_.which == " 정의되지 않음 " ) {
ig_.which = ig_.button
} > 꺼짐 꺼짐
};
//다음은 초기화 함수입니다. 위의 내용이 어떻게 호출되는지 확인하세요.
var _IG_initDrag = function(el) {
// 열 컨테이너, Google에서 , netvibes에서 사용하는 테이블 레이아웃의 tbody입니다. .rows[ 0 ]; // 열, Google에는 3개의 열이 있으며 실제로 더 있을 수 있습니다.
Util.column = Util._rows .cells;
// 드래그 가능한 객체에 액세스하는 데 사용됩니다.
Util.dragArray = new Array()
var counter = 0
for (var i = 0; i < Util.column. length; i ) {
// 모든 열 검색
var ele = Util.column[i]
for ( var j = 0 ; j < ele.childNodes.length; j ) {
// 각 열의 모든 요소를 검색
var ele1 = ele.childNodes[j]
// div인 경우 드래그 가능한 객체로 초기화
if (ele1.tagName == " DIV " ) {
Util.dragArray[ counter] = new draggable(ele1);
; id "t_1"입니다.
//onload로 마운트되었으며, 로딩 후 실행됩니다. 그러나 실제로 Google은 onload를 사용하지 않습니다.
//대신 페이지 하단에 작성하는데, 이는 다르지만 동일한 효과를 가지고 있습니다. 페이지에 직접 작성하는 것이 특이한 것일 수도 있고, 호환성을 고려한 것일 수도 있습니다. // window.onload = _IG_initDrag(_table);
// 사실 이 코드를 이해하는 것은 자바스크립트를 배우는 데 많은 도움이 되기를 바랍니다.