Issues dynamically creating buttons with jQuery

Tags: , , ,



I’m attempting to dynamically add operator buttons to my calculator however I’m just not having any luck. I’ve created functions to dynamically create the number and operator buttons. The numbers have been created successfully but once I try to add in the operators, nothing happens. I’m attempting to add the operators in between my parentheses buttons and the evaluate button using a for-in loop. It seems when I create the evaluate button before the operators, the evaluate button is created successfully yet the operators aren’t. If I shift the code to create the operators before the evaluate button, neither are appearing. I’m fairly certain the issue lies within my for-in loop but I’m not quite sure where. Any and all help/guidance is greatly appreciated!

 var opsData = {
  add: {
    precedence: 1,
    name: 'add',
    operation: function (a, b) {return a + b;},
    output: function (a, b) {return a + ' + ' + b;},
    buttonHTML: '+'
  },
  subtract: {
    precedence: 1,
    name: 'subtract',
    operation: function (a, b) {return a - b;},
    output: function (a, b) {return a + ' - ' + b;},
    buttonHTML: '-'
  },
  multiply: {
    precedence: 2,
    name: 'multiply',
    operation: function (a, b) {return a * b;},
    output: function (a, b) {return a + ' * ' + b;},
    buttonHTML: '*'
  },
  divide: {
    precedence: 2,
    name: 'divide',
    operation: function (a, b) {return a / b;},
    isInvalidInput: function (a, b) {return b == 0 ? 'division by 0' : false;},
    output: function (a, b) {return a + ' / ' + b;},
    buttonHTML: '/'
  }
}

$.fn.addButton = function(html, className, onclick) {
  $('<button />', {
    html: html,
    'class': 'button ' + className,
    click: onclick
    }).appendTo(this);
  return this;
}

var addOperatorButton = function(op, click) {
  $operators.addButton(op.buttonHTML, 'operator ' + op.name, function(e) {
    click.call(this, e);
    $currentCalc.text(inputStack.getCalculationString());
    $collapsedCalc.text(inputStack.getCalculationString(true));
    $input.text(inputStackgetPartialResult());
    $input.data({clearOnInput: true});
  });
};

var getInput = () => {
  var input = $input.text();
  return input.match(/error/i) ? 0 : parseFloat($input.text())
}

for (var i in opsData) {
  (function(i) {
    if (!opsData.buttonHTML[i]) return;
    addOperatorButton(opsData[i], () => {
      inputStack.push(getInput(), new Operation(opsData[i]));
    })
  }(i))
}

The link to my full codepen is here: https://codepen.io/tazmancooks/pen/PoNwGMX

Apologies if my issue isn’t articulated well, I’m still fairly new to jQuery and Javascript in general.

Answer

The issue is when you are trying to loop through the opsData object.

for (var i in opsData) {
  (function(i) {
    if (!opsData.buttonHTML[i]) return;
      addOperatorButton(opsData[i], () => {
      inputStack.push(getInput(), new Operation(opsData[i]));
    })
  }(i))
}

You are accessing the [i] property of buttonHTML when you should be accessing opsData[i].buttonHTML



Source: stackoverflow