Canot read property of Map undefined

Canot read property of Map undefined
0.0 0

#1
//Budget controller

var budgetController = (function(){
  // Made expense and income functions to calculate Data
  var Expense = function(id,description,value){
      this.id = id;
      this.description = description;
      this.value = value;
};

 var Income = function(id,description,value){
    this.id = id;
    this.description = description;
    this.value = value;

};

var calculateTotal = function(type){
var sum = 0;
  data.allItems[type].forEach(function(cur){
  sum +=  cur.value;

});
data.totals[type] = sum;

};

var data = {
    allItems:{
      exp:[],
      inc:[]
},

     totals:{
      exp:0,
      inc:0
},
budget:0,
percentage: -1

};
return {
  addItem: function(type,des,val){
  var newItem, ID;
  // Create new ID 
if (data.allItems[type].length > 0 ){

  ID = data.allItems[type][data.allItems[type].length -1].id + 1;
}
else {

  ID = 0;

}

  // Create new Item based on "inc" or "exp" type
  if (type === 'exp') {
    newItem = new Expense(ID,des,val);
  }
  else if(type === "inc"){
    newItem = new Income(ID,des,val);
  }
  // Push it into Data structure
  data.allItems[type].push(newItem);
  // Return element
  return newItem;
  },

deleteItem: function (type, id) {
var ids, index;

// data.allItems[type][id];
// id = 6
// index = 3
// ids = [1, 2, 4 , 6, 9];
// index = [0, 1, 2, 3, 4];

ids = data.allItems[type].map(function (current) {
return current.id;
});

index = ids.indexOf(id);

if (index !== -1) {
data.allItems[type].splice(index, 1);
}
},








calculateBudget: function(){
//calculate total income and expense
calculateTotal('exp');
calculateTotal('inc');
//calculate the Budget income - expense
data.budget = data.totals.inc - data.totals.exp;

//calculate the percentage of income
if (data.totals.inc > 0) {
  data.percentage = Math.round((data.totals.exp/data.totals.inc) * 100);
}
else { 
  data.percentage = -1;
}

},
getBudget: function(){

return {

budget:data.budget,
totalInc:data.totals.inc,
totalExp:data.totals.exp,
percentage:data.percentage

};

},

testing: function(){
  console.log(data);
}

};

})();

// UI controller
var UIController = (function(){
    var DOMstrings = {
      inputType:'.add__type',
      inputDescription: '.add__description',
      inputValue:'.add__value',
      inputBtn: '.add__btn',
      incomeContainer:'.income__list',
      expensesContainer:'.expenses__list',
      budgetLabel:'.budget__value',
      incomeLabel:'.budget__income--value',
      expensesLabel:'.budget__expenses--value',
      percentageLabel:'.budget__expenses--percentage',
      container:'.container'
}
     return {
       getInput: function(){
          return {
             // getting input data from elements
              type: document.querySelector(DOMstrings.inputType).value,
              description: document.querySelector(DOMstrings.inputDescription).value,
              value: parseFloat(document.querySelector(DOMstrings.inputValue).value)

         };
        
      },

     addListItem: function(obj, type) {
      var html, newHtml, element;
      //Create html stings with placeholder text
     if (type === 'inc'){

     element = DOMstrings.incomeContainer;
     html = html = html = '<div class="item clearfix" id="income-%id%"><div class="item__description">%description%</div><div class="right clearfix"><div class="item__value">%value%</div><div class="item__delete"><button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button></div></div></div>'
      }
      else if(type === 'exp') {
     element = DOMstrings.expensesContainer;
     html = '<div class="item clearfix" id="expense-%id%"><div class="item__description">%description%</div><div class="right clearfix"><div class="item__value">%value%</div><div class="item__percentage">21%</div><div class="item__delete"><button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button></div></div></div>';

     }
     //Replace the placeholder text with actual data
      newHtml = html.replace('%id%', obj.id);
      newHtml = newHtml.replace('%description%', obj.description);
      newHtml = newHtml.replace('%value%', obj.value);
    // insert html into DOM
    document.querySelector(element).insertAdjacentHTML('beforeend',newHtml);
     },

     clearFields: function(){
      var fields, fieldsArr;
      fields = document.querySelectorAll(DOMstrings.inputDescription + ' , ' + DOMstrings.inputValue);
      fieldsArr = Array.prototype.slice.call(fields);
      fieldsArr.forEach(function(current,index,array){
      current.value = "";

      });

     fieldsArr[0].focus();

     },
     displayBudget: function(obj){
       document.querySelector(DOMstrings.budgetLabel).textContent=obj.budget;
       document.querySelector(DOMstrings.incomeLabel).textContent=obj.totalInc;
       document.querySelector(DOMstrings.expensesLabel).textContent=obj.totalExp;
       if (obj.percentage > 0){
       document.querySelector(DOMstrings.percentageLabel).textContent=obj.percentage + "%" ;
     }
     else{
      document.querySelector(DOMstrings.percentageLabel).textContent="---";

     }
 },

    // exposing to public so that we can excess DOMstrings
      getDOMstrings: function(){
        return DOMstrings;
        }

      };
})();

// Global App controller.
var controller = (function(budgetCtrl,UICtrl){
// privioulsly all the event listeners were scattered But now i have a seprate function SetupEventListeners  for all events
var setupEventListeners = function(){
var DOM = UICtrl.getDOMstrings();
document.querySelector(DOM.inputBtn).addEventListener('click',ctrlAddItem);
document.addEventListener('keypress',function(event){
  if (event.keyCode === 13 || event.which === 13) {
            ctrlAddItem();
        }
    });
 document.querySelector(DOM.container).addEventListener('click',ctrlDeleteItem);

};

var updateBudget = function(){
//calculate budget
budgetCtrl.calculateBudget();
//return budget
var budget = budgetCtrl.getBudget();
//Display budget on UI
UICtrl.displayBudget(budget);

}

var ctrlAddItem = function(){
      var input, newItem;
      // Get the input data.
      input = UICtrl.getInput();
    
     if(input.description !== "" && !isNaN(input.value) && input.value > 0 ) {
        //add the item to the budget controller
      newItem   =  budgetCtrl.addItem(input.type,input.description,input.value);

      // add the item to the Ui
      UICtrl.addListItem(newItem, input.type);
      //Clear fields
      UICtrl.clearFields();
      // calculate and update budget
      updateBudget();

     }

     
    };

var ctrlDeleteItem = function (event) {
 var itemID, splitID, type, ID;
 
 // example: ID = 'inc-0'
 itemID = event.target.parentNode.parentNode.parentNode.parentNode.id;
 
 if (itemID) {
 
 //inc-1
 splitID = itemID.split('-');
 type = splitID[0];
 ID = parseInt(splitID[1]);
 
 // 1. Delete the item from the data structure
 budgetCtrl.deleteItem(type, ID);
 
 // 2. Delete the item from UI
 
 // 3. Update and show the new budget
 }
};
return {
  init:function(){
     console.log("Your App Has started");
     UICtrl.displayBudget({

budget:0,
totalInc:0,
totalExp:0,
percentage:-1

});
    setupEventListeners();
  }
};
})(budgetController,UIController);

controller.init();

#2

I’ve edited your post for readability. When you enter a code block into the forum, precede it with a line of three backticks and follow it with a line of three backticks to make easier to read. See this post to find the backtick on your keyboard. The “preformatted text” tool in the editor (</>) will also add backticks around text.

When you post a large chunk of code and only put a title of “Canot read property of Map undefined”, you are not going to get much of a response. You need to explain what you expected your code to do, so we can focus our efforts on helping you with that specific part.

BTW - When I run the code you posted as it shows now, I get the following error message:

TypeError: Cannot set property ‘textContent’ of null (line 192)