I'm stuck with recursion. I've read a few similar questions, but it brought me no relief.
My function works well inside, but it returns "undefined" at the end.
I have a binary tree. Now I'm trying to make a function, which can get me an answer: if any nodes on this level have children.
class tree_node {
constructor(n_array, parent) {
this.n_array = n_array;
this.has_children = false;
this.children = [];
if (parent != null) {
this.parent = parent;
this.level = this.parent.level + 1;
}
else {
this.level = 0;
}
// run the tree
this.child();
}
child() {
if (this.n_array.length != 1) {
this.has_children = true;
let m = Math.floor(this.n_array.length / 2);
let l = this.n_array.slice(0, m);
let r = this.n_array.slice(m);
const left = new tree_node(l, this);
const right = new tree_node(r, this);
this.children.push(left, right);
}
else return 0
}
get_if_node_has_children(node, level) {
console.log(node.level, node.has_children)
if (node.has_children && node.level < level) {
console.log("in loop")
node.children.forEach(element => {
return element.get_if_node_has_children(element, level);
});
}
else {
console.log("first else")
if (node.level == level && node.has_children) {
console.log("node.level == level && node.has_children " + node.n_array)
return true;
}
else {
console.log("return false")
return false;
}
}
}
show() {
console.log(this.n_array + " | Level: " + this.level + ". " + this.branch + " Has children = " + this.has_children);
if (this.has_children) {
this.children.forEach(element => {
return element.show();
});
}
else {
return 0;
}
}
}
get_if_node_has_children(node, level) work inside, so to speak. I've expected the exact behaviour and log. Except on thing: function returns "undefined". But I have no idea where I missed the point.
let root = [];
class tree_node {
constructor(n_array, parent) {
this.n_array = n_array;
this.has_children = false;
this.children = [];
// при создании экземпляра класса то parent == null
if (parent != null) {
this.parent = parent;
this.level = this.parent.level + 1;
} else {
this.level = 0;
}
// run the tree
this.child();
}
child() {
if (this.n_array.length != 1) {
this.has_children = true;
let m = Math.floor(this.n_array.length / 2);
let l = this.n_array.slice(0, m);
let r = this.n_array.slice(m);
const left = new tree_node(l, this);
const right = new tree_node(r, this);
this.children.push(left, right);
} else return 0
}
get_if_node_has_children(node, level) {
console.log(node.level, node.has_children)
if (node.has_children && node.level < level) {
console.log("in loop")
node.children.forEach(element => {
return element.get_if_node_has_children(element, level);
});
} else {
console.log("first else")
if (node.level == level && node.has_children) {
console.log("node.level == level && node.has_children " + node.n_array)
return true;
} else {
console.log("return false")
return false;
}
}
}
show() {
console.log(this.n_array + " | Level: " + this.level + ". " + "Has children = " + this.has_children);
if (this.has_children) {
this.children.forEach(element => {
return element.show();
});
} else {
return 0;
}
}
// CLASS END ===========================
}
root = new tree_node([1, 3, 5, 7, 9, ])
console.log("=== root.show() ===")
root.show();
console.log("=== let a = root.get_if_node_has_children(root, 2) ===")
let a = root.get_if_node_has_children(root, 2)
console.log(" a is " + a)
There are two problems:
return inside a callback (for instance, your forEach callback) just returns from the callback, not the function that called forEach. In general, in modern code, use for-of unless you need the index of the element.
You're not checking the result of the recursive call before returning it. But if the first child node you call it on returns false, you want to keep looking, rather than immediately returning false.
Fixing both:
get_if_node_has_children(node, level) {
console.log(node.level, node.has_children)
if (node.has_children && node.level < level) {
console.log("in loop")
for (const element of node.children) { // *** #1, using `for-of` instead of `forEach` so we can return below
const hasChild = element.get_if_node_has_children(element, level);
if (hasChild) { // *** #2, only return here if you got `true`
return true; // ***
} // ***
}
return false; // *** #2 part 2 -- didn't find it anywhere, return `false`
} else {
console.log("first else")
if (node.level == level && node.has_children) {
console.log("node.level == level && node.has_children " + node.n_array)
return true;
} else {
console.log("return false")
return false;
}
}
}
I'd reorganize that slightly though, which is easier if I remove some no-longer-needed logging:
get_if_node_has_children(node, level) {
console.log(node.level, node.has_children)
if (node.has_children) {
if (node.level === level) {
return true;
}
if (node.level < level) {
for (const element of node.children) {
if (element.get_if_node_has_children(element, level)) {
return true;
}
}
}
}
return false;
}
I`m trying to remove event listener from a tile that has been filled correctly on a sudoku game. But it is not working. After i fill the correct number on slot, i wish i wouldnt be able to click it again, but happens as the GIF show, it is erasing the grayed slots, meaning that removeEventListener is not working correctly. Any Help?
function qsa(selector) {
return document.querySelectorAll(selector);
}
function removeListenTiles() {
let tiles = qsa("tile");
for (let i = 0; i < tiles.length; i++) {
if (tiles[i].innerHTML.indexOf("table") == -1) {
if (tiles[i].textContent != "") {
tiles[i].removeEventListener("click", () => handleTile(tile[i), true);
}
}
}
}
function handleTile(tile) {
if (!disableSelect) {
if (tile.classList.contains("selected")) {
removeAllGrayedSelected();
updateMove();
removeSelected(tile);
selectedTile = null;
selectedNum = null;
} else {
removeAllGrayedSelected();
if (tile.innerHTML.indexOf("table") != -1) {
for (let j = 0; j < 81; j++) {
if (qsa(".tile")[j] !== tile) removeSelected(qsa(".tile")[j]);
}
tile.classList.add("selected");
selectedTile = tile;
updateSurround(tile);
updateMove();
}
}
}
}
function addListenTile(tile) {
tile.addEventListener("click", () => handleTile(tile), true);
}
Tried the currying method,and added tile.id to handlers array. Solved the problem.
const handlers = [];
const addListenTile = (tile) => {
tile.addEventListener("click", handlers[tile.id] = handleTile(tile), true);
};
const removeListenTile = (tile) => {
tile.removeEventListener("click", handlers[tile,id], true);
}
const handleTile = function (tile) {
return function onhandlerTile(event) {
console.log("OK1")
if (!disableSelect) {
if (tile.classList.contains("selected")) {
console.log("OK2");
removeAllGrayedSelected();
updateMove();
removeSelected(tile);
selectedTile = null;
selectedNum = null;
} else {
console.log("OK3");
removeAllGrayedSelected();
if (tile.innerHTML.indexOf("table") != -1) {
for (let j = 0; j < 81; j++) {
if (qsa(".tile")[j] !== tile) removeSelected(qsa(".tile")[j]);
}
tile.classList.add("selected");
selectedTile = tile;
updateSurround(tile);
updateMove();
}
}
}
};
};
in hasValue class, why return is not working? when i try with console.log and alert, it worked.
want to implement function like priorityQueue.changePriority("Sheru", 1); changePriority class is not working.
commented code is code i tried to implement the changes i.e. i want to change the priority of existing item present in queue. Could anyone please help?
class QElement {
constructor(element, priority) {
this.element = element;
this.priority = priority;
}
}
class PriorityQueue {
constructor() {
this.items = [];
}
isEmpty() {
return this.items.length == 0;
}
add(element, priority) {
var qElement = new QElement(element, priority);
var contain = false;
for (var i = 0; i < this.items.length; i++) {
if (this.items[i].priority > qElement.priority) {
this.items.splice(i, 0, qElement);
contain = true;
break;
}
}
if (!contain) {
this.items.push(qElement);
}
}
peek() {
if (this.isEmpty())
return "No elements in Queue";
return this.items[0];
}
poll() {
if (this.isEmpty())
return "Underflow";
return this.items.shift();
}
/*changePriority(firstTerm, secondTerm)
{
let xxx = new QElement(firstTerm, secondTerm);
for (let i = 0; i < this.items.length; i++){
if (this.items[i].element === firstTerm){
this.items[i].priority = secondTerm;
this.items.splice(i, 0, xxx);
}
}
this.items.push(xxx);
}*/
hasValue(args) {
let status = false;
for (let i = 0; i < this.items.length; i++) {
if (this.items[i].element === args) {
status = true;
}
}
console.log(status);
}
size() {
if (this.isEmpty())
return "Underflow";
return this.items.length;
}
printPQueue() {
var str = "";
for (var i = 0; i < this.items.length; i++)
str += this.items[i].element + " ";
return str;
}
}
var priorityQueue = new PriorityQueue();
console.log(priorityQueue.isEmpty());
console.log(priorityQueue.peek());
priorityQueue.add("Sumit", 2);
priorityQueue.add("Gourav", 1);
priorityQueue.add("Piyush", 1);
priorityQueue.add("Sunny", 2);
priorityQueue.add("Sheru", 3);
console.log(priorityQueue.printPQueue());
console.log(priorityQueue.peek().element);
console.log(priorityQueue.poll().element);
priorityQueue.add("Sunil", 2);
console.log(priorityQueue.size());
priorityQueue.hasValue('Sumit');
console.log(priorityQueue.printPQueue());
priorityQueue.changePriority("Sheru", 1);
console.log(priorityQueue.printPQueue());
You missing return keyword. This just works:
hasValue(args) {
for (let i = 0; i < this.items.length; i++) {
if (this.items[i].element === args) {
return true;
}
}
return false;
}
I did not understand the idea how your changePriority function should work. Just find the element and move it up or down based on priority change:
swap(a, b) {
let tmp = this.items[a];
this.items[a] = this.items[b];
this.items[b] = tmp;
}
changePriority(firstTerm, secondTerm) {
let i = 0;
while (i < this.items.length) {
if (this.items[i].element === firstTerm) {
if (secondTerm < this.items[i].priority) {
// move up
this.items[i].priority = secondTerm;
while (i > 0 && this.items[i - 1].priority > secondTerm) {
this.swap(i - 1, i);
i--;
}
} else if (secondTerm > this.items[i].priority) {
// move down
this.items[i].priority = secondTerm;
while (i < this.items.length - 1 && this.items[i + 1].priority < secondTerm) {
this.swap(i + 1, i);
i++;
}
}
break;
}
i++;
}
}
I am working on JQuery mechanism that is building tree, it has to be as fast as possible. Volume of data is quite large so master record column is used to be able to 'grab' all relevant nodes in one select from webSQL db.
Whole mechanism but one part is done, when assembling tree it must check that there is no infinite recursion being created. What mechanism does at the moment if Record A is Master and Parent of record B, and Record B is Master and Parent of record A then structure like A.Children[0] = B and B.Children[0] = A is being built. It all would work fine, but it has do be knockout.js bound and displayed as expandable list to users, which results in overflow when trying to display the tree.
Requirement is to detect such loops and do not create tree relationships.
Mechanism that would check if item is already in the tree I came up is:
function InTree(master, item) {
return $.inArray(item, $.map(master, function recurs(n) {
return ($.isArray(n) ? $.map(n, recurs) : n);
})) != -1;
}
if(!InTree(tree, record))
{
//attach
} else {
// get next record
}
Is there anything faster than InTree() function that would get me if item is in the tree?
Whole tree building algorithm is below (not that I think it is relevant but rather to avoid the comments 'show the code')
$(document).on('OnPreQuery', onTheMove.PageDataRoles, function (e, options) {
var isChildAttachmentQueued = true;
var knockoutContextName = options.knockoutContextName;
if (TreeEnabled(knockoutContextName)) {
var isModelReadyToAttachChildren = function () {
var isReady = false;
if (PageObj[knockoutContextName] != undefined) {
isReady = (PageObj[knockoutContextName]().length > 0) && isChildAttachmentQueued;
}
return isReady;
};
var businessComponent = eval(knockoutContextName);
var treeSettings = businessComponent.Tree;
treeSettings.knockoutContextName = knockoutContextName;
$(businessComponent).on('OnPreUIUpdate', function (e, options) {
if (isModelReadyToAttachChildren()) {
getChildrenForMasterRecordList({
parentTable: businessComponent.primaryTableName,
knockoutContextName: treeSettings.knockoutContextName,
parentIdColumn: treeSettings.ParentIdColumn,
masterIdColumn: treeSettings.MasterIdColumn
});
isChildAttachmentQueued = false;
}
});
}
});
function TreeEnabled(knockoutContextName) {
var isTreeEnabled = false;
try {
eval(knockoutContextName);
} catch (e) {
return isTreeEnabled;
}
var treeSettings = eval(knockoutContextName).Tree;
if (treeSettings && treeSettings.IncludeChildren) {
isTreeEnabled = true;
}
return isTreeEnabled;
}
function ComposeRecordsToTreeStructure(results, tableArray, columnArray, options) {
if (results.rows.length > 0) {
if (options.parentLayerIdList == undefined) {
options.parentLayerIdList = options.masterIdList;
}
if (options.orphans == undefined) {
options.orphans = [];
}
var knockoutContextName = options.knockoutContextName;
var childRecordIdArray = [];
if (options.runningOnOrphans) {
if (options.orphans.length > 0) {
for (var j = 0; j < options.orphans.length; j++) {
var rowRecord = options.orphans[j];
var rowRecordParentId = rowRecord[options.parentIdColumn];
var result = EstablishParentChildConnectionOnAlreadyProcessedNodes(rowRecord, rowRecordParentId, options.parentLayerIdList, knockoutContextName, childRecordIdArray, options);
if (result.hasEstablishedConnection) {
childRecordIdArray = result.childRecordIdArray;
}
}
options.orphans = $.grep(options.orphans, function (item) {
return $.inArray(item['Id'], childRecordIdArray) == -1;
});
}
} else {
for (var i = 0; i < results.rows.length; i++) {
var rowRecord = results.rows.item(i);
var rowRecordParentId = rowRecord[options.parentIdColumn];
if (rowRecord[options.parentIdColumn] == '' || rowRecord[options.masterIdColumn] == '' || rowRecord[options.masterIdColumn] == rowRecord['Id']) {
rowRecord.isInvalid = true;
} else if ($.inArray(rowRecord['Id'], options.masterIdList) != -1) {
masterRecordClone = $.grep(PageObj[knockoutContextName](), function (item) { return item.Fields.Id() == rowRecord['Id'] })[0];
if (masterRecordClone != undefined && masterRecordClone.Children) {
rowRecord.Children = masterRecordClone.Children;
}
}
if (rowRecord.isInvalid == true) {
if (rowRecord[options.masterIdColumn] != rowRecord['Id']) {
var result = EstablishParentChildConnection(rowRecord, rowRecord[options.masterIdColumn], options.parentLayerIdList, knockoutContextName, childRecordIdArray, options);
if (result.hasEstablishedConnection) {
childRecordIdArray = result.childRecordIdArray;
EstablishParentChildConnectionOnAlreadyProcessedNodes(rowRecord, rowRecordParentId, options.parentLayerIdList, knockoutContextName, childRecordIdArray, options);
}
}
} else {
var result = EstablishParentChildConnectionOnAlreadyProcessedNodes(rowRecord, rowRecordParentId, options.parentLayerIdList, knockoutContextName, childRecordIdArray, options);
if (result.hasEstablishedConnection) {
childRecordIdArray = result.childRecordIdArray;
} else {
var recordObject = AddIsExpandedProperty(rowRecord);
options.orphans.push(recordObject);
options.runningOnOrphans = true;
}
}
}
}
if (options.orphans.length > 0 && childRecordIdArray.length > 0) {
options.parentLayerIdList = childRecordIdArray;
ComposeRecordsToTreeStructure(results, tableArray, columnArray, options);
}
}
onTheMove.seleniumHelper.markPageAsLoaded();
}
function EstablishParentChildConnectionOnAlreadyProcessedNodes(rowRecord, rowRecordParentId, parentLayerIdList, knockoutContextName, childRecordIdArray, options) {
var result = EstablishParentChildConnection(rowRecord, rowRecordParentId, parentLayerIdList, knockoutContextName, childRecordIdArray);
if (result.hasEstablishedConnection) {
childRecordIdArray = result.childRecordIdArray;
} else {
var result = EstablishParentChildConnection(rowRecord, rowRecordParentId, childRecordIdArray, knockoutContextName, childRecordIdArray);
if (result.hasEstablishedConnection) {
childRecordIdArray = result.childRecordIdArray;
} else {
var matchingOrphans = $.grep(options.orphans, function (item) {
return item['Id'] == rowRecordParentId;
});
if (matchingOrphans.length > 0) {
AttachPassedChildRecord(rowRecord, matchingOrphans);
var result = {
hasEstablishedConnection: true
};
}
}
}
return {
childRecordIdArray: childRecordIdArray,
hasEstablishedConnection: result.hasEstablishedConnection
};
}
function EstablishParentChildConnection(rowRecord, rowRecordParentId, parentLayerIdList, knockoutContextName, childRecordIdArray) {
var hasEstablishedConnection = false;
var parentPosition = $.inArray(rowRecordParentId, parentLayerIdList);
if (parentPosition != -1) {
AttachChildRecordsToParents(rowRecord, parentLayerIdList[parentPosition], knockoutContextName);
childRecordIdArray = AddChildRecordsToNextParentList(rowRecord, childRecordIdArray);
childRecordIdArray.push(rowRecord['Id']);
hasEstablishedConnection = true;
}
return {
childRecordIdArray: childRecordIdArray,
hasEstablishedConnection: hasEstablishedConnection
};
}
function AddChildRecordsToNextParentList(childRecord, childRecordIdArray) {
if (childRecord.Children != undefined) {
for (var i = 0; i < childRecord.Children.length; i++) {
childRecordIdArray.push(childRecord.Children[i]['Id']);
if (childRecord.Children[i].Children != undefined) {
AddChildRecordsToNextParentList(childRecord.Children[i], childRecordIdArray);
}
}
}
return childRecordIdArray;
}
function RowsToListDataStructure(results) {
var array = [];
for (var i = 0; i < results.rows.length; i++) {
array.push(results.rows.item(i));
}
return array;
}
function AttachChildRecordsToParents(recordRow, id, knockoutContextName) {
var childTreeOptions = {
id: id,
knockoutContextName: knockoutContextName,
results: []
};
findObjectsInChildTreeById(childTreeOptions);
if (childTreeOptions.results.length > 0) {
AttachPassedChildRecord(recordRow, childTreeOptions.results);
}
}
function AttachPassedChildRecord(recordObject, pageObjParentResults) {
for (var i = 0; i < pageObjParentResults.length; i++) {
if (pageObjParentResults[i].Children == undefined) {
pageObjParentResults[i].Children = [];
}
if ($.grep(pageObjParentResults[i].Children, function (children) {
return children['Id'] == recordObject['Id'];
}).length == 0) {
recordObject = AddIsExpandedProperty(recordObject);
pageObjParentResults[i].Children.push(recordObject);
}
}
}
function AddIsExpandedProperty(recordObject) {
recordObject.IsExpanded = ko.observable(false);
return recordObject;
}
function findObjectsInChildTreeById(options) {
if (options.item == undefined) {
if (typeof PageObj[options.knockoutContextName] != 'undefined') {
for (var item in PageObj[options.knockoutContextName]()) {
findObjectsInChildTreeById({
item: PageObj[options.knockoutContextName]()[item],
id: options.id,
results: options.results
});
}
}
} else {
if (typeof options.item.Fields != 'undefined') {
if (options.item.Fields['Id']() == options.id)
options.results.push(options.item);
} else {
if (options.item['Id'] == options.id)
options.results.push(options.item);
}
if (options.item.Children != undefined) {
for (var item in options.item.Children) {
findObjectsInChildTreeById({
item: options.item.Children[item],
id: options.id,
results: options.results
});
}
}
}
}
function getChildrenForMasterRecordList(options) {
var parentTable = options.parentTable,
masterIdColumn = options.masterIdColumn,
parentIdColumn = options.parentIdColumn,
knockoutContextName = options.knockoutContextName,
masterIds = getParentIdsAndMastersOfParentsFromPageObj(knockoutContextName, masterIdColumn);
for (var item in PageObj[options.knockoutContextName]()) {
AddIsExpandedProperty(PageObj[knockoutContextName]()[item]);
}
var dbManager = new OnTheMoveDatabaseManager();
dbManager.queryDatabase({
statement: {
Tables: [{
Alias: parentTable,
JoinSpec: null,
JoinType: "",
Name: parentTable
}, {
Alias: "Record",
JoinSpec: "Record.Id = " + parentTable + ".Id",
JoinType: "INNER",
Name: "Record"
}],
WhereClause: parentTable + "." + masterIdColumn + " IN ('" + masterIds.join("','") + "') AND Record.RecordType ='" + parentTable + "'",
SelectFields: [{
IsAggregate: false,
Name: "*"
}],
DisablePaging: true,
OrderClause: "Record.Id"
},
knockoutContextName: knockoutContextName,
isObservable: false,
masterIdColumn: masterIdColumn,
masterIdList: masterIds,
parentIdColumn: parentIdColumn,
parentTable: options.parentTable,
success: function (results, tableArray, columnArray, options) {
ComposeRecordsToTreeStructure(results, tableArray, columnArray, options);
}
});
}
function getParentIdsAndMastersOfParentsFromPageObj(knockoutContextName, masterColumnName) {
var list = [];
if (typeof PageObj[knockoutContextName] != 'undefined') {
for (var item in PageObj[knockoutContextName]()) {
if ($.inArray(PageObj[knockoutContextName]()[item].Fields['Id'](), list) == -1) {
list.push(PageObj[knockoutContextName]()[item].Fields['Id']());
}
if (PageObj[knockoutContextName]()[item].Fields[masterColumnName]() != '' && $.inArray(PageObj[knockoutContextName]()[item].Fields[masterColumnName](), list) == -1) {
list.push(PageObj[knockoutContextName]()[item].Fields[masterColumnName]());
}
}
}
return list
}
function InTree(master, item) {
return $.inArray(item, $.map(master, function recurs(n) {
return ($.isArray(n) ? $.map(n, recurs) : n);
})) != -1;
}
it depends on your circumstances. if you're able to run code on add/creation of the tree you may simply create a node id array and do a check like
if(allNodes[searchKey])
//etc
This is a very specific solution of course but technically it'd be as fast as it could possibly be.
I'm working on a calculator that takes an expression such as (5+4) and evaluates it by passing the buttons pressed to an array, and then building a parse tree from the data in the array.
What's interesting/strange, is that my code won't push the value of the right parenthesis to the array. Here is my code, could someone help me out?
The console.log activeButton shows that is the value of the button being pressed, but even when I placed calcArray.push() outside the if statements it would not push ) to an array.
$(document).ready(function(){
var calcArray = new Array();
$("input").click(function(){
var activeButton = this.value;
console.log(activeButton);
if(!isNaN(activeButton))
{
calcArray.push(parseInt(activeButton));
console.log(calcArray);
}
else if(activeButton === "=")
{
evaluate(buildTree(calcArray));
calcArray = [];
}
else
{
calcArray.push(activeButton);
}
});
});
The BuildTree code:
function BinaryTree(root) {
this.root = root;
this.activeNode = root;
}
function Node(element){
this.element = element;
this.parent;
this.rightChild;
this.leftChild;
this.setLeft = function(node){
this.leftChild = node;
node.parent = this;
};
this.setRight = function(node){
this.rightChild = node;
node.parent = this;
};
}
//methods
var buildTree = function(array)
{
var tree = new BinaryTree(new Node(null));
for(var i = 0; i < array.length; i++)
{
var newNode = new Node(array[i]);
if(array[i] == "(")
{
newNode.element = null;
tree.activeNode.setLeft(newNode);
tree.activeNode = newNode;
}
else if(array[i] == "+" || array[i] == "-" || array[i] == "/" || array[i] == "*")
{
tree.activeNode.element = newNode.element;
tree.activeNode.setRight(new Node(null));
tree.activeNode = tree.activeNode.rightChild;
}
else if(array[i] == ")")
{
if(tree.activeNode.parent == null)
{
;
}
else
{
tree.activeNode = tree.activeNode.parent;
tree.root = tree.activeNode;
}
}
else
{
tree.activeNode.element = newNode.element;
tree.activeNode = tree.activeNode.parent;
}
}
return tree.activeNode;
}
var evaluate = function(node){
var newNode1, newNode2;
newNode1 = new Node(null);
newNode1.parent = node;
newNode2 = new Node(null);
newNode2.parent = node;
if(node.leftChild == null && node.rightChild == null)
return node.element;
else{
newNode1.element = evaluate(node.leftChild);
newNode2.element = evaluate(node.rightChild);
if(newNode1.parent.element == "+")
{
return Number(newNode1.element) + Number(newNode2.element);
}
if(newNode1.parent.element == "-")
{
return newNode1.element - newNode2.element;
}
if(newNode1.parent.element == "*")
{
return newNode1.element * newNode2.element;
}
else
{
return newNode1.element / newNode2.element;
}
}
};
I just tried this out using your code and it worked fine passing the value as a string:
function pushButton (value) {
var activeButton = value;
console.log(activeButton);
if(!isNaN(activeButton))
{
calcArray.push(parseInt(activeButton));
console.log(calcArray);
}
else if(activeButton === "=")
{
evaluate(buildTree(calcArray));
calcArray = [];
}
else
{
calcArray.push(activeButton);
}
};
You aren't ever printing out the array in the last case (which is where the right paren would go), so are you sure it's not on the array and you just aren't seeing the visual feedback?
If so, we need to see more of your code. Try and setup a jsfiddle.