Skip to content

Instantly share code, notes, and snippets.

@burtlo
Last active November 7, 2017 22:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save burtlo/4d1e1cd4186a4db04c68f93723d70fa3 to your computer and use it in GitHub Desktop.
Save burtlo/4d1e1cd4186a4db04c68f93723d70fa3 to your computer and use it in GitHub Desktop.
Learn Chef Rally Presentation Mode. This script is designed to be used through TamperMonkey (https://tampermonkey.net/) a plugin for browsers.
// ==UserScript==
// @name Learn Chef Rally Presentation
// @namespace https://learn.chef.io/
// @version 0.1
// @description Present only the code windows
// @author Franklin Webber
// @match https://learn.chef.io/modules/*
// @grant none
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js
// ==/UserScript==
/**
* Title: KeyboardJS
* Version: v0.3.0
* Description: KeyboardJS is a flexible and easy to use keyboard binding library.
* Author: Robert Hurst.
*
* Copyright 2011, Robert William Hurst
* Licenced under the BSD License.
* See https://raw.github.com/RobertWHurst/KeyboardJS/master/license.txt
*/
window.KeyboardCreate = function(name) {
createKeyboard(name,this,keyboardFactory);
};
createKeyboard = function(name, context, factory) {
var namespaces = [], previousValues = {}, library;
if(typeof define === 'function' && define.amd) {
define(function() { return factory('amd'); });
} else {
library = factory('global',name);
library.noConflict = function( ) {
var args, nI;
newNamespaces = Array.prototype.slice.apply(arguments);
for(nI = 0; nI < namespaces.length; nI += 1) {
if(typeof previousValues[namespaces[nI]] === 'undefined') {
delete context[namespaces[nI]];
} else {
context[namespaces[nI]] = previousValues[namespaces[nI]];
}
}
previousValues = {};
for(nI = 0; nI < newNamespaces.length; nI += 1) {
if(typeof newNamespaces[nI] !== 'string') { throw new Error('Cannot replace namespaces. All new namespaces must be strings.'); }
previousValues[newNamespaces[nI]] = context[newNamespaces[nI]];
context[newNamespaces[nI]] = library;
}
namespaces = newNamespaces;
return namespaces;
};
library.noConflict(name);
}
};
keyboardFactory = function(env) {
var keyboardJS = {}, locales, locale, map, macros, activeKeys = [], bindings = [], activeBindings = [], activeMacros = [];
//INDEXOF POLLYFILL
//[].indexOf||(Array.prototype.indexOf=function(a,b,c){for(c=this.length,b=(c+~~b)%c;b<c&&(!(b in this)||this[b]!==a);b++);return b^c?b:-1;});
//BUNDLED LOCALES
locales = {
'us': {
"map": {
//general
"3": ["cancel"],
"8": ["backspace"],
"9": ["tab"],
"12": ["clear"],
"13": ["enter"],
"16": ["shift"],
"17": ["ctrl"],
"18": ["alt", "menu"],
"19": ["pause", "break"],
"20": ["capslock"],
"27": ["escape", "esc"],
"32": ["space", "spacebar"],
"33": ["pageup"],
"34": ["pagedown"],
"35": ["end"],
"36": ["home"],
"37": ["left"],
"38": ["up"],
"39": ["right"],
"40": ["down"],
"41": ["select"],
"42": ["printscreen"],
"43": ["execute"],
"44": ["snapshot"],
"45": ["insert", "ins"],
"46": ["delete", "del"],
"47": ["help"],
"91": ["command", "windows", "win", "super", "leftcommand", "leftwindows", "leftwin", "leftsuper"],
"92": ["command", "windows", "win", "super", "rightcommand", "rightwindows", "rightwin", "rightsuper"],
"145": ["scrolllock", "scroll"],
"186": ["semicolon", ";"],
"187": ["equal", "equalsign", "="],
"188": ["comma", ","],
"189": ["dash", "-"],
"190": ["period", "."],
"191": ["slash", "forwardslash", "/"],
"192": ["graveaccent", "`"],
"219": ["openbracket", "["],
"220": ["backslash", "\\"],
"221": ["closebracket", "]"],
"222": ["apostrophe", "'"],
//a-z
"65": ["a"],
"66": ["b"],
"67": ["c"],
"68": ["d"],
"69": ["e"],
"70": ["f"],
"71": ["g"],
"72": ["h"],
"73": ["i"],
"74": ["j"],
"75": ["k"],
"76": ["l"],
"77": ["m"],
"78": ["n"],
"79": ["o"],
"80": ["p"],
"81": ["q"],
"82": ["r"],
"83": ["s"],
"84": ["t"],
"85": ["u"],
"86": ["v"],
"87": ["w"],
"88": ["x"],
"89": ["y"],
"90": ["z"],
//0-9
"48": ["zero", "0"],
"49": ["one", "1"],
"50": ["two", "2"],
"51": ["three", "3"],
"52": ["four", "4"],
"53": ["five", "5"],
"54": ["six", "6"],
"55": ["seven", "7"],
"56": ["eight", "8"],
"57": ["nine", "9"],
//numpad
"96": ["numzero", "num0"],
"97": ["numone", "num1"],
"98": ["numtwo", "num2"],
"99": ["numthree", "num3"],
"100": ["numfour", "num4"],
"101": ["numfive", "num5"],
"102": ["numsix", "num6"],
"103": ["numseven", "num7"],
"104": ["numeight", "num8"],
"105": ["numnine", "num9"],
"106": ["nummultiply", "num*"],
"107": ["numadd", "num+"],
"108": ["numenter"],
"109": ["numsubtract", "num-"],
"110": ["numdecimal", "num."],
"111": ["numdevide", "num/"],
"144": ["numlock", "num"],
//function keys
"112": ["f1"],
"113": ["f2"],
"114": ["f3"],
"115": ["f4"],
"116": ["f5"],
"117": ["f6"],
"118": ["f7"],
"119": ["f8"],
"120": ["f9"],
"121": ["f10"],
"122": ["f11"],
"123": ["f12"]
},
"macros": [
//secondary key symbols
[[[["shift", "graveaccent"]]], ["tilde", "~"]],
[[[["shift", "one"]]], ["exclamation", "exclamationpoint", "!"]],
[[[["shift", "two"]]], ["at", "@"]],
[[[["shift", "three"]]], ["number", "#"]],
[[[["shift", "four"]]], ["dollar", "dollars", "dollarsign", "$"]],
[[[["shift", "five"]]], ["percent", "%"]],
[[[["shift", "six"]]], ["caret", "^"]],
[[[["shift", "seven"]]], ["ampersand", "and", "&"]],
[[[["shift", "eight"]]], ["asterisk", "*"]],
[[[["shift", "nine"]]], ["openparen", "("]],
[[[["shift", "zero"]]], ["closeparen", ")"]],
[[[["shift", "dash"]]], ["underscore", "_"]],
[[[["shift", "equal"]]], ["plus", "+"]],
[[[["shift", "openbracket"]]], ["opencurlybrace", "opencurlybracket", "{"]],
[[[["shift", "closebracket"]]], ["closecurlybrace", "closecurlybracket", "}"]],
[[[["shift", "backslash"]]], ["verticalbar", "|"]],
[[[["shift", "semicolon"]]], ["colon", ":"]],
[[[["shift", "apostrophe"]]], ["quotationmark", "\""]],
[[[["shift", "comma"]]], ["openanglebracket", "<"]],
[[[["shift", "period"]]], ["closeanglebracket", ">"]],
[[[["shift", "forwardslash"]]], ["questionmark", "?"]],
//capital A-Z
[[[["shift", "a"]]], ["A"]],
[[[["shift", "b"]]], ["B"]],
[[[["shift", "c"]]], ["C"]],
[[[["shift", "d"]]], ["D"]],
[[[["shift", "e"]]], ["E"]],
[[[["shift", "f"]]], ["F"]],
[[[["shift", "g"]]], ["G"]],
[[[["shift", "h"]]], ["H"]],
[[[["shift", "i"]]], ["I"]],
[[[["shift", "j"]]], ["J"]],
[[[["shift", "k"]]], ["K"]],
[[[["shift", "l"]]], ["L"]],
[[[["shift", "m"]]], ["M"]],
[[[["shift", "n"]]], ["N"]],
[[[["shift", "o"]]], ["O"]],
[[[["shift", "p"]]], ["P"]],
[[[["shift", "q"]]], ["Q"]],
[[[["shift", "r"]]], ["R"]],
[[[["shift", "s"]]], ["S"]],
[[[["shift", "t"]]], ["T"]],
[[[["shift", "u"]]], ["U"]],
[[[["shift", "v"]]], ["V"]],
[[[["shift", "w"]]], ["W"]],
[[[["shift", "x"]]], ["X"]],
[[[["shift", "y"]]], ["Y"]],
[[[["shift", "z"]]], ["Z"]]
]
}
//If you create a new locale please submit it as a pull request or post it in the issue tracker at
// http://github.com/RobertWhurst/keyboardJS/issues/
};
locale = 'us';
map = locales[locale].map;
macros = locales[locale].macros;
if(document.addEventListener) {
document.addEventListener('keydown', keydown, false);
document.addEventListener('keyup', keyup, false);
document.addEventListener('blur', blur, false);
} else if(document.attachEvent) {
document.attachEvent('onkeydown', keydown);
document.attachEvent('onkeyup', keyup);
document.attachEvent('onblur', blur);
} else {
throw new Error('Cannot bind to keydown event. Both addEventListener and attachEvent are unsupported by your browser.');
}
keyboardJS.enable = function() {
keyboardJS.enabled = true;
};
keyboardJS.disable = function() {
keyboardJS.enabled = false;
};
keyboardJS.toggle = function() {
keyboardJS.enabled = !keyboardJS.enabled;
};
keyboardJS.enabled = true;
keyboardJS.activeKeys = getActiveKeys;
keyboardJS.on = createBinding;
keyboardJS.clear = removeBindingByKeyCombo;
keyboardJS.clear.key = removeBindingByKeyName;
keyboardJS.locale = getSetLocale;
keyboardJS.locale.register = registerLocale;
keyboardJS.macro = createMacro;
keyboardJS.macro.remove = removeMacro;
keyboardJS.getKey = getKeyName;
keyboardJS.combo = {};
keyboardJS.combo.parse = parseKeyCombo;
keyboardJS.combo.stringify = stringifyKeyCombo;
window.map = map;
window.macros = macros;
return keyboardJS;
function keydown(event) {
if (!keyboardJS.enabled) { return; }
var keyNames, kI;
keyNames = getKeyName(event.keyCode);
if(keyNames.length < 1) { return; }
for(kI = 0; kI < keyNames.length; kI += 1) {
addActiveKey(keyNames[kI]);
}
executeMacros();
executeBindings(event);
}
function keyup(event) {
var keyNames, kI;
keyNames = getKeyName(event.keyCode);
if(keyNames.length < 1) { return; }
for(kI = 0; kI < keyNames.length; kI += 1) {
removeActiveKey(keyNames[kI]);
}
if (!keyboardJS.enabled) { return; }
pruneMacros();
pruneBindings(event);
}
function blur(event) {
activeKeys = [];
if (!keyboardJS.enabled) { return; }
pruneMacros();
pruneBindings(event);
}
function getKeyName(keyCode) {
return map[keyCode] || [];
}
function createMacro(combo, injectedKeys) {
if(typeof combo !== 'string' && (typeof combo !== 'object' || typeof combo.push !== 'function')) { throw new Error("Cannot create macro. The combo must be a string or array."); }
if(typeof injectedKeys !== 'object' || typeof injectedKeys.push !== 'function') { throw new Error("Cannot create macro. The injectedKeys must be an array."); }
marcos.push([combo, injectKeys]);
}
function removeMacro(combo) {
var macro;
if(typeof combo !== 'string' && (typeof combo !== 'object' || typeof combo.push !== 'function')) { throw new Error("Cannot remove macro. The combo must be a string or array."); }
for(mI = 0; mI < macros.length; mI += 1) {
macro = macros[mI];
if(compareCombos(combo, macro[0])) {
removeActiveKey(macro[1]);
macros.splice(mI, 1);
break;
}
}
}
function executeMacros() {
var mI, combo, kI;
for(mI = 0; mI < macros.length; mI += 1) {
combo = parseKeyCombo(macros[mI][0]);
if(activeMacros.indexOf(macros[mI]) === -1 && isSatifiedCombo(combo)) {
activeMacros.push(macros[mI]);
for(kI = 0; kI < macros[mI][1].length; kI += 1) {
addActiveKey(macros[mI][1][kI]);
}
}
}
}
function pruneMacros() {
var mI, combo, kI;
for(mI = 0; mI < activeMacros.length; mI += 1) {
combo = parseKeyCombo(activeMacros[mI][0]);
if(isSatifiedCombo(combo) === false) {
for(kI = 0; kI < activeMacros[mI][1].length; kI += 1) {
removeActiveKey(activeMacros[mI][1][kI]);
}
activeMacros.splice(mI, 1);
mI -= 1;
}
}
}
function createBinding(keyCombo, keyDownCallback, keyUpCallback) {
var binding, subBindings = [], bindingApi = {}, kI, subCombo;
if(typeof keyCombo === 'string') {
keyCombo = parseKeyCombo(keyCombo);
}
for(kI = 0; kI < keyCombo.length; kI += 1) {
binding = {};
subCombo = stringifyKeyCombo([keyCombo[kI]]);
if(typeof subCombo === 'function') {
subCombo = false;
keyUpCallback = keyDownCallback;
keyDownCallback = subCombo;
}
if(subCombo !== false && typeof subCombo !== 'string') { throw new Error('Failed to bind key combo. The key combo must be string.'); }
binding.keyCombo = subCombo;
binding.keyDownCallback = [];
binding.keyUpCallback = [];
if(keyDownCallback) { binding.keyDownCallback.push(keyDownCallback); }
if(keyUpCallback) { binding.keyUpCallback.push(keyUpCallback); }
bindings.push(binding);
subBindings.push(binding);
}
return {
"clear": clear,
"on": on
};
function clear() {
var bI;
for(bI = 0; bI < subBindings.length; bI += 1) {
bindings.splice(bindings.indexOf(subBindings[bI]), 1);
}
}
function on(eventName ) {
var callbacks, cI, bI;
if(typeof eventName !== 'string') { throw new Error('Cannot bind callback. The event name must be a string.'); }
if(eventName !== 'keyup' && eventName !== 'keydown') { throw new Error('Cannot bind callback. The event name must be a "keyup" or "keydown".'); }
callbacks = Array.prototype.slice.apply(arguments, [1]);
for(cI = 0; cI < callbacks.length; cI += 1) {
if(typeof callbacks[cI] === 'function') {
if(eventName === 'keyup') {
for(bI = 0; bI < subBindings.length; bI += 1) {
subBindings[bI].keyUpCallback.push(callbacks[cI]);
}
} else {
for(bI = 0; bI < subBindings.length; bI += 1) {
subBindings[bI].keyDownCallback.push(callbacks[cI]);
}
}
}
}
return { "clear": clear };
function clear() {
var cI, bI;
for(cI = 0; cI < callbacks.length; cI += 1) {
if(typeof callbacks[cI] === 'function') {
if(eventName === 'keyup') {
for(bI = 0; bI < subBindings.length; bI += 1) {
subBindings[bI].keyUpCallback.splice(subBindings[bI].keyUpCallback.indexOf(callbacks[cI]), 1);
}
} else {
for(bI = 0; bI < subBindings.length; bI += 1) {
subBindings[bI].keyDownCallback.splice(subBindings[bI].keyDownCallback.indexOf(callbacks[cI]), 1);
}
}
}
}
}
}
}
function removeBindingByKeyCombo(keyCombo) {
var bI, binding, keyName;
for(bI = 0; bI < bindings.length; bI += 1) {
binding = bindings[bI];
if(compareCombos(keyCombo, binding.keyCombo)) {
bindings.splice(bI, 1); bI -= 1;
}
}
}
function removeBindingByKeyName(keyName) {
var bI, cI, binding;
for(bI = 0; bI < bindings.length; bI += 1) {
binding = bindings[bi];
for(cI = 0; cI < binding.keyCombo.length; cI += 1) {
if(binding.keyCombo[kI].indexOf(keyName) > -1) {
bindings.splice(bI, 1); bI -= 1;
break;
}
}
}
}
/**
* Executes bindings that are active. Only allows the keys to be used once as to prevent binding overlap.
* @param {KeyboardEvent} event The keyboard event.
*/
function executeBindings(event) {
var bI, sBI, binding, bidningKeys, remainingKeys, cI, killEventBubble, kI, bindingKeysSatified,
index, sortedBindings = [], bindingWeight;
remainingKeys = [].concat(activeKeys);
for(bI = 0; bI < bindings.length; bI += 1) {
bindingWeight = extractComboKeys(bindings[bI].keyCombo).length;
if(!sortedBindings[bindingWeight]) { sortedBindings[bindingWeight] = []; }
sortedBindings[bindingWeight].push(bindings[bI]);
}
for(sBI = sortedBindings.length - 1; sBI >= 0; sBI -= 1) {
if(!sortedBindings[sBI]) { continue; }
for(bI = 0; bI < sortedBindings[sBI].length; bI += 1) {
binding = sortedBindings[sBI][bI];
bindingKeys = extractComboKeys(binding.keyCombo);
bindingKeysSatified = true;
for(kI = 0; kI < bindingKeys.length; kI += 1) {
if(remainingKeys.indexOf(bindingKeys[kI]) === -1) {
bindingKeysSatified = false;
break;
}
}
if(bindingKeysSatified && isSatifiedCombo(binding.keyCombo)) {
activeBindings.push(binding);
for(kI = 0; kI < bindingKeys.length; kI += 1) {
index = remainingKeys.indexOf(bindingKeys[kI]);
if(index > -1) {
remainingKeys.splice(index, 1);
kI -= 1;
}
}
for(cI = 0; cI < binding.keyDownCallback.length; cI += 1) {
if (binding.keyDownCallback[cI](event) === false) {
killEventBubble = true;
}
}
if(killEventBubble === true) {
event.preventDefault();
event.stopPropagation();
}
}
}
}
}
/**
* Removes bindings that are no longer satisfied by the active keys. Also fires the keyup callbacks.
* @param {KeyboardEvent} event [description]
*/
function pruneBindings(event) {
var bI, cI, binding, killEventBubble;
for(bI = 0; bI < activeBindings.length; bI += 1) {
binding = activeBindings[bI];
if(isSatifiedCombo(binding.keyCombo) === false) {
for(cI = 0; cI < binding.keyUpCallback.length; cI += 1) {
if (binding.keyUpCallback[cI](event) === false) {
killEventBubble = true;
}
}
if(killEventBubble === true) {
event.preventDefault();
event.stopPropagation();
}
activeBindings.splice(bI, 1);
bI -= 1;
}
}
}
/**
* Compares two key combos returning true when they are functionally equivalent.
* @param {String|Array} keyComboArrayA keyCombo A key combo string or array.
* @param {String|Array} keyComboArrayB keyCombo A key combo string or array.
* @return {Boolean}
*/
function compareCombos(keyComboArrayA, keyComboArrayB) {
var cI, sI, kI;
keyComboArrayA = parseKeyCombo(keyComboArrayA);
keyComboArrayB = parseKeyCombo(keyComboArrayB);
if(keyComboArrayA.length !== keyComboArrayB.length) { return false; }
for(cI = 0; cI < keyComboArrayA.length; cI += 1) {
if(keyComboArrayA[aI].length !== keyComboArrayB[aI].length) { return false; }
for(sI = 0; sI < keyComboArrayA[aI].length; sI += 1) {
if(keyComboArrayA[aI][sI].length !== keyComboArrayB[aI][sI].length) { return false; }
for(kI = 0; kI < keyComboArrayA[aI][sI].length; kI += 1) {
if(keyComboArrayB[aI][sI].indexOf(keyComboArrayA[aI][sI][kI]) === -1) { return false; }
}
}
}
return true;
}
/**
* Checks to see if a key combo string or key array is satisfied by the currently active keys. It does not
* take into account spent keys.
* @param {String|Array} keyCombo A key combo string or array.
* @return {Boolean}
*/
function isSatifiedCombo(keyCombo) {
var cI, sI, stage, kI, stageOffset = 0, index;
keyCombo = parseKeyCombo(keyCombo);
for(cI = 0; cI < keyCombo.length; cI += 1) {
for(sI = 0; sI < keyCombo[cI].length; sI += 1) {
stage = [].concat(keyCombo[cI][sI]);
for(kI = stageOffset; kI < activeKeys.length; kI += 1) {
index = stage.indexOf(activeKeys[kI]);
if(index > -1) {
stage.splice(index, 1);
stageOffset = kI;
}
}
if(stage.length !== 0) { return false; }
}
}
return true;
}
/**
* Accepts a key combo array or string and returns a flat array containing all keys referenced by
* the key combo.
* @param {String|Array} keyCombo A key combo string or array.
* @return {Array}
*/
function extractComboKeys(keyCombo) {
var cI, sI, kI, keys = [];
keyCombo = parseKeyCombo(keyCombo);
for(cI = 0; cI < keyCombo.length; cI += 1) {
for(sI = 0; sI < keyCombo[cI].length; sI += 1) {
keys = keys.concat(keyCombo[cI][sI]);
}
}
return keys;
}
/**
* Converts a key combo string into a 3 dimensional array.
* Level 1 represents each combo as combo strings can contain more than one.
* Level 2 represents each stage. A stages are sub combos that must be satisfied in the order they are defined.
* Level 3 represents each key that must be pressed to satisfy a stage.
* @param {String} keyCombo A key combo string.
* @return {Array}
*/
function parseKeyCombo(keyCombo) {
var s = keyCombo, i = 0, op = 0, ws = false, nc = false, combos = [], combo = [], stage = [], key = '';
if(typeof keyCombo === 'object' && typeof keyCombo.push === 'function') { return keyCombo; }
if(typeof keyCombo !== 'string') { throw new Error('Cannot parse "keyCombo" because its type is "' + (typeof keyCombo) + '". It must be a "string".'); }
//remove leading whitespace
while(s.charAt(i) === ' ') { i += 1; }
while(true) {
if(s.charAt(i) === ' ') {
//white space & next combo op
while(s.charAt(i) === ' ') { i += 1; }
ws = true;
} else if(s.charAt(i) === ',') {
if(op || nc) { throw new Error('Failed to parse key combo. Unexpected , at character index ' + i + '.'); }
nc = true;
i += 1;
} else if(s.charAt(i) === '+') {
//next key
if(key.length) { stage.push(key); key = ''; }
if(op || nc) { throw new Error('Failed to parse key combo. Unexpected + at character index ' + i + '.'); }
op = true;
i += 1;
} else if(s.charAt(i) === '>') {
//next stage op
if(key.length) { stage.push(key); key = ''; }
if(stage.length) { combo.push(stage); stage = []; }
if(op || nc) { throw new Error('Failed to parse key combo. Unexpected > at character index ' + i + '.'); }
op = true;
i += 1;
} else if(i < s.length - 1 && s.charAt(i) === '!' && (s.charAt(i + 1) === '>' || s.charAt(i + 1) === ',' || s.charAt(i + 1) === '+')) {
key += s.charAt(i + 1);
op = false;
ws = false;
nc = false;
i += 2;
} else if(i < s.length && s.charAt(i) !== '+' && s.charAt(i) !== '>' && s.charAt(i) !== ',' && s.charAt(i) !== ' ') {
//end combo
if(op === false && ws === true || nc === true) {
if(key.length) { stage.push(key); key = ''; }
if(stage.length) { combo.push(stage); stage = []; }
if(combo.length) { combos.push(combo); combo = []; }
}
op = false;
ws = false;
nc = false;
//key
while(i < s.length && s.charAt(i) !== '+' && s.charAt(i) !== '>' && s.charAt(i) !== ',' && s.charAt(i) !== ' ') {
key += s.charAt(i);
i += 1;
}
} else {
//unknown char
i += 1;
continue;
}
//end of combos string
if(i >= s.length) {
if(key.length) { stage.push(key); key = ''; }
if(stage.length) { combo.push(stage); stage = []; }
if(combo.length) { combos.push(combo); combo = []; }
break;
}
}
return combos;
}
/**
* Stringifys a key combo.
* @param {Array|String} keyComboArray A key combo array. If a key combo string is given it will be returned.
* @return {String}
*/
function stringifyKeyCombo(keyComboArray) {
var cI, ccI, output = [];
if(typeof keyComboArray === 'string') { return keyComboArray; }
if(typeof keyComboArray !== 'object' || typeof keyComboArray.push !== 'function') { throw new Error('Cannot stringify key combo.'); }
for(cI = 0; cI < keyComboArray.length; cI += 1) {
output[cI] = [];
for(ccI = 0; ccI < keyComboArray[cI].length; ccI += 1) {
output[cI][ccI] = keyComboArray[cI][ccI].join(' + ');
}
output[cI] = output[cI].join(' > ');
}
return output.join(' ');
}
/**
* Returns the a copy of the active keys array.
* @return {Array}
*/
function getActiveKeys() {
return [].concat(activeKeys);
}
/**
* Adds a key to the active keys array, but only if it has not already been added.
* @param {String} keyName The key name string.
*/
function addActiveKey(keyName) {
if(keyName.match(/\s/)) { throw new Error('Cannot add key name ' + keyName + ' to active keys because it contains whitespace.'); }
if(activeKeys.indexOf(keyName) > -1) { return; }
activeKeys.push(keyName);
}
/**
* Removes a key from the active keys array.
* @param {String} keyName The key name string.
*/
function removeActiveKey(keyName) {
if(keyName === 'super') { activeKeys = []; } //remove all key on release of super.
activeKeys.splice(activeKeys.indexOf(keyName), 1);
}
/**
* Registers a new locale. This is useful if you would like to add support for a new keyboard layout. It could also be useful for
* alternative key names. For example if you program games you could create a locale for your key mappings. Instead of key 65 mapped
* to 'a' you could map it to 'jump'.
* @param {String} localeName The name of the new locale.
* @param {Object} localeMap The locale map.
*/
function registerLocale(localeName, localeMap) {
if(typeof localeName !== 'string') { throw new Error('Cannot register new locale. The locale name must be a string.'); }
if(typeof localeMap !== 'object') { throw new Error('Cannot register ' + localeName + ' locale. The locale map must be an object.'); }
if(typeof localeMap.keys !== 'object' || typeof localeMap.keys.push !== 'function' || typeof localeMap.map !== 'object' || typeof localeMap.map !== 'function') { throw new Error('Cannot register ' + localeName + ' locale. The locale map is invalid.'); }
locales[localeName] = localeMap;
}
/**
* Swaps the current locale.
* @param {String} localeName The locale to activate.
* @return {Object}
*/
function getSetLocale(localeName) {
if(!localeName) {
if(typeof localeName !== 'string') { throw new Error('Cannot set locale. The locale name must be a string.'); }
if(!locales[localeName]) { throw new Error('Cannot set locale to ' + localeName + ' because it does not exist. If you would like to submit a ' + localeName + ' locale map for keyboardJS please submit it at https://github.com/RobertWHurst/keyboardJS/issues.'); }
locale = localeName;
map = locales[locale].map;
macros = locales[locale].macros;
}
return locale;
}
};
(function($){
var o = $({});
$.subscribe = function() {
o.bind.apply( o, arguments );
};
$.unsubscribe = function() {
o.unbind.apply( o, arguments );
};
$.publish = function() {
console.log("Publish: " + arguments[0]);
o.trigger.apply( o, arguments );
};
})(jQuery);
(function() {
'use strict';
// enable keyboard shortcut to launch presentation
KeyboardCreate('MainKeyboard');
MainKeyboard.on('p',function(){
$.publish("presentation:show");
});
KeyboardCreate('PresentationKeyboard');
PresentationKeyboard.on('escape', function() {
$.publish("presentation:hide");
});
PresentationKeyboard.on('left, up', function() {
$.publish("presentation:back");
});
PresentationKeyboard.on('right, down', function() {
$.publish("presentation:forward");
});
var presentationTracker = {
"slides" : $("div.window"),
"slideIndex" : 0,
"length" : function() {
return this.slides.length;
},
"currentSlide" : function() {
return this.slides[this.slideIndex];
}
};
$.subscribe("presentation:show", function() {
setTimeout(function() { PresentationKeyboard.enable(); }, 50 );
MainKeyboard.disable();
$("#main-content").append("<div id='current-slide' style='margin: 0; padding: 0; width: 100%; height: 650px; margin-left:auto; margin-right:auto; overflow:hidden; font-size: 80%; position:fixed; left: 0; top: 0; z-index: 99; zoom: 200%; background: #FFF; padding: 50px;'>&nbsp;<div style='position: absolute; right: 15px; bottom: 95px;'><span id='current-slide-count'>" + presentationTracker.slideIndex + 1 + "</span> of <span id='total-slide-count'>" + presentationTracker.length() + "</span></div></div>");
$('#current-slide').append(presentationTracker.currentSlide());
// create the div to take over the screen and populate with the first dinow
// find all the code samples
});
$.subscribe("presentation:forward", function() {
presentationTracker.slideIndex = presentationTracker.slideIndex + 1;
if (presentationTracker.slideIndex >= presentationTracker.slides.length) {
presentationTracker.slideIndex = presentationTracker.slides.length - 1;
}
$("#current-slide .window").replaceWith(presentationTracker.currentSlide());
$("#current-slide-count").text(presentationTracker.slideIndex + 1);
});
$.subscribe("presentation:back", function() {
presentationTracker.slideIndex = presentationTracker.slideIndex + - 1;
if (presentationTracker.slideIndex < 0) {
presentationTracker.slideIndex = 0;
}
$("#current-slide .window").replaceWith(presentationTracker.currentSlide());
$("#current-slide-count").text(presentationTracker.slideIndex + 1);
});
$.subscribe("presentation:hide", function() {
setTimeout(function() { MainKeyboard.enable(); }, 50 );
PresentationKeyboard.disable();
$('#current-slide').remove();
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment