Last active
December 12, 2018 01:01
-
-
Save kujyp/33449f4581f0b960d0368198362eb76f to your computer and use it in GitHub Desktop.
codespitz_week05.html
This file contains hidden or 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
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Title</title> | |
</head> | |
<style> | |
.urgent{color:red} | |
.high{color:orange} | |
.normal{color:skyblue} | |
.low{color:grey} | |
</style> | |
<body> | |
<section id="base"></section> | |
<br/> | |
<br/> | |
<br/> | |
<section id="b"></section> | |
</body> | |
<script src="utils.js"></script> | |
<script src="definitions.js"></script> | |
<script src="week05.js"></script> | |
</html> |
This file contains hidden or 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
const Task = class { | |
constructor (title, date) { | |
if (!title) { | |
error("invalid title"); | |
} | |
this._title = title; | |
this._date = date; | |
this._isComplete = false; | |
this._list = []; | |
} | |
get task() { | |
return this; | |
} | |
get list() { | |
return 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.sortedList('title', stateGroup); | |
} | |
byDate(stateGroup = true) { | |
return this.sortedList('date', stateGroup); | |
} | |
sortedList(sort, stateGroup = true) { | |
if (!(sort === 'title' || sort === 'date')) { | |
error('invalid param'); | |
return; | |
} | |
const list = this._list; | |
const sortFunc = (a, b) => a['_' + sort] > b['_' + sort]; | |
const mapFunc = task => task.sortedList(sort, stateGroup); | |
return { | |
task: this, | |
list: (!stateGroup ? [...list].sort(sortFunc) : [ | |
...list.filter(v => !v.isComplete()).sort(sortFunc), | |
...list.filter(v => v.isComplete()).sort(sortFunc), | |
]).map(mapFunc) | |
}; | |
} | |
}; | |
const SortedTask = class { | |
constructor(task, sort) { | |
this._task = task; | |
this._sort = sort; | |
try { | |
const _ = this._task.sortedList(this._sort); | |
} catch (e) { | |
error(e); | |
} | |
} | |
get list() { | |
return this._task.sortedList(this._sort)['list']; | |
} | |
get task() { | |
return this._task; | |
} | |
}; | |
const Renderer = class { | |
constructor(processor) { | |
this.p = processor; | |
processor.setObserver(this); | |
} | |
observe(type) { | |
if (type == 'rerender') { | |
this.rerender(); | |
} | |
} | |
rerender() { | |
if (this.oldList) { | |
this.render(this.oldList); | |
} | |
} | |
render(list) { | |
this.oldList = list; | |
const { | |
task, | |
list: sublist, | |
} = list; | |
this.p.folder(task); | |
this.p.parent(task); | |
this.subTask(sublist); | |
} | |
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; | |
this._fv = FolderView.base; | |
} | |
observe(msg) { | |
this.notify(msg); | |
} | |
setObserver(v) { | |
this.observer = v; | |
} | |
notify(msg) { | |
this.observer && this.observer.observe(msg); | |
} | |
taskView(...tv) { | |
tv.forEach(eachTv => { | |
eachTv.set(this._tv); | |
this._tv = eachTv; | |
}); | |
} | |
folderView(...fv) { | |
fv.forEach(eachFv => { | |
eachFv.set(this._fv); | |
this._fv = eachFv; | |
}); | |
} | |
folder(task) { | |
error('override'); | |
} | |
task(task) { | |
error('override'); | |
} | |
parent(task) { | |
error('override'); | |
} | |
folderRender(task) { | |
this._fv.setObserver(this); | |
return this._fv.folder(task); | |
} | |
taskRender(task) { | |
this._tv.setObserver(this); | |
return this._tv.task(this.prop.ptask, task); | |
} | |
}; | |
const Dom = class extends Renderer.Processor { | |
constructor(parent) { | |
super(); | |
this._p = parent; | |
this._tv = TaskView.base; | |
} | |
folder(task) { | |
const parent = document.querySelector(this._p); | |
parent.innerHTML = ""; | |
parent.appendChild(el('h1', {innerHTML: this.folderRender(task)})); | |
this.prop.parent = parent; | |
} | |
task(task) { | |
const li = el('li', { | |
innerHTML: this.taskRender(task) | |
}); | |
this.prop.parent.appendChild(li); | |
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 { | |
setObserver(v) { | |
this.observer = v; | |
} | |
notify(msg) { | |
if (this.observer) { | |
this.observer.observe(msg); | |
} | |
} | |
set(tv) { | |
this._tv = tv; | |
} | |
task(parent, task) { | |
this.result = this._tv ? this._tv.task(parent, task) : task._title; | |
return this._task(parent, task); | |
} | |
_task(parent, task) { | |
error("override"); | |
} | |
}; | |
TaskView.base = new (class extends TaskView { | |
_task(parent, task) { | |
return this.result; | |
} | |
}); | |
const FolderView = class { | |
setObserver(v) { | |
this.observer = v; | |
} | |
notify(msg) { | |
if (this.observer) { | |
this.observer.observe(msg); | |
} | |
} | |
set(fv) { | |
this._fv = fv; | |
} | |
folder(task) { | |
this.result = this._fv ? this._fv.folder(task) : task._title; | |
return this._folder(task); | |
} | |
_folder(task) { | |
error("override"); | |
} | |
}; | |
FolderView.base = new (class extends FolderView { | |
_folder(task) { | |
return this.result; | |
} | |
}); | |
const Complete = class extends FolderView { | |
_folder(task) { | |
return `<span style="text-decoration: ${task._isComplete ? "line-through" : ""}">${this.result}</span>`; | |
} | |
}; | |
const Priority = class extends TaskView { | |
_task(parent, task) { | |
return this.result.replace( | |
/\[(urgent|high|normal|low)\]/gi, '<span class="$1">■</span>' | |
); | |
} | |
}; | |
const Member = class extends TaskView { | |
constructor(...members) { | |
super(); | |
this._reg = new RegExp(`@(${members.join('|')})`, 'g'); | |
} | |
_task(task, parent, prev) { | |
return this.result.replace( | |
this._reg, '<a href="member/$1">$1</a>' | |
); | |
} | |
}; | |
const Remove = class extends TaskView { | |
_task(parent, task) { | |
const id = Remove.id++; | |
Remove[id] = (_) => { | |
delete Remove[id]; | |
parent.remove(task); | |
this.notify('rerender'); | |
}; | |
return this.result + ` <a onclick="Remove[${id}]()">X</a>`; | |
} | |
}; | |
Remove.id = 0; |
This file contains hidden or 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
const error = (msg) => { | |
alert(msg); | |
throw msg; | |
}; | |
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)); |
This file contains hidden or 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
const folder = new Task('s3-4'); | |
folder.add("[urgent] 2강 답안 작성"); | |
folder.add("[high] 3강 답안 작성 @hika, @summer"); | |
const { list } = folder.sortedList('title'); | |
list[1].task.add('[normal] ppt정리'); | |
list[1].task.add('[low] 코드정리'); | |
const { list: sublist } = list[1].task.sortedList('title'); | |
sublist[1].task.add('슬라이드마스터 정리 @summer'); | |
sublist[1].task.add('디자인개선 @summer, @hika'); | |
const dom = new Dom('#base'); | |
dom.taskView(new Priority(), new Member('hika', 'summer'), new Remove()); | |
dom.folderView(new Complete()); | |
const renderer = new Renderer(dom); | |
// renderer.render(new SortedTask(folder, 'title')); | |
folder.toggle(); | |
renderer.render(folder); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment