/**
* @class Abstract controller.
* @author Jakub Melezinek
*
* @abstract
* @protected
* @constructor
* @param {HTMLDivElement} controlsDiv
* @param {HTMLDivElement} treeDiv
*/
btv.AbstractController = function(controlsDiv, treeDiv) {
// Prevent flashing new created elements.
jsgl.IMMEDIATE_UPDATE = true;
/**
* @global
* @type {btv.AbstractController}
*/
btv.controller = this;
/**
* @protected
* @type {HTMLDivElement}
*/
this.controlsDiv = controlsDiv;
/**
* @protected
* @type {HTMLDivElement}
*/
this.treeDiv = treeDiv;
/**
* Init in concrete child class.
*
* @protected
* @type {btv.BinaryTree}
*/
this.tree = this.tree;
/**
* @protected
* @type {btv.Visualiser}
*/
this.visualiser = new btv.Visualiser(new jsgl.Panel(treeDiv));
/**
* @protected
* @type {jsgl.util.ArrayList}
*/
this.algorithms = new btv.AlgorithmsArrayList();
/**
* @public
* @type {mixed}
*/
this.returnedValue = undefined;
/**
* @protected
* @type {Function}
*/
this.delegatedDisableButtons = jsgl.util.delegate(this, this.disableButtons);
/**
* @protected
* @type {Function}
*/
this.delegatedEnableButtons = jsgl.util.delegate(this, this.enableButtons);
// create inner divs
/**
* @protected
* @type {HTMLDivElement}
*/
this.controlsDiv.animationDiv = document.createElement("div");
this.controlsDiv.animationDiv.setAttribute("id", "animationDiv");
this.controlsDiv.appendChild(this.controlsDiv.animationDiv);
// fill animation div
this.controlsDiv.animationDiv.innerHTML =
'<div id="animationLegend" class="legend">Animation</div>' +
'<div class="item">' +
'<button id="previousButton">Previous</button>' +
'<button id="skipBackwardButton">Skip Backward</button>' +
'<button id="playPauseButton">Play</button>' +
'<button id="skipForwardButton">Skip Forward</button>' +
'<button id="nextButton">Next</button>' +
'<input id="continuouslyCheckbox" type="checkbox" checked="checked"/><label for="continuouslyCheckbox">Continuously</label>' +
'</div>' +
'<div class="item">' +
'Speed of move: <div id="moveSpeedSlider"></div>' +
'</div>' +
'<div class="item">' +
'Duration of a step: <div id="stepDurationSlider"></div>' +
'</div>';
// jQuery UI
$("#previousButton").button({
icons: {
primary: "ui-icon-seek-prev"
},
disabled: true,
text: false
}).click(jsgl.util.delegate(this, this.redoPreviousButton));
$("#skipBackwardButton").button({
icons: {
primary: "ui-icon-seek-start"
},
disabled: true,
text: false
}).click(jsgl.util.delegate(this, this.skipBackwardButton));
$("#playPauseButton").button({
icons: {
primary: "ui-icon-play"
},
text: false,
disabled: true
}).click(jsgl.util.delegate(this, this.playPauseButton));
$("#skipForwardButton").button({
icons: {
primary: "ui-icon-seek-end"
},
disabled: true,
text: false
}).click(jsgl.util.delegate(this, this.skipForwardButton));
$("#nextButton").button({
icons: {
primary: "ui-icon-seek-next"
},
disabled: true,
text: false
}).click(jsgl.util.delegate(this, this.redoNextButton));
$("#continuouslyCheckbox").change(jsgl.util.delegate(this, this.continuouslyCheckbox));
$("#moveSpeedSlider").slider({
min: 100,
max: 1000,
value: this.visualiser.getMoveSpeed()*1000,
change: jsgl.util.delegate(this, this.moveSpeedButton)
});
$("#stepDurationSlider").slider({
min: 100,
max: 2000,
value: this.visualiser.getStepDuration(),
change: jsgl.util.delegate(this, this.stepDurationButton)
});
/**
* @protected
* @type {HTMLDivElement}
*/
this.controlsDiv.historyDiv = document.createElement("div");
this.controlsDiv.historyDiv.setAttribute("id", "historyDiv");
this.controlsDiv.appendChild(this.controlsDiv.historyDiv);
// fill history div
this.controlsDiv.historyDiv.innerHTML =
'<div id="historyLegend" class="legend">History</div>' +
'<form id="historyForm" action="javascript:btv.controller.redoSelectedButton()">' +
'<div class="item">' +
'<select id="historySelect" ondblclick="btv.controller.redoSelectedButton();">' +
'</select>' +
'</div>' +
'</form>';
/**
* @protected
* @type {HTMLDivElement}
*/
this.controlsDiv.algorithmsDiv = document.createElement("div");
this.controlsDiv.algorithmsDiv.setAttribute("id", "algorithmsDiv");
this.controlsDiv.appendChild(this.controlsDiv.algorithmsDiv);
}
/**
* Check and alert.
*
* @protected
* @static
* @param{Number} num
* @return{Boolean}
*/
btv.AbstractController.isNumber = function(num) {
if(isNaN(num)) {
alert("The value is not a number.");
return false;
}
return true;
}
/**
* Add an option to historySelect.
*
* @protected
* @param {btv.AbstractAlgorithm} algorithm
*/
btv.AbstractController.prototype.addHistoryOption = function(algorithm) {
var select = document.getElementById("historySelect");
var option = document.createElement("option");
option.text = algorithm.toString();
// add the option at the end
try
{
// for IE earlier than version 8
select.add(option,select.options[null]);
}
catch (e)
{
select.add(option,null);
}
// select current algorithm
select.selectedIndex = this.algorithms.currentAlgorithmIndex;
}
/**
* Enable algorithms buttons and change animation buttons.
* Used as listener of end of animation.
*
* @protected
*/
btv.AbstractController.prototype.enableButtons = function() {
var buttons;
var i;
buttons = this.getAlgorithmsButtons();
for(i = 0; i < buttons.length; i++) {
buttons[i].disabled = false;
buttons[i].form.onsubmit = function () {
return true;
};
}
$("#playPauseButton").button("option", "disabled", true).button("option", "icons", {
primary: "ui-icon-play"
});
$("#skipForwardButton").button("option", "disabled", true);
}
/**
* Disable algorithms buttons and change animation buttons.
* Used as listener of start of animation.
*
* @protected
*/
btv.AbstractController.prototype.disableButtons = function() {
var buttons;
var i;
buttons = this.getAlgorithmsButtons();
for(i = 0; i < buttons.length; i++) {
buttons[i].disabled = true;
buttons[i].form.onsubmit = function () {
return false;
};
}
$("#playPauseButton").button("option", "disabled", false).button("option", "icons", {
primary: "ui-icon-pause"
});
$("#skipBackwardButton").button("option", "disabled", false);
$("#skipForwardButton").button("option", "disabled", false);
if(this.algorithms.getCurrentAlgorithmIndex() >= 1) {
$("#previousButton").button("option", "disabled", false);
}
if(this.algorithms.getCurrentAlgorithmIndex() < this.algorithms.getCount() - 1) {
$("#nextButton").button("option", "disabled", false);
} else {
$("#nextButton").button("option", "disabled", true);
}
}
/**
* @abstract
* @protected
*/
btv.AbstractController.prototype.getAlgorithmsButtons = function() {
throw new AlgorithmException("abstract function");
}
/**
* Plays or pause current visualisation depending on state of animation.
*
* @public
*/
btv.AbstractController.prototype.playPauseButton = function() {
switch(this.visualiser.animation.isPlaying()) {
case -1: // animation is stopped
break;
case 0: // animation is paused
this.playButton();
break;
case 1: // animation is playing
this.pauseButton();
break;
}
}
/**
* Plays current visualisation. Change play/pause button.
*
* @public
*/
btv.AbstractController.prototype.playButton = function() {
if(this.visualiser.playAnimation()) {
$("#playPauseButton").button( "option", "icons", {
primary: "ui-icon-pause"
});
}
}
/**
* Pauses current visualisation. Change play/pause button.
*
* @public
*/
btv.AbstractController.prototype.pauseButton = function() {
if(this.visualiser.pauseAnimation()) {
$("#playPauseButton").button("option", "icons", {
primary: "ui-icon-play"
});
}
}
/**
* Set new speed of move.
*
* @public
*/
btv.AbstractController.prototype.moveSpeedButton = function(event, ui) {
//var speed = $("#moveSpeedSlider").slider("option", "value");
this.visualiser.setMoveSpeed(ui.value/1000);
}
/**
* Set new duration of a step.
*
* @public
*/
btv.AbstractController.prototype.stepDurationButton = function(event, ui) {
this.visualiser.setStepDuration(ui.value);
}
/**
* Skip current visualisation backward.
*
* @public
*/
btv.AbstractController.prototype.skipBackwardButton = function() {
var alg = this.algorithms.getCurrentAlgorithm();
if(alg !== null) {
this.isPlayingSafety();
this.redoAlgorithm(alg);
} else {
alert("No algorithm.");
}
}
/**
* Skip current visualisation forward.
*
* @public
*/
btv.AbstractController.prototype.skipForwardButton = function() {
var skipped = this.visualiser.skipAnimationForward();
if(skipped) { // if a visualisation was skipped it is needed to redraw tree and fire end listeners of animation
this.visualiser.redrawTree(this.tree);
var curAlg = this.algorithms.getCurrentAlgorithm();
if($('#continuouslyCheckbox').is(':checked')) { // do not go to next animation
// remove end animation listener to delegated increase algorithm index
curAlg.removeEndAnimationListener(this.algorithms.delegatedIncreaseCurrentAlgorithmIndex);
}
curAlg.fireEndAnimationListeners(); // will fire end listeners but without delegatedIncreaseCurrentAlgorithmIndex
if($('#continuouslyCheckbox').is(':checked')) {
// readd end animation listener to delegated increase algorithm index
curAlg.addEndAnimationListener(this.algorithms.delegatedIncreaseCurrentAlgorithmIndex);
}
}
}
/**
* Add or remove listeners that ensure playing one animation after another.
*
* @public
*/
btv.AbstractController.prototype.continuouslyCheckbox = function() {
if($('#continuouslyCheckbox').is(':checked')) {
// add increaseCurrentAlgorithmIndex() function to all algorithms as endAnimatorListener
for(var i = 0; i < this.algorithms.getCount(); i++) {
this.algorithms.get(i).addEndAnimationListener(this.algorithms.delegatedIncreaseCurrentAlgorithmIndex);
}
} else {
// remove increaseCurrentAlgorithmIndex() function from all algorithms
for(var j = 0; j < this.algorithms.getCount(); j++) {
this.algorithms.get(j).removeEndAnimationListener(this.algorithms.delegatedIncreaseCurrentAlgorithmIndex);
}
}
}
/**
* Redo previous algorithm and start animation.
*
* @public
*/
btv.AbstractController.prototype.redoPreviousButton = function() {
var index = this.algorithms.getCurrentAlgorithmIndex() - 1; // previous
var alg = this.algorithms.get(index);
if(alg !== null) {
this.isPlayingSafety();
this.algorithms.currentAlgorithmIndex = index; // set right current index
this.redoAlgorithm(alg);
} else {
alert("No previous algorithm.");
}
if(this.algorithms.getCurrentAlgorithmIndex() >= 1) {
$("#previousButton").button("option", "disabled", false);
} else {
$("#previousButton").button("option", "disabled", true);
}
}
/**
* Redo algorithm selected from history and start animation.
*
* @public
*/
btv.AbstractController.prototype.redoSelectedButton = function() {
var index = document.getElementById("historySelect").selectedIndex; // selected
var alg = this.algorithms.get(index);
if(alg !== null) {
this.isPlayingSafety();
this.algorithms.currentAlgorithmIndex = index; // set current index
this.redoAlgorithm(alg);
} else {
alert("No selected algorithm.");
}
if(this.algorithms.getCurrentAlgorithmIndex() >= 1) {
$("#previousButton").button("option", "disabled", false);
} else {
$("#previousButton").button("option", "disabled", true);
}
if(this.algorithms.getCurrentAlgorithmIndex() < this.algorithms.getCount() - 1) {
$("#nextButton").button("option", "disabled", false);
} else {
$("#nextButton").button("option", "disabled", true);
}
}
/**
* Redo next algorithm and start animation.
*
* @public
*/
btv.AbstractController.prototype.redoNextButton = function() {
var index = this.algorithms.getCurrentAlgorithmIndex() + 1; // next
var alg = this.algorithms.get(index);
if(alg !== null) {
this.isPlayingSafety();
this.algorithms.currentAlgorithmIndex = index; // set right current index
this.redoAlgorithm(alg);
} else {
alert("No next algorithm.");
}
if(this.algorithms.getCurrentAlgorithmIndex() < this.algorithms.getCount() - 1) {
$("#nextButton").button("option", "disabled", false);
} else {
$("#nextButton").button("option", "disabled", true);
}
}
/**
* Skip animation forward if it is playing but it is need to be stopped.
*
* @protected
*/
btv.AbstractController.prototype.isPlayingSafety = function() {
if(this.visualiser.animation.isPlaying() != -1) { // not stopped, stop it
this.skipForwardButton(); // do not fire increase cur alg index, but fire all others end listeners
}
}
/**
* Add an algorithm to algorithms array list, add history option and increase current algorithm index that (re)does the algorithm for the first time and plays the algorithm.
*
* @protected
* @param {btv.AbstractAlgorithm} algorithm
*/
btv.AbstractController.prototype.doAlgorithm = function(algorithm) {
// if there are some algorithms after current one
// they have to be removed from algorithms array list and history select
var select = document.getElementById("historySelect");
for(var i = this.algorithms.getCount() - 1; i > this.algorithms.currentAlgorithmIndex; i--) {
this.algorithms.removeAt(i);
select.remove(i);
}
algorithm.addStartAnimationListener(this.delegatedDisableButtons);
algorithm.addEndAnimationListener(this.delegatedEnableButtons);
this.algorithms.add(algorithm, $('#continuouslyCheckbox').is(':checked'));
this.algorithms.increaseCurrentAlgorithmIndex();
this.addHistoryOption(algorithm);
}
/**
* Calls undoAlgorithm(returns tree to the state before given algorithm, redraw tree and select right history option) and execute the algorithm again and play the animation.
*
* @protected
* @param {btv.AbstractAlgorithm}
*/
btv.AbstractController.prototype.redoAlgorithm = function(algorithm) {
if(algorithm != null) {
this.undoAlgorithm(algorithm);
algorithm.redo();
this.visualiser.playAnimation();
}
}
/**
* Returns tree to the state before given algorithm, redraw tree and select right history option.
*
* @protected
* @param {btv.AbstractAlgorithm}
*/
btv.AbstractController.prototype.undoAlgorithm = function(algorithm) {
// return to the tree in state before that algoritm
algorithm.undo();
// redraw the tree
this.visualiser.redrawTree(this.tree);
// select right algorithm in history option
var select = document.getElementById("historySelect");
select.selectedIndex = this.algorithms.getCurrentAlgorithmIndex();
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/**
* @class Controller for binary search tree.
* @author Jakub Melezinek
*
* @public
* @constructor
* @param {HTMLDivElement} controlsDiv
* @param {HTMLDivElement} treeDiv
* @extends btv.AbstractController
*/
btv.BinarySearchTreeController = function(controlsDiv, treeDiv) {
this.tree = new btv.BinaryTree("Binary Search Tree");
btv.AbstractController.call(this, controlsDiv, treeDiv);
// fill div with controls
this.controlsDiv.algorithmsDiv.innerHTML =
'<div id="algorithmsLegend" class="legend">Algorithms</div>' +
'<div class="item">' +
'<form id="BSTRandomBSTreeForm" action="javascript:btv.controller.randomBSTreeButton()">' +
'<input id="BSTRandomBSTreeButton" type="submit" value="Random BSTree"/> ' +
'min: <input id="BSTRandomBSTreeMinText" type="text" value="0" size="1"/> ' +
'max: <input id="BSTRandomBSTreeMaxText" type="text" value="99" size="1"/>' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BSTInsertForm" action="javascript: btv.controller.insertButton()">' +
'<input id="BSTInsertButton" type="submit" value="Insert"/> ' +
'value: <input id="BSTInsertText" type="text" size="1"/>' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BSTFindForm" action="javascript:btv.controller.findButton()">' +
'<input id="BSTFindButton" type="submit" value="Find"/> ' +
'value: <input id="BSTFindText" type="text" size="1"/>' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BSTDeleteForm" action="javascript:btv.controller.deleteButton()">' +
'<input id="BSTDeleteButton" type="submit" value="Delete"/> selected node' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BSTGetMaxForm" action="javascript:btv.controller.getMaxButton()">' +
'<input id="BSTGetMaxButton" type="submit" value="Get Max"/> of selected (sub)tree ' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BSTGetMinForm" action="javascript:btv.controller.getMinButton()">' +
'<input id="BSTGetMinButton" type="submit" value="Get Min"/> of selected (sub)tree ' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BSTGetPredecessorForm" action="javascript:btv.controller.getPredecessorButton()">' +
'<input id="BSTGetPredecessorButton" type="submit" value="Get Predecessor"/> of selected node' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BSTGetSuccessorForm" action="javascript:btv.controller.getSuccessorButton()">' +
'<input id="BSTGetSuccessorButton" type="submit" value="Get Successor"/> of selected node' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BSTToPreorderArrayForm" action="javascript:btv.controller.toPreorderArrayButton()">' +
'<input id="BSTToPreorderArrayButton" type="submit" value="To Preorder Array"/>' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BSTToInorderArrayForm" action="javascript:btv.controller.toInorderArrayButton()">' +
'<input id="BSTToInorderArrayButton" type="submit" value="To Inorder Array"/> (To Sorted Array)' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BSTToPostorderArrayForm" action="javascript:btv.controller.toPostorderArrayButton()">' +
'<input id="BSTToPostorderArrayButton" type="submit" value="To Postorder Array"/>' +
'</form>' +
'</div>';
}
btv.BinarySearchTreeController.jsglExtend(btv.AbstractController);
/**
* @override
* @protected
*/
btv.BinarySearchTreeController.prototype.getAlgorithmsButtons = function() {
return new Array(
document.getElementById("BSTRandomBSTreeButton"),
document.getElementById("BSTInsertButton"),
document.getElementById("BSTFindButton"),
document.getElementById("BSTDeleteButton"),
document.getElementById("BSTGetMaxButton"),
document.getElementById("BSTGetMinButton"),
document.getElementById("BSTGetPredecessorButton"),
document.getElementById("BSTGetSuccessorButton"),
document.getElementById("BSTToPreorderArrayButton"),
document.getElementById("BSTToInorderArrayButton"),
document.getElementById("BSTToPostorderArrayButton")
);
}
/**
* @public
*/
btv.BinarySearchTreeController.prototype.randomBSTreeButton = function() {
// get params
var minInput = document.getElementById("BSTRandomBSTreeMinText");
var maxInput = document.getElementById("BSTRandomBSTreeMaxText");
// parse values to int
var min = parseInt(minInput.value);
if(btv.AbstractController.isNumber(min) == false) {
minInput.value = "";
minInput.focus();
return;
}
var max = parseInt(maxInput.value);
if(btv.AbstractController.isNumber(max) == false) {
maxInput.value = "";
maxInput.focus();
return;
}
if(min > max) {
alert("Minimum is greather than maximum.");
return;
}
// create alg
var alg = new btv.bst.RandomBSTreeAlg(this.tree, this.visualiser, min, max);
// execute alg
this.doAlgorithm(alg);
}
/**
* @public
*/
btv.BinarySearchTreeController.prototype.insertButton = function() {
// get alg params
var valueInput = document.getElementById("BSTInsertText");
// parse value to float and check if is number
var value = parseFloat(valueInput.value);
if(btv.AbstractController.isNumber(value) == false) {
// reset value input
valueInput.value = "";
valueInput.focus();
return;
}
// create alg
var alg = new btv.bst.InsertAlg(this.tree, this.visualiser, value);
// execute alg
this.doAlgorithm(alg);
// reset value input
valueInput.value = "";
valueInput.focus();
}
/**
* @public
*/
btv.BinarySearchTreeController.prototype.findButton = function() {
// get alg params
var valueInput = document.getElementById("BSTFindText");
var value = parseFloat(valueInput.value);
if(btv.AbstractController.isNumber(value) == false) {
// reset value input
valueInput.value = "";
valueInput.focus();
return;
}
// create alg
var alg = new btv.bst.FindAlg(this.tree, this.visualiser, value);
// execute alg
this.doAlgorithm(alg);
// reset value input
valueInput.value = "";
valueInput.focus();
}
/**
* @public
*/
btv.BinarySearchTreeController.prototype.deleteButton = function() {
// get alg params
var selectedNode = this.visualiser.getSelectedNode();
if(selectedNode === null) {
return;
}
// create alg
var alg = new btv.bst.DeleteAlg(this.tree, this.visualiser, selectedNode);
// execute alg
this.doAlgorithm(alg);
}
/**
* @public
*/
btv.BinarySearchTreeController.prototype.getMaxButton = function() {
// get alg params
var selectedNode = this.visualiser.getSelectedNode();
if(selectedNode === null) {
selectedNode = this.tree.getRoot(); // get max of whole tree
if(selectedNode === null) { // root === null
return;
}
}
// create alg
var alg = new btv.bst.GetMaxAlg(this.tree, this.visualiser, selectedNode);
// execute alg
this.doAlgorithm(alg);
}
/**
* @public
*/
btv.BinarySearchTreeController.prototype.getMinButton = function() {
// get alg params
var selectedNode = this.visualiser.getSelectedNode();
if(selectedNode === null) {
selectedNode = this.tree.getRoot(); // get min of whole tree
if(selectedNode === null) { // root === null
return;
}
}
// create alg
var alg = new btv.bst.GetMinAlg(this.tree, this.visualiser, selectedNode);
// execute alg
this.doAlgorithm(alg);
}
/**
* @public
*/
btv.BinarySearchTreeController.prototype.getPredecessorButton = function() {
// get alg params
var selectedNode = this.visualiser.getSelectedNode();
if(selectedNode === null) {
return;
}
// create alg
var alg = new btv.bst.GetPredecessorAlg(this.tree, this.visualiser, selectedNode);
// execute alg
this.doAlgorithm(alg);
}
/**
* @public
*/
btv.BinarySearchTreeController.prototype.getSuccessorButton = function() {
// get alg params
var selectedNode = this.visualiser.getSelectedNode();
if(selectedNode === null) {
return;
}
// create alg
var alg = new btv.bst.GetSuccessorAlg(this.tree, this.visualiser, selectedNode);
// execute alg
this.doAlgorithm(alg);
}
/**
* @public
*/
btv.BinarySearchTreeController.prototype.toIndexArrayButton = function() {
// create alg
var alg = new btv.bst.ToIndexArrayAlg(this.tree, this.visualiser);
// execute alg
this.doAlgorithm(alg);
}
/**
* @public
*/
btv.BinarySearchTreeController.prototype.toPreorderArrayButton = function() {
// create alg
var alg = new btv.bst.ToPreorderArrayAlg(this.tree, this.visualiser);
// execute alg
this.doAlgorithm(alg);
}
/**
* @public
*/
btv.BinarySearchTreeController.prototype.toInorderArrayButton = function() {
// create alg
var alg = new btv.bst.ToInorderArrayAlg(this.tree, this.visualiser);
// execute alg
this.doAlgorithm(alg);
}
/**
* @public
*/
btv.BinarySearchTreeController.prototype.toPostorderArrayButton = function() {
// create alg
var alg = new btv.bst.ToPostorderArrayAlg(this.tree, this.visualiser);
// execute alg
this.doAlgorithm(alg);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/**
* @class Controller for binary heap.
* @author Jakub Melezinek
*
* @public
* @constructor
* @param {HTMLDivElement} controlsDiv
* @param {HTMLDivElement} treeDiv
* @extends btv.AbstractController
*/
btv.BinaryHeapController = function(controlsDiv, treeDiv) {
this.tree = new btv.BinaryTree("Binary Heap");
btv.AbstractController.call(this, controlsDiv, treeDiv);
// fill div with controls
this.controlsDiv.algorithmsDiv.innerHTML =
'<div id="algorithmsLegend" class="legend">Algorithms</div>' +
'<div class="item">' +
'<form id="BHRandomHeapForm" action="javascript:btv.controller.randomBHeapButton()">' +
'<input id="BHRandomHeapButton" type="submit" value="Random BHeap"/> ' +
'min: <input id="BHRandomHeapMinText" type="text" value="0" size="1"/> ' +
'max: <input id="BHRandomHeapMaxText" type="text" value="99" size="1"/>' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BHBuildHeapForm" action="javascript:btv.controller.buildHeapButton()">' +
'<input id="BHBuildHeapButton" type="submit" value="Build Heap"/> array: <input id="BHArrayText" type="text" size="10"/>' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BHInsertForm" action="javascript: btv.controller.insertButton()">' +
'<input id="BHInsertButton" type="submit" value="Insert"/> value: <input id="BHInsertText" type="text" size="1"/>' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BHDeleteForm" action="javascript:btv.controller.deleteButton()">' +
'<input id="BHDeleteButton" type="submit" value="Delete"/> selected node' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BHExtractMaxForm" action="javascript:btv.controller.extractMaxButton()">' +
'<input id="BHExtractMaxButton" type="submit" value="Extract Max"/>' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BHGetMaxForm" action="javascript:btv.controller.getMaxButton()">' +
'<input id="BHGetMaxButton" type="submit" value="Get max"/>' +
'</form>' +
'</div>' +
'<div class="item">' +
'<form id="BHHeapSortForm" action="javascript:btv.controller.heapSortButton()">' +
'<input id="BHHeapSortButton" type="submit" value="Heap Sort"/>' +
'</form>' +
'</div>';
}
btv.BinaryHeapController.jsglExtend(btv.AbstractController);
/**
* @override
* @protected
*/
btv.BinaryHeapController.prototype.getAlgorithmsButtons = function() {
return new Array(
document.getElementById("BHRandomHeapButton"),
document.getElementById("BHBuildHeapButton"),
document.getElementById("BHInsertButton"),
document.getElementById("BHDeleteButton"),
document.getElementById("BHExtractMaxButton"),
document.getElementById("BHGetMaxButton"),
document.getElementById("BHHeapSortButton")
);
}
/**
* @public
*/
btv.BinaryHeapController.prototype.randomBHeapButton = function() {
// get params
var minInput = document.getElementById("BHRandomHeapMinText");
var maxInput = document.getElementById("BHRandomHeapMaxText");
// parse values to int
var min = parseInt(minInput.value);
if(btv.AbstractController.isNumber(min) == false) {
minInput.value = "";
minInput.focus();
return;
}
var max = parseInt(maxInput.value);
if(btv.AbstractController.isNumber(max) == false) {
maxInput.value = "";
maxInput.focus();
return;
}
if(min > max) {
alert("Minimum is greather than maximum.");
return;
}
// create alg
var alg = new btv.bh.RandomBHeapAlg(this.tree, this.visualiser, min, max);
// execute alg
this.doAlgorithm(alg);
}
/**
* @public
*/
btv.BinaryHeapController.prototype.buildHeapButton = function() {
// get alg params
var valueInput = document.getElementById("BHArrayText");
var array = valueInput.value.split(',');
for(var i = 0; i < array.length; i++) {
array[i] = parseFloat(array[i]);
if(btv.AbstractController.isNumber(array[i]) == false) {
valueInput.focus();
return;
}
}
// create alg
var alg = new btv.bh.BuildHeapAlg(this.tree, this.visualiser, array);
// execute alg
this.doAlgorithm(alg);
// reset value input
valueInput.value = "";
valueInput.focus();
}
/**
* @public
*/
btv.BinaryHeapController.prototype.insertButton = function() {
// get alg params
var valueInput = document.getElementById("BHInsertText");
// parse value to float and check if is number
var value = parseFloat(valueInput.value);
if(btv.AbstractController.isNumber(value) == false) {
// reset value input
valueInput.value = "";
valueInput.focus();
return;
}
// create alg
var alg = new btv.bh.InsertAlg(this.tree, this.visualiser, value);
// execute alg
this.doAlgorithm(alg);
// reset value input
valueInput.value = "";
valueInput.focus();
}
/**
* @public
*/
btv.BinaryHeapController.prototype.deleteButton = function() {
// get alg params
var selectedNode = this.visualiser.getSelectedNode();
if(selectedNode === null) {
return;
}
// create alg
var alg = new btv.bh.DeleteAlg(this.tree, this.visualiser, selectedNode);
// execute alg
this.doAlgorithm(alg);
}
/**
* @public
*/
btv.BinaryHeapController.prototype.extractMaxButton = function() {
// create alg
var alg = new btv.bh.ExtractMaxAlg(this.tree, this.visualiser);
// execute alg
this.doAlgorithm(alg);
}
/**
* @public
*/
btv.BinaryHeapController.prototype.getMaxButton = function() {
// create alg
var alg = new btv.bh.GetMaxAlg(this.tree, this.visualiser);
// execute alg
this.doAlgorithm(alg);
}
/**
* @public
*/
btv.BinaryHeapController.prototype.heapSortButton = function() {
// create alg
var alg = new btv.bh.HeapSortAlg(this.tree, this.visualiser);
// execute alg
this.doAlgorithm(alg);
}