I am learning some JS now and I am having some trouble with a new functionality I am trying to add to a website.
I have designed a div with a preview image and a navigation bar below with 4 thumbnails of the images you can navigate through, I have two buttons so you can navigate through the images quicker. My goal is to change from one image to another with JS trying to avoid CSS so I can practice. The code I wrote changes to the immediate next image but not the following, no matter how many times I click the "next" button.
I copied the entire project CSS to the pen and I can't delete it. I don't think you'll need to check the CSS but if so, the part of the code that has to do with this question starts in line 410, ignore the rest.
For the time being, I just want it to navigate forwards. I'm working with an array but if anyone has a different approach let me know!
Sorry for my English, hope I made myself clear. Anyways, here is my pen so you can see what I am talking about: https://codepen.io/Nulaxz/pen/poroKJg.
Here is the actual function I am using but seems not to work. The last two "console.log" are just for testing purposes.
nextBtn.addEventListener('click', () => {
const result = arr => {
count++;
if (count >= 4) {
count = 0;
};
return `<div class="img-div">
<img src="http://127.0.0.1:5500/img/icon-previous.svg" alt="prev-btn" class="prev-btn">
<img src=${arr[count]} alt="" id="image-1-preview">
<img src="http://127.0.0.1:5500/img/icon-next.svg" alt="next-btn" class="next-btn">
</div>`;
};
imgPreview.innerHTML = result(imgArr);
console.log(count);
console.log(result(imgArr));
});
This project is a challenge from FrontEndMentor, just in case anyone did it in the past and could tell me how he solved it.
The problem is, you're recreating the next button as well. It causes the button element to be removed from the DOM (along with its click event listener) and recreated again. This is why the button doesn't work anymore.
What you could do is, just updating the image src property. like so:
nextBtn.addEventListener('click', () => {
count++;
if (count >= 4) {
count = 0;
};
document.getElementById('image-1-preview').src = arr[count];
});
Related
I am trying to loop through a gallery of gradient swathes, to highlight them so they can be edited back in the main image, but hitting a roadblock when clicking them to test they are working. They are in a bootstrap row, as col-md-3's, and each swatch bg has an id of bg-gradient (row id is gallery). The below code works in as much as they become active via the css when hovered, but wont console log a test message on click.
html structure is a bootstrap row with id of "gallery", then 4 col-md-3's with id of "swatch", then the actual bg-gradient is what is being looped through. These become active on hover via css settings not via the JavaScript, but wont console log test message on click.
Demo
Code:
editSwatch() {
let swatchs = document.querySelectorAll('swatch'),
//let swatchs = document.getElementById('gallery'),
links = swatchs.getElementsByTagName('bg-gradient'),
i;
for (i = 0; i < links.length; i += 1) {
links[i].addEventListener('click', function () { console.log('click works') });
}
Updated code as per comments below, but still exactly the same result, tried tagName on the links var and still same.
Seems to be finding the swatches, but not working on click.
Need to get that click working to carry on?
Any tips welcome.
Thanks.
You can not keep same id for swatchs, also you can use below query selector with appropriate selector as parameter and loop through swatchs
var swatchs= document.querySelectorAll(".swatchs");
Technically onclick needs to be a function instead. Currently you are passing the return value of console.log() which is undefined I believe. A function needs to be attached to click event in order to make it work.
You can use addEventListener as the following:
links[i].addEventListener('click', function () { console.log('click works') });
Please see a working example how to attach a click event to a <div>:
const div = document.getElementById('elem');
div.addEventListener('click', function () { console.log('hey hello'); });
<div id="elem">Click me!</div>
I hope this helps!
I am trying to make a simple image viewer application using Electron and with the possibility to edit images. I am using CamanJS for image manipulation effects but I have a small problem. When I load the folder with all images, I can scroll through them, also, I can apply some filters to image number 3 for example, save it and scroll no next one. But when I am trying to edit another image, say number 5, when I press the button it renders the image nr 3 and apply the effects to image nr 3. I have tried to resolve this bug but with no success. Can someone help me? Bellow is some code.
Here is the image on the "web page"
<canvas id="currentImage" class="img-thumb center"></canvas>
I have an array of indexes with images from the folder and I iterate through it to change the image that is displayed. Below is the function how I change the image:
var onPreviousClick = function() {
var currentImageId = $currentImage.data('currentIndex');
if (currentImageId > 0) {
showImage(--currentImageId);
}
};
And this is how I apply the Lomo effect to the image:
$lomobtn.on('click', function() {
Caman('#currentImage', function() {
this.lomo().render();
});
});
I suppose that is something related to this. First time when I press the button it references to the first image, and second time when I press the button it also references to the first image.
UPDATE
I find out that I have to use the function reloadCanvasData() to refresh the data from canvas, but I can't find out how to use this function. https://github.com/meltingice/CamanJS/blob/master/src/core/caman.coffee#L387-L392
Can someone help me to use this function? Tried different methods to call this function and I receive and error.
This is a few months old question, but hopefully still relevant for you or someone else.
I had the same issue. Just use it like this:
$lomobtn.on('click', function() {
Caman('#currentImage', function() {
this.reloadCanvasData() // <--- here, before you apply your filter
this.lomo().render();
});
});
I'm trying at the moment to target multiple instances of the same div class (.overlay) - the basic idea I'm trying to execute is that each div contains a HTML5 video inside another wrapped div which on mouseenter reveals itself, sets the video timeline to 0 and plays, and on mouseout resets the video to 0 again.
The problem I'm having is that only the first item of my grid works at the moment with nothing happening on the rollover of the others. This is my Javascript:
$(document).ready(function() {
$('.overlay').mouseenter(function(){
$('#testvideo').get(0).play();
}).mouseout(function() {
$('#testvideo').get(0).pause();
$('#testvideo').get(0).currentTime = 0;
})
});
I've also tried the following
$(document).ready(function() {
$('.overlay').mouseenter.each(function(){
$('#testvideo').get(0).play();
}).mouseout(function() {
$('#testvideo').get(0).pause();
$('#testvideo').get(0).currentTime = 0;
})
});
but that simply broke the functionality all together!
Here is a fiddle showing what should happen: http://jsfiddle.net/jameshenry/ejmfydfy/
The only difference between this and the actual site is that there are multiple grid items and thumbnails. I also don't want the behaviour to by asynchronous but rather individual - does anyone have any idea where I'm going wrong (I'm guessing my javascript!)
The problem is that you're using always $('#testvideo'), independent on the div you're entering the mouse. Since the HTML's id property must be unique, only the first element that you set the id testvideo will work the way you expect.
You should be using the video tag referenced by the div.overlay, or you could add a CSS class to the video tags, so you could use that class to find the video.
The code below will get the overlayed video, independent of which it is.
$(document).ready(function() {
$('.overlay').hover(function() {
$(this).parent().find('video').get(0).play();
}, function() {
var video = $(this).parent().find('video').get(0);
video.pause();
video.currentTime = 0;
});
});
Take a look at your updated fiddle.
The first way you did it should work, the second one not. But, you shouldn't use an id like #testvideo if there are a lot of videos (one on each .overley element). Having multiple instances of the same id produce unexpected behaviuor, like "only working on the first item".
You should change your #testvideo with .testvideo and change your code to something like this:
$(document).ready(function() {
$('.overlay').mouseenter(function(){
$(this).find('.testvideo').play();
}).mouseout(function() {
$(this).find('.testvideo').pause();
$(this).find('.testvideo').currentTime = 0;
})
});
I have a webpage with images.
A user can click on images to show() or hyde() these images.
Sometimes, the user opens a popup to watch a video.
Then the code hide() all elements previously opened.
When the user closes the video, i need to know which elements was previously opened in order to show only them.
What is the best way to do that ?
What i've done :
I've created an array and i push images names into it.
var arr_popup_open = [];
Then, this function is called when user open a popup and hide all elements :
function toggleAllPopup() {
if( $('#popup_micro_1').is(":visible"))
{
$('#popup_micro_1').hide();
arr_popup_open.push('#popup_micro_1');
}
if( $('#popup_micro_2').is(":visible"))
{
$('#popup_micro_2').hide();
arr_popup_open.push('#popup_micro_2');
}
if( $('#popup_micro_3').is(":visible"))
{
$('#popup_micro_3').hide();
arr_popup_open.push('#popup_micro_3');
}
}
// and so on ... I have 7 images so it seems it's not very well optimized
When i need to show only images previously opened, i execute this code, a loop to show() elements in array.
$('#close_pop_up').click(function() {
for(var i= 0; i < arr_popup_open.length; i++)
{
$(arr_popup_open[i]).show();
}
});
What do you think about that ? Is there a better way to to do it ?
There are a few ways you could go about this with jQuery. Your way should work, but if you want to reduce the amount of code you could do something like:
var visibleDivs = $('div:visible', '#ContainerDiv');
Alternatively you could add a specific class to all visible elements when you show them and use:
var visibleDivs = $('.someClassName');
When hiding them due to your popup, you can store the list in the data of any element. In this case, putting it on #close_pop_up might make sense:
visibleDivs.hide();
$('#close_pop_up').data('myDivs', visibleDivs);
When you want to show them again in your click function:
$('#close_pop_up').click(function() {
$(this).data('myDivs').show();
});
Looks fine to me. Just remember to clear arr_popup_open in the start of the toggleopen function.
The alternative you could do if you really wanted is to keep the information of what is open or closed in Javascript variables that get updated when you open and close things. This way you don't need to depend on complex things such as is(:visible)
Simply put I'm trying to sync two slideshows created using widgetkit lib in a joomla website, eg. when user clicks next slide on one, the other one also runs nextSlide() function in the slideshow.js. Same for previous. The problems I'm having is widgetkit uses anonymous functions for creating those slideshows and I dont have global references to them after they are created. With my limited programming knowledge I cant seem to trigger the nextSlide function for other slideshows once inside click handler.
If anyone can take a look it would be most welcome.
EDIT:
Of course I forgot to link the example webpage
http://www.yootheme.com/widgetkit/examples/slideshow
Mine is similar with only 2 slideshows, but is still only on local server.
Taking a brief look at widgetkit here is one possible solution. Using jquery you can search for any objects that have a class of slides with a child of next and click all others. The code provided below isn't tested but should point you in the right direction. As long as you don't call stop propagation or prevent default then the original click handlers should still fire.
var slideshow_count = $('.slides .next').length;
var cascade_countdown = 0;
$('.slides .next').each(function() {
$(this).click(function() {
// stop an infinite loop if we're already cascading till we've done it for all the elements.
if(cascade_countdown != 0) {
cascade_countdown--;
return true;
}
// we don't include the slideshow we're clicking in this count
cascade_countdown = slideshow_count - 1;
var clicked_el = this;
$('.slides .next').each(function() {
// only click elements that aren't the initiator
if(this !== clicked_el) {
$(this).click();
}
});
});
});