summaryrefslogtreecommitdiff
path: root/assets/js/core
diff options
context:
space:
mode:
Diffstat (limited to 'assets/js/core')
-rw-r--r--assets/js/core/base.js54
-rw-r--r--assets/js/core/bootstrap.js1
-rw-r--r--assets/js/core/dom.js18
-rw-r--r--assets/js/core/utils.js55
4 files changed, 111 insertions, 17 deletions
diff --git a/assets/js/core/base.js b/assets/js/core/base.js
index d304d8bd..a4fd00ac 100644
--- a/assets/js/core/base.js
+++ b/assets/js/core/base.js
@@ -37,12 +37,16 @@ KB.onChange = function (selector, callback) {
this.listeners.changes[selector] = callback;
};
-KB.onKey = function (key, callback) {
- this.listeners.keys[key] = callback;
+KB.onKey = function (key, callback, ignoreInputField) {
+ this.listeners.keys[key] = {
+ 'callback': callback,
+ 'ignoreInputField': ignoreInputField || false
+ };
};
KB.listen = function () {
var self = this;
+ var keysQueue = [];
function onClick(e) {
for (var selector in self.listeners.clicks) {
@@ -61,28 +65,48 @@ KB.listen = function () {
}
}
- function onKeypress(e) {
- var key = (typeof e.which === 'number') ? e.which : e.keyCode;
- var element = e.target;
+ function onKeyPressed(e) {
+ var key = KB.utils.getKey(e);
+ var isInputField = KB.utils.isInputField(e);
- if (element.tagName === 'INPUT' ||
- element.tagName === 'SELECT' ||
- element.tagName === 'TEXTAREA' ||
- element.isContentEditable) {
- return;
+ if (! isInputField || ['Escape', 'Meta', 'Enter', 'Control'].indexOf(key) !== -1) {
+ keysQueue.push(key);
}
- for (var keyMap in self.listeners.keys) {
- if (self.listeners.keys.hasOwnProperty(keyMap) && key === parseInt(keyMap)) {
- e.preventDefault();
- self.listeners.keys[key](e);
+ if (keysQueue.length > 0) {
+ var reset = true;
+
+ for (var combination in self.listeners.keys) {
+ if (self.listeners.keys.hasOwnProperty(combination)) {
+ var keyboardListener = self.listeners.keys[combination];
+ var sequence = combination.split('+');
+
+ if (KB.utils.arraysIdentical(keysQueue, sequence)) {
+ if (isInputField && !keyboardListener.ignoreInputField) {
+ keysQueue = [];
+ return;
+ }
+
+ e.preventDefault();
+ e.stopPropagation();
+ keysQueue = [];
+ keyboardListener.callback(e);
+ break;
+ } else if (KB.utils.arraysStartsWith(keysQueue, sequence)) {
+ reset = false;
+ }
+ }
+ }
+
+ if (reset) {
+ keysQueue = [];
}
}
}
document.addEventListener('click', onClick, false);
document.addEventListener('change', onChange, false);
- document.addEventListener('keypress', onKeypress, false);
+ window.addEventListener('keydown', onKeyPressed, false);
};
KB.component = function (name, object) {
diff --git a/assets/js/core/bootstrap.js b/assets/js/core/bootstrap.js
index 3af086f1..7baa9e76 100644
--- a/assets/js/core/bootstrap.js
+++ b/assets/js/core/bootstrap.js
@@ -2,4 +2,5 @@
document.addEventListener('DOMContentLoaded', function () {
KB.render();
KB.listen();
+ KB.keyboardShortcuts();
});
diff --git a/assets/js/core/dom.js b/assets/js/core/dom.js
index 2c44de58..84bdade2 100644
--- a/assets/js/core/dom.js
+++ b/assets/js/core/dom.js
@@ -4,10 +4,12 @@ KB.dom = function (tag) {
var element = typeof tag === 'string' ? document.createElement(tag) : tag;
this.attr = function (attribute, value) {
- if (value !== null) {
+ if (value !== null && typeof value !== 'undefined') {
element.setAttribute(attribute, value);
+ return this;
+ } else {
+ return element.getAttribute(attribute);
}
- return this;
};
this.data = function (attribute, value) {
@@ -175,3 +177,15 @@ KB.find = function (selector) {
return null;
};
+
+KB.exists = function (selector) {
+ return !!document.querySelector(selector);
+};
+
+KB.focus = function (selector) {
+ var element = document.querySelector(selector);
+
+ if (element) {
+ return element.focus();
+ }
+};
diff --git a/assets/js/core/utils.js b/assets/js/core/utils.js
index e8e74b17..4d0f8847 100644
--- a/assets/js/core/utils.js
+++ b/assets/js/core/utils.js
@@ -32,3 +32,58 @@ KB.utils.getSelectionPosition = function (element) {
selectionEnd: selectionEnd
};
};
+
+KB.utils.arraysIdentical = function (a, b) {
+ var i = a.length;
+
+ if (i !== b.length) {
+ return false;
+ }
+
+ while (i--) {
+ if (a[i] !== b[i]) {
+ return false;
+ }
+ }
+
+ return true;
+};
+
+KB.utils.arraysStartsWith = function (array1, array2) {
+ var length = Math.min(array1.length, array2.length);
+
+ for (var i = 0; i < length; i++) {
+ if (array1[i] !== array2[i]) {
+ return false;
+ }
+ }
+
+ return true;
+};
+
+KB.utils.isInputField = function (event) {
+ var element = event.target;
+
+ return !!(element.tagName === 'INPUT' ||
+ element.tagName === 'SELECT' ||
+ element.tagName === 'TEXTAREA' ||
+ element.isContentEditable);
+};
+
+KB.utils.getKey = function (e) {
+ var mapping = {
+ 'Esc': 'Escape',
+ 'Up': 'ArrowUp',
+ 'Down': 'ArrowDown',
+ 'Left': 'ArrowLeft',
+ 'Right': 'ArrowRight'
+ };
+
+ for (var key in mapping) {
+ if (mapping.hasOwnProperty(key) && key === e.key) {
+ return mapping[key];
+ }
+ }
+
+ return e.key;
+};