javascript - 在 JavaScript 中,e.target 没有像我预期的那样工作

标签 javascript dom dom-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");
    

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);

这已经解决了第一个问题,但我仍然坚持如何让它在给定时间只打开一个盒子。因此,当用户打开登录框并单击 currencyChanger 时,我希望关闭登录框。

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

最佳答案

When I click inside the element it closes, I only want it to close if they have clicked outside the box.

正如我在评论中所说,如果框包含其他元素,则 e.target 不是指框本身,而是指框内的元素。

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

例子:

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

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

You can open more than one of the showed elements when I only want one open at a time.

如果你想让这三个对话框相互依赖,你必须维护一些共享状态。我建议,您可以使用一个对话框管理器来代替三个对话框,它负责打开和关闭框。

例子:

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 事件,无论对话框是否打开。

关于javascript - 在 JavaScript 中,e.target 没有像我预期的那样工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8777327/

相关文章:

javascript - 如何在网页上出现-消失导航栏?

javascript - 我无法在 react 中读取 dom 元素的属性 'ref'

php - 是否可以在 php 循环中重复 file_get_html()?

没有输入字段的 HTML 日期选择器。使用 VBA 触发更新事件

javascript - LeafletJS 面向对象的最佳方法

java - 检测文件是否准备就绪并提供下载服务

javascript stopPropagation/cancelBubble/preventDefault 在 Firefox 中不起作用

javascript - 在 HTML 表格中,如何使单元格的内容(而不是表格本身)居中?

jquery - 如何动态地将一个div定位在另一个div下面?

javascript - 缩放滚动页面