eightArmCode
eightArmCode

Reputation: 185

jquery: focus jumps before event runs

The focus moves to the next input field before the event is fired. Can anyone help me find the bug, or figure out how to find it myself?

The goal is to catch the keyup event, verify that it is tab or shift+tab, and then tab as though it were tabbing through a table. When the focus gets to the last input that is visible, the three rows (see fiddle for visual) should move together to reveal hidden inputs. Once to the end of the inputs in that row, the three rows will slide back down to the beginning again, kind of like a carriage return on a typewriter, or tabbing into a different row in a table.

Right now, the tab event is moving just the row that holds the focus, and it is moving it before my script even starts to run. I just need to know why this is happening so that I can research how to resolve it.

Any help you can offer is appreciated. Please let me know if you need more information.

P.S. Using jquery 1.9.1

Link to Fiddle

jQuery(document).ready(function ($) {
  // bind listeners to time input fields
  //$('.timeBlock').blur(validateHrs);
  $('.timeBlock').keyup(function () {
      var caller = $(this);
      var obj = new LayoutObj(caller);
      if (event.keyCode === 9) {
          if (event.shiftKey) {
              obj.dir = 'prev';
          }
          obj.navDates();
      }
  });

  // bind listeners to prev/next buttons
  $('.previous, .next').on('click', function () {
      var str = $(this).attr('class');
      var caller = $(this);
      var obj = new LayoutObj(caller);
      obj.src = 'pg';
      if (str === 'previous') {
          obj.dir = 'prev';
      }
      obj.navDates();
  });
});

function LayoutObj(input) {
  var today = new Date();
  var thisMonth = today.getMonth();
  var thisDate = today.getDate();
  var dateStr = '';
  var fullDates = $('.dateNum');
  var splitDates = new Array();
  this.currIndex = 0; //currIndex defaults to 0
  this.todayIndex;

  fullDates.each(function (index) {
      splitDates[index] = $(this).text().split('/');
  });

  //traverse the list of dates in the pay period, compare values and stop when/if you find today
  for (var i = 0; i < splitDates.length; i++) {
    if (thisMonth === (parseInt(splitDates[i][0], 10) - 1) && thisDate === parseInt(splitDates[i][1], 10)) {
      thisMonth += 1;
      thisMonth += '';
      thisDate += '';
      if (thisMonth.length < 2) {
          dateStr = "0" + thisMonth + "/";
      }
      else {
          dateStr = thisMonth + "/";
      }
      if (thisDate.length < 2) {
          dateStr += "0" + thisDate;
      }
      else {
          dateStr += thisDate;
      }
      fullDates[i].parentNode.setAttribute('class', 'date today');
      this.todayIndex = i;
      break;
    }
  }

  //grab all of the lists & the inputs
  this.window = $('div.timeViewList');
  this.allLists = $('.timeViewList ul');
  this.inputs = $('.timeBlock');

  //if input`isn't null, set currIndex to match index of caller
  if (input !== null) {
      this.currIndex = this.inputs.index(input);
  }
  //else if today is in the pay period, set currIndex to todayIndex
  else if (this.todayIndex !== undefined) {
      this.currIndex = this.todayIndex;
  }
  //(else default = 0)

  //grab the offsets for the cell, parent, and lists.
  this.winOffset = this.window.offset().left;
  this.cellOffset = this.inputs.eq(this.currIndex).offset().left;
  this.listOffset = this.inputs.offset().left;

  //grab the width of a cell, the parent, and lists
  this.cellWidth = this.inputs.outerWidth();
  this.listWidth = this.inputs.last().offset().left + this.cellWidth - this.inputs.eq(0).offset().left;
  this.winWidth = this.window.outerWidth();

  //calculate the maximum (left) offset between the lists and the parents
  this.offsetMax = (this.listWidth - this.winWidth);

  //set default scroll direction as fwd, and default nav as tab
  this.dir = 'next';
  this.src = 'tab';

  //grab the offsets for the cell, parent, and lists.
  this.cellOffset = this.inputs.eq(this.currIndex).offset().left;
  this.listOffset = this.inputs.eq(0).offset().left;
  this.winOffset = this.allLists.parent().offset().left;

  //calculate the maximum (left) offset between the lists and the parents
  this.offsetMax = (this.listWidth - this.winWidth);
}
LayoutObj.prototype.focusDate = function () {
  this.inputs.eq(this.currIndex).focus();
};

LayoutObj.prototype.slideLists = function (num) {
  this.listOffset += num;
  this.allLists.offset({ left: this.listOffset });
};

LayoutObj.prototype.navDates = function () {

  if (!this.inWindow()) {
      var slide = 0;
      switch (this.src) {
          case 'pg':
              slide = this.winWidth - this.cellWidth;
              break;
          case 'tab':
              slide = this.cellWidth + 1;
              break;
          default:
              break;
      }
      if (this.dir === 'next') {
          slide = -slide;
      }
      this.slideLists(slide);
  }
  this.focusDate();
};

LayoutObj.prototype.inWindow = function () {
  //detects if cell intended for focus is visible in the parent div
  if ((this.cellOffset > this.winOffset) && ((this.cellOffset + this.cellWidth) < (this.winOffset + this.winWidth))) {
    return true;
  }
  else {
    return false;
  }
}

Upvotes: 0

Views: 286

Answers (1)

eightArmCode
eightArmCode

Reputation: 185

All it needed was 'keydown()' instead of 'keyup().'

Upvotes: 0

Related Questions