I need some help to figure it out a solution with the focusout
and click
event conflict.
I'm doing a dropdownlist
project, so we have two part of the dropdown:
If
click
on the arrow button, this one opened a list. But, when youclick
on the arrow button this one should close the list.If
click
on text box, this one opened a list. But, when youclick
on text box this one should close the list.
The problem that I have, it is focusout
event of the text box when you try to close the list pressing the arrow button. It is opening, closing and opening again.
So it should close at once when need it and when is focusout if the list is opened.
PS: the delete button doesn't has function yet.
What should I do?
"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>