자바스크립트/Ext JS2012. 1. 2. 15:34
이제 필요한 각각의 탭을 관장할 컨트롤러를 만들어 보자.
/**
 * File			: app/controller/Content.js
 * Class Name	: Docs.controller.Content
 * Desc 		: 컨트롤러 상위클래스
 */
Ext.define("Docs.controller.Content", {
    extend: "Ext.app.Controller",
    MIDDLE: 1,
    title: "",
    onLaunch: function () {
    }
});
/**
 * File			: app/controller/Welcome.js
 * Class Name	: Docs.controller.Welcome
 * Desc 		: 환영페이지 컨트롤러
 */
Ext.define("Docs.controller.Welcome", {
    extend: "Docs.controller.Content",
    baseUrl: "#",
    init: function () {
    	console.log('Docs.controller.Welcome.init called..');
        this.addEvents("loadIndex")
    }
});

/**
 * File			: app/controller/Classes.js
 * Class Name	: Docs.controller.Classes
 * Desc 		: 
 */
Ext.define("Docs.controller.Classes", {
    extend: "Docs.controller.Content",
    baseUrl: "#!/api",
    title: "API Documentation",
    requires: ["Docs.Settings"],
    stores: ["Settings"],
    models: ["Setting"],
    init: function () { 
    	//console.log('Docs.controller.Classes call', this.stores);
    }
});

/**
 * File			: app/controller/Tabs.js
 * Class Name	: Docs.controller.Tabs
 * Desc 		: 상단 탭영역 처리
 */
Ext.define("Docs.controller.Tabs", {
    extend: "Ext.app.Controller",
    //requires: ["Docs.Settings"],
     refs: [{
        ref: "doctabs",		// this.getDoctabs()로 접근이 가능하다. 하단에서.
        selector: "#doctabs"
    },{
        ref: "welcomeIndex",
        selector: "#welcomeindex"
    }, {
        ref: "classIndex",
        selector: "#classindex"
    }],
    init: function () {
    	/*this.getController("Classes").addListener({
            showClass: function (b) {
            	//console.log('b', b);
                this.addTabFromTree("#!/api/" + b)
            },
            scope: this
        });*/
    },
    onLaunch: function () {
    	this.getDoctabs().setStaticTabs(Ext.Array.filter([	
    											this.getWelcomeIndex().getTab(), 
    											this.getClassIndex().getTab()], 
    											function (a) {
            return a
        }));
    }
});

/**
 * File			: app.js
 * Class Name	: Docs.Application
 * App Name		: Docs
 * Desc 		: Main Class
 */
// app.js 에 controller : ["Welcome"]를 추가한다.
Ext.define("Docs.Application", {
    extend: "Ext.app.Application",
    name: "Docs",
    appFolder : 'app',
    controllers: ["Welcome","Classes","Tabs"],  // 이 부분을 추가한다.
    launch: function () {
    	Docs.App = this;
        Ext.create("Docs.view.Viewport");
        Ext.get("loading").remove()
    }
});

// 위의 4개 클래스를 index.html에서 access할 수 있도록 하자.
  
  
  
  
Posted by 베니94
자바스크립트/Ext JS2011. 12. 30. 16:54

본격적으로 코딩에 들어 가기 앞서 디렉토로 구조를 먼저 설명합니다. 현재는 app.js에 모든 코드가 들어가 있지만 이렇게 되면 혼란스럽기도 하고 본래 mvc모델의 모습을 파악하기 힘듭니다. 해서 아래 그림처림 디렉토리를 나누면서 코딩을 하도록 하겠습니다.


/**
 * File			: LocalStore.js
 * Desc 		: store
 */
Ext.define("Docs.LocalStore", {
    storeName: "",
    init: function () {
       // 로컬 스토리지에 대한 초기화.
    	 this.localStorage = !! window.localStorage;
    	 // 여기서 this.storeName는 Docs.Settings의 storeName으로 
    	 // Classes Controller에서 Settings라는 이름의 store를 참조하기 때문에 아래의 코드가
    	 // 유효하다.
         this.store = Ext.getStore(this.storeName); 
         if (this.localStorage) {
             this.cleanup();
             this.store.load();
             if (window.addEventListener) {
                 window.addEventListener("storage", Ext.Function.bind(this.onStorageChange, this), false)
             } else {
                 window.attachEvent("onstorage", Ext.Function.bind(this.onStorageChange, this))
             }
         }
    },
    onStorageChange: function (b) {
       
    },
    syncStore: function () {
        
    },
    cleanup: function () {
       
    }
});

/**
 * File			: Settings.js
 * Desc 		: 
 */
Ext.define("Docs.Settings", {
    extend: "Docs.LocalStore",
    storeName: "Settings",  // 참조만.
    singleton: true,
    set: function (d, f) {
        
    },
    get: function (c) {
       
    }
});

/**
 * File			: ContentGrabber.js
 * Desc 		: 
 */
Ext.define("Docs.ContentGrabber", {
    singleton: true,
    get: function (f) {
        var e;
        var d = Ext.get(f);
        if (d) {
            e = d.dom.innerHTML;
            d.remove();
        }
        return e
    }
});

/**
 * File			: app/model/Setting.js
 * Class Name	: Docs.model.Setting
 * Desc 		: 
 */
Ext.define("Docs.model.Setting", {
    fields: ["id", "key", "value"],
    extend: "Ext.data.Model",
    proxy: {
        type: window.localStorage ? "localstorage" : "memory",
        id: Docs.data.localStorageDb + "-settings"
    }
});

/**
 * File			: app/store/Settings.js
 * Class Name	: Docs.store.Settings
 * Desc 		: 
 */
Ext.define("Docs.store.Settings", {
    extend: "Ext.data.Store",
    model: "Docs.model.Setting"
});


// 이하 app.js
/*
 * 메인 클래스로 전체 레이아웃을 관장하는 Docs.view.Viewport를 호출
 */
Ext.define("Docs.Application", {
    extend: "Ext.app.Application",
    name: "Docs",
    appFolder : 'app',
    launch: function () {
    	Docs.App = this;
        Ext.create("Docs.view.Viewport");
        Ext.get("loading").remove()
    }
});
Ext.onReady(function () {
    Ext.create("Docs.Application")
});


/**
 * File			: app/view/Viewport.js
 * Class Name	: Docs.view.Viewport
 * Desc 		: 화면 레이아웃
 */
Ext.define("Docs.view.Viewport", {
	extend: "Ext.container.Viewport",
	id: "viewport",
    layout: "border",
    border: 1,
    defaults: {
        xtype: "container"
    },
    initComponent: function () {
    	this.items = [{
    		region: "north",
            id: "north-region",
            style: {borderColor:'#000000', borderStyle:'solid', borderWidth:'1px'},
            title: "north-region",
            height: 65,
            layout: {
                type: "vbox",
                align: "stretch"
            },
            items: [{
                height: 37,
                xtype: "container",
                layout: "hbox",
                items: [{
                	xtype: "docheader",
                	style: {borderColor:'#000000', borderStyle:'solid', borderWidth:'1px'}
                }, {
                    xtype: "container",
                    html : '빈공간',
                    style: {borderColor:'#000000', borderStyle:'solid', borderWidth:'1px'},
                    flex: 1
                }, {
                    id: "loginContainer",
                    xtype: "authentication",
                    style: {borderColor:'#000000', borderStyle:'solid', borderWidth:'1px'},
                    width: 500,
                    padding: "10 20 0 0"
                }, {
                    xtype: "searchcontainer",
                    id: "search-container",
                    style: {borderColor:'#000000', borderStyle:'solid', borderWidth:'1px'},
                    width: 230,
                    margin: "4 0 0 0"
                }]
            }, {
                xtype: "doctabs"
            }]
    	},
    	{
    		region : 'center',
    		style: {borderColor:'#000000', borderStyle:'solid', borderWidth:'1px'},
    		html :'center',
    		layout: "border",
    		minWidth: 800,
    		items: [{
                region: "west",
                xtype: "treecontainer",
                id: "treecontainer",
                border: 1,
                bodyPadding: "10 9 4 9",
                width: 240
            },{
    			region: "center",
                id: "center-container",
                layout: "fit",
                minWidth: 800,
                border: false,
                padding: "5 10",
                style: {borderColor:'#000000', borderStyle:'solid', borderWidth:'1px'},
                items: {
                    id: "card-panel",
                    cls: "card-panel",
                    xtype: "container",
                    layout: {
                        type: "card",
                        deferredRender: true
                    },
                    items: [{
                    	autoScroll: true,
                        xtype: "welcomeindex",
                        id: "welcomeindex"
                    }, {
                        xtype: "container",
                        id: "failure"
                    }, {
                        autoScroll: true,
                        xtype: "classindex",
                        id: "classindex"
                    }]
                }
    		}]
    	}, {
            region: "south",
            id: "footer",
            height: 20,
            contentEl: "footer-content" // index.html div  footer-content.
        }];
        this.callParent(arguments)
    },
    setPageTitle: function (b) {
       
    }
});

/**
 * app/view/Header.js
 * 프로그램 상단
 */
Ext.define("Docs.view.Header", {
    extend: "Ext.container.Container",
    alias: "widget.docheader",
    contentEl: "header-content", // index.html 내부의 header-content div를 현 클래스에 삽입.
    initComponent: function () {       
        this.callParent();
    },
    listeners: {       
    }
});
/**
 * app/view/auth/Login.js
 * 상단 로그인영역
 */
Ext.define("Docs.view.auth.Login", {
    extend: "Ext.container.Container",
    alias: "widget.authentication",
    html : '로그인 영역',
    loginTplHtml: [
'
', '', '', '', '', " or ", '회원가입', "
"], initComponent: function () { this.callParent(arguments); } }); /** * app/view/Tabs.js * 상단 탭영역 , 계속 늘어나겠죠.. */ Ext.define("Docs.view.Tabs", { extend: "Ext.container.Container", alias: "widget.doctabs", id: "doctabs", html :'탭영역', style: {borderColor:'#000000', borderStyle:'solid', borderWidth:'1px'}, initComponent: function () { this.callParent(); }, setStaticTabs: function (b) { this.staticTabs = b; //this.refresh() } }); /** * File : app/view/welcome/Index.js * Class Name : Docs.view.welcome.Index * Widget Name : welcomeindex * Desc : 환영페이지 */ Ext.define("Docs.view.welcome.Index", { extend: "Ext.container.Container", alias: "widget.welcomeindex", requires: ["Docs.ContentGrabber"], cls: "welcome iScroll", initComponent: function () { this.html = Docs.ContentGrabber.get("welcome-content"); this.hasContent = !! this.html; this.callParent(arguments) }, getTab: function () { return this.hasContent ? { cls: "index", href: "#", tooltip: "Home" } : false } }); /** * File : app/view/cls/Index.js * Class Name : Docs.view.cls.Index * Widget Name : classindex * Desc : 클래스 Api 페이지 */ Ext.define("Docs.view.cls.Index", { extend: "Ext.container.Container", alias: "widget.classindex", requires: ["Docs.ContentGrabber"], cls: "class-categories iScroll", margin: "15 10", autoScroll: true, initComponent: function () { this.callParent(arguments); }, getTab: function () { var b = (Docs.data.classes || []).length > 0; return b ? { cls: "classes", href: "#!/api", tooltip: "API Documentation" } : false } }); // 이제 index.html에 아래와 같이 위에서 언급된 파일들을 기입하자.
이로서 Doc어플리케이션의 레이아웃을 구성했습니다. 프로그램의 뼈대를 만드는게 제일 중요합니다. 이번 강좌는 그런면에서 뼈대를 완성하고 또 완성된 뼈대에 어떻게 프로그램들을 채워 넣을지 알아보는게 핵심입니다.
Posted by 베니94
자바스크립트/Ext JS2011. 12. 30. 13:47
이제 app.js파일의 원상태를 확인 할 수 있으니 파일내용을 찬찬히 들여다 보기로 하겠습니다.
우선 메인 함수부터 찾아야 겠죠. 모든 프로그램이 그렇겠지만 맨 아래쪽에서 메인함수와 주요 클래스들을 발견할 수 있었습니다.
실마리는 여기서 부터 잡아나가면 되겠죠


그런데 좀 이상한 것은 파일 라인수 입니다. 4만5천라인이라니~ 용량도 1.3메가나 나갑니다.~ ext-all-debug.js파일이 13만라인에 4메가 정도인데 이건 뭔가 이상합니다.
해서 파일 내용을 좀 자세하게 살펴 보았더니 클래스 중에 Ext로 시작하는 클래스가 상당히 존재합니다. 아래 그림처럼 말이죠!

 


일단 예상하기로는 빌드 과정에서 용량을 최소화 하기 위해 해당 어플리케이션에서 사용하는 클래스들만 따로 골라서 app.js파일에 통체로 같이 빌드하지 않았나 싶습니다. 그래야만 전체 클래스를 내려받는것 보다 낫고 필요한 클래스만 내려 받을 수 있도록 해서 성능을 개선하기 위함이지 않나 싶습니다.  이놈들의 정체가 뭔지 확실히 알려면 Ext로 시작하는 클래스를 ext-all-debug.js와 비교해 보면 알 수 있겠죠 클래스 중 하나를 골라 ext-all-debug.js파일의 동일한 클래스와 내용이 같은지 확인 해보니 100%동일 한 것으로 확인 되었습니다.

분석하는 입장에서는 모두 불필요하니 Ext로 시작하는 클래스들은 모두 app.js파일에서 제거하였습니다. 그리고 브라우저를 통해 다시 실행해봅니다. 이상없는걸 보니 제 생각이 맞는것 같습니다. 일단 이상태의 소스를 카피하여 남겨 놓습니다.

그런데 Ext클래스들을 제거 했는데도 소스량이 아직도 상당히 많아 보여서 확인 해보니 CodeMirror라는 놈이 있습니다. 소스의 맨처음에 시작하여 4천라인정도를 사용하고 있습니다. 일단 제거 해보고 나중에 필요하다면 다시 넣는것으로 하겠습니다.

이제 소스코드 량은 4천 라인정도로 실제 필요한 내용들만 남기고 제거가 되었습니다. 이 상태의 소스도 남겨 놓습니다.

이제 하나씩 프로그램을 다시 조립해 보겠습니다.

우선 app.js의 내용을 모두 삭제합니다. index.html도 내용을 모두 정리합니다. 아래 처럼요 그래야 처음 부터 하나씩 조립해서 완성품을 만들 수 있겠죠!


이제 웹브라우저를 통해 실행해보면 아무것도 보이지 않습니다. 브라우저는 항상 파이어폭스를 쓰는게 좋습니다. 구글크롬도 좋지만 디버그 모드의 활용은 파이어폭스쪽이 좀더 나아 보입니다.
이제 본격적으로 app.js파일에 코딩을 하고 프로그램을 만들어봅니다. 제일 중요한 것은 이 어플리케이션의 layout이 어떻게 구성되어 있느냐를 파악해야 합니다. 해서 뼈대 부터 만들고 하나씩 뼈대위에 살을 붙여 보도록 하겠습니다.
아래 그림은 Doc 어플리케이션의 뼈만 앙상한 모습입니다.

Posted by 베니94