Is there anyway to simplify this Javascript code - javascript

I have this code that, when a certain card is clicked, its content is displayed on an overlay card. But the way I have it right now is to repetitive:
HTML:
<div class="card c1">
<img src="max.png" width="65px">
<div class="text">
<h3 class="firstName">Owen</h3>
<h3 class="lastName">Osagiede</h3>
<p>[email]</p>
<p>[city]</p>
</div>
</div>
<div class="card c2">
<img src="max.png" width="60px">
<div class="text">
<h3 class="firstName">Kanye</h3>
<h3 class="lastName">West</h3>
<p>[email]</p>
<p>[city]</p>
</div>
</div>
<div class="card c3">
<img src="max.png" width="65px">
<div class="text">
<h3 class="firstName">Quando</h3>
<h3 class="lastName">Rondo</h3>
<p>[email]</p>
<p>[city]</p>
</div>
</div>
JS:
function overlayUser(){
card[1].addEventListener('click', function(){
first.innerHTML = card[1].getElementsByTagName('h3')[0].innerHTML;
last.innerHTML = card[1].getElementsByTagName('h3')[1].innerHTML;
});
card[2].addEventListener('click', function(){
first.innerHTML = card[2].getElementsByTagName('h3')[0].innerHTML;
last.innerHTML = card[2].getElementsByTagName('h3')[1].innerHTML;
});
card[3].addEventListener('click', function(){
first.innerHTML = card[3].getElementsByTagName('h3')[0].innerHTML;
last.innerHTML = card[3].getElementsByTagName('h3')[1].innerHTML;
});
I have tried to loop over it with a for loop, but keep getting an error:
`function overlayUser(){
for (i = 0; i < card.length; i++){
card[i].addEventListener('click', function(){
first.innerHTML = card[i].getElementsByTagName('h3')[0].innerHTML;
last.innerHTML = card[i].getElementsByTagName('h3')[1].innerHTML;
});
}
}`

In a DOM event handler, the current element is this. Therefore you can write a single function for all of them:
function handleClick () {
first.innerHTML = this.getElementsByTagName('h3')[0].innerHTML;
last.innerHTML = this.getElementsByTagName('h3')[1].innerHTML;
}
function overlayUser(){
for (i = 0; i < card.length; i++){
card[i].addEventListener('click', handleClick);
}
}
The this API is the original API for finding out which element caused the event. Thus it is very compatible with all browsers.
Alternatively, if you feel uncomfortable mixing the usage of this you can also find out the current element from the event object:
function handleClick (event) {
let card = event.target;
first.innerHTML = card.getElementsByTagName('h3')[0].innerHTML;
last.innerHTML = card.getElementsByTagName('h3')[1].innerHTML;
}
The event object is a slightly less ancient API but is compatible with everything from IE8 and above.
Additionaly you can use event bubbling/capturing to even get rid of the for loop. Just install the event on the parent element of all three cards and let event.target sort out which card caused the event:
parentDiv.addEventListener('click', handleClick);

Instead of looping over all the individual elements that you want to have event handlers and hooking each up, set a single handler on an ancestor element and allow the event to bubble up to that element. Then, when handling it, look at the event.target, which refers to the actual element that triggered the event. This is called event delegation.
Also, do not use .getElementsByTagName() in 2020. That is a 25+ year old API that returns a live node list that can dramatically hurt performance, especially since you are only interested in a single element when you use it.
Addtionally, never use .innerHTML if you can avoid it. It has security and performance implications. Since you aren't actually working with a string that needs any HTML parsed, you should use .textContent.
Finally, you should not be using h3 unless it is to create a sub-section of a pre-existing h2. Headings are meant to divide your document into ordered sections and these sections are used by those who rely on assistive technologies to navigate a document. If you are just using the h3 because of the styling the browser applies to the text, you should instead just use a p and then use CSS to style it the way you want.
// Get references to first and last (for this demo)
let first = document.querySelector(".first");
let last = document.querySelector(".last");
// Just handle the click event at the wrapper of all the cards
document.querySelector(".wrapper").addEventListener("click", function (event){
// Then access the content of the card that actaully triggered the event
first.textContent = event.target.closest(".card").querySelector("h3").textContent;
last.textContent = event.target.closest(".card").querySelector("h3:nth-child(2)").textContent;
});
/* Just for demo */
.results {
position:sticky;
left:50%;
top:0;
background-color:#e0e0e0;
border:2px solid red;
}
<div class="results">
<div class="first"></div>
<div class="last"></div>
</div>
<div class="wrapper">
<div class="card c1">
<img src="max.png" width="65px">
<div class="text">
<h3 class="firstName">Owen</h3>
<h3 class="lastName">Osagiede</h3>
<p>[email]</p>
<p>[city]</p>
</div>
</div>
<div class="card c2">
<img src="max.png" width="60px">
<div class="text">
<h3 class="firstName">Kanye</h3>
<h3 class="lastName">West</h3>
<p>[email]</p>
<p>[city]</p>
</div>
</div>
<div class="card c3">
<img src="max.png" width="65px">
<div class="text">
<h3 class="firstName">Quando</h3>
<h3 class="lastName">Rondo</h3>
<p>[email]</p>
<p>[city]</p>
</div>
</div>
</div>

Related

Display none some content and block one element

I would like to make 3 buttons with each one make all the content div to display: none and depending on the button you have click one of the content div change to display: block. For example, If I click on the second button It will show only the second div content.
function showPanel(id) {
var elements = document.getElementsByClassName("content");
for (let i = 0; i < elements.length; i++) {
document.getElementById(i).style.display = "none";
}
document.getElementById(id).style.display = "block";
}
<button onclick="showPanel('1')">test1</button>
<button onclick="showPanel('2')">test2</button>
<button onclick="showPanel('3')">test3</button>
<div class="content">
<div id="1" class="content">
<p>TEST1</p>
</div>
<div id="2" class="content">
<p class="other">TEST2</p>
</div>
<div id="3" class="content ">
<p class="other">TEST3</p>
</div>
</div>
There's a couple of issues in your code. Firstly length is a property, not a method, so you don't need the () suffix to invoke it. Secondly, there's no className attribute in HTML. This should just be class. Lastly the parent container shares the same class as the elements you're hiding, so all the child elements get hidden, even if they have display: block applied to them.
With these issues corrected, your code would look like this:
function showPanel(id) {
var elements = document.getElementsByClassName("panel");
for (let i = 0; i < elements.length; i++) {
elements[i].style.display = "none";
}
document.getElementById(id).style.display = "block";
}
<button onclick="showPanel('p1')">test1</button>
<button onclick="showPanel('p2')">test2</button>
<button onclick="showPanel('p3')">test3</button>
<div class="content">
<div id="p1" class="panel">
<p>TEST1</p>
</div>
<div id="p2" class="panel">
<p class="other">TEST2</p>
</div>
<div id="p3" class="panel">
<p class="other">TEST3</p>
</div>
</div>
However it's worth noting that using onX attributes is outdated and not good practice. A better solution would be to use unobtrusive event handlers and provide custom metadata to the event handler through data attributes placed on the elements.
The improved version of the logic would look like this:
let buttons = document.querySelectorAll('button');
let panels = document.querySelectorAll('.panel');
buttons.forEach(button => {
button.addEventListener('click', e => {
panels.forEach(panel => {
panel.style.display = panel.id === e.target.dataset.panel ? 'block' : 'none';
});
});
});
<button data-panel="1">test1</button>
<button data-panel="2">test2</button>
<button data-panel="3">test3</button>
<div class="content">
<div id="1" class="panel">
<p>TEST1</p>
</div>
<div id="2" class="panel">
<p class="other">TEST2</p>
</div>
<div id="3" class="panel">
<p class="other">TEST3</p>
</div>
</div>
No need for JS or Jquery. Instead of a button you can use an anchor tag. Then you calling with the anchor the id of the element. Last but not least you make the boxes hidden through CSS and use the :target selector to display the elements:
.content {
display: none;
}
.content:target {
display: block;
}
test1<br>
test2<br>
test3<br>
<div class="content-container">
<div id="1" class="content">
<p>TEST1</p>
</div>
<div id="2" class="content">
<p class="other">TEST2</p>
</div>
<div id="3" class="content ">
<p class="other">TEST3</p>
</div>
</div>
Multiple issues.
Length can be calculated using elements.length and not elements.length()
You have given same class name to both the parent and the child divs. So hiding all elements with class name content will hide your whole parents itself. So after updating style.display = "block" to the required target, it will not work. Because your parent is already style.display = "none". So you should make a logic update there. So I changed the parent class name.
function showPanel(id) {
var elements = document.getElementsByClassName("content");
for (let i = 0; i < elements.length; i++) {
elements[i].style.display = "none";
}
document.getElementById(id).style.display = "block";
}
<button onclick="showPanel('1')">test1</button>
<button onclick="showPanel('2')">test2</button>
<button onclick="showPanel('3')">test3</button>
<div>
<div id="1" class="content">
<p>TEST1</p>
</div>
<div id="2" class="content">
<p class="other">TEST2</p>
</div>
<div id="3" class="content ">
<p class="other">TEST3</p>
</div>
</div>
A more elegant way I might approach a prob,problem like this would be to tie the panels and their triggers together using data-attributes. This way, you don't risk conflicts with other IDs that m ay be the same on the page (IDs should always be unique).
Before setting up my event listener, I would initialize an openPanel variable and set it to any panel that is already created with the active class name. Whenever we open a new panel, we will overwrite this variable vaklue, so we don't need to do a new querySelctor each time.
Then, in the CSS, rather than hiding all panels and then showing the one with the active class, we can write a single style that hides any panels without the active class using the :not negation selector.
This is how that would look (initializing this with panel #1 open by default, but you can simply remove the active class from it in the HTML if you don't want that):
let openPanel = document.querySelector('[data-panel-id].active');
document.addEventListener('click', e => {
if (e.target?.matches?.('[data-panel-target]')) {
const id = e.target.dataset.panelTarget;
if (id) {
const panel = document.querySelector(`[data-panel-id="${id}"]`);
if (panel) {
openPanel?.classList.remove('active');
panel.classList.add('active');
openPanel = panel;
}
}
}
})
[data-panel-id]:not(.active) {
display: none;
}
<button data-panel-target="1">test1</button>
<button data-panel-target="2">test2</button>
<button data-panel-target="3">test3</button>
<main>
<div data-panel-id="1" class="active">
<p>TEST #1</p>
</div>
<div data-panel-id="2">
<p>TEST #2</p>
</div>
<div data-panel-id="3">
<p>TEST #3</p>
</div>
</main>
I already submitted a separate solution with my preferred recommendation, but I wanted to provide an answer to your question using the same approach you started with so as not to deviate from the code you already have in place.
The code you already had in place was actually fairly close to working already. The main issue I saw was that you were using document.getElementById(i) where you should actually have been using elements[i]. We can improve this further though, by replacing the for loop with a for..of loop, and determining inline whether the current element being evaluated is the one we want to show. If so, we use 'block', otherwise 'none'.
After initializing our function, we can call it on one of our IDs within the JS to have one panel open by default. **It's also important that the parent of all these .content elements NOT contain the class name content as well, as that would conflict with your function. I have replaced that parent element with a simple <main>…</main> element.
Here is how I would achieve solving this using your existing approach:
function showPanel(contentId) {
const elements = Array.from(document.getElementsByClassName('content'));
for (const element of elements) {
element.style.display = element.id === contentId ? 'block' : 'none';
}
}
showPanel('1');
<button onclick="showPanel('1')">test1</button>
<button onclick="showPanel('2')">test2</button>
<button onclick="showPanel('3')">test3</button>
<main>
<div id="1" class="content">
<p>TEST1</p>
</div>
<div id="2" class="content">
<p>TEST2</p>
</div>
<div id="3" class="content ">
<p>TEST3</p>
</div>
</main>

Appended node does not trigger JavaScript event

I have an inventory with some slots in it. With some actions from the client, new items are added to these slots by the appendChild function.
<div id="letters">
<div class="slot">
<div class="item">
<img src="...">
</div>
</div>
<div class="slot"></div>
<div class="slot">
<div class="item">
<img src="...">
</div>
</div>
</div>
With the following code I try to trigger a mouseover event for each slot.
var items = document.querySelectorAll(".item");
items.forEach(function(element) {
element.addEventListener("mouseover", function () {
//Stuff
});
});
It works perfectly fine, but when I add a new item to a class slot, this one does not trigger the event.
Can anybody guess the problem?
Thanks a lot!
Edit:
I solved the problem by adding a new eventListener too whenever I append a new item. EventListeners must be added before using them (pretty obvious), and in my code I was working with them as if they were onmouseover functions.
You need to add the handler to the newly constructed element after it is created.
var items = document.querySelectorAll(".item");
function attachMouseOverHandler(element) {
element.addEventListener("mouseover", mouseOverHappened);
}
items.forEach(attachMouseOverHandler);
function addNewElement(element) {
attachMouseOverHandler(element);
}
Following the append, you need to add the event listener to the new element, as it did not exist when you originally created the event listeners.
Here's a solution using a single deferred event listener, so you don't have to dynamically add new event listeners:
document.getElementById('letters').addEventListener('mouseover', function (event) {
const element = event.target;
if (!element.matches('.item')) return;
//Stuff
console.log(element.textContent.trim());
})
<div id="letters">
<div class="slot">
<div class="item">
Foo
</div>
</div>
<div class="slot">I do not match .item</div>
<div class="slot">
<div class="item">
Bar
</div>
</div>
</div>

How to get the ID of a clicked element, when it or its children are clicked?

UPDATED
I think I may have inadvertently made the question confusing. This is an update that is more specific with updated code based on comments and answer I have been given so far. Thank you to everyone that has taken the time to comment and answer.
How can I get the ID of a <div> with the class of .button when I have a click listener for .button. If .button or any of its children are clicked, it should return the ID for that particular div with the class of .button.
This is what I have so far: New JSFiddle
HTML
<div class="row">
<div id="b1" class="button">
<h2>Button 1</h2>
</div>
<div id="b2" class="button">
<h2>Button 2</h2>
</div>
<div id="b3" class="button">
<h2>Button 3</h2>
</div>
</div>
jQuery
var selected = "";
$('.button').on('click', function(e) {
selected = e.target.id;
$('.button').css('backgroundColor', '#becde5');
$('#' + selected).css('backgroundColor', '#3b71c6');
$('#selected').html(selected);
});
This is almost correct but does not propagate, if I click on a <h2> the function does not work. However if I click on the .button div itself it works.
Initial Question
I am trying to create a general function that can identify what child was selected from its parents click listener. The child may have its own children that would all be considered part of the same element so that if any of these children where selected they should also elicit the same response from the click listener.
This is an example of what I have working so far: JSFiddle
HTML consisting of three buttons that all have one child <h2> tag and share the <div class="row"> as their parent.
<div class="row">
<div class="b1 button">
<h2 class="b1">Button 1</h2>
</div>
<div class="b2 button">
<h2 class="b2">Button 2</h2>
</div>
<div class="b3 button">
<h2 class="b3">Button 3</h2>
</div>
</div>
jQuery that listens for a click on <div class="row">. It retrieves the first class name of the clicked element and stores it in a variable. The elicited response in this case is a change of the CSS style background-color though this is arbitrary and would change depending on the use of the function.
var selected = "";
$('.row').on('click', function(e) {
selected = e.target.className.split(" ")[0];
$('.b1, .b2, .b3').css('backgroundColor', '#becde5');
$("." + selected).css('backgroundColor', '#3b71c6');
$('#selected').html(selected);
});
The fact that I am adding a lot of classes to elements purely to identify them on a click seems like it would not scale very well and is generally a bad approach. This method also means that I would always have to put the class name that identifies what element was selected at the beginning of its HTML class attribute. This could potentially clash with other functions using the same method.
Is there a better way to identify what child element was selected from its parents click listener, where a child may have other children that also require the same response from the listener?
EDIT based on the edited question:
I think that what you really want is the id of the element that triggered the event.
But by using e.target you have the target element... which is not necessarily the element that triggered the event.
See in this updated Fiddle.
So simply use $(this) as the selector to retrieve the id... Using .attr("id").
;)
Answer to the initial question:
To determine what can be "selected", I used a "clickable" class.
To avoid using id or class as an identifier to determine what has been clicked,
a data attribute can be usefull.
I used data-id... But you can use whatever you want, like: data-selected or data-target, and assign whatever value to it.
In the below code, I made two exactly identical rows, except their data-id value.
var selected = "";
$('.clickable').on('click', function(e) {
e.stopPropagation(); // To prevent bubbling.
// Reset all bg colors
$('.button').css('backgroundColor', 'initial');
$('.row').css('backgroundColor', 'initial');
// Find exactly what was clicked
if ($(this).hasClass("row")) {
var row = $(this).data("id");
selected = row + " (whole)";
}
if ($(this).hasClass("button")) {
// Find in which row
var row = $(this).closest(".row").data("id");
var btn = $(this).data("id");
selected = btn + " in " + row;
}
// Pale all buttons
$('.button').css('backgroundColor', '#becde5');
// Change bg color of the selected element
$(this).css('backgroundColor', '#3b71c6');
$('#selected').html(selected);
});
.row {
display: table;
width: 100%;
color: white;
border-spacing: 20px;
}
.button {
display: table-cell;
border-radius: 12px;
background-color: #6fa1f2;
text-align: center;
}
#selected {
font-size: 30px;
color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span>Selected : <span id="selected">no selection</span></span><br>
<div class="row clickable" data-id="row1">
<div class="button clickable" data-id="btn1">
<h2>Button 1</h2>
</div>
<div class="button clickable" data-id="btn2">
<h2>Button 2</h2>
</div>
<div class="button clickable" data-id="btn3">
<h2>Button 3</h2>
</div>
</div>
<br>
<div class="row clickable" data-id="row2">
<div class="button clickable" data-id="btn1">
<h2>Button 1</h2>
</div>
<div class="button clickable" data-id="btn2">
<h2>Button 2</h2>
</div>
<div class="button clickable" data-id="btn3">
<h2>Button 3</h2>
</div>
</div>
no need to id the subject, since it was the one clicked, i.e. e.target which with jQuery you cant select like $(e.target) without any trouble
then you need .closest('.button') to search up to the parent .button (if any)
$('.row').on('click', function(e) {
$('.row > .button').css('backgroundColor', '#becde5');
$(e.target).closest('.button').css('backgroundColor', '#3b71c6');
console.log($(e.target).html());
});
.button {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="row">
<div class="button">
<h2>Button 1</h2>
</div>
<div class="button">
<h2>Button 2</h2>
</div>
<div class="button">
<h2>Button 3</h2>
</div>
</div>
If you avoid giving an identifier (classes, IDs, etc) you'd need to do some manual checking for tag type to see what you clicked on (so basically, an identifier as well)
Here's an example, and not very memory efficient method
jsfiddle example
$('.row, .row *').on('click', function(e) {
e.stopPropagation()
$('.button').removeClass('active')
$('.button').css('backgroundColor', '#becde5');
$(this).toggleClass('active')
$('#selected').html(e.target.tagName + ': ' + e.target.className);
});
If you bind a click to div.row and clicked the h2 tag inside the button, and want to manipulate the h2 tag, you could check its tagName- but that less scalable than your OP.

Pass multiple ID's to JS function

My goal in this code is to show specific div tags when the link is clicked and hide all other div tags. I keep rewriting it in different ways but can't seem to get it working properly.
JavaScript below...
function show(id1, id2, id3, id4)
{
document.getElementById(id1).style.visibility="visible";
document.getElementById(id2).style.visibility="hidden";
document.getElementById(id3).style.visibility="hidden";
document.getElementById(id4).style.visibility="hidden";
}
HTML below...
Home
Information
Payment
Contact
<div id="home">Content</div>
<div id="info">Content</div>
<div id="payment">Content</div>
<div id="content">Content</div>
Your code is not working properly because you are passing contact in your function instead of content.
Consider using display:none instead of visibility because if you use visibility your content will be hidden but it will leave a space behind:
function show(id1, id2, id3, id4)
{
document.getElementById(id1).style.display="block";
document.getElementById(id2).style.display="none";
document.getElementById(id3).style.display="none";
document.getElementById(id4).style.display="none";
}
Home
Information
Payment
Contact
<div id="home">Home Content</div>
<div id="info">Info Content</div>
<div id="payment">Pay Content</div>
<div id="contact">Con Content</div>
If this is your html:
<div id="home" class="singleVisible" onclick="disableOthers(this)">Content #1</div>
<div id="info" class="singleVisible" onclick="disableOthers(this)">Content #2</div>
<div id="payment" class="singleVisible" onclick="disableOthers(this)">Content #3</div>
<div id="content" class="singleVisible" onclick="disableOthers(this)">Content #4</div>
Then this could be your script:
function disableOthers(e) {
var all = document.getElementsByClassName('singleVisible');
for(var i = 0; i < all.length; i++) {
// First make all of the elements with the same class hidden.
if (all[i] !== this) {
all[i].style.visibility = 'hidden';
}
// Then make the clicked element visible.
e.style.visibility = 'visible';
}
}
While I feel that it's important that people learn JavaScript this is the sort of thing that jQuery DOES really help with. The 'onclick' attributes above are not recommended for multiple reasons but if you're going to want to remove those and replace them with actual event handler calls in JavaScript then you ALSO are probably going to want to make sure you support older (IE8, not THAT old) browsers as well. Check this out:
http://www.anujgakhar.com/2013/05/22/cross-browser-event-handling-in-javascript/
In any case, the JQuery version is as simple as removing those onclick attributes and using this script instead:
<div id="home" class="singleVisible">Content #1</div>
<div id="info" class="singleVisible">Content #2</div>
<div id="payment" class="singleVisible">Content #3</div>
<div id="content" class="singleVisible">Content #4</div>
<script>
$('.singleVisible').click(function() {
$('.singleVisible').hide();
$(this).show();
});
</script>
Also, note that best practice (if you can) is to have a parent container and attach the event to that instead. Otherwise in both examples I've given you're attaching four event handlers in each case. It's as simple as wrapping the links in a parent div and doing something like this:
<div id="parent">
<div id="home" class="singleVisible">Content #1</div>
<div id="info" class="singleVisible">Content #2</div>
<div id="payment" class="singleVisible">Content #3</div>
<div id="content" class="singleVisible">Content #4</div>
</div>
<script>
$('#parent').on('click', '.singleVisible', function() {
$('.singleVisible').hide();
$(this).show();
});
</script>
Have fun! =)
Give all your div elements a class. On click:
hide all of them by using
getElementsByClassName
https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName
make the particular div visible by its id
Doing these kind of DOM manipulations is very easy with jQuery.

Accordion Box malfunction in firefox

i have the following function written in javascript which operate a slide up/down box. but in firefox, it malfunctions. it just opens/closes once. after that no play.
i am getting the height() param from the box and storing it in hidden input. but firefox is unable to read the correct height of the box.
look at the code to understand better :
JS :
function boxCollapse() {
$("#boxHeight").attr("value", parseInt($("#accTipsBox").height()));
$("#accTipsBox").animate({height:'0px'});
$(".btnCollapse").css({display:'none'});
$(".btnExpand").css({display:'block'});
$("#accTipsBox").css({padding:'0px'});
}
function boxExpand() {
$("#accTipsBox").animate({height: $("#boxHeight").attr("value")});
$(".btnExpand").css({display:'none'});
$(".btnCollapse").css({display:'block'});
$("#accTipsBox").css({padding:'0px'});
}
HTML :
<section class="accBox grey">
<header>
<div class="title">DISCLAIMERS</div>
<a style="display: none;" class="btnExpand" href="javascript:void(0);"><img src="/resources/images/boxExpandGrey.jpg" alt="button"></a>
<a style="display: block;" class="btnCollapse" href="javascript:void(0);"><img src="/resources/images/boxCollapseGrey.jpg" alt="button"></a>
</header>
<div id="accTipsBox" style="height: 125px; padding: 0px;">
<input type="hidden" id="boxHeight" value="125">
<div class="accBoxContent">
<div><p></p><p></p><p></p></div>
</div>
</div>
</section>
I think this is what you were going for:
//bind a `click` event handler to all the elements with the `btnExpandCollapse` class
$('.btnExpandCollapse').on('click', function (event) {
//stop the default behavior of clicking the link (stop the browser from scrolling to the top of the page)
event.preventDefault();
//first select the parent of this element (`header` tag) and then get its sibling element that has the `accTipsBox` class, then take that element and slide it up or down depending on its current state
$(this).parent().siblings('.accTipsBox').slideToggle(500);
});
With some slight tweaks to your HTML:
<section class="accBox grey">
<header>
<div class="title">DISCLAIMERS</div>
<!-- Notice there is only one link now that does the job of both -->
<a class="btnExpandCollapse" href="#"><img src="/resources/images/boxExpandGrey.jpg" alt="button"></a>
</header>
<!-- Notice I changed the ID attribute to CLASS so this code will work for repeated structure -->
<div class="accTipsBox" style="height: 125px; padding: 0px;">
<div class="accBoxContent">
<div>
<p>1</p>
<p>2</p>
<p>3</p>
</div>
</div>
</div>
</section>
Here is a demo: http://jsfiddle.net/VGN64/
Here is some documentation:
.slideToggle(): http://api.jquery.com/slidetoggle
.siblings(): http://api.jquery.com/siblings
On a side-note, if you want to store data about a DOM element, use jQuery's $.data() method:
var $box = $("#accTipsBox");
$.data($box[0], 'height', $box.height());
You can then access this data like this
var height = $.data($('#accTipsBox')[0], 'height');
Notice that I appended [0] onto the end of the jQuery object to return just the DOM node associated with the object, this is required by the $.data() method: http://api.jquery.com/jquery.data. This is a very fast method of storing data associated with DOM elements.

Categories