JS 實作 #8 | 計算預算數值並顯示

JS 實作 #7 | 輸入欄位轉換型態與驗証;parseFloat()、isNaN() 後可以開始實際加總預算總值。

開始實作

1. 在 BUDGET CONTROLLER 裡面,新增一個公開的 calculateBudget() 方法,處理以下三件事。

// BUDGET CONTROLLER
var budgetController = (function(){

    var Expense = function(id, description, value) {
        ...
    }

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

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

    return {
        addItem: function(type, des, val){
            ...
        },
        **calculateBudget: function() {
            
            // calculate total income and expense

            // calculate the budget: income - expense

            // calculate the percentage of income that we spent

        },**
        testing: function(){
            ...
        }
    }

})();

2. 建立一個 BUDGET CONTROLLER 裡面的私有方法 calculateTotal() ,來計算 income 和 expense 的加總。

// BUDGET CONTROLLER
var budgetController = (function(){

    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
        }
    };

    return {
        addItem: function(type, des, val){
           ...
        },
        calculateBudget: function() {

					  ****// calculate total income and expense
							 **calculateTotal('exp');
							 calculateTotal('inc');**

            // calculate the budget: income - expense

            // calculate the percentage of income that we spent
          
        },
        testing: function(){
            console.log(data);
        }
    }

})();

3. 在 data object 裡新增總預算和百分比,並且注意到除以0的情況。

// BUDGET CONTROLLER
var budgetController = (function(){

    var Expense = function(id, description, value) {
        ...
    }

    var Income = function(id, description, 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){
            ...
        },
        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 that we spent
            **if (data.totals.inc > 0) {
                data.percentage = Math.round((data.totals.exp  / data.totals.inc) * 100);
            } else {
                data.percentage = -1;
            }**
        },

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

})();

4. 回到 GLOBAL APP CONTROLLER 呼叫此公開函式 calculateBudget() 執行。

// GLOBAL APP CONTROLLER
var controller = (function(budgetCtrl, UICtrl){

    var setupEventListeners = function() {
        ...
    };
    var updateBudget = function() {

        // 5-1. Calcuate the budget
        **budgetCtrl.calculateBudget();**

        // 5-2. Return the budget

        // 5-3  Display the budget on the UI
    };

    var ctrlAddItem = function() {
       ...
    }
    
    return {
        init: function() {
            console.log('Application has started.');
            setupEventListeners();
        }
    }
})(budgetController, UIController);

controller.init();

5. 在 BUDGET CONTROLLER 裡,新增 getBudget() 方法將執行結果傳回(有四個參數因此直接回傳一個物件 **return {}** )。

// BUDGET CONTROLLER
var budgetController = (function(){

    var Expense = function(id, description, value) {
        ...

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

    var calculateTotal = function(type) {
        ...
    }

    var data = {
        allItems: {
            exp: [],
            inc: []
        },
        totals: {
            exp: 0,
            inc: 0
        },
        budget: 0,
        percentage: -1
    };

    return {
        addItem: function(type, des, val){
            ...
        },
        calculateBudget: function() {
            
            ...
        },
        **getBudget: function() {
            return {
                totalInc: data.totals.inc,
                totalExp: data.totals.exp,
                budget: data.budget,
                percentage: data.percentage
            }
        },**

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

})();
// GLOBAL APP CONTROLLER
var controller = (function(budgetCtrl, UICtrl){

    var setupEventListeners = function() {
        ...
    };
    var updateBudget = function() {

        // 5-1. Calcuate the budget
        budgetCtrl.calculateBudget();

        // 5-2. Return the budget
        **var budget = budgetCtrl.getBudget();**
        
        // 5-3  Display the budget on the UI
        console.log(budget);
    };

    var ctrlAddItem = function() {
        ...
    }
    
    return {
        init: function() {
            console.log('Application has started.');
            setupEventListeners();
        }
    }
})(budgetController, UIController);

controller.init();

6. 獲得數值後,就可以在 UI CONTROLLER 裡新增公開方式 displayBudget() 來顯示了。

// UI CONTROLLER
var UIController = (function() {

    var DOMstrings = {
        inputType: '.add__type',
        inputDescription: '.add__description',
        inputValue: '.add__value',
        inputBtn: '.add__btn',
        incomeContainer: '.income__list',
        expenseContainer: '.expenses__list',
        **budgetLabel: '.budget__value',
        incomeLabel: '.budget__income--value',
        expensesLabel: '.budget__expenses--value',
        percentageLabel: '.budget__expenses--percentage'**
    };

    return {
        getInput: function() {
            ...
        },
        getDOMstrings: function() {
            return DOMstrings;
        },
        addListItem: function(obj, type) {

            ...
        },
        clearFields: function () {
           ...
        },
        **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 = '---';
            }
        }**
    };

})();
// GLOBAL APP CONTROLLER
var controller = (function(budgetCtrl, UICtrl){

    var setupEventListeners = function() {
        ...
    };
    var updateBudget = function() {

        // 5-1. Calcuate the budget
        budgetCtrl.calculateBudget();

        // 5-2. Return the budget
        var budget = budgetCtrl.getBudget();

        **// 5-3  Display the budget on the UI
        UICtrl.displayBudget(budget);**
    };

    var ctrlAddItem = function() {
        ...
    }
    
    return {
        init: function() {
            console.log('Application has started.');
            setupEventListeners();
        }
    }
})(budgetController, UIController);

controller.init();

7. 最後,在網頁一打開時,初始化所有資料為0。

// GLOBAL APP CONTROLLER
var controller = (function(budgetCtrl, UICtrl){

    var setupEventListeners = function() {
        ...
    };
    var updateBudget = function() {

        // 5-1. Calcuate the budget
        budgetCtrl.calculateBudget();

        // 5-2. Return the budget
        var budget = budgetCtrl.getBudget();

        // 5-3  Display the budget on the UI
        UICtrl.displayBudget(budget);
    };

    var ctrlAddItem = function() {
        ...
    }
    
    return {
        init: function() {
            console.log('Application has started.');
            **UICtrl.displayBudget({
                budget: 0,
                totalInc: 0,
                totalExp: 0,
                percentage: -1
            });**
            setupEventListeners();
        }
    }
})(budgetController, UIController);

controller.init();

至此已完成的程式架構圖如下:

Zeen is a next generation WordPress theme. It’s powerful, beautifully designed and comes with everything you need to engage your visitors and increase conversions.