Skip to content
Open
4 changes: 2 additions & 2 deletions html/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -269,13 +269,13 @@ a {
.button--sacnite:not(.disabled):hover {
color: #37474f;
}
.button--sacnite.button--inverted:not(.disabled):hover {
.button--sacnite.button--inverted:not(.disabled):hover i, .button--sacnite.button--inverted:not(.disabled):focus i {
color: #fff;
}
.button--sacnite.button--inverted.active {
color: #fff;
}
.button--sacnite:not(.active):not(.disabled):hover::before {
.button--sacnite:not(.active):not(.disabled):hover::before, .button--sacnite:not(.active):not(.disabled):focus::before {
box-shadow: inset 0 0 0 2px #37474f;
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
Expand Down
4 changes: 4 additions & 0 deletions html/css/svg-styles.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
.node:hover {
fill: #808080;
}

.node.hover {
fill: #808080;
}
.node.selected {
fill: #14A520;
}
Expand Down
8 changes: 5 additions & 3 deletions html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@
<li><button id="button-player-less" class="button button--sacnite button--inverted" alt="Less players" title="Less players"><i class="icon-user-less"></i></button></li>
</ul>
<ul class="vertical-centered">
<li><button id="button-merge" class="button button--sacnite button--inverted" alt="Merge isets"><i class="icon-link"></i></button></li>
<li><button id="button-dissolve" class="button button--sacnite button--inverted" alt="Dissolve iset"><i class="icon-unlink"></i></button></li>
<li><button id="button-merge" class="button button--sacnite button--inverted" alt="Merge isets" title="Merge isets"><i class="icon-link"></i></button></li>
<li><button id="button-dissolve" class="button button--sacnite button--inverted" alt="Dissolve iset" title="Dissolve isets"><i class="icon-unlink"></i></button></li>
</ul>
<ul class="vertical-centered">
<li><button id="button-settings" class="button button--sacnite button--inverted" alt="Settings"><i class="icon-cog"></i></button></li>
<li><button id="button-settings" class="button button--sacnite button--inverted" alt="Settings" title="Settings"><i class="icon-cog"></i></button></li>
</ul>
</div>
</div>
Expand Down Expand Up @@ -88,11 +88,13 @@ <h2>Settings</h2>
</form>
</div>
</div>
<script src="js/thirdparty/KeyEvent.min.js"></script>
<script src="js/thirdparty/svg.min.js"></script>
<script src="js/structure.js"></script>
<script src="js/guiutils/Tools.js"></script>
<script src="js/guiutils/ContentEditable.js"></script>
<script src="js/guiutils/MultiAction.js"></script>
<script src="js/guiutils/KeyTraversal.js"></script>
<script src="js/tree/Utils.js"></script>
<script src="js/tree/ISet.js"></script>
<script src="js/tree/Move.js"></script>
Expand Down
224 changes: 224 additions & 0 deletions html/js/guiutils/KeyTraversal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
GTE.UI = (function (parentModule) {

/**
* Creates a new KeyTraversal object. Currently implements
* "postorder" tree traversal.
* @class
*/
function KeyTraversal() {
this.keyMode = GTE.KEYMODES.NODE_TRAVERSAL;
this.activeNode = null;
this.activeMulti = null;
this.enabled = null;
}

/**
* Function that switches the current key traversal mode
* Valid modes are declared in GTE.KEYMODES
* @param {Number} newMode Key mode to be switched to.
*/
KeyTraversal.prototype.switchMode = function(newMode) {
switch(newMode) {
case GTE.KEYMODES.DISABLED:
break;
case GTE.KEYMODES.NODE_TRAVERSAL:
case GTE.KEYMODES.MULTI_TRAVERSAL:
var buttonsToBlur = document.getElementsByTagName('button');
for (var i = 0; i < buttonsToBlur.length; i++)
buttonsToBlur[i].blur();
break;
case GTE.KEYMODES.NO_TRAVERSAL:
this.resetCanvasFocuses();
break;
}
this.keyMode = newMode;
};

/**
* Function that adds listeners for KeyTraversal functionality
*/
KeyTraversal.prototype.addListeners = function() {
this.enabled = true;
document.addEventListener("keydown", this.keyHandler.bind(this));
document.addEventListener("click", this.resetCanvasFocuses.bind(this));
};

/**
* Function that removes listeners for KeyTraversal functionality
*/
KeyTraversal.prototype.removeListeners = function() {
this.enabled = false;
document.removeEventListener("keydown", this.keyHandler.bind(this));
document.removeEventListener("click", this.resetCanvasFocuses.bind(this));
}

/**
* Function that resets the currently any currently focused canvas objects
*/
KeyTraversal.prototype.resetCanvasFocuses = function() {
if (this.activeNode != null){
this.activeNode.classList.remove("hover");
}
if (this.activeMulti != null) {
this.activeMulti.onmouseout();
}
this.activeNode = null;
this.activeMulti = null;
}

/**
* Function that traverses canvas objects via keypresses
* @param {Number} e KeyCode for key pressed
*/
KeyTraversal.prototype.keyHandler = function(e) {
//console.log(e.which);
if (this.keyMode == GTE.KEYMODES.DISABLED)
return;
/**
* Function that traverses canvas tree until it finds an object of a
* specified type, else returns a default canvas object.
*
* @param {String} name The tag name of the target canvas object.
* @param {SVGAnimatedString} startNode Start object to traverse from
* @param {SVGAnimatedString} loopValue Value to hover on after end traversal
* @param {Boolean} isReverse Determines if traversing backwards
* @return {SVGAnimatedString} Returns the next object after traversal.
*/
function findElement(name, startNode, loopValue, isReverse) {
var nextElement = startNode;
var check;

while (true) {

if (isReverse)
check = nextElement.previousElementSibling;
else
check = nextElement.nextElementSibling;

if (check == null) {
nextElement = loopValue;
break;
} else {
nextElement = check;
if (nextElement.tagName == name)
break;
}
}

return nextElement;
};

/**
* Function that changes the current mode, and delegates what the
* current hovered svg object should change to.
*
* @param {String} newMode The mode corresponding to the hovered object.
* @param {String} name The tag name of the SVG object.
* @param {SVGAnimatedString} currentValue The current hovered object.
* @param {SVGAnimatedString} rootValue The default object to hover on.
* @param {SVGAnimatedString} loopValue Value to hover on after end traversal
* @param {Boolean} isReverse Whether to traverse backwards if needed.
* @param {KeyTraversal} self Access to outer scope of this function.
* @return {SVGAnimatedString} Returns the new object to hover on.
*/
function assignActive(newMode, name, currentValue, rootValue, loopValue, isReverse, self) {
// If coming from a different mode, reset and change mode
if (self.keyMode != newMode) {
self.resetCanvasFocuses();
self.switchMode(newMode);
}

// If currently null, then hover on root
if (currentValue == null)
currentValue = rootValue;
else
currentValue = findElement(name, currentValue, loopValue, isReverse);

return currentValue;
};

// Will hold the default loop-around value
var loopValue;
// Will hold the root value to hover on initially
var rootValue;

switch(e.which) {
case KeyEvent.DOM_VK_UP:

// Remove hover on current node
if (this.activeNode != null)
this.activeNode.classList.remove("hover");

rootValue = document.querySelector(".node.root");
loopValue = document.querySelector(".node");

this.activeNode = assignActive(GTE.KEYMODES.NODE_TRAVERSAL, "ellipse",
this.activeNode, rootValue, loopValue, false, this);

// Add hover to new current node
this.activeNode.classList.add("hover");
break;

case KeyEvent.DOM_VK_DOWN:

// Remove hover on current node
if (this.activeNode != null)
this.activeNode.classList.remove("hover");

rootValue = document.querySelector(".node.root");
loopValue = document.querySelector(".node.root");

this.activeNode = assignActive(GTE.KEYMODES.NODE_TRAVERSAL, "ellipse",
this.activeNode, rootValue, loopValue, true, this);

if (!this.activeNode)
return;
// Add hover to new current node
this.activeNode.classList.add("hover");
break;

case KeyEvent.DOM_VK_X:

// Remove hover on current multi
if (this.activeMulti != null)
this.activeMulti.onmouseout();

rootValue = document.querySelector(".multiaction-rect.root");
loopValue = document.querySelector(".multiaction-rect.root");

do {
this.activeMulti = assignActive(GTE.KEYMODES.MULTI_TRAVERSAL, "rect",
this.activeMulti, rootValue, loopValue, false, this);
}
while(this.activeMulti != null && this.activeMulti.classList.contains('show'));

if (!this.activeMulti)
return;
// Add hover to current multi
this.activeMulti.onmouseover();
break;

case KeyEvent.DOM_VK_SPACE:

// Simulate click on object depending on mode
if (this.keyMode == GTE.KEYMODES.NODE_TRAVERSAL) {
if (this.activeNode != null)
this.activeNode.onclick();
} else if (this.keyMode == GTE.KEYMODES.MULTI_TRAVERSAL) {
if (this.activeMulti != null)
this.activeMulti.onclick();
}
break;

case KeyEvent.DOM_VK_TAB:

// Disable key traversal when tabbing; tabbing is for natural DOM ordering
this.switchMode(GTE.KEYMODES.NO_TRAVERSAL);
break;
}
};

parentModule.KeyTraversal = KeyTraversal;
return parentModule;

}(GTE.UI));
2 changes: 2 additions & 0 deletions html/js/guiutils/MultiAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ GTE.TREE = (function(parentModule) {
color: '#9d9d9d'
})
.addClass('multiaction-rect');
if (this.nodesInLine[0].parent.parent == null)
this.shape.addClass('root');
this.shape.translate(this.x1,
this.y - GTE.CONSTANTS.CIRCLE_SIZE / 2);
var thisMultiAction = this;
Expand Down
5 changes: 5 additions & 0 deletions html/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
// GTE is initialized by the library
GTE.canvas = SVG('canvas').size("100%", "100%").attr({'style': 'background: #fff'});
GTE.tools = new GTE.UI.Tools();
GTE.keyTraversal = new GTE.UI.KeyTraversal();

// Initialize settings
var setSettingsToDefaults = function() {
GTE.STORAGE.settingsCircleSize = GTE.CONSTANTS.CIRCLE_SIZE;
Expand Down Expand Up @@ -73,6 +75,8 @@

// Always start with root and two children
GTE.tools.newTree();
// Initiate key listening for canvas traversal
GTE.keyTraversal.addListeners();

document.getElementById("button-new").addEventListener("click", function(){
GTE.tools.newTree();
Expand Down Expand Up @@ -161,6 +165,7 @@
return false;
});


document.getElementById("button-settings-reset").addEventListener("click", function() {
// Clear localStorage and reset settings
localStorage.clear();
Expand Down
7 changes: 7 additions & 0 deletions html/js/structure.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ var GTE = (function () {
MERGE: 3,
DISSOLVE: 4
};
GTE.KEYMODES = {
DISABLED: 0,
NO_TRAVERSAL: 1,
NODE_TRAVERSAL: 2,
MULTI_TRAVERSAL: 3
};

if (Object.freeze) {
Object.freeze(GTE.MODES);
}
Expand Down
Loading