-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
178 lines (153 loc) · 4.9 KB
/
Copy pathindex.js
File metadata and controls
178 lines (153 loc) · 4.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
const type = (target, type) => {
if(typeof type == 'string') {
if(typeof target != type) throw `invalid type ${target} : ${type}`;
} else if(!(target instanceof type)) throw `invalid type ${target} : ${type}`;
return target;
};
/*
searchData = {
keyword : '', //검색옵션
isManager : '', //구분 필터값
isSubManager : '',
currentPage: 1,
pageSize: 10,
memberStatusValueCode: ''
};
*/
const ViewModel = class {
static get(data) {
return new ViewModel(data);
}
styles ={}; attributes ={}; properties ={}; events ={};
constructor(data) {
// if(checker != ViewModel.private) throw 'use ViewModel.get()'; //외부에서 생성 불가능
Object.entries(data).forEach(([k, v]) => {
switch(k) {
case 'styles': this.styles = v; break;
case 'attributes': this.attributes = v; break;
case 'properties': this.properties = v; break;
case 'events': this.events = v; break;
default: this[k] = v;
}
});
Object.seal(this);
}
};
const BinderItem = class {
el; viewmodel;
constructor(el, viewmodel, _0=typeof(el, HTMLElement), _1=type(viewmodel, 'string')) {
this.el = el;
this.viewmodel = viewmodel;
Object.freeze(this);
}
};
const Binder = class {
items = new Set; //객체지향 -> 메모리의 주소 객체의 메모리할당을 위해 Set으로 넣어야함
add(v, _ = type(v, BinderItem)) { this.items.add(v); }
render(viewmodel, _ = type(viewmodel, ViewModel)) {
this.items.forEach(item => {
//타입이 감수해야할 책임을 다른곳에 미루면안됨
const vm = type(viewmodel[item.viewmodel], ViewModel), el = item.el;
//제어역전된 그리는 코드
Object.entries(vm.styles).forEach(([k, v]) => el.styles[k] = v);
Object.entries(vm.attributes).forEach(([k, v]) => el.attributes(k, v));
Object.entries(vm.properties).forEach(([k, v]) => {
el[k] = v;
});
Object.entries(vm.events).forEach(([k, v]) => el['on' + k] = e =>v.call(el, e, viewmodel));
});
}
};
const Scanner = class {
scan(el, _ = type(el, HTMLElement)) {
const binder = new Binder;
this.checkItem(binder, el);
const stack = [el.firstElementChild];
let target;
while(target = stack.pop()) {
this.checkItem(binder, target);
if(target.firstElementChild) stack.push(target.firstElementChild);
if(target.nextElementSibling) stack.push(target.nextElementSibling);
}
return binder;
}
checkItem(binder, el) {
const vm = el.getAttribute('data-viewmodel');
if(vm) {
binder.add(new BinderItem(el, vm));
}
}
};
const Data = class {
getData() {
const json = this._getData();
return json;
}
_getData() {
throw 'getData must override';
}
};
const JsonData = class extends Data {
constructor(data) {
super();
this._data = data;
}
_getData() {
if(typeof this._data == 'string') {
let data;
$.ajax({
method: 'get',
dataType: 'json',
contentType: 'application/json',
url: this._data,
async: false
}).done((d) => {
this._data = data = d;
});
return data;
} else return this._data;
}
};
const Renderer = class {
constructor() { }
renderTable(data) {
if(!(data instanceof Data))throw 'invalid data type';
this._info = data._getData();
return this._renderTable();
}
_renderTable() { throw '_render must override'; }
};
const TableRenderer = class extends Renderer {
constructor() {
super();
}
_renderTable() {
return this._info.map((list, idx) => `<tr><td ${idx===0 ? 'id="clickevt" data-viewmodel="clickevt"' :''}>${list.id}</td><td>${list.first_name}</td><td>${list.last_name}</td><td>${list.email}</td></tr>`).join('');
}
};
const data = new JsonData('./test.json');
const renderer = new TableRenderer();
const tableVM = ViewModel.get({
tbody : ViewModel.get({
properties: {
innerHTML : renderer.renderTable(data)
}
})
});
//global
const scanner = new Scanner;
//local
const TableScanner = scanner.scan(document.querySelector('#test'));
TableScanner.render(tableVM); //redner 의 시점을 조절할수있는게 필요함
//local
const afterDrawScanner = scanner.scan(document.querySelector('#clickevt'));
const afterDrawVM = ViewModel.get({
clickevt: ViewModel.get({
events: {
click(el, vm) {
alert('test');
}
}
})
});
afterDrawScanner.render(afterDrawVM);