Search/Filter Dropdown Javascript - javascript

I'm following this guide to create Search/Filter Dropdown.
But I have this method 'allNameMuseums()', that returns an array of names (for example :
array = ["Jack", "Paul", "George"]
My JS code :
async function allNameMuseums() {
let nomeFile = "dati_musei_infovis.csv";
let data3 = await d3.dsv(";", nomeFile, function (d) {
return {
Museo: d.Museo,
Ingresso: d.Ingresso,
Anno: d.Anno,
Mese: d.Mese,
Visitatori: d.Visitatori
};
});
return filtraggioNomeMuseo(data3);
};
function filtraggioNomeMuseo(data) {
array_filtrato = [];
var map = {};
//var visitatori = 0;
for (i=0; i<data.length; i++) {
if (!(array_filtrato.includes(data[i].Museo))) {
array_filtrato.push(data[i].Museo)
}
}
return array_filtrato;
}
I want to put these names instead of About, Base, Blog etc...

You could loop through the returned array and append the names as anchors to the dropdown like :
document.addEventListener("DOMContentLoaded", function(event) {
allNameMuseums().forEach(function(item){
document.getElementById("myDropdown").innerHTML += ''+item+'';
})
});
NOTE: Put your code inside DOMContentLoaded event listener to make sure all the DOM elements are loaded before executing your code/
Working sample:
document.addEventListener("DOMContentLoaded", function(event) {
allNameMuseums().forEach(function(item) {
document.getElementById("myDropdown").innerHTML += '' + item + '';
})
});
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
function filterFunction() {
var input, filter, ul, li, a, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
div = document.getElementById("myDropdown");
a = div.getElementsByTagName("a");
for (i = 0; i < a.length; i++) {
if (a[i].innerHTML.toUpperCase().indexOf(filter) > -1) {
a[i].style.display = "";
} else {
a[i].style.display = "none";
}
}
}
function allNameMuseums() {
return ["Jack", "Paul", "George"];
}
.dropbtn {
background-color: #4CAF50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropbtn:hover,
.dropbtn:focus {
background-color: #3e8e41;
}
#myInput {
border-box: box-sizing;
background-image: url('searchicon.png');
background-position: 14px 12px;
background-repeat: no-repeat;
font-size: 16px;
padding: 14px 20px 12px 45px;
border: none;
border-bottom: 1px solid #ddd;
}
#myInput:focus {
outline: 3px solid #ddd;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f6f6f6;
min-width: 230px;
overflow: auto;
border: 1px solid #ddd;
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown a:hover {
background-color: #ddd;
}
.show {
display: block;
}
<h2>Search/Filter Dropdown</h2>
<p>Click on the button to open the dropdown menu, and use the input field to search for a specific dropdown link.</p>
<div class="dropdown">
<button onclick="myFunction()" class="dropbtn">Dropdown</button>
<div id="myDropdown" class="dropdown-content">
<input type="text" placeholder="Search.." id="myInput" onkeyup="filterFunction()">
</div>
</div>

Related

Javascripts multiple choice onclick modify all questions

I build this multiple choice questions but not in quiz format. I have in the page an sequence of divs with questions and each question have their own choices and check button, so they are independent and free for the users to respond one, all or none. I made the content (questions and answers) wrote directly on HTML file because I have others working with me and they have only contact with the HTML files to implement some classes.
My problem is that I made one question and it's working, but when a duplicated the div with another question the interaction affects all the divs. For exemple:
when you select an option, the check button turns from disable to enable, but if you select an option from the second question, the check button from the first question change.
if you want to interact with two question in the same time, when you select an option in the first question, when you select an option in the second question on the first that you selected turns unselected.
So I want to make each div with question be independent, in a way that we can create as many questions as we want.
I created this https://jsfiddle.net/1yLwrcek/2/
let mcqCard = document.querySelectorAll('.mcq-card');
let answerOption = document.querySelectorAll('.mcq__answers li');
let submitButton = document.querySelector('.mcq__submit button');
let submitFeedback = document.querySelector('.mcq__submit--feedback');
let score = 0;
(function () {
// Select option, clear the others and enable submit
answerOption.forEach(option => {
option.addEventListener('click', function () {
console.log(submitButton.getAttribute('type'));
answerSelect(option);
});
});
//Submit button to check only selected class option.
submitButton.addEventListener('click', function () {
if (submitButton.getAttribute('type') === 'submit' && submitButton.getAttribute('aria-disabled') === 'false') {
butttonCheck();
} else {
buttonReset();
}
});
})();
function answerSelect(e) {
if (submitButton.getAttribute('type') === 'submit') {
for (let i = 0; i < answerOption.length; i++) {
const element = answerOption[i];
element.classList.remove('mcq__answers--selected');
}
e.classList.add('mcq__answers--selected');
submitButton.setAttribute('aria-disabled', 'false');
}
}
function incorrectAnswer(event) {
event.classList.remove('mcq__answers--selected');
event.classList.add('mcq__answers--incorrect');
submitFeedback.innerHTML = `<span class="material-symbols-rounded">cancel</span>Resposta errada! <br class="d-lg-none" />Tente novamente.`;
submitFeedback.classList.remove('d-none', 'mcq__submit__feedback--correct');
submitFeedback.classList.add('mcq__submit__feedback--incorrect');
}
function correctAnswer(event) {
event.classList.remove('mcq__answers--selected');
event.classList.add('mcq__answers--correct');
submitFeedback.innerHTML = `<span class="material-symbols-rounded">check_circle</span>Resposta correta! <br class="d-lg-none" />VocĂȘ acertou em ${score} tentativa(s).`;
submitFeedback.classList.remove('d-none', 'mcq__submit__feedback--incorrect');
submitFeedback.classList.add('mcq__submit__feedback--correct');
}
function blockAnswerOption() {
for (let i = 0; i < answerOption.length; i++) {
const element = answerOption[i];
element.classList.add('mcq__answers--blocked');
}
}
function butttonCheck() {
if (submitButton.getAttribute('type') === 'submit') {
score++;
for (let i = 0; i < answerOption.length; i++) {
const element = answerOption[i];
if (element.classList.contains('mcq__answers--selected')) {
if (!element.hasAttribute('correct')) {
incorrectAnswer(element);
blockAnswerOption();
} else {
correctAnswer(element);
blockAnswerOption();
}
}
}
submitButton.setAttribute('type', 'reset');
submitButton.innerHTML = 'Reset';
}
}
function buttonReset() {
if (submitButton.getAttribute('type') === 'reset') {
for (let i = 0; i < answerOption.length; i++) {
const element = answerOption[i];
element.classList.remove('mcq__answers--correct', 'mcq__answers--incorrect', 'mcq__answers--blocked', 'mcq__answers--selected');
submitButton.setAttribute('type', 'submit');
submitButton.innerHTML = 'Check';
submitButton.setAttribute('aria-disabled', 'true');
}
if (submitFeedback.classList.contains('mcq__submit__feedback--correct')) {
score = 0;
}
submitFeedback.classList.remove('mcq__submit__feedback--correct', 'mcq__submit__feedback--incorrect');
submitFeedback.classList.add('d-none');
}
}
:root {
/* Colors */
--primary-color: #d27f7d;
--primary-color-light: #ee9b9a;
--primary-color-dark: #bb6564;
--secondary-color: #8a6580;
--secondary-color-extra-light: #fae9f5;
--secondary-color-light: #c28cb4;
--secondary-color-dark: #5a3751;
--text-color: #1e1e1e;
--text-color-light: #535658;
--color-dark: #1e1e1e;
--color-light: #eef2f6;
--color-light-hover: #e6e6e625;
}
.mcq-card {
padding: 0px 30px;
}
.mcq-card .mcq__question {
padding: 30px 0;
border-bottom: 1px solid var(--secondary-color-light);
font-family: 'DM Sans Bold', sans-serif;
font-size: 1.25rem;
}
/* Answers List */
.mcq-card .mcq__answers {
padding: 30px 0;
}
.mcq-card .mcq__answers ul {
list-style-type: none;
margin: 0;
}
.mcq-card .mcq__answers ul li {
padding: 10px 20px;
margin-bottom: 20px;
border: 2px solid var(--primary-color-light);
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
transition: 0.1s;
}
.mcq-card .mcq__answers ul li:last-child {
margin-bottom: 0;
}
.mcq-card .mcq__answers ul li:not(.mcq__answers--blocked, .mcq__answers--selected, .mcq__answers--correct, .mcq__answers--incorrect):hover {
border-color: var(--primary-color-dark);
/* background-color: var(--color-light-hover); */
}
.mcq-card .mcq__answers ul li.mcq__answers--selected {
background-color: var(--secondary-color-extra-light);
border-color: var(--secondary-color-light);
color: var(--secondary-color-dark);
}
.mcq-card .mcq__answers ul li.mcq__answers--correct {
background-color: #c0ffce;
border-color: #28a745;
color: #014811;
cursor: not-allowed;
}
.mcq-card .mcq__answers ul li.mcq__answers--incorrect {
background-color: #ffc5cb;
border-color: #dc3545;
color: #81000c;
cursor: not-allowed;
}
.mcq-card .mcq__answers ul li.mcq__answers--blocked:not(.mcq__answers--correct, .mcq__answers--incorrect) {
cursor: not-allowed;
border-color: var(--color-light);
color: var(--text-color-light);
}
/* Submit Button */
.mcq-card .mcq__submit {
display: flex;
flex-direction: row;
justify-content: start;
align-items: center;
padding: 30px 0;
border-top: 1px solid var(--secondary-color-light);
}
.mcq-card .mcq__submit button[aria-disabled='true'] {
background-color: #909599;
border-color: #909599;
cursor: not-allowed;
}
/* Feedback mensage */
.mcq-card .mcq__submit .mcq__submit--feedback {
font-family: 'DM Sans Bold', sans-serif;
margin-left: 20px;
line-height: 1.2;
}
.mcq-card .mcq__submit .mcq__submit--feedback .material-symbols-rounded {
font-weight: 700;
margin-right: 10px;
}
.mcq-card .mcq__submit .mcq__submit--feedback.mcq__submit__feedback--correct {
display: block !important;
color: #28a745;
}
.mcq-card .mcq__submit .mcq__submit--feedback.mcq__submit__feedback--incorrect {
display: block !important;
color: #dc3545;
}
<div class="mcq-card card shadow round border-0">
<div class="mcq__question">1. Question</div>
<div class="mcq__answers">
<ul>
<li tabindex="0">Option 1</li>
<li tabindex="0">Option 2</li>
<li tabindex="0" correct>Option 3</li>
</ul>
</div>
<div class="mcq__submit">
<button class="button-primary" aria-disabled="true" type="submit">Check</button>
<span class="d-none mcq__submit--feedback"></span>
</div>
</div>
<div class="mcq-card card shadow round border-0">
<div class="mcq__question">2. Question</div>
<div class="mcq__answers">
<ul>
<li tabindex="0">Option 1</li>
<li tabindex="0">Option 2</li>
<li tabindex="0" correct>Option 3</li>
</ul>
</div>
<div class="mcq__submit">
<button class="button-primary" aria-disabled="true" type="submit">Check</button>
<span class="d-none mcq__submit--feedback"></span>
</div>
</div>
Thanks
Because each question has exact same structure, you'll need either assign an unique ID for each or go by its index.
But most simple solution is to query each element of each question separately:
let mcqCard = document.querySelectorAll('.mcq-card');
let score = 0;
(function () {
mcqCard.forEach(mcq =>
{
let answerOption = mcq.querySelectorAll('.mcq__answers li');
let submitButton = mcq.querySelector('.mcq__submit button');
let submitFeedback = mcq.querySelector('.mcq__submit--feedback');
// Select option, clear the others and enable submit
answerOption.forEach(option => {
option.addEventListener('click', function () {
console.log(submitButton.getAttribute('type'));
answerSelect(option, submitButton, answerOption);
});
});
//Submit button to check only selected class option.
submitButton.addEventListener('click', function () {
if (submitButton.getAttribute('type') === 'submit' && submitButton.getAttribute('aria-disabled') === 'false') {
butttonCheck();
} else {
buttonReset();
}
});
function answerSelect(e, submitButton) {
if (submitButton.getAttribute('type') === 'submit') {
for (let i = 0; i < answerOption.length; i++) {
const element = answerOption[i];
element.classList.remove('mcq__answers--selected');
}
e.classList.add('mcq__answers--selected');
submitButton.setAttribute('aria-disabled', 'false');
}
}
function incorrectAnswer(event) {
event.classList.remove('mcq__answers--selected');
event.classList.add('mcq__answers--incorrect');
submitFeedback.innerHTML = `<span class="material-symbols-rounded">cancel</span>Resposta errada! <br class="d-lg-none" />Tente novamente.`;
submitFeedback.classList.remove('d-none', 'mcq__submit__feedback--correct');
submitFeedback.classList.add('mcq__submit__feedback--incorrect');
}
function correctAnswer(event) {
event.classList.remove('mcq__answers--selected');
event.classList.add('mcq__answers--correct');
submitFeedback.innerHTML = `<span class="material-symbols-rounded">check_circle</span>Resposta correta! <br class="d-lg-none" />VocĂȘ acertou em ${score} tentativa(s).`;
submitFeedback.classList.remove('d-none', 'mcq__submit__feedback--incorrect');
submitFeedback.classList.add('mcq__submit__feedback--correct');
}
function blockAnswerOption() {
for (let i = 0; i < answerOption.length; i++) {
const element = answerOption[i];
element.classList.add('mcq__answers--blocked');
}
}
function butttonCheck() {
if (submitButton.getAttribute('type') === 'submit') {
score++;
for (let i = 0; i < answerOption.length; i++) {
const element = answerOption[i];
if (element.classList.contains('mcq__answers--selected')) {
if (!element.hasAttribute('correct')) {
incorrectAnswer(element);
blockAnswerOption();
} else {
correctAnswer(element);
blockAnswerOption();
}
}
}
submitButton.setAttribute('type', 'reset');
submitButton.innerHTML = 'Reset';
}
}
function buttonReset() {
if (submitButton.getAttribute('type') === 'reset') {
for (let i = 0; i < answerOption.length; i++) {
const element = answerOption[i];
element.classList.remove('mcq__answers--correct', 'mcq__answers--incorrect', 'mcq__answers--blocked', 'mcq__answers--selected');
submitButton.setAttribute('type', 'submit');
submitButton.innerHTML = 'Check';
submitButton.setAttribute('aria-disabled', 'true');
}
if (submitFeedback.classList.contains('mcq__submit__feedback--correct')) {
score = 0;
}
submitFeedback.classList.remove('mcq__submit__feedback--correct', 'mcq__submit__feedback--incorrect');
submitFeedback.classList.add('d-none');
}
}
});
})();
:root {
/* Colors */
--primary-color: #d27f7d;
--primary-color-light: #ee9b9a;
--primary-color-dark: #bb6564;
--secondary-color: #8a6580;
--secondary-color-extra-light: #fae9f5;
--secondary-color-light: #c28cb4;
--secondary-color-dark: #5a3751;
--text-color: #1e1e1e;
--text-color-light: #535658;
--color-dark: #1e1e1e;
--color-light: #eef2f6;
--color-light-hover: #e6e6e625;
}
.mcq-card {
padding: 0px 30px;
}
.mcq-card .mcq__question {
padding: 30px 0;
border-bottom: 1px solid var(--secondary-color-light);
font-family: 'DM Sans Bold', sans-serif;
font-size: 1.25rem;
}
/* Answers List */
.mcq-card .mcq__answers {
padding: 30px 0;
}
.mcq-card .mcq__answers ul {
list-style-type: none;
margin: 0;
}
.mcq-card .mcq__answers ul li {
padding: 10px 20px;
margin-bottom: 20px;
border: 2px solid var(--primary-color-light);
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
transition: 0.1s;
}
.mcq-card .mcq__answers ul li:last-child {
margin-bottom: 0;
}
.mcq-card .mcq__answers ul li:not(.mcq__answers--blocked, .mcq__answers--selected, .mcq__answers--correct, .mcq__answers--incorrect):hover {
border-color: var(--primary-color-dark);
/* background-color: var(--color-light-hover); */
}
.mcq-card .mcq__answers ul li.mcq__answers--selected {
background-color: var(--secondary-color-extra-light);
border-color: var(--secondary-color-light);
color: var(--secondary-color-dark);
}
.mcq-card .mcq__answers ul li.mcq__answers--correct {
background-color: #c0ffce;
border-color: #28a745;
color: #014811;
cursor: not-allowed;
}
.mcq-card .mcq__answers ul li.mcq__answers--incorrect {
background-color: #ffc5cb;
border-color: #dc3545;
color: #81000c;
cursor: not-allowed;
}
.mcq-card .mcq__answers ul li.mcq__answers--blocked:not(.mcq__answers--correct, .mcq__answers--incorrect) {
cursor: not-allowed;
border-color: var(--color-light);
color: var(--text-color-light);
}
/* Submit Button */
.mcq-card .mcq__submit {
display: flex;
flex-direction: row;
justify-content: start;
align-items: center;
padding: 30px 0;
border-top: 1px solid var(--secondary-color-light);
}
.mcq-card .mcq__submit button[aria-disabled='true'] {
background-color: #909599;
border-color: #909599;
cursor: not-allowed;
}
/* Feedback mensage */
.mcq-card .mcq__submit .mcq__submit--feedback {
font-family: 'DM Sans Bold', sans-serif;
margin-left: 20px;
line-height: 1.2;
}
.mcq-card .mcq__submit .mcq__submit--feedback .material-symbols-rounded {
font-weight: 700;
margin-right: 10px;
}
.mcq-card .mcq__submit .mcq__submit--feedback.mcq__submit__feedback--correct {
display: block !important;
color: #28a745;
}
.mcq-card .mcq__submit .mcq__submit--feedback.mcq__submit__feedback--incorrect {
display: block !important;
color: #dc3545;
}
<div class="mcq-card card shadow round border-0">
<div class="mcq__question">1. Question</div>
<div class="mcq__answers">
<ul>
<li tabindex="0">Option 1</li>
<li tabindex="0">Option 2</li>
<li tabindex="0" correct>Option 3</li>
</ul>
</div>
<div class="mcq__submit">
<button class="button-primary" aria-disabled="true" type="submit">Check</button>
<span class="d-none mcq__submit--feedback"></span>
</div>
</div>
<div class="mcq-card card shadow round border-0">
<div class="mcq__question">2. Question</div>
<div class="mcq__answers">
<ul>
<li tabindex="0">Option 1</li>
<li tabindex="0">Option 2</li>
<li tabindex="0" correct>Option 3</li>
</ul>
</div>
<div class="mcq__submit">
<button class="button-primary" aria-disabled="true" type="submit">Check</button>
<span class="d-none mcq__submit--feedback"></span>
</div>
</div>

Javascript Blur background when div is block?

I'm having a problem with bluring the background when my menu is open. I tried writing something on my own but it's not working.
function backgroundBlur() {
var menuBox = document.getElementById("mobile-menu");
var blur = document.getElementById("body");
if (menuBox.style.dsiplay = "block") {
blur.style.filter = "blur(3px)";
}
}
I think the problem can be caused by three reasons:
Typo noted by #RyanWalls
The backgroundBlur() method is not called
The display property of the menuBox is not block
I made a run to simulate this event:
let button = document.getElementById('setBlur');
let control = false;
function backgroundBlur(control) {
var menuBox = document.getElementById("mobile-menu");
var blur = document.getElementById("body");
if (menuBox.style.display === "block")
{
if(!control)
{
blur.style.filter = "blur(3px)";
button.innerHTML = 'Remove Blur';
}
else
{
blur.style.filter = "blur(0px)";
button.innerHTML = 'Add Blur';
}
}
}
button.addEventListener('click', function() {
backgroundBlur(control);
control = !control;
});
*{
margin: 0;
}
#body{
background-color: black;
}
button{
margin-top: 25px;
background-color: #4CAF50;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
width: 100%;
}
.vertical-menu {
width: 200px;
}
.vertical-menu a {
background-color: #eee;
color: black;
display: block;
padding: 12px;
text-decoration: none;
}
.vertical-menu a:hover {
background-color: #ccc;
}
.vertical-menu a.active {
background-color: #04AA6D;
color: white;
}
<div id="body">
<div id="mobile-menu" style="display: block;">
<div class="vertical-menu">
Home
Link 1
</div>
</div>
</div>
<button id="setBlur">Add Blur</button>

How to make my tags inside the input element

The tag items are appearing above the input element but I'd like them to be inside the input element. I've included the jQuery code and CSS. Can someone give me advice?
[].forEach.call(document.getElementsByClassName('tags-input'), function(el) {
let hiddenInput = document.createElement('input'),
mainInput = document.createElement('input');
tags = [];
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', el.getAttribute('data-name'));
mainInput.setAttribute('name', 'tag');
mainInput.setAttribute('id', 'tag2');
mainInput.setAttribute('placeholder', 'Contoh: akreditasi, banding, TUK mandiri')
mainInput.setAttribute('type', 'text');
mainInput.classList.add('main-input');
mainInput.addEventListener('input', function() {
let enteredTags = mainInput.value.split(',');
if (enteredTags.length > 1) {
enteredTags.forEach(function(t) {
let filteredTag = filterTag(t);
if (filteredTag.length > 0)
addTag(filteredTag);
});
mainInput.value = '';
}
});
...
.tags-input {}
.main-input {}
.tags-input .tag {
font-size: 85%;
padding: 0.5em 0.75em;
margin: 0.25em 0.1em;
display: inline-block;
background-color: #ddd;
border-radius: 10%;
}
.tags-input .tag .close::after {
content: 'x';
font-weight: bold;
margin-left: 0.75em;
display: inline-block;
transform: (1.2);
cursor: pointer;
}
.tags-input .main-input {
border: 0;
outline: 0;
}
...
<div class="field">
<label>Tag</label>
<div class="tags-input" data-name="tags-input">
</div>
...

dropdown menu with only 10 visible links

So, I am wondering if it is possible to make the dropdown menu only have 10 visible links, and the rest would be invisible. If it ain't possible, is it possible to make it so you can only se 10 and scroll down. Any suggestions?
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
function filterFunction() {
var input, filter, ul, li, a, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
div = document.getElementById("myDropdown");
a = div.getElementsByTagName("a");
for (i = 0; i < a.length; i++) {
if (a[i].innerHTML.toUpperCase().indexOf(filter) > -1) {
a[i].style.display = "";
} else {
a[i].style.display = "none";
}
}
}
.dropbtn {
background-color: #4CAF50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropbtn:hover, .dropbtn:focus {
background-color: #3e8e41;
}
#myInput {
border-box: box-sizing;
background-image: url('searchicon.png');
background-position: 14px 12px;
background-repeat: no-repeat;
font-size: 16px;
padding: 14px 20px 12px 45px;
border: none;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f6f6f6;
min-width: 230px;
overflow: auto;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown a:hover {background-color: #ddd}
.show {display:block;}
<div class="dropdown">
<button onclick="myFunction()" class="dropbtn">Dropdown</button>
<div id="myDropdown" class="dropdown-content">
<input type="text" placeholder="Search.." id="myInput" onkeyup="filterFunction()">
About
Base
Blog
Contact
Custom
Support
Tools
About
Base
Blog
Contact
Custom
Support
Tools
About
Base
Blog
Contact
Custom
Support
Tools
</div>
</div>
EDIT: New answer:
I misinterpreted the question. You can slightly modify your filter function to keep track of shown items (10) and then just call it once whenever you open the menu. This way you're showing max 10 items when opening the menu and when filtering. fiddle: https://jsfiddle.net/d3kta5sw/
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
filterFunction();
}
function filterFunction() {
var input, filter, ul, li, a, i,
elementsToShow = 10,
elementsShowing = 0;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
div = document.getElementById("myDropdown");
a = div.getElementsByTagName("a");
for (i = 0; i < a.length; i++) {
if (a[i].innerHTML.toUpperCase().indexOf(filter) > -1 &&
elementsShowing < elementsToShow) {
a[i].style.display = "";
elementsShowing++;
} else {
a[i].style.display = "none";
}
}
}
Old Answer (only works for first 10 visible items):
You can do this in pure css. Try adding the following, this will hide the 11th 'a' element and onwards:
.dropdown-content a:nth-of-type(n+11) {
display:none;
}
You could add the height values of the first 10 items and set that manually in CSS or you can use Javascript count the first 10 items and add their heights together. As it is now they all have the same height so you could do h*10 but if for some reason an item breaks to a second line your height would be off. I've updated your snipped.
I've updated the myFunction function. You'll notice I add the show class before calculating the height as offsetHeight will always return 0 if the parent is hidden.
Hiding When Clicking off Button
We can handle this with the blur event. Rather than using an attribute for the event like the onclick we're going to handle this solely with JS.
Returning to Top of Dropdown
In order to return to the top of the dropdown after you click out of the dropdown we need to use the scrollTop property. in myFunction() the last line we set scrollTop = 0 on the dropDown element which scrolls us to the top!
var btn = document.querySelector('.dropbtn');
btn.addEventListener('blur', function() {
var dd = document.querySelector('.dropdown-content');
if ( dd.classList.contains('show') ) {
dd.classList.remove('show');
}
});
function myFunction() {
var dropDown = document.getElementById('myDropdown'),
items = dropDown.children,
height = 0;
dropDown.classList.toggle('show');
for (var i = 1; i < 10; i++) {
height += items[i].offsetHeight;
}
dropDown.style.height = height + 'px';
dropDown.scrollTop = 0;
}
function filterFunction() {
var input, filter, ul, li, a, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
div = document.getElementById("myDropdown");
a = div.getElementsByTagName("a");
for (i = 0; i < a.length; i++) {
if (a[i].innerHTML.toUpperCase().indexOf(filter) > -1) {
a[i].style.display = "";
} else {
a[i].style.display = "none";
}
}
}
var btn = document.querySelector('.dropbtn');
btn.addEventListener('blur', function() {
var dd = document.querySelector('.dropdown-content');
if ( dd.classList.contains('show') ) {
dd.classList.remove('show');
}
});
.dropbtn {
background-color: #4CAF50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropbtn:hover,
.dropbtn:focus {
background-color: #3e8e41;
}
#myInput {
border-box: box-sizing;
background-image: url('searchicon.png');
background-position: 14px 12px;
background-repeat: no-repeat;
font-size: 16px;
padding: 14px 20px 12px 45px;
border: none;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f6f6f6;
min-width: 230px;
overflow: auto;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown a:hover {
background-color: #ddd
}
.show {
display: block;
}
<div class="dropdown">
<button onclick="myFunction()" class="dropbtn">Dropdown</button>
<div id="myDropdown" class="dropdown-content">
<input type="text" placeholder="Search.." id="myInput" onkeyup="filterFunction()">
About
Base
Blog
Contact
Custom
Support
Tools
About
Base
Blog
Contact
Custom
Support
Tools
About
Base
Blog
Contact
Custom
Support
Tools
</div>
</div>
CSS option:
.show{
overflow:overlay: //to hide to the other elements
height:200px; //to show desired number of elements
}
Better to use this element:
.dropdown-content

Sorting an unordered list with JavaScript

I have an unordered list.
This list has elements with checkboxes in it. If you check in a checkbox, the list element goes to the bottom of the list. when you check out one of the checkboxes, it has to go back to its original place. so far, I managed.
BUT. Take the following situation: You checked in all the checkboxes, and they seem to align according to their original place. Now, when you check out a list element, it will stuck between to other elements, which are on their place, but they are checked in. I want that in that case, the checked off box will be the first in the list. Then, when you check off the next box, that one will now be on the right place, aligning with thee unchecked boxes only.
TL;DR:
I have to make a To Do list, the 'done' elements go to the bottom, the undone elements sorted above, according to their timestamp.
http://codepen.io/balazsorban44/pen/mAvqmk
<!DOCTYPE html>
<html>
<head>
<title>A Todo List</title>
<style media="screen">
*{
margin:0;
padding: 0;
font-family: sans-serif;
color: gold;
font-weight: bolder;
font-size: 1em;
border: none;
}
body{
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
width: 100vw;
background: #333;
}
#content{
border: 1px solid #333;
padding: 20px;
border-radius: 10px;
display: flex;
flex-direction: column;
align-items: center;
background-color: gold;
box-shadow: 0px 0px 4px 4px rgba(0,0,0,.2);
}
h1,h2{
display: block;
color: #444;
font-size: 1.3em;
padding: 10px;
align-self: flex-start;
}
h2{
font-size: 1.1em
}
input{
color: #333;
padding: 5px;
border-radius: 5px;
border: 1px solid #333;
box-shadow: inset 0px 0px 3px rgba(0,0,0,.3)
}
input:focus{
outline: none
}
button{
background: #333;
border-radius: 5px;
padding: 5px 10px;
max-width: 50%;
margin-top:15px;
cursor: pointer
}
ul li{
list-style-type: none;
color:#333;
min-width: 100px;
padding: 5px;
align-self: flex-start;
}
ul li input{
margin: 0 5px
}
</style>
</head>
<body onload="loaded()">
<div id=content>
<h1>A very nice To Do list</h1>
<div>
<input id="todo-input" type="text" name="todo-input" value="" placeholder="Click + or press Enter." onkeydown="enter()">
<button type="button" name="button" onclick="addTask()">+</button>
</div>
<h2>Your todo list (done/all): <output>/</output></h2>
<ul id="tasks">
</ul>
</div>
<script type="text/javascript">
const inputArea= document.getElementById('todo-input')
const list = document.getElementById("tasks");
tasks = [];
function loaded(){
inputArea.focus();
}
function addTask(){
const newTask = document.createElement("li")
const text = document.createTextNode(inputArea.value)
const checkBox = document.createElement("input");
newTask.appendChild(text);
list.insertBefore(newTask, list.childNodes[0]);
checkBox.setAttribute("type", "checkbox");
checkBox.setAttribute("onclick", "toggleCheckBox()");
list.childNodes[0].insertBefore(checkBox, list.childNodes[0].childNodes[0]);
tasks.push({timestamp: new Date(), task: inputArea.value});
list.childNodes[0].id=tasks[tasks.length-1].timestamp.getTime();
inputArea.value ="";
inputArea.focus();
}
function enter(){
if(event.keyCode == 13) {
addTask()
}
}
function toggleCheckBox(){
const task = event.target.parentNode
if (task.style.textDecoration == '') {
task.style.textDecoration = 'line-through';
list.appendChild(task)
}
else {
task.style.textDecoration = ''
for (var i = 0; i < tasks.length; i++) {
if (task.id > list.childNodes[i].id) {
list.insertBefore(task, list.childNodes[i]);
break
}
}
}
}
</script>
</body>
</html>
Manage your tasks list in javascript and update the HTML whenever a checkbox value is changed or task is added:
var inputArea = document.getElementById('todo-input')
var list = document.getElementById("tasks");
var tasks = [];
function loaded() {
inputArea.value = "";
inputArea.focus();
}
function update(){
list.innerHTML = '';
// Sort the tasks on done boolean
tasks.sort(function(x, y) {
return (x.done === y.done)? 0 : x.done ? 1 : -1;
});
for(var i = 0; i < tasks.length; i++){
var item = tasks[i];
var task = document.createElement("li")
var text = document.createElement("span");
var checkBox = document.createElement("input");
text.innerHTML = item.task;
text.style.color = 'black';
checkBox.setAttribute("type", "checkbox");
checkBox.addEventListener("change", (function(t){
return function(){
tasks[t].done = this.checked;
console.log(tasks[t]);
update();
}
}(i)));
if(item.done){
checkBox.checked = true;
text.style.textDecoration = 'line-through'
}
task.appendChild(checkBox);
task.appendChild(text);
list.appendChild(task);
}
}
function addTask() {
tasks.push({
id: tasks.length ? tasks[tasks.length - 1].timestamp.getTime() : +new Date(),
done: false,
timestamp: new Date(),
task: inputArea.value
});
update();
loaded();
}
Codepen
I guess you have to make an object structure as
function Task(id,itemName,timeStamp,isCompleted){
this.id=id;
this.itemName=itemName;
this.time=timeStamp;
this.completed=isCompleted;
}
var Tasks=[];
while adding each task,you have to save in such format.
So whenever a task is completed ,you would set completed to true . For all the uncompleted tasks all you need to do is to sort based on their time or based on their name
Hope this helps

Categories