JS 實作 #5 | 將新增資料顯示在 UI 上;insertAdjacentHTML()

在上一節中 JS 實作 #4 | 建立 init() 開始程式、存放資料 ,已經完成了資料的存放。接著就是將它顯示到 UI 裡(DOM)。

以下是原本的 code

// 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 data = {
        allItems: {
            exp: [],
            inc: []
        },
        totals: {
            exp: 0,
            inc: 0
        }
    };

    return {
        addItem: function(type, des, val){
            var newItem, ID;

            //[1, 2, 3, 4, 5],next ID = 6
            //[1, 2, 4, 6, 8],next ID = 9
            if (data.allItems[type].length > 0) {
                ID = data.allItems[type][data.allItems[type].length - 1].id + 1;
            } else {
                ID = 0;
            }

            if (type === 'inc') {
                newItem = new Income(ID, des, val);
            } else if (type === 'exp') {
                newItem = new Expense(ID, des, val);
            }

            data.allItems[type].push(newItem);

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

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

    var DOMstrings = {
        inputType: '.add__type',
        inputDescription: '.add__description',
        inputValue: '.add__value',
        inputBtn: '.add__btn'
    };

    return {
        getInput: function() {
            return {
                type: document.querySelector(DOMstrings.inputType).value, // inc or exp
                description : document.querySelector(DOMstrings.inputDescription).value,
                value : document.querySelector(DOMstrings.inputValue).value
            }
        },

        getDOMstrings: function() {
            return DOMstrings;
        }
    };

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

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

    var ctrlAddItem = function() {

        var input,newItem;

        // 1. Get the field input data
        input = UICtrl.getInput();
        // 2. add the item to the budget controller
        newItem = budgetController.addItem(input.type, input.description, input.value);
        // 3. add the item to the UI
        // 4. Calculate the budget
        // 5. Display the budget on the UI
    }
    
    return {
        init: function() {
            console.log('Application has started.');
            setupEventListeners();
        }
    }
})(budgetController, UIController);

controller.init();

開始實作

1. 在 UI Controller 裡新增一個公開方法 addListItem並且在 Global App Controller 裡呼叫它

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

    var DOMstrings = {
        inputType: '.add__type',
        inputDescription: '.add__description',
        inputValue: '.add__value',
        inputBtn: '.add__btn'
    };

    return {
        getInput: function() {
						...
        },
        getDOMstrings: function() {
            return DOMstrings;
        },
        **addListItem: function(obj, type) {
            // create HTML string with placeholder text

            // replace placholder text with soma actual data

            // insert the HTML into the DOM
        }**
    };

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

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

    var ctrlAddItem = function() {

        var input,newItem;

        // 1. Get the field input data
        input = UICtrl.getInput();
        // 2. add the item to the budget controller
        newItem = budgetController.addItem(input.type, input.description, input.value);
        // 3. add the item to the UI
        **UICtrl.addListItem(newItem, input.type);**
        // 4. Calculate the budget
        // 5. Display the budget on the UI
    }
    
    return {
        init: function() {
            console.log('Application has started.');
            setupEventListeners();
        }
    }
})(budgetController, UIController);

controller.init();

2. 將 income 和 expense 二種樣式的 HTML 寫入,並且使用 %變數% 之後可以 replace() 取代

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

    var DOMstrings = {
        inputType: '.add__type',
        inputDescription: '.add__description',
        inputValue: '.add__value',
        inputBtn: '.add__btn'
    };

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

            var html, newHtml,

            **// create HTML string with placeholder text
            if (type === 'inc') {
                html = '<div class="item clearfix" id="inc-%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') {
                html = '<div class="item clearfix" id="exp-%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 placholder text with soma actual data
            newHtml = html.replace('%id', obj.id);
            newHtml = newHtml.replace('%description%', obj.description);
            newHtml = newHtml.replace('%value%', obj.value);**

            // insert the HTML into the DOM
        }
    };

})();

3. 找到要插入 HTML 的 DOM 元件,使用 insertAdjacentHTML()

InsertAdjacentHTML()

element.insertAdjacentHTML(position, text);
  • 'beforebegin': 在 element 之前。
  • 'afterbegin': 在 element 裡面,第一個子元素之前。
  • 'beforeend': 在 element 裡面,最後一個子元素之後。
  • 'afterend': 在 element 之後。
<!-- beforebegin -->
<p>
  <!-- afterbegin -->
  foo
  <!-- beforeend -->
</p>
<!-- afterend -->

於此案例中是使用 'beforeend'

// 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'**
    };

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

            var html, newHtml, **element**;

            // create HTML string with placeholder text
            if (type === 'inc') {
                **element = DOMstrings.incomeContainer;**
                html = '<div class="item clearfix" id="inc-%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.expenseContainer;**
                html = '<div class="item clearfix" id="exp-%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 placholder text with soma actual data
            newHtml = html.replace('%id', obj.id);
            newHtml = newHtml.replace('%description%', obj.description);
            newHtml = newHtml.replace('%value%', obj.value);

            // insert the HTML into the DOM
            **document.querySelector(element).insertAdjacentHTML('beforeend',newHtml);**
        }
    };

})();

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.