Конфликт между событиями focusout и click в JS - PullRequest
0 голосов
/ 05 августа 2020

Мне нужна помощь, чтобы найти решение с конфликтом событий focusout и click.

Я делаю проект dropdownlist, поэтому у нас есть две части раскрывающегося списка:

  1. Если click на кнопке со стрелкой, это открывает список. Но, когда вы click на кнопке со стрелкой, это должно закрыть список.

  2. Если click в текстовом поле, это открывает список. Но когда вы click в текстовом поле, это должно закрыть список.

Проблема, которая у меня есть, это событие focusout текстового поля при попытке закрыть список, нажав кнопку со стрелкой. Он открывается, закрывается и снова открывается.

Таким образом, он должен закрываться сразу, когда это необходимо, и когда происходит фокусировка, если список открыт.

PS: кнопка удаления не работает еще.

Что делать?

"use strict";

// LISTA DE INICIALIZACIÓN DE VARIABLES

// Se obtiene los ID de los elementos principales.

const tagSys = document.getElementById('tag-sys');
const tagInput = document.getElementById('input-section');
const textInput = document.getElementById('text-input');
const arrowButton = document.getElementById('btn-arrow');
var displayToggle = false;

// Se crea un arreglo por default.

var data = [
    'The Shawshank Redemption',
    'The Godfather',
    'The Godfather: Part II',
    'The Dark Knight',
    '12 Angry Men',
    "Schindler's List",
    'Pulp Fiction',
    'The Lord of the Rings: The Return of the King',
    'The Good, the Bad and the Ugly',
    'Fight Club'
];

// LISTA DE EVENTOS ACONTINUACIÓN

/* 
    El siguiente addEventListener se aplica sobre textInput.
    Su función hace mostrar el listado de data segun las palabras
    ingresadas.
*/

textInput.addEventListener('keyup', function (e) {
    console.log('keyup');
    let hasData = DropdownFilter(e.target.value);
    DropdownDisplay(hasData);
});

/* 
    El siguiente addEventListener se aplica sobre textInput.
    Su función hace mostrar el listado de la data.
*/

textInput.addEventListener('click', function () {
    DisplayToggle();
});

/* 
    El siguiente addEventListener se aplica sobre textInput.
    Su función hace cerrar el listado de la data.
*/

textInput.addEventListener('focusout', function () {
    if (displayToggle == true) {
        let hasData = false;
        DropdownDisplay(hasData);
        displayToggle = false;
    }
});

/* 
    El siguiente addEventListener se aplica sobre arrowButton.
    Su función hace enviar el focus al textInput y mostrar
    el listado de la data.
*/

arrowButton.addEventListener('click', function () {
    textInput.focus();
    DisplayToggle();
});

// LISTA DE MÉTODOS ACONTINUACIÓN

function DisplayToggle() {
    if (displayToggle == false) {
        let hasData = DropdownList(data);
        DropdownDisplay(hasData);
        displayToggle = true;
    } else {
        let hasData = false;
        DropdownDisplay(hasData);
        displayToggle = false;
    }
}

/* 
    El siguiente método DropdrowFilter, recibe como parametro
    una palabra que se encarga de buscar dentro del arreglo,
    para luego enviar al metodo DropdownList.
*/

function DropdownFilter(params) {
    let dataFilter = data.filter(function (e) {
        return e.toLowerCase().includes(params.toLowerCase());
    });
    return DropdownList(dataFilter);
}

/* 
    El siguiente método DropdrowList, recibe como parametro
    una lista de datos que usara para mostrar.
*/

function DropdownList(dataList) {
    RemoveList();
    if (dataList.length != 0) {
        let objList = {
            div: document.createElement('div'),
            ul: document.createElement('ul'),
            li: ''
        };

        objList.div.setAttribute("id", "tag-list");
        objList.div.classList.add('tag-list');
        tagInput.appendChild(objList.div);

        objList.div.appendChild(objList.ul);

        dataList.forEach(element => {
            objList.li = document.createElement('li');
            objList.li.textContent = element;
            objList.ul.appendChild(objList.li);
        });
    } else {
        let objList = {
            div: document.createElement('div'),
            ul: document.createElement('ul'),
            li: document.createElement('li')
        };

        objList.div.setAttribute("id", "tag-list");
        objList.div.classList.add('tag-list');
        tagInput.appendChild(objList.div);

        objList.div.appendChild(objList.ul);

        dataList[0] = 'No options';
        objList.li.textContent = dataList[0];
        objList.ul.appendChild(objList.li);
    }

    return true; // Retornamos True porque ya retorna data para mostrar.
}

/* 
    El siguiente método RemoveList, cumple como función
    eliminar la etiqueta con ID 'tag-list'.
*/

function RemoveList() {
    if (document.getElementById('tag-list')) {
        let div = document.getElementById('tag-list');
        tagInput.removeChild(div);
    }
}

/* 
    El siguiente metodo DropdownDisplay, cumple como función
    agregar la clase 'tag-list-show' para que sea visible la data,
    y la posición de la flecha.
*/

function DropdownDisplay(params) {
    let div = document.getElementById('tag-list');
    if (params == true) {
        div.classList.add('tag-list-show');
        arrowButton.classList.replace('fa-chevron-down', 'fa-chevron-up');
    } else {
        div.classList.remove('tag-list-show');
        arrowButton.classList.replace('fa-chevron-up', 'fa-chevron-down');
    }
}
body {
    margin: 0;
    background-color: #f39c12;
    font-family: 'Poppins', sans-serif;
}

main {
    align-items: center;
    display: flex;
    height: 100vh;
    justify-content: center;
}

.tag-sys {
    border: 1px solid #000000;
    border-radius: 2px;
    cursor: text;
    display: flex;
    font-size: 13px;
    max-width: 200px;
    min-height: 20px;
    position: relative;
}

.input-section {
    display: flex;
    flex-wrap: wrap;
    width: 80%;
}

.text-input {
    border: none;
    border-right: 1px solid #000000;
    border-bottom-left-radius: 2px;
    border-top-left-radius: 2px;
    font-size: 1em;
    flex: 1;
    margin: 0;
    min-width: 20px;
    padding: 0;
    padding-left: 2px;
}

.text-input::placeholder {
    color: #bdc3c7;
}

.text-input:focus {
    outline: none;
}

.control-section {
    align-items: center;
    background-color: #bdc3c7;
    display: flex;
    justify-content: space-around;
    width: 20%;
}

.control-section-icon {
    align-items: center;
    border-radius: 3px;
    cursor: pointer;
    display: flex;
    height: 16px;
    justify-content: center;
    width: 16px;
}

.control-section-icon i {
    font-size: 14px;
}

.tag-list {
    background-color: #ffffff;
    border: 1px solid #000000;
    border-radius: 2px;
    position: absolute;
    font-size: 14px;
    height: 100px;
    overflow-y: scroll;
    left: -1px;
    top: 22px;
    width: 100%;
    display: none;
}

.tag-list-show {
    display: block !important;
}

.tag-list ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
}

.tag-list ul li {
    padding: 5px;
}

.tag-list ul li:hover {
    cursor: pointer;
    background-color: #bdc3c7;
}
<link rel="stylesheet" type="text/css" href="style.css">
    <link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet"> 
    <script src="https://kit.fontawesome.com/1001c03ba9.js" crossorigin="anonymous"></script>
    <main>
        <div id="tag-sys" class="tag-sys">
            <div id="input-section" class="input-section">
                <input id="text-input" class="text-input" type="text">
            </div>
            <div class="control-section">
                <span class="control-section-icon">
                    <i id="btn-delete" class="fas fa-times"></i>
                </span>
                <span class="control-section-icon">
                    <i id="btn-arrow" class="fas fa-chevron-down"></i>
                </span>
            </div>
        </div>
    </main>
    <script src="app.js"></script>

1 Ответ

0 голосов
/ 05 августа 2020

Это потому, что focusout срабатывает перед click. Используйте mousedown вместо

...