자바스크립트/Ext JS2013. 5. 22. 16:23
Ext.onReady(function() {
	/***
	 * 인스턴스를 검색하는 함수는 총 4가지다.
	 * query, child, up and down.
	 */
	var panel = Ext.create('Ext.panel.Panel', {
		height : 500,
		width : 500,
		renderTo : Ext.getBody(),
		margin : 50,
		id : 'myPanel',
		layout : {
			type : 'vbox',
			align : 'stretch'
		},
		items : [ {
			xtype : 'tabpanel',
			itemId : 'mainTabPanel',
			flex : 1,
			items : [ {
				xtype : 'panel',
				title : 'Users',
				id : 'usersPanel',
				layout : {
					type : 'vbox',
					align : 'stretch'
				},
				tbar : [ {
					xtype : 'button',
					text : 'Edit',
					itemId : 'editButton'
				} ],
				items : [ {
					xtype : 'form',
					border : 0,
					items : [ {
						xtype : 'textfield',
						fieldLabel : 'Name',
						allowBlank : false
					}, {
						xtype : 'textfield',
						fieldLabel : 'Email',
						allowBlank : false
					} ],
					buttons : [ {
						xtype : 'button',
						text : 'Save',
						action : 'saveUser',
						listeners : {
							click : function(){
								// 메소드의 실행이 가능하다.
								// 아래에 경우 리턴되는 객체가 없을 것이다.
								// 해당 텍스트필드에 값이 들어가 있다면 isValid조건에 맞는 객체를 리턴하게 될것이다.
								// 텍스트 필드에 값을 입력 후 Save버튼을 클릭해본다.
								var validField = Ext.ComponentQuery
										.query('form > textfield{isValid()}');
								console.log(validField);
							}
						}
					} ]
				}, {
					xtype : 'grid',
					flex : 1,
					border : 0,
					columns : [ {
						header : 'Name',
						dataIndex : 'Name',
						flex : 1
					}, {
						header : 'Email',
						dataIndex : 'Email'
					} ],
					store : Ext.create('Ext.data.Store', {
						fields : [ 'Name', 'Email' ],
						data : [ {
							Name : 'Joe Bloggs',
							Email : 'joe@example.com'
						}, {
							Name : 'Jane Doe',
							Email : 'jane@example.com'
						} ]
					})
				} ]
			} ]
		}, {
			xtype : 'component',
			itemId : 'footerComponent',
			html : 'Footer Information',
			extraOptions : {
				option1 : 'test',
				option2 : 'test'
			},
			height : 40
		} ]
	});

	// Ext.ComponentQuery's 'query' method
	/***
	 * ComponentQuery는 down, up과는 달리 해당되는 조건의
	 * component를 모두 찾아리턴한다.
	 */
	// Get all Panels
	var panels = Ext.ComponentQuery.query('panel');
//	console.log(panels);
	
	var formPanel = Ext.ComponentQuery.query('form');
	console.log(formPanel);
	// get all Buttons that are descendents of a Panel
	var buttons = Ext.ComponentQuery.query('button');
//	console.log(buttons);

	// get specific Button based on 'action' property
	var saveButton = Ext.ComponentQuery
			.query('button[action="saveUser"]')[0];
//	console.log(saveButton);

	// get 2 types of Component (buttons and textfields)
	var buttonsAndTextfields = Ext.ComponentQuery
			.query('button, textfield');
//	console.log(buttonsAndTextfields);
//
//	// get specific Panel based on ID
	// ID기반 검색.
	var usersPanel = Ext.ComponentQuery.query('panel#usersPanel')[0]; // or
	// Ext.ComponentQuery.query('#usersPanel');
//	console.log(usersPanel);

	// get components that have 'extraOptions' property with any value
	/***
	 * component중에 extraOption속성을 가지고 있는 콤포넌트를 찾아라.
	 * 속성의 존재여부에 따른 검색.
	 */
	var extraOptionsComponents = Ext.ComponentQuery
			.query('component[extraOptions]');
	// 달리 사용하면 component[height] -> 검색가능
	// component[height=40] -> 검색 가능.
//	console.log(extraOptionsComponents);

	

	// myPanel이라는 아이디를 가진 인스턴스를 찾아 하위에 있는 모든 패널을 찾는다. child 밑에 child까지.
	var validField = Ext.ComponentQuery
			.query('#myPanel panel');
//	console.log(validField);
	// myPanel이라는 아이디를 가진 인스턴스를 찾아 하위에 바로 붙어있는 child를 찾는다.
	var validField = Ext.ComponentQuery
			.query('#myPanel > panel');
//	console.log(validField);

	// Ext.ComponentQuery's 'is' method

	// decide if main Panel is a panel
	// 아래 부터는 인스턴스의 유형을 비교한다.
	var isPanel = Ext.ComponentQuery.is(panel, 'panel');
//	console.log(isPanel); // true

	// decide if main Panel is a panel with an ID of 'myPanel'
	// 비교 대상인 인스턴스가 panel이고 id가 myPanel인가?
	var isPanelWithCorrectID = Ext.ComponentQuery.is(panel,
			'panel[id="myPanel"]');
//	console.log(isPanelWithCorrectID); 

	// Container's 'query' method

	// get all buttons under Users Panel
	var usersPanelButtons = usersPanel.query('button');
//	console.log(usersPanelButtons);

	// Container's 'down' method

	// get first Panel under the main Panel (panel)
	var firstChildPanel = panel.down('panel');
//	console.log('001', firstChildPanel);

	// Container's 'child' method
//
//	// get first child button under the main Panel
//	var childButton = panel.child('button');
//	console.log(childButton); // is no Button in first level so
//								// returns null
//
//	// Container's 'up' method
//
//	// get first Panel above 'Add Order' button
	var saveUserButon = Ext.ComponentQuery
			.query('button[action="saveUser"]')[0];
	var saveUserButonParentPanel = saveUserButon.up('panel');

//	console.log(saveUserButonParentPanel);

	// Pseudo-selectors

	// get last textfield
	var lastTextfield = Ext.ComponentQuery.query('textfield:last');
	console.log(lastTextfield);

	// define your own that returns visible components
	Ext.ComponentQuery.pseudos.visible = function(items) {
		console.log('ii', items)
		var result = [];

		for ( var i = 0; i < items.length; i++) {

			if (items[i].isVisible()) {
				result.push(items[i]);
			}
		}

		return result;
	};
	var visibleComponents = Ext.ComponentQuery
			.query('component:visible');
//	console.log(visibleComponents);

});
// 출처 : Ext JS4 Web Application Development Cookbook
Posted by 베니94
자바스크립트/Ext JS2013. 5. 22. 16:22
Ext.onReady(function() {
	Ext.define('Customer.support.SupportMessage', {
        extend: 'Ext.panel.Panel',
        alias: 'widget.supportMessage',
        title: 'Customer Support',
        html: 'Customer support is online'
    });
    
    Ext.application({
        name: 'Customer',
        launch: function(){
            Ext.create('Ext.container.Viewport', {
                layout: 'fit',
                items: [{
                    xtype: 'supportMessage'
                }]
            });
        }
    });
	
});
// 출처 : Ext JS4 Web Application Development Cookbook
Posted by 베니94
자바스크립트/Ext JS2013. 5. 22. 01:22
// Configure the Ext.Loader class
Ext.Loader.setConfig({
	enabled : true,
	paths : {
		'Cookbook' : 'src/Cookbook'
	}
});
Ext.onReady(function() {
	// 동적 로딩 클래스에 대한 예제이다.
	// 상단에서 path를 잡아주었고 하단에서 require하면
	// 팔요한 클래스가 로딩되어 사용이 가능해 진다.
	// 단지 이러한 동적클래스 로딩은 개발모드에서 사용되어 진다고 봐야한다.
	// 운영환경에서는 정적으로 모든 클래스를 로딩할 수 밖에 없는 환경이므로(압축 및 최적화)..
	// 또한 아래와 같이 할 경우 인스펙터 상의 'Elements탭'의 html에서 자동으로 자바스크립트 링크가 
	// 생성된 것을 확인할 수 있다.
	// Create an instance of the Cookbook.Vehicle class inside the Ext.require() callback
	Ext.require('Cookbook.Vehicle', function() { // 이 부분이 있고 없고에 따라
//		var plane = Ext.create('Cookbook.Vehicle', 'Ford', 'Transit', 60);
//		plane.travel(200);
	});
//
//	// Create an instance of the Cookbook.Plane class inside the Ext.require() callback
//	Ext.require('Cookbook.Plane', function() {
//		var plane = Ext.create('Cookbook.Plane', 'Boeing', '747', 500, 35000);
//		plane.travel(200);
//	});
});
// 출처 : Ext JS4 Web Application Development Cookbook

require를 통해 로딩된 클래스 파일을 확인 할 수 있다.


아래 그림은 예제소스를 실행하고 있는 html파일의 내용이다. 위의 인스펙터와는 달리 Vehicle.js를 불러오고 있지 않다는 것을

확인 할 수 있다.



Posted by 베니94
자바스크립트/Ext JS2013. 5. 22. 01:10
Ext.onReady(function() {
	/***
	 * Date : 2013.05.22
	 * Desc : scope에 대한 예제이다.
	 * 		  동일 변수가 지역일 경우 전역일 경우, 또는 동일 함수가 지역일 경우 
	 * 		  전역일 경우 이 scope에 따라 호출되는 변수, 함수가 달라지겠다.
	 */
	// 썩 좋은 예제같지는 않다.
	// 범위 체인은 자바 스크립트 변수를 확인하는 방법입니다. 당신은 그 안에 지역 변수로 선언되지 않은 함수 내에서 변수에 액세스하려고하는 경우, 자바 스크립트 엔진 (즉, 범위), 함수의 체인을 다시 통과합니다
	//그 이름과 일치하는 변수를 찾고. 그것은 한 다음이 사용됩니다 발견하면, 그렇지 않으면 오류가 발생합니다. 또한이 지역 변수가 같은 이름의 전역 변수보다 우선적으로 적용된다는 것을 의미합니다.
	var myGlobalVar = 'Hello from Global Scope!';

	function myFunction() {
		var myGlobalVar = 'Hello from MyFunction!';
		console.log(this);
		alert(myGlobalVar);
	}

	//	alert(myGlobalVar);
	//	myFunction();
	//	alert(myGlobalVar);

	function MyClass() {
		console.log(this);

		this.myProperty = 'Hello';
	}

	var myClass = new MyClass();

	//	alert(myClass.myProperty);
	//	alert(this.myProperty);

	// create 'cat' object
	var cat = {
		sound : 'miaow',
		speak : function() {
			alert(this.sound);
		}
	};

	// create 'dog' object
	var dog = {
		sound : 'woof',
		speak : function() {
			alert(this.sound);
		}
	};

	// call 'speak' method on each
	//	cat.speak(); // alerts 'miaow'
	//	dog.speak(); // alerts 'woof'

	// Ext.bind를 사용하여 dog.speak함수의 scope를 cat클래스로 변경하여 
	// cat클래스의 speak함수가 실행되도록 하였다.
	//	Ext.bind(dog.speak, cat)(); // alerts 'miaow'

	// 아래 소스는 정상적인 버튼을 생성하고 클랙했을 경우 scope에 해당하는
	// text를 실행하도록 하였다 . 여기서 scope는 버튼 자체이므로 'My Test Button' 이겠다.
	var button = Ext.create('Ext.button.Button', {
		text : 'My Test Button',
		listeners : {
			click : function(button, e, options) {
				alert(this.text); // alerts 'My Test Button'
			}
		},
		renderTo : Ext.getBody()
	});
	//	button.show();

	// create our sample scope object
	var exampleObject = {
		text : 'My Test Object'
	};

	// 버튼을 생성하며 클릭 이벤트에 대한 구현체를 Ext.bind로 scope를 위의 exampleObject로 변경하였다.
	var button = Ext.create('Ext.button.Button', {
		text : 'My Test Button',
		listeners : {
			click : Ext.bind(function(button, e, options) {
				alert(this.text); // alerts 'My Test Object'
			}, exampleObject)
		},
		renderTo : Ext.getBody()
	});
	button.show();
	// 위의 2	번째 버튼과 동일하게 실행된다.
	var button = Ext.create('Ext.button.Button', {
		text : 'My Test Button',
		listeners : {
			click : function(button, e, options) {
				alert(this.text); // alerts 'My Test Object'
			},
			scope : exampleObject
		},
		renderTo : Ext.getBody()
	});
	button.show();
});

// 출처 : Ext JS4 Web Application Development Cookbook
Posted by 베니94
자바스크립트/Ext JS2013. 5. 22. 01:05
Ext.onReady(function() {
	/**
	 * Date : 2013.05.22
	 * Desc : Mixins를 설명한다. 이를 통해 다중 상속를 구현할 수 있다.
	 */
	Ext.define('HasCamera',{
		takePhoto : function(){
			console.log('Say Cheese! Click!')
		}
	});
	
	Ext.define('Cookbook.Smartphone',{
		mixins : {
			camera : 'HasCamera'
		},
		
		useCamera : function(){
			/***
			 * 우선 현재 클래스에 takePhoto함수가 있다면
			 * 실행하고 없다면 mixins에서 참조하고 있는 클래스를
			 * 찾아 실행한다.
			 * 현재 클래스의 takePhoto를 삭제하면 아래에서 호출되는 
			 * takePhoto는 mixins에서 참조한 클래스의 함수 일 것 이다.
			 */
			this.takePhoto();
		},
		
		takePhoto: function(){
			this.focus();
			// mixins으로 접근 시.
			this.mixins.camera.takePhoto.call(this);
		},
		
		focus: function(){
			console.log('Focusing Subject...');
		}

	});
	
	var smartphone = Ext.create('Cookbook.Smartphone');
	smartphone.useCamera();
});
// 출처 : Ext JS4 Web Application Development Cookbook
Posted by 베니94
자바스크립트/Ext JS2013. 5. 22. 00:57
Ext.onReady(function() {
	/***
	 * 여기에서는 상속을 통해 클래스를 재활용하고 상속해준 클래스를 초기화 또는 override로 재정의한다.
	 */
	Ext.define('Cookbook.Vehicle', {

		config : {
			manufacturer : 'Unknown Manufacturer',
			model : 'Unknown Model',
			topSpeed : 0
		},

		constructor : function(manufacturer, model, topSpeed) {
			// initialise our config object
			this.initConfig(); // 초기화 
			console.log(manufacturer, model, topSpeed)
			if (manufacturer) {
				this.setManufacturer(manufacturer);
			}
			if (model) {
				this.setModel(model);
			}
			if (topSpeed) {
				this.setTopSpeed(topSpeed);
			}
		},

		travel : function(distance) {
			console.log('The ' + this.getManufacturer() + ' ' + this.getModel()
					+ ' travelled ' + distance + ' miles at '
					+ this.getTopSpeed() + 'mph');
		}

	}, function() {
		console.log('Vehicle Class defined!');
	});

	// 생성사 클래스명과 필요한 인자를 같이 제공해 줄 수 있다.
	var vehicle = Ext
			.create('Cookbook.Vehicle', 'Aston Martin', 'Vanquish', 60);

	vehicle.travel(100); // alerts �The Aston Martin Vanquish travelled 100 miles at 60mph

	// Define the Cookbook.Plane class
	Ext.define('Cookbook.Plane', {

		extend : 'Cookbook.Vehicle',

		config : {
			maxAltitude : 0
		},

		constructor : function(manufacturer, model, topSpeed, maxAltitude) {
			// initialise our config object
			this.initConfig();

			if (maxAltitude) {
				this.setMaxAltitude(maxAltitude);
			}

			/***
			 * 상속 받은 클래스를 초기화 할 경우 아래와 같이 
			 * 제공받은 인자로 초기화가 가능하다.
			 * 즉 현재 메소드가 생성자이고 생성자 내부에서 callparent했으므로
			 * 상속해준 클래스의 생성자가 호출되는 것이다.
			 */
			this.callParent([ manufacturer, model, topSpeed ]);
		},

		takeOff : function() {
			console.log('The ' + this.getManufacturer() + ' ' + this.getModel()
					+ ' is taking off.');
		},
		land : function() {
			console.log('The ' + this.getManufacturer() + ' ' + this.getModel()
					+ ' is landing.');
		},

		travel : function(distance) {
			this.takeOff();

			// execute the base class� generic travel method
			console.log('current arg : ', arguments)
			/***
			 * 하단에 주목하자 현재 실행되고 있는 함수는 travel이고 동일한 함수가 상속받은
			 * 클래스에도 존재하는데 상속된 클래스의 함수를 콜하기 위해 아래와 같이 한다.
			 */
			this.callParent(arguments);
//
			console.log('The ' + this.getManufacturer() + ' ' + this.getModel()
					+ ' flew at an altitude of ' + this.getMaxAltitude()
					+ 'feet');
//
			this.land();
		}

	}, function() {
		console.log('Plane Class Defined!');
	});
	
	
	// create an instance of Cookbook.Plane class
	var plane = Ext.create('Cookbook.Plane', 'Boeing', '747', 500, 30000);
                
	plane.travel(800); // alerts 'The Boeing 747 is taking off'
});
// 출처 : Ext JS4 Web Application Development Cookbook
Posted by 베니94
자바스크립트/Ext JS2013. 5. 22. 00:52
Ext.onReady(function() {
	/***
	 * config에 대한 설명이다.
	 * config에 표기된 변수는 자동으로 set, get, apply메소드가 생성되고
	 * 필요에 따라 override를 하여 사용한다.
	 */
	// Define new class 'Vehicle' under the 'Cookbook' namespace
	Ext.define('Cookbook.Vehicle', {

		// define our config object
		config : {
			Manufacturer : 'Aston Martin',
			Model : 'Vanquish'
		},

		constructor : function(config) {
			/***
			 * 초기화 한다. 필요할때..
			 */
			this.initConfig(config);

			return this;
		},

		// show details of Vehicle
		getDetails : function() {
			console.log('I am an ' + this.getManufacturer() + ' ' + this.getModel());
		},

		// update DOM elements with current Values
		applyManufacturer : function(manufacturer) {
			console.log('Called applyManufacturer:', manufacturer)
			
			// 아래와 같이 사용할 경우 무한루프가 발생한다.
			// 이는 setter메소드는 apply메소드를 수반하기때문에 
			// setter메소드를 쓰면 안되고 config에 직접 세팅해야한다.
//			this.setManufacturer(manufacturer);
			
			this.Manufacturer = ':[ ' + manufacturer + ']';
		},
		
		getManufacturer : function(){
			console.log('Called getManufacturer', this.Manufacturer)
			return this.Manufacturer;
		},
		
		setManufacturer : function(manufacturer) {
			console.log('Called setManufacturer', manufacturer)
			this.manufacturer = this.applyManufacturer(manufacturer) || manufacturer;
		},

		applyModel : function(model) {
			console.log('Called model:', model)
			Ext.get('model').update(model);

			return model;
		}
	}, 
	function() {
		console.log('Cookbook.Vehicle class defined!');
	});

	// create a new instance of Vehicle class
	var vehicle = Ext.create('Cookbook.Vehicle');
	console.log(vehicle.getManufacturer());
	vehicle.setManufacturer('Volkswagen');
	vehicle.setModel('Golf');
	console.log(vehicle.getManufacturer());
	vehicle.getDetails();

});
// 출처 : Ext JS4 Web Application Development Cookbook
Posted by 베니94
자바스크립트/Ext JS2013. 4. 19. 10:29

안녕하세요 ExtJS 2번째 오프라인 강좌로 "ExtJS MVC 따라잡기"를 준비 했습니다.

ExtJS의 장점인 MVC 패턴을 통한 구현 방법을 알아보고 

TA, 개발PL 입장에서의 모듈화가 가능한 개발 구조가 어떤 것인지 알아봅니다.

[강사소개]

    • ExtJS적용 다수 시스템 구축 경험
    • 한국센챠유저그룹 활동
    • 삼성SDS ExtJS 강의 수행
    • 온오프믹스 ExtJS 강의 진행
    • Blog : http://benney.tistory.com

[ExtJS MVC 따라잡기]

  • 대상 : ExtJS에 관심있는 분, 막연히 MVC모델을 따라하는 분, TA입장에서 프로젝트 모듈화 및 구조를 고민하고 계신 분
  • 일시 : 5월 4일(토) 18:00 ~ 20:00
  • 장소 : 강남토즈타워점 (강남점, 강남2호점 아닙니다.!!)
    • URL : http://www.toz.co.kr/branch/main/index.htm?id=24
    • 주소 : 서울시 강남구 강남대로 84길 24-4
    • Map : http://durl.me/3p4m43
  • 등록비용 : 50,000원 (아래신청주소를 클릭하시고 온오프믹스에서 등록해주세요)
  • 신청주소 : http://onoffmix.com/event/14549
  • 강의방식 : 완벽히 실행가능한 소스를 통해 MVC구조를 설명 (실습X)
  • 강의내용
    • ExtJS MVC의 소개
      • MVC란 무엇인가?
      • MVC를 통해 무엇을 얻을 수 있나?
      • 각 요소에 대한 샘플을 보고 역할을 알 수 있다.
      • Controller는 만능인가? 알고 쓰자 Controller
    •  TA, PL입장에서 ExtJS MVC 구조
      • 대단위 프로젝트에서 어떤 형태로 모듈화를 해야하는가?
      • 개별 개발자간의 혼선을 줄이면서 개발할 수 있는 구성은 어떤 것인가?
      • 최종 배포는 어떤 모습이여야 하는가? Case별 장단점
      • 모듈별 개발은 어떤 모습으로 합쳐져 배포되어야 하는가?

기타 문의는 benneykwag@gmail.com으로 해주세요



Posted by 베니94
자바스크립트/Ext JS2013. 3. 15. 14:55


기존 시스템의 수정사항으로 인해 운영시스템에 재배포한 
배포 파일에 문제가 발생해서 확인 한 결과 역시나 한글문제로
인한 것으로 보인다.

아래 그림은 실제 배포된 시스템에서 발생한 에러이다.



아래 그림은 실제 소스와 최종 압축된 배포판의 소스를 비교한것이다.
그림 처럼 // scheduler event store 재정의 : 라는 주석이 달린 상태에서는
배포판 소스에서 주석 다음부분 한줄이 없어져서 실제 구동시 에러를
발생시켰다.



위의 주석을 아래의 그림처럼 /**/로 변경하거나 한글 "재정의"를 제거할 경우 문제가 해결되었다.



이런 문제는 최적화 및 압축 과정에서 생겨난 실 배포판 소스에 대해 신뢰를 못하게되고

배포 이후 어디서 문제가 발생할지 예측하기 힘들게 된다.


아무래도 내가 뭘 모르고 있는 것인지 의심해봐야 겠다.



Posted by 베니94
자바스크립트/Ext JS2013. 3. 9. 14:25

아래 공유한 글은 Sencha forum에서 가져온 내용이다.

레이아웃과 리팩토링에 대한 내용으로 정말 공감하고 좋은 내용이다.


출처 : http://www.sencha.com/forum/showthread.php?239725-Screencasts-Layouts-amp-Refactoring-into-Components


I've noticed that the Sencha examples for grids, forms, trees and other components are great for people to adapt to their own needs. Where those new to Ext JS often struggle is with laying out and structuring their applications correctly. 

To support some internal training, I've put together a couple of screencasts. I've tried to keep them simple and fast paced. Hopefully some people in the community find them useful too.

The first screencast covers the basics of components, containers and layouts.

 

The second describes how to refactor large blocks of code into loosely coupled components.

 

Make sure you turn up the resolution to 720p and make them fullscreen. Enjoy!

Posted by 베니94