Change class according to array - javascript

I've got this array:
var size = [small, medium, large];
and this element:
<div class="wp-one wp-two wp-small"></div>
How do I change the size class looping through the size array in JQuery on pressing a button? For example if the element has wp-small, change to wp-medium and so forth looping through the array.
.wp-small {
color: #f00;
}
.wp-medium {
color: #0f0;
}
.wp-large {
color: #00f;
}
<div class="wp-one wp-two wp-small">fdgbfbfnghn</div>
<button>CHANGE CLASS</button>

You can do something like this:
var size = ['small', 'medium', 'large'];
var button = document.getElementById("button");
var id= document.getElementById("sentence");
var i = 0;
button.onclick = function(){
sentence.classList.remove("wp-"+size[i]);
(i == size.length - 1) ? i = 0 : i++;
sentence.classList.add("wp-"+size[i]);
}
JSFiddle
It could probably be tidied up but I'm no JS Wizard.
Basically, the first 4 lines are just me putting stuff into variables. Simple stuff.
I then make a function that on the click of button, it removes the class from the element that is current in the size array. It then checks to see what number the i is at (starting at 0) and if it's larger than the length of size, it resets back to the beginning, if not, it goes to the next array element.
It can be done in jQuery too:
$(document).ready(function(){
var size = ['small', 'medium', 'large'],
button = $("#button"),
sentence= $("#sentence"),
i = 0;
button.click(function(){
sentence.removeClass("wp-"+size[i]);
(i == size.length - 1) ? i = 0 : i++;
sentence.addClass("wp-"+size[i]);
});
});
JSFiddle
But will be faster and just as simple in pure JavaScript

is that what you need ?
var state = 0;
var size = ['small', 'medium', 'large'];
btn = document.getElementById('changeSize');
div = document.getElementById('btn');
btn.addEventListener('click', function() {
state = state == size.length - 1 ? 0 : state + 1;
btn.className = 'wp-' + size[state];
});
JSFiddle

You could add this jQuery code:
$(function(){
currSize = 0;
maxSize = (size.length - 1);
$('button').on('click', function(){
$('.wp-one').removeClass('wp-'+size[currSize]);
if (currSize < maxSize){
currSize++;
}
else{
currSize = 0;
}
$('.wp-one').addClass('wp-'+size[currSize]);
});
});

I am not sure what you are trying to accomplish. Do you want to alter through the availyble sizes, so that a wp-small element will be a wp-medium element and so on? And large ones will be small again?
If so try this:
buttonclickHandler = function(e) {
for(i=size.length;i>0;i--) {
var nextIndex = i % size.length;
$(".wp-" + size[i-1]).switchClass(".wp-" + size[i-1],".wp-" + size[nextIndex]);
}
}
Although in this code you'd have the problem that large elements would be first changed to small elements and later on to medium elements (within one single click). So you'd have to remember those initially large ones and exclude them from the small-to-medium-changes.
Due to simplicity I did not include that in the code above.

Related

Toggle between 3 functions on mouse click

I am adding an addEventListener to a picture on my website.
The goal is that every time the user clicks this picture (album-cover-art) a function will be called (function (event)), which will toggle between 3 functions
document.getElementsByClassName("album-cover-art")[0].addEventListener("click", function (event){
});
these are the 3 functions i want to toggle between:
setCurrentAlbum(albumPicasso);
setCurrentAlbum(albumMarconi);
setCurrentAlbum(albumGreenDay);
how can include these 3 function calls in the eventListener that when the picture is clicked it will toggle between them??
document.getElementsByClassName("album-cover-art")[0].addEventListener("click", function (event){
//toggle between the 3 functions below:
setCurrentAlbum(albumPicasso);
setCurrentAlbum(albumMarconi);
setCurrentAlbum(albumGreenDay);
});
NOTE:
This is a challenge where can i only use JavaScript NOT JQuery
It must toggle between them forever, not a loop which will have an end
you can create an array containg all choise then , using an index , select choise and increment this last every click , if index equals to the arrays length then return to the first index (0) ,
var index= 1;
var albums = [albumPicasso,albumMarconi,albumGreenDay];
document.getElementsByClassName("album-cover-art")[0].addEventListener("click", function(event) {
if(index == albums.length) index = 0;
setCurrentAlbum(albums[index]);
index++;
});
See beelow snippet as an explaining sample :
var albumPicasso = "https://dummyimage.com/300x300/500/f0f",
albumMarconi = "https://dummyimage.com/300x300/550/ff0",
albumGreenDay = "https://dummyimage.com/300x300/555/0ff";
var index= 0;
var albums = [albumPicasso,albumMarconi,albumGreenDay];
document.getElementsByClassName("album-cover-art")[0].addEventListener("click", function(event) {
if(index == albums.length) index = 0;
setCurrentAlbum(albums[index]);
index++;
});
function setCurrentAlbum(album){
document.getElementsByClassName("album-cover-art")[0].style.backgroundImage = "url('"+album+"')";
}
.album-cover-art {
background-image : url('https://dummyimage.com/300x300/500/0ff');
width:300px;
height:300px;
}
<div class="album-cover-art">
</div>
For all downvoters: just because you don't like the pattern it doesn't mean the solution is wrong. Type your own, better answer and let the asker pick the one he prefer. Also, if you're downvoting supply the reason (as a comment) for learning purposes, for me and the asker. thanks.
Here is the snippet you may find usefull:
albumClickCounter = 0;
document.getElementsByClassName("album-cover-art")[0].addEventListener("click", function (event){
if(window.albumClickCounter % 3 === 0) setCurrentAlbum(albumPicasso);
if(window.albumClickCounter % 3 === 1) setCurrentAlbum(albumMarconi);
if(window.albumClickCounter % 3 === 2) setCurrentAlbum(albumGreenDay);
window.albumClickCounter++;
});
var setCurrentAlbum = function(album) { alert(album); }
var albumPicasso = 1;
var albumMarconi = 2;
var albumGreenDay = 3;
.album-cover-art {
width: 200px;
height: 200px;
background: green;
}
<div class="album-cover-art"></div>
For demonstration purposes albums are numbers, but the logic can be whatever you like. Adjust to suit your needs.
use as below
var previouParam="";
document.getElementsByClassName("album-cover-art")
[0].addEventListener("click", function (event){
if(previouParam==""){
setCurrentAlbum("albumPicasso");
}else if(previouParam=="albumPicasso"){
setCurrentAlbum("albumMarconi");
}else{
previouParam="";
setCurrentAlbum("albumGreenDay");
}
});

Multiple Functions with one Code

so I'm using this code, to slideToggle a box on my webpage.
// OPEN CERTAIN BOX
$(function() {
var sliding = false;
var mq = window.matchMedia( "(min-width: 700px)" );
if (mq.matches) {
var time = 500;
} else {
var time = 0;
}
var id = ('1');
var div = ('#toggle-content-' + id);
var img = ('#toggle-img-' + id);
var toggler = ('toggler-' + id);
$(div).hide()
$(toggler).click(function() {
if (sliding == false) {
sliding = true;
// Open / Close
$( div ).slideToggle(time,"swing");
// ...
As you can see, I'm using the var id, to use the toggle function for a certain box, which has its own css and html code.
I have 7 more boxes. Until now, i copied the code 7 times and changed the id at each copy from 2 - 8. Is there a way to make it with one code?
I tried a for loop, that goes from 1 - 8 but this obviously didnt work.
Has someone an idea? Or do I have to make that 8 copies and changed the id.
Edit:
My approach with the for-loop:
$(function() {
var sliding = false;
var mq = window.matchMedia( "(min-width: 700px)" );
if (mq.matches) {
var time = 500;
} else {
var time = 0;
}
for(i = 1; i <= 8; i++){
var id = (i.toString());
var div = ('#toggle-content-'+id);
var img = ('#toggle-img-'+id);
var toggler = ('toggler-'+id);
$( div ).hide()
$( toggler ).click(function(){
if (sliding == false){
sliding = true;
// Open / Close
$( div ).slideToggle(time,"swing");
...
And this is my html code for one box:
<tr><td cellspacing="0" cellpadding="0" height="50px" class="upper">
<toggler-1><area-head-text><img id="toggle-img-1" src="images/box_opener.png"/>Starterpaket</area-head-text></toggler-1>
</td></tr>
<tr><td>
<div id="toggle-content-1">
<area-head-text>
<img class="text-image" src="images/arrow.png"/>3 individuelle Entwürfe<br>
<img class="text-image" src="images/arrow.png"/>3 Korrekturzeichnungen<br>
<img class="text-image" src="images/arrow.png"/>Internationale Nutzungsrechte<br>
<img class="text-image" src="images/arrow.png"/>400€<br><br>
</area-head-text>
</div>
</td></tr>
I'm not sure why you put "Obviously" a loop doesn't work, because that's pretty much exactly what you should do. Something like this:
for(var i = 1; i <= 8; i++)
{
var div = $('#toggle-content-' + i);
var img = $('#toggle-img-' + i);
var toggler = $('toggler-' + i);
$(div).hide()
$(toggler).click(function() {
if (sliding == false) {
sliding = true;
// Open / Close
$( div ).slideToggle(time,"swing");
// ...
}
This is 2 options.
(and my preference) -
Instead of using an ID to add the click event onto each individual toggle button, use the same class on each, and add the click event on that class. When the user clicks a toggle button traverse the DOM from the clicked toggle button to perform your toggle on the relevant <div>.
This would look something like:
$(function() {
$('.toggleBtn').click(function() {
var sliding = $(this).data('sliding'); //use data attr to store sliding status
if (sliding == false) {
$(this).data('sliding') = true;
}else {
return; //don't toggle we're sliding
}
// navigate to element and toggle
$(this).parent('.someParentElement').children('.theDiv').slideToggle(time,"swing");
//clear sliding status
$(this).data('sliding', false);
}
}
The reason this is my preference, is because although it's faster to target an ID for a click event than a class for a single event, using 7 click events on 7 different IDS in my opinion (I don't know for sure) is less efficient than using a single click event on 1 class. That's my perceived purpose of using events on classes rather than IDS.
Also this way, when you want to add another box in, or remove a box, you don't need to modify any Javascript, the only thing you would need to maintain this code for is if you decide to change the structure of the HTML, and therefore the navigation of the DOM to perform your toggle.
using your method:
var ids = ["id1","id2","id3"];
for(var id in ids) {
var $div = $('#toggle-content-' + id);
var $img = $('#toggle-img-' + id);
var $toggler = $('toggler-' + id);
$div.hide()
$toggler.click(function() {
if (sliding == false) {
sliding = true;
// Open / Close
$div.slideToggle(time,"swing");
// ...
}

How to reduce 180 lines of code down to 20 in Javascript?

I have a lot of click handler functions which are almost (textually and functionally) identical. I've got a menu with maybe 10 items in it; when I click on an item, the click handler simply makes one div visible, and the other 9 div's hidden. Maintaining this is difficult, and I just know there's got to be a smart and/or incomprehensible way to reduce code bloat here. Any ideas how? jQuery is Ok. The code at the moment is:
// repeat this function 10 times, once for each menu item
$(function() {
$('#menuItem0').click(function(e) {
// set 9 divs hidden, 1 visble
setItem1DivVisible(false);
// ...repeat for 2 through 9, and then
setItem0DivVisible(true);
});
});
// repeat this function 10 times, once for each div
function setItem0DivVisible(on) {
var ele = document.getElementById("Item0Div");
ele.style.display = on? "block" : "none";
}
Create 10 div with a class for marking
<div id="id1" class="Testing">....</div>
<div id="id2" class="Testing">....</div>
<div id="id3" class="Testing">....</div>
and apply the code
$('.Testing').each(function() {
$(this).click(function() {
$('.Testing').css('display', 'none');
$(this).css('display', 'block');
}
}
$(document).ready(function (){
$("div").click(function(){
// I am using background-color here, because if I use display:none; I won't
// be able to show the effect; they will all disappear
$(this).css("background-color","red");
$(this).siblings().css("background-color", "none");
});
});
Use .siblings() and it makes everything easy. Use it for your menu items with appropriate IDs. This works without any for loops or extra classes/markup in your code. And will work even if you add more divs.
Demo
Fiddle - http://jsfiddle.net/9XSJW/1/
It's hard to know without an example of the html. Assuming that there is no way to traverse from the menuItem to ItemDiv - you could use .index and .eq to match up the elements based on the order they match with the selector.
var $menuItems = $("#menuItem0, #menuItem1, #menuItem2, ...");
var $divs = $("#Item0Div, #Item1Div, #Item2Div, ...");
$menuItems.click(function(){
var idx = $(this).index();
// hide all the divs
$divs.hide()
// show the one matching the index
.eq(idx).show();
})
Try
function addClick(i) {
$('#menuItem'+i).click(function(e) {
// set nine divs hidden, 1 visble
for( var j = 0; j < 10; ++j ) {
var ele = document.getElementById("Item"+j+"Div");
ele.style.display = (i == j ? "block" : "none");
}
});
}
// One click function for all menuItem/n/ elements
$('[id^="menuItem"]').on('click', function() {
var id = this.id; // Get the ID of the clicked element
$('[id^="Item"][id$="Div"]').hide(); // Hide all Item/n/Div elements
$('#Item' + id + 'Div').show(); // Show Item/n/Div related to clicked element
});
Obviously this would be much more logical if you were using classes instead:
<elem class="menuItem" data-rel="ItemDiv-1">...</elem>
...
<elem class="ItemDiv" id="ItemDiv-1">...</elem>
$('.menuItem').on('click', function() {
var rel = $(this).data('rel'); // Get related ItemDiv ID
$('.ItemDiv').hide(); // Hide all ItemDiv elements
$('#' + rel).show(); // Show ItemDiv related to clicked element
});
Save the relevant Id's in an array - ["Item0Div", "Item1Div", ...]
Create a generic setItemDivVisible method:
function setItemDivVisible(visible, id) {
var ele = document.getElementById(id);
ele.style.display = visible ? "block" : "none";
}
And set your click handler method to be:
function(e) {
var arrayLength = myStringArray.length;
for (var i = 0; i < idsArray.length; i++) {
setItemDivVisible(idsArray[i] === this.id, idsArray[i]);
}
}
I think this will do the trick

Flipping 3 text with animation

I have a small requirement. I have a div with three child divs with text. On load the first text will be visible. After 3 seconds the first one hides and second one is visible. After another 3 seconds the second one hides and third one is visible. This continues.
Currently I do not have any animation on the hide of one span and show of another. So it looks kind of murky. White I want is to show some kind of animation as it happens on the windows 8 tiles. Like the text that hides should slide up and disappear and the text that is to be shown should slide in from bottom. the animation should give the user a smooth experience.
I am not using any animation library. Is this possible through javascript / css ? Below is my code. Any idea would be useful.
HTML :
<div class="dataflipping">
<div class="first">FIRST TEXT</div>
<div class="second">SECOND TEXT</div>
<div class="third">THIRD TEXT</div>
</div>
JavaScript:
var srcElement = document.getElementsByClassName("dataflipping");
var elementChld = srcElement.getElementsByTagName("div");
var elementArr = [];
for (counter === 0; counter < elementChld.length; counter++) {
elementArr.push(elementChld[counter]);
}
var elementCount = elementArray.length;
// Set all except first one to hidden initially
for (counter = 1; counter < elementCount; counter++) {
var ele = elementArray[counter];
ele.style.display = "none";
}
counter = 0;
setInterval(function () {
counter++;
var prevElement = null;
var curElement = null;
if (counter === 1) {
var prevElement = elementArr[elementCount - 1];
}
else {
prevElement = elementArr[counter - 2];
}
curElement = elementArr[counter - 1];
prevElement.style.display = "none";
curElement.style.display = "block";
if (counter === elementCount) {
counter = 0;
}
}, 3000);
Girija
IF I understood well. I think easier way is to use MODULO, I wrote something like this:
elementArr[counter%elementCount]
http://jsfiddle.net/t3N4A/
I think you just need to try make position:absolute; and like i change opacity you should change it left/top position, change frequency of setInterval function to make it smoother and make it disappear where u want to. Hope that helped a little.

Variable in getElementById

I need to go over all radio buttons of the form and paint the td that contain the checked ones.
Cant pass the variable of the TD id, in the loop (aca):
function veamos() {
var allElems = document.getElementsByTagName('input');
for (i = 0; i < allElems.length; i++) {
if (allElems[i].type === 'radio' && allElems[i].checked) {
var aca="pinta"+i;
document.getElementById(aca).style.backgroundcolor = '#9e0000';
} else {
//document.getElementById(estetd).style.backgroundColor = '#ffffff';
}
}
}
document.getElementById('pinta1').style.backgroundColor = '#9e0000', seems to work... cant build the variable to loop all form
Any ideas?
Thanks in advanced.
If i understand your question right I think you have 2 options.
function veamos () {
var allElems = document.getElementsByTagName('input');
for (var i = 0, len = allElems.length; i<len; i++) { /* do not use .length in the loop condition, that will have very bad performance on element arrays returned by getElementsByTagName. */
var elem = allElems[i];
if (elem.type==='radio') {
/* Option 1: This depends on the HTML structure, where is the TD in relation to the input? */
var td = elem.parentNode; /* if it is 2 levels up then use elem.parentNode.parentNode */
/* Option 2: This depends on having an ID on the <input> and <td> that are similar, like this <input id="r1"> <td id="r1TD"> */
var td = document.getElementById(elem.id + 'TD');
td.style.backgroundColor = elem.checked ? '#9e0000' : '#ffffff';
/* I would recommend using a class name (CSS) instead of using a hard coded color! */
}
}
}
You have a typo. Javascript is case sensitive. Change
document.getElementById(aca).style.backgroundcolor = '#9e0000';
to
document.getElementById(aca).style.backgroundColor = '#9e0000';
...
UPDATE See a working example
Instead
document.getElementById(aca).style.backgroundcolor = '#9e0000';
should be
allElems[i].style.backgroundcolor = '#9e0000';

Categories

Resources