2

I am using hotkeys plugin to add handlers to key events. I have made an image slider, where I go through cover images of magazines. I have first made a script where the user can go through covers of a magazine, with a click on navigation buttons.

$(document).ready(function () {
  imagesIndex = 0,
  nextImage = 0,
  loadedImages = [];

  if (typeof images !== 'undefined') {

    preload();

    $('#forward').click(forwardClick);
    $('#back').click(backClick);
  }
});

var preload = function () {
  for (i = 0; i < 4; i++) {
    if (nextImage < images.length) {
        var img = new Image();
        img.src = '/imagecache/cover/' + images[nextImage];
        loadedImages[nextImage] = img;
        ++nextImage;
    }
  }
}

var forwardClick = function() {
  imagesIndex++;

  preload();
  $('#back').removeClass('not-allowed');

  if (imagesIndex > (loadedImages.length - 1)) {
      imagesIndex = loadedImages.length - 1;
  }

  if (imagesIndex > (loadedImages.length - 2)) {
      $('#forward').addClass('not-allowed');
  }

  $('#cover-image').attr({"src" : loadedImages[imagesIndex].src, "alt" : name});
}

var backClick = function() {
  imagesIndex--;

  $('#forward').removeClass('not-allowed');

  if (imagesIndex < 0) {
      imagesIndex = 0;
  }

  if (imagesIndex < 1) {
      $('#back').addClass('not-allowed');
  }

  $('#cover-image').attr({"src" : loadedImages[imagesIndex].src, "alt" : name});
}

module.exports.preload = preload;
module.exports.forward = forwardClick;
module.exports.back = backClick;

That works fine, I have a selection of magazines, where when a user clicks on one, gets scrolled to a section where the magazine details that a user has clicked on are created. I am dynamically changing that section each time a user clicks on some magazine, and updating the details with the magazine that was clicked. There a user can go through covers of that magazine on click of navigation buttons. So, each time a user clicks on some new magazine, I am calling this function:

var showMagazineDetail = function showMagazineDetail(id, slug, name, summary, issueImage, magazineImage, visiolinkPrefix, page){
    images = [];
    nextImage = 0;
    imagesIndex = 0;
    loadedImages = [];

    ...rest of the code

Here I am emptying the images and loadedImages arrays. So, this part works fine. The problem I have is with key events. I have made this script, where I check if the section is in the viewport, and then enable going through the covers of the magazine.

var issueImages = require('./issue-images');
var forward = issueImages.forward;
var back = issueImages.back;

$(document).ready(function () {
  var coverImage = $('.magazine-hero');
  window.onscroll = function() {
    var coverVisible = isElementInViewport(coverImage);

    if (coverVisible) {
      $(document).on('keyup', null, 'right', forward);
      $(document).on('keyup', null, 'left', back);
    }
  };

});


function isElementInViewport(el) {
  var rect = el[0].getBoundingClientRect();

  return rect.bottom > rect.height*0.8 &&
        rect.top < ((window.innerHeight*0.7) || (document.documentElement.clientHeight*0.7)) &&
        rect.right > 0 &&
        rect.left < (window.innerWidth || document.documentElement.clientWidth);
}

The problem is that when I press the key to go to the next cover it goes immediately to the last cover of the magazine. When I was checking for imagesIndex in the console, I could see that on pressing the right key arrow, the index goes to 12 (which is the last cover of the magazine) immmediately:

1 issue-images.js?828c:28 2 issue-images.js?828c:28 3 issue-images.js?828c:28 4 issue-images.js?828c:28 5 issue-images.js?828c:28 6 issue-images.js?828c:28 7 issue-images.js?828c:28 8 issue-images.js?828c:28 9 issue-images.js?828c:28 10 issue-images.js?828c:28 11 issue-images.js?828c:28 12

Leff
  • 1,968
  • 24
  • 97
  • 201

1 Answers1

1

As mentionned in the jquery doc "The keydown event is sent to an element when the user presses a key on the keyboard. If the key is kept pressed, the event is sent every time the operating system repeats the key."

You go to the last image because the function is called multiple times.

Use the keyup event instead of keydown

$(document).on('keyup', null, 'right', forward);
$(document).on('keyup', null, 'left', back);

And set your events a single time

var issueImages = require('./issue-images');
var forward = issueImages.forward;
var back = issueImages.back;
var eventBinded = false;

$(document).ready(function () {
  var coverImage = $('.magazine-hero');
  window.onscroll = function() {
    var coverVisible = isElementInViewport(coverImage);

    if (coverVisible && !eventBinded ) {
      $(document).on('keydown', null, 'right', forward);
      $(document).on('keydown', null, 'left', back);
      eventBinded = true;
    }
  };
});
Théo Bouveret
  • 209
  • 2
  • 9