Close menu dropdown by clicking on it twice - javascript

I have a vertical menu with some dropdown. Actually more dropdowns can't be opened simultaneously, and, if a dropdown is open, when I click on another dropdown-button, the dropdown closes himself.
You can see a demo here.
The problem is that now, if I click twice on the same dropdown button, the first time I click the dropdown open itself (as it should be), but the second time the dropdown doesn't close itself as I want.
Furthermore, also when the dropdown is open and I click on another button on the menu the dropdown doesn't close itself.
Here you can see my code:
<div class="sidenav">
About
Services
Clients
Contact
<button class="dropdown-btn">Dropdown
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-container">
Link 1
Link 2
Link 3
</div>
<button class="dropdown-btn">Dropdown
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-container">
Link 1
Link 2
Link 3
</div>
Search
</div>
var accItem = document.getElementsByClassName('dropdown-container');
var accHD = document.getElementsByClassName('dropdown-btn');
for (i = 0; i < accHD.length; i++) {
accHD[i].addEventListener('click', toggleItem, false);
}
function toggleItem() {
var itemClass = this.nextElementSibling;
for (i = 0; i < accItem.length; i++) {
accItem[i].style.display = "none";
accHD[i].classList.remove("active");
}
if (itemClass.style.display === "none") {
this.classList.add("active");
//this.classList.toggle("active");
this.nextElementSibling.style.display = "block";
}
}
Is someone able to find where the problem is and solve it?
Thank you, regards
(Hope it is clear, if not, let me know in the comments. I do not speak English very well.)

Above your for loop try adding:
if (itemClass.style.display === "block") {
this.nextElementSibling.style.display = "none";
this.classList.remove("active");
return;
}
This will check to see if the item clicked is already open and handle setting all your values. By adding the return it will prevent the rest of the code from being executed.
Here is a fiddle with your code and answering your other question about closing them on click of one of the main links:
fiddle

Related

Dynamically generated button, not open modal Bootstrap 3

I'm using bootstrap 3 and dynamically creating buttons with a elements of the type
<a class="btn btn-primary" data-id="1" data-toggle="modal" data-target=".ver-persona">
<i class="fas fa-search"></i> Ver
</a>
My script to generate the button is:
let boton_elem = $('<a>');
boton_elem.addClass('btn');
for(let clase_btn in botones[boton].clases){
boton_elem.addClass(botones[boton].clases[clase_btn]);
}
for(let data_btn in botones[boton].datas){
boton_elem.data(botones[boton].datas[data_btn][0],botones[boton].datas[data_btn][1]);
}
if(botones[boton].icon !== undefined){
let icon_elem = $('<i>');
for(let clase_icon in botones[boton].icon.clases){
icon_elem.addClass(botones[boton].icon.clases[clase_icon]);
}
icon_elem.appendTo(boton_elem);
}
if(botones[boton].valor.length > 0){
boton_elem.html(boton_elem.html() + ' '+ botones[boton].valor);
}
if(botones[boton].listens !== undefined){
for(let listen in botones[boton].listens){
$('#'+tabla).on(botones[boton].listens[listen].evento,botones[boton].listens[listen].botones[boton].listens[listen].funcion);
}
}
boton_elem.appendTo(columna_elem);
The buttons are created perfect, the data is in it, and all parameters are applied correctly, but the .ver-persona modal not open with the generated button, all of buttons loaded with the page works perfectly and the modal opens normally.
Exist any way to refresh or reassing bootstrap listeners when a button is created? or some function to get button advised to open the modal?
I make this fiddle for reference: Live example
Thanks in advance.
For dynamic content, you can add data attributes using .attr of jQuery. So instead of boton_elem.data(boton.datas[data_btn][0],boton.datas[data_btn][1]); you can re-write it as boton_elem.attr("data-"+boton.datas[data_btn][0],boton.datas[data_btn][1]);
You can test it here

Div doesn't stay visible

I have 4 links. When I click the first link div 1 should be displayed and the other 3 hidden.
When I click link 2, div 2 should be displayed and the other 3 hidden, and so on...
What I did:
With CSS I've set the class of the 4 divs to display: none
Created 4 functions with javascript that set the display property of the correct div to block and the 3 others to none
Call the function when clicking the link
When I click a link, the div is shown for a quarter of a second but then it disappears again
CSS:
.CatDiv {
display:none;
}
JS function:
function showKadoballonnen() {
document.getElementById("Kadoballonnen").style.display = "block"
document.getElementById("Geschenkmanden").style.display = "none"
document.getElementById("Pampercadeaus").style.display = "none"
document.getElementById("OrigineleVerpakkingen").style.display = "none";
}
Calling the function:
Kadoballonnen
Div that has to be called:
<div id="Kadoballonnen" class="CatDiv">TEST</div>
function showKadoballonnen(e) {
e.preventdefault();
document.getElementById("Kadoballonnen").style.display = "block";
document.getElementById("Geschenkmanden").style.display = "none";
document.getElementById("Pampercadeaus").style.display = "none";
document.getElementById("OrigineleVerpakkingen").style.display = "none";
}
.CatDiv {
display: none;
}
Kadoballonnen
<div id="Kadoballonnen" class="CatDiv">TEST</div>
<div id="Geschenkmanden" class="CatDiv">TEST</div>
<div id="Pampercadeaus" class="CatDiv">TEST</div>
<div id="OrigineleVerpakkingen" class="CatDiv">TEST</div>
What am I missing?
All is easier than you think. In your tag you got "href" with empty parameter. It makes your page reloading while pressing on it.
So all you should do is to write "#" as a parameter.
Kadoballonnen
You should avoid empty href attribute on a link. Use a button instead.
If it still does not work, attach your method to window object. Also, I don't recommend this approach, you should handle it in your Javascript by targetting at your DOM elements using an ID for example and adding your event listener from here.
document.getElementById('myelement').addEventListener('click', showKadoBallonnen);
You have a few errors in your code, and you also need to stop your link (<a>) firing.
On your link, add return false;:
Kadoballonnen
<!-- ^ Also, add href="#" so you don't have an empty href -->
Also, add semicolons to the end of each line of your javascript:
document.getElementById("Kadoballonnen").style.display = "block";
document.getElementById("Geschenkmanden").style.display = "none";
document.getElementById("Pampercadeaus").style.display = "none";
document.getElementById("OrigineleVerpakkingen").style.display = "none";
I was running into this problem while writing some coffeescript in a rails application. Another answer helped me.
The solution is the event.preventDefault() as shown below:
app/views/posts/index.html.erb:
<%= link_to "Some link", '#', id: 'some-link' %>
<div class="some-div">
<h4>Some list</h4>
<ul id='some-list'>
<li>cats</li>
<li>and</li>
<li>dogs</li>
</ul>
</div>
app/assets/javascripts/posts.coffee:
$(document).on 'turbolinks:load', ->
$('#some-link').click (event) ->
event.preventDefault()
$('#some-list').toggle()
I managed to make it working: https://jsfiddle.net/ke81koj6/
function showKadoBallonnen() {
document.getElementById("one").style.display = "block";
document.getElementById("two").style.display = "none";
document.getElementById("three").style.display = "none";
document.getElementById("four").style.display = "none";
}
EDIT
Edited the fiddle and now works with the press on a button. It's better to use a button than an anchor with a empty href.
HTML:
<button id="button" onclick="showKadoBallonnen()">click here</button>
JS:
document.getElementById("button").onclick = showKadoBallonnen;

How to update all values in an array? -JS/Jquery

I'm trying to update an array when clicking on the li tag. I've been testing, testing, and unable to come up with a solution.
I have two tabs: The "Create" tab opens a container that allows you to insert paragraphs, the "Home" tab opens another container containing a "Select paragraph" button.
Problem
It won't update the values of the array when I do it for the second time. I.e., if I switch between the tabs and go on select mode again to select/deselect, it will not update the new selection, instead I get the same selection from the first time.
I've created an example so you can look at it and if there is a better way to accomplish this (which I know there is) then be my guest. Link is below the next paragraph.
Instructions
In order to select a paragraph, first you need to add a paragraph which is created on the fly, then you switch to "Home" section, click on the "Select paragraph" button, this takes you to the "Create" section on select mode. To select/deselect, click on any paragraph. When you select a paragraph, it stores its position using jQuery - index() in the "storeClass" array. Once you're done selecting paragraphs then you exit the select mode by clicking "Ok" button and it switches to "Home" section, but let's say you want to create another paragraph then you click on "Create" tab, create the paragraph, switch to "Home" tab, go on select mode and select again and switch between tabs and you will see just the first selection you made on the first time.
Here is the same example: http://jsfiddle.net/7mbhnvas/8/
HTML
<ul class="tab">
<li><a class="paragraph-tab">Create</a></li>
<li><a class="select-tab">Home</a></li>
</ul>
<div class="wrap">
<div class="create-para-cont">
<h3>Create a paragraph</h3>
<ul class="para-results">
</ul>
<div class="para-tool">
<p><textarea class="textarea"></textarea></p>
<button type="button" class="create-para-button">Create paragraph</button>
<div>
<button type="button" class="select-ok-button">OK</button>
</div>
</div>
</div>
<div class="select-para-cont">
<h3>Select Mode</h3>
<p><button type="button" class="select-para-button">Select paragraph</button></p>
</div>
</div>
jQuery
$('ul.tab li a:first').addClass('tab-active');
$('.create-para-cont').addClass('cont-active');
$('.create-para-button').on('click', function(){
$('.create-para-cont').addClass('cont-active');
var parent = $('.para-results');
var child = $('<li></li>');
var p = $('<p></p>');
var textarea = $('.textarea').val();
if($('.create-para-cont').hasClass('cont-active')){
p.text(textarea);
child.append(p);
parent.append(child);
} else {
return false
}
});
var storeClass = [];
$('.select-para-button').on('click', function(){
$('.create-para-cont').addClass('cont-select');
if($('.para-results li').length >= 1){
$('.textarea, .create-para-button').hide();
$('.select-para-cont').hide();
$('.select-tab').removeClass('tab-active');
$('.create-para-cont').show();
$('.paragraph-tab').addClass('tab-active');
$('.select-ok-button').show();
for ( var i = 0; i < storeClass.length; i = i + 1 ) {
$('.para-results').each(function( index ) {
$( this ).find( "li:eq("+ storeClass[ i ] +")" ).addClass('p-selected');
});
}
}
});
$('ul.tab li').on('click','a', function(){
if($(this).hasClass('paragraph-tab')){
$('.para-results').children('li').removeClass('p-selected');
$('.select-para-cont').hide();
$('.select-tab').removeClass('tab-active');
$('.create-para-cont').show();
$('.paragraph-tab').addClass('tab-active');
} else {
$('.create-para-cont').removeClass('cont-active');
$('.create-para-cont').hide();
$('.paragraph-tab').removeClass('tab-active');
$('.select-para-cont').show();
$('.select-tab').addClass('tab-active');
}
});
$('ul.para-results').on('click','li', function(){
if($('.create-para-cont').hasClass('cont-select')){
$(this).toggleClass('p-selected');
var selected = $('.p-selected ');
var pSelected = selected.parent().children().index(this);
storeClass.push( pSelected );
} else {
return false;
}
});
$('.select-ok-button').on('click', function(){
if($('.create-para-cont').hasClass('cont-select')){
$('.create-para-cont').removeClass('cont-select');
$('.create-para-cont').removeClass('cont-active');
$('.create-para-cont').hide();
$('.paragraph-tab').removeClass('tab-active');
$('.select-para-cont').show();
$('.select-tab').addClass('tab-active');
}
});
I would reset storeClass to a blank array when the 'OK' button is clicked, and then re-push all the correct values into it in that same click handler:
$('.select-ok-button').on('click', function(){
if($('.create-para-cont').hasClass('cont-select')) {
storeClass = []; // make it blank
$('.p-selected').each(function() {
storeClass.push($(this).index()); // push each one into the array
});
....
}
});
Then your click handler of ul.para-results would look like this:
$('ul.para-results').on('click','li', function(){
if($('.create-para-cont').hasClass('cont-select')){
$(this).toggleClass('p-selected');
} else {
return false;
}
});
Here's an updated Fiddle

Display : None/Block Style Tab Menu Creation with Buttons and Javascript

function tab_menu(){
if (buttonObject.value == value){
document.getElementById("div1").style.display = "block";
}
}
i was trying when click to buttons check Button Value and show a div based on Button's Value and hide others divs it should show just one div at same time. I wonder there is a javascript Master who can solve this problem.
SCRIPT:
function tabmenu(buttonObject){
var value = buttonObject.value
var target = document.getElementById(value);
if(target) {
var siblings = target.parentNode.getElementsByTagName("DIV");
for(i=0;i<siblings.length;i++){
siblings[i].style.display = "none";
}
target.style.display = "block";
}
}
HTML:
<div>
<div id="tab1">Tab1</div>
<div id="tab2">Tab2</div>
<div id="tab3">Tab3</div>
</div>
<button onclick="tabmenu(this);" value="tab1">Tab1</button>
<button onclick="tabmenu(this);" value="tab2">Tab2</button>
find the tab to activate (assuming value = tab.id)
find the parent and hence it's siblings (assuming they are DIVs)
hide the siblings
show the target
You can see it working here: http://jsfiddle.net/4rWdQ/

Jquery Expand Collapse all divs on Click

I know this has been asked a thousand times but I'm still having trouble figuring it out. I have a simple according following this tutorial and I'm trying to add an "expand/collapse all" link. I have found a way to expand all but can't figure out how to collapse them. The problem with a slideToggle() solution is if I open one then click the link it will close/open all of them but the one that was previoiusly active.
I set up a jsFiddle here.
Here is an overview of the code:
HTML:
<h2 class="acc_trigger">Div 1</h2>
<div class="acc_container">
<div class="block"> Yay content!</div>
</div>
<h2 class="acc_trigger">Div 2</h2>
<div class="acc_container">
<div class="block">More Content, Score!</div>
</div>
<h2 class="acc_trigger">Div 3</h2>
<div class="acc_container">
<div class="block">Even More Content</div>
</div>
Expand/Collapse All
JS:
jQuery(document).ready(function($) {
//Set default open/close settings
$('.acc_container').hide(); //Hide/close all containers
//On Click
$('.acc_trigger').click(function(){
$('.acc_trigger').removeClass('active').next().slideUp();
//Remove all "active" state and slide up the immediate next container
$(this).toggleClass('active').next().slideDown();
return false; //Prevent the browser jump to the link anchor
});
$('.acc_expand-all').click(function(){
//expand all on click
$('.acc_trigger').addClass('active').next().slideDown();
return false;
});
});
You have to check in your expand/collapse handler to see how many are open, etc., something like this (updated fiddle):
$('.acc_expand-all').click(function(){
var all = $('.acc_trigger'),
active = all.filter('.active');
if (all.length && all.length === active.length) {
// All open; close them
all.removeClass('active').next().slideUp();
}
else {
// At least some are closed, open all
all.not('.active').addClass('active').next().slideDown();
}
return false;
});
Regarding your question in the comments, you can check to see whether you should be in "exclusive" mode or not by checking how many are open and whether the clicked one is open, e.g. (updated fiddle):
$('.acc_trigger').click(function(){
var $this = $(this),
thisActive = $this.hasClass('active'),
active;
// If this one is active, we always just close it.
if (thisActive) {
$this.removeClass('active').next().slideUp();
}
else {
// Is there just one active?
active = $('.acc_trigger.active');
if (active.length === 1) {
// Yes, close it
active.removeClass('active').next().slideUp();
}
// Open this one
$this.addClass('active').next().slideDown();
}
});

Categories