addClass dont works on conditional - javascript

I come to you with my next problem xd
This is my js:
$(document).ready(function(e) {
let imagesContainer = $(".slider__imageContainer");
let index = 0;
for(let item of imagesContainer) {
if(item == imagesContainer[0]) {
item.addClass("d-block");
}
else {
imagesContainer.addClass("d-none")
}
}
})
Why dont work the "addClass("d-block") function - but my "else" works fine.
and this is my HTML
<body>
<div class="slider">
<div class="slider__imageContainer">
<img src="images/cat-5852139_640.jpg" alt="" class="slider__imageContainer--image">
</div>
<div class="slider__imageContainer">
<img src="images/kingfisher-6146356_640.jpg" alt="" class="slider__imageContainer--image">
</div>
<div class="slider__imageContainer">
<img src="images/meerkats-6153748_640.jpg" alt="" class="slider__imageContainer--image">
</div>
</div>

this is not the element you are thinking, it refers to the HTMLDocument object. You can try
$(item).addClass("d-block");

You need to use item instead of this. Also your code could be optimised further from:
for (let item of imagesContainer) {
if (item == imagesContainer[0]) {
item.addClass("d-block");
} else {
imagesContainer.addClass("d-none")
}
}
to:
imagesContainer.addClass("d-none");
imagesContainer[0].addClass("d-block");

Related

Remove and restore styles on click

I need a button called #btn-limone to remove filter: "grayscale(100%)" on first click and on the second click to restore it. I need it to be done through styles and not classes. How can I do this?
jQuery("#btn-limone").on("click", function () {
jQuery("#agrumi_box, #frutta_polpa_bianca_box, #limone_box").removeAttr("style");
});
With this I can remove the style but I would like that at the second click it would be brought back to 100%.
Thank you to anyone who wants to help me
You can check it has style attribute or not, if id doesn't have you can add your style, if it has style you can remove it. like this:
const items = $('.item');
function toggleFilter(button, relevantIndexes) {
const toggleOn = button.attr('data-toggle') == 'on'
button.attr('data-toggle', toggleOn ? 'off' : 'on')
$.each(items, function(index, item) {
if (!relevantIndexes.includes(index)) return;
const style = item.getAttribute('style');
if (toggleOn) {
item.removeAttribute('style');
} else {
item.setAttribute('style', 'filter:grayscale(100%)');
}
});
}
$('#btn-limone').on('click', function() {
const relevantIndexes = [0, 1, 3];
toggleFilter($(this), relevantIndexes);
});
$('#btn-lime').on('click', function() {
const relevantIndexes = [1, 2, 3];
toggleFilter($(this), relevantIndexes);
});
.item {
display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class="item">
<img src="https://fakeimg.pl/200x100/a10000/?text=Lemone" />
</div>
<div class="item">
<img src="https://fakeimg.pl/200x100/a10000/?text=Lemone-Lime" />
</div>
<div class="item">
<img src="https://fakeimg.pl/200x100/a10000/?text=Lime" />
</div>
<div class="item">
<img src="https://fakeimg.pl/200x100/a10000/?text=Lemone-Lime" />
</div>
</div>
<button class="btn" id="btn-limone" data-toggle="off">Limone</button>
<button class="btn" id="btn-lime" data-toggle="off">Lime</button>

How to add and remove from array?

I have a series of images and I want to insert their src values and then add some div elements too associated with it into the array into the array on a click on the image and remove them if we click again.
Trying the following but I got the logic wrong as it is not removing the already el:
HTML
<div class="card">
<img src="test_2.jpg">
</div>
<div class="card">
<img src="test_2.jpg">
</div>
<div class="card">
<img src="test_3.jpg">
</div>
JS
$('body').on('click', '.card img', function () {
var urls = [];
if($(this).hasClass("checked")) {
$(this).removeClass("checked");
var urlInArray = $(this).attr('src');
urls.splice($.inArray(urlInArray, urls), 1);
console.log(urls);
} else {
$(this).addClass("checked");
var checkedItems = $('.checked'); // get the checked items
checkedItems.each(function () {
urls.push($(this).attr('src'));
});
var str = '';
urls.forEach(function (url) {
str += '<div class="card"><img class="img-fluid" onerror="this.parentNode.removeChild(this);" src="' + url + '"></div>';
});
console.log(urls);
}
});
You can use splice() to remove url from array and indexOf() to get index of that url.
var urls = [];
$(".card img").click(function() {
var src = $(this).attr('src')
$(this).hasClass('checked') ? urls.splice(urls.indexOf(src), 1) : urls.push(src);
$(this).toggleClass('checked')
console.log(urls)
})
.checked {
border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="card">
<img src="test_1.jpg">
</div>
<div class="card">
<img src="test_2.jpg">
</div>
<div class="card">
<img src="test_3.jpg">
</div>
That's an overkill of bytes. Use simple indexOf to check if image is already in urls. I don't see how checked on img tag is semantic, perhaps switch to data-checked?
var urls = [];
$('body').on('click', '.card img', function () {
// src; unique
var src = $(this).attr('src'),
// index of src key
index = urls.indexOf(src);
// if element exists;
if(index >= 0){
// remove
urls.splice(index, 1);
} else {
// add to urls
urls.push(src);
}
console.log(urls);
});
div {
display:inline-block
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="card">
<img src="https://source.unsplash.com/uK9QFr3fFk0/100x100">
</div>
<div class="card">
<img src="https://source.unsplash.com/pHANr-CpbYM/100x100">
</div>
<div class="card">
<img src="https://source.unsplash.com/39-0VXkvcbw/100x100">
</div>
It should be very simple. check this
$(document).ready(function () {
var status = {};
$('body').on('click', '.card img', function () {
var src = $(this).attr('src');
if (typeof status[src] == 'undefined' || status[src] == false) {
status[src] = true;
$(this).next().html('added');
} else {
status[src] = false;
$(this).next().html('removed');
}
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="card">
<img src="france_fan.jpg" alt='image_1'>
<span>removed</span>
</div>
<div class="card">
<img src="italy-s.gif" alt='image2'>
<span>removed</span>
</div>
<div class="card">
<img src="bangladesh-s.gif" alt='image3'>
<span>removed</span>
</div>

Jquery data attribute value equals

Below are my requirements.. i tried in below way. it doesnt work for me. Please let me know what is missed out. Thanks
if data-block = 1, add data-rewardpoints = 300
if data-block = 2, add data-rewardpoints = 400
if data-block = 3, add data-rewardpoints = 500
HTML:
<div class="ir_image_holder">
<img class="ir_img_src" src="1.jpg" data-block="1" data-rewardpoints="" />
</div>
<div class="ir_image_holder">
<img class="ir_img_src" src="2.jpg" data-block="2" data-rewardpoints="" />
</div>
<div class="ir_image_holder">
<img class="ir_img_src" src="3.jpg" data-block="3" data-rewardpoints="" />
</div>
JS:
if ($('.ir_image_holder .ir_img_src').data('block')===1) {
$('.ir_image_holder .ir_img_src').attr('data-rewardpoints', '300');
} else if ($('.ir_image_holder .ir_img_src').data('block')===2) {
$('.ir_image_holder .ir_img_src').attr('data-rewardpoints', '400');
} else if ($('.ir_image_holder .ir_img_src').data('block')===3) {
$('.ir_image_holder .ir_img_src').attr('data-rewardpoints', '500');
}
To achieve this you need to loop over all the .ir_img_src elements individually. Right now your code is setting all the elements data() attributes based on the first element of the set.
You can also tidy the logic by holding all the values to set in an object keyed by the block. Try this:
var data = { 1: 300, 2: 400, 3: 500 }
$('.ir_img_src').each(function() {
$(this).attr('data-rewardpoints', data[$(this).data('block')]);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="ir_image_holder">
<img class="ir_img_src" src="1.jpg" data-block="1" data-rewardpoints="" />
</div>
<div class="ir_image_holder">
<img class="ir_img_src" src="2.jpg" data-block="2" data-rewardpoints="" />
</div>
<div class="ir_image_holder">
<img class="ir_img_src" src="3.jpg" data-block="3" data-rewardpoints="" />
</div>
Note that it's considered better practice to use the setter of data() instead of attr(), where possible. I've left your code as-is here, as there are certain cases where you have to use attr() to set the data attribute.
Do some thing like this
// Get all matched element
var elem = $('.ir_image_holder .ir_img_src');
// loop through each o fthem to get the data-block value
$(elem).each(function(e,v){
if($(this).data('block')===1){
// assign the data-reward point here
$(this).attr('data-rewardpoints',300);
}
// rest of code
})
try iterating over all elements
$('.ir_image_holder .ir_img_src').each(function() {
if($( this ).data('block') == "1") {
$( this ).attr('data-rewardpoints', '300');
}
else if($( this ).data('block') == "2") {
$( this ).attr('data-rewardpoints', '400');
}
else if($( this ).data('block') == "3") {
$( this ).attr('data-rewardpoints', '500');
}
});
Your selector selects all elements that match it and not a single one, which is the expectation of the JS snippet you've provided.
I assume you want the image to be clicked and then to perform the operation in your JS snippet. Here's how you can do it:
$('.ir_image_holder .ir_img_src').on('click', function () {
var $el = $(this);
if ($el.data('block')===1) {
$el.attr('data-rewardpoints', '300');
} else if ($el.data('block')===2) {
$el.attr('data-rewardpoints', '400');
} else if ($el.data('block')===3) {
$el.attr('data-rewardpoints', '500');
}
});
If you're just trying to initialize them then iterate over all selected elements.
$('.ir_image_holder .ir_img_src').each(function () {
var $el = $(this);
if ($el.data('block')===1) {
$el.attr('data-rewardpoints', '300');
} else if ($el.data('block')===2) {
$el.attr('data-rewardpoints', '400');
} else if ($el.data('block')===3) {
$el.attr('data-rewardpoints', '500');
}
});
When you just want to compare similar values, why not use switch instead of if
$('.ir_img_src').each(function(e,v){
var me = $(this);
var db = parseInt($(this).attr('data-block'));
switch(db)
{
case 1 : me.attr('data-rewardpoints', '300');
break;
case 2 : me.attr('data-rewardpoints', '400');
break;
case 3 : me.attr('data-rewardpoints', '500');
break;
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="ir_image_holder">
<img class="ir_img_src" src="1.jpg" data-block="1" data-rewardpoints="" />
</div>
<div class="ir_image_holder">
<img class="ir_img_src" src="2.jpg" data-block="2" data-rewardpoints="" />
</div>
<div class="ir_image_holder">
<img class="ir_img_src" src="3.jpg" data-block="3" data-rewardpoints="" />
</div>

If class also is class then.. move active class on click

(New at jQuery)
Trying to write a function that moves an active class along as an arrow is clicked..
html
<div id="steps">
<a href="#1" data-ref="dynamic-tabs slider-id">
<div class="step step-1 active">
<div class="step-img">
<img width="175" height="120" src="http://site.com/img.png">
</div>
<div class="step-title">Schedule Online or Wave Down a Biker</div>
<div class="step-over"></div>
</div>
</a>
<a href="#2" data-ref="dynamic-tabs slider-id">
<div class="step step-2">
<div class="step-img">
<img width="175" height="120" src="http://site.com/img.png">
</div>
<div class="step-title">We Bike to & Clean Your Car</div>
<div class="step-over"></div>
</div>
</a>
<a href="#3" data-ref="dynamic-tabs slider-id">
<div class="step step-3">
<div class="step-img">
<img width="175" height="120" src="http://site.com/img.png">
</div>
<div class="step-title">Come Back to a Clean Car</div>
<div class="step-over"></div>
</div>
</a>
</div>
<div class="nav-right" data-dir="next" title="Slide right">
right »
</div>
jQuery I'm trying
$(".nav-right a").click(function() {
if( $(".step-1").is('.active') ) {
$(".step-1").removeClass("active");
$(".step-2").addClass("active");
}
});
$(".nav-right a").click(function() {
if( $(".step-2").is(".active") ) {
$(".step-2").removeClass("active");
$(".step-3").addClass("active");
}
});
$(".nav-right a").click(function() {
if( $(".step-3").is(".active") ) {
$(".step-3").removeClass("active");
$(".step-1").addClass("active");
}
});
The problem seems to be that you create 3 (sic!) event handlers which fire sequentially when you click the link.
The first handler, as step 1 is active, sets step 2 to active.
The second handler, as step 2 is now active, sets step 3 to active
The third handler, as step 3 is now active, sets step 1 to active again.
In the end, nothing has happened.
Solution: Use only one event handler, and if-else-statements instead of only if-statements:
$(".nav-right a").click(function() {
if( $(".step-1").is('.active') ) {
$(".step-1").removeClass("active");
$(".step-2").addClass("active");
} else if( $(".step-2").is(".active") ) {
$(".step-2").removeClass("active");
$(".step-3").addClass("active");
} else if( $(".step-3").is(".active") ) {
$(".step-3").removeClass("active");
$(".step-1").addClass("active");
}
});
Of course, we can do much better and write a generic function, which also does not need the step-N classes:
var rotatedElements = $(".step");
$(".nav-right a").click(function() {
var cur = rotatedElements.filter(".active");
cur.removeClass("active");
var index = rotatedElements.index(cur) + 1;
if (index >= rotatedElements.length)
index = 0;
rotatedElements.eq(index).addClass("active");
});
As suggested in comment by theScientist you should use only one event handler.
$(".nav-right a").click(function() {
if( $(".step-1").is('.active') ) {alert('1');
$(".step-1").removeClass("active");
$(".step-2").addClass("active");
return;
}
if( $(".step-2").is(".active") ) {alert('2');
$(".step-2").removeClass("active");
$(".step-3").addClass("active"); return;
}
if( $(".step-3").is(".active") ) {alert('3');
$(".step-3").removeClass("active");
$(".step-1").addClass("active"); return;
}
});
Here it is in a single handler and about as concise as I can make it :
$(".nav-right a").click(function() {
var $steps = $(".step"),
index = $steps.filter('.active').removeClass("active").index();
$steps.eq((index + 1) % $steps.length).addClass('active');
});
There's a couple of problems here, but to address the question you could simplify your code to just this and remove the dependency on .step1, .step2, etc in case you decide to add more steps.
$('.nav-right').find('a').on('click', function(e) {
e.preventDefault();
var $activeStep = $('.step.active'),
$expectedNextStep = $activeStep.closest('a').next().find('.step'),
$nextActiveStep = $expectedNextStep.length ? $expectedNextStep : $('.step').first();
$activeStep.removeClass('active');
$nextActiveStep.addClass('active');
});
​
However; I would highly recommend putting this in an ordered list, and not wrapping block elements in an anchor. The page will work as you have it but it's just poor semantics.

jQuery code refactoring help needed

An update to before, here's what I'm dealing with:
<body>
<div class="header"> <img class="imgLogo" src="img/vegtablelogo.jpg"> </div>
<div id="thumbsContainer">
<div class="thumb" id="carrotThumb"> <img id="showCarrot" class="imgThumb" src="img/carot.jpg" onClick=setupVeg("showCarrot", "carrotBig") /> </div>
<div class="hidden" id="carrotBig"> <img class="imgBig" src="img/carot.jpg" /> </div>
<div class="thumb" id="brocThumb"> <img id="showBroc" class="imgThumb" src="img/brocoli.jpg" onClick=setupVeg("showBroc", "brocBig") /> </div>
<div class="hidden" id="brocBig"> <img class="imgBig" src="img/brocoli.jpg" /> </div>
</div>
<!-- end thumbs container -->
<script>
var active = "";
function setupVeg(thumbVeg, hiddenVeg) {
$("#" + thumbVeg).click(function() {
if (active != hiddenVeg) {
$("div.hidden").hide("fast");
$("#" + hiddenVeg).show("fast", function() {});
active = hiddenVeg;
}
else {
$("div.hidden").hide("fast");
active="";
}
});
}
$("div.hidden").click(function () {
$("div.hidden").hide("fast");
isAnyBig=false;
});
</script>
</body>
This code is not working unfortunately. I have borrowed from suggested solution below.
Would be nice if it did work!
Any suggestions, most welcome.
I don't think you need any of the flags or the if conditions really. I think your logic is:
toggle carrotBig whenever showCarrot
is clicked.
hide div.hidden whenever showCarrot is clicked.
So all you need is:
$("#showCarrot").click(function () {
$("#carrotBig").toggle("fast");
$("#div.hidden").hide();
});
.toggle will handle one of your flags (isCarrotBig) and .hide() won't do anything if div.hidden is already hidden, so that takes care of your isAnyBig flag.
Now.. let's make that work with broc as well...
function setupVegetable(showId, toggleId) {
$("#" + showId).click(function () {
$("#" + toggleId).toggle("fast");
$("#div.hidden").hide();
});
}
setupVegetable("showCarrot", "carrotBig");
setupVegetable("showBroc", "brocBig");
If you're interested, you can refactor it FURTHER so you don't need to supply the IDs for each of the vegetables. I'll need to see your HTML markup though.
Ok I'll post a new answer in response to the edit.
Points worth noting:
Removed divs surrounding the imgs - they are unnecessary and complicate the relationship between the thumnnails and the large images.
Removed onclick attribute from within HTML - you will be attaching the event handlers in the JS so this is not needed.
Since the relationship between the thumbnails and the large images is quite obvious (the large images is just the next element) you don't need IDs to identify ANY of them. All you need is a class on the thumbnails.
Since we're not using IDs, only classes, you can add as many vegetables as you want without touching the JS
Your code modified:
<body>
<div class="header"> <img class="imgLogo" src="img/vegtablelogo.jpg"> </div>
<div id="thumbsContainer">
<img class="imgThumb" src="img/carot.jpg" />
<img class="imgBig hidden" src="img/carot.jpg" />
<img class="imgThumb" src="img/brocoli.jpg" />
<img class="imgBig hidden" src="img/brocoli.jpg" />
</div>
<!-- end thumbs container -->
<script>
$("#thumbsContainer .imgThumb").click(function () {
var thisImgBig = $(this).next();
// Hide all imgBigs, except for this one
$("#thumbsContainer .imgBig").not(thisImgBig[0]).hide();
// Toggle this imgBig
thisImgBig.toggle();
});
$("#thumbsContainer .imgBig").click(function () {
// Hide this imgBig
$(this).hide();
});
</script>
</body>
create a function and reuse it....something like:
/**
* document here....
*/
var toggleElements = function() {
// your code here
}
and then
$("#whatever").click(toggleElements);
Personally I would suggest creating a simple jQuery plugin. Something like so:
(function($){
$.fn.big = function(options) {
var defaults = {
target: '#carrotBig',
};
var options = $.extend(defaults, options);
return this.each(function() {
$(this).click(function () {
isBrocBig=false;
if (isCarrotBig == false && isAnyBig == false) {
$(options.target).show("fast", function() {});
isCarrotBig=true;
isAnyBig=true;
}
else if (isCarrotBig == true) {
$(options.target).hide("fast");
isCarrotBig=false;
isAnyBig=false;
}
else if (isCarrotBig == false && isAnyBig == true) {
$("div.hidden").hide("fast");
$(options.target).show("fast", function() {});
isCarrotBig=true;
}
else {
$("div.hidden").hide("fast");
isCarrotBig=false;
isAnyBig=false;
}
});
});
};
})(jQuery);
Then you just call it with something like so:
$("#showCarrot").big({target: '#carrotBig'})
Your next step should be to investigate whether you can get rid of the global variables or not.
Ok I have found a neat(ish) sollution, dependent on each hidden DIV being the .next() one. If it isn't it won't work but should be fine generally though. Hacked!
<div class="header"> <img class="imgLogo" src="img/vegtablelogo.jpg"> </div>
<div id="thumbsContainer">
<div class="thumb" id="carrotThumb"> <img id="showCarrot" class="imgThumb" src="img/carot.jpg" /> </div>
<div class="hidden" id="carrotBig"> <img class="imgBig" src="img/carot.jpg" /> </div>
<div class="thumb" id="brocThumb"> <img id="showBroc" class="imgThumb" src="img/brocoli.jpg" /> </div>
<div class="hidden" id="brocBig"> <img class="imgBig" src="img/brocoli.jpg" /> </div>
</div>
<!-- end thumbs container -->
<script>
var active = "";
$("div.thumb").click(function() {
var thumbVeg = $(this).attr("id");
var hiddenVeg = $(this).next().attr("id");
setupVeg(thumbVeg, hiddenVeg);
});
function setupVeg(thumbVeg, hiddenVeg) {
if (active != hiddenVeg) {
$("div.hidden").hide("fast");
$("#" + hiddenVeg).show("fast", function() {});
active = hiddenVeg;
}
else {
$("div.hidden").hide("fast");
active="";
}
}
$("div.hidden").click(function () {
$("div.hidden").hide("fast");
});
</script>

Categories

Resources