How to target a div with a same ID - javascript

I currently have some ASP.Net code that builds an output and then displays it through a string literal. The idea is that for every Receipt, there is a 'view more' button which toggles extra information that is display: none; to start with. I tried to use the eq() method to attempt to find which one I wanted to toggle because I am doing that inside the ul. My current code is this:
$("#btn-expand").click(function () {
var ldx = $("#list li .active").index(); // Get the list number so we know what ID to work with
var idx = $("#expand").next().index(); // Get the next ID index point
// Check that it isn't going negative
if (idx == -1 || ldx == -1) {
// If it is, reset ldx
ldx = 0;
idx = 0;
}
$("#expand").eq(ldx).toggle(); // Toggle that one
console.log(ldx);
});
The first button works fine and console.log shows 0 however, all the others do not show anything. A sample of my HTML looks like this:
<ul id="list">
<li class="active">
Something <br />
Something Again <br />
<span id="btn-expand">[View more]</span>
<div id="expand">
Something hidden
</div>
</li>
This <br />
Shows <br />
<span id="btn-expand">[View more]</span>
<div id="expand">
This is hidden until toggled
</div>
<li></li>
</ul>
There is a lot more li elements in the ul but that is how it is structured. I am also using <span class="btn" id="btn-next">Next</span> to loop through each li in the ul so I am really confused why the same method for doing it with the `#expand' won't work.
If anyone could point me in the right direction, I'd be appreciated. Thanks.
$(document).ready(function() {
$("#btn-next").click(function() {
var $list = $("#list li");
var idx = $(".active").removeClass("active").next().index();
if (idx == -1) {
idx = 0;
}
$list.eq(idx).addClass("active");
});
$("#btn-prev").click(function() {
var $list = $("#list li");
var idx = $(".active").removeClass("active").prev().index();
if (idx == -1) {
idx = 0;
}
$list.eq(idx).addClass("active");
});
$("#btn-expand").click(function() {
// Get the list number so we know what ID to work with
var ldx = $("#list li .active").index();
// Get the next ID index point
var idx = $("#expand").next().index();
// Check that it isn't going negative
if (idx == -1 || ldx == -1) {
// If it is, reset ldx
ldx = 0;
idx = 0;
}
// Toggle that one
$("#expand").eq(ldx).toggle();
console.log(ldx);
});
});
#list {
list-style: none;
}
.active {
display: block;
}
#btn-expand {
cursor: pointer;
font-size: 9px;
margin-left: 10px;
}
#expand {
display: none;
}
li {
display: none;
}
.btn {
background: none;
padding: 10px;
border: 1px solid #000;
margin-left: 50px;
cursor: pointer;
}
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<ul id="list">
<li class="active">
Something here
<br />Something here again
<span id="btn-expand"> [View More] </span>
<br />
<br />
<span id="expand">
This is hidden, shh..
</span>
</li>
<li>
You can see this
<br />Toggling shouldn't effect me
<span id="btn-expand"> [View More] </span>
<br />
<br />
<span id="expand">
But toggling should effect me!
</span>
</li>
</ul>
<span class="btn" id="btn-prev">Prev</span> - <span class="btn" id="btn-next">Next</span>

id should be unique in same document, replace the duplicate ones by general class, r.g :
<ul id="list">
<li class="active">
Something <br />
Something Again <br />
<span class="btn-expand">[View more]</span>
<div class="expand">
Something hidden
</div>
</li>
This <br />
Shows <br />
<span class="btn-expand">[View more]</span>
<div class="expand">
This is hidden until toggled
</div>
<li>
</li>
</ul>
Then replace id selector # in you script by class selector . :
$(".btn-expand").click(function() {
// Get the list number so we know what ID to work with
var ldx = $("#list li .active").index();
// Get the next ID index point
var idx = $(".expand").next().index();
// Check that it isn't going negative
if (idx == -1 || ldx == -1) {
// If it is, reset ldx
ldx = 0;
idx = 0;
}
// Toggle that one
$(".expand").eq(ldx).toggle();
console.log(ldx);
});
You could use just next() instead of all the code in your event :
$(this).next(".expand").toggle();
//OR
$(this).next().toggle();
Hope this helps.
$(".btn-expand").click(function() {
$(this).next(".expand").toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="list">
<li class="active">
Something <br />
Something Again <br />
<span class="btn-expand">[View more]</span>
<div class="expand">
Something hidden
</div>
</li>
<li>
This <br />
Shows <br />
<span class="btn-expand">[View more]</span>
<div class="expand">
This is hidden until toggled
</div>
</li>
</ul>

Change id's to classes and all you need then is:
$(".btn-expand").click(function() {
$(this).next().toggle();
$(this).text(function(_, oldText){
return oldText.indexOf('More') === -1 ? 'View More' :'View Less';
})
});

$(document).ready(function() {
$("#btn-next").click(function() {
var $list = $("#list li");
var idx = $(".active").removeClass("active").next().index();
if (idx == -1) {
idx = 0;
}
$list.eq(idx).addClass("active");
});
$("#btn-prev").click(function() {
var $list = $("#list li");
var idx = $(".active").removeClass("active").prev().index();
if (idx == -1) {
idx = 0;
}
$list.eq(idx).addClass("active");
});
$(".btn-expand").click(function() {
// Toggle
$(this).next().toggle();
});
});
#list {
list-style: none;
}
.active {
display: block;
}
#btn-expand {
cursor: pointer;
font-size: 9px;
margin-left: 10px;
}
li {
display: none;
}
.btn {
background: none;
padding: 10px;
border: 1px solid #000;
margin-left: 50px;
cursor: pointer;
}
.expand-inner {
display:inline-block;
width:100%;
}
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<ul id="list">
<li class="active">
Something here
<br />Something here again
<span class="btn-expand"> [View More] </span>
<span style="display:none;">
<div class="expand-inner">This is hidden, shh..</div>
</span>
</li>
<li>
You can see this
<br />Toggling shouldn't effect me
<span class="btn-expand"> [View More] </span>
<span style="display:none;">
<div class="expand-inner">But toggling should effect me!</div>
</span>
</li>
</ul>
<span class="btn" id="btn-prev">Prev</span> - <span class="btn" id="btn-next">Next</span>

Related

make same actions for all elements inside ul li

I have an unordered list in which every list item has a span and inside of it a picture.
I'm trying to set as background-image of every span, the image that their inner img block contains and then put the opacity of that image block to 0.
Here's the code I wrote. The problem is that this seems not work correctly, even if I coomment the line where I set the background image, I still can see the pictures, while I wouldn't be supposed of, since the opacity of the img block is set to 0. That makes me think that the code isn't setting the background image correctly.
Can you help me understand what I am doing wrong?
thank you!
var myUl = $('.my-ul');
[...myUl.children].forEach(childLi => {
const span_list = childLi.querySelector('span');
const img_list = childLi.querySelector('img');
var path_picture = img_list.src;
$(span_list).css("background-image", "url(${path_picture})");
$(span_list).css("background-size", "contain");
img_list.style.opacity = 0;
});
.my-ul li span {
display: block;
width: 200px;
height: 200px;
}
.my-ul li img {
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<ul class="my-ul">
<li>
<span>
<img src="https://www.trudellanimalhealth.com/sites/default/files/documents/tmdi-cat-athma-concern_2x.png" />
</span>
</li>
<li>
<span>
<img src="https://img.webmd.com/dtmcms/live/webmd/consumer_assets/site_images/article_thumbnails/other/cat_relaxing_on_patio_other/1800x1200_cat_relaxing_on_patio_other.jpg" />
</span>
</li>
<li>
<span>
<img src="https://undark.org/wp-content/uploads/2020/02/GettyImages-1199242002-1-scaled.jpg" />
</span>
</li>
</ul>
There are two issues:
$(".myul") returns a jquery collection, which as a .children() function (not a property) but this is not an array, so can't be iterated using [...].forEach
"url(${path_picture})" looks like it uses string interpolation, so needs to use backtick ` not quote "
Giving:
//var myUl = $('.my-ul');
var myUl = document.querySelector(".my-ul");
[...myUl.children].forEach(childLi => {
const span_list = childLi.querySelector('span');
const img_list = childLi.querySelector('img');
var path_picture = img_list.src;
$(span_list).css("background-image", `url(${path_picture})`);
$(span_list).css("background-size", "contain");
img_list.style.opacity = 0;
});
.my-ul li span {
display: block;
width: 200px;
height: 200px;
}
.my-ul li img {
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<ul class="my-ul">
<li>
<span>
<img src="https://www.trudellanimalhealth.com/sites/default/files/documents/tmdi-cat-athma-concern_2x.png" />
</span>
</li>
<li>
<span>
<img src="https://img.webmd.com/dtmcms/live/webmd/consumer_assets/site_images/article_thumbnails/other/cat_relaxing_on_patio_other/1800x1200_cat_relaxing_on_patio_other.jpg" />
</span>
</li>
<li>
<span>
<img src="https://undark.org/wp-content/uploads/2020/02/GettyImages-1199242002-1-scaled.jpg" />
</span>
</li>
</ul>
The alternative is to use jquery
var myUl = $('.my-ul');
myUl.children().each((i, e) => {
var path_picture = $("img", e).attr("src");
$("span", e)
.css("background-image", `url(${path_picture})`)
.css("background-size", "contain");
$("img", e).hide();
});
.my-ul li span {
display: block;
width: 200px;
height: 200px;
}
.my-ul li img {
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<ul class="my-ul">
<li>
<span>
<img src="https://www.trudellanimalhealth.com/sites/default/files/documents/tmdi-cat-athma-concern_2x.png" />
</span>
</li>
<li>
<span>
<img src="https://img.webmd.com/dtmcms/live/webmd/consumer_assets/site_images/article_thumbnails/other/cat_relaxing_on_patio_other/1800x1200_cat_relaxing_on_patio_other.jpg" />
</span>
</li>
<li>
<span>
<img src="https://undark.org/wp-content/uploads/2020/02/GettyImages-1199242002-1-scaled.jpg" />
</span>
</li>
</ul>
Not sure how you handle changing styles in vanilla js or jquery, but it could be this img_list.style.opacity = 0; is wrong. Maybe img_list is a group of elements/nodes so it won't work?

JS/jQuery events/data lost when altering cloned DOM element

I am pretty new to JS and jQuery and trying to build a plugin for some form controls to dynamically add and remove elements containing inputs and values which should be stored in a database later on.
I am using a list of elements while the first of those elements serves as a template. In preparation to the cloning, a button triggering on click and containing some data is added to remove newly added or already existing elements. Those elements mainly contain input fields with IDs relating to an index.
This issue happens only when altering the HTML which is copied to create a new element in the DOM.
Here is a fiddle displaying the behavior:
$('ul').sortable({
handle: '.handle',
});
$('<button>remove</button>')
.appendTo($('li'))
.click(function() {
$(this).closest('li').remove();
})
const $template = $('ul>li').first().clone(true);
$('<button>another one</button>')
.appendTo($('#add-btn-holder'))
.click(function() {
$clone = $template.clone(true).html(function(i, html) {
return html.replace(/id-\d-/g, 'id-X-');
});
$('ul').append($clone);
});
ul {
list-style-type: none;
}
li {
background: #f1f1f1;
margin: .4em;
}
[id^="id-X-"] {
background: #ddd;
}
input {
height: 3em;
}
.handle {
cursor: move;
font-size: 1.2em;
padding: 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<ul>
<li id="id-0-holder">
<span class="handle"><b>=</b></span>
<input id="id-0-field_0" value="val_0_0" />
<input id="id-0-field_1" value="val_0_1" />
</li>
<li id="id-2-holder">
<span class="handle"><b>=</b></span>
<input id="id-1-field_0" value="val_1_0" />
<input id="id-1-field_1" value="val_1_1" />
</li>
<li id="id-2-holder">
<span class="handle"><b>=</b></span>
<input id="id-2-field_0" value="val_2_0" />
<input id="id-2-field_1" value="val_2_1" />
</li>
</ul>
<div id="add-btn-holder">
</div>
After adding an new element and altering the html, the event handlers and data will be lost. For simplicity I did not include any data but the click event to remove the new row will be lost.
Commenting out line 17 in the script code (string#replace) leaves all events and data intact.
I can store the data values in a temporary variable before altering the html and re-apply them afterwards. I don't know how to deal with events though and hopefully there is an easier solution without temporary variables.
Unfortunately I didn't find anything useful here because most headers sound promising but are solved with a simple $.clone(true) or $.clone(true, true) (which I am already using).
My real world code is a bit more complex. The remove-button is holding the corresponding to-be-removed item within a data attribute and the query is also build around data, therefore I pretty much have to rely on those values. Unfortunately the classes and IDs may alter why I cannot query with conventional methods.
If this was already asked somewhere else, feel free to guide me there, I wasn't able to find anything useful :(
Don't update the HTML, modify the attributes directly.
When you update the HTML, it's reparsed from scratch and any dynamic modifications to the DOM are lost.
$('ul').sortable({
handle: '.handle',
});
$('<button>remove</button>')
.appendTo($('li'))
.click(function() {
$(this).closest('li').remove();
})
const $template = $('ul>li').first().clone(true);
$('<button>another one</button>')
.appendTo($('#add-btn-holder'))
.click(function() {
$clone = $template.clone(true);
$clone.find("[id^=id-]").attr('id', function(i, id) {
return id.replace(/^id-\d+-/, 'id-X-');
});
$('ul').append($clone);
});
ul {
list-style-type: none;
}
li {
background: #f1f1f1;
margin: .4em;
}
[id^="id-X-"] {
background: #ddd;
}
input {
height: 3em;
}
.handle {
cursor: move;
font-size: 1.2em;
padding: 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<ul>
<li id="id-0-holder">
<span class="handle"><b>=</b></span>
<input id="id-0-field_0" value="val_0_0" />
<input id="id-0-field_1" value="val_0_1" />
</li>
<li id="id-2-holder">
<span class="handle"><b>=</b></span>
<input id="id-1-field_0" value="val_1_0" />
<input id="id-1-field_1" value="val_1_1" />
</li>
<li id="id-2-holder">
<span class="handle"><b>=</b></span>
<input id="id-2-field_0" value="val_2_0" />
<input id="id-2-field_1" value="val_2_1" />
</li>
</ul>
<div id="add-btn-holder">
</div>
Just .clone() the .last() <li> and increment #id and value by 1. Delegate the click event by using the .on() method. BTW I shortened the #ids to save myself some unneeded typing, feel free to use whatever you prefer.
$('ul').sortable({
handle: '.handle',
});
$('<button>Remove</button>')
.appendTo('li')
.on('click', function() {
if ($('li').length === 1) {
return;
} else {
$(this).closest('li').remove();
}
});
let idx;
$('<button>Add</button>')
.appendTo('.add-box')
.on('click', function() {
const $template = $('ul>li').last();
let prev = Number($template[0].id.split('-').pop());
idx = prev + 1;
let $clone = $template.clone(true, true);
$clone[0].id = `i-${idx}`;
$clone.find('input').each(function(i) {
$(this)[0].id = `i-${idx}-f_${i}`;
$(this).val(`v_${idx}_${i}`);
});
$('ul').append($clone);
});
ul {
list-style-type: none;
}
li {
background: #f1f1f1;
margin: .4em;
}
[id^="id-X-"] {
background: #ddd;
}
input {
height: 3em;
}
.handle {
cursor: move;
font-size: 1.2em;
padding: 1em;
}
<ul>
<li id="i-0">
<label class="handle"><b>=</b></label>
<input id="i-0-f_0" value="v_0_0" />
<input id="i-0-f_1" value="v_0_1" />
</li>
<li id="i-1">
<label class="handle"><b>=</b></label>
<input id="i-1-f_0" value="v_1_0" />
<input id="i-1-f_1" value="v_1_1" />
</li>
<li id="i-2">
<label class="handle"><b>=</b></label>
<input id="i-2-f_0" value="v_2_0" />
<input id="i-2-f_1" value="v_2_1" />
</li>
</ul>
<div class="add-box"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
So with some help from your answers I came up with this solution to dynamically handle all attributes matching the regex. thanks.
$('<button>remove</button>')
.appendTo($('li'));
$('<button>another one</button>')
.appendTo($('#add-btn-holder'));
// remove-button handler
$('li').on('click', 'button', function() {
$(this).closest('li').remove();
});
const $template = $('li').first().clone(true, true);
// add-button handler
$('#add-btn-holder').on('click', function() {
$clone = $template.clone(true, true);
var re = /id-\d-/,
repl = 'id-X-';
$clone.find('*').each(function() {
var $el = $(this);
$($el.get(0).attributes).each(function() {
$el.prop(this.name, this.value.replace(re, repl));
})
});
$('ul').append($clone);
});
ul {
list-style-type: none;
}
li {
background: #f1f1f1;
margin: .4em;
}
[id^="id-X-"] {
background: #ddd;
}
input {
height: 3em;
}
.handle {
cursor: move;
font-size: 1.2em;
padding: 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<ul>
<li id="id-0-holder">
<input id="id-0-field_0" value="val_0_0" />
<input id="id-0-field_1" value="val_0_1" />
</li>
<li id="id-2-holder">
<input id="id-1-field_0" value="val_1_0" />
<input id="id-1-field_1" value="val_1_1" />
</li>
<li id="id-2-holder">
<input id="id-2-field_0" value="val_2_0" />
<input id="id-2-field_1" value="val_2_1" />
</li>
</ul>
<div id="add-btn-holder">
</div>

Javascript tabs using data attributes rather than IDs to link button and tab

I'm wanting to create a variation of Javascript tabs using data attributes rather than IDs to link the tab and the content.
Here's how it should work:
Clicking a <button class="tab" data-tab-trigger="1"> adds a class of is-active and removes any is-active classes from all other button elements
The value of data-tab-trigger matches the value of data-tab-content on the corresponding <div class="tab-content" data-tab-content="1"> and should add a class of is-open to it
The is-active class highlights the active tab and the is-open class shows the related tab content
Here's the JS I'm currently working which isn't working as expected:
var tabTriggerBtns = document.querySelectorAll('.tabs li button');
tabTriggerBtns.forEach(function(tabTriggerBtn, index){
tabTriggerBtn.addEventListener('click', function(){
var tabTrigger = this;
var tabTriggerData = tabTrigger.getAttribute('data-tab-trigger');
var tabContent = document.querySelector('.tab-content');
var currentTabData = document.querySelector('.tab-content[data-tab-content="' + tabTriggerData + '"]').classList.add('is-open');
if(tabContent !== currentTabData) {
tabContent.classList.toggle('is-open');
}
if(tabTrigger.classList.contains('is-active')) {
tabTrigger.classList.remove('is-active');
}
else {
tabTriggerBtn.classList.remove('is-active');
tabTrigger.classList.add('is-active');
}
});
});
Here's a Codepen with my ongoing script: https://codepen.io/abbasarezoo/pen/752f24fc896e6f9fcce8b590b64b37bc
I'm having difficulty finding what's going wrong here. I'm relatively comfortable writing jQuery, but quite raw when it comes to vanilla JS so any help would be very much appreciated.
One of your main issue is in this line:
tabContent !== currentTabData
You may use dataset in order to access data attributes.
Moreover, you may simplify your code in few steps:
remove classess
add classess
The snippet:
var tabTriggerBtns = document.querySelectorAll('.tabs li button');
tabTriggerBtns.forEach(function(tabTriggerBtn, index){
tabTriggerBtn.addEventListener('click', function(){
var currentTabData = document.querySelector('.tab-content[data-tab-content="' + this.dataset.tabTrigger + '"]');
// remove classess
document.querySelector('.tab-content.is-open').classList.remove('is-open');
document.querySelector('.tabs li button.is-active').classList.remove('is-active');
// add classes
currentTabData.classList.add('is-open');
this.classList.add('is-active');
});
});
* {
margin: 0;
padding: 0;
}
body {
display: flex;
}
.tabs {
width: 25%;
border: 2px solid red;
}
button.is-active {
background-color: red;
}
.tab-content__outer {
width: 75%;
}
.tab-content {
display: none;
}
.tab-content.is-open {
display: block;
background-color: yellow;
}
<ul class="tabs">
<li>
<button class="tab is-active" data-tab-trigger="1">First</button>
</li>
<li>
<button class="tab" data-tab-trigger="2">Second</button>
</li>
<li>
<button class="tab" data-tab-trigger="3">Third</button>
</li>
</ul>
<div class="tab-content__outer">
<div class="tab-content is-open" data-tab-content="1">
First
</div>
<div class="tab-content" data-tab-content="2">
Second
</div>
<div class="tab-content" data-tab-content="3">
Third
</div>
</div>

jquery dynamic filter list

I'm trying to make a filter list on keypress. For example if I write in input "It", the elements that doesn't match this input value are hidden. I'm not sure if the idea I have with code below does the job. Any tips will be highly appreciated!
$('ul li ul li').addClass('displayNone');
var geInputValue = $('input').val();
var getInputLength = $('input').length;
function sortDynamically(){
$('input').on('keypress', function(){
for(var i=0; i < getInputLength; i++){
if(getInputValue === $('li').text){
// remove everything that doesnt match input value
$('li').siblings().addClass('displayNone');
}
else{
$('li').siblings().removeClass('displayNone');
});
}
sortDynamically();
ul, li{
list-style-type: none;
margin: 0;
padding: 0;
}
.displayNone{
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" />
<ul class="list">
<li>Item</li>
<li>Product
<ul>
<li>Bike</li>
</ul>
</li>
<li>About</li>
</ul>
This code filters based on what you type. If there is nothing in the text input then everything is shown.
$('input').on('keypress keyup', function(){
var value = $(this).val().toLowerCase();
if (value != '') {
$('.list > li').each(function () {
if ($(this).text().toLowerCase().indexOf(value) > -1) {
$(this).removeClass('displayNone');
} else {
$(this).addClass('displayNone');
}
});
} else {
$('.list > li').removeClass('displayNone');
}
});
ul, li{
list-style-type: none;
margin: 0;
padding: 0;
}
.displayNone{
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" />
<ul class="list">
<li>Item</li>
<li>Product
<ul>
<li>Bike</li>
</ul>
</li>
<li>About</li>
</ul>
jQuery provides filters and javascript implements toLowerCase() and includes() methods that you can use to improve your code
<body>
<style>
.displayNone
{
display: none;
}
</style>
<input type="text" id="input-filter"/>
<ul class="list">
<li>Item</li>
<li>Product
<ul>
<li>Bike</li>
</ul>
</li>
<li>About</li>
</ul>
<script>
var items = $('ul.list li');
$('#input-filter').on('input', function ($event)
{
items.addClass('displayNone').filter(function (item)
{
return $(this).text().toLowerCase().includes($($event.target).val().toLowerCase());
}).removeClass('displayNone');
});
</script>
</body>

How to make accordion in pure javascript and html

I want this list to behave as an accordion. I have to do this in pure javascript without using jQuery or other external libraries. I am not allowed to adjust the HTML code shown below.
<ul class="accordion">
<li>Apple
<ul>
<li>abc</li>
<li>xyz</li>
<li>pqr</li>
</ul>
</li>
<li>Apple1</li>
<li>Apple2</li>
<li>Apple3</li>
<li>Apple4</li>
</ul>
I have javascript code below provided by #Ruud, which is showing accordion menu but it does not have animation effect. I want animation effect with only one item activated at a time
window.getTopUL = function() {
var uls = document.getElementsByTagName('UL');
for (var i = 0; i < uls.length; i++) {
if (uls[i].className == 'accordion') return uls[i];
}
return null;
};
window.getChild = function(li, tag) {
return li.getElementsByTagName(tag)[0];
};
window.toggleDisplay = function(s) {
s.display = s.display == 'none' ? 'block' : 'none';
};
window.setEventHandlers = function(topUL) {
if (topUL) {
var lis = document.getElementsByTagName('LI');
for (var i = 0; i < lis.length; i++) {
var ul = getChild(lis[i], 'UL');
if (ul) {
ul.style.display = 'none';
getChild(lis[i], 'A').onclick = function() {
toggleDisplay(getChild(this.parentNode, 'UL').style);
return false;
}
}
}
}
};
setEventHandlers(getTopUL());
window.getTopUL = function() {
var uls = document.getElementsByTagName('UL');
for (var i = 0; i < uls.length; i++) {
if (uls[i].className == 'accordion') return uls[i];
}
return null;
};
window.getChild = function(li, tag) {
return li.getElementsByTagName(tag)[0];
};
window.toggleDisplay = function(s) {
s.display = s.display == 'none' ? 'block' : 'none';
};
window.setEventHandlers = function(topUL) {
if (topUL) {
var lis = document.getElementsByTagName('LI');
for (var i = 0; i < lis.length; i++) {
var ul = getChild(lis[i], 'UL');
if (ul) {
ul.style.display = 'none';
getChild(lis[i], 'A').onclick = function() {
toggleDisplay(getChild(this.parentNode, 'UL').style);
return false;
}
}
}
}
};
setEventHandlers(getTopUL());
<ul class="accordion">
<li>Apple
<ul>
<li>abc
</li>
<li>xyz
</li>
<li>pqr
</li>
</ul>
</li>
<li>Apple1
</li>
<li>Apple2
</li>
<li>Apple3
</li>
<li>Apple4
</li>
</ul>
You can do it with simple html and css also
/* Clean up the lists styles */
ul.accordion {
list-style: none;
margin: 0;
padding: 0;
}
/* Hide the radio buttons */
/* These are what allow us to toggle content panes */
ul.accordion label + input[type='radio'] {
display: none;
}
/* Give each content pane some styles */
ul.accordion li {
background-color: #CCCCCC;
border-bottom: 1px solid #DDDDDD;
}
/* Make the main tab look more clickable */
ul.accordion label {
background-color: #666666;
color: #FFFFFF;
display: block;
padding: 10px;
}
ul.accordion label:hover {
cursor: pointer;
}
/* Set up the div that will show and hide */
ul.accordion div.content {
overflow: hidden;
padding: 0 10px;
display: none;
}
/* Show the content boxes when the radio buttons are checked */
ul.accordion label + input[type='radio']:checked + div.content {
display: block;
}
<ul class='accordion'>
<li>
<label for='cp-1'>Content pane 1</label>
<input type='radio' name='a' id='cp-1' checked='checked'>
<div class='content'>
<p>content to be displayed</p>
</div>
</li>
<li>
<label for='cp-2'>Content pane 2</label>
<input type='radio' name='a' id='cp-2'>
<div class='content'>
<p>content to be displayed</p>
</div>
</li>
<li>
<label for='cp-3'>Content pane 3</label>
<input type='radio' name='a' id='cp-3'>
<div class='content'>
<p>content to be displayed</p>
</div>
</li>
<li>
<label for='cp-4'>Content pane 4</label>
<input type='radio' name='a' id='cp-4'>
<div class='content'>
<p>content to be displayed</p>
</div>
</li>
<li>
<label for='cp-5'>Content pane 5</label>
<input type='radio' name='a' id='cp-5'>
<div class='content'>
<p>content to be displayed</p>
</div>
</li>
</ul>

Categories