Skip to content

Instantly share code, notes, and snippets.

@andiwand
Created July 26, 2016 20:20
Show Gist options
  • Save andiwand/2e01680aad36adc30d8b895ab9423f56 to your computer and use it in GitHub Desktop.
Save andiwand/2e01680aad36adc30d8b895ab9423f56 to your computer and use it in GitHub Desktop.
Javascript focus tree eventing
focustree = (function() {
var entries = [];
var currentFocus = [];
function indexOf(array, element) {
for (var i = 0; i < array.length; i++) {
if (array[i] === element) return i;
}
return -1;
}
function removeAll(a, b) {
var result = [];
for (var i = 0; i < a.length; i++) {
if (indexOf(b, a[i]) < 0) result.push(a[i]);
}
return result;
}
function contains(element) {
for (var i = 0; i < entries.length; i++) {
if (entries[i].element === element) return true;
}
return false;
}
function descendants(start) {
var result = [];
var node = start;
while (node != null) {
if (contains(node)) result.push(node);
node = node.parentNode;
}
return result;
}
function fireIn(element, event) {
var entry = register(element);
for (var i = 0; i < entry.in.length; i++) {
entry.in[i]();
}
}
function fireOut(element, event) {
var entry = register(element);
for (var i = 0; i < entry.out.length; i++) {
entry.out[i]();
}
}
function onfocus(event) {
var newFocus = descendants(event.srcElement);
var elementsIn = removeAll(newFocus, currentFocus);
for (var i = 0; i < elementsIn.length; i++) {
fireIn(elementsIn[i], event);
}
var elementsOut = removeAll(currentFocus, newFocus);
for (var i = 0; i < elementsOut.length; i++) {
fireOut(elementsOut[i], event);
}
currentFocus = newFocus;
}
function onblur(event) {
}
function init() {
document.body.addEventListener("focus", onfocus, true);
document.body.addEventListener("blur", onblur, true);
}
function register(element) {
var i;
for (i = 0; i < entries.length; i++) {
if (entries[i].element === element) break;
}
if (i < entries.length) return entries[i];
var entry = {element: element, in: [], out: []};
entries.push(entry);
return entry;
}
function registerIn(element, callback) {
var entry = register(element);
entry.in.push(callback);
}
function registerOut(element, callback) {
var entry = register(element);
entry.out.push(callback);
}
return {init: init, registerIn: registerIn, registerOut: registerOut};
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment