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>
Related
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>
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");
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>
I had a look out on the interwebs for a jQuery image gallery and couldn't find one that suited what I wanted to do. So I, ended up creating one myself and am trying to figure out how to get the prev and next buttons to work.
<div class="gallery portrait">
<nav>
<div class="close"></div>
<div class="prev"></div>
<div class="next"></div>
</nav>
<div class="cover">
<img src="image.jpg">
</div>
<ul class="thumbs">
<li class="thumb">
<img src="image.jpg">
</li>
...
</ul>
</div>
I'm also using a bit of jQuery to add a class of .full to the .thumb a element, which makes the thumbnails go fullscreen.
$( ".thumb a" ).click(function() {
$( this ).toggleClass( "full" );
$( "nav" ).addClass( "show" );
});
Now I can't work out this next bit, I need a way when the .prev or .next buttons are clicked for it to remove the class of .full from the current element and add it to the next or previous .thumb a element, depending on which was clicked.
I've got a demo setup here: http://codepen.io/realph/pen/hjvBG
Any help is appreciated, thanks in advance!
P.S. If this turns out well, I plan on releasing it for free. I guess you can't have too many jQuery image galleries, eh?
You can use $.next() and $.prev():
$(".prev").click(function () {
var current = $('.full');
current.prev('.thumb').addClass('full');
current.removeClass('full');
return false; // stop propagation; prevents image click event
});
$(".next").click(function () {
var current = $('.full');
current.next('.thumb').addClass('full');
current.removeClass('full');
return false; // stop propagation; prevents image click event
});
I suggest the following additions to your code to handle wrapping around with your next and previous links:
$(".next").click(function (event) {
navigate("next");
return false;
});
$(".prev").click(function (event) {
navigate("prev");
return false;
});
function navigate(operation) {
var $thumbs = $(".thumb"),
$full = $thumbs.find("a.full").closest(".thumb"),
$next;
$thumbs.find('a').removeClass('full');
if (operation == 'prev' && $full.is($thumbs.first()))
$next = $thumbs.last();
else if (operation == 'next' && $full.is($thumbs.last()))
$next = $thumbs.first();
else
$next = $full[operation]();
$next.find('a').click();
}
Here is a forked CodePen.
Something like this will get you started, but what you're wanting to do takes a little time to get just right.
<script type="text/javascript">
var imgSrcs = ['/imgs/this.jpg', '/imgs/will.jpg', '/imgs/work.jpg', '/imgs/just.jpg', '/imgs/fine.jpg'];//img url loaded into an array
var btnPrev = document.getElementById('prev'),
btnNext = document.getElementById('next'),
cover = document.getElementById('cover'),
thumb = document.getElementById('thumb'),
currImgIx = 0;
btnPrev.onclick = function () {
if (currImgIx === 0) { return; };
currImgIx--;
cover.src = imgSrcs[currImg];
thumb.src = imgSrcs[currImgIx];
};
btnNext.onclick = function () {
if (currImgIx === imgSrcs.length - 1) { return; };
currImgIx++;
cover.src = imgSrcs[currImgIx];
thumb.src = imgSrcs[currImgIx];
};
</script>
<div class="gallery portrait">
<nav>
<div class="close">X</div>
<div id="prev" class="prev">Prev</div>
<div id="next" class="next">Next</div>
</nav>
<div class="cover">
<img id="cover" src="image.jpg">
</div>
<ul class="thumbs">
<li class="thumb">
<img id="thumb" src="image.jpg">
</li>
...
</ul>
</div>
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>