I've been trying to get an accordion movement going with javascript.
The problem that I'm having is having one close if it's already open and stay closed.
Right now the according closing one and opening another when I click a different div.
I see that the argument is always resolving to true because I'm removing the classes.. but I can't seem to find a away to get around that so I could have a nice accordion.
<div class="speaker-container">
<div class="span3 offset1 speaker" id="sp-info-0">
<div class="speaker-img">
<div class="hover"></div>
<img src="" alt="">
</div>
<h4>Title</h4>
</div>
<div class="speaker-info" id="sp-info-0">
<button class="close-speaker">Close</button>
<h2>Title</h2>
</div>
<div class="span3 offset1 speaker" id="sp-info-1">
<div class="speaker-img">
<div class="hover"></div>
<img src="" alt="">
</div>
<h4>Sub Title</h4>
</div>
<div class="speaker-info" id="sp-info-1">
<button class="close-speaker">Close</button>
<h2>Title</h2>
</div>
<div class="span3 offset1 speaker" id="sp-info-2">
<div class="speaker-img">
<div class="hover"></div>
<img src="" alt="">
</div>
<h4>Title</h4>
</div>
<div class="speaker-info" id="sp-info-2">
<button class="close-speaker">Close</button>
<h2>Title</h2>
</div>
</div>
var timer;
$('.speaker-container .speaker').on('click', function(){
var speakerContainer = document.getElementsByClassName('speaker-container');
var self = this;
var children = $('.speaker-container').children();
var selfHeight = this.clientHeight;
var parentOffset = this.parentElement.offsetHeight;
var selfOffset = this.nextElementSibling.offsetHeight;
console.dir(children);
console.log(parentOffset);
$('.speaker-container').removeClass('open').css({'height' : selfHeight + 'px'});
for (var i = 0; i < children.length; i++) {
if (children[i].className == 'speaker-info fade') {
console.dir(children[i]);
$(children[i]).removeClass('fade');
}
}
if (self.parentElement.className !== 'speaker-container open' && self.nextElementSibling.className !== 'speaker-info fade') {
timer = setTimeout(function(){
self.parentElement.setAttribute('class' , 'speaker-container open');
self.parentElement.style.height = selfOffset + selfHeight + 'px';
self.nextElementSibling.style.top = selfHeight + 'px';
self.nextElementSibling.setAttribute('class' , 'speaker-info fade');
// return false;
}, 500);
} else {
$('.speaker-container').removeClass('open').css({'height' : selfHeight + 'px'});
self.nextElementSibling.setAttribute('class' , 'speaker-info');
window.clearTimeout(timer);
}
});
Make a class that has the item open. (let's say the class is "open")
Make a class that has the item closed. (let's say the class is closed")
let's say all the accordion items are in the accordion class.
function that opens an item:
cycle through and remove any existing open item classes, add closed class.
add open class to the selected item.
by default, give closed class to all items (except the one you want open by default, if any)
with javascript it would look something like:
function openOnClick()
{
var openaccordion=document.getElementsByClassName('open');
openaccordion.className.replace( /(?:^|\s)open(?!\S)/g , 'close' );
this.className.replace( /(?:^|\s)close(?!\S)/g , 'open' );
}
with jQuery it would look like this:
$('div.accordion').click(function(){
$('.open').removeClass('open').addClass('close');
$(this).removeClass('close').addClass('open');
}
you can use jqueryui to get some sliding effects in there pretty simply too:
$(this).switchClass('close','open',1000);
Related
I have a question about Javascript.
You can find my HTML markup below
<div class="slides">
<div class="slide active" id="one"></div>
<div class="slide" id="two"></div>
<div class="slide" id="third"></div>
<div class="slide" id="fourth"></div>
</div>
<button onclick="slide-down()">
Next slide
</button>
<button onclick="slide-up()">
Previous slide
</button>
What can i do if the user click on the button slide-down to remove with pure javascript the class 'active' en set this to the next slide element?
You can use a single function, set class at <button> elements to "prev" and "next", pass clicked button .className to function; .getElementsByClassName(), .nextElementSibling, .previousElementSibling
.active {
color: green;
}
<div class="slides">
<div class="slide active" id="one">one</div>
<div class="slide" id="two">two</div>
<div class="slide" id="third">third</div>
<div class="slide" id="fourth">fourth</div>
</div>
<button class="next" onclick="slide(this.className)">
Next slide
</button>
<button class="prev" onclick="slide(this.className)">
Previous slide
</button>
<script>
var active = document.getElementsByClassName("active");
function slide(prevNext) {
if (prevNext === "next") {
if (active[0].nextElementSibling) {
active[0].nextElementSibling.className = "active";
active[0].className = "";
}
} else {
if (active[0].previousElementSibling) {
active[0].previousElementSibling.className = "active";
active[active.length - 1].className = "";
}
}
}
</script>
Something like the below will work. Makes use of many javascript DOM properties and methods. You will need to change the names of your functions slightly as a hyphen is not valid in a name of a function. Ive replaced with underscores.
function slide_down(){
var elems = document.querySelectorAll(".slide");
var curr = document.querySelector(".active");
curr.classList.remove("active");
if(curr.nextElementSibling)
curr.nextElementSibling.classList.add("active");
else
elems[0].classList.add("active");
}
function slide_up(){
var elems = document.querySelectorAll(".slide");
var curr = document.querySelector(".active");
curr.classList.remove("active");
if(curr.previousElementSibling)
curr.previousElementSibling.classList.add("active");
else
elems[elems.length-1].classList.add("active");
}
.active{background-color:red}
<div class="slides">
<div class="slide active" id="one">1</div>
<div class="slide" id="two">2</div>
<div class="slide" id="third">3</div>
<div class="slide" id="fourth">4</div>
</div>
<button onclick="slide_down()">
Next slide
</button>
<button onclick="slide_up()">
Previous slide
</button>
Here is an example I wrote. Jasmiec answered before I finished, and I honestly like some of the different methods used in that example. As already mentioned, you will need to change the names of your functions because a hyphen makes the name invalid.
<div class="slides">
<div class="slide active" id="one"></div>
<div class="slide" id="two"></div>
<div class="slide" id="three"></div>
<div class="slide" id="four"></div>
</div>
<button onclick="slideDown()">
Next slide
</button>
<button onclick="slideUp()">
Previous slide
</button>
<script>
var slides = ["one", "two", "three", "four"]
function slideDown() {
var element = document.getElementsByClassName('active')[0];
var index = slides.indexOf(element.id) + 1;
if (index < slides.length) {
element.className = "slide";
document.getElementById(slides[index]).className = "slide active";
}
}
function slideUp() {
var element = document.getElementsByClassName('active')[0];
var index = slides.indexOf(element.id) - 1;
if (index >= 0) {
element.className = "slide";
document.getElementById(slides[index]).className = "slide active";
}
}
</script>
It's my first steps with programming in js.
I've problem with compare elements in memory game.
After clicking, the code compares only one element from the first click and it causes the function and does not compare further elements despite the collected value -
For example: if I click img with src="f1.png", it's comparing only that element with that same src, not comparing other elements. Here it's f2.png
(This can be confusing but I don't know how to best to describe it)
Please, help me fix that problem.
html
<div class="c ef">
<div class="f"></div>
<div class="b"><img src="f1.png" /></div>
</div>
<div class="c ef">
<div class="f"></div>
<div class="b"><img src="f2.png" /></div>
</div>
<div class="c ef">
<div class="f"></div>
<div class="b"><img src="f1.png" /></div>
</div>
<div class="c ef">
<div class="f"></div>
<div class="b"><img src="f2.png" /></div>
</div>
script
(function() {
var open = "";
var cards = $(".c.ef");
for ( var i = 0, len = cards.length; i < len; i++ ) {
var card = cards[i];
clickListener(card);
}
function clickListener(card) {
card.addEventListener( "click", function() {
var c = this.classList;
c.add("flip");
var open1="";
if(open == ""){
open = $( ".flip" ).contents().find("img").attr("src");
}else{
open1 = $( ".flip" ).contents().find("img").attr("src");
}
if(open !== open1){
setTimeout(function(){
c.remove("flip");
}, 1200);
}else{
setTimeout(function(){
$(".flip").css("visibility", "hidden");
c.remove("flip");
}, 800);
}
});
}
})();
I will try to describ how i will proceded
1rst : you can use data attribute for manipulate easier dom img
2nd : save data value in variable when you click on image
3rd : compare if you second click match with your first variable
so e.g :
<div class="c ef">
<div class="f"></div>
<div class="b" data-img-value="1"><img src="f1.png" /></div>
</div>
<div class="c ef">
<div class="f"></div>
<div class="b" data-img-value="2"><img src="f2.png" /></div>
</div>
<div class="c ef">
<div class="f"></div>
<div class="b" data-img-value="1"><img src="f1.png" /></div>
</div>
<div class="c ef">
<div class="f"></div>
<div class="b" data-img-value="2"><img src="f2.png" /></div>
</div>
------------------- script----------
(function() {
var $card= $('.b');
var $firstVal = null;
$card.on('click',function(){
if($firstVal === null){
$firstVal = $(this).first().attr('data-img-value');
}
else{
if($firstVal === $(this).first().attr('data-img-value')){
//your code if pair match
console.log('pair founded')
$firstval = null;
}
else{
//your code if not match
console.log('not pair')
}
}
});
})();
you can run this exemple here
https://jsfiddle.net/a1na9hLe/5/
After the comparison was made, you have to reset open in order to make a new comparison.
After the first click, open is set to, for example, "f1.png". (btw, imo, you should return here).
After the second click, open1 is set to, for example, "f2.png".
Then the comparison open !== open1 gives you a result, but you never reset open back to "".
So, for the third click, open is already set to the previous value ("f1.png"), and it'll compare the same thing again and again.
TL;DR
This should do the trick:
if(open !== open1){
setTimeout(function(){
c.remove("flip");
open = '';
}, 1200);
}else{
setTimeout(function(){
$(".flip").css("visibility", "hidden");
c.remove("flip");
open = '';
}, 800);
}
I just need some advice with my current code. I am trying to display a different div depending on the menu item clicked. I was thinking theoretically using some kind of indexing method. i think the if statement i am using for once does not work but also seems a little horrible in terms of coding.
anyway what do you think?
/**
* Lets get Menu container
*/
var menu = document.getElementById("configurator-menu");
/**
* Set Current Tab and Store which tab is Active
*/
var navitem = menu.querySelector(".configurator-menuitems div");
navitem.className += " " + "activeTab";
/**
* Add click events to Menu Tabs
*/
var tabs = menu.querySelectorAll(".configurator-menuitems div");
for (var i = 0; i < tabs.length; i++) {
tabs[i].onclick=displayPage;
}
/**
* Tabs Logic
*/
function displayPage() {
var items = menu.querySelectorAll(".configurator-menuitems div");
for (var i = 0; i < items.length; i++) {
items[i].classList.remove("activeTab");
}
this.className += " " + "activeTab";
if (this.classList.contains("mainMenu1")) {
var item = document.getElementByClassName("appCanvas1");
item.style.display = "block";
}
else if (this.classList.contains("mainMenu2")) {
var item = document.getElementByClassName("appCanvas2");
item.style.display = "block";
}
else if (this.classList.contains("mainMenu3")) {
var item = document.getElementByClassName("appCanvas3");
item.style.display = "block";
}
}
<div id="configurator-menu" class="appMenu" style="background-color:#001A35;">
<div class="appLogo">
Logo Here
</div>
<hr class="no-margin" />
<div class="configurator-menuitems">
<div class="mainMenu-btn mainMenu1">Shape</div><hr class="no-margin" />
<div class="mainMenu-btn mainMenu2">Size</div><hr class="no-margin" />
<div class="mainMenu-btn mainMenu3">Color</div><hr class="no-margin" />
</div>
<div class="menuspacer"></div><hr class="no-margin" />
<div class="currentSettings">
<p class="settings-title">Your Selection</p>
<p class="variant-config">Shape: </p>
<p class="variant-config">Colors: </p>
<p class="variant-config">Size: </p>
<p class="variant-config">Quantity: </p>
<p class="variant-config">Total Price: </p>
</div>
</div>
<div class="canvas-wrapper">
<div class="appCanvas1" style="background-color:#e7e7e7;">
<div class="shape-selection-bar">
<div class="shape-selector"><img src="'.plugins_url("pentant_conical.png", __FILE__).'" alt="" /></div>
<div class="shape-selector"><img src="'.plugins_url("pendant_cyl.png", __FILE__).'" alt="" /></div>
<div class="shape-selector"><img src="'.plugins_url("standing_lamp_conical.png", __FILE__).'" alt="" /></div>
<div class="shape-selector"><img src="'.plugins_url("standing_lamp_cyl.png", __FILE__).'" alt="" /></div>
</div>
<div class="configurator-progressBtn"> Move On</div>
</div>
<div class="appCanvas2" style="background-color:#e7e7e7;">
<div class="configurator-progressBtn"> Move On</div>
</div>
<div class="appCanvas3" style="background-color:#e7e7e7;">
<div class="configurator-progressBtn"> Move On</div>
</div>
</div>
I have got a task to create a puzzle.I have 12 div.Each div contains different value up to 12.I have button like start now.I want to change my div value on each click of the start now button.
DEMO
<div id="container">
<div class="finder">
<div class="block1"> <div id="one"><h1>1</h1></div>
</div>
<div class="block1"> <div id="two"><h1>2</h1></div>
</div>
<div class="block1"> <div id="three"><h1>3</h1></div>
</div>
<div class="block1"> <div id="four"><h1>4</h1></div>
</div>
<div class="block1"> <div id="five"><h1>5</h1></div>
</div>
<div class="block1"> <div id="six"><h1>6</h1></div>
</div>
<div class="block1"> <div id="seven"><h1>7</h1></div>
</div>
<div class="block1"> <div id="eight"><h1>8</h1></div>
</div>
<div class="block1"> <div id="nine"><h1>9</h1></div>
</div>
<div class="block1"> <div id="ten"><h1>10</h1></div>
</div>
<div class="block1"> <div id="eleven"><h1>11</h1></div>
</div>
<div class="block1"> <div id="twelve"><h1>12</h1></div>
</div>
</div>
<div class="button">
<div id="startButton">
<button>Start</button>
</div>
</div>
</div>
js is
$(".finder").css('display','none');
$("#startButton").click(function () {
$(".finder").css('display','block');
});
var myDiv;
$(".block1 div").on('click', function(){myDiv = $(this)});
$(".block1 div").click(function () {
if(myDiv.text() < 12)
{
myDiv.text(parseInt(myDiv.text())+1);
}
if(myDiv.text() > 12)
{
myDiv.text(1);
myDiv.text(parseInt(myDiv.text())+1);
}
});
How can i change the values?
I have provided a solution below. One of the key takeaways you should get from it, is that when an event handler is used this will be assigned the element the event was trigger on within the bound function.
To Fill the boxes with random numbers use this code
$(function() {
//Array of values
var values = [1,2,3,4,5,6,7,8,9,10,11,12];
$( "input[type=submit], button" )
.button()
.click(function( event ) {
event.preventDefault();
});
$(".finder").css('display','none');
$("#startButton").click(function () {
var tmpValues = values.slice(); //copy array
$(".block1 div h1").each(function(){
var r = Math.floor(Math.random()*tmpValues.length);
//assign html to random array value that gets removed from array
$(this).html(tmpValues.splice(r,1));
});
$(".finder").css('display','block');
});
$(".block1 div").click(function () {
//Instead of setting myDiv use $(this) which will refer to the div
//We can grab the value of the H1 within the div using a scoped selector
var value = parseInt($("h1",this).html());
//Set the html of the clicked div
//When setting the html we must include new value in h1 to maintain style
//Ternary expression tidies up the logic, not sure why it sets to to 2 though?
$(this).html("<h1>" + ((value > 12) ? 2: value+1) + "</h1>");
});
});
Working Example http://jsfiddle.net/W55xc/3/
I didnt quite get the question, but I guess you want to generate random numbers for the div's, right? Use Math.random()
$(".block1 div").each(function() {
$(this).children('h1').text(Math.floor((Math.random() * 12) + 1)); // Generate a random number <-> [1, 12]
}
Okay, so I am in the process of recreating this feature:
http://www.w3.org/html/logo/#the-technology
I current have it so when you click on a link, it will add a class to the image that relates to that link (href="#one" on the <a> and then id="#one" on the <img>), however it is currently not going through each <a> tag and only one. And also it is not removing the class I requested.
Code follows:
JS
$(document).ready(function() {
var container = '#portfolio #text_container';
var img_container = '#portfolio #image_container';
$(container).children('a').bind('click', function() {
var this_attr = $(this).attr('href');
var this_img = $(img_container).find('img').attr('id');
if(this_attr == this_img) {
//$(img_container).find('img').hasClass('current').removeClass('current');
// ^^^ This line isn't working, any ideas? :/
$(img_container + ' img[id*="' + this_attr + '"]').addClass('current');
}
else {
alert(this_img + ' this img');
alert(this_attr + ' this attr');
}
});
});
And the HTML is as follows
<div id="portfolio">
<div id="image_container">
<img src="http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif" alt="" class="current" id="#one" />
<img src="http://static.jquery.com/files/rocker/images/btn_downloadLarge.gif" alt="" id="#two" />
</div>
<div id="text_container">
Item 1
Item 2
<p id="#one" class="current">A bunch of text!</p>
<p id="#two">The second bunch of text!</p>
</div>
</div>
Please let me know if you need any more information :)
rcravens fixed this with the following code..
JS
$(document).ready(function() {
$('#text_container a').click(function(evt) {
evt.preventDefault();
$('.current').removeClass('current');
var href = $(this).attr('href');
$("." + href).addClass('current');
});
And the HTML..
<div id="portfolio">
<div id="image_container">
<img src="http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif" alt="" class="one current" />
<img src="http://static.jquery.com/files/rocker/images/btn_downloadLarge.gif" alt="" class="two" />
</div>
<div id="text_container">
Item 1
Item 2
<p class="one current">A bunch of text!</p>
<p class="two">The second bunch of text!</p>
</div>
</div>
My interpretation of what you are trying to do is here:
http://jsfiddle.net/rcravens/wMhEC/
The code is changed a bit. You shouldn't have multiple elements with the same id.
Bob
The reason this isn't working:
if(this_attr == this_img)
is because this_attr is a URL and this_img is an ID attribute value.