Home > Mobile >  How can I encapsulate my code, so I can pass arguments from one function to another?
How can I encapsulate my code, so I can pass arguments from one function to another?

Time:02-06

I wrote this simple carousel but without encapsulation. So previously I placed items from buttonControl() in global scope and added eventListeners on global scope, which are now emraced in prev() and next() functions. However, my encapsulation breaks the code. Because arguments from buttonControl() aren't global but prev() and next() needs them to work. I thought that maybe I can pass all arguments from buttonsControl() inside addEventListener('click', prev) but I cannot, because when I write thisaddEventListener('click', prev(slides,totalItems,allItems....)) it is launching this event without a click.And I even don't know if its correct way.

I thought of puting arguments from buttonsControl() inside prev() and next() but it won't work.


function buttonsControl(){
const slides = document.querySelector('.slides');
const totalItems = document.querySelectorAll('.slides>*').length - 1;
const allItems = document.querySelectorAll('.slides>*').length;
console.log(totalItems)
let activeItem = 0;

let controlCarouselFooter = document.querySelector('.carousel_footer');
controlCarouselFooter.innerHTML = `1 / ${allItems}`
console.log(controlCarouselFooter)
const prevButton = document.querySelector('.prev_button').addEventListener('click', prev)
const nextButton = document.querySelector('.next_button').addEventListener('click', next)
// no idea how to pass those arguments
}

// Buttons controls

function prev(){
// const prevButton = document.querySelector('.prev_button').addEventListener('click', () => {
 
if (activeItem === 0) {
    activeItem = totalItems;
    slides.style.transform = `translateX(-${totalItems * 100}%)`;
    console.log(`if ${activeItem}`)
    controlCarouselFooter.innerHTML = `${activeItem 1} / ${allItems}`
  }else {
    activeItem--;
    slides.style.transform = `translateX(-${activeItem * 100}%)`;
    console.log(`else ${activeItem}`)
    controlCarouselFooter.innerHTML = `${activeItem 1} / ${allItems} `
  }
  }
//   );
// }

function next(){
  // const nextButton = document.querySelector('.next_button').addEventListener('click', () => {
 
  if(activeItem < totalItems) {
    activeItem  ;
      slides.style.transform = `translateX(-${activeItem * 100}%)`;
      console.log(`if ${activeItem}`)
      controlCarouselFooter.innerHTML = `${activeItem 1} / ${allItems}`
  } else {
    activeItem = 0;
    slides.style.transform = 'none';
    console.log(`else ${activeItem 1}`)
    console.log(`totalItems ${totalItems}`)
    controlCarouselFooter.innerHTML = `${activeItem 1} / ${allItems}`
  }
}
// );
// };
// });
buttonsControl();

CodePudding user response:

The easiest solution would be to define the functions prev and next inside the buttonsControl function, so that all its local variables are in scope through closure:

function buttonsControl() {
  const slides = document.querySelector('.slides');
  const totalItems = document.querySelectorAll('.slides>*').length - 1;
  const allItems = document.querySelectorAll('.slides>*').length;

  let activeItem = 0;
  let controlCarouselFooter = document.querySelector('.carousel_footer');

  controlCarouselFooter.innerHTML = `1 / ${allItems}`;

  const prevButton = document.querySelector('.prev_button').addEventListener('click', prev);
  const nextButton = document.querySelector('.next_button').addEventListener('click', next);
    
  // Buttons controls
  function prev() {
    if (activeItem === 0) {
      activeItem = totalItems;
    } else {
      activeItem--;
    }
    slides.style.transform = `translateX(-${totalItems * 100}%)`;
    controlCarouselFooter.innerHTML = `${activeItem 1} / ${allItems}`
  } 
  function next() {
    if (activeItem < totalItems) {
      activeItem  ;
      slides.style.transform = `translateX(-${activeItem * 100}%)`;
    } else {
      activeItem = 0;
      slides.style.transform = 'none';
    }
    controlCarouselFooter.innerHTML = `${activeItem 1} / ${allItems}`
  }
}
buttonsControl();

CodePudding user response:

If I'm understanding your question correctly, You could bind the variables to the listeners.

EDIT: Someone pointed out that you're mutating activeItems. Which is true. So You will want to define all your variables on an object first so that mutation is persistent between function calls.

function buttonsControl(){
let obj = {};
obj.slides = document.querySelector('.slides');
obj.totalItems = document.querySelectorAll('.slides>*').length - 1;
obj.allItems = document.querySelectorAll('.slides>*').length;
console.log(obj.totalItems)
obj.activeItem = 0;

obj.controlCarouselFooter = document.querySelector('.carousel_footer');
controlCarouselFooter.innerHTML = `1 / ${allItems}`
console.log(controlCarouselFooter)

//bind the variables you want to use to your input
const prevButton = document.querySelector('.prev_button').addEventListener('click', prev.bind(null, obj))
const nextButton = document.querySelector('.next_button').addEventListener('click', next.bind(null, obj))
// no idea how to pass those arguments
}

// Buttons controls

function prev(obj){
//define the arguments in your fn params. 
// const prevButton = document.querySelector('.prev_button').addEventListener('click', () => {
 
if (obj.activeItem === 0) {
    obj.activeItem = totalItems;
    obj.slides.style.transform = `translateX(-${totalItems * 100}%)`;
    console.log(`if ${activeItem}`)
    obj.controlCarouselFooter.innerHTML = `${obj.activeItem 1} / ${obj.allItems}`
  }else {
    obj.activeItem--;
    obj.slides.style.transform = `translateX(-${activeItem * 100}%)`;
    console.log(`else ${obj.activeItem}`)
    obj.controlCarouselFooter.innerHTML = `${obj.activeItem 1} / ${obj.allItems} `
  }
  }
//   );
// }

function next(obj){
  ...similar implimentation to prev()
}
// );
// };
// });
buttonsControl();
  • Related