Last active
December 11, 2018 17:05
-
-
Save chj1768/d9f4bc26b20e82ef009dbf45ca202144 to your computer and use it in GitHub Desktop.
#5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<body> | |
<p id="base"></p> | |
</body> | |
<script> | |
const Task = class{ | |
constructor(title, date){ | |
this._title = title, | |
this._date = date, | |
this._isComplete = false; | |
this._list = []; | |
} | |
isComplete(){return this._isComplete;} | |
toggle(){ | |
this._isComplete = !this._isComplete; | |
} | |
add(title, date = null){ | |
this._list.push(new Task(title, date)); | |
} | |
remove(task){ | |
const list = this._list; | |
if(list.includes(task)) | |
list.splice(list.indexOf(task), 1); | |
} | |
byTitle(stateGroup = true){return this.list('title', stateGroup);} | |
byDate(stateGroup = true){return this.list('date', stateGroup);} | |
list(sort, stateGroup = true){ | |
const list = this._list, | |
f = (a, b)=>a[sort] > b[sort]; | |
const map = task=>task.list(sort, stateGroup); | |
return { | |
task:this, | |
list:!stateGroup ? [...list].sort(f).map(map) : [...list.filter(v=>!v.isComplete()).sort(f).map(map), | |
...list.filter(v=>v.isComplete()).sort(f).map(map)] | |
}; | |
} | |
}; | |
const el = (tag, attr={})=>Object.entries(attr).reduce((el, v)=>{ | |
typeof el[v[0]] == 'function' ? el[v[0]](v[1]) : (el[v[0]] = v[1]);return el;}, | |
document.createElement(tag)); | |
const Renderer = class{ | |
constructor(processor){ | |
this.p = processor; | |
processor.addObserver(this); | |
} | |
observe(type){ | |
type=='rerender'&&this.rerender(); | |
} | |
rerender(){ | |
this.oldList && this.render(this.oldList); | |
} | |
render({task, list}){ | |
this.oldList = {task, list}; | |
this.p.folder(task); | |
this.p.parent(task); | |
this.subTask(list); | |
} | |
subTask(list){ | |
list.forEach(({task, list})=>{ | |
this.p.task(task); | |
if(list.length){ | |
this.p.parent(task); | |
this.subTask(list); | |
} | |
}); | |
} | |
}; | |
Renderer.Processor = class{ | |
constructor(){ | |
this.prop = Object.create(null); | |
this._tv=TaskView.base; | |
} | |
observe(msg){ | |
this.notify(msg); | |
} | |
addObserver(v){ | |
this.observer = v; | |
} | |
notify(msg){ | |
this.observer && this.observer.observe(msg); | |
} | |
taskView(...tv){ | |
tv.forEach(tv=>this._tv = tv.set(this._tv)); | |
} | |
folder(task){ | |
throw 'override'; | |
} | |
task(task){ | |
throw 'override'; | |
} | |
parent(task){ | |
throw 'override'; | |
} | |
remove(task){ | |
throw 'override'; | |
} | |
taskRender(task){ | |
this._tv.addObserver(this); | |
return this._tv.task(this.prop.ptask, task); | |
} | |
}; | |
const Dom = class extends Renderer.Processor{ | |
constructor(parent){ | |
super(); | |
this._p = parent; | |
} | |
folder(task){ | |
const parent = document.querySelector(this._p); | |
parent.innerHTML = ''; | |
this.prop.parent = parent; | |
this.parent(task); | |
this.task(task); | |
} | |
task(task){ | |
const li = this.taskRender(task); | |
this.prop.parent.appendChild(li); | |
if(task._list.length) | |
this.prop.parent = li; | |
} | |
parent(task){ | |
const ul = el('ul'); | |
this.prop.parent.appendChild(ul); | |
this.prop.parent = ul; | |
this.prop.ptask = task; | |
} | |
}; | |
const TaskView = class{ | |
addObserver(v){ | |
this.observer = v; | |
} | |
notify(msg){ | |
this.observer && this.observer.observe(msg); | |
} | |
set(tv){ | |
this._tv = tv; | |
return this; | |
} | |
task(parent, task){ | |
this.result = this._tv ? this._tv.task(parent, task) : el('li', {innerHTML : task._title}); | |
return this._task(parent, task); | |
} | |
_task(parent, task){ | |
throw "override!" | |
} | |
}; | |
TaskView.base = new (class extends TaskView{ | |
constructor() { | |
super(); | |
} | |
_task(parent, task){ | |
return this.result; | |
} | |
}); | |
const Priority = class extends TaskView{ | |
constructor() { | |
super(); | |
this._reg = new RegExp(/\[(urgent|high|normal|low)\]/,'gi'); | |
} | |
_task(parent, task){ | |
const word = this.result.innerText.match(this._reg); | |
if(word) { | |
this.result.innerHTML = `<strong>${word[0]}</strong>${this.result.innerHTML.replace(this._reg, "")}`; | |
} | |
return this.result; | |
} | |
}; | |
const Member = class extends TaskView{ | |
constructor(...members){ | |
super(); | |
this._reg = new RegExp(`@(${members.join('|')})`, 'g'); | |
} | |
_task(parent, task){ | |
const word = this.result.innerText.match(this._reg); | |
if(word) { | |
this.result.innerHTML = `${this.result.innerHTML.replace(this._reg, "")}<a href=${word[0].replace("@", "")}>${word[0].replace("@", "")}</a>`; | |
} | |
return this.result; | |
} | |
}; | |
const Remove = class extends TaskView{ | |
constructor() { | |
super(); | |
} | |
_task(parent, task){ | |
const remove = e => { | |
parent.remove(task); | |
e.currentTarget.parentElement.remove(); | |
}; | |
const a = el('button', {innerHTML : 'X'}); | |
a.onclick = remove; | |
this.result.appendChild(a); | |
return this.result; | |
} | |
}; | |
const folder = new Task('[high]s3-4@aaa'); | |
folder.add("2강교안작성"); | |
folder.add("3강교안작성"); | |
const {list} = folder.list('title'); | |
list[1].task.add('ppt정리 @bbb'); | |
list[1].task.add('코드정리 @aaa'); | |
const {list:sublist} = list[1].task.list('title'); | |
sublist[1].task.add('[high]슬라이드마스터정리'); | |
sublist[1].task.add('디자인개선'); | |
const dom = new Dom('#base'); | |
dom.taskView(new Member('aaa', 'bbb'), new Priority(), new Remove()); | |
const renderer = new Renderer(dom); | |
renderer.render(folder.list('title')); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
practice #1, #2 [심화] 포함.