2010-06-25 90 views
0

我有我做了一個JS對象,有幾個原型的功能,並從內部構造精細,採用這種美其名曰[功能]無法解析Javascript對象方法這個參考

但在後面的事件處理函數中,這指的是元素,而不是對象,我不知道如何解決這個問題:

它通過AddListener罰款,鼠標向下事件觸發,導致啓用/ disableDragging工作正常。但在該函數中,「this」是元素,而不是拖動器對象,所以我無法調用訪問WindowCenter,DraggingBool或Add/RemoveListener事件。

從閱讀起來,它看起來像我可能需要實現prototype.bind?但不知道如何重新安排我現有的代碼來做到這一點。或者我改變其中一個函數來返回一個函數?

是的,我知道我可以在jQuery的做到這一點,做了很多次,只是想看看我是否能得到它與POJS :)

Dragger = function(element, draggingElement) { 
    this.Element = element; 
    this.DraggingElement = element; 
    this.WindowCenter; 
    this.DraggingBool = false; 

    this.AddListener(this.DraggingElement, "mousedown", this.enableDragging); 
    this.AddListener(this.DraggingElement, "mouseup", this.disableDragging); 
} 

Dragger.prototype.AddListener = function (element, eventType, listener, bubble) { 
    if (typeof (element) != "object" || typeof (listener) != "function") 
     return; 
    if (typeof (bubble) == "undefined") 
     var bubble = false; 
    eventType = eventType.toLowerCase(); 
    if (eventType.substr(0, 2) == "on") 
     eventType = eventType.substr(2); 
    if (window.addEventListener) { // Mozilla, Netscape, Firefox 
     element.addEventListener(eventType, listener, bubble); 
    } else if (window.attachEvent) { // IE 
     element.attachEvent("on" + eventType, listener); 
    } 
} 

Dragger.prototype.RemoveListener = function (element, eventType, listener) { 
    eventType = eventType.toLowerCase(); 
    if (eventType.substr(0, 2) == "on") 
     eventType = eventType.substr(2); 
    if (window.addEventListener) { // Mozilla, Netscape, Firefox 
     element.removeEventListener(eventType, listener, false); 
    } else if (window.attachEvent) { // IE 
     element.detachEvent("on" + eventType, listener); 
    } 
} 

Dragger.prototype.enableDragging = function (e) { 
    if (!e) var e = window.event; 
    //dont move for right click 
    if (e.which && e.which == 3) 
     return; 
    else if (e.button && e.button == 2) 
     return; 

    this.DraggingBool = true; 
    this.WindowCenter = new Point(e.pageX, e.pageY); 
    this.AddListener(document.body, "mouseover", this.mouseMoveListener); 
} 

Dragger.prototype.disableDragging = function() { 
    this.DraggingBool = false; 
    this.RemoveListener(document.body, "mouseover", this.mouseMoveListener); 
} 

Dragger.prototype.mouseMoveListener = function (e) { 
    if (!this.DraggingBool) 
     return; 
    if (!e) var e = window.event; 
    e.preventDefault(); 
    var newLoc = new Point(e.pageX, e.pageY); 
    var xDif = windowCenter.X - newLoc.X; 
    var yDif = windowCenter.Y - newLoc.Y; 
    this.Element.style.left = (this.Element.offsetLeft + xDif) + "px"; 
    this.Element.style.top = (this.Element.offsetTop + yDif) + "px"; 
    this.WindowCenter = newLoc; 
} 

回答

2

這是使用addEventListener執行範圍時,因爲要去設置爲節點,就像您使用node.onclick = foo一樣。當您在IE中使用attachEvent時,執行範圍將成爲全局執行範圍,即窗口。

解決此問題的一種方法是使用Function.call或Function.apply來指定您的喜好的執行範圍。許多圖書館將宣佈一個綁定功能,以解決這個問題,比如:

function bind(fn, context) { 
    return function() { 
    return fn.apply(context, arguments); 
    }; 
} 

this.AddListener(this.DraggingElement, "mousedown", 
    bind(this.enableDragging, this)); 

你也可以添加一個上下文參數到您的addListener功能,並在那裏做了結合。

Ecmascript 5有一個內置的綁定方法。

+0

太棒了!乾杯,比創建時將對象實例全局變量設置爲全局變量,以及在函數中調用該硬編碼要好得多。) 現在我只需在IE中使用它,因爲您顯然不能設置style.left¬.¬。但我會解決它^^ – Psytronic 2010-06-25 11:07:11

0
Function.prototype.bind = function() { 
    if (arguments.length < 2 && arguments[0] === undefined) { 
    return this; 
    } 

    var thisObj = this, 
    args = Array.prototype.slice.call(arguments), 

    obj = args.shift(); 

    return function() { 
    return thisObj.apply(obj, args.concat(Array.prototype.slice.call(arguments))); 
    }; 

    }; 



    Function.bind = function() { 
    var args = Array.prototype.slice.call(arguments); 
    return Function.prototype.bind.apply(args.shift(), args); 

    } 

Dragger = function(element, draggingElement) { 
    this.Element = element; 
    this.DraggingElement = element; 
    this.WindowCenter; 
    this.DraggingBool = false; 

    this.AddListener(this.DraggingElement, "mousedown", this.enableDragging,this); 
    this.AddListener(this.DraggingElement, "mouseup", this.disableDragging,this); 
} 

Dragger.prototype.AddListener = function (element, eventType, listener, bubble,dragger_obj) { 
    if (typeof (element) != "object" || typeof (listener) != "function") 
     return; 
    if (typeof (bubble) == "undefined") 
     var bubble = false; 
    eventType = eventType.toLowerCase(); 
    if (eventType.substr(0, 2) == "on") 
     eventType = eventType.substr(2); 
    if (window.addEventListener) { // Mozilla, Netscape, Firefox 
     element.addEventListener(eventType, listener.bind(dragger_obj), bubble); 
    } else if (window.attachEvent) { // IE 
     element.attachEvent("on" + eventType, listener.bind(dragger_obj)); 
    } 
} 

Dragger.prototype.RemoveListener = function (element, eventType, listener,dragger_obj) { 
    eventType = eventType.toLowerCase(); 
    if (eventType.substr(0, 2) == "on") 
     eventType = eventType.substr(2); 
    if (window.addEventListener) { // Mozilla, Netscape, Firefox 
     element.removeEventListener(eventType, listener.bind(dragger_obj), false); 
    } else if (window.attachEvent) { // IE 
     element.detachEvent("on" + eventType, listener.bind(dragger_obj)); 
    } 
} 

Dragger.prototype.enableDragging = function (e) { 
    if (!e) var e = window.event; 
    //dont move for right click 
    if (e.which && e.which == 3) 
     return; 
    else if (e.button && e.button == 2) 
     return; 

    this.DraggingBool = true; 
    this.WindowCenter = new Point(e.pageX, e.pageY); 
    this.AddListener(document.body, "mouseover", this.mouseMoveListener,this); 
} 

Dragger.prototype.disableDragging = function() { 
    this.DraggingBool = false; 
    this.RemoveListener(document.body, "mouseover", this.mouseMoveListener,this); 
} 

Dragger.prototype.mouseMoveListener = function (e) { 
    if (!this.DraggingBool) 
     return; 
    if (!e) var e = window.event; 
    e.preventDefault(); 
    var newLoc = new Point(e.pageX, e.pageY); 
    var xDif = windowCenter.X - newLoc.X; 
    var yDif = windowCenter.Y - newLoc.Y; 
    this.Element.style.left = (this.Element.offsetLeft + xDif) + "px"; 
    this.Element.style.top = (this.Element.offsetTop + yDif) + "px"; 
    this.WindowCenter = newLoc; 
}