2
votes

A pure JS question.

When the page loads, small thumbnail images are loaded (webp or jpg). When one clicks on an image (picture element) - two things happen: picture element changes class to large (and css resizes it) and srcset string of the small file is edited to point to a larger file ('-large.webp' is the end of string). And once the image is clicked on again the srcset string should be again edited to point to the small file ('.webp' should be the end of string). However this last thing does not happen, rather the srcset string get another '-large.webp' now pointing to a non existing file.

A page has a lots of images and I need to load big file only on click. Lazy loading doesn't help because scrolling is not the event I want to trigger them.

I suppose my logic in the if else loop is faulty ... but it may be something else?

Any help appreciated.

function toggleImages() {
    var images = document.querySelectorAll('figure picture');
    for(var i =0; i< images.length; i++){
        
        images[i].onclick = function() {

            // resize the container 
            this.classList.toggle('thumb');
            this.classList.toggle('large');

            // img and source DOM elements
            var imgtag = this.querySelector('img');
            var sourcetag = this.querySelector('source');
            
            // get urls of small image files
            var thumbsourceJpg = imgtag.getAttribute('src');
            var thumbsourceWebp = sourcetag.getAttribute('srcset');

            // strip the last 4 chars (extension and dot)
            var noJpg = thumbsourceJpg.slice(0,-4);
            var noWebp = thumbsourceWebp.slice(0,-5);
            
            // change ending of urls to point to larger image            
            var largesourceJpg = noJpg + '-large.jpg';
            var largesourceWebp = noWebp + '-large.webp';

            // if srcset points to small file
            if (sourcetag.srcset == thumbsourceWebp) {
                // make it point to a large one
                sourcetag.srcset = largesourceWebp;
                } else {
                    // otherwise point to the small file
                    sourcetag.srcset = thumbsourceWebp;
                }
            
            // do the same for jpgs (this doesnt work at all)
            if (imgtag.src == thumbsourceJpg) {
                imgtag.src = largesourceJpg;
                } else {
                    imgtag.src = thumbsourceJpg;
                }

            }
        
        }
    }
    
window.onload = function() {
toggleImages();

}
figure picture {background: gray;}

figure picture.large{
        width: 608px;
        -moz-transition: all .5s ease;
        -webkit-transition: all .5s ease;
        -o-transition: all .5s ease;
        transition: all .5s ease;  
    }
    
figure picture.thumb {
    width: 180px;
    cursor:pointer;
}
<!DOCTYPE html>
<html>
<body>
<figure>
  <picture class="thumb">
    <source type="image/webp" srcset="https://fokusgrupa.net/files/file1.webp">
    <img src="https://fokusgrupa.net/files/file1.jpg" alt="description">
  </picture>

  <picture class="thumb">
    <source type="image/webp" srcset="https://fokusgrupa.net/files/file2.webp">
    <img src="https://fokusgrupa.net/files/file2.jpg" alt="description">
  </picture>
</figure>
</body>
2

2 Answers

0
votes

You are actually adding -large to your path each time you are clicking in an image. As a solution you could use an IFEE to store your image path variable in an outer scope, so you don't have to get its value from html element each time you click it.

function toggleImages() {
    var images = document.querySelectorAll('figure picture');
    for(var i =0; i< images.length; i++){
        
        images[i].onclick = ((image) => {
            var imgtag = image.querySelector('img');
            var sourcetag = image.querySelector('source');

            var thumbsourceJpg = imgtag.getAttribute('src');
            var thumbsourceWebp = sourcetag.getAttribute('srcset');
            
            return function() {

                // resize the container 
                this.classList.toggle('thumb');
                this.classList.toggle('large');

                // strip the last 4 chars (extension and dot)
                var noJpg = thumbsourceJpg.slice(0,-4); // getting from outer scope instead of html element
                var noWebp = thumbsourceWebp.slice(0,-5);

                // change ending of urls to point to larger image            
                var largesourceJpg = noJpg + '-large.jpg';
                var largesourceWebp = noWebp + '-large.webp';

                // if srcset points to small file
                if (sourcetag.srcset == thumbsourceWebp) {
                    // make it point to a large one
                    sourcetag.srcset = largesourceWebp;
                    } else {
                        // otherwise point to the small file
                        sourcetag.srcset = thumbsourceWebp;
                    }

                // do the same for jpgs (this doesnt work at all)
                if (imgtag.src == thumbsourceJpg) {
                    imgtag.src = largesourceJpg;
                    } else {
                        imgtag.src = thumbsourceJpg;
                    }

            }
        
        })(images[i]);
    }
}
    
window.onload = function() {
toggleImages();

}
figure picture {background: gray;}

figure picture.large{
        width: 608px;
        -moz-transition: all .5s ease;
        -webkit-transition: all .5s ease;
        -o-transition: all .5s ease;
        transition: all .5s ease;  
    }
    
figure picture.thumb {
    width: 180px;
    cursor:pointer;
}
<!DOCTYPE html>
<html>
<body>
<figure>
  <picture class="thumb">
    <source type="image/webp" srcset="https://fokusgrupa.net/files/file1.webp">
    <img src="https://fokusgrupa.net/files/file1.jpg" alt="description">
  </picture>

  <picture class="thumb">
    <source type="image/webp" srcset="https://fokusgrupa.net/files/file2.webp">
    <img src="https://fokusgrupa.net/files/file2.jpg" alt="description">
  </picture>
</figure>
</body>
0
votes

Since you need to toggle the filenames to either include "-large" or not depending on what the src or srcset attribute value is at the time of the click, you need to check those strings before you either add or remove that substring. You could use the URL constructor and some basic string operations to handle inserting or removing the substring.

function toggleURL(s) {
  var url = new URL(s);
  var path = url.pathname.split('/');
  var filename = path[path.length - 1];
  var index = filename.lastIndexOf('-large');
  if (index !== -1) {
    filename = filename.slice(0, index) + filename.slice(index + 6);
  } else {
    index = filename.lastIndexOf('.');
    filename = filename.slice(0, index) + '-large' + filename.slice(index);
  }
  
  path[path.length - 1] = filename;
  url.pathname = path.join('/');
  return url.href;
}

window.onload = function() {
  var images = document.querySelectorAll('figure picture');
  for (var i = 0; i < images.length; i++) {
    images[i].onclick = function() {
      var img = this.querySelector('img');
      var source = this.querySelector('source');
      img.src = toggleURL(img.getAttribute('src'));
      source.srcset = toggleURL(source.getAttribute('srcset'));
      this.classList.toggle('thumb');
      this.classList.toggle('large');

    }

  }
  
}
figure picture {
  background: gray;
}

figure picture.large {
  width: 608px;
  -moz-transition: all .5s ease;
  -webkit-transition: all .5s ease;
  -o-transition: all .5s ease;
  transition: all .5s ease;
}

figure picture.thumb {
  width: 180px;
  cursor: pointer;
}
<figure>
  <picture class="thumb">
    <source type="image/webp" srcset="https://fokusgrupa.net/files/file1.webp">
    <img src="https://fokusgrupa.net/files/file1.jpg" alt="description">
  </picture>

  <picture class="thumb">
    <source type="image/webp" srcset="https://fokusgrupa.net/files/file2.webp">
    <img src="https://fokusgrupa.net/files/file2.jpg" alt="description">
  </picture>
</figure>