В JavaScript e.target не работает, как я ожидал - PullRequest
2 голосов
/ 08 января 2012

Я написал некоторый 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/

1 Ответ

1 голос
/ 08 января 2012

Когда я щелкаю внутри элемента, который он закрывает, я хочу, чтобы он закрывался, только если они щелкнули за пределами поля.

Как я уже сказал в своем комментарии, если поле содержит другие элементы, то 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, независимо от того, открыт диалог или нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...