Such a task may arise when independent data binding is required for elements on the page. This example demonstrates how this can be implemented using mvc:
class MenuModel { constructor() { this._obs = []; this._selected = -1; this.selected = 0; } select(num) { this.selected = num; } set selected(value) { if(value != this._selected) { this._selected = value; this.dispatchEvent(new Event("selectChange")); } } get selected() { return this._selected; } addEventListener(type, node) { this._obs.push({type, node}); } removeEventListener(type, node) { this._obs = this._obs.filter(obs=>obs.type == type && obs.node == node); } dispatchEvent(event) { let obs = this._obs.filter(obs => obs.type == event.type); obs.forEach(obs=>{ let node = obs.node; if(typeof node == "function") { node.call(this, event); } else if(node.handleEvent) { node.handleEvent(event); } }); } } class ButtonView { constructor(target, index) { this.target = target; target.addEventListener("click", this); this.index = index; } bind(model) { if(this.model != model) { if(this.model) this.model.removeEventListener("selectChange", this); this.model = model; if(model) { model.addEventListener("selectChange", this); this.refresh(); } } } refresh() { this.target.classList.toggle("active", this.model.selected == this.index); } handleEvent(event) { if(event.type == "selectChange") this.refresh(); else if(event.type == "click") { if(this.model) this.model.select(this.index); } } } ButtonView.create = (target, index) => new ButtonView(target, index); window.addEventListener("load", ()=>{ let menu1 = document.body.querySelectorAll("menu")[0]; let menu2 = document.body.querySelectorAll("menu")[1]; let list1view = [].slice.call(menu1.querySelectorAll("button")).map(ButtonView.create); let list2view = [].slice.call(menu2.querySelectorAll("button")).map(ButtonView.create); var menu = new MenuModel(); list1view.forEach(elm=>elm.bind(menu)); list2view.forEach(elm=>elm.bind(menu)); });
Initially, a rather bulky bike is obtained, but if programmed in the same style, then the redundancy in the code will be less due to generalization. One of the advantages of this approach is that you can now influence the elements of the list without referring to the dom element directly, but simply by changing the model, for example, if you now do this:
menu.select(2);
then the changes will be automatically applied to the view.
Understanding the principle of operation of this code helps to easily switch to any modern mvc framework.