input tag 키패드 입력 이벤트 catch

javascript 2018. 12. 3. 17:17 Posted by jiddong

모바일 기기 input box keypad 입력 이벤트 catch


안드로이드, ios 하이브리드 앱개발시 키패드 이벤트 잡는 방법


$("#input-id").on("change keyup paste", function(){
    dosomething();
})




// jquery 처럼 파라미터 전달하고 체이닝방식으로 개발해봄

//소스 데이터 전송후 getValue 함수를 추가해야함~

var opDailogCallbackListner = [];
$.fn.opDialog = function(_value, _id, _data){
var tempId = this.selector.replace('#','');
if($(this.selector).length != 1){
//팝업창 객체 없음
$('body').append('<iframe id="'+tempId+'" style="display: none;" data-value=undefined iframe>');
}
if(_value == 'open'){
//배경 페이지 생성
$(this.selector).css({"background-color": "rgba(0, 0, 0, 0.5)"
, "display":"block"
, "left": "0px"
, "top": "0px"
, "width": "100%"
, "height": "100%"
, "position": "absolute"
});
//다이어로그 페이지 이동
var url = $(this.selector).attr('data-url');
$(this.selector).attr('src',inavigator.getUrl(url));
}else if(_value == 'close'){
//버튼 이벤트 리스너에 등록된 id를 가진 이벤트가 있을경우에만 실행
var removeIndex = -1;
for (var index = 0; index < window.parent.opDailogCallbackListner.length; index++) {
if(window.parent.opDailogCallbackListner[index].id == tempId){
//close 이벤트시 선택이벤트있을때만 실행
removeIndex = index;
var events = window.parent.opDailogCallbackListner[index].event;
for (var key in events) {
if(_id == key){
events[key](_data);
}
}
}
}
if(removeIndex != -1){
window.parent.opDailogCallbackListner.splice(removeIndex,1);
}
//딤처리 및 화면 초기화
var frame = window.parent.document.getElementById(tempId);
frame.parentNode.removeChild(frame);
}else{
//데이터 url 이벤트 셋팅
$(this.selector).attr('data-url',_value.url);
$(this.selector).attr('data-value', JSON.stringify(_value.data));
opDailogCallbackListner.push({id:tempId , event:_value.buttons});
}
//요 리턴하는법이 체이닝 방식으로 할수있는법
// $('a').func1().func2() 이렇게 호출가능
return this;
}
//사용방법 팝업 생성
$('#iframe0').opDialog({
url : 'popup_test.html',
data : { text : "전달"},
buttons: {
button0 : function(d){console.log(d)},
button1 : function(d){console.log(d)}
}
}).opDialog('open');


//사용방법 팝업 닫기
$('#iframe0').opDialog('close', "button1" , {text :"리턴데이타" });


CSS 셀렉터

javascript 2015. 3. 2. 10:34 Posted by jiddong

CSS 셀렉터 

css 보통 클래스 이름이나 요소(tr, td, div) 선택으로 사용했는데 다양한 셀렉터가 존재 했었다니..

특히 특정 태그의 속성 값으로 색상을 줄수 있다늬!!! 충격이었다 예를 들면 아래와 같다

 

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <style>
  5.         td[field="test"] {
  6.             color: blue;
  7.         }
  8.     </style>
  9. </head>
  10. <body>
  11.     <table>
  12.         <tr>
  13.             <td field="test">CSS selector color Change</td>
  14.             <td>CSS selector color Change</td>
  15.         </tr>
  16.     </table>
  17. </body>
  18. </html>

셀렉터 정보

선택자는 Type(element),Universal(*),class/id,attribute(속성),가상요소/가상클래스,선택자결합(하위,자식,인접) 등으로 구성된다.

PatternMeaningS5C8F3.6O11I9bI8I7I6
#idid로 지정된 요소 선택OOOOOOOO
.classclass로 지정된 요소 선택OOOOOOOO
EE 요소를 선택OOOOOOOO
E:link방문하지 않은 E를 선택OOOOOOOO
E:visited방문한 E를 선택OOOOOOOO
E:hover마우스가 올라가 있는 동안 E를 선택OOOOOOOO
E:active마우스 클릭 또는 키보드(enter)가 눌린 동안 E를 선택OOOOOOOX
E:focusfocus가 머물러 있는 동안 E를 선택OOOOOOXX
E:first-lineE 요소의 첫 번째 라인 선택OOOOOOOX
E:first-letterE 요소의 첫 번째 문자 선택OOOOOOOX
*모든 요소 선택OOOOOOOO
E[foo]‘foo’ 속성이 포함된 E를 선택OOOOOOOX
E[foo="bar"]‘foo’ 속성의 값이 ’bar’와 일치하는 E를 선택OOOOOOOX
E[foo~="bar"]‘foo’ 속성의 값에 ’bar’가 포함되는 E를 선택OOOOOOOX
E[foo|="en"]‘foo’ 속성의 값이 ’en’ 또는 ’en-’ 으로 시작되는  E를 선택OOOOOOOX
E:first-child첫 번째 자식 요소가 E라면 선택OOOOOOOX
E:lang(fr)HTML lang 속성의 값이 ’fr’로 지정된 E를 선택OOOOOOXX
E::beforeE 요소 전에 생성된 요소 선택OOOOOOXX
E::afterE 요소 후에 생성된 요소 선택OOOOOOXX
E>FE 요소의 자식인 F 요소 선택OOOOOOOX
E+FE 요소를 뒤의 F 요소 선택OOOOOOOX
E[foo^="bar"]‘foo’ 속성의 값이 ’bar’로 정확하게 시작하는 요소 선택OOOOOOOX
E[foo$="bar"]‘foo’ 속성의 값이 ’bar’로 정확하게 끝나는 요소 선택OOOOOOOX
E[foo*="bar"]‘foo’ 속성의 값에 ’bar’를 포함하는 요소 선택OOOOOOOX
E:root문서의 최상위 루트 요소 선택OOOOOXXX
E:nth-child(n)그 부모의 n번째 자식이 앞으로부터 지정된 순서와 일치하는 E 라면 선택OOOOOXXX
E:nth-last-child(n)n번째 자식이 뒤로부터 지정된 순서와 일치하는 요소가 E 라면 선택OOOOOXXX
E:nth-of-type(n)E 요소 중 앞으로부터 순서가 일치하는 n번째 E 요소 선택OOOOOXXX
E:nth-last-of-type(n)E 요소 중 끝으로부터 순서가 일치하는 n번째 E 요소 선택OOOOOXXX
E:last-childE 요소 중 마지막 자식이라면 E 선택OOOOOXXX
E:first-of-typeE 요소 중 첫번째 E 선택OOOOOXXX
E:last-of-typeE 요소 중 마지막 E 선택OOOOOXXX
E:only-childE 요소가 유일한 자식이면 선택OOOOOXXX
E:only-of-typeE 요소가 같은 타입이면 선택OOOOOXXX
E:empty텍스트 및 공백을 포함하여 빈 자식을 가진 E를 선택OOOOOXXX
E:targetE의 URI의 대상이 되면 선택OOOOOXXX
E:enabled활성화된 폼 컨트롤 E요소 선택OOOOOXXX
E:disabled비활성화된 폼 컨트롤 E요소 선택OOOOOXXX
E:checked선택된 폼 컨트롤(라디오버튼,체크박스)을 선택OOOOOXXX
E:not(s)s가 아닌 E 요소 선택OOOOOXXX
E~FE 요소가 앞에 존재하면 F를 선택OOOOOOOX

<표 1> CSS 버전에 따른 선택자의 종류와 브라우저별 지원여부 – CSS1 – CSS2 – CSS3

::출처 http://www.clearboth.org/css3_1_by_isdn386/


[위키] 데코레이터 패턴

javascript 2012. 12. 27. 13:21 Posted by jiddong

데코레이터 패턴

위키백과, 우리 모두의 백과사전.

데코레이터 패턴(Decorator pattern)이란 주어진 상황 및 용도에 따라 어떤 객체에 책임을 덧붙이는 패턴으로, 기능 확장이 필요할 때 서브클래싱 대신 쓸 수 있는 유연한 대안이 될 수 있다.

목차

  [숨기기

[편집]

[편집]자바

// the Window interface
interface Window {
    public void draw(); // draws the Window
    public String getDescription(); // returns a description of the Window
}
 
 
// implementation of a simple Window without any scrollbars
class SimpleWindow implements Window {
    public void draw() {
        // draw window
    }
 
    public String getDescription() {
        return "simple window";
    }
}

아래의 클래스들은 모든 Window 클래스들의 데코레이터를 포함하고 있다.

// abstract decorator class - note that it implements Window
abstract class WindowDecorator implements Window {
    protected Window decoratedWindow; // the Window being decorated
 
    public WindowDecorator (Window decoratedWindow) {
        this.decoratedWindow = decoratedWindow;
    }
}
 
 
// the first concrete decorator which adds vertical scrollbar functionality
class VerticalScrollBarDecorator extends WindowDecorator {
    public VerticalScrollBarDecorator (Window decoratedWindow) {
        super(decoratedWindow);
    }
 
    public void draw() {
        drawVerticalScrollBar();
        decoratedWindow.draw();
    }
 
    private void drawVerticalScrollBar() {
        // draw the vertical scrollbar
    }
 
    public String getDescription() {
        return decoratedWindow.getDescription() + ", including vertical scrollbars";
    }
}
 
 
// the second concrete decorator which adds horizontal scrollbar functionality
class HorizontalScrollBarDecorator extends WindowDecorator {
    public HorizontalScrollBarDecorator (Window decoratedWindow) {
        super(decoratedWindow);
    }
 
    public void draw() {
        drawHorizontalScrollBar();
        decoratedWindow.draw();
    }
 
    private void drawHorizontalScrollBar() {
        // draw the horizontal scrollbar
    }
 
    public String getDescription() {
        return decoratedWindow.getDescription() + ", including horizontal scrollbars";
    }
}

Window 인스터스를 만드는 테스트 프로그램은 아래와 같다.

public class DecoratedWindowTest {
    public static void main(String[] args) {
        // create a decorated Window with horizontal and vertical scrollbars
        Window decoratedWindow = new HorizontalScrollBarDecorator (
                new VerticalScrollBarDecorator(new SimpleWindow()));
 
        // print the Window's description
        System.out.println(decoratedWindow.getDescription());
    }
}

[편집]C++

#include <iostream>
 
using namespace std;
 
/* Component (interface) */
class Widget {
 
public: 
  virtual void draw() = 0; 
  virtual ~Widget() {}
};  
 
/* ConcreteComponent */
class TextField : public Widget {
 
private:                  
   int width, height;
 
public:
   TextField( int w, int h ){ 
      width  = w;
      height = h; 
   }
 
   void draw() { 
      cout << "TextField: " << width << ", " << height << '\n'; 
   }
};
 
/* Decorator (interface) */                                           
class Decorator : public Widget {
 
private:
   Widget* wid;       // reference to Widget
 
public:
   Decorator( Widget* w )  { 
     wid = w; 
   }
 
   void draw() { 
     wid->draw(); 
   }
 
   ~Decorator() {
     delete wid;
   }
};
 
/* ConcreteDecoratorA */
class BorderDecorator : public Decorator { 
 
public:
   BorderDecorator( Widget* w ) : Decorator( w ) { }
   void draw() {
      Decorator::draw();    
      cout << "   BorderDecorator" << '\n'; 
   }  
};
 
/* ConcreteDecoratorB */
class ScrollDecorator : public Decorator { 
public:
   ScrollDecorator( Widget* w ) : Decorator( w ) { }
   void draw() {
      Decorator::draw(); 
      cout << "   ScrollDecorator" << '\n';
   }  
};
 
int main( void ) {
 
   Widget* aWidget = new BorderDecorator(
                     new ScrollDecorator(
                     new TextField( 80, 24 )));
   aWidget->draw();
   delete aWidget;
}

[편집]C#

namespace GSL_Decorator_pattern
{
        interface IWindowObject
        {
                void draw(); // draws the object
                String getDescription(); // returns a description of the object
        }
 
 
        class ControlComponent : IWindowObject
        {
                public ControlComponent()
                {
                }
 
                public void draw() // draws the object
                {
                        Console.WriteLine( "ControlComponent::draw()" ); 
                }
 
                public String getDescription() // returns a description of the object
                {
                        return "ControlComponent::getDescription()";
                }
        }
 
        abstract class Decorator : IWindowObject
        {
                protected IWindowObject _decoratedWindow = null; // the object being decorated
 
                public Decorator( IWindowObject decoratedWindow )
                {
                        _decoratedWindow = decoratedWindow;
                }
 
                public virtual void draw()
                {
                        _decoratedWindow.draw();
                        Console.WriteLine("\tDecorator::draw() ");
                }
 
                public virtual String getDescription() // returns a description of the object
                {
                        return _decoratedWindow.getDescription() + "\n\t" + "Decorator::getDescription() ";
                }
        }
 
        // the first decorator 
        class DecorationA : Decorator
        {
                public DecorationA(IWindowObject decoratedWindow) : base(decoratedWindow)
                {
                }
 
                public override void draw()
                {
                        base.draw();
                        DecorationAStuff();
                }
 
                private void DecorationAStuff()
                {
                        Console.WriteLine("\t\tdoing DecorationA things");
                }
 
                public override String getDescription()
                {
                        return base.getDescription() + "\n\t\tincluding " + this.ToString();
                }
 
        }// end  class ConcreteDecoratorA : Decorator
 
        class DecorationB : Decorator
        {
                public DecorationB(IWindowObject decoratedWindow) : base(decoratedWindow)
                {
                }
 
                public override void draw()
                {
                        base.draw();
                        DecorationBStuff();
                }
 
                private void DecorationBStuff()
                {
                        Console.WriteLine("\t\tdoing DecorationB things");
                }
 
                public override String getDescription()
                {
                        return base.getDescription() + "\n\t\tincluding " + this.ToString();
                }
 
        }// end  class DecorationB : Decorator
 
        class DecorationC : Decorator
        {
                public DecorationC(IWindowObject decoratedWindow) : base(decoratedWindow)
                {
                }
 
                public override void draw()
                {
                        base.draw();
                        DecorationCStuff();
                }
 
                private void DecorationCStuff()
                {
                        Console.WriteLine("\t\tdoing DecorationC things");
                }
 
                public override String getDescription()
                {
                        return base.getDescription() + "\n\t\tincluding " + this.ToString();
                }
 
        }// end  class DecorationC : Decorator
 
}// end of namespace GSL_Decorator_pattern

[편집]파이썬

class Coffee:
    def cost(self):
        return 1
 
class Milk:
    def __init__(self, coffee):
        self.coffee = coffee
 
    def cost(self):
        return self.coffee.cost() + .5
 
class Whip:
    def __init__(self, coffee):
        self.coffee = coffee
 
    def cost(self):
        return self.coffee.cost() + .7
 
class Sprinkles:
    def __init__(self, coffee):
        self.coffee = coffee
 
    def cost(self):
        return self.coffee.cost() + .2
 
# Example 1
coffee = Milk(Coffee())
print "Coffee with milk : "+str(coffee.cost())
 
# Example 2
coffee = Whip(Milk(Sprinkles(Coffee())))
print "Coffee with milk, whip and sprinkles : "+str(coffee.cost())

[편집]자바스크립트

//Class to be decorated
function Coffee(){
    this.cost = function(){
        return 1;
    };
}
 
//Decorator A
function Milk(coffee){
    this.cost = function(){
        return coffee.cost() + 0.5;
    };  
}
 
//Decorator B
function Whip(coffee){
    this.cost = function(){
        return coffee.cost() + 0.7;
    };
}
 
//Decorator C
function Sprinkles(coffee){
    this.cost = function(){
        return coffee.cost() + 0.2;
    };
}
 
//Here's one way of using it
var coffee = new Milk(new Whip(new Sprinkles(new Coffee())));
alert( coffee.cost() );
 
//Here's another
var coffee = new Coffee();
coffee = new Sprinkles(coffee);
coffee = new Whip(coffee);
coffee = new Milk(coffee);
alert(coffee.cost());


출처 위키 피디아

http://ko.wikipedia.org/wiki/%EB%8D%B0%EC%BD%94%EB%A0%88%EC%9D%B4%ED%84%B0_%ED%8C%A8%ED%84%B4

[위키]팩토리 메서드 패턴

javascript 2012. 12. 27. 13:19 Posted by jiddong

팩토리 메서드 패턴

위키백과, 우리 모두의 백과사전.
UML로 표현된 팩토리 메서드
LePUS3로 표현된 펙토리 메서드

팩토리 메서드 패턴(Factory method pattern)은 객체지향 디자인 패턴이다. 다른 생성 패턴들처럼, 이 패턴도 생성하려는 객체의 클래스를 정확히 지정하지 않으면서 객체를 만드는 문제를 다룬다. 팩토리 메서드 패턴은 이 문제를 객체를 만드는 또 다른 메서드를 정의하여 처리한다. 일반적으로, 팩토리 메서드라는 용어는 객체를 만드는 것이 주 목적인 메서드를 지칭하는데 주로 사용한다.

목차

  [숨기기

[편집]

[편집]C#

Pizza example:

public abstract class Pizza
{
    public abstract decimal GetPrice();
 
    public enum PizzaType
    {
        HamMushroom, Deluxe, Seafood
    }
    public static Pizza PizzaFactory(PizzaType pizzaType)
    {
        switch (pizzaType)
        {
            case PizzaType.HamMushroom:
                return new HamAndMushroomPizza();
 
            case PizzaType.Deluxe:
                return new DeluxePizza();
 
            case PizzaType.Seafood:
                return new SeafoodPizza();
 
        }
 
        throw new System.NotSupportedException("The pizza type " + pizzaType.ToString() + " is not recognized.");
    }
}
public class HamAndMushroomPizza : Pizza
{
    private decimal price = 8.5M;
    public override decimal GetPrice() { return price; }
}
 
public class DeluxePizza : Pizza
{
    private decimal price = 10.5M;
    public override decimal GetPrice() { return price; }
}
 
public class SeafoodPizza : Pizza
{
    private decimal price = 11.5M;
    public override decimal GetPrice() { return price; }
}
 
// Somewhere in the code
...
  Console.WriteLine( Pizza.PizzaFactory(Pizza.PizzaType.Seafood).GetPrice().ToString("C2") ); // $11.50
...

[편집]자바스크립트

Pizza example:

//Our pizzas
function HamAndMushroomPizza(){
  var price = 8.50;
  this.getPrice = function(){
    return price;
  }
}
 
function DeluxePizza(){
  var price = 10.50;
  this.getPrice = function(){
    return price;
  }
}
 
function SeafoodPizza(){
  var price = 11.50;
  this.getPrice = function(){
    return price;
  }
}
 
//Pizza Factory
function PizzaFactory(){
  this.createPizza = function(type){
     switch(type){
      case "Ham and Mushroom":
        return new HamAndMushroomPizza();
      case "DeluxePizza":
        return new DeluxePizza();
      case "Seafood Pizza":
        return new SeafoodPizza();
      default:
          return new DeluxePizza();
     }     
  }
}
 
//Usage
var pizzaPrice = new PizzaFactory().createPizza("Ham and Mushroom").getPrice();
alert(pizzaPrice);

[편집]

출처 위키 피디아 

http://ko.wikipedia.org/wiki/%ED%8C%A9%ED%86%A0%EB%A6%AC_%EB%A9%94%EC%84%9C%EB%93%9C_%ED%8C%A8%ED%84%B4

'javascript' 카테고리의 다른 글

CSS 셀렉터  (0) 2015.03.02
[위키] 데코레이터 패턴  (0) 2012.12.27
[Javascript] IOS WebView Ajax return page call init funtion issue  (0) 2012.09.19
JavaScript-Garden 한글  (0) 2012.08.17
JSDT (Java script 코드 어시스트)  (0) 2012.08.17

Ajax 방식의 하이브리드 어플리케이션을 구현할때

IOS Webview에서 location.href = url; 으로 다른페이지로 이동후 

이전 페이지 재진입시 javascript function이 onload, 등등 호출이 안되는 이슈가 있다.

이유는 캐쉬에 있는 데이터로 데이터로 페이지 재구성됨...

안드로이드는 호출이 되고... ㅠㅠ 


그때 해결방안.

onload 를 쓰지말고 onpageshow 함수를 쓰자. 

onpageshow

script

창이 나타나면 스크립트 실행

  1. <script type="text/javascript">
  2. window.onpageshow = function(){
  3.     initializeView();
  4. }
  5. </script>


page 재진입시 fuction 이 잘 호출된다.

하지만...

각 element 에 등록한 이벤트 핸들러나 리스너 (.on() 이나 .delegate() 등등등 )가 재 등록 되는 이슈가있다. 버튼을 누르면 두번눌림. (Android의 경우)

html 에서 직접 구현한 onclick 함수는 상관이 없다.

아래는 이벤트 함수 .live는 쓰지 맙시다...

$(elements).delegate(selector, events, data, handler);  // jQuery 1.4.3+
$(elements).on(events, selector, data, handler);        // jQuery 1.7+

이벤트 리스너는 JQuery 에 맞는 함수를 쓰자

초기화 호출되는 함수에서 핸들러를 초기화 시켜주자.

  1. var initializeView = function() {
  2.     $(document).off();
  3. .............
  4. }


끝.


'javascript' 카테고리의 다른 글

[위키] 데코레이터 패턴  (0) 2012.12.27
[위키]팩토리 메서드 패턴  (0) 2012.12.27
JavaScript-Garden 한글  (0) 2012.08.17
JSDT (Java script 코드 어시스트)  (0) 2012.08.17
javascript parttern (모듈 패턴!!!!! 꼭알자)  (3) 2012.08.07

JavaScript-Garden 한글

javascript 2012. 8. 17. 19:28 Posted by jiddong

Java Script 를 시작 했다면 꼭보자.

기초 지식은 있어야함!!!!!!


http://bonsaiden.github.com/JavaScript-Garden/ko/

JSDT (Java script 코드 어시스트)

javascript 2012. 8. 17. 19:27 Posted by jiddong


JSDT (Java script 코드 어시스트) 

 인디고 이상 지원 !!!

설치 방법 

1. Eclipse  Help ->   Eclipse Marketplace → 'JSDT' 검색 후 설치

2. 사용할 Dynimic Web Project 를 생성후

JavaScript Resources 에서 properties 열고 

(못 찾을경우!!!)

생선된 project 우클릭 Properties -> JavaScript -> Include Path -> Libraries 

Add JavaScript Libray  버튼 선택

jQuery Library 선택 


이제 코드어시스트를 사용하자



  1. //Parttern 1
  2. var namespace = (function(){
  3.     var namespace = {};
  4.  
  5.     var i  = 0;
  6.  
  7.     function func1(){ //내부 함수
  8.         alert(i);      
  9.     };
  10.     namespace.func2 = function(){ //외부 노출 함수
  11.         alert(i);      
  12.     };
  13.    
  14.     return namespace;
  15. })();
  16.  
  17. //Parttern 2 권장한다 !!!!
  18. var namespace = (function(namespace, $, undefined){
    // $ = jQuery임 전역번수를 지역변수로 전달하면 실행함수내에서 지역변수로 사용                                //하기때문에 탐색작업이 좀더 빨라진다
  19.     var i  = 0;
  20.  
  21.     function func1(){ //내부 함수 private
  22.         alert(i);      
  23.     };
  24.     namespace.func2 = function(){ //외부 노출 함수 public
  25.         alert(i);      
  26.     };
  27.    
  28.     return namespace; //리턴을 해야함 
  29. })(window.namespace || {},jQuery); //객체 없으면 생성
  30.  
  31. //Parttern 3
  32. (function(namespace , $, undefined) {
  33.         var i  = 0;
  34.  
  35.     function func1(){ //내부 함수
  36.         alert(i);      
  37.     };
  38.     namespace.func2 = function(){ //외부 노출 함수
  39.         alert(i);      
  40.     };
  41. })(window.namespace = window.namespace || {}, jQuery);


-- 아래 글은 퍼옴 http://oneblog.thoth.kr/

모듈 (Modules)

여러분이 만든 자바스크립트를 사용하는 어플리케이션들중 얼마나 많은 것들이 아래처럼 파일에 삽입되어 있나요? (HTML 파일이라고 말하지 않은것에 주목. HTML이라면 언급할 가치도 없습니다...)

var someSharedValue = 10;
var myFunction = function(){ //do something }
var anotherImportantFunction = function() { //do more stuff }

이 글을 읽는 시점에, 여러분이 다루는(혹은 만드는) 코드는 대부분 위처럼 되어있을겁니다. 여러분을 비난하려는건 아닙니다. 저도 오래도록 이렇게 코딩했었으니 까요. 이런 코드의 문제점은 여러가지가 있습니다만 여기서는 전역 네임스페이스를 지저분하게 만들어 버린다는 것에 집중해 봅시다(역자주: 전역 네임스페이스는 소스코드내의 모든 영역에서 참조가 가능하기 때문에, 여러 소스를 함께 로드할 경우 전역 변수가 같은 이름을 가지면 소스코드가 맛이 갑니다.. 가요). 이렇게 코드를 짜면 모든 메서드와 변수가 전역 네임스페이스에 들어가기 때문에 얘네를 전역 변수에서 걷어낼 필요가 있는데, 여기에 사용되는것이 '모듈 패턴' 입니다. 모듈은 여러가지 모습으로 만들수 있지만 쉬우면서도 요새 유행하는 방법이 IIFE(Immediately Invoked Founction Expression: 선언과 동시에 실행되는 함수 표현) 입니다.

이름은 길고도 거창하지만, 코드로 써보면 간단합니다.
(function(){
    //do some work
})();

IIFE를 이전에 써본적이 없는 분들은, '뭐 이렇게 생겨먹은 코드가 다있나...' 하실 겁니다. 이 코드에는 괄호가 많이 나와 혼란스러울수 있는데, 기본적으로는 익명함수(anonymous function)와 그 뒤에 () 로 함수를 실행하는 부분으로 이루어져 있습니다. 즉 함수 선언 + 실행이 한번에 이루어 지는것이죠. 그래서 "Immediately invoke function"가 IIFE라는 이름에 포함되어있는것이고, 나머지 "expression" 부분은 이 코드속의 함수가 익명함수이므로 statement가 아닌 expression에 해당됨을 의미합니다. (역자주: statement 와 expression은 여러가지 차이점이 있는데, 여기서는 expression이 모여서 statement 가 되고, 세미콜론으로 한 문장을 완성해야 statement 가 된다 정도로 알고 넘어가면 될듯 합니다. 또한 함수가 statement 가 되려면 이름을 가져야 합니다). 이 과정은 익명함수 겉에 ()로 감싸주는 부분때문에 가능합니다. 또한 이런 표현 (함수 선언 밖에 ()로 감싸는 것) 때문에 IIFE 방식이 코드에 사용되었다는것을 쉽게 알아볼 수 있습니다.

이제 구현방법을 알았으니, 이걸 왜 쓰는지도 알아봅시다. 자바스크립트에서는 scope를 사용하기 위해서는 함수를 써야 합니다 (역자주: scope는 변수의 접근 제한 단위이며, 자바스크립트는 함수 단위로 scope를 구분합니다). IIFE방식으로 실행된 익명함수는 그 자체로 scope를 제한하게 됩니다. 따라서 전역 네임스페이스를 건드리지 않게 되지요. 다만, 익명함수 안에서 사용하는 모든 변수의 scope가 그 함수 내부로만 제한되어서, 함수 밖에서 접근하려면 전역 네임스페이스와의 연결고리를 만들어주어야 합니다.

이를 위한 가장 간단한 방법중에 하나는 window 오브젝트를 함수에 파라미터로 넘겨주고, 그 함수 안에서 변수나 메서드를 window 오브젝트에 연결 해줘서 함수 외부에서도 실행이 가능하게 하는것입니다. (역자주: window 오브젝트는 글로벌 오브젝트로써 자바스크립트에서는 최상위 오브젝트 입니다. 여기에 값이나 함수를 할당하면 당연히 전역 변수 혹은 함수가 됩니다). window 변수가 꼬이는것을 방지하기 위해, window 객체를 명시적으로 파라미터로 넘겨줍니다. 다른 라이브러리들의 레퍼런스나 심지어 'undefined' 값도 이렇게 넘겨줄 수 있습니다. 예를들면 이런 형태가 되겠군요.

(function(window, $, undefined){
    //do some work
})(window, jQuery);

보시다 시피, window 와 jQuery($) 를 파라미터로 넘겨주고 있지만, 함수에는 3개의 파라미터를 받고 있습니다. 그 이유는, 내부의 익명함수를 실행할때 3번째 파라미터를 넘겨주지 않았기 때문에, 다른 모듈에서 'undefined' 라는 변수의 값을 변경해도, 적어도 이 모듈 안에서는 undefined값을 가지도록 보장하기 위함입니다. (역자주: 자바스크립트에서는 undefined가 primitive 값의 한 종류 입니다). 자바스크립트에는 클로저라는 개념이 있어서, 함수가 정의될때 그 함수 외부의 scope를 참조할수 있도록 자동으로 매핑이 되기 때문에, 위의 경우 undefined 같은 글로벌 변수를 파라미터로 넘기지 않아도 함수 내부에서 참조가 가능합니다. 클로저라는 개념은 따로 글을 하나 써야 할만큼 길기 때문에 저자의 다른글(http://www.codethinked.com/c-closures-explained) 을 참조하기 바랍니다.

이제 여러분은 window, $, undfined 변수를 보다 안전하게 사용할수 있는 즉시 실행된 메서드를 작성 할수 있게 되었습니다. (물론 이 메서드가 실행되기전에 이런 변수들 값이 바뀔 위험은 여전히 있지만, 그래도 비교적 안전할것입니다). 이제 여러분은 전역 네임스페이스를 보다 깔끔하게 만들수 있고, 다른 자바스크립트 모듈과의 간섭이 생갈 가능성을 많이 줄이게 되었습니다.

남은건 window 오브젝트에 모듈을 연결 해주는것 뿐입니다. 하지만 저는 모듈을 직접 window 오브젝트에 연결하는것 보다는 체계적으로 연결이 되는 기능을 만드는것이 좋다고 생각합니다. 대부분의 컴퓨터 언어에서는 이걸 네임스페이스라 하고, 자바스크립트의 오브젝트개념을 이용하여 흉내내보겠습니다.

네임스페이스 (Namespaces)

네임스페이스를 선언하고 함수를 연결해 주기 위해서는 아마 이렇게 많이 할겁니다.

window.myApp = window.myApp || {};
window.myApp.someFunction = function(){
    //so some work
};

이건 단지 이미 같은 이름으로 생성된 오브젝트가 있나 보고 없으면 {} 표현을 사용해서 새 오브젝트를 만들어 주는 정도 입니다. 하지만 이 코드 처럼 네임스페이스를 만드는 것 보다는, 위에서 작성한 모듈방식을 활용해 보죠. 이렇게 말이죠.

(function(myApp, $, undefined){
    //do some work
}(window.myApp = window.myApp || {}, jQuery));

혹은 이렇게도 가능합니다.

window.myApp = (function(myApp, $, undefined){
    //do some work
    return myApp;
})(window.myApp || {}, jQuery);

이제 window 오브젝트를 모듈에 넘겨주는 대신, 윈도우 오브젝트에서 파생된 네임스페이스 오브젝트를 넘겨 주게 되었습니다. || 표현을 쓴 이유는 여러 소스에서 같은 네임스페이스를 쓸 경우 새로운 오브젝트를 매번 만들지 않도록 하기 위함입니다. 많은 라이브러리들이 네임스페이스 함수를 제공하고 있으며, namespace.js(https://github.com/maximebf/Namespace.js) 를 쓰는것도 좋은 방법입니다. 또한 네임스페이스는 너무 여러 depth로 중첩되지 않도록 하는것이 좋습니다. 예를들어 "doSometing"이라는 메서드를 "MyApp.MyModule.MySubModule"라는 네임스페이스 하위에 추가한다면, 이 메서드를 쓰기위해선 아래처럼 길게 써야겠죠

MyApp.MyModule.MySubModule.doSomething();

매번 이렇게 사용하기 힘들며 아래처럼 변수에 붙여서 쓸수는 있습니다.

var MySubModule = MyApp.MyModule.MySubModule;

이렇게 하면 "MySubModule.doSomething()" 정도로 호출이 가능하죠. 하지만 왠만큼 대규모의 코드를 짜는게 아니라면 이렇게 여러번 중첩된 네임스페이스를 안쓰는게 좋습니다.

노출식 모듈 패턴 (Revealing Module Pattern)

모듈을 만들다 보면 노출식 모듈 패턴이라 불리는 아래 방식을 자주 보게 됩니다. 이 패턴은 모듈 생성 방식의 하나로써, 모듈 내부에서 모든 값들을 처리한 다음, 외부에 공개하고 싶은 변수와 메서드에 대해서만 레퍼런스 오브젝트를 리턴 해주는 것입니다. 아래 코드를 보면 어떻게 사용되는지 알 수 있을 겁니다.

var myModule = (function($, undefined){
    var myVar1 = '',
    myVar2 = '';
    var someFunction = function(){
        return myVar1 + " " + myVar2;
    };
    return {
        getMyVar1: function() { return myVar1; }, //myVar1         public getter
        setMyVar1: function(val) { myVar1 = val; }, //myVar1 public setter
        someFunction: someFunction //some function made public
    }
})(jQuery);

보시다시피, 모듈 생성이 간단하게 한번에 이루어 집니다. 그리고 이 모듈 생성 방식으로 인해 private 변수는 내부에 숨겨지고, 외부에 노출하고 싶은 일부 내용만 오브젝트 형식으로 리턴되고 있습니다. 결국 "myModule"라는 변수에 대입되어, 이 변수는 두개의 public 메서드를 가지게 되지만, 내부에 있는 "someFunction"은 priviate 변수인 "myVal2"같은것에 접근이 가능합니다.

생성자 만들기 (Creating Constructors: Classes)

자바스크립트에는 클래스가 없지만, 오브젝트 생성시의 생성자 함수를 통해 구현이 가능합니다. 'Person' 오브젝트를 여러개 생성한다고 해 봅시다. 생성시에는 이름과 성, 나이를 파라미터로 넘겨줄수 있도록 하겠습니다. 아마 이런 형태의 생성자가 될것입니다. (역자주: 여기서 글쓴이가 말하는 생성자가 곧 클래스를 의미합니다)

var Person = function(firstName, lastName, age){
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
}

Person.prototype.fullName = function(){
    return this.firstName + " " + this.lastName;
};

둘중 위쪽 함수는 'Person' 의 생성자 입니다. 이걸로 새로운 'Person' 오브젝트 생성할수 있습니다. 이때 3개의 파라미터가 넘어가는데, 생성자가 실행되면서 자연스럽게 변수에 입력이 됩니다. 이렇게 생성된 변수는 public 변수가 됩니다. 생성자 내부에 따로 로컬 변수를 생성하면 private변수로 사용이 가능하지만, public 메서드에서 접근이 불가능해지므로 일단 모두 public 변수로 만들어 둡니다. 사실 생성자 내부에 public 메서드를 만들면 그 메서드는 private변수에 접근이 가능하긴 해도 또 다른 문제가 있습니다.

그다음의 두번째 함수쪽을 보면 "prototype"을 통해 'person'오브젝트의 생성자에 접근하고 있습니다. "prototype" 오브젝트는 어떤 함수든 인스턴스가 생성되면, 그 인스턴스들에게 연결되어서 해당 함수의 변수나 메서드에 접근할때 가장 먼저 접근하는 수단이 됩니다. 따라서 여기서 "fullName" 이라는 메서드를 만들면, 'Person' 인스턴스를 만들때 따로 "fullName"이라는 메서드를 만들어 주지않아도 모든 'Person'의 인스턴스에서 사용이 가능합니다. 생성자 내부에서 "this.fullName = function() { ... }"같은 방식으로 "fullName"같은 메서드를 생성자 내부에서 만들 수도 있긴 하지만 이렇게 하면 'Person'의 인스턴스를 만들때마다 "fullName"함수도 사본이 만들어지게되어서 좋지 못한 방법입니다.

이제 'Person'의 인스턴스를 생성해 보겠습니다.



var person = new Person("Justin", "Etheredge");
alert(person.fullName());

원한다면, 'Person' 생성자에서 상속을 한 새로운 생성자를 만들수도 있습니다. 'Spy'라는 생성자를 만들고, 거기에 메서드를 하나 추가해 보겠습니다.

var Spy = function(firstName, lastName, age){
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
};
Spy.prototype = new Person();

Spy.prototype.spy = function(){
    alert(this.fullName() + " is spying.");
}

var mySpy = new Spy("Mr.", "Spy", 50);
mySpy.spy();

보시다시피 'Person'과 똑같은 모습의 생성자를 만들었습니다. 다만 'Spy'의 prototype에 'Person'의 생성자를 연결해 주었습니다. 그리고 거기에 'spy' 메서드를 추가한 다음 'Spy'의 인스턴스를 하나 생성해 주었습니다. 이 메서드는 'Spy'의  'Person'의 public 메서드에 접근이 가능하며, 'Person'의 메서드들 또한 'Spy' 인스턴스의 변수들에 접근이 가능합니다. 다소 복잡한 감이 있지만, 큰 틀에서 보면 굉장히 멋진 방법이 아닐수 없습니다.

엮어 보기 (Wrapping it up)

이 글을 여기 까지 읽은 여러분이 뭔가를 배웠다면 좋겠지만, 이걸로는 최신 자바스크립트 개발이라는 경지에 이르렀다고 보기는 어렵습니다. 여기에 소개된 주제들은 이미 몇년이상 사용된 비교적 낡은 기법들이니까요. 하지만 적어도 고수가 되기 위한 길에 한발을 내딛었다고 볼수는 있습니다. 여기서 배운 기법을 바탕으로 여러분이 만드는 코드를 모듈화 해서 여러 파일로 나눠 보십시오. 그 다음엔 자바스크립트의 결합(combination)과 경량화(minification)에 대해 공부할 차례입니다. 여러분이 만약 Rails 개발자이고 Rails3을 쓴다면 이 두가지를 쉽게 한번에 해결가능 할것입니다. 그외에 .NET 개발자라면 제가 시도해봤던 SquishIt(https://github.com/jetheredge/SquishIt)을 활용할수도 있을것입니다. 그외에 ASP.NET MVC4 를 사용한다면, 내장된 결합과 경량화 지원 기능이 있을것입니다.

끝으로 이글이 도움이 되었기를 바라며, 다음 글에서 또 다른 최신 자바스립트 개발에 관한 주제로 만날수 있기를 바랍니다.


'javascript' 카테고리의 다른 글

[위키]팩토리 메서드 패턴  (0) 2012.12.27
[Javascript] IOS WebView Ajax return page call init funtion issue  (0) 2012.09.19
JavaScript-Garden 한글  (0) 2012.08.17
JSDT (Java script 코드 어시스트)  (0) 2012.08.17
java split 공백  (1) 2012.01.03

java split 공백

javascript 2012. 1. 3. 17:17 Posted by jiddong

스플릿 사용시 공백데이터를 주의해야한다. 

공백데이터를 스플릿으로 나눌시 데이터 갯수가 맞지 않음

제일 마지막에 오는 요소의 값이 없을 경우 그 요소를 무시하도록 되어 있음



StringTokenize


구분자 사이에 분해할 요소의 값이 존재하지 않으면 무시
완전하게 모든 요소의 값이 존재하는 경우라면 사용을 해도 되겠지만
가변적인 데이터라면 사용하기 꺼림직함

 

String.split(string text, int limite)

limit를 저정 하지 않았을 경우에는
제일 마지막에 오는 요소의 값이 없을 경우 그 요소를 무시하도록 되어 있음
  
limit를 지정 했을 경우 해당 숫자만큼만 분해.

limit는 분해를 한 후 얻고자 하는 String[]의 크기라고 보시면 됩니다.

limit가 분해하고자 하는 요소의 개수와 같거나 클 경우 배열의 개수만큼의 String[]을 되돌려 주지만, 요소의 개수보다 작을 경우 지정한 숫자만큼의 String[]으로 되돌려 줌

아래관련
소스들을 보시면 이해가능


관련 소스





  1.         public static void main(String[] args) {
  2.                 String recode = "a-b-c-d-e-f";
  3.                 String[] values = recode.split("-");
  4.                    System.out.print("length ::"+values.length + "\n");
  5.                                  
  6.                   for(int i=0 ; i<values.length ; i++) {
  7.                    System.out.print("values["+i+"]::["+values[i]+"]\n");
  8.                   }
  9.  
  10.         }
  11.        
  12.         //출력값
    스플릿된 갯수 만큼 length 가 나오고 있음
  13. length ::6
    values[0]::[a]
    values[1]::[b]
    values[2]::[c]
    values[3]::[d]
    values[4]::[e]
    values[5]::[f]

  14.  
  15. }

  1.         public static void main(String[] args) {
  2.                 String recode = "a-b-c-d-e-f--------"; 데이터가 없다면!!!!????
  3.                 String[] values = recode.split("-"); 리미트값 없음
  4.                    System.out.print("length ::"+values.length + "\n");
  5.                                  
  6.                   for(int i=0 ; i<values.length ; i++) {
  7.                    System.out.print("values["+i+"]::["+values[i]+"]\n");
  8.                   }
  9.  
  10.         }
  11.         
    split()함수에 Limite 값이 없기 때문에 값이 없는 데이터는 무시됨
    스플릿된 갯수 만큼 length 가 나오고 있음

    length ::6

  12. values[0]::[a]
    values[1]::[b]
    values[2]::[c]
    values[3]::[d]
    values[4]::[e]
    values[5]::[f]

  13.  
  14. }
 
  1.         public static void main(String[] args) {
  2.                 String recode = "a-b-c-d-e-f--------";
  3.                 String[] values = recode.split("-", 20); 리미트 값이 생겨땅!!!
  4.                    System.out.print("length ::"+values.length + "\n");
  5.                                  
  6.                   for(int i=0 ; i<values.length ; i++) {
  7.                    System.out.print("values["+i+"]::["+values[i]+"]\n");
  8.                   }
  9.  
  10.         }
  11.         
    split()함수에 limite 값이  있 기  때문에 값이 없는 데이터와 토큰뒤도 또한 스플릿데된 데이터로 나옴
    스플릿된 갯수 만큼 length 가 나오고 있음

    length ::14

  12. length ::14
    values[0]::[a]
    values[1]::[b]
    values[2]::[c]
    values[3]::[d]
    values[4]::[e]
    values[5]::[f]
    values[6]::[] //공백도 데이터로 본다 리미트가 있다면
    values[7]::[]
    values[8]::[]
    values[9]::[]
    values[10]::[]
    values[11]::[]
    values[12]::[]
    values[13]::[]


  13.  
  14. }
  

  1.         public static void main(String[] args) {
  2.                 String recode = "a-b-c-d-e-f- - - - - - - -"; 공백을 넣었당
  3.                 String[] values = recode.split("-");
  4.                    System.out.print("length ::"+values.length + "\n");
  5.                                  
  6.                   for(int i=0 ; i<values.length ; i++) {
  7.                    System.out.print("values["+i+"]::["+values[i]+"]\n");
  8.                   }
  9.  
  10.         }
  11.        

    split()함수에 Limite 값이 없기 때문에 마지막 토큰뒤에 값이 없는 데이터는 무시됨
  12. 스플릿된 갯수 만큼 length 가 나오고 있음

    length ::13 
    13 이 나오는 이유는 마지막 토큰 뒤에 데이터가 없기 때문에 스플릿이 제외됨
  13. values[0]::[a]
    values[1]::[b]
    values[2]::[c]
    values[3]::[d]
    values[4]::[e]
    values[5]::[f]
    values[6]::[ ]
    values[7]::[ ]
    values[8]::[ ]
    values[9]::[ ]
    values[10]::[ ]
    values[11]::[ ]
    values[12]::[ ]

  14.  
  15.  
  16. }


  1.         /**
  2.          * @param args
  3.          */
  4.         public static void main(String[] args) {
  5.                 String recode = "a-b-c-d-e-f- - - - - - - -";
  6.                 String[] values = recode.split("-"20);
  7.                    System.out.print("length ::"+values.length + "\n");
  8.                                  
  9.                   for(int i=0 ; i<values.length ; i++) {
  10.                    System.out.print("values["+i+"]::["+values[i]+"]\n");
  11.                   }
  12.  
  13.         }
  14.       
    split()함수에 Limite 값이 있기 때문에 마지막토큰 뒤에도 데이터가 있는것으로 간주함
  15. length : 14

  16.   
  17. length ::14
    values[0]::[a]
    values[1]::[b]
    values[2]::[c]
    values[3]::[d]
    values[4]::[e]
    values[5]::[f]
    values[6]::[ ]
    values[7]::[ ]
    values[8]::[ ]
    values[9]::[ ]
    values[10]::[ ]
    values[11]::[ ]
    values[12]::[ ]
    values[13]::[]

  18.  
  19.  
  20. }