The problem I have is a bit more complicated, so I have made a video that shows the behavior I am talking about.
As you can see what I want to achieve is to open a photo on a larger size upon clicking on it. As you can see it works ... well ... kind of. It behaves kind of weird because it seems to be lagging and not recording the onclick event very well. Sometimes it can record it faster sometimes slower, but not even once would it open the image on a single click as I would want it to. It takes at least two clicks. And I tried the code on a page that has no XML requests and it works on a single click (with a slight delay between the two console log calls though .. around 0.3 sec). And it also works on the chat page if I have a huge delay in refreshing the chat. But I would want to have it work with a single click on a refresh rate of 1 second.
The XML request is the following:
table2 = function(url, callback)
{
var request = new XMLHttpRequest();
request.onreadystatechange = function()
{
if (request.readyState == 4 && request.status == 200)
{
callback(request.responseText);
document.getElementById("scrollchat").innerHTML = this.responseText;
}
};
request.open('GET', url);
request.send();
}
function mycallback(data) {
//alert(data);
}
table2('load_chat.php', mycallback);
setInterval(function(){
table2('load_chat.php', mycallback);
}, 1700);
The items within the XML request file load_chat.php look like this:
<img src="image1.jpg" class="responsive" onclick="fullimagetry()">
<img src="image2.jpg" class="responsive" onclick="fullimagetry()">
<img src="image3.jpg" class="responsive" onclick="fullimagetry()">
<!-- And the list goes on as more images are being loaded. -->
My JS function that handles this is the following:
function fullimagetry() {
let photonameval = document.getElementsByClassName('responsive');
console.log("click");
document.querySelectorAll('.responsive').forEach((element, index) => {
element.addEventListener('click', function(event) {
console.log('Clicked element index:', index, 'Image path:',photonameval[index].src);
const fullPage = document.querySelector('#fullpage');
fullPage.style.backgroundImage = 'url(' + photonameval[index].src + ')';
fullPage.style.display = 'block';
});
});
}
Is there a better way to handle this? Maybe modify the fullimagetry() function and make it more efficient, or change something in the XML request itself? As you can see the request is made at 1.7s which is already too slow, but it makes things work at least on a double click. And I would want it to load at 1 second so that the user won't feel like the server is lagging. Looking forward to your response.
EDIT: I have to specify that I use XML for this because I don't know any other way to load elements on page without refreshing it. If you could provide me with an alternate way that is more efficient, I am keen to try it. I am still learning, and I go by what I can find on Youtube or W3Schools. Also that 1.7 delay is just set to make the opening of the photo more likely, the lower the value is the more click it needs to open (I know it's weird).
I can only give you a partial answer due to missing information. You should use some kind of an event delegation.
You should not add an addEventListener
to every image but simply to the chat container and check if the clicked element was an image. That way you will be more time efficient and you can execute the script from the start on. You can add images dynamically without having to re-execute the function.
You're using:
function fullimagetry() {
let photonameval = document.getElementsByClassName('responsive');
document.querySelectorAll('.responsive').forEach((element, index) => {
element.addEventListener('click', function(event) {
//...
)}
})
}
that is highly inefficient. Every time you click on an image, you create a List (HTML Collection Object
) and then create an (almost) identical list (Node List
) of all images.
After that, you attach an event listener to every image. There is no reason for all of that the function fullimagetry
already can be referenced to a single image. Next, you set up 2 lists when one would be sufficient. All of that cost unnecessary time!
So you should optimize your code by not adding an event listener to every image but simply only getting the image you clicked on. For that, you don't even need any kind of list as you already have the exact element you want to work with!
ChatContainer.addEventListener('click', function(element) {
if (element.target.tagName === 'IMG') {
FullPage.style.backgroundImage = `url(${element.target.src})`;
FullPage.classList.add('d-block');
}
})
FullPage.addEventListener('click', function() {
this.classList.remove('d-block');
})
#FullPage {
position: fixed;
inset: 0;
z-index: 100;
display: none;
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
background-size: contain;
background-color: black;
&.d-block {
display: block;
}
}
<div id="ChatContainer">
<img src="https://placehold.co/600x400/FF0000/FFFFFF/png">
<img src="https://placehold.co/600x400/00FF00/FFFFFF/png">
<img src="https://placehold.co/600x400/0000FF/FFFFFF/png">
</div>
<div id="FullPage"></div>
For Optimizing your XML request into a fetch
and reducing the loading times on that part, I would need to know exactly what your data package looks like. But I'm already pretty confident that with the optimized code you don't even need the 1.7sec delay anymore!