Skip to content

Instantly share code, notes, and snippets.

@wellic
Created September 26, 2019 13:16
Show Gist options
  • Save wellic/09e30d59a731c736ab25bd1d4d14fe6a to your computer and use it in GitHub Desktop.
Save wellic/09e30d59a731c736ab25bd1d4d14fe6a to your computer and use it in GitHub Desktop.
Add arrays key to table
(function ($, undefined) {
//Plugin for navigationg
(function () {
'use strict';
var PLUGIN_NAMESPACE = 'keys_control_table';
var DEFAULT_LISTEN_INPUTS_SELECTOR = 'input';
var DEFAULT_DEBOUNCE_TIME = 50;
var DEFAULT_CARET_MODE = true;
var DEFAULT_SELECT_AFTER_MOVE = true;
var DEFAULT_SKIP_SELECTION_BEFORE_MOVE = true;
var KEY_LEFT = 'left';
var KEY_RIGHT = 'right';
var KEY_UP = 'up';
var KEY_DOWN = 'down';
var DEFAULT_ARROW_KEYS = [KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN];
var MAP_CODE_KEYS = {
37: KEY_LEFT,
39: KEY_RIGHT,
38: KEY_UP,
40: KEY_DOWN
};
$ = $ && $.hasOwnProperty('default') ? $['default'] : $;
function _ClassArrowTable(tableSelector, options) {
this._init(tableSelector, options);
}
_ClassArrowTable.prototype = {
_defaults: {
listenInputs: DEFAULT_LISTEN_INPUTS_SELECTOR,
controlKeys: DEFAULT_ARROW_KEYS,
debounce: DEFAULT_DEBOUNCE_TIME,
selectAfterMove: DEFAULT_SELECT_AFTER_MOVE,
clearSelectionBeforeMove: DEFAULT_SKIP_SELECTION_BEFORE_MOVE,
caretMode: DEFAULT_CARET_MODE,
beforeMove: function (input, direction) {
if (!this.caretMode) return true;
var $input = $(input);
var l = $input.val().length, s = input.selectionStart, e = input.selectionEnd;
if (direction === 'up' || direction == 'down') {
return true;
} else {
if (!this.clearSelectionBeforeMove && s == 0 && e == l) return true;
if (direction === 'left') {
if (s == 0 && e == 0) return true;
$input.caret(s == 0 ? 0 : s - 1);
}
if (direction === 'right') {
if (s == l && e == l) return true;
$input.caret(e == l ? l : e + 1);
}
}
return false;
},
afterMove: function (element, direction, prevElement) {
if (!!this.selectAfterMove) {
var $currentInput = $(element).find(this.listenInputs);
if ('select' in $currentInput) $currentInput.select();
}
return true;
},
findNextTarget: function (element, direction) {
var step_tr = 0, step_td = 0, $td_cur = $(element).closest('td');
var $tr_next, $td_next, step, eq_td;
switch (direction) {
case 'right':
step_td = 1;
break;
case 'left':
step_td = -1;
break;
case 'down':
step_tr = 1;
break;
case 'up':
step_tr = -1;
break;
}
if (step_tr == 0) {
step = step_td > 0 ? 'next' : 'prev';
$td_next = $td_cur[step]();
while ($td_next.length) {
if ($td_next.find(this.listenInputs).filter(':visible').length) return $td_next;
$td_next = $td_next[step]();
}
} else {
eq_td = 'td:eq(' + $td_cur.index() + ')';
step = step_tr > 0 ? 'next' : 'prev';
$tr_next = $td_cur.closest('tr')[step]();
while ($tr_next.length) {
$td_next = $tr_next.find(eq_td);
if ($td_next.find(this.listenInputs).filter(':visible').length) return $td_next;
$tr_next = $tr_next[step]();
}
}
return $td_cur;
}
},
_init: function (tableSelector, options) {
this.options = $.extend({}, this._defaults, options);
this.$table = $(tableSelector);
this._bindEvents();
},
_move: function (element, direction) {
var $element = $(element)[0];
var move = this.options.beforeMove($element, direction);
if (!!move) {
var $target = this.options.findNextTarget($element, direction);
if ($target.length) {
this._focusTarget($target);
this.options.afterMove($target[0], direction, $element);
}
}
},
_focusTarget: function ($target) {
$target.find(this.options.listenInputs).focus();
},
_bindEvents: function () {
var moveTimer;
var moveEvent = function (event) {
var direction = MAP_CODE_KEYS[event.which];
if ($.inArray(direction, this.options.controlKeys) === -1) {
return;
}
if (this.options.debounce > 0) {
if (moveTimer) {
return;
}
moveTimer = setTimeout(function () {
moveTimer = null;
}, this.options.debounce);
}
event.preventDefault();
this._move(event.target, direction);
};
this.$table
.off('keydown.' + this.options.namespace)
.on('keydown.' + this.options.namespace, this.options.listenInputs, $.proxy(moveEvent, this))
.off('keyup.' + this.options.namespace)
.on('keyup.' + this.options.namespace, this.options.listenInputs, function () {moveTimer = null;});
},
_destroy: function () {
this._unbindEvents();
return this;
},
_unbindEvents: function () {
this.$table.off('.' + this.options.namespace);
}
};
$.fn.arrowTable = function (options) {
options = options || {};
var namespace = options.namespace || _ClassArrowTable.prototype._defaults.namespace,
isMethodCall = typeof options === 'string';
return $(this).each(function () {
var $item = $(this);
var keysControlTable = $item.data(namespace);
if (isMethodCall) {
if (keysControlTable instanceof _ClassArrowTable) {
switch (options) {
case 'destroy':
keysControlTable._destroy();
$item.removeData(namespace);
break;
}
}
return this;
}
// Initialize
if (keysControlTable instanceof _ClassArrowTable) {
keysControlTable._destroy()._init(this, options);
} else {
$item.data(namespace, new _ClassArrowTable(this, options));
}
return this;
});
};
return _ClassArrowTable;
}());
//Plugin for detecting cursor posistions in text inputs
(function () {
$.caretTo = function (el, index) {
if (el.createTextRange) {
var range = el.createTextRange();
range.move("character", index);
range.select();
} else if (el.selectionStart != null) {
el.focus();
el.setSelectionRange(index, index);
}
};
$.caretPos = function (el) {
if ("selection" in document) {
var range = el.createTextRange();
try {
range.setEndPoint("EndToStart", document.selection.createRange());
} catch (e) {
return 0;
}
return range.text.length;
} else if (el.selectionStart != null) {
return el.selectionStart;
}
};
$.fn.caret = function (index, offset) {
if (typeof (index) === "undefined") {
return $.caretPos(this.get(0));
}
return this.queue(function (next) {
if (isNaN(index)) {
var i = $(this).val().indexOf(index);
if (offset === true) {
i += index.length;
} else if (typeof (offset) !== "undefined") {
i += offset;
}
$.caretTo(this, i);
} else {
$.caretTo(this, index);
}
next();
});
};
$.fn.caretToStart = function () {
return this.caret(0);
};
$.fn.caretToEnd = function () {
return this.queue(function (next) {
$.caretTo(this, $(this).val().length);
next();
});
};
}());
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment