How to run Jscript without postback - javascript

I'm trying to build an "accordion" style collapsible div into my web page as described here on w3c schools...
accordion description
I've got most of it working - my code is this:
ASP:
<div class="col-md-4">
<button class="accordion">Section 1</button>
<div class="content">
<asp:Table ID="Consumable_table" runat="server">
<asp:TableHeaderRow>
<asp:TableHeaderCell>
<h2>
<u>Consumable Stock</u>
</h2>
</asp:TableHeaderCell>
</asp:TableHeaderRow>
</asp:Table>
</div>
</div>
CSS:
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;}
.active, .accordion:hover {
background-color: #ccc;}
.content {
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;}
And I've added the following Jscript:
$(document).ready(function () {
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function () {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
return false;
});
}
});
The code seems to work fine and when I click the Accordion element it expands - But it then seems to post back and the accordion collapses again and doesn't display.
My question is how can I have it expand and stay expanded as described in the tutorial. I've seen a number of answers here and on various sites that suggests "return false" might be enough.
Does this have anything to do with the ASP table inside the div?

The dafault behaviour of the HTML button is to submit the form when clicked (its type is submit by default). All you need to do is to add type="button" attribute to the element, like this:
<button class="accordion" type="button">Section 1</button>
That should resolve the problem - it indicates that the button is just a simple clickable button, without any special action.
This answer also covers it: <button> vs. <input type="button" />. Which to use?

There are two ways,
By default the button behavior like submit button so postback will happen. If you want to prevent postback you can use below code.
<button class="accordion" onclick="return false;">Section 1</button>
You can use type attribute to prevent submit behavior.
<button type="button" class="accordion">Section 1</button>

Related

this in the DOM and event listeners

Could some one please tell me how to refactor the JavaScript without "this" in a way that explains the use of "this" in the browser context? (please don't answer the following question with jQuery solutions)
I have passed e (event) into the callback function and implemented:
e.target.classList.toggle("active");
var panel = e.target.nextElementSibling;
What I have implemented has worked. However I want to know to what benefit/why you would use "this" in the context shown, it doesn't seem as declarative as e.target. Is this a function binding issue?
(other snippet related questions below snippet)
I have taken the below snippet from W3schools, it is used for creating an accordion menu:
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
/* Toggle between adding and removing the "active" class,
to highlight the button that controls the panel */
this.classList.toggle("active");
/* Toggle between hiding and showing the active panel */
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
});
}
/* Style the buttons that are used to open and close the accordion panel */
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
text-align: left;
border: none;
outline: none;
transition: 0.4s;
}
/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
.active, .accordion:hover {
background-color: #ccc;
}
/* Style the accordion panel. Note: hidden by default */
.panel {
padding: 0 18px;
background-color: white;
display: none;
overflow: hidden;
}
<button class="accordion">Section 1</button>
<div class="panel">
<p>Lorem ipsum...</p>
</div>
<button class="accordion">Section 2</button>
<div class="panel">
<p>Lorem ipsum...</p>
</div>
<button class="accordion">Section 3</button>
<div class="panel">
<p>Lorem ipsum...</p>
</div>
Could some one please explain the relationship between the loop and the event listener?
The way I understand it, I would expect that:
every time the DOM is altered/reloads =>
the loop runs =>
adding an event listener on each html collection element=>
if HTML element clicked == true (or) the event is fired
the class is toggled to active
the following if statement is executed and styles may or may not be applied inline to the html element.
This seems like a computationally expensive method of adding event listeners.
Is the above statement that I have written correct if not exactly what is happening?
Is there a more efficient way of writing the event listener loop snippet?
I.e. using event bubbling on a containing element perhaps?
Here's a simple HTML layout:
<main>
<div class='A'></div>
<section></section>
<div class='B'></div>
<section></section>
<div class='C'></div>
</main>
Here's the JavaScript using a programming paradigm called Event Delegation:
document.querySelector('main').addEventListener('click', eventHandler);
Because the majority of the events bubble (click bubbles), the event listener should be registered to an ancestor tag (in this example that would be <main>) of the tags you want to control via events (in this example it's .A, .B, and .C). Now the event handler:
function eventHandler(event) {
const listener = event.currentTarget; // or `this` points to `<main>`
const clicked = event.target; // This is the tag user actually clicked
....
We need to control exactly what reacts to a click and what doesn't react when clicked. We can use if/if else or switch() or even a ternary to delegate events to what we want while excluding what we don't want. Continuing within eventHandler(e)...
....
// All <section>s and even <main> is excluded
if (clicked.matches('div')) {
if (clicked.matches('.A')) {
clicked.style.background = 'red';
}
if (clicked.matches('.C') {
clicked.style.background = 'blue';
}
}
// .B was never mentioned with any specific intructions so it's also excluded.
}
The example below is pretty much the same delegation scheme as the previous explination except with an additional CSS trick with adjacent sibling combinator:
.accordion.active+.panel {
display: block;
}
Whenever a button is .active, the .panel that follows it will disappear.
document.body.addEventListener("click", togglePanel);
function togglePanel(e) {
const clk = e.target;
if (clk.matches('.accordion')) {
clk.classList.toggle("active");
}
};
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
text-align: left;
border: none;
outline: none;
transition: 0.4s;
}
.active,
.accordion:hover {
background-color: #ccc;
}
.panel {
padding: 0 18px;
background-color: white;
display: none;
overflow: hidden;
}
.accordion.active+.panel {
display: block;
}
<button class="accordion">Section 1</button>
<div class="panel">
<p>Lorem ipsum...</p>
</div>
<button class="accordion">Section 2</button>
<div class="panel">
<p>Lorem ipsum...</p>
</div>
<button class="accordion">Section 3</button>
<div class="panel">
<p>Lorem ipsum...</p>
</div>

Hiding a popup using javascript

I have a page which has multiple CSS only pop-ups implemented.
The popups work fine & close when the 'X' is clicked. However I wish for them to be closed when user clicks anywhere on the page. For that I implemented a short javascript code, which does close them on any click, but they dont open again (until page is refreshed). I am guessing the state is being saved as "none". How do i fix this?
The code:
window.onclick = function(event) {
if (event.target.className === "overlay") {
event.target.style.display = "none";
}
}
<div class="editbutton">
<a class="btn btn-link" href="#popupedit">Edit</a></div>
<div id="popupedit" class="overlay">
<div class="popup10">
<a class="close" href="#"></a>
........
</div>
</div>
<div class="editbutton">
<a class="btn btn-link" href="#popupedit1">Edit</a></div>
<div id="popupedit1" class="overlay">
<div class="popup10">
<a class="close" href="#"></a>
........
</div>
</div>
<div class="editbutton">
<a class="btn btn-link" href="#popupedit2">Edit</a></div>
<div id="popupedit2" class="overlay">
<div class="popup10">
<a class="close" href="#"></a>
........
</div>
</div>
The CSS code:
.overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
transition: opacity 500ms;
visibility: hidden;
opacity: 0;
z-index: 2000;
}
.overlay:target {
visibility: visible;
opacity: 1;
}
.popup10 {
margin: 70px auto;
padding: 20px;
background: #fff;
border-radius: 5px;
width: 50%;
position: relative;
transition: all 5s ease-in-out;
}
.popup10 h2 {
margin-top: 0;
color: #333;
font-family: Tahoma, Arial, sans-serif;
}
.popup10 .close {
position: absolute;
top: 8px;
right: 10px;
transition: all 200ms;
font-size: 30px;
font-weight: bold;
text-decoration: none;
color: #333;
}
.popup10 .close:hover {
color: #06D85F;
}
.popup10 .content {
max-height: 30%;
overflow: auto;
}
Here is the code you should update in javascript.
window.onclick = function(event) {
if (event.target.className === "btn btn-link") {
document.getElementById('popupedit').style.display = "block";
}
if (event.target.className === "overlay") {
event.target.style.display = "none";
}
}
Why the popup is not opened again is that you set the overlay part display: none when clicking the part, but no process to set back to display: block.
So you should set the popup layout back to display: block again when clicking the edit button.
Please see the result working : https://jsfiddle.net/254xmyv7/3/
Hope this would be helpful. :)
Although #Kevin Lee's code works, adding a long list of elements with getElementById isn't recommended. If you remove one of the popup elements or add one, you have to go back and manually change the code. You should consider instead looping through all the existing elements with the class 'overlay' and applying the property with a single line of code rather than 10 separate ones:
window.onclick = function(event) {
var popups;
if (event.target.className === "btn btn-link") {
popups = document.getElementsByClassName('overlay');
console.log(popups[i]);
for (let i = 0; i < popups.length; i++) {
popups[i].style.display = "block";
}
}
if (event.target.className === "overlay") {
event.target.style.display = "none";
}
};
This will save you a lot of time and potentially aggravation down the road. Working fiddle here: https://jsfiddle.net/Vanadu/u7n30Lra/24/
In your javascript, the window element gets the click, finds the element with the class 'overlay' and sets its style.display property to 'none'. Then, when you click the element to open the popup, that click is 'bubbling up' the DOM tree to the window, and the window then sets the display property to 'none' again before the popup can open.
One approach might be to prevent the click on the elements from 'bubbling up' and use the same class on the window level to control the popup that you use on the element level.
https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation

Close all open drop downs and consolidate code if possible

What I need to be able to do is to have the text drop downs close when another is selected so that I do not end up with a bunch of drop downs open on the page at the same time.
I have two text dropdowns that will be used one after the other alternating on a page. In other words accordion1, accordion2, accordion1, accordion2 and so on the reason I have accordion1 and accordion2 is that with my limited experience it is the only way I could figure out change the button color so the list could alternate colors. It would be nice to consolidate the code, but I can live with the extra code if need be.
Here is the code for accordion1
var acc = document.getElementsByClassName("accordion1");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
/* Toggle between adding and removing the "active" class,
to highlight the button that controls the panel */
this.classList.toggle("active1");
/* Toggle between hiding and showing the active panel */
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
});
}
var acc = document.getElementsByClassName("accordion2");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
/* Toggle between adding and removing the "active" class,
to highlight the button that controls the panel */
this.classList.toggle("active1");
/* Toggle between hiding and showing the active panel */
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
});
}
.accordion1 {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
text-align: left;
border: none;
outline: none;
transition: 0.4s;
}
.accordion2 {
background-color: #8461E8;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
text-align: left;
border: none;
outline: none;
transition: 0.4s;
}
/* Add a background color to the button if it is clicked on (add the
.active class with JS), and when you move the mouse over it (hover) */
.active1,
.accordion1:hover {
background-color: #ccc;
}
/* Style the accordion panel. Note: hidden by default */
.panel1 {
padding: 0 18px;
background-color: white;
display: none;
overflow: hidden;
}
.accordion1:after {
content: '\02795';
/* Unicode character for "plus" sign (+) */
font-size: 13px;
color: #777;
float: right;
margin-left: 5px;
}
.accordion2:after {
content: '\02795';
/* Unicode character for "plus" sign (+) */
font-size: 13px;
color: #777;
float: right;
margin-left: 5px;
}
.active1:after {
content: "\2796";
/* Unicode character for "minus" sign (-) */
}
<Section><button class="accordion1"><h3>Alternators and regulators</h3>
</button>
<div id="accordion1-div" class="panel1">
<p>First group of words go here></div>
</Section>
<Section><button class="accordion2"><h3>Batteries and Inverters</h3>
</button>
<div id="accordion-div" class="panel1">
<p>Second set of words go here.</p>
</div>
</Section>
<Section><button class="accordion1"><h3>AC and DC Panels </h3>
</button>
<div id="accordian1-div" class="panel1">
<p>Third set of words reusing "accordion1 go here"</p>
</div>
</Section>
Any help or resources to figure out the needed code would be greatly appreciated.
Question 1 — "How do I not end up with a bunch of drop downs open on the page at the same time":
You close all dropdowns before opening another one. You can also create css rules to display or hide the dropdown. This way, it will be easier to find the currently active dropdown. See code below.
Question 2 — "How can I make the list alternate colors"
You can add more than one class to an element. Simply create color classes and add them to the right elements. See code below.
Notes:
Use the CSS selectors instead of JavaScript to show/hide the panel
Element h3 is not allowed as child of element button. Do it the other way round.
Use the same JavaScript code and CSS for all accordions.
Edit (scrollIntoView)
I added code to automatically scroll the window so that the active tab is visible.
It works only on Chrome, Firefox and Opera. Use this polyfill iamdustan/smoothscroll to use it in other browsers. See compatibility here and all functions here.
// Query all accordions
var accordions = document.querySelectorAll('.accordion');
for (var i = 0; i < accordions.length; i++) {
accordions[i].addEventListener('click', function() {
// Get the currently active accordion
var active = document.querySelector('.accordion.active');
// If there is one, deactivate it
if (active) {
active.classList.remove('active');
}
// Activate the new accordion, if it's not the one you just deactivated
if (active !== this) {
this.classList.add('active');
// Use scrollIntoView to adjust the window scroll position to show the content.
this.scrollIntoView({
behavior: 'smooth'
});
}
});
}
.accordion .header button {
text-align: left;
padding: 18px;
background: transparent;
border: none;
outline: none;
cursor: pointer;
width: 100%;
color: #444;
width: 100%;
transition: 0.4s;
}
/* Set the color according to the modifier class */
.accordion.gray button {
background-color: #eee;
}
.accordion.purple button {
background-color: #8461E8;
}
.accordion.active button,
.accordion button:hover {
background-color: #ccc;
}
.accordion .panel {
padding: 0 18px;
background-color: white;
display: none;
overflow: hidden;
}
/* Show the panel if the accordion is active */
.accordion.active .panel {
display: block;
}
.accordion button:after {
content: '\02795';
font-size: 13px;
color: #777;
float: right;
margin-left: 5px;
}
.accordion.active button:after {
content: "\2796";
}
<section>
<!-- Each accordion is wrapped by a div with the class 'accordion' -->
<!-- 'accordion' is the component, 'gray' is the color modifier -->
<div class="accordion gray">
<!-- h3 can contain a button -->
<h3 class="header">
<button>Alternators and regulators</button>
</h3>
<div class="panel">
<p>
First group of words go here.<br/> I'm afraid I just blue myself. No… but I'd like to be asked! Michael! It's called 'taking advantage.' It's what gets you ahead in life. Now, when you do this without getting punched in the chest, you'll have
more fun.
</p>
</div>
</div>
</section>
<section>
<!-- Use the 'purple' modifier class here -->
<div class="accordion purple">
<h3 class="header">
<button>Batteries and Inverters</button>
</h3>
<div class="panel">
<p>
Second set of words go here.<br/> Steve Holt! I don't criticize you! And if you're worried about criticism, sometimes a diet is the best defense. That's why you always leave a note! Well, what do you expect, mother? I don't criticize you! And
if you're worried about criticism, sometimes a diet is the best defense.<br/>
<br/> Across from where? As you may or may not know, Lindsay and I have hit a bit of a rough patch. Now, when you do this without getting punched in the chest, you'll have more fun. No… but I'd like to be asked!
</p>
</div>
</div>
</section>
<section>
<div class="accordion gray">
<h3 class="header">
<button>AC and DC Panels
</button>
</h3>
<div class="panel">
<p>
Third set of words go here.<br/> That's why you always leave a note! Not tricks, Michael, illusions. As you may or may not know, Lindsay and I have hit a bit of a rough patch. It's called 'taking advantage.' It's what gets you ahead in life.<br/>
<br/> Say goodbye to these, because it's the last time! First place chick is hot, but has an attitude, doesn't date magicians. I'm afraid I just blue myself. I'm afraid I just blue myself. I'm afraid I just blue myself.
</p>
</div>
</div>
</section>

Using javascript for multiple elements [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I would like to handle several elements that require a specific functionality in our development stage for toggle-like buttons that open and close divs. I say toggle-like because it isn't your standard toggle setup.
The code I have works for a single instance of the buttons and container. Now I need to learn how to apply this to a dozen more which should function independent of each other.
This fiddle shows four examples where the first CSS button is the only one working.
https://jsfiddle.net/e2fexbqp/12/
This is the code that is creating the working example of a single block - two buttons and our div - which should be functional for several other button / div areas.
HTML
<a class="button" id="open">Open</a>
<div id="click-drop" style="display:none">
<h2>Hello World</h2>
<p>You can see me! I'm open! Type your code below.</p>
<textarea></textarea>
<p><a class="button" id="close" style="display:none">Close</a></p>
</div>
Javascript
var open = document.getElementById("open");
var close = document.getElementById("close");
function show(target) {
document.getElementById(target).style.display = 'block';
}
function hide(target) {
document.getElementById(target).style.display = 'none';
}
function hideButton() {
var x = document.getElementById("open");
x.style.display = "none";
var x = document.getElementById("close");
x.style.display = "";
}
function showButton() {
var x = document.getElementById("open");
x.style.display = "";
var x = document.getElementById("close");
x.style.display = "none";
}
open.onclick = function() {show('click-drop');hideButton()}
close.onclick = function() {hide('click-drop');showButton()
I would like something clean and concise as well as unobtrusive.
This demo is pure JavaScript as it is indicated in the tags and implied by the provided code in the question. It has only one eventListener and multiple event.targets BTW, unique ids can only be given to one element. You cannot have multiple ids with the same value. So you'll notice I used only classes no ids.
Advantages
Pure JavaScript and no dependencies on plugins.
Cross-browser with modern browsers.
Having to use only one eventListener is very memory efficient.
It determines exactly which button is clicked without creating an array, or NodeList to iterate through in a loop.
Disadvantages
If you need to be compatible with IE9, then classList has to be replaced with className.
The HTML layout must be in strict pattern. Key elements must be positioned in a predetermined sequence. That's not much of a problem if you have a habit of making organized patterns in markup.
Step by step description is commented in the source.
FIDDLE
SNIPPET
// Reference the parent element
var box = document.querySelector('.box');
// add an eventListener to parent
box.addEventListener('click', toggleBtn, false);
function toggleBtn(event) {
/* This will prevent the <a>nchors from
behaving like normal anchors which
jump from one location to another
*/
event.preventDefault();
// event.target is the element that was clicked (.open/.close .button)
// event.currentTarget is the element that listens for an event (.box)
if (event.target != event.currentTarget) {
var clicked = event.target;
/* If the clicked element has .open class
find the sibling element that was before it and
show it by adding .show class and removing .hide
Then hide clicked element.
*/
if (clicked.classList.contains('open')) {
var drop = clicked.previousElementSibling;
drop.classList.remove('hide');
drop.classList.add('show');
clicked.classList.remove('show');
clicked.classList.add('hide');
} else {
/* Else find clicked parent and hide it
and then show the parent's sibling that is after it.
*/
var drop = clicked.parentElement;
var open = drop.nextElementSibling;
drop.classList.remove('show');
drop.classList.add('hide');
open.classList.remove('hide');
open.classList.add('show');
}
}
/* This prevents the bubbling phase from continuing
up the event chain and triggering any unnecessary
eventListeners
*/
event.stopPropagation();
}
* {
/* Prefix no longer needed */
box-sizing: border-box;
}
.box {
/* Just for demo */
border: 1px dashed red;
}
.button {
text-decoration: none;
font-size: 13px;
line-height: 26px;
height: 28px;
width: 48px;
margin: 0;
padding: 1px;
cursor: pointer;
border-width: 1px;
border-style: solid;
-webkit-appearance: none;
/* Prefix no longer needed for years */
border-radius: 3px;
text-align: center;
}
.click-drop {
border: solid 1px;
border-radius: 3px;
padding: 10px 25px;
}
.hide {
display: none;
}
.show {
display: block;
}
.button.show {
display: inline-block;
}
.close {
display: block;
}
<!--[The order in which elements are positioned is important which will be evident when you review the JavaScript]-->
<!--.box is the 'ancestor/parent' element and event.currentTarget-->
<section class="box">
<h1>Header Content</h1>
<!--Each .click-drop is initially hidden hence it has .hide as a class as well-->
<div class="click-drop hide">
<!--All descendants/children of each .click-drop inherits display:none prop/val from .click-drop.hide-->
<p>Header style</p>
<textarea></textarea>
<a class="close button">Close</a>
</div>
<!--Each .open.button follows it's corresponding .click-drop-->
<a class="open button show">CSS</a>
<div class="click-drop hide">
<p>Header content</p>
<textarea></textarea>
<a class="close button">Close</a>
</div>
<a class="open button show">HTML</a>
<h1>Footer Content</h1>
<div class="click-drop hide">
<p>Footer style</p>
<textarea></textarea>
<a class="close button">Close</a>
</div>
<a class="open button show">CSS</a>
<div class="click-drop hide">
<p>Footer content</p>
<textarea></textarea>
<a class="close button">Close</a>
</div>
<a class="open button show">HTML</a>
</section>
Use event target to style the individual element that got clicked.
anchors = doc.getElementsByClassName("button");
for (var i = 0; i < anchors.length; i++) {
anchors[i].addEventListener("click", function(e){
e.target.classList.toggle('hide');
});
}
Let's explain some points :
IDs in HTML, in a page, shall be unique.
Using classes and jQuery you can achieve this pretty much easily.
I added a span over all the "open button + its corresponding zone" that I set a "zone" class
I put an "open" class to all open links.
I put a "close" class to all close links.
I registered the click for '.zone .open' elements so they hide themselves and show the contained DIV in their parent.
I registered the click for '.zone .close' elements so they hide the DIV under '.zone' element containing them and show the '.open' link under them.
So here is what I've done :
https://jsfiddle.net/e2fexbqp/13/
$(document).ready(function() {
$('.zone .open').click(function() {
$(this).hide();
$(this).parent().find('div').show();
});
$('.zone .close').click(function() {
var parent = $(this).parents('.zone');
parent.children('div').hide();
parent.children('a.open').show();
});
});
.button {
display: inline-block;
text-decoration: none;
font-size: 13px;
line-height: 26px;
height: 28px;
margin: 0;
padding: 0 10px 1px;
cursor: pointer;
border-width: 1px;
border-style: solid;
-webkit-appearance: none;
-webkit-border-radius: 3px;
border-radius: 3px;
white-space: nowrap;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.zone div {
border: solid 1px;
border-radius: 3px;
padding: 10px 25px;
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h1>Header Content</h1>
<span class="zone">
<a class="button open">CSS</a>
<div>
<p>Header style</p>
<textarea></textarea>
<p><a class="button close">Close</a></p>
</div>
</span>
<span class="zone">
<a class="button open">HTML</a>
<div>
<p>Header content</p>
<textarea></textarea>
<p><a class="button close">Close</a></p>
</div>
</span>
<h1>Footer Content</h1>
<span class="zone">
<a class="button open">CSS</a>
<div>
<p>Footer style</p>
<textarea></textarea>
<p><a class="button close">Close</a></p>
</div>
</span><span class="zone">
<a class="button open">HTML</a>
<div>
<p>Footer content</p>
<textarea></textarea>
<p><a class="button close">Close</a></p>
</div>
</span>

How to make Accordion(CSS+javascript) work?

I have this code so far:
var acc;
acc = document.getElementByClassName('button');
acc.onclick = function()
{
this.classList.toggle("active");
this.nextElementSibling.classList.toggle("show");
}
div.panel {
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: 0.6s ease-in-out;
opacity: 0;
}
div.panel.show {
opacity: 1;
max-height: 500px;
}
.button{
display:block;
height:431px;
width:100%;
font-family: Futura, 'Trebuchet MS', Arial, sans-serif;
color:black;
font-size:80px;
margin:0 auto;
background-color:transparent;
border-style:none;
}
.button:hover, .button.active{
background: url('pcluj.jpg') ;
background-size: cover;
}
<center><button class="button" id="button">CLUJ</button></center>
<div class="panel">
<p>Lorem ipsum...</p>
</div>
Right now it doesn't work and I don't know why!! The div doesn't show up when I press the first button. What is the solution? Please help!
It looked like my post was only code so I had to write this in order to be able to post ...........
One way to achieve it if you are only supporting Chrome and Safari or Mobile Devices is to use the HTML5 details element and style it with CSS. You won't even need JavaScript.
Read on: http://dipaksblogonline.blogspot.in/2014/09/html5-details-element.html
Basic Demo: http://jsfiddle.net/8mthoj5g/1/
<details open>
<summary>Click me to toggle more information</summary>
<div>The details element is used as a widget to show/hide additional information.</div>
</details>
Another way is to use the onclick as attribute on the button - it will work -
<button class="button" id="button1" onclick="someFunc()">CLUJ</button>
Demo: https://jsfiddle.net/Lp05m27p/
Jquery
$("#button").click(function(){
var divPnl = $('.panel');
$(this).toggleClass("active");
divPnl.toggleClass("show");
});
fiddle link
javascript:
window.onload = function(){
var acc;
acc = document.getElementById('button');
acc.onclick = function()
{
this.classList.toggle("active");
this.nextElementSibling.classList.toggle("show");
}
}
html:
<button class="button" id="button">CLUJ</button>
<div class="panel">
<p>Lorem ipsum...</p>
</div>
You have several errors in your Javascript code. You are trying to assign a click event handler to an element before it actually exists in the DOM. You are also referring to the div that you are trying to show incorrectly. See below a working JavaScript code with comments and your mistakes fixed.
// You need to make sure that the button element exists before trying to attach a click handler to it.
// You can do that by running the function when the onload event is triggered.
window.onload = function () {
var acc;
acc = document.getElementsByClassName('button')[0];
// You have errors in the above line, "s" is missing in getElement/s/ByClassName, also that method returns an array, not an element, so you need to add [0] at the end.
acc.onclick = function()
{
this.classList.toggle("active");
// this.nextElementSibling.classList.toggle("show");
// This does not work because <button> is in <center> and the panel div is therefore not its sibling.
// there are many ways to reference the panel div, eg:
var panel= document.getElementsByClassName("panel")[0];
panel.classList.toggle("show");
}
}
Ideally you would use an established method or existing library for an accordion such as an Unordered List but what you've got already can be made to work with a few minor changes:
Firstly, use querySelectorAll to select the .button element. This returns a NodeList.
Iterate through the NodeList using a basic for-loop and add an event listener to each item which calls a method to toggle the .button's active class.
Rather than find the children of the active .button we simply use CSS2's Adjacent Sibling Selector to select the .buttons next sibling .panel
E.G:
// Get the .buttons
var buttons = document.querySelectorAll('.button');
// For each button
for (i = 0; i < buttons.length; ++i) {
//add an event listener
buttons[i].addEventListener("click", onButtonClick, false);
}
// On button click...
function onButtonClick(){
this.classList.toggle("active");
}
div.panel {
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: 0.6s ease-in-out;
opacity: 0;
}
/*
div.panel.show {
opacity: 1;
max-height: 500px;
}
*/
.button{
display:block;
height:50px;
width:100%;
font-family: Futura, 'Trebuchet MS', Arial, sans-serif;
color:black;
font-size:20px;
margin:0 auto;
background-color:transparent;
border-style:none;
outline:none;
}
.button:hover, .button.active{
background:#eee url('http://lorempixel.com/100/20/') ;
background-size: cover;
}
#button1:hover, #button1.active{
background-image:url('http://lorempixel.com/100/20/');
}
#button2:hover, #button2.active{
background-image:url('http://lorempixel.com/200/20/');
}
/* adjacent sibling selector to select a .panel next to an button.active: */
.button.active + .panel {
opacity: 1;
max-height: 500px;
}
<button class="button" id="button1">ONE</button>
<div class="panel">
<p>Lorem ipsum one...</p>
</div>
<button class="button" id="button2">TWO</button>
<div class="panel">
<p>Lorem ipsum two...</p>
</div>

Categories

Resources