NOTICE 
Scripter/JAVASCRIPT 에 해당하는 글 : 28 개
2008/04/15 :: HTML include하기
2008/03/06 :: Browser detect
2008/03/06 :: IE minimize
올바른 성장과 따뜻한 나눔이 있는 넥스트리
가끔씩 Ajax 웹어플리케이션을 만들다 보면 단축키를 요구하는 고객들이 많다.
그러한 이유로 단축키 관련 스크립트를 찾아보던중에 prototype el.observe() (extjs에서는 el.on())를 이용한 keycode를 바인딩해주는
스크립트를 찾았다.

얼마전에 ajaxian post에 올라왔던 글이였는데 잊고 있었던거.. ㅡ.,ㅡ;
잠시 꼬불쳐 두다... 키값 참조할때도 좋겠다.

참조URL , 샘플URL

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/scriptaculous/1.8.1/scriptaculous.js"></script>
<script type="text/javascript" >
var Key = {

// -- Alphabet
  A: 65,
  B: 66,
  C: 67,
  D: 68,
  E: 69,
  F: 70,
  G: 71,
  H: 72,
  I: 73,
  J: 74,
  K: 75,
  L: 76,
  M: 77,
  N: 78,
  O: 79,
  P: 80,
  Q: 81,
  R: 82,
  S: 83,
  T: 84,
  U: 85,
  V: 86,
  W: 87,
  X: 88,
  Y: 89,
  Z: 90,

  a: 97,
  b: 98,
  c: 99,
  d: 100,
  e: 101,
  f: 102,
  g: 103,
  h: 104,
  i: 105,
  j: 106,
  k: 107,
  l: 108,
  m: 109,
  n: 110,
  o: 111,
  p: 112,
  q: 113,
  r: 114,
  s: 115,
  t: 116,
  u: 117,
  v: 118,
  w: 119,
  x: 120,
  y: 121,
  z: 122,

// -- Special Keys
  BACKSPACE: 8,
  TAB: 9,
  ENTER: 13,
  ESCAPE: 27,
  END: 35,
  HOME: 36,
  ARROW_LEFT: 37,
  ARROW_UP: 38,
  ARROW_RIGHT: 39,
  ARROW_DOWN: 40,
  DELETE: 46,
  QUESTION_MARK: 63

};

/*
 * Tie into ? and ESCAPE
 */
document.onkeypress = function(e) {
    if (e.charCode == Key.QUESTION_MARK) {
        KeyBindingsHUD.toggle();
    } else if (e.keyCode == Key.ESCAPE) {
        KeyBindingsHUD.hide();
    } else {
        KeyBindings.actionForKey(e);
    }
}

var KeyBindings = (function() {
    var bindings = {};

    var findNumber = function(key) { // get the name of the key from the charCode
        for (var name in Key) {
            if (Key[name] == key) {
                return name;
            }
        }
    }

    return {
        add: function(binding) {
            if (typeof binding.keys == "string") { // short circuit for non-arrays
                binding.keys = [ binding.keys ];
            }
            bindings[binding.eventname] = binding;
        },

        remove: function(eventname) {
            bindings[eventname] = undefined;
        },

        html: function() {
            var html = [];

            for (var key in bindings) {
                if (bindings.hasOwnProperty(key)) {
                    var binding = bindings[key];
                    var keys = binding.keys.collect(function(key) {
                        return Object.isNumber(key) ? findNumber(key) : key;
                    });
                    html.push(keys.join(', ') + ': ' + binding.description);
                }
            }

            return html.join('<br/>');
        },

        actionForKey: function(e) {
            for (var action in bindings) {
                if (bindings.hasOwnProperty(action)) {
                    var keys = bindings[action].keys;
                    keys.each(function(key) {
                        if (e.charCode == 0) {
                            if (e.keyCode == key) {
                                document.fire(action, e);
                                throw $break;
                            }
                        }
                        if (String.fromCharCode(e.charCode) == key) {
                            document.fire(action, e);
                            throw $break;
                        }
                    });
                }
            }
        },

        caseInsensitive: function(keys) {
            if (typeof keys == "string") keys = [ keys ]; // array wrap
            var newArray = [];
            keys.each(function(c) {
               newArray.push(c, c.toUpperCase());
            });
            return newArray;
        }
    }
})();

/*
 *
 */
var KeyBindingsHUD = (function() {
    var isShown = false;
    var headerId = '_keybindings_header';

    return {
        toggle: function() {
          (isShown) ? this.hide() : this.show();
        },
        show: function() {
            if (!isShown) {
                var header = $(headerId);
                if (!header) {
                    header = this.createElement();
                }
                header.innerHTML = KeyBindings.html();
                header.blindDown({duration: 0.2});
                isShown = true;
            }
        },
        hide: function() {
            if (isShown) {
                $(headerId).blindUp({duration: 0.2});
                isShown = false;
            }
        },
        createElement: function() {
            var header = document.createElement('div');
            header.id = headerId;
            header.align = 'center';
            header.style.display = 'none';
            header.style.width = '100%';
            header.style.backgroundColor = '#111111';
            header.style.color = '#eeeeee';
            header.style.fontSize = '10pt';
            header.style.paddingTop = '4px';
            header.style.paddingBottom = '4px';
            header.style.borderBottom = '1px solid #333';

            var body = document.body;
            body.insertBefore(header, body.firstChild);

            return $(headerId);
        }
    }
})();




KeyBindings.add({
   eventname: 'action:move-up',
   keys: ['p', Key.ARROW_UP ],
   description: "Move up the stack"
});

KeyBindings.add({
   eventname: 'action:move-down',
   keys: ['n', Key.ARROW_DOWN ],
   description: "Move down the stack"
});

document.observe('action:move-up', function(e) {
    alert(1)
});

document.observe('action:move-down', function(e) {
    alert(2);
});

</script>


소스다운로드 :




이올린에 북마크하기(0) 이올린에 추천하기(0)
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback :: http://techbug.tistory.com/trackback/120
올바른 성장과 따뜻한 나눔이 있는 넥스트리


자바스크립트 최적화하기 코드는 웹상에서 비법을 전수해 주는 사이트는 많이 있다.
sun.com의 frontend 개발자인 Gregory Reimer는 다음과 같이 HTML 콜렉션 반복문을 추천해 주었다. (난 왜 이런 생각을 못하지?? ㅡ.,ㅡ;)

// looping a dom html collection
for (var i=0, node; node = hColl[i++];) {
    // do something with node
}


var i = arr.length; while (i--) {}

나름대로 장단점은 있겠지만 속도면에서는 월등히 뛰어나다는게 그의 블로그에 벤치마킹결과로 나타나 있다.

참고적으로 다음 사이트들도 한번 봐두길...



이올린에 북마크하기(0) 이올린에 추천하기(0)
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback :: http://techbug.tistory.com/trackback/115
올바른 성장과 따뜻한 나눔이 있는 넥스트리
유지보수의 용이성과 JSDOC으로 API를 추려내기 위해서 다음과 같이 자바스크립트 코딩하시기 바랍니다.


1. 페이지 상단 파일설명
/**
 * @fileoverview 테이블소트 클래스로 Javascript만으로 테이블을 소트한다.
 * @author 데꾸벅
 * @version 0.1
 * @since 2008.06.11
 */


2. 클래스 및 메쏘드 설명
/**
 *  테이블 소트 클래스
 * @class 테이블 소트 클래스로 Javascript만으로 테이블을 {@link http://sourceforge.net/projects/jsdoc JSDoc} 소트한다.
 * @constructor
 * <code>var sortTable = new SortTableClass("tblSort",true,'img','images/button/bts_down.gif','images/button/bts_downon.gif');</code>
 * @param {string} sTableID 소팅할 테이블의 아이디
 * @param {string} isReverse 오름차순,내림차순 가능여부
 * @param {string} markType 이미지나 마크처리 (예: 'txt', 'img')
 * @param {string} defaultMark 기본마크
 * @param {string} descMark 내림차순일때 마크
 * @param {string} ascMark 오름차순일때 마크
 * @throws
 * @author 데꾸벅
 * @since 2008.06.11
 */


 

  • @class : 클래스설명을 기술한다.
    @constructor : 생성자일때만 표기
    @param : 인자값들을 표기한다.
                  표기방법 : @param {타입} 인자명 인자설명
                  표기예 : @param {int} tableLength 테이블의 갯수
    @throws : 예외처리에 대해 기술한다.
    @extends : 상속
    @author : 작성자
    @version : 버전
    @since : 작성일
    @see : 참조
          표기방법 : @see 참조문서
          표기예 : @see #generateTableMethod  -> 현재 클래스의 generateTableMethod참조
                      @see sortTable.generateTableMethod
     @link : API문서에 링크걸때 표기
          표기방법 : {@link 링크할주소 링크표시}              

    @type : 메쏘드 타입
    @return : 반환값 있을 경우 (반환값이 한개일때 경우 )
    @returns : 반환값 있을경우 (반환값이 여러개일 경우)

    그외 : 각 설명(description)에는 HTML Tag로 표기하되 스타일시트가 없는 형태로 넣는다



3. 클래스 변수 및 메쏘드 변수표기

 /***소팅한 컬럼 저장 */
 this.tmpSortICol = "";

 /*** 초기(내림차순) 정렬방식 저장 */
 this.tmpADESC = "desc";

 /*** 소팅한 테이블의 아이디 */
 this.sTableID = sTableID;

 /*** 오름차순,내림차순 가능여부 */
 this.isReverse = (isReverse!=null) ? isReverse : false;

 /*** 이미지나 마크처리 */
 this.markType = (markType !=null) ? markType : null ;

 /*** 기본마크 */
 this.defaultMark = (defaultMark !=null) ? defaultMark : '▽';

 /*** 내림차순일때 마크 */
 this.descMark = (descMark !=null) ? descMark : '▼';

 /*** 오름차순일때 마크 */
 this.ascMark = (ascMark !=null) ? ascMark : '▲';

표기법 참조 문서 (첨부파일참조) :




위와 같이 해주시면 다음과 같이 유지보수시 다음 사용자가 쉽게 해당 메쏘드나 클래스를 사용할수 있도록 API문서로 도출이 가능합니다.

사용자 삽입 이미지
사용자 삽입 이미지
사용자 삽입 이미지

JSDOC 사용법은 http://jsdoc.sourceforge.net/ 을 참조하세요




자바스크립트 명명법

자바스크립트 파일명명법은 java,jsp 파일명과 동일하게 camel 표기법으로 명명한다.

주의사항 :
    - 다른 파일냉의 동일한 메쏘드명으로 작성하지 않는다.
    - js 파일은 항상 인코딩 타입을 euc-kr (ms949 ascii)타입으로 코딩하되  파일자체가 Ajax를 통해 불러오는 페이지의
      경우는 반드시 UTF-8 형태로 작성한다. (<script type="text/javascript" src="흠.js" charset="euc-kr"></script>)
    - 각 비즈니스(여기서는 메뉴)별 스크립트를 나누어 작성하되 필요한 경우에만 불러 사용한다.
    - 공통 클래스는 클래스임을 표기하여 준다. (sortTableClass.js)
    - 해당 비즈니스(여기서는 메뉴)에만 전용으로 쓰는 스크립트가 많다면 비즈니스명으로 폴더링한다.


표준 자바스크립트 사용

객체 접근은 cross-browser를 지원하는 표준 메쏘드나 프로퍼티를 사용한다.
1. document.all 보다는 document.getElementById, document.getElementsByName 등으로 접근한다.
2. eval은 되도록이면 자제하도록한다.
3. 객체가 create되면 반드시 destory할때 null처리를 한다.
4. try~ catch~throws 문은 필요한 부분에서만 사용한다.


AJAX사용시 Callback함수 표기방법 (jQuery기준)

1. 기본표기법 : 해당 메쏘드를 XHR 형태와 혼합해서 쓰는경우

$.getJSON(
 "http://localhost:8080/BetmanWeb/cartGetSportsLottery.so",
 { gameId: "G015", gameRound: "1553", memberId: "200804474628" },
 function(json) {
  $("#result").html(json.length);
 }

);

2. Callback함수 별도지정 : Callback함수를 공통으로 사용하는 경우

$.getJSON(
 "http://localhost:8080/BetmanWeb/cartGetSportsLottery.so",
 { gameId: "G015", gameRound: "1553", memberId: "200804474628" },
 callbackFunc
);  <-- 주의: 인자값이 들어가 있지 않습니다. (closure 문제발생)

//콜백함수는 반드시 호출한 함수의 바로 밑에서 시작합니다.

function callbackFunc(json){  <-- 인자값이 들어가 있습니다. (자바스크립트의 유연성을 이용-closure
 //blah blah blah~ ^^
}


 

참고사이트

  1. Mozilla Developer Center: Core JavaScript 1.5 Reference Manual
  2. Yahoo UI개발자인 Douglas Crockford's JavaScript
  3. Yahoo Developer Network : YUI Theater  ( 더글라스 크록포드의 동영상 강의 수록)
  4. Peter-Paul Koch의 QuirksMode
  5. http://home.cogeco.ca/~ve3ll/jstutor0.htm
  6. 모질라 개발자 사이트 (DOM Reference)
  7. koxo.com <-- 누구신지 대단하죠?
    두곳만 알아도.. 대단.. 쿨럭~~


그외 볼만한 사이트

  1. JavaScript: The Definitive Guide by David Flanagan
  2. Pro JavaScript Techniques by John Resig
  3. Ajax and REST Recipes by Christian Gross
  4. ppk on JavaScript by Peter-Paul Koch
  5. Professional JavaScript for Web Developers by Nicholas C. Zakas
  6. Ajax Patterns and Best Practices by Christian Gross
  7. Dynamic HTML by Danny Goodman
  8. Head First Design Patterns by Freeman & Freeman

OO JavaScript 참조사이트

  1. How to achieve private, public, and privileged members in JavaScript, by Dustin Diaz.
    : Method scoping에 대한 좋은 설명
  2. OOP in JS, Part 1 : Public/Private Variables and Methods, by Gavin Kistner.
    : Scoping 및 prototyping에 대한 샘플
  3. A JavaScript Module Pattern, by Eric Miraglia in YUI Blog.
    : 더글라스 크록포드가 얘기한 module pattern에 대한 설명
  4. Again with the Module Pattern - reveal something to the world, by Christian Heilmann.
    : 모듈패턴
  5. JavaScript for Object-Oriented Programmers (Appendix B of the book AJAX in Action).

DOM









 
이올린에 북마크하기(0) 이올린에 추천하기(0)
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback :: http://techbug.tistory.com/trackback/110
올바른 성장과 따뜻한 나눔이 있는 넥스트리

IE5에서 첫선을 보인 객체.getBoundingClientRect는 객체의 offset의 top, left,width,height를 반환하는 멋진놈이다.
일반적으로 gecko 엔진을 사용하는 FF2에서는 getBoxObjectFor(객체)를 사용했으나
FF3에서는 getBoxObjectFor()가 없어지고 getBoundingClientRect가 생겨났다.

FF3가 출시되자 마자 기존 스크립트들을 많이 바꾸고 있는데 이중에 getBoundingClientRect가 포함되었다.
드디어 FF도 IE의 손을 들어준것인가? IE8에서는 얼마만큼 오픈소스진영의 손을 들어줄것인지 귀추가 주목된다.

Mozilla사이트의 getBoundingClientRect에 관련된 Reference 참조

사용자 삽입 이미지
John Resig의 getBoundingClientRect is Awesome 포스트 참조

데꾸벅이 사용하는 객체의 offset left,top,width, height반환하는 함수
/**
 * tag 객체의 위치값 및 너비/높이값을 반환한다.
 * @param {objId} DOM객체 : document.getElementById()
 * @return {ret} left,top,width,height 를 반환한다.
 * @author 데꾸벅
 */
function getBoundsObject(objId){
    var techbug = new Object();
    var tag = document.getElementById(objId);

    if(tag !=null && tag != undefined ){
        if(tag.getBoundingClientRect){ //IE, FF3
            var rect = tag.getBoundingClientRect();
            techbug.left = rect.left + (document.documentElement.scrollLeft || document.body.scrollLeft);
            techbug.top = rect.top + (document.documentElement.scrollTop || document.body.scrollTop);
            techbug.width = rect.right - rect.left;
            techbug.height = rect.bottom - rect.top +1; // +1 = Moz와 맞춤
        } else  if (document.getBoxObjectFor) { // gecko 엔진 기반 FF3제외
            var box = document.getBoxObjectFor(tag);
            techbug.left = box.x;
            techbug.top = box.y;
            techbug.width = box.width;
            techbug.height = box.height;
        }else {
            techbug.left = tag.offsetLeft;
            techbug.top = tag.offsetTop;
            techbug.width = tag.offsetWidth;
            techbug.height = tag.offsetHeight  + 3;  // +1 = Moz와 맞춤
            var parent = tag.offsetParent;
            if (parent != tag) {
                while (parent) {
                    techbug.left += parent.offsetLeft;
                    techbug.top += parent.offsetTop;
                    parent = parent.offsetParent;
                }
            }
            // 오페라와 사파리의 'absolute' postion의 경우 body의 offsetTop을 잘못 계산 보정
            var ua = navigator.userAgent.toLowerCase();
            if (ua.indexOf('opera') != -1 || ( ua.indexOf('safari') != -1 && getStyle(tag, 'position') == 'absolute' )) {
                techbug.top -= document.body.offsetTop;
            }

        }
        return techbug;
    }
}

이올린에 북마크하기(0) 이올린에 추천하기(0)
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback :: http://techbug.tistory.com/trackback/108
지나가다
getBoxObjectFor 가 없어지지는 않았고 아직도 존재합니다.
그리고 아직 사파리에서는 getBoundingClientRect , getBoxObjectFor(파이어폭스만 됨) 모두 지원하지 않네요...
2008/07/16 16:44

올바른 성장과 따뜻한 나눔이 있는 넥스트리

엊그제 Firefox 3.0 정식버전이 출시되자 마자 설치를 했다.
조금더 빨라진거, UI가 조금더 고급(?)스러워진것, 주소표시줄에 사용자접근성을 고려해서 나오는 아이콘들... 뭐 여튼 이건 설치해 보면 자연스레 알게 될것이고..
알려진 버그로는 URL에 한글이 들어가면 깨진다는거... 기본셋팅이 UTF-8이 아니라서 그런거라 about:config에서 변경해주면 그만이겠고....
여튼 다 좋은데.......

IE전용인줄 알았던 window.showModalDialog 로 먹는것이 아닌가? 
항상 스크립트에서..

if(window.showModalDialog) {
  //IE전용
}else {
   //그외 브라우저
}


일케 작업했었는데 하나를 더 주가해 주게 생겼다.

if(window.showModalDialog && document.all) {
  //IE전용
}else {
  //그외 브라우저
}


참고 사이트 : http://developer.mozilla.org/en/docs/DOM:window.showModalDialog

흠.. Mozilla 사이트에서 MSDN 사이트를 참조하란다...  ㅡ.,ㅡ;


그외의 window객체에 새로추가된것들이 많은데..  여기(모질라개발자사이트) 에서 확인하기 바란다.

뭐 간단히 정리하면 ...
window.applicationCache
window.fullScreen
window.returnValue
window.postMessage <-- 이녀석 드디어 추가됐다..


IE6, IE7에서 지원하던 스크립트도 FF3에서 지원을 하기 시작한 메쏘드나 프로퍼티가 있는데 아래 사이트를 참조하면 도움이 될듯하다.
DOM Client Object Cross-Reference:document







사용자 삽입 이미지




이올린에 북마크하기(0) 이올린에 추천하기(0)
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback :: http://techbug.tistory.com/trackback/107
올바른 성장과 따뜻한 나눔이 있는 넥스트리

유독 IE6에서 position:fixed로 했을 경우 고정되지 않는 버그패치
javascript로 패치할 경우 : http://www.doxdesk.com/file/software/js/fixed.js 참조

* { margin:0; padding:0;} /* html, body 사이의 간격을 제거 */
html { _overflow-y:hidden;} /* 기본 스크롤 제거 */
body{ height:100%; _overflow-y:auto;} /* 대체 스크롤 생성 */
#content { width:580px; height:1000px; margin:20px; padding:10px; background:#eeeeee;}
#aside { position:fixed; _position:absolute; left:650px; top:20px; width:100px; height:300px; padding:10px; background:#dddddd;}

일케 해봤으나 스크롤이 이상하게 생기는 문제가 발생하여


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<style>
html { filter: expression(document.execCommand("BackgroundImageCache", false, true)); _overflow: hidden;  }
:root html { overflow: hidden; }
body { _overflow: hidden; height: 100%; width: 100%; }
:root body { overflow: hidden; }
#dvwrap { width: 100%; height: 100%; overflow-y: scroll; overflow-x: hidden; position:relative; z-index:1; /* padding-bottom: 40px; */}
#SLIPAREA { position:fixed; _position:absolute;  bottom: 0px; width: 900px; z-index: 199; margin: 0 0 -1px 10px; _margin: 0 0 -1px 10px; }
:root #SLIPAREA { width: 100%; }
</style>

<body topmargin="0" leftmargin="0" marginwidth="0" marginheight="0">
<div id="dvwrap">
 1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
 1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
 1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
 1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
 1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
 1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
</div>
<div id="SLIPAREA">
 <script type="text/javascript">
 function techbug(){
  var h = document.getElementById('testSlip').style.height;
  if( parseInt(h) < 30 )
   document.getElementById('testSlip').style.height = "200px";
  else
   document.getElementById('testSlip').style.height = "20px";

 }
 </script>
 <div id="testSlip" style="border:#000 solid 1px width:888px;height:20px;background:orange">
  <a href="javascript:techbug();">눌러</a>
 </div>

</div>
</body>
</html>