'Javascript'에 해당되는 글 112건

  1. 2012.09.30 javascript XML CDATA Section 사용 방법
  2. 2012.09.28 IE 버전을 알아내는 여러가지 구현 방법
  3. 2012.09.14 "소셜 버튼" 생성 모듈 구현
  4. 2012.09.06 자바스크립트 인터페이스 구현
  5. 2012.09.06 자바스크립트 추상 클래스 구현
  6. 2012.08.27 자바스크립트 문서화를 위한 "jsdoc toolkit" 사용법 및 예제
  7. 2012.08.18 Javascript MVC 패턴 구현 1
  8. 2012.07.24 LazyImageLoader.js(점진적 이미지 로딩)
  9. 2012.07.04 자바스크립트 (Singleton, Factory, Chain, Interator) Pattern 구현
  10. 2012.07.04 자바스크립트 Mediator(중재자) Pattern 과 Facade Pattern 구현

javascript XML CDATA Section 사용 방법




javascript XML CDATA Section 사용 방법



1. XML은 CDATA Section(<![CDATA[ ~ ]]>)이라는 것을 지원하는데, 이 영역 안에 들어갈 경우 <, >, & 와 같은 특수 문자(마크업으로 인식될 문자)들을 일반 문자(<, >, &)와 같이 쓸 수 있다.


즉, &lt;, &gt;, &amp;와 같이 Entity로 써야하는 문자들을 아무런 변환 없이 일반 문자(<, >, &)와 동일하게 사용할할 수 있게 만든다.(하지만 실제 JS 영역 안의 Entity 문자는 브라우저가 Entiry 문자 그대로 해석해 버리기 때문에 일반 문자로 변환되지 않는 단점이 존재한다.)




  


- 소스보기는 위 HTML TAB 이동!!!(결과 페이지: http://mohwa.org/html/cdata.xhtml)




2. Javascript 코드에 CDATA Section 삽입 시 시작과 끝 부분에 //(주석)을 포함하는 것은 해당 Section을 해석하지(오래된 브라우저) 못하는 브라우저에 대한 에러를 막기 위해서다.(위 소스 코드를 참조)




3. 브라우저가 해당 페이지의 응답 Content-Type을 XHTML로 해석 시 제대로 작동하며, HTML등 다르게 해석 시 에러가 발생한다.(대부분의 브라우저(IE8+, Chrome, Safari, FF)에서 해당 파일의 확장명을 *.xhtml로 생성한 경우 서버는 페이지의 응답 Content-Type을 "application/xhtml+xml"로 반환한다. 그렇지 않은 경우 보통 "text/html"로 반환하고 페이지 에러가 발생하게 된다.)



- Content-Type: text/html




- (문법오류):







- Content-Type: application/xhtml+xml





- 결과(성공)페이지:





4. 파일의 확장명을 *.xhtml로 생성하거나, 응답 Content-Type을 "application/xhtml+xml"로 지정한 경우 브라우저는 자동으로 XML 유효성 검사를 실행하게 된다.(**IE를 제외한 대부분의 브라우저**)


즉, 개발 시 "W3C Validator"로 재 확인해 볼 필요없이 검증이 실시간으로 가능해지며, 그에 따른 개발 비용을 줄일 수 있있다.



- Chrome:




- Firefox:





5. "text/html" 응답 Content-Type에서 위 문제(</script> 문자열 사용?)를 해결할 수 있는 방법으로, 해당 태그 문자열을 아래와 같이 변경해 주면 된다.






- 소스보기는 위 HTML TAB 이동!!!





참고사이트: 


XHTML과 CDATA의 문제점

http://kwon37xi.egloos.com/3798259


XHTML 에서 자바스크립트 사용하기

http://forums.mozilla.or.kr/viewtopic.php?f=9&t=3433



IE 버전을 알아내는 여러가지 구현 방법

 

 

IE 버전을 알아내는 여러가지 구현 방법
 


 

 

 

 

 

IE 버전을 알아 내는 "첫 번째 방법"은 보통 사용자 "Agent" 정보를 반환하는 "window.navigator.userAgent" 속성 과 간단한 정규식을 활용해 위와 같이 해당 IE 버전을 필터링 하여 반환 받을 수 있다.


또한, 두 번째 방법으로는 "HTML 조건부 주석"을 활용한 방법으로 while 문 안에서 각 버전(IE4+)별 조건부 주석을 모두 실행하여, 해당 버전이 일치할 시 조건부 주석 안의 "i" 태그가 미리 생성된 div 태그에 포함(innerHTML 속성 사용) 된다.


즉, 미리 생성된 f 컬렉션은 하나의 "i" 태그를 포함하게 되므로 "!f[0]" 가 조건부인 "while 순회문"은 빠져나오게 되는 것이다.

 

 

 

P.S: 두 번째 코드는 아래 사이트를 참고하여, 알아보기 편하게(제 기준이지만;;) 코드를 변경하였습니다. 하지만 원본 코드의 간결함은 잃어 버린듯 합니다..^^;;

 


 



 

 

 


참고 사이트:

 

- userAgent sniffing을 사용하지 않고 IE의 버전 알아내기

http://codefactory.kr/2012/01/15/non-ua-based-ie-version-check/

"소셜 버튼" 생성 모듈 구현



1. 소셜 버튼 생성 모듈 구현


각종 SNS 서비스(트윗, 페이스북, 구글플러스)에서 제공하는 "소셜 버튼"을 생성하는 자바스크립트 모듈을 아래와 같이 구현해 보았습니다.


모듈에 대한 더 자세한 내용은 아래 링크(테스트, 메뉴얼)를 통해 확인 하실 수 있습니다.



테스트(예제) 페이지:

http://mohwa.org/html/twitter.html


모듈(sns.js) 메뉴얼:

http://mohwa.org/doc/sns/index.html


jsfiddle 소스:

http://jsfiddle.net/mohwa/mV7sU/




- 참고 사이트:


트위터 플러그인:

https://dev.twitter.com/docs/twitter-for-websites


구글플러스 플러그인:

https://developers.google.com/+/plugins/


페이스북 플러그인:

http://developers.facebook.com/docs/plugins/


미투데이 플러그인:

http://me2day.net/me2/plugin/guide/metoo_plugins




2. "트윗" 소셜 버튼 옵션 중 "data-dnt" 에서 DNT(Do Not Track)란?


사용자 브라우저의 DNT(do not track) 옵션 설정(유효)시 해당 사이트의 컨텐츠 커스터마이즈(사용자 정보 수집으로 인한 신규 컨텐츠 개발 및 수정)를 위한 사용자 정보 수집을 중지 시킨다.


예: 트위터 제공 컨텐츠 중 하나인 "추천 이용자" 또한 각 사용자 정보(Follow 데이타 등..)를 수집한 결과로 생산된 파생 컨텐츠이다.





DNT(do not track) 설정 방법:


1. 사용자 브라우저의 DNT 옵션 활성화 설정(사파리 기준).

2. 사용자 브라우저의 DNT 활성화 설정 유/무 에 따른 "HTTP Request Header" 비교 이미지.




2.1: 비활성 시 화면








2.2: 활성 시 화면










위 결과와 같이 "DNT" 옵션 설정 유/무 에 따라 "HTTP Request Header"에 "DNT" 헤더가 추가 요청되며, 요청받은 웹 사이트에서는 요청된 "DNT" 헤더를 확인 후 이 사용자에 대해서는 어떠한 "정보 수집" 등의 "트래킹" 행위를 중지 하게 된다.


당연한 얘기지만, 사용자 브라우저 설정(옵션)에 따라 헤더(DNT)값이 서버로 요청될 뿐, 로그 수집과 관련된 모든 권한은 해당 웹 사이트가 가지고 있는 것이다.


즉, 컨텐츠 제공자에게 사용자 정보 수집 중지에 관한 강제성이 존재하지 않으며, 이에 따라 결국 사용자는 DNT가 지원되는 사이트(트위터 등)에서만 정보 수집에 관한 "중지" 권한을 보장받을 수 있는 것이다





DNT(do not track) 관련 참고 링크:


트위터 프라이버시 보호 기능이란?

http://blog.naver.com/PostView.nhn?blogId=cspark14&logNo=30138563806&redirect=Dlog&widgetTypeCall=true


브라우저 추적 거부 설정이란?

http://japanese.engadget.com/2012/05/18/twitter-do-not-track/


DNT 기능이란?

http://buzz.tistory.com/entry/DNTDo-Not-Track




자바스크립트 인터페이스 구현






1. 제약사항(C# 기준)


1. 스스로의(추상클래스 자신) 객체를 가질 수 없다.

2. 선언된 인터페이스의 메서드는 상속받은 일반클래스(구현클래스)에서 반드시 전부 구현되어야 한다.

3. 추상클래스와 달리 일반 속성(Attribute) 및 메서드(Method)를 정의할 수 없다.

4. 다중상속이 가능하다.




2. 다중상속 예제 코드:


01: using System;
02: 
03: namespace ConsoleApplication2
04: {
05:         interface IMy
06:         {
07:                 void abc();
08:         }
09: 
10:         interface IYou
11:         {
12:                 void abc();
13:         }
14: 
15:         class CMy : IMy, IYou
16:         {
17:                 void IMy.abc()
18:                 {
19:                         Console.WriteLine("My");
20:                 }
21: 
22:                 void IYou.abc()
23:                 {
24:                         Console.WriteLine("You");
25:                 }               
26:         }
27: 
28:         class Program
29:         {
30:                 static void Main(string[] args)
31:                 {
32:                         CMy m = new CMy();
33:                         ((IMy)m).abc();
34:                         ((IYou)m).abc();
35:                 }
36:         }
37: }



출처: http://blog.naver.com/PostView.nhn?blogId=thx4alice&logNo=110023547339




3. 자바스크립트 인터페이스 구현


// IUser 인터페이스
var IUser = (function(){
	
	var iUser = function(){
		
		// 자기 자신의 객체 생성을 막기 위한 추가 소스
		if (this.constructor === iUser){
			throw new Error('정의된 인터페이스는 자기 자신의 객체를 가질 수 없습니다.');
		}
		else{
			return this;
		}
	};

	var prototype_members = { 
		// 메서드
		getId: function(){
		},
		setId: function(){
		}
	};
	
	for (var n in prototype_members) iUser.prototype[n] = prototype_members[n];
	
	return iUser;
	
})();


// IBoard 인터페이스
var IBoard = (function(){
	
	var iBoard = function(){
		
		// 자기 자신의 객체 생성을 막기 위한 추가 소스
		if (this.constructor === iBoard){
			throw new Error('정의된 인터페이스는 자기 자신의 객체를 가질 수 없습니다.');
		}
		else{
			return this;
		}	
	}

	var prototype_members = { 
		// 메서드
		getBoard: function(){
		},
		setBoard: function(){
		}	
	};
	
	for (var n in prototype_members) iBoard.prototype[n] = prototype_members[n];
	
	
	return iBoard;
	
})();		        


// User Entitie
var UserEntitie = new (function(){
	
	var userEntitie = function(){
		this.id = '';
        return this;	
    }
        	
   return userEntitie;
        	
}())();
  
        
        
        // 정의된 인터페이스(IUser) 메소드들을 상속받은 일반 클래스(User1)에서 구현한다.
var User1 = interfaceInherit(IUser, {
	// Repository
	getId: function(){
		return UserEntitie.id + '의 아이디 입니다.';
	},
	setId: function(id){
		UserEntitie.id = id;
		return this;
	}
});

// 정의된 인터페이스(IUser, IBoard) 메소드들을 다중 상속([IUser, IBoard]받은 일반 클래스(User2)에서 구현한다.
var User2 = interfaceInherit([IUser, IBoard], {
	// Repository
	getId: function(){
		return UserEntitie.id + '의 아이디랑꼐!!!!';
	},
	setId: function(id){
		UserEntitie.id = id;
		return this;
	},
	getBoard: function(){
		return this;
	},
	setBoard: function(){
		return this;
	}
});		        

// 인터페이스 상속(다중) 및 구현
function interfaceInherit(_interfaces, opt){
	
	var o = {};
	
	// 인터페이스 메서드 카운트
	var interfaceMethodCount = 0;        			
	// 일반클래스(구현클래스)의 인터페이스 메서드 구현 카운트
	var classMethodCount = 0;
	
	_interfaces = _interfaces.length ? _interfaces : [_interfaces];
	
	for (var i = 0, length = _interfaces.length; i < length; i++){
		
		var _interface = _interfaces[i];
	
		var F = function(){};
		
		for (var n in _interface.prototype){
			F.prototype[n] = _interface.prototype[n];
		}
	
		var $F = _interface.call(new F());
		
		for (var n in $F){
			// 인터페이스에 정의된 함수만 구현 가능하다.
			if (Object.hasOwnProperty.call(opt, n)){
				
				o[n] = opt[n];
				
				classMethodCount++;
			}
			
			interfaceMethodCount++;
		}
		
		if (interfaceMethodCount !== classMethodCount){
			// 일반 클래스(구현 클래스)에 정의된 인터페이스 메서드의 구현 메서드가 없을떄..
			throw new Error('상속된 인터페이스 메서드가 구현(모두)되지 않았습니다.');
			return {};
		}      			
	}
	
	return o;
}

alert(User1.setId('xanione').getId());
alert(User2.setId('yanione').setBoard().getBoard().getId());



예제 실행 URL:

http://jsfiddle.net/jeonseounggyun/jML3y/



참고 URL:


1. 인터페이스를 사용하는 이유는 몰까?

http://mrtint.tistory.com/679


2. 추상클래스와 인터페이스의 사용

http://blog.daum.net/question0921/1056


3. 인터페이스와 다중상속

http://warmz.tistory.com/359


4. 인터페이스 사용이유?

http://www.okjsp.pe.kr/seq/161248





자바스크립트 추상 클래스 구현









- 추상클래스 분류:

Animal(동물), Felidae(고양이과), Canidae(개과)


- 일반클래스(구현클래스) 분류:

하마, 사자, 고양이, 호랑이, 늑대, 개




1. 각 단어에 대한 의미


추상: 덜 구체화된 무엇.

객체: 상태(Attribute)와 행동(Method)을 가진 것.

클래스: 객체 생성을 위한 일종의 도면(설계도, 청사진).

초기화: 정의된 클래스를 이용하여 객체를 생성(인스턴스 생성)하는 것.




2. 제약사항(C# 기준)


1. 스스로의(추상클래스 자신) 객체를 가질 수 없다.

2. 선언된 추상클래스의 추상 메서드는 상속받은 일반클래스(구현클래스)에서 반드시 전부 구현되어야 한다.

3. 클래스(추상)가 메서드(추상)를 반드시 포함하지 않더라도 abstract 키워드가 있다면 추상클래스가 된다.

4. 일반 속성(Attribute) 및 메서드(Method)를 정의할 수 있다.




3. 추상클래스(Animal(동물))는 왜 객체를 가질 수 없는가?


위 "1. 단어에 대한 의미"에서 "객체"란 상태(Attribute)와 행동(Method)을 가진것이라 이미 언급하였다.


또한, "추상"이란 덜 구체화된 무엇을 뜻하며, 이는 "객체"가 반드시 가져야할 상태(Attribute)와 행동(Method(구현되지 않은 추상 메서드))을 갖지 못했다는 의미로 볼 수 있다.


즉, 이를 요약하면, "넌 너무 추상적인 클래스(설계도, 청사진)를 가졌으니 객체를 만들 수 없다!!!(인용)" 라는 의미로 보면 될듯하다.




4. 자바스크립트 추상 클래스 구현


/**
 * 
 * 추상클래스(ABoard)가 가진 기본적인(C# 기준) "제약"과 같이 자기 자신의 객체를 가질 수 없다.
*/
var ABoard = (function(){
	
	var aBoard = function(){
		
		this.id = '';
		this.name = '';
		
		// 자기 자신의 객체 생성을 막기 위한 추가 소스
		if (this.constructor === aBoard){
			throw new Error('정의된 추상클래스는 자기 자신의 객체를 가질 수 없습니다.');
		}
		else{
			return this;
		}		
	};
	
	var prototype_members = {
		
		getId: function(){
			return this.id;
		},
		setId: function(id){
			this.id = id;
			return this;
		},
		getName: function(){
			return this.name;
		},
		setName: function(name){
			this.name = name;
			return this;
		},		        	
		view: function(){
		},
		write: function(){
		}
	};
	
	for (var n in prototype_members) aBoard.prototype[n] = prototype_members[n];
	
	// 기존 OOP 언어의 abstract "키워드"와 같이 아래 처럼 추상메서드를 선언이 가능하다.
	aBoard.prototype.view.isabstract = true;
	aBoard.prototype.write.isabstract = true;
	
	return aBoard;
	
})();

// 상속받은 추상 메소드를 구현한다.(자유게시판)
var Free = abstractInherit(ABoard, {
	// Repository
	view: function(){
		alert(this.id + '님의 이름은 ' + this.name + '입니다.');	
	},
	write: function(){
		alert('write ok!!!');
		return this;
	}
});	


// 상속받은 추상 메소드를 구현한다.(QA게시판)
var QA = abstractInherit(ABoard, {
	// Repository
	view: function(){
		alert(this.name + '님 안녕하세요!!!!');	
	},
	write: function(){
		alert('write ok!!!');
		return this;
	}
});			       	        

// 일반클래스(구현클래스)에 정의된 추상클래스 상속함수
function abstractInherit(_abstract, opt){
	
	
	var o = {};
	
	// 추상 클래스의 추상 메서드 카운트
	var abstractMethodCount = 0;
	// 일반 클래스의 추상 메서드 구현 카운트
	var classMethodCount = 0;
	
	var F = function(){};
	
	for (var n in _abstract.prototype){
		F.prototype[n] = _abstract.prototype[n];
	}

	var $F = _abstract.call(new F());
	
	
	for (var n in $F){
		
		o[n] = $F[n];
		if (opt[n]) o[n] = opt[n];
		
		if ($F[n].isabstract) abstractMethodCount++;
		if ($F[n].isabstract && opt[n]) classMethodCount++;
	}
	
	if (abstractMethodCount !== classMethodCount){
		// 일반 클래스(구현 클래스)에 정의된 추상 메서드의 구현 메서드가 없을떄..
		throw new Error('상속된 추상 메서드가 구현(모두)되지 않았습니다.');
		return {};
	}
	else {
		return o;
	}
}

Free.setId('yanione1').setName('전성균1').write().view();
QA.setId('yanione2').setName('전성균2').write().view(); 





예제 실행 URL:

http://jsfiddle.net/jeonseounggyun/Cavbe/



출처 및 참고 URL:


1. 추상 클래스의 존재 이유

http://itewbm.tistory.com/24


2. 왜 추상 클래스를 사용하게 될까?

http://mrtint.tistory.com/678




자바스크립트 문서화를 위한 "jsdoc toolkit" 사용법 및 예제





자바스크립트 문서화를 위한 "jsdoc toolkit" 사용법 및 예제





1. jsdoc tookit-2.4.0.zip(현재 버전 기준)을 다운받아 적당한 위치에 압축을 해제한다.



2. jsdoc toolkit 실행



- Mac OS 기준:


터미널 접근 후 해당 폴더(jsdoc tookit 루트 폴더)에 위치하여 아래 명령어를 실행한다.


java -jar jsrun.jar app/run.js javascript_doc_test.js(jsdoc을 활용해 변환시킬 *.js 파일)  -t=templates/jsdoc -d="out"(이와 같이 디렉토리를 지정(-d="out")하면 현재 위치(jsdoc 루트 폴더)에 ".out" 폴더가 생성되며, 그 아래 index.html(root file), symbols(하위 file을 포함하는 디렉토리)가 추가적으로 생성된다.



- Window OS 기준:


아래 링크를 참고해 "java"를 다운받아 설치한 후 OS 환경변수를 설정한다.


- 자바(java) 설치 및 환경변수 설정...

http://caskers.tistory.com/372


윈도우 명령프롬프트(커멘드창) 접근 후 해당 폴더(jsdoc tookit 루트 폴더)에 위치하여 아래 명령어를 실행한다.


java.exe -jar jsrun.jar app/run.js javascript_doc_test.js -t=templates/jsdoc -d="out"




3. jsdoc toolkit 작성법









@namespace: 네임스페이스 설명(javascript 이용한 MVC Pattern 구현)
@author: 작성자(<a href="http://mohwaproject.tistory.com">mohwa</a>)
@version: 버전(0.1)
@since: 작성일(2012.08.)
@see: 참조 문서 및 메서드
@description: 상세 설명








@class: 클래스 설명(MVC Data Model 하나로 등록된 데이터 모델(Object) 갱신 mvc.Entities.cookie 클래스를 통해 유지 시킨다.)
@constructor 함수가 생성자일 경우만 표기(Entities Class 생성자 함수)
@param 해당 매개변수({String} memberName 등록된 Entities 객체 구분 key(mvc.Entities[key] 암묵적 전역 변수에 객체(this) 선언 정의한다.))
@type 리턴 데이터 타입(Object)
@returns 리턴값(해당 context)
@example 예제코드(mvc.Entities('board');)






@private: 해당 함수가 private(지역) 경우만 표기
@public: 해당 함수가 public(공공) 경우만 표기
@static: 해당 함수가 static(정적) 경우만 표기





4. 참조 사이트:


jsdoc toolkit: 

http://code.google.com/p/jsdoc-toolkit/


mvc.js jsdoc:

http://mohwa.org/doc/mvc/index.html


jundo jsdoc:

http://dev.iamdenny.com/Drag-Drop/doc/index.html




Javascript MVC 패턴 구현




Javascript MVC 패턴 구현





1. MVC 패턴 정의:


하나의 응용 프로그램을 Model(데이터)계층, View(표현(페이지랜더링))계층Control(User Interation)계층으로 분리하는 디자인 패턴 중 하나이다.




2. javascript MVC 패턴 정의:


Model: 데이터 객체를 저장하는 창고로 쓰이며, View나 Controler에 대해서 전혀 신경 쓸 필요가 없고, 모델은 데이터, 데이터와 직접적으로 관련이 있는 로직만을 포함하는 것이 좋다. 


즉, "이벤트 처리 코드", "뷰 템플릿" 과 같이 모델과 관련 없는 로직등은 포함하지 말아야 한다.


View: 사용자와의 상호작용을 맡는 계층이며, 보통 HTML, CSS, 자바스크립트 템플릿으로 View를 구성한다. 


Model과 마찬가지로 View 또한, 에플리케이션의 다른 부분(계층)과 분리되어야 한다.(Controler나 Model 객체와 독립적이어야 한다는 뜻이다.)


Controler: Model과 View 사이의 접착제 역활을 하며, 보통 이벤트를 통해 갱신된 데이터를 Model에 적용하고 그 결과를 View에 반영 시킨다. 또한, 보통 Controler객체 초기화(init)시 각 이벤트 리스너를 추가시키는 로직을 구성한다.




3. 구현한 MVC 패턴 정의:


Model: 등록된 Data Model인 "Concrete(Function 구성)" 객체를 통해 데이터를 Controler에 반환하고, "Entitie(Object(json)구성)" 객체를 통해 등록된 각 데이터 모델을 갱신하고, 유지(Cookie 사용)시킨다.


View: Controler를 통해 등록된 View(Function)를 호출 한다.


Controler: Model과 View 사이의 접착제 역활을 하며, 각 이벤트들을 통해 호출 시킨다.

또한, Model(Concrete, Entitie)를 통해 반환된 결과를 View에 반환 후 호출(렌더링)시킨다.




MVC.js URL:

http://img.fpscamp.com/js/mvc/mvc.js


테스트 URL:

http://jsbin.com/azizok/1/



ps. 아직 각 브라우저의 몇가지 잔존 버그가 존재합니다.(테스트 시 크롬 브라우저를 이용을 권장드립니다.^^;;)




4. 실행 예제


        	
        	// Entities
        	mvc.Entities('board').append('info', {id: 'yanione', name: 'yanione_name'});
        	// Concretes
        	mvc.Concretes('board').append('view', function(entitie){
        		this.callback(entitie);
        	});
        	
        	// Views
        	mvc.Views('info').append('render', function(ret){
        		
        		for (var n in ret){
        			document.body.innerHTML += n + '=' + ret + '
'; } }); window.onload = function(e){ // Controls, Models mvc.Controls('boardInfo', mvc.Models(mvc.Concretes.board, mvc.Entities.board), mvc.Views.info).exec('view', 'render', 'info'); }



5. 구현된 MVC.JS jsDoc 문서.


http://mohwa.org/doc/mvc/index.html



LazyImageLoader.js(점진적 이미지 로딩)



LazyImageLoader.js


얼마전 @niceaji님을 통해 알게 된 Jquery 확장 기능인 LazyLoad.js 테스트 해보니 몇가지 버그가 존재하는것을 발견하였습니다.


@niceaji 님의 포스트: http://uix.kr/archives/1088


코드 전체를 분석해 보지는 않았지만, 핵심 기능인 가시거리(좌표)내의 이미지 로딩이 제대로 되지 않는 버그가 존재 했으며,(가시거리 수치가 잘못 계산된 탓인지? 로딩 시 수치 밖의 이미지까지 로딩되는 버그.) 또한 IE 브라우저에서는 스크립트 오류가 발생하기도 했습니다.(오류는 발생하지만 기능은 정상적으로 수행됩니다;;;)



아래는 해당 기능(점진적 로딩)과 몇 가지 기능을 추가하여, 재 작성된 소스 코드 링크 및 사용 방법 입니다.



1. jsbin 소스 링크:

http://jsbin.com/owayim/11/edit




2. 모듈 사용방법

LazyImageLoader({
        onload: function (e, elem) {
            //alert(elem);
        },
        onerror: function (e, elem) {
        },
        loadingImage: '',
        loadIntervalTime: 30
    });


onload: 각 이미지 로딩 시 이벤트 핸들러

onerror: 각 이미지 로딩 에러 시 이벤트 핸들러

loadingImage: 각 이미지 로딩 전 Default 이미지 경로

loadIntervalTime: 각 이미지 로딩 시간 간격




3. <img> 태그 정의

<img data-name="lazy" data-src="http://img.vaanonline.co.kr/upload/screenshot/120705/120705adiifqytcrimqb.jpg" />
<img data-name="lazy" data-src="http://img.vaanonline.co.kr/upload/screenshot/120705/120705adiifqytcrimb.jpg" />
<img data-name="lazy" data-src="http://img.vaanonline.co.kr/upload/screenshot/120705/120705adiifqytcrimqb.jpg" />
<img data-name="lazy" data-src="http://img.vaanonline.co.kr/upload/screenshot/120705/120705adiifqytcrimqb.jpg" />


data-name: "lazy"

data-src: 대치 이미지 경로





자바스크립트 (Singleton, Factory, Chain, Interator) Pattern 구현



Singleton Pattern


함수클래스의 객체를 단 "하나"만 생성하게 만드는 디자인 패턴.


즉, 동일한 함수클래스 호출 시 반환되는 두번째 객체 부터는 이전에 생성된 객체를 반환하게 된다.


  1. var Singleton = (function () {
  2.  
  3.     var that = null;
  4.  
  5.     var Singleton = function () {
  6.  
  7.         if (that) return that;
  8.  
  9.         that = this;
  10.  
  11.         return that;
  12.     }
  13.  
  14.     return Singleton;
  15.  
  16. })();
  17.  
  18. function User() {
  19.     return this;
  20. }
  21.  
  22. var obj1 = Singleton();
  23. var obj2 = Singleton();
  24.  
  25. //alert(obj1 === obj2); // true
  26. //alert(new User() === new User()); // false





Factory Pattern


사용자가 구체적인 클래스 정보를 모르고도 빌드(객체 생성 캡슐화)를 통해 객체를 생성할 수 있도록 만드는 디자인 패턴.


아래 코드에서는 클래스 타입 뿐 아니라 해당 클래스의 매개변수까지 넘겨 객체를 반환할 수 있게 설계 되었다.


  1. var Factory = (function () {
  2.  
  3.     var Factory = function () {
  4.  
  5.         var ns = arguments[0].split('.')
  6.           , parent = eval(ns[0])
  7.           , childs = ns.slice(1);
  8.  
  9.         for (var i = 0, length = childs.length; i < length; i++) {
  10.  
  11.             if (!parent[childs[i]]) break;
  12.  
  13.             parent = parent[childs[i]];
  14.         }
  15.  
  16.         // parent.apply(obj, []) 함수의 반환값은 parent 함수(User)를 실행시킨 결과 return this(window object) 이다.
  17.         function T(args) { return parent.apply(this, Array.prototype.slice.call(args, 1)); };
  18.  
  19.         T.prototype = parent.prototype;
  20.  
  21.         return new T(arguments);
  22.     }
  23.  
  24.     return Factory;
  25.  
  26. })();
  27.  
  28.  
  29. function User(name, score) {
  30.     this.name = name;
  31.     this.score = score;
  32.    
  33.     return this;
  34. }
  35.  
  36. User.prototype.getName = function () {
  37.     return this.name;
  38. }
  39.  
  40. User.prototype.getScore = function () {
  41.     return this.score;
  42. }
  43.  
  44. User.name1 = function (name, score) {
  45.     this.name = name;
  46.     this.score = score;
  47.     return this;
  48. }
  49.  
  50. User.name1.prototype.getName = function () {
  51.     return this.name;
  52. }
  53.  
  54. User.name1.prototype.getScore = function () {
  55.     return this.score;
  56. }
  57.  
  58.  
  59. var obj1 = Factory('User', 'user1', 1);
  60. var obj2 = Factory('User.name1', 'user2', 2);
  61.  
  62. alert(obj1.getName());
  63. alert(obj1.getScore());
  64.  
  65. alert(obj2.getName());
  66. alert(obj2.getScore());





Chain Pattern


해당 객체를 메서드의 반환 값으로 지정하여 연속된 메서드를 호출할 수 있도록 만드는 디자인 패턴이다.


  1. var Chain = new (function () {
  2.  
  3.     var Chain = function () {
  4.  
  5.         this.name = '';
  6.         this.age = 0;
  7.  
  8.         return this;
  9.     };
  10.  
  11.     Chain.fn = Chain.prototype = {
  12.  
  13.         getName: function () {
  14.             return this.name;
  15.         },
  16.         setName: function (name) {
  17.             this.name = name;
  18.             return this;
  19.  
  20.         },
  21.         getAge: function () {
  22.             return this.age;
  23.         },
  24.         setAge: function (age) {
  25.             this.age = age;
  26.             return this;
  27.         }
  28.     };
  29.  
  30.     return Chain;
  31.  
  32. }())();
  33.  
  34. //alert(Chain.setName('test').getName()); // test
  35. //alert(Chain.setAge(10).getAge()); // 10
  36. //alert(Chain.setName('test').setAge(10).getAge()); // 10





Interator(반복자) Pattern


기능의 세부적인 구현을 외부로 노출시키지 않고, 컨테이너(Interator(arguments)의 요소에 차례대로 접근할 수 있는 방법(.each())을 제공하는 디자인 패턴


  1. var Interator = (function () {
  2.  
  3.     var Interator = function () {
  4.         return new Interator.fn.init(arguments);
  5.     };
  6.  
  7.     Interator.fn = Interator.prototype = {
  8.         init: function (arguments) {
  9.             this.arguments = arguments;
  10.             return this;
  11.         },
  12.         each: function (callback) {
  13.  
  14.             callback = typeof callback === 'function' ? callback : function () { ; };
  15.  
  16.             for (var i = 0, length = this.arguments.length; i < length; i++) {
  17.                
  18.                 var argument = this.arguments[i];
  19.                 callback.call(argument, i);
  20.             }
  21.         }
  22.     };
  23.  
  24.     Interator.fn.init.prototype = Interator.prototype;
  25.  
  26.     return Interator;
  27.  
  28. })();
  29.  
  30.  
  31. Interator(1, 2, 3).each(function (i) {
  32.     alert(this + ',' + i);
  33. });




자바스크립트 Mediator(중재자) Pattern 과 Facade Pattern 구현


Mediator(중재자) Pattern

객체 설계 시 최대한 객체간의 결합도를 낮춰, 필요 시 유지보수가 용이한 형태로 설계되야 한다.

즉, 객체간의 결합도가 높아지면 높아질수록, 유지보수(수정 비용) 비용 또한 올라간다. 중재자 패턴은 이런 문제를 완하하기 위한 디자인 패턴이며, 아래 코드의 독립된 객체(user1 ~ user4)들은 자신의 상태(score)가 변경되면, 이를 중재자에게 알리고(Mediator.play()), 점수판 객체(Score)의 update 메서드를 호출해 모든 플레이어들이게 변경사항을 통지한다.


- 점수판 객체(Score)는 어떤 유저에 관한 정보도 일체 알지 못하며, 어떤 정보도 저장하지 않는다.


  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head id="Head1" runat="server">
  4. <title></title>
  5. <script type="text/javascript">
  6. //<![CDATA[
  7.  
  8.  
  9. // Mediator(중재자) Pattern
  10.  
  11. var Mediator = new (function () {
  12.  
  13. var Mediator = function () {
  14. this.mediators = [];
  15. return this;
  16. }
  17.  
  18. Mediator.fn = Mediator.prototype = {
  19.  
  20. make: function (user) {
  21.  
  22. if (!user) return false;
  23.  
  24. this.mediators.push({ user: user });
  25.  
  26. return this;
  27. },
  28. remove: function (user) {
  29.  
  30. for (var t in this.mediators) {
  31. if (user) {
  32. if (this.mediators[t].user === user) {
  33. delete this.mediators[t];
  34. }
  35. }
  36. else {
  37. delete this.mediators[t];
  38. }
  39. }
  40.  
  41. return this;
  42. },
  43. play: function () {
  44.  
  45. var names = []
  46. , scores = [];
  47.  
  48. for (var n in this.mediators) {
  49. names.push(this.mediators[n].user.name);
  50. scores.push(this.mediators[n].user.score);
  51. }
  52.  
  53. var score = new Score();
  54. score.update.apply(score, [names, scores]);
  55. }
  56. }
  57.  
  58.  
  59. return Mediator;
  60.  
  61. } ())();
  62.  
  63. function Users(name) {
  64.  
  65. this.name = name;
  66. this.score = 0;
  67.  
  68. // 플레이어 목록 추가
  69. Mediator.make(this);
  70.  
  71. return this;
  72. }
  73.  
  74. Users.prototype.play = function () {
  75.  
  76. this.score++;
  77. // boardcast call
  78. Mediator.play();
  79.  
  80. return false;
  81. }
  82.  
  83. function Score() {
  84. return this;
  85. }
  86.  
  87. Score.prototype.update = function (names, scores) {
  88.  
  89. var elem = document.getElementById('userScoreBoardList')
  90. , h = [];
  91.  
  92. for (var t in names) {
  93. h.push('<li>' + names[t] + '님의 점수는 ' + scores[t] + '</li>');
  94. }
  95.  
  96. elem.innerHTML = h.join('');
  97.  
  98. return this;
  99. }
  100.  
  101. window.onload = function () {
  102. user1 = new Users('user1');
  103. user2 = new Users('user2');
  104. user3 = new Users('user3');
  105. user4 = new Users('user4');
  106.  
  107. //Mediator.remove(user4);
  108. }
  109.  
  110. //]]>
  111. </script>
  112. </head>
  113. <body>
  114. <a href="#" onclick="return user1.play()">user1</a>
  115. <a href="#" onclick="return user2.play()">user2</a>
  116. <a href="#" onclick="return user3.play()">user3</a>
  117. <a href="#" onclick="return user4.play()">user4</a>
  118. <ul id="userScoreBoardList"></ul>
  119. </body>
  120.  
  121. </html>





Facade Pattern

사용되는 빈도가 높은 메서드들을 하나로 감싸 새로운 메서드를 만들어 좀 더 편리한 API제공하는 디자인 패턴이다.

가장 대표적인 예로 아래와 코드에서 처럼 크로스 브라우징을 위한 DOM Event 할당 함수(addEventListener, attachEvent)를 꼽을 수 있다.


  1. var Facade = new (function () {
  2.  
  3. var Facade = function () {
  4. return this;
  5. }
  6.  
  7. Facade.fn = Facade.prototype = {
  8.  
  9. bind: function (elem, type, handler, capture) {
  10.  
  11. type = typeof type === 'string' ? type : '';
  12. handler = typeof handler === 'function' ? handler : function () { ; };
  13. capture = capture || false;
  14.  
  15. if (elem.addEventListener) {
  16. elem.addEventListener(type, handler, capture);
  17. }
  18. else if (elem.attachEvent) {
  19. elem.attachEvent('on' + type, handler);
  20. }
  21.  
  22. return this;
  23. },
  24. unbind: function (elem, type, handler, capture) {
  25.  
  26. type = typeof type === 'string' ? type : '';
  27. handler = typeof handler === 'function' ? handler : function () { ; };
  28. capture = capture || false;
  29.  
  30. if (elem.removeEventListener) {
  31. elem.removeEventListener(type, handler, capture);
  32. }
  33. else if (elem.detachEvent) {
  34. elem.detachEvent('on' + type, handler);
  35. }
  36.  
  37. return this;
  38. }
  39. }
  40.  
  41.  
  42. return Facade;
  43.  
  44. } ())();
  45.  
  46. window.onload = function () {
  47.  
  48. var btn1 = document.getElementById('btn1');
  49. var btn1_callback = function () { alert('btn1'); return false; };
  50.  
  51. var btn2 = document.getElementById('btn2');
  52. var btn2_callback = function () { alert('btn2'); return false; };
  53.  
  54. Facade.bind(btn1, 'click', btn1_callback).unbind(btn1, 'click', btn1_callback);
  55. Facade.bind(btn2, 'click', btn2_callback);
  56. }




prev 1 2 3 4 5 6 7 ··· 12 next