3

I have the same slider on my site on two pages, for which one common js file is used

 // Slider
 const slider = document.getElementById('generalSlider');
 const sliderRow = document.getElementById('generalSliderRow');
 const slides = document.querySelectorAll('.general');
 const INTERVAL = 6000;
 let timer = null;
 
 initSlider(slider, sliderRow, slides);
 
 function initSlider(slider, sliderRow, slides) {
     const slidesLength = slides.length;
 
     let allowShift = true;
     const CLONES_COUNT = 1;
     let slideWidth = slider.offsetWidth;
     const firstSlide = slides[0];
 
     let currentOffset = -slideWidth * CLONES_COUNT;
     let currentIndex = 1;
 
     slides.forEach(slide => {
         slide.style.width = slideWidth + 'px';
     });
 
     const appendSlides = [];
     const prependSlides = [];
 
     for (let i = 1; i <= CLONES_COUNT; i++) {
         prependSlides.push(slides[slidesLength - i].cloneNode(true));
         appendSlides.push(slides[i - 1].cloneNode(true));
     }
 
     prependSlides.reverse().forEach(slide => {
         sliderRow.insertBefore(slide, firstSlide);
     });
 
     appendSlides.forEach(slide => {
         sliderRow.appendChild(slide);
     });
 
     sliderRow.style.width = (slideWidth * (slidesLength + CLONES_COUNT * 2)) + 'px';
     sliderRow.style.transform = `translateX(${currentOffset}px)`;
 
     document.querySelector(`.general:nth-child(${currentIndex + CLONES_COUNT})`).classList.add('active');
     document.getElementById('navText').innerHTML = `${currentIndex} of ${slidesLength}`;
 
     const prevArrow = document.getElementById('prevArrow');
     const nextArrow = document.getElementById('nextArrow');
 
     prevArrow.addEventListener('click', () => {
         shiftSlide(-1);
         stopAutoplay();
     });
 
     nextArrow.addEventListener('click', () => {
         shiftSlide(1);
         stopAutoplay();
     });
 
     sliderRow.addEventListener('transitionend', checkIndex);
     sliderRow.addEventListener('click', stopAutoplay);
 
     function shiftSlide(dir, action = null) {
         sliderRow.classList.add('shifting');
 
         if (action) {
             currentOffset = posInitial;
         }
 
         if (allowShift) {
             if (dir === 1) {
                 currentOffset -= slideWidth;
                 sliderRow.style.transform = `translateX(${currentOffset}px)`;
                 currentIndex++;
             } else if (dir === -1) {
                 currentOffset += slideWidth;
                 sliderRow.style.transform = `translateX(${currentOffset}px)`;
                 currentIndex--;
             }
 
             document.querySelector('.general.active').classList.remove('active');
             document.querySelector(`.general:nth-child(${currentIndex + CLONES_COUNT})`).classList.add('active');
         }
 
         allowShift = false;
     }
 
     function checkIndex (){
         sliderRow.classList.remove('shifting');
 
         if (currentIndex === 0) {
             currentOffset = (-slideWidth * CLONES_COUNT) + (-slideWidth * (slidesLength - 1));
             sliderRow.style.transform = `translateX(${currentOffset}px)`;
             currentIndex = slidesLength;
         }
 
         if (currentIndex > slidesLength) {
             currentOffset = -slideWidth * CLONES_COUNT;
             sliderRow.style.transform = `translateX(${currentOffset}px)`;
             currentIndex = 1;
         }
 
         document.getElementById('navText').innerHTML = `${currentIndex} of ${slidesLength}`;
         document.querySelector('.general.active').classList.remove('active');
         document.querySelector(`.general:nth-child(${currentIndex + CLONES_COUNT})`).classList.add('active');
 
         allowShift = true;
     }
 
     let posX1 = 0;
     let posX2 = 0;
     let posInitial;
     let posFinal;
     const threshold = 100;
 
     // sliderRow.onmousedown = dragStart;
     // sliderRow.addEventListener('touchstart', dragStart);
     // sliderRow.addEventListener('touchend', dragEnd);
     // sliderRow.addEventListener('touchmove', dragAction);
 
     function dragStart (e) {
         e = e || window.event;
         e.preventDefault();
         if (!allowShift) {
             return;
         }
         posInitial = currentOffset;
 
         if (e.type == 'touchstart') {
             posX1 = e.touches[0].clientX;
         } else {
             posX1 = e.clientX;
             document.onmouseup = dragEnd;
             document.onmousemove = dragAction;
         }
     }
 
     function dragAction (e) {
         e = e || window.event;
 
         if (e.type == 'touchmove') {
             posX2 = posX1 - e.touches[0].clientX;
             posX1 = e.touches[0].clientX;
         } else {
             posX2 = posX1 - e.clientX;
             posX1 = e.clientX;
         }
         currentOffset = currentOffset - posX2;
         sliderRow.style.transform = `translateX(${currentOffset}px)`;
     }
 
     function dragEnd (e) {
         posFinal = currentOffset;
         if (posFinal - posInitial < -threshold) {
             shiftSlide(1, 'drag');
         } else if (posFinal - posInitial > threshold) {
             shiftSlide(-1, 'drag');
         } else {
             currentOffset = posInitial;
             sliderRow.style.transform = `translateX(${currentOffset}px)`;
         }
 
         document.onmouseup = null;
         document.onmousemove = null;
     }
 
     window.addEventListener('resize', () => {
         resizeSlider();
     })
 
     function resizeSlider() {
         const newSlideWidth = slider.offsetWidth;
 
         if (newSlideWidth === slideWidth) return;
 
         slideWidth = newSlideWidth;
 
         document.querySelectorAll('.general').forEach(slide => {
             slide.style.width = slideWidth + 'px';
         });
 
         currentOffset = (-slideWidth * CLONES_COUNT) + (-slideWidth * (currentIndex - 1));
 
         sliderRow.style.width = (slideWidth * (slidesLength + CLONES_COUNT * 2)) + 'px';
         sliderRow.style.transform = `translateX(${currentOffset}px)`;
     }
 
     function startAutoplay() {
         timer = setInterval(() => {
             shiftSlide(1);
         }, INTERVAL)
     }
 
     function stopAutoplay() {
         clearInterval(timer);
         timer = null;
     }
 
     startAutoplay();
 }

But now on one of the pages I need to slightly change the js file, but literally a couple of lines of code

I need to add this

let CLONES_COUNT;

if (slidesLength < 2) {
    CLONES_COUNT = 0;
} else {
    CLONES_COUNT = 1;
}

and

if (slidesLength > 1) {
    startAutoplay();
}

Is it possible to make some condition to use a specific piece of code in a js file for a specific page? so as not to make exactly the same file where there will be minimal changes

Something like

if (RouteName() === 'home') {
const CLONES_COUNT = 1;
}

if (RouteName() === 'blog'){
let CLONES_COUNT;

if (slidesLength < 2) {
    CLONES_COUNT = 0;
} else {
    CLONES_COUNT = 1;
}
}

js

function initSlider(slider, sliderRow, slides, CLONES_COUNT, doAutoPlay) {
. . .
}

blade.php

@section('scripts')
<script src="/js/slider.js"></script>
<script defer>$( document ).ready(function() {initSlider(slider, sliderRow, slides, (slides.length < 2) ? 0 : 1, slides.length > 1)})</script>
@endsection
  • 1
    Isn't it `slidesLength` is decided by `slides`, and `CLONES_COUNT` is determined by `slidesLength`? So that's all down to `slides`, which is already a parameter? And if each page has different `slides`, `slidesLength` and `CLONES_COUNT` will be changed accordingly? What is the problem if you just put additional script to the existing JS file? – Huy Phạm Nov 23 '21 at 12:03

2 Answers2

0

You could add a parameter to your initSlider function, and remove the calling of it from your common.js

function initSlider(slider, sliderRow, slides, CLONES_COUNT) {
  // ...
}

And then call it on home with initSlider(slider, sliderRow, slides, 1) or on blog with:

const CLONES_COUNT = (slidesLength < 2) ? 0 : 1;
initSlider(slider, sliderRow, slides, CLONES_COUNT);

This gives the option to configure it differently on different pages in the future as well.

Pjetr
  • 1,372
  • 10
  • 20
  • okay, thanks, but how to do this, on one page this function `startAutoplay();` should be launched immediately, and on the other only if `slidesLength > 1` –  Nov 23 '21 at 11:49
  • You could add another parameter `function initSlider(slider, sliderRow, slides, CLONES_COUNT, doAutoPlay)` where if true, call the function at the end of initializing your slider. On your blog page you can simply use `initSlider(slider, sliderRow, slides, (slides.length < 2) ? 0 : 1, slides.length > 1);` – Pjetr Nov 23 '21 at 11:55
  • I understood everything, thanks, but here's another, but where exactly to call `initSlider` for different pages, right on the page itself? sorry, I just never did this before –  Nov 23 '21 at 12:01
  • here is my `blog.blade.php` page, how can I call `initSlider` right in it –  Nov 23 '21 at 12:01
  • I can't see your php file, but basically, let php print out a script-tag `` – Pjetr Nov 23 '21 at 12:07
  • okay, I understand, I will try to do, thanks –  Nov 23 '21 at 12:09
  • unfortunately it is not pulled up in this way `` –  Nov 23 '21 at 12:27
  • I have a laravel environment, here is a regular php page where at the end there is a section with scripts where I am trying to pull up –  Nov 23 '21 at 12:30
  • `@section('scripts') @endsection` –  Nov 23 '21 at 12:30
  • Can you update your question, so I can see how and what you tried, and if possible, also share the errors you've had. – Pjetr Nov 23 '21 at 12:30
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/239481/discussion-between-pjetr-and-meow). – Pjetr Nov 23 '21 at 12:31
-1

Using pathname property of the Location interface, you can try this :

if (window.location.pathname.startWith('/home')) {
  const CLONES_COUNT = 1;
}

if (window.location.pathname.startWith('/blog')){
  let CLONES_COUNT;

  if (slidesLength < 2) {
    CLONES_COUNT = 0;
  } else {
    CLONES_COUNT = 1;
  }
}
Tom
  • 4,972
  • 3
  • 10
  • 28
  • unfortunately does not work, what is not applied in `if` at all –  Nov 23 '21 at 11:27
  • Is there some way to do this without using routes? –  Nov 23 '21 at 11:28
  • @meow can you share URLs of both of your pages please ? And if you really don't want to use URL, you can take a look at [this answer](https://stackoverflow.com/a/9034365/16688813) that could do the trick. – Tom Nov 23 '21 at 11:36
  • `Route::get('/', 'App\Http\Controllers\HomeController@index')->name('home');` –  Nov 23 '21 at 11:39
  • `Route::get('/blog/{slug}', 'App\Http\Controllers\ArticleController@index')->name('blog/{slug}');` –  Nov 23 '21 at 11:39
  • @meow I meant what you get in your browser like `https://stackoverflow.com/questions/69505790/` – Tom Nov 23 '21 at 11:45
  • `https://test.loc/` and `https://test.loc/blog/article_1` –  Nov 23 '21 at 11:47
  • I think this is **really** bad advice, for starters this will result in an undefined variable if the pages change paths, or if another page loads this script. Furthermore does it put setup per page to an obscure location for everyone who would later review the code. – Pjetr Nov 23 '21 at 12:03