JS 학습 20 (고급 기술)

고급 함수
함 수 는 본질 적 으로 매우 간단 하고 과정 적 이지 만 JS 의 타고 난 동적 특성 때문에 사용 방식 이 매우 복잡 할 수 있다.
안전 한 유형 검사
JS 에 서 는 유형 검 측 이 있 지만 브 라 우 저 구현 등 으로 신뢰 할 수 없습니다.예 를 들 어 type: of 는 Safari 에서 정규 표현 식 에 대해 서도 function 을 되 돌려 줍 니 다.instanceof 는 여러 개의 전역 작용 역 이 존재 할 때 도 같은 종류의 서로 다른 작용 역 에서 함 수 를 구성 하 는 실례 를 서로 다른 실례 로 식별한다.
var isArray = value instanceof Array;

이 표현 식 이 true 로 돌아 가 려 면 value 는 배열 이 어야 하고 Array 구조 함수 와 같은 전역 역할 영역 에 있어 야 합 니 다. value 가 다른 전역 역할 영역 에서 정의 하 는 배열 이 라면 이 표현 식 은 false 로 돌아 갑 니 다.어떤 대상 이 원생 인지 개발 자가 정의 한 대상 인지 검사 할 때 도 문제 가 있 을 수 있다.브 라 우 저가 원래 JSON 을 지원 하기 시 작 했 기 때문에 일부 개발 자 들 은 제3자 라 이브 러 리 로 JSON 을 실현 하고 있 습 니 다. 이 라 이브 러 리 에는 전체적인 JSON 대상 이 있 을 것 입 니 다. 이렇게 해서 JSON 대상 이 원래 의 것 인지 아 닌 지 확인 하려 면 번 거 로 울 것 입 니 다.이 문 제 를 해결 하 는 방법 은 Object 의 toString 방법 을 사용 하 는 것 입 니 다. 이 방법 은 [object Native Constructor Name] 형식의 문자열 을 되 돌려 줍 니 다.
function isArray(value){
    return Object.prototype.toString.call(value) == "[object Array]";
}
function isFunction(value){
    return Object.prototype.toString.call(value) == "[object Function]";
}
function isRegExp(value){
    return Object.prototype.toString.call(value) == "[object RegExp]";
}

그러나 주의해 야 할 것 은 IE 에서 COM 형식 으로 이 루어 진 모든 함수 에 대해 isFunction () 은 false 로 되 돌아 갑 니 다.JSON 이 원생 인지 에 대한 질문 은 다음 과 같다.
var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON) == "[object JSON]";

역할 영역 안전 구조 함수
전에 우리 가 말 한 구조 함 수 는 이렇게 사용 되 었 다.
function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
}
var person = new Person("Nicholas", 29, "Software Engineer");

여기 서 new 연산 자 를 사 용 했 기 때문에 this 는 새로 만 든 Person 대상 에 연결 되 어 있 습 니 다. new 연산 자 를 사용 하지 않 고 Person () 을 직접 호출 하면 this 는 window 에 연결 되 어 있 습 니 다. 이것 은 분명 안 됩 니 다.
function Person(name, age, job){
    if (this instanceof Person){
        this.name = name;
        this.age = age;
        this.job = job;
    } else {
        return new Person(name, age, job);
    }
}
var person1 = Person("Nicholas", 29, "Software Engineer");
alert(window.name);      //""
alert(person1.name);     //"Nicholas"
var person2 = new Person("Shelby", 34, "Ergonomist");
alert(person2.name);     //"Shelby"

그러나 이러한 역할 영역 안전 한 구조 함 수 를 사용 한 후에 구조 함 수 를 바탕 으로 훔 친 계승 을 사용 하면 문제 가 생 길 수 있다.
function Polygon(sides){
    if (this instanceof Polygon) {
        this.sides = sides;
        this.getArea = function(){
            return 0;
        };
    } else {
        return new Polygon(sides);
    }
}
function Rectangle(width, height){
    //     ,    this Rectangle   ,     side  
    Polygon.call(this, 2);
    this.width = width;
    this.height = height;
    this.getArea = function(){
        return this.width * this.height;
    };
}
var rect = new Rectangle(5, 10);
alert(rect.sides);        //undefined

해결 방법 은 Rectangle 도 Polygon 의 인 스 턴 스 였 으 면 좋 겠 어 요.
Rectangle.prototype = new Polygon();
var rect = new Rectangle(5, 10);
alert(rect.sides);        //2

불활성 불 러 오기 함수
브 라 우 저의 차이 로 인해 브 라 우 저의 능력 을 판단 하 는 함수 가 대량으로 사용 되 어야 합 니 다. 그러나 이러한 판단 은 일반적으로 매번 실행 할 필요 가 없습니다. 한 번 실행 한 후에 브 라 우 저의 능력 이 확정 되 고 앞 으로 는 판단 하지 않 아 도 됩 니 다.예 를 들 면:
function createXHR(){
    if (typeof XMLHttpRequest != "undefined"){
        return new XMLHttpRequest();
    } else if (typeof ActiveXObject != "undefined"){
        if (typeof arguments.callee.activeXString != "string"){
            var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                    "MSXML2.XMLHttp"],
                i,len;
            for (i=0,len=versions.length; i < len; i++){
                try {
                    new ActiveXObject(versions[i]);
                    arguments.callee.activeXString = versions[i];
                    break;
                } catch (ex){
                }
            }
        }
        return new ActiveXObject(arguments.callee.activeXString);
    } else {
        throw new Error("No XHR object available.");
    }
}

XHR 대상 을 만 드 는 함수 입 니 다. 대상 을 만 들 때마다 브 라 우 저 능력 을 판단 하 는 것 은 불필요 합 니 다.타성 불 러 오 는 방법 은 두 가지 가 있 습 니 다. 첫 번 째 는 함수 가 처음 호출 되 었 을 때 상황 에 따라 서로 다른 새로운 함수 로 이 함 수 를 덮어 쓰 는 것 입 니 다. 나중에 호출 하면 더 이상 판단 하지 않 고 이 실행 하 는 작업 을 직접 수행 하 는 것 입 니 다.
function createXHR(){
    if (typeof XMLHttpRequest != "undefined"){
        createXHR = function(){
            return new XMLHttpRequest();
        };
    } else if (typeof ActiveXObject != "undefined"){
        createXHR = function(){
            if (typeof arguments.callee.activeXString != "string"){
                var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                        "MSXML2.XMLHttp"],
                        i, len;
                for (i=0,len=versions.length; i < len; i++){
                    try {
                        new ActiveXObject(versions[i]);
                        arguments.callee.activeXString = versions[i];
                        break;
                    } catch (ex){
                        //skip
                    }
                }
            }
            return new ActiveXObject(arguments.callee.activeXString);
        };
    } else {
        createXHR = function(){
            throw new Error("No XHR object available.");
        };
    }
    return createXHR();
}
createXHR();
alert(createXHR);

두 번 째 사고방식 은 똑 같 습 니 다. 함 수 를 설명 할 때 새 함 수 를 지정 할 뿐 첫 번 째 호출 할 때 지정 하지 않 습 니 다.두 가지 방법 은 사실 본질 적 으로 같은 것 이 니, 네가 어떻게 쓰 려 고 하 는 지 봐 라.
var createXHR = (function(){
    if (typeof XMLHttpRequest != "undefined"){
        return function(){
            return new XMLHttpRequest();
        };
    } else if (typeof ActiveXObject != "undefined"){
        return function(){
            if (typeof arguments.callee.activeXString != "string"){
                var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                    "MSXML2.XMLHttp"],
                    i, len;
                for (i=0,len=versions.length; i < len; i++){
                    try {
                        new ActiveXObject(versions[i]);
                        arguments.callee.activeXString = versions[i];
                        break;
                    } catch (ex){
                        //skip
                    }
                }
            }
            return new ActiveXObject(arguments.callee.activeXString);
        };
    } else {
        return function(){
            throw new Error("No XHR object available.");
        };
    }
})();
alert(createXHR);

함수 바 인 딩
함수 바 인 딩 이 해결 하 는 문 제 는 함수 호출 시 함수 의 this 대상 이 우리 가 원 하지 않 는 대상 으로 바 뀌 는 문제 입 니 다.이런 상황 은 이벤트 처리 함 수 를 지정 할 때 자주 나타난다.예 를 들 어:
var handler = {
    message: "Event handled",
    handleClick: function(event){
        alert(this);
        alert(this.message);
    }
};
var btn = document.getElementById("myButton");
EventUtil.addHandler(btn, "click", handler.handleClick);  //[object HTMLButtonElement] undefined
handler.handleClick();  // [object Object] Event handled

이 곳 의 this 는 단추 요소 로 바 뀌 었 습 니 다.해결 방법 은 진정한 함 수 를 하나의 패키지 에 끼 워 서 함수 의 환경 을 보존 하 는 것 이다.
var handler = {
    message: "Event handled",
    handleClick: function(event){
        alert(this); // [object Object] 
        alert(this.message); // Event handled
    } };
var btn = document.getElementById("myButton");
EventUtil.addHandler(btn, "click", function(event){
    alert(this);  //[object HTMLButtonElement]
    handler.handleClick(event);
});

보 실 수 있 습 니 다. 닫 힌 this 는 button 으로 바 뀌 었 습 니 다. 이 닫 힌 보호 로 인해 우리 의 처리 함수 환경 이 저장 되 었 습 니 다.매번 수 동 으로 패 키 지 를 만 들 지 않 기 위해 서 도구 함수 bid 를 만 들 수 있 습 니 다.
function bind(fn, context){
    alert(arguments[0]);  //fn  
    return function(){
        alert(arguments[0]); //event
        return fn.apply(context, arguments);
    };
}

이것 은 하나의 함 수 를 apply 를 특정한 환경 에서 호출 하 는 것 입 니 다. arguments 대상 을 주의 하 십시오. 마지막 으로 return 과거의 익명 함수 (패키지 닫 기) 의 arguments 를 사용 해 야 합 니 다. 그러면 사건 이 사건 처리 함수 에 전달 하 는 매개 변 수 는 우리 의 편지 에 들 어 갈 수 있 습 니 다.
var handler = {
    message: "Event handled",
    handleClick: function(event){
        alert(this); // [object Object]
        alert(this.message); // Event handled
    } };
var btn = document.getElementById("myButton");
EventUtil.addHandler(btn, "click", bind(handler.handleClick, handler));

ES5 에 서 는 모든 함수 에 원생 bind () 방법 을 정의 합 니 다.그냥 쓰 면 돼.
EventUtil.addHandler(btn, "click", handler.handleClick.bind(handler));

특정한 함수 지침 을 값 으로 전달 하 는 동시에 이 함 수 는 특정한 환경 에서 실행 되 어야 하 며 바 인 딩 함수 의 효과 가 나타 납 니 다.
함수 코 리 화
이것 은 하나 이상 의 매개 변 수 를 설정 한 함 수 를 만 드 는 데 사 용 됩 니 다. 하나의 예 로 기본 사상 을 보 세 요.
function add(num1, num2){
    return num1 + num2;
}
function curriedAdd(num2){
    return add(5, num2);
}
alert(add(2, 3));     //5
alert(curriedAdd(3)); //8

코 리 화 함 수 를 만 드 는 일반적인 방법:
function curry(fn){
    var args = Array.prototype.slice.call(arguments, 1);
    return function(){
        var innerArgs = Array.prototype.slice.call(arguments);
        var finalArgs = args.concat(innerArgs);
        return fn.apply(null, finalArgs);
    };
}

이 함수 의 주요 작업 은 외부 함수 와 내부 함수 의 인 자 를 모두 되 돌아 오 는 함수 에 전달 하 는 것 입 니 다.
function add(a,b) { alert(a); alert(b); alert(a+b); } var curriedAdd = curry(add, 5);
curriedAdd(3);   //8
curriedAdd = curry(add, 3);
curriedAdd(5);   //8
curriedAdd = curry(add, 5,3);
curriedAdd();   //8

이 를 bind 함수 에 이용 하여 이벤트 처리 함수 에 여러 개의 인 자 를 전달 할 수 있 습 니 다.
function bind(fn, context){
    var args = Array.prototype.slice.call(arguments, 2); 
    return function(){
        var innerArgs = Array.prototype.slice.call(arguments); 
        var finalArgs = args.concat(innerArgs);
        return fn.apply(context, finalArgs);
    };
}
var handler = {
    message: "Event handled",
    handleClick: function(name, event){
        alert(this.message + ":"+ name + ":"+ event.type);
    }
};
var btn = document.getElementById("myButton");
EventUtil.addHandler(btn, "click", bind(handler.handleClick, handler, "myButton"));

여기 서 주의해 야 할 것 은 매개 변수의 순서 입 니 다. 예 를 들 어 여기 name 과 event 가 바 뀌 면 안 됩 니 다.ES5 의 bind 도 코 리 화 되 어 직접 사용 하면 된다.
EventUtil.addHandler(btn, "click", handler.handleClick.bind(handler, "myButton"));

왜곡 방지 대상
JS 공유 의 본질은 임의의 대상 을 임의로 수정 할 수 있 게 한다.이러 면 때때로 매우 불편 하 다.ES5 는 대상 을 설정 하 는 몇 가지 방법 을 추가 했다.일단 대상 을 변경 방지 로 설정 하면 취소 할 수 없습니다.
확장 불가 대상
새로운 속성 과 방법 을 추가 할 수 없습니다
var person = { name: "Nicholas" };
Object.preventExtensions(person);
person.age = 29;
alert(person.age); //undefined
alert(Object.isExtensible(person)); //false
person.name = "hahah";
alert(person.name); //hahah

밀봉 대상
속성 을 추가 하거나 삭제 할 수 없습니다. 기 존 구성원 의 [Configurable] 이 false 로 설정 되 었 습 니 다.
var person = { name: "Nicholas" };
Object.seal(person);
person.age = 29; 
alert(person.age); //undefined
delete person.name; 
alert(person.name); //"Nicholas"
alert(Object.isExtensible(person)); //false
alert(Object.isSealed(person));     //true

얼 어 붙 은 대상
확장 할 수 없고 밀봉 할 수 없 으 며 대상 데이터 속성의 [Writable] 은 false 로 설 정 됩 니 다.[Set] 이 정의 되 어 있 으 면, 접근 기 속성 은 여전히 쓸 수 있 습 니 다.
var person = { name: "Nicholas" };
Object.freeze(person);
person.age = 29; alert(person.age); //undefined
delete person.name; alert(person.name); //"Nicholas"
person.name = "Greg"; alert(person.name); //"Nicholas"

alert(Object.isExtensible(person));//false
alert(Object.isSealed(person));//true
alert(Object.isFrozen(person));//true

고급 타이머
setTimeout () 과 setInterval () 은 실 용적 인 기능 이지 만 주의해 야 할 것 이 있 습 니 다.JS 는 단일 라인 으로 타이머 가 사실상 막 힐 가능성 이 높다 는 것 을 의미한다.우리 가 이 두 함수 에서 설정 한 시간 은 코드 를 실행 대기 열 에 추가 하 는 것 을 대표 하 는 이벤트 입 니 다. 만약 에 가입 할 때 마침 JS 가 비어 있 으 면 이 코드 는 바로 실 행 됩 니 다. 즉, 이 시간 에 제시간에 실 행 됩 니 다.반면 JS 가 비어 있 지 않 거나 대기 열 에 다른 우선 순위 가 높 은 코드 가 있다 면 타이머 가 지연 되 는 것 을 의미 합 니 다.
중복 타이머
setInterval 을 사용 하여 타 이 머 를 만 드 는 목적 은 코드 규칙 을 대기 열 에 삽입 하 는 것 입 니 다.이 방식 의 문 제 는 마지막 코드 가 실행 되 지 않 았 을 때 코드 가 다시 대기 열 에 추 가 될 수 있다 는 점 이다.JS 엔진 은 이 문 제 를 해결 합 니 다. 코드 를 대기 열 에 추가 할 때 대기 열 에 코드 인 스 턴 스 가 있 는 지 확인 합 니 다. 있 으 면 추가 하지 않 습 니 다. 이 는 타이머 코드 가 가입 대기 열 에 있 는 최소 간격 이 정 해진 간격 임 을 확인 합 니 다.그러나 어떤 특수 한 상황 에서 도 두 가지 문제 가 발생 할 수 있 습 니 다. 어떤 간격 은 JS 의 처리 가 건 너 뛰 었 기 때문에 코드 간 의 간격 이 예상 보다 작 습 니 다.그래서 가능 한 한 setTimeout () 시 뮬 레이 션 간격 으로 호출 합 니 다.
setTimeout(function(){ 
    setTimeout(arguments.callee, interval);
}, interval);

Yielding Processes
만약 당신 의 페이지 에서 대량의 순환 처 리 를 하려 고 한다 면, 매번 순환 할 때마다 대량의 시간 을 소모 할 것 이 며, 그러면 사용자 의 조작 을 막 을 것 입 니 다.이때 블록 을 나 누 어 데 이 터 를 처리 하 는 것 이 좋 은 방법 이다.이 예 는 100 ms 마다 배열 요 소 를 취하 여 페이지 에 추가 합 니 다.
function chunk(array, process, context){
    setTimeout(function(){
        var item = array.shift();
        process.call(context, item);
        if (array.length > 0){
            setTimeout(arguments.callee, 100);
        }
    }, 100);
}
var data = [12,123,1234,453,436,23,23,5,4123,45,346,5634,2234,345,342];
function printValue(item){
    var div = document.getElementById("myDiv");
    div.innerHTML += item + "<br>";
}
chunk(data, printValue);

함수 절 류
이것 은 어떤 조작 이 끊임없이 촉발 되 는 것 을 피하 기 위해 서 이다. 예 를 들 어 DOM 조작 과 관련 되 고 대량의 DOM 조작 은 자원 을 매우 소모 한다.함수 절 류 의 기본 사상 은 매번 호출 은 실제 호출 된 setTimeout 작업 을 설정 하 는 것 입 니 다. 호출 할 때마다 현재 setTimeout 을 제거 하고 새로운 것 을 설정 합 니 다.짧 은 시간 안에 대량으로 호출 되면 setTimeout 내 작업 을 수행 하지 않 고 새로운 setTimeout 을 설정 합 니 다.setTimeout 시간 이 될 때 까지 충분 한 시간 을 사용 하지 않 아야 내부 의 진정한 작업 이 실 행 됩 니 다.이것 은 onresize 사건 에 특히 유용 합 니 다.
function throttle(method, context) {
    clearTimeout(method.tId);
    method.tId= setTimeout(function(){
        method.call(context);
    }, 100);
}
function reDiv(){
    var div = document.getElementById("myDiv");
    div.innerHTML += "qqqqqq" + "<br>";
}
window.onresize = function(){
    throttle(reDiv);
};

이렇게 하면 창 크기 를 100 ms 조정 하 는 것 을 멈 춘 후에 야 reDiv 작업 을 수행 할 수 있 습 니 다.
사용자 정의 이벤트
사건 과 같은 상호작용 은 바로 관찰자 모델 이다. 이런 모델 은 두 가지 대상 으로 구성 된다. 주체 와 관찰자 이다.주 체 는 사건 을 발표 하고 관찰 자 는 이 사건 들 을 구독 함으로써 이 주 체 를 관찰한다.사용자 정의 이 벤트 를 만 드 는 것 은 실제 적 으로 이 벤트 를 관리 하 는 대상 을 만 들 고 그 안에 각종 이벤트 형식의 처리 함 수 를 저장 합 니 다. 이 벤트 를 촉발 할 때 이벤트 형식 을 제시 하면 이 대상 은 해당 이벤트 처리 프로그램 을 찾 아 실 행 됩 니 다.다음은 이벤트 관리 대상 의 대체 형식 입 니 다.
function EventTarget(){
    this.handlers = {};
}
EventTarget.prototype = {
    constructor: EventTarget,
    addHandler: function(type, handler){
        if (typeof this.handlers[type] == "undefined"){
            this.handlers[type] = [];
        }
    this.handlers[type].push(handler);
    },
    fire: function(event){
        if (!event.target){
            event.target = this;
        }
        if (this.handlers[event.type] instanceof Array){
            var handlers = this.handlers[event.type];
            for (var i=0, len=handlers.length; i < len; i++){
                handlers[i](event);
            }
        }
    },
    removeHandler: function(type, handler){
        if (this.handlers[type] instanceof Array){
            var handlers = this.handlers[type];
            for (var i=0, len=handlers.length; i < len; i++){
                if (handlers[i] === handler){
                    break;
                }
            }
        handlers.splice(i, 1);
        }
    }
};

이벤트 처리 프로그램 을 추가 할 때 addHandler 는 이벤트 형식 에 따라 처리 함 수 를 handlers 속성 에 대응 하 는 배열 에 저장 합 니 다 (없 으 면 새로 만 듭 니 다).이 벤트 를 촉발 할 때 fire 를 사용 하여 최소한 type 속성 이 있 는 대상 에 게 전 달 됩 니 다.사용 시 이렇게:
function handleMessage(event){
    alert("Message received: " + event.message);
}
var target = new EventTarget();
target.addHandler("message", handleMessage);
target.fire({ type: "message", message: "Hello world!"});
target.removeHandler("message", handleMessage);
target.fire({ type: "message", message: "Hello world!"});

사용자 정의 이 벤트 는 항상 결합 대상 간 의 상호작용 을 해제 하 는 데 사 용 됩 니 다. 이 벤트 를 사용 하면 대상 과 대상 간 의 인용 이 필요 하지 않 고 이벤트 처리 와 이벤트 트리거 를 격 리 시 킵 니 다.
드래그 앤 드 롭
원본 마우스 이벤트 사용 하기
하나의 예 를 만 들 고 모듈 모드 를 사용 하여 드래그 하 는 플러그 인 을 만 들 고 모든 이벤트 처리 프로그램 을 추가 하고 제거 하 는 두 가지 방법 을 되 돌려 줍 니 다.
var DragDrop = function(){
    var dragging = null;
    var diffX = 0;
    var diffY = 0;
    function handleEvent(event){
        event = EventUtil.getEvent(event);
        var target = EventUtil.getTarget(event);
        switch(event.type){
            case "mousedown":
                if (target.className.indexOf("draggable") > -1){
                    dragging = target;
                    diffX = event.clientX - target.offsetLeft;
                    diffY = event.clientY - target.offsetTop;
                }
                break;
            case "mousemove":
                if (dragging !== null){
                    dragging.style.left = (event.clientX - diffX) + "px";
                    dragging.style.top = (event.clientY - diffY) + "px";
                }
                break;
            case "mouseup":
                dragging = null;
                break;
        }
    };
    return {
        enable: function(){
            EventUtil.addHandler(document, "mousedown", handleEvent);
            EventUtil.addHandler(document, "mousemove", handleEvent);
            EventUtil.addHandler(document, "mouseup", handleEvent);
        },
        disable: function(){
            EventUtil.removeHandler(document, "mousedown", handleEvent);
            EventUtil.removeHandler(document, "mousemove", handleEvent);
            EventUtil.removeHandler(document, "mouseup", handleEvent);
        }
    }
}();
DragDrop.enable();

이렇게 보면 드래그 의 기능 은 실현 되 었 지만 문제 가 있다.예 를 들 어 이것 은 제 가 쓴 플러그 인 입 니 다. 사용 하 는 사람 이 드래그 를 시작 할 때 뭔 가 를 하려 면 그 는 기 존의 소스 코드 에서 수정 해 야 합 니 다.그 는 실행 할 코드 와 함 수 를 모두 case "mousedown" 에 추가 해 야 한다.만약 이 플러그 인 을 내 가 암호 화 했다 면, 이 시간 에 뭔 가 를 하려 면 더욱 번 거 로 울 것 이다.이런 방법 은 분명히 결코 과학적 이지 않다.이때 사용자 정의 이 벤트 를 사용 하면 이 문 제 를 잘 해결 할 수 있다.
사용자 정의 이벤트 추가
여기에서 dragdrop 변 수 를 새로 정의 합 니 다. 이것 은 EventTarget 형식의 대상 입 니 다. 그 위 에 이벤트 처리 함수 나 트리거 이 벤트 를 추가 할 수 있 습 니 다.드래그 가 시 작 될 때, 과정 이 끝 날 때, 사용자 정의 이벤트 가 발생 합 니 다. 이 노드 에서 무엇 을 하고 싶 은 지 이벤트 처리 함 수 를 직접 추가 하면 됩 니 다.
var DragDrop = function(){
    //   dragdrop    EventTarget  ,           
    var dragdrop = new EventTarget(),
        dragging = null,
        diffX = 0,
        diffY = 0;
    function handleEvent(event){
        event = EventUtil.getEvent(event);
        var target = EventUtil.getTarget(event);
        switch(event.type){
            case "mousedown":
                if (target.className.indexOf("draggable") > -1){
                    dragging = target;
                    diffX = event.clientX - target.offsetLeft;
                    diffY = event.clientY - target.offsetTop;
                    //       
                    dragdrop.fire({type:"dragstart", target: dragging,
                        x: event.clientX, y: event.clientY});
                }
                break;
            case "mousemove":
                if (dragging !== null){
                    dragging.style.left = (event.clientX - diffX) + "px";
                    dragging.style.top = (event.clientY - diffY) + "px";
                    dragdrop.fire({type:"drag", target: dragging,
                        x: event.clientX, y: event.clientY});
                }
                break;
            case "mouseup":
                dragdrop.fire({type:"dragend", target: dragging,
                    x: event.clientX, y: event.clientY});
                dragging = null;
                break;
        }
    };
    dragdrop.enable = function(){
        EventUtil.addHandler(document, "mousedown", handleEvent);
        EventUtil.addHandler(document, "mousemove", handleEvent);
        EventUtil.addHandler(document, "mouseup", handleEvent);
    };
    dragdrop.disable = function(){
        EventUtil.removeHandler(document, "mousedown", handleEvent);
        EventUtil.removeHandler(document, "mousemove", handleEvent);
        EventUtil.removeHandler(document, "mouseup", handleEvent);
    };
    return dragdrop;
}();
DragDrop.addHandler("dragstart", function(event){
    var status = document.getElementById("myDiv");
    status.innerHTML = "Started dragging " + event.target.id;
});
DragDrop.addHandler("drag", function(event){
    var status = document.getElementById("myDiv");
    status.innerHTML += "<br/> Dragged " + event.target.id + " to (" + event.x +
        "," + event.y + ")";
});
DragDrop.addHandler("dragend", function(event){
    var status = document.getElementById("myDiv");
    status.innerHTML += "<br/> Dropped " + event.target.id + " at (" + event.x +
        "," + event.y + ")";
});
DragDrop.enable();

좋은 웹페이지 즐겨찾기