在JavaScript中,e.target无法正常工作

时间:2012-01-08 12:03:09

标签: javascript dom javascript-events

我写了一些javascript,当点击一个元素时会打开一个元素。但是我无法获得

 var menu = document.getElementById(show);
 if (menuOpen && e.target !== menu){...}

这不符合我的要求,因为:

  1. 当我只希望一次打开时,您可以打开多个显示的元素。
  2. 当我点击它关闭的元素内部时,我只想让它在盒子外面点击时关闭。

    function openBox(button, show){
        var menuOpen = false; //to toggle when the button is clicked.
    
        // checks the whole document for clicks and then if the element is open it will >
        // check to see if you have clicked away from it or not.
        document.addEventListener("click", function(e){
            var menu = document.getElementById(show);
            if (menuOpen && e.target !== menu){       // if elements open and the click event target does not match >
                menu.style.display = "none";          // we will close it
                menuOpen = false;
            }
        },false);
    
        // add an event listner to the button element and then if its clicked stop any >
        // links an stop bubbling and then change the display style.
        document.getElementById(button).addEventListener("click", function(e){
            var menu = document.getElementById(show);
            e.preventDefault();
            e.stopPropagation();
            if (menuOpen){
                menu.style.display = "none";
                menuOpen = false;
            } else {
                menu.style.display = "block";
                menuOpen = true;
            }
        },false);
    }
    openBox("signInButton", "signIn");
    openBox("bagButton", "shoppingBag");
    openBox("currencyButton", "currencySelect");
    
  3. http://jsfiddle.net/jamcoupe/9CEGw/

    编辑: 在@Felix Kling发布后,我将代码更改为:

    document.addEventListener("click", function(e){
        var menu = document.getElementById(show);
        if (menuOpen && (e.target.parentNode !== menu) && (e.target !== menu)){    
            menu.className = "closedBoxes";       
            pointer = document.getElementById(arrow).className = "arrowE";
            menuOpen = false;
        }
        },false);
    

    这解决了第一个问题,但我仍然坚持如何制作它,以便只有一个盒子在一个给定时间打开。因此,当用户打开signIn框并点击currencyChanger时,我希望signIn框关闭。

    http://jsfiddle.net/jamcoupe/kcF9Z/7/

1 个答案:

答案 0 :(得分:1)

  

当我在它关闭的元素内部点击时,我只希望它在盒子外面点击时关闭。

正如我在评论中已经说过的那样,如果框中包含其他元素,则e.target不会引用框本身,而是引用框内的元素。

因此,为了测试点击是否在外,您必须测试e.target是否是框内的元素或框本身。为此,您必须遍历DOM树。

示例:

var target = e.target;
while(target && target !== menu) {
    target = target.parentNode;
}

if(!target) {
   // click was outside of the box
}
  

当我只希望一次打开时,您可以打开多个显示的元素。

如果要使三个对话框相互依赖,则必须保持一些共享状态。我建议,您可以使用一个对话管理器来处理打开和关闭框,而不是有三个对话框。

示例:

function DialogManager() {
    this.dialogs_ = {};
    this.openedDialog_ = null;

    this.init_();
}

DialogManager.prototype.init_ = function(e) {
    var self = this;
    document.addEventListener('click', function(e) {
        var id = e.target.id;
        if(id && id in self.dialogs_) { // if one of the buttons was clicked.
            self.openDialog(id);        // the dialog is opened (or closed)
            return;
        }

        if(self.openedDialog_) { // if a dialog is currently open, we have to
            var target = e.target; // close it if the click was outside
            while(target && target.id !== self.openedDialog_) {
                target = target.parentNode;
            }
            if(!target) {
                self.closeDialog(self.openedDialog_);
            }
        }
    }, false);
};

DialogManager.prototype.registerDialog = function(button_id, dialog_id) {
    this.dialogs_[button_id] = dialog_id;
};

DialogManager.prototype.openDialog = function(id) {
    var open_id = this.openedDialog_;
    if(open_id) {
        this.closeDialog(open_id);
    }
    if(id !== open_id) {
        var dialog = document.getElementById(this.dialogs_[id]);
        dialog.style.display = "block";
        this.openedDialog_ = id;
    }
};

DialogManager.prototype.closeDialog = function(id) {
        var dialog = document.getElementById(this.dialogs_[id]);
        dialog.style.display = "none";
        this.openedDialog_ = null;
};

DEMO

我希望这会给你一些想法。还有很多可以改进的地方,例如,现在管理员会监听每个click事件,无论对话是否打开。