简体   繁体   中英

Using mod to wrap around

Assume the array has a length of 1000. I am trying to create a simple way to traverse the image paths stored in the array without going out of bounds. The method below handles the wrap around using modulus well when it comes to clicking the 'next' button to increment array index, but not when I have to decrement and deduct one from the index (when the user clicks the previous button).

Basically what I am trying to do is:

998 -> click next -> 999
999 -> click next -> 0
0 -> click previous -> 999

My Javacript

var index = 0;

$('.catalog-img-container').attr("src", javascript_array[index]);
$(".next").click(function(){
        $('.catalog-img-container').attr("src", javascript_array[++index%arrayLength]);
    });         
$(".previous").click(function(){
    $('.catalog-img-container').attr("src", javascript_array[--index]);
    alert(index);

I appreciate any help with

Many thank in advance.

There might be a more elegant way around this, but this is simple:

$(".previous").click(function(){
    if (--index < 0) index = arrayLength - 1;
    $('.catalog-img-container').attr("src", javascript_array[index%arrayLength]);
}); 

Since --index%arrayLength doesn't work, just add the length of the array prior to taking the modulo:

index = (index+arrayLength-1) % arrayLength

You could also do

(index+=arrayLength-1)%arrayLength

but this will lead to index getting very large, possibly out of range over enough time.

You can also use a handy object for it.

var Cursor = function (array) {
  var idx = 0;
  this.prev = function () {
    idx = (!!idx ? idx : array.length) - 1;
    return array[idx];
  };
  this.current = function () {
    return array[idx];
  };
  this.next = function () {
    idx = (idx + 1) % array.length;
    return array[idx];
  };
  return this;
};

For example,

var $container = $(".catalog-img-container");
var cursor = new Cursor(javascript_array);

$container.attr("src", cursor.current());

$(".next").click(function(){
  $container.attr("src", cursor.next());
});         

$(".previous").click(function(){
  $container.attr("src", cursor.prev());
});

Umm, not sure if this is what you wanted but:

$(".previous").click(function(){if (index-1 <0){index = arrayLength -1;}

            $('.catalog-img-container').attr("src", javascript_array[--index]);
            //alert(index);
        });  

I am assuming arrayLength = javascript_array.length;

I hope this helps

WORKING DEMO TEST

This is all you need:

var index=0;

$('.catalog-img-container').attr("src", javascript_array[index]);

$(".next, .previous").click(function(){

  var MyClass = $(this).hasClass('next') ? index++ : index-- ;
  index = index==-1 ? arrayLength-1 : index%arrayLength ;  
  $('.catalog-img-container').attr("src", javascript_array[index]);

}); 
/**
* @param {number} counter
* @param {number} maxValue
* @return {number}
* @desc Always returns a number between 0 and maxValue. Can be used to 
iterate through an array without "Range out of bounds" error.
*/
export default function mapToRange(counter, maxValue) {
  if (maxValue === undefined || maxValue === 0) return 0;
  // positive counter
  if (counter >= 0) return counter % maxValue;
  // negative counter
  const modulo = counter % maxValue;
  if (modulo === 0) {
      return modulo;
  }
  return modulo + maxValue;
}

I use this function to map the counter , a int number to the range between 0 and maxValue .

let counter = 0;
const array = ['apple', 'pear','peach'];
if(press arrow up) counter--;
else if (press arrow down) counter++;

let idx = mapInRange(counter, array.length)
console.log(array[idx]);

Imagine you have a drop down list and you want to navigate through the list with arrow keys.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM