How to make accordion in pure javascript and html - javascript

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>

Related

Get the value of checkboxes in a specific section using javascipt

I have a page that contain different section these section appear when the user click on li an active class is added to the section and then this section appear
each section contain a box with checkboxes and a link to another page when i click on this link i should store the value of the checkboxes for the section active only to print them later
all the code work fine but my problem is that i only can have the checkbox value for the first section that contain active class by defaul
how can i solve that please?
/*Put active class on li click for section*/
let tabs = document.querySelectorAll(".nav li");
let tabsArray = Array.from(tabs);
let section = document.querySelectorAll(".section");
let sectionArray = Array.from(section);
tabsArray.forEach((ele) => {
ele.addEventListener("click", function (e) {
tabsArray.forEach((ele) => {
ele.classList.remove("active");
});
e.currentTarget.classList.add("active");
sectionArray.forEach((sec) => {
sec.classList.remove("active");
});
document.querySelector('#' + e.currentTarget.dataset.cont).classList.add("active");
});
});
/*put the check box value in localstorage to print them later*/
let printBtn = document.querySelector(".active .btn-print");
let terms = document.querySelectorAll(".active input[type='checkbox']");
let termsValChecked = [];
let termsValUnChecked = [];
printBtn.addEventListener("click", function (e) {
localStorage.removeItem("termschecked");
localStorage.removeItem("termsunchecked");
for (let i = 0; i < terms.length; i++) {
if (terms[i].checked == true) {
termsValChecked.push(terms[i].value);
} else {
termsValUnChecked.push(terms[i].value);
}
}
window.localStorage.setItem("termschecked", JSON.stringify(termsValChecked));
window.localStorage.setItem("termsunchecked", JSON.stringify(termsValUnChecked));
});
.box {
display: flex;
align-items: center;
}
section {
display: none;
}
section.active {
display: block;
}
.nav {
list-style:none;
display: flex;
align-items: center;
}
.nav li {
padding: 20px;
background-color: #ccc;
margin-left: 2px;
cursor: pointer;
}
<ul class="nav">
<li data-cont="r1">1</li>
<li data-cont="r2">2</li>
<li data-cont="r3">3</li>
</ul>
<section class="section section-one active" id="r1">
<h3>Section 1</h3>
<div class="box">
<input type="checkbox" value="test1">
<p>test1</p>
</div>
<div class="box">
<input type="checkbox" value="test2">
<p>test2</p>
</div>
<div class="print">
Print
</div>
</section>
<section class="section section-two" id="r2">
<h3>Section 2</h3>
<div class="box">
<input type="checkbox" value="test3">
<p>test3</p>
</div>
<div class="box">
<input type="checkbox" value="test4">
<p>test4</p>
</div>
<div class="print">
Print
</div>
</section>
<section class="section section-three" id="r3">
<h3>Section 3</h3>
<div class="box">
<input type="checkbox" value="test5">
<p>test5</p>
</div>
<div class="box">
<input type="checkbox" value="test6">
<p>test6</p>
</div>
<div class="print">
Print
</div>
</section>
querySelectorAll returns a static NodeList, i.e. the list will reflect the state at invocation and won't update if the page later changes.
The following line runs when you initialize your page:
let terms = document.querySelectorAll(".active input[type='checkbox']");
And that's why you always capture the first section in local storage.
You need to move this line inside your click handler so that you enumerate the checkboxes inside the .active section at that time.
Remove the Attribute ".change" from your selector on line 23
simply change
let terms = document.querySelectorAll(".active input[type='checkbox']");
to
let terms = document.querySelectorAll("input[type='checkbox']");

JS loop to add event listeners not working during one condition for second element

I am working on a piece of code to toggle the visibility of some UL items by clicking corresponding buttons by toggling a class on the UL that changes opacity/height to 0 (so that I can also apply transitions). The second element doesn't work when the first is toggled to be invisible. The onclick event does not register.
The code works when the button and h3 are not styled to appear on the same line, and breaks when I try to use flex, float, or inline to position the two elements side by side. Is there a method that I can use to position them as such and still retain full functionality?
const buttons = document.getElementsByClassName("toggle");
const lists = document.getElementsByClassName("list");
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function() {
toggle(i);
})
};
function toggle(i) {
if (lists[i].classList.contains("hide")) {
lists[i].classList.remove("hide");
} else {
lists[i].classList.add("hide");
}
}
<div id="sidebar">
<div class="side">
<div class="header">
<h3>Protein</h3>
<button class="toggle"></button>
</div>
<div>
<ul class="list">
<li class="fi">Beef</li>
<li class="fi">Fish</li>
<li class="fi">Lamb</li>
<li class="fi">Pork</li>
<li class="fi">Poultry</li>
<li class="fi">Shellfish</li>
<li class="fi">Vegetarian</li>
</ul>
</div>
</div>
<div class="side">
<div class="header">
<h3>Cuisine</h3>
<button class="toggle"></button>
</div>
<ul class="list">
<li class="fi">African</li>
<li class="fi">American</li>
<li class="fi">Asian</li>
<li class="fi">British</li>
<li class="fi">Cajun Creole</li>
<li class="fi">Carribean</li>
<li class="fi">Eastern European</li>
<li class="fi">Show More</li>
</ul>
</div>
</div>
<style>
.header{
display: flex;
align-items: center;
}
.hide {
height: 0;
opacity: 0;
margin: 0;
}
</style>
gif of the issue
As the response for user120242 says you are overlaying the below side class div you can resolve it by adding your <div class="side"> element a overflow: hidden; style to avoid overflowing the below div, so try this:
If you want to place elements next to each other you need working with flexbox as #user120242 said.
const buttons = document.getElementsByClassName("toggle");
const lists = document.getElementsByClassName("list");
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function() {
toggle(i);
})
};
function toggle(i) {
if (lists[i].classList.contains("hide")) {
lists[i].classList.remove("hide");
} else {
lists[i].classList.add("hide");
}
}
.side {
overflow: hidden;
}
<div id="sidebar">
<div class="side">
<div class="header">
<h3>Protein</h3>
<button class="toggle"></button>
</div>
<div>
<ul class="list">
<li class="fi">Beef</li>
<li class="fi">Fish</li>
<li class="fi">Lamb</li>
<li class="fi">Pork</li>
<li class="fi">Poultry</li>
<li class="fi">Shellfish</li>
<li class="fi">Vegetarian</li>
</ul>
</div>
</div>
<div class="side">
<div class="header">
<h3>Cuisine</h3>
<button class="toggle"></button>
</div>
<ul class="list">
<li class="fi">African</li>
<li class="fi">American</li>
<li class="fi">Asian</li>
<li class="fi">British</li>
<li class="fi">Cajun Creole</li>
<li class="fi">Carribean</li>
<li class="fi">Eastern European</li>
<li class="fi">Show More</li>
</ul>
</div>
</div>
<style>
.header{
display: flex;
align-items: center;
}
.hide {
height: 0;
opacity: 0;
margin: 0;
}
</style>
I've added pointer-events: none so it doesn't intercept mouse events and it works, but you should probably find another way to deal with it. I don't know what you're doing for animations, code, nor the rest of the styling, so this might be the best solution depending on what you're doing.
I've added a "Show Problem" button to show what's happening. The list is (repainted in a new stacking context triggered by opacity) and covering the second list.
Another solution is to set the position style. So adding position: relative to the .hide { position: relative } will also work
Scroll to bottom to read a detailed description of the cause (opacity style).
// show problem
test.onclick=()=>{
if (lists[0].classList.contains("hide1")) {
lists[0].classList.remove("hide1");
} else {
lists[0].classList.add("hide1");
}
}
const buttons = document.getElementsByClassName("toggle");
const lists = document.getElementsByClassName("list");
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function() {
toggle(i);
})
};
function toggle(i) {
if (lists[i].classList.contains("hide")) {
lists[i].classList.remove("hide");
} else {
lists[i].classList.add("hide");
}
}
.header { display:flex; flex-direction:row }
.header{
display: flex;
align-items: center;
}
.hide {
height: 0;
opacity: 0;
margin: 0;
pointer-events: none /* don't intercept mouse events */
}
/* show problem */
.hide1 {
height: 0;
margin: 0;
opacity: 0.5;
border: 1px solid red;
}
.hide1 * {
border: 1px solid blue;
}
<button id="test">Show Problem</button>
<div id="sidebar">
<div class="side">
<div class="header">
<h3>Protein</h3>
<button class="toggle"></button>
</div>
<div>
<ul class="list">
<li class="fi">Beef</li>
<li class="fi">Fish</li>
<li class="fi">Lamb</li>
<li class="fi">Pork</li>
<li class="fi">Poultry</li>
<li class="fi">Shellfish</li>
<li class="fi">Vegetarian</li>
</ul>
</div>
</div>
<div class="side">
<div class="header">
<h3>Cuisine</h3>
<button class="toggle"></button>
</div>
<ul class="list">
<li class="fi">African</li>
<li class="fi">American</li>
<li class="fi">Asian</li>
<li class="fi">British</li>
<li class="fi">Cajun Creole</li>
<li class="fi">Carribean</li>
<li class="fi">Eastern European</li>
<li class="fi">Show More</li>
</ul>
</div>
</div>
<style>
.header{
display: flex;
align-items: center;
}
.hide {
height: 0;
opacity: 0;
margin: 0;
pointer-events: none
}
</style>
The problem is related to the z-index stacking context being triggered by the opacity style due to re-render: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
You can prove this by setting opacity: 0.9 on the second list's header, so that the second list's header renders in the same context layer, and see that you will then be able to click the button.
This SO answer summarizes it well:
What has bigger priority: opacity or z-index in browsers?
If an element with opacity less than 1 is not positioned, implementations must paint the layer it creates, within its parent stacking context, at the same stacking order that would be used if it were a positioned element with ‘z-index: 0’ and ‘opacity: 1’

How to delete an item from a drag and drop menu

I'm trying to add an Delete button function to a drag and drop shopping cart. I have the button in place but I can not call a function that seems to work. I'm very novice.
Im not sure if were the function should appear because the list is created from a drag and drop menu
Below is the code so far - any help would be greatly appreciated
thanks
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>HTML 5 Drag and Drop Shopping Cart</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.products1 { grid-area: products1; }
.menu1 { grid-area: menu1; }
.menu2 { grid-area: menu2; }
.menu3 { grid-area: menu3; }
.menu4 { grid-area: menu4; }
.grid-container {
display: grid;
grid-template-areas:
'products1 menu1 menu2 menu3 menu4'
;
grid-gap: 5px;
background-color: #2196F3;
padding: 5px;
}
.grid-container > div {
background-color: rgba(255, 255, 255, 0.8);
text-align: center;
padding: 20px 0;
font-size: 20px;
}
#item-container{
width: 280px;
padding: 10px;
border: 5px solid gray;
margin:20px auto;
text-align: center;
font-size: 20px;
}
ul, li{
list-style: none;
margin: 2px;
padding: 0px;
cursor: grabbing;
}
section#cart ul{
height: 600px;
overflow: auto;
background-color: #cccccc;
}
</style>
<script src="jquery-3.3.1.min.js"></script>
<script>
function addEvent(element, event, delegate ) {
if (typeof (window.event) != 'undefined' && element.attachEvent)
element.attachEvent('on' + event, delegate);
else
element.addEventListener(event, delegate, false);
}
addEvent(document, 'readystatechange', function() {
if ( document.readyState !== "complete" )
return true;
var items = document.querySelectorAll("section.products ul li");
var cart = document.querySelectorAll("#cart ul")[0];
function updateCart(){
var total = 0;
var term = 48;
var rate = 7;
var amount = 15090;
var cart_items = document.querySelectorAll("#cart ul li")
for (var i = 0; i < cart_items.length; i++) {
var cart_item = cart_items[i];
var quantity = cart_item.getAttribute('data-quantity');
var price = cart_item.getAttribute('data-price');
var payment = amount*((((rate/12)/100)*((1+((rate/12)/100))**term))/(((1+((rate/12)/100))**term)-1));
var sub_total = parseFloat(quantity * parseFloat(price));
cart_item.querySelectorAll("span.sub-total")[0].innerHTML = + sub_total.toFixed(2);
total += sub_total*((((rate/12)/100)*((1+((rate/12)/100))**term))/(((1+((rate/12)/100))**term)-1));
newpayment=total+payment
}
document.querySelectorAll("#cart span.total")[0].innerHTML = total.toFixed(2);
document.querySelectorAll("#cart span.newpayment")[0].innerHTML = newpayment.toFixed(2);
}
function addCartItem(item, id) {
var clone = item.cloneNode(true);
clone.setAttribute('data-id', id);
clone.setAttribute('data-quantity', 1);
clone.removeAttribute('id');
var fragment = document.createElement('span');
fragment.setAttribute('class', 'quantity');
fragment.innerHTML = '<button id="butt" onclick="one(this);">delete item</button> $';
clone.appendChild(fragment);
fragment = document.createElement('span');
fragment.setAttribute('class', 'sub-total');
clone.appendChild(fragment);
cart.appendChild(clone);
}
function updateCartItem(item){
var quantity = item.getAttribute('data-quantity');
quantity = parseInt(quantity) + 1
item.setAttribute('data-quantity', quantity);
var span = item.querySelectorAll('span.quantity');
span[0].innerHTML = ' x ' + quantity;
}
function onDrop(event){
if(event.preventDefault) event.preventDefault();
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true;
var id = event.dataTransfer.getData("Text");
var item = document.getElementById(id);
var exists = document.querySelectorAll("#cart ul li[data-id='" + id + "']");
{
addCartItem(item, id);
}
updateCart();
return false;
}
function onDragOver(event){
if(event.preventDefault) event.preventDefault();
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true;
return false;
}
addEvent(cart, 'drop', onDrop);
addEvent(cart, 'dragover', onDragOver);
function onDrag(event){
event.dataTransfer.effectAllowed = "move";
event.dataTransfer.dropEffect = "move";
var target = event.target || event.srcElement;
var success = event.dataTransfer.setData('Text', target.id);
}
for (var i = 0; i < items.length; i++) {
var item = items[i];
item.setAttribute("draggable", "true");
addEvent(item, 'dragstart', onDrag);
};
});
</script>
</head>
<body>
<div id="page">
<div class="grid-container">
<div class="products1">
<section id="products" class="products">
<h1></h1>
<ul>
<li id="product-1" data-price="3999.00"><div id="item-container">Product 1<br> descr<br>descr </div></li>
<li id="product-2" data-price="1895"><div id="item-container">Product 2<br> descr<br>descrip</div></li>
<li id="product-3" data-price="2.99"><span>Product 3</span></li>
<li id="product-4" data-price="3.50"><span>Product 4</span></li>
<li id="product-5" data-price="4.25"><span>Product 5</span></li>
<li id="product-6" data-price="6.75"><span>Product 6</span></li>
<li id="product-7" data-price="1.99"><span>Product 7</span></li>
</ul>
</section>
</div>
<div class="menu1">
<section id="cart" class="shopping-cart">
<h1>Preferred</h1>
<ul>
</ul>
<p> $<span class="total">0.00</span></p>
<p> $<span class="newpayment">0.00</span></p>
</section>
</div>
<div class="menu2">
<section id="cart" class="shopping-cart">
<h1>Value</h1>
<ul>
</ul>
<p> $<span class="total">0.00</span></p>
</section>
</div>
<div class="menu3">
<section id="cart" class="shopping-cart">
<h1>Basic</h1>
<ul>
</ul>
<p> $<span class="total">0.00</span></p>
</section>
</div>
<div class="menu4">
<section id="cart" class="shopping-cart">
<h1>Economy</h1>
<ul>
</ul>
<p> $<span class="total">0.00</span></p>
</section>
</div>
</div>
</div>
</body>
</html>

How to target a div with a same ID

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>

when click on the first li, it show content one, when click on second li, it shows content two

<style type="text/css">
.web_index div {width: 400px; height: 300px; background: #eee;}
ul li{width: 100px; height: 30px; line-height: 30px; list-style: none; display: inline-block; *display: inline; zoom: 1;}
</style>
<script type="text/javascript">
function licker(){
var lier=document.getElementsByTagName("li");
var diver=document.getElementsByClassName("web_index")[0].getElementsByTagName("div");
for(var i=0;i<lier.length;i++)
{
for(j=0;j<diver.length;j++)
{
if(i==j)
{
diver[j].style.display=block;
}
else{
diver[j].style.display=none;
}
}
}
}
</script>
html:
<ul>
<li onclick="licker()" class="li01">the first li</li>
<li onclick="licker()" class="li02">the second li</li>
<li onclick="licker()" class="li03">the third li</li>
<div class="web_clear"></div>
</ul>
<div class="web_index">
<div style="display:block" >content one</div>
<div style="display:none">content two</div>
<div style="display:none">content three</div>
</div>
when click on the first li, it show content one, the others are all hidden, when click on second li, it shows content two. the others are all hidden....why my code doesn't work.how to correct it.thank you,
You should assign an index to your li's:
<ul>
<li onclick="licker(0)" class="li01">the first li</li>
<li onclick="licker(1)" class="li02">the second li</li>
<li onclick="licker(2)" class="li03">the third li</li>
<div class="web_clear"></div>
</ul>
and your function:
function licker(id){
var diver=document.getElementsByClassName("web_index")[0].getElementsByTagName("div");
for(var i=0;i<diver.length;i++){
if(i==id){
diver[i].style.display='block';
} else {
diver[i].style.display='none';
}
}
}​
JSFiddle Example
Try this
<ul>
<li onclick="licker(this);">the first li</li>
<li onclick="licker(this);">the second li</li>
<li onclick="licker(this);">the third li</li>
</ul>
<div class="web_index">
<div style="display: block">content one</div>
<div style="display: none">content two</div>
<div style="display: none">content three</div>
function licker(sender) {
var lier = document.getElementsByTagName("li");
var diver = document.getElementsByClassName("web_index")[0].getElementsByTagName("div");
for (var i = 0; i < lier.length; i++) {
if (lier[i] != sender) continue;
for (j = 0; j < diver.length; j++) {
if (i == j)
diver[j].style.display = 'block';
else
diver[j].style.display = 'none';
}
}
}
</script>

Categories