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