Skip to content
Advertisement

Change image with and js

I have a small slider that switches the preview image to the main image. It works fine now

blade.php

<div class="custom-carousel-section">
  <div class="custom-container">
    <div class="custom-carousel">
      @if(!empty($article_block_images)) @foreach($article_block_images as $article_block_image)
      <div class="custom-carousel__title">
        @if($loop->first)
          <span>{{ $article_block_image->title }}</span>
        @endif
      </div>
      @endforeach @endif
      @if(!empty($article_block_images)) @foreach($article_block_images as $article_block_image)
      <div class="main-image">
      @if($loop->first)
          <img src="{{ $article_block_image->main_image }}" alt="{{ $article_block_image->image_alt }}" title="{{ $article_block_image->image_title }}" data-title="{{ $article_block_image->title }}">
      @endif
      </div>
      @endforeach @endif
      <div class="img-to-select">
        @if(!empty($article_block_images)) @foreach($article_block_images as $article_block_image)
        <div @if($loop->first) class="img-to-select__item  selected" @else class="img-to-select__item" @endif>
          <img src="{{ $article_block_image->preview_image }}" alt="{{ $article_block_image->image_alt }}" title="{{ $article_block_image->image_title }}" data-title="{{ $article_block_image->title }}" data-main-src="{{ $article_block_image->main_image }}">
        </div>
        @endforeach @endif
      </div>
    </div>
  </div>
</div>

js

$('.img-to-select__item').click(function () {
$('.img-to-select__item').removeClass('selected');
$(this).addClass('selected');
$('.main-image > img').attr('src', $(this).children('img').data('main-src'));
$('.custom-carousel__title > span').html($(this).children('img').attr('data-title'));
});

But I still have a picture mobile_image, and I want the mobile_image to change instead of main_image at the maximum size of 576px, for this I use <picture>

I change my code to like this

<div class="main-image">
@if($loop->first)
<picture>
  <source srcset="{{ $article_block_image->mobile_image }}" media="(max-width: 576px)" alt="{{ $article_block_image->image_alt }}" title="{{ $article_block_image->image_title }}" data-title="{{ $article_block_image->title }}">
  <source srcset="{{ $article_block_image->main_image }}" alt="{{ $article_block_image->image_alt }}" title="{{ $article_block_image->image_title }}" data-title="{{ $article_block_image->title }}">
  <img src="{{ $article_block_image->main_image }}" alt="{{ $article_block_image->image_alt }}" title="{{ $article_block_image->image_title }}" data-title="{{ $article_block_image->title }}">
</picture>
@endif
</div>

But my slider just stops working

The main image eventually changes to mobile, but the slider itself does not switch

In this case, the preview images also echo, but the main image itself does not change

My slider essentially works like this

https://jsfiddle.net/a9yvdu75/

I just need to put what in the main-image class in <picture> and change the image depending on the screen size

Advertisement

Answer

This line is problematic:

$('.main-image > img').attr('src', $(this).children('img').data('main-src'));

The symbol > means that img must be an immediate child of .main-image. So you have to choose one of the selectors $('.main-image img') or $('.main-image > picture > img'). But that still won’t work because…

The second problem is that you don’t fully understand how <picture> works. The browser chooses <source> to display itself, based on the rules in media. And the same <img> is only for browsers, which doesn’t support <picture>. So setting .attr('src' only works if you remove all <source>.

Also in many places you use .children('img').

So if you want to do such substitutions, you have to remove responsive image selection.

I believe the quickest solution for you is to use an alternative syntax. (You will still need to programmatically remove srcset, sizes)

<img srcset="elva-fairy-480w.jpg 480w,
             elva-fairy-800w.jpg 800w"
     sizes="(max-width: 600px) 480px,
            800px"
     src="elva-fairy-800w.jpg"
     alt="Elva dressed as a fairy">

Another alternative is to swap the entire .main-image section. eg.:

<div class="main-image">
  <picture>
    <!-- placeholder, insert the correct HTML yourself  -->
  </picture>
</div>

And using JS like:

$('.main-image > picture').html(`
  <source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">
  <source media="(min-width: 800px)" srcset="elva-800w.jpg">
  <img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">
`)

You must store “desktop” and mobile sources in the thumbnail.

<div @if($loop->first) class="img-to-select__item  selected" @else class="img-to-select__item" @endif>
  <img src="{{ $article_block_image->preview_image }}" 
    ... 
    data-main-src="{{ $article_block_image->main_image }}" 
    data-mobile-src="{{ $article_block_image->mobile_image }}"
  >
</div>

The rest is just tedious gluing of strings.

//EDIT: one of possible solutions.

$('.img-to-select__item').click(function () {
  $('.img-to-select__item').removeClass('selected');
  $(this).addClass('selected');
  let mainSrc = $(this).children('img').data('main-src')
  let mobileSrc = $(this).children('img').data('mobile-src')
  let title = $(this).children('img').attr('title')
  let alt = $(this).children('img').attr('alt')
  $('.main-image > picture').html(`
    <source srcset="{$mobileSrc}" media="(max-width: 576px)" alt="{$alt}" title="{$title}">
    <source srcset="{$mainSrc}" alt="{$alt}" title="{$title}">
    <img src="{$mainSrc}" alt="{$alt}" title="{$title}">
  `);
  $('.custom-carousel__title > span').html($(this).children('img').attr('data-title'));
});

Remember, in JS you work with already generated HTML (provided data), you do not have access to PHP variables.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement