티스토리 뷰



var Task = function() {
    //자바스크립트에서는 0은 false 로 인식한다.  그래서 1로 하는게 좋다.
    // c -complte 상태, p - progress 상태
    var  c = {}, p ={}

    var Task = function(title){
        this.title = title;
        //아이디는 Task 만 알면 되므로 Scope 를 구성합니다.
        //의미상 이 Task 위 Task 가 된다.
        //개체는 바깥쪽과 상태로 대화하지 않는다.! 메서드로 대화한다.
        this._state = p
    };

    var fn = Task.prototype;

    fn.isComplete = function(){
        return this._state === c;
    };

    fn.toogle = function() {
        if ( this._state === c) {
            this._state = p;
        } else {
            this._state = c;
        }
    };

    fn.toString = function() {
        return this._title;
    }

    return Task;
}
//컨텍스트에 제너릭 한 Todo 로 변경 스코프에 의존하지 않는다.
//투두라는 진짜의미는 TaskManager 이다. Todo의 toggle의 역확은 task안에 있는 toggle를 중계해주는 역활만 하는거구나.
//개체는 식별로 비교한다. 값으로 비교하지 않는다. 예를 개체에 id값줘서 비교하는 경우 식별비고 tasks.indexOf(task);
var TodoManager = (function(){
    //객체 컨테스트로 지역스코프로 구성하기 , 암묵적인 컨텍스티인 this 를 사용한다.
    var TodoManager = function() {
        this._tasks = [];
        //taget 은 랜더러
        this._renderer = null;
    }

    var fn = TodoManager.prototype;

    fn._render = function(){
        this._renderer.render(this._tasks.slice(0));
    };

    fn.setRenderer = function(renderer) {
        if ( !(this._renderer instanceof Renderer) ) return ;
        this._renderer = renderer;
        renderer.init(this);
    };
    fn.add = function(title) {
        this._tasks.push(new Task(title));
        this._render();
    };
    fn.remove = function(task) {
           var ts = this._tasks;
        if (  this._checkTask(task) ) {
            ts.splice(ts.indexOf(task), 1);
        }
        this._render();
    };
    //메서드일까 아닐까? 일까 정답은 아닌다. 맞다 this를 사용한다.
    //메서드는 컨텍스트에 의존해야한다.
    fn._checkTask = function(task) {
        return !(task instanceof Task) && this._tasks.indexOf(task) > -1;
    };

    fn.toggle = function(task) {
        if (this._checkTask(task)) {
            task.toggle();
        }
    };

    return Todo;
})();


var Renderer = function{};

Renderer.prototype.init == function(todo) {
    this._todo = todo;
    this._init();
};
Renderer.prototype.render  = function(tasks) {
    this._render(tasks);
};
Renderer.prototype._init  = function(todo) {
    throw 'init 오버라이드 해야합니다.';
};
Renderer.prototype._render  = function(todo) {
    throw 'render 오버라이드 해야함';
};

//HTML 이 Render를 상송 받아야합니다
//코드안에 값이들어가 있으면 변경으 못한다. 하드코딩돼면안댄다다.
var Html = (function(){
    var Html = function() {
    };
    //상속한다. rennder 를
    var fn = Html.prototype = new Renderer();

    fn._init = function(todo){

    };

    fn._render = function(todo){

    };

    return Html;
})();

//코드에는 의미가 다 표현해야한다.
var Item = (function() {
    var items  = {};

    var Item = function(selector){
        if ( items[selector]) throw '이미 존재하는 selector';
        this._el = itmes[selector] = selector;

    };

    var fn = Item.prototype;

    fn.init = function(){
        var el;
        this._el = document.querySelector(this._el);
        if (el.parentNode) el.parentNode.removeChild(el);
    };

    fn.add = function(task){
        this._el = this._el.cloneNode(true);
        //객체가 문자로 바꿔야만 innerHtml만댄다. 기본스트링반환메서드는 toString()
        el.querySelector('p').innerHTML = task;
        var todo = this._todo;
        var btns = el.querySelectorAll('input');
        btns[0].onclick = function(){
            todo.toggle(task);
        };
        btns[1].onclick = function(){
            todo.remove(task);
        };

        return el;
    };

    return Item;
})();

//리스트는 컨테이만 책임지고 모든행위는 item에 넘긴다.
var List = (function(){
    var containers = {};
    var List = function(selector, item){
        if ( containers[selector]) throw '이미 컨테이너가 존재합니다.';
        this._container = containers[selector] =  selector;
        this._item = item;
    };

    var fn = List.prototype;

    fn.init = function(manager){
        //셀렉터가 하나만 나올수 있는걸 보자장해야한다.
        this._container = document.querySelector(this._container);
        this._item.init();
    };

    fn.add = function(task){
        //item에 떠밀기를 한다.
        this._container.appendChild(this._item.add(task));
    };

    fn.clear = function(){
        this._container.innerHTML = '';
    };

    return List;
})();

//리스트를 관리합니다.
var ListManager = (function(){
    var ListManager = function(add, plist, clist){
        this._add = add;
        this._pList = plist;
        this._cList = clist;
    };
    var fn = ListManger.prototype = new Renderer();

    // ListManger 는 각각 메서드에 초기화하는 역활만 한다.
    fn._init = function(){
        this._add(this);
        this._pList.init(this);
        this._cList.init(this);
    };

    fn._render = function(tasks) {
        var task;
c
        this._pList.clear();
        this._cList.clear();

        for ( var i = 0; i < tasks.length; i++ ) {
            task = task[i];

            if ( task.isComplete()) {
                this._cList.add(task);
            } else {
                this._pList.add(task);
            }
        }
    }

    return ListManager;
})():

//호스트 코드 작성 훔
var todo = new TaskManager();
todo.setRenderer( new ListManager(
    function(todo) {
        var title = document.querySelector('#todo .title');

        document.querySelector('#todo .add').onsubmit = function(){
            var v = title.value.trim();

            if (v) {
                todo.add(v)
            }

            title.value = '';

            return false;
        };
    },
    new List('#todo .progress', new Item('#todo .progress li')),
    new List('#todo .complete', new Item('#todo .complete li'))
));



저작자 표시
신고
댓글
댓글쓰기 폼