Last active
September 13, 2022 13:42
-
-
Save samternent/f12ccf6c3854bc19dc4488a94080c138 to your computer and use it in GitHub Desktop.
keymando
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, | |
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; | |
window.Keymando = (function() { | |
function Keymando(id, params, options) { | |
var ref, ref1; | |
if (params == null) { | |
params = {}; | |
} | |
if (options == null) { | |
options = {}; | |
} | |
this.dispose = bind(this.dispose, this); | |
this.disposeOf = bind(this.disposeOf, this); | |
this.disposeOfChildren = bind(this.disposeOfChildren, this); | |
this.unpause = bind(this.unpause, this); | |
this.pause = bind(this.pause, this); | |
this.trigger = bind(this.trigger, this); | |
this.getComponent = bind(this.getComponent, this); | |
this.components = {}; | |
this.events = {}; | |
this.inFocus = []; | |
this.hasFocus = id; | |
this.currentTarget = id; | |
this.useDOM = (ref = options.useDOM) != null ? ref : true; | |
this.focusOnFirstChild = (ref1 = options.focusOnFirstChild) != null ? ref1 : false; | |
this.parent = id; | |
this.pausedEvents = []; | |
this.mousetrap = new Mousetrap(); | |
this.register(id, params); | |
return; | |
} | |
Keymando.prototype.register = function(id, params) { | |
var event, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, type; | |
if (this.components[id] != null) { | |
this.removeFromNavigation(this.components[id].parent, id); | |
} | |
this.components[id] = { | |
id: id, | |
parent: (ref = params.parent) != null ? ref : null, | |
navigation: (ref1 = params.navigation) != null ? ref1 : [], | |
current: (ref2 = params.current) != null ? ref2 : -1, | |
onFocus: (ref3 = params.onFocus) != null ? ref3 : function() {}, | |
onBlur: (ref4 = params.onBlur) != null ? ref4 : function() {}, | |
events: (ref5 = params.events) != null ? ref5 : {}, | |
data: (ref6 = params.data) != null ? ref6 : null, | |
displayIndex: (ref7 = params.displayIndex) != null ? ref7 : null | |
}; | |
if ((params.parent != null) && (params.displayIndex != null)) { | |
this.addToNavigation(params.parent, id, params.displayIndex); | |
} | |
ref8 = params.events; | |
for (type in ref8) { | |
event = ref8[type]; | |
this.registerEvent(type, event); | |
} | |
if (params.initFocus) { | |
this.selectElement(id); | |
} | |
}; | |
Keymando.prototype.registerEvent = function(type, event) { | |
var action; | |
if (this.events[type] != null) { | |
return this.events[type] = !!(event != null ? event.allowBulk : void 0); | |
} | |
this.events[type] = !!(event != null ? event.allowBulk : void 0); | |
action = (function(_this) { | |
return function(type, e) { | |
var i; | |
if (_this.components[_this.hasFocus] == null) { | |
return; | |
} | |
if (typeof e.preventDefault === "function") { | |
e.preventDefault(); | |
} | |
if (_this.events[type]) { | |
i = _this.inFocus.length; | |
while (i--) { | |
_this.fireEventChain(type, e, _this.inFocus[i]); | |
} | |
return; | |
} | |
_this.fireEventChain(type, e, _this.hasFocus); | |
}; | |
})(this); | |
this.mousetrap.bind(type, function(e) { | |
return action(type, e); | |
}); | |
}; | |
Keymando.prototype.fireEventChain = function(type, e, activeId) { | |
var activeComponent, newOptions, ref, ref1, ref2, ref3; | |
if (this.pausedEvents.indexOf(type) > -1) { | |
return; | |
} | |
activeComponent = this.components[activeId]; | |
if (activeComponent == null) { | |
return; | |
} | |
if (((ref = activeComponent.events) != null ? ref[type] : void 0) != null) { | |
this.fireEvent(type, e, activeId, activeComponent); | |
} | |
if ((activeComponent.parent != null) && !((ref1 = activeComponent.events[type]) != null ? ref1.cancelBubble : void 0)) { | |
newOptions = (ref2 = this.components[activeComponent.parent]) != null ? (ref3 = ref2.events) != null ? ref3[type] : void 0 : void 0; | |
this.fireEventChain(type, e, activeComponent.parent); | |
} | |
}; | |
Keymando.prototype.fireEvent = function(type, e, activeId, activeComponent) { | |
var event, overrideGlobal, ref; | |
ref = activeComponent.events[type], event = ref.event, overrideGlobal = ref.overrideGlobal; | |
if (!overrideGlobal) { | |
Mousetrap.trigger(type); | |
} | |
if (event == null) { | |
return; | |
} | |
event(e, activeId, activeComponent, { | |
back: this.back.bind(this), | |
forward: this.forward.bind(this) | |
}); | |
}; | |
Keymando.prototype.selectElement = function(id) { | |
var oldId; | |
if (this.components[id] == null) { | |
return; | |
} | |
oldId = this.hasFocus; | |
if (this.inFocus.indexOf(id) < 0) { | |
this.inFocus.push(id); | |
} | |
this.hasFocus = id; | |
this.components[id].onFocus(id, oldId); | |
if (!(this.useDOM && (document.getElementById(id) != null))) { | |
return; | |
} | |
document.getElementById(id).focus(); | |
}; | |
Keymando.prototype.unselectElement = function(id, next) { | |
var index; | |
if (this.components[id] == null) { | |
return; | |
} | |
index = this.inFocus.indexOf(id); | |
if (index > -1) { | |
this.inFocus.splice(index, 1); | |
} | |
this.components[id].onBlur(id, next); | |
if (!(this.useDOM && (document.getElementById(id) != null))) { | |
return; | |
} | |
document.getElementById(id).blur(); | |
}; | |
Keymando.prototype.softUnselectElement = function(id, next) { | |
if (this.components[id] == null) { | |
return; | |
} | |
this.components[id].onBlur(id, next, true); | |
if (!(this.useDOM && (document.getElementById(id) != null))) { | |
return; | |
} | |
document.getElementById(id).blur(); | |
}; | |
Keymando.prototype.childHasFocus = function(id) { | |
var child, j, len, ref; | |
if (this.components[id] == null) { | |
return; | |
} | |
ref = this.components[id].navigation; | |
for (j = 0, len = ref.length; j < len; j++) { | |
child = ref[j]; | |
if (child === this.hasFocus) { | |
return true; | |
} | |
} | |
return false; | |
}; | |
Keymando.prototype.navigate = function(id, dir, multiselect) { | |
var i; | |
if (multiselect == null) { | |
multiselect = false; | |
} | |
if (this.components[id] == null) { | |
return; | |
} | |
if (this.components[id].current + dir > -1 && this.components[id].current + dir < this.components[id].navigation.length) { | |
this.components[id].current += dir; | |
} | |
i = this.inFocus.length; | |
while (i--) { | |
if (multiselect) { | |
this.softUnselectElement(this.inFocus[i], this.components[id].navigation[this.components[id].current]); | |
} else { | |
if (this.inFocus[i] !== id) { | |
this.unselectElement(this.inFocus[i], this.components[id].navigation[this.components[id].current]); | |
} | |
} | |
} | |
if (this.components[id].navigation[this.components[id].current] != null) { | |
this.selectElement(this.components[id].navigation[this.components[id].current]); | |
} | |
}; | |
Keymando.prototype.forward = function(id, multiselect) { | |
if (multiselect == null) { | |
multiselect = false; | |
} | |
this.navigate(id, 1, multiselect); | |
}; | |
Keymando.prototype.back = function(id, multiselect) { | |
if (multiselect == null) { | |
multiselect = false; | |
} | |
this.navigate(id, -1, multiselect); | |
}; | |
Keymando.prototype.focus = function(id, multiselect) { | |
if (multiselect == null) { | |
multiselect = false; | |
} | |
this.navigate(id, 0, multiselect); | |
}; | |
Keymando.prototype.navigateTo = function(parent, id, multiselect) { | |
var i, newIndex; | |
if (multiselect == null) { | |
multiselect = false; | |
} | |
if (this.components[parent] == null) { | |
return; | |
} | |
newIndex = this.components[parent].navigation.indexOf(id); | |
if (!((newIndex != null) || newIndex < 0)) { | |
return; | |
} | |
this.components[parent].current = newIndex; | |
if (!multiselect) { | |
i = this.inFocus.length; | |
while (i--) { | |
this.unselectElement(this.inFocus[i], this.components[parent].navigation[this.components[parent].current]); | |
} | |
} | |
if (this.components[parent].navigation[this.components[parent].current] != null) { | |
this.selectElement(this.components[parent].navigation[this.components[parent].current]); | |
} | |
}; | |
Keymando.prototype.addToNavigation = function(parent, id, position) { | |
var parentComponent; | |
parentComponent = this.components[parent]; | |
if (parentComponent == null) { | |
return; | |
} | |
if (parentComponent.navigation.indexOf(id) > -1) { | |
return; | |
} | |
if (!((position != null) || !position)) { | |
position = parentComponent.navigation.length; | |
} | |
this.components[parent].navigation.splice(position, 0, id); | |
}; | |
Keymando.prototype.removeFromNavigation = function(parent, id) { | |
var index, parentComponent; | |
parentComponent = this.components[parent]; | |
if (parentComponent == null) { | |
return; | |
} | |
index = parentComponent.navigation.indexOf(id); | |
if (index < 0) { | |
return; | |
} | |
this.components[parent].navigation.splice(index, 1); | |
}; | |
Keymando.prototype.getPosition = function(parent, id) { | |
var parentComponent; | |
parentComponent = this.components[parent]; | |
if (parentComponent == null) { | |
return null; | |
} | |
return parentComponent.navigation.indexOf(id); | |
}; | |
Keymando.prototype.getPositionFromBottom = function(parent, id) { | |
var bottom, position; | |
position = this.getPosition(parent, id); | |
bottom = this.getNavigationLength(parent) - 1; | |
return bottom - position; | |
}; | |
Keymando.prototype.getNavigationLength = function(id) { | |
var component; | |
component = this.components[id]; | |
if (component == null) { | |
return null; | |
} | |
return component.navigation.length; | |
}; | |
Keymando.prototype.resetNavigation = function(id, soft) { | |
var firstNavId, ref; | |
if (this.components[id] == null) { | |
return; | |
} | |
this.components[id].current = -1; | |
firstNavId = (ref = this.components[id].navigation) != null ? ref[0] : void 0; | |
if (this.focusOnFirstChild) { | |
this.hasFocus = firstNavId != null ? firstNavId : id; | |
this.inFocus = this.inFocus.filter((function(_this) { | |
return function(i) { | |
return !(indexOf.call(_this.components[id].navigation, i) >= 0); | |
}; | |
})(this)); | |
if (firstNavId != null) { | |
this.inFocus.push(firstNavId); | |
} | |
} | |
if (!(this.useDOM && !soft)) { | |
return; | |
} | |
if (document.getElementById(firstNavId) != null) { | |
document.getElementById(firstNavId).focus(); | |
} | |
if (document.getElementById(id) != null) { | |
document.getElementById(id).focus(); | |
} | |
}; | |
Keymando.prototype.clearNavigation = function(id) { | |
if (this.components[id] == null) { | |
return; | |
} | |
this.components[id].navigation = []; | |
}; | |
Keymando.prototype.getParent = function(id) { | |
var ref, ref1; | |
if (((ref = this.components[id]) != null ? ref.parent : void 0) == null) { | |
return; | |
} | |
return (ref1 = this.components[this.components[id].parent]) != null ? ref1 : false; | |
}; | |
Keymando.prototype.getComponent = function(id) { | |
var ref; | |
return (ref = this.components[id]) != null ? ref : false; | |
}; | |
Keymando.prototype.trigger = function(key) { | |
this.mousetrap.trigger(key); | |
}; | |
Keymando.prototype.pause = function(types) { | |
var j, len, type; | |
if (types == null) { | |
return this.mousetrap.pause(); | |
} | |
for (j = 0, len = types.length; j < len; j++) { | |
type = types[j]; | |
if (this.pausedEvents.indexOf(type) < 0) { | |
this.pausedEvents.push(type); | |
} | |
} | |
}; | |
Keymando.prototype.unpause = function(types) { | |
var j, len, type; | |
if (types == null) { | |
return this.mousetrap.unpause(); | |
} | |
for (j = 0, len = types.length; j < len; j++) { | |
type = types[j]; | |
if (this.pausedEvents.indexOf(type) > -1) { | |
this.pausedEvents.splice(this.pausedEvents.indexOf(type), 1); | |
} | |
} | |
}; | |
Keymando.prototype.disposeOfChildren = function(parent) { | |
var childId, j, len, ref; | |
if (this.components[parent] == null) { | |
return; | |
} | |
ref = this.components[parent].navigation; | |
for (j = 0, len = ref.length; j < len; j++) { | |
childId = ref[j]; | |
delete this.components[childId]; | |
} | |
this.components[parent].navigation = []; | |
}; | |
Keymando.prototype.disposeOf = function(id, soft) { | |
var childId, j, len, parent, ref, ref1; | |
if (this.components[id] == null) { | |
return; | |
} | |
parent = this.components[id].parent; | |
ref = this.components[id].navigation; | |
for (j = 0, len = ref.length; j < len; j++) { | |
childId = ref[j]; | |
this.disposeOf(childId); | |
} | |
this.removeFromNavigation(parent, id); | |
if ((this.hasFocus === id || this.childHasFocus(id)) && !soft) { | |
if (this.components[parent].navigation[0] != null) { | |
this.navigateTo(parent, this.components[parent].navigation[0]); | |
} else if (((ref1 = this.components[this.components[parent].parent]) != null ? ref1.navigation[0] : void 0) != null) { | |
this.navigateTo(this.components[parent].parent, parent); | |
} else { | |
this.hasFocus = null; | |
} | |
} | |
delete this.components[id]; | |
}; | |
Keymando.prototype.dispose = function() { | |
this.mousetrap.reset(); | |
}; | |
return Keymando; | |
})(); | |
// --- | |
// generated by coffee-script 1.9.2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment