javascript2008/12/01 13:50

스타일 적용시에는 styleSheet 오브젝트의 (document.styleSheets : Array) 메소드를 사용하는데,

  • IE 에서는 addRule 을 사용

인자값을 3개(필수3개)로,

  1. 0번 argument에는 선택자('div', 'p' 등..)를 넣고,
  2. 1번 argument에는 스타일 명령("color:blue", "overflow:hidden" 등..)을 넣는다.
  3. 2번 argument에는 0부터 시작하는 pages 컬렉션(document.styleSheets[?].pages : Array)에서의 위치할 인수를 넣는다. (-1을 넣으면 제일 뒤에 위치하게 된다.)
    반환값은 항상 -1이다. (주의: 오류가 없어도 -1을 반환)
  • FF 에서는 insertRule 를 사용

인자값은 2개(필수2개)로,

  1. 0번 argument에는 스타일 명령을 선택자를 포함하여 넣는다. (예: "#myTable {-moz-user-select:none}")
  2. 1번 argument에는 0부터 시작하는 cssRules 컬렉션(document.styleSheets[?].cssRules : Array)에서의 위치할 인수를 넣는다. (주의: addRule과는 다르다, -1 인자값을 넣으면 에러가 난다.)
    반환값은 cssRules 컬렉션에서의 위치한 위치값이다.

ps. 아즈키네 2번째 블로그 옛글중에 가져옴 (http://2.azki.org/182)

Posted by 아즈키
javascript2008/11/18 17:56
자바스크립트 막코딩으로 (특별한 animation/effect 라이브러리 사용 없이) 뒤집는 효과를 구현해 보았습니다

구현을 위주로 엉망으로 짠 코드라  부끄럽지만, 올리고 봅니다.


  • url
http://fliptest.azki.org/proto.html
(상수값으로 효과를 만들어본 첫번째 버전)
http://fliptest.azki.org/
(몇가지 변수를 적용할 수 있는 두번째 버전)


  • 소개
4각형과 3각형의 조합으로 접히는 효과를 내보았습니다.
실제 flip 과정중 캡쳐화면입니다.
사용자 삽입 이미지
그리고 element 의 구성은 3가지로 이루어져 있습니다.
사용자 삽입 이미지
왼쪽 삼각형과 오른쪽 삼각형이 입체적으로 착각하도록 할 수 있습니다.

삼각형을 만드는 방법은 참고사이트중 Triangles in Javascript 에 자세하게 나와있습니다.
사용자 삽입 이미지


  • 참고 사이트
http://lab.smashup.it/flip/
(Flip!0.4 - A jQuery plugin)
http://www.uselesspickles.com/triangles/demo.html
(Triangles in Javascript)
http://www.xentrik.net/css/filters.php
(CSS Filters)


ps.
참고사이트중 Flip!0.4 - A jQuery plugin 에서 처음 flip 효과를 보았는데,
그 flip 은 Opera browser 를 지원하지 못합니다. 제가 만든 것은 됩니다 :]
테스트 한 브라우저 목록입니다.
  • FF2, FF3
  • IE6, IE7, IE8
  • Opera 9
  • safari 3 (windows)
  • Chrome 0.3
Posted by 아즈키
javascript2008/10/30 11:05
등록 부분
initialize: function(id, container){
    (...)

    var thisP = this;
    AzLib.Event.observe(
        this._element,
        AzLib.Browser.Gecko ?
            "DOMMouseScroll" :
           "mousewheel",
        function(e){
            thisP.__event_mouseWheel(e);
        }
    );

    (...)
}

콜백 부분
__event_mouseWheel: function(e){
    AzLib.Event.stop(e);
    var delta = 0;
    if (e.wheelDelta) { /* IE, Opera, Safari, Chrome */
        delta = -e.wheelDelta / (AzLib.Browser.Chrome? 360: 120);
    } else if (e.detail) { /* Gecko */
        delta = e.detail / 3;
    }
    this._verticalScrollbar.stepPosition(delta * this.wheelRowCount);
}

mouse wheel 관련 자료를 찾아보니 살짝? 오동작도 하고 크롬 브라우저에 대한 처리가 안되어있어 수정하여 적용중인 코드.

IE6, IE7, IE8beta, FF2, Opera9, Safari3, Chrome0.2 에서 테스트 됨.
Posted by 아즈키
javascript2008/07/02 09:18
다른 팀의 업무를 도와주며 한두시간의 시간을 투자해서 만든 프로그램입니다.. (그런데 사용할 일이 사라져서 빛을 보지도 못한 프로그램입니다;)


  • URL
http://json2table.azki.org/ 입니다


  • 소개
JSON 문자열을 textarea 에 넣고 2 table ! 버튼을 누르면 JSON 데이타를 테이블로 출력하고, 출력하는데 걸린 시간을 출력합니다. 표시하는 룰은 object 타입은 테이블로 나타내고, array 타입은 row로 나타냅니다.
(참고: array 타입일 경우 테이블의 첫번째 로우에 각 item 의 이름(key)이 표시되는데, 그 아이템의 순서가 뒤바뀌거나 item 의 이름 종류나 개수가 일치하지 않는 경우 예외처리를 해놓지 않아서 정확하게 동작하지 않습니다)


  • 예제

{
    code: 'success',
    data: {
        member: {
            name: '김성준',
            id: 'azki',
            sno: '0701082'
        }
    }
}
위의 JSON 코드를 넣으니 아래 테이블로 표시되네요..
codedata
success
member
nameidsno
김성준azki0701082
15ms

아래부터는 다른 예제입니다

{
    "dataset": [{
        "columnInfo": [{
            "type": "string",
            "size": 10,
            "name": "departure_city"
        }, {
            "type": "string",
            "size": 10,
            "name": "departure_date"
        }, {
            "type": "string",
            "size": 10,
            "name": "arrival_city"
        }, {
            "type": "string",
            "size": 10,
            "name": "arrival_date"
        }],
        "rows": [{
            "arrival_city": "TOKYO",
            "departure_date": "03Jul08",
            "arrival_date": "05Jul08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "03Jul08",
            "arrival_date": "06Jul08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "10Jul08",
            "arrival_date": "12Jul08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "10Jul08",
            "arrival_date": "13Jul08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "17Jul08",
            "arrival_date": "19Jul08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "17Jul08",
            "arrival_date": "20Jul08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "24Jul08",
            "arrival_date": "26Jul08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "24Jul08",
            "arrival_date": "27Jul08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "31Jul08",
            "arrival_date": "02Aug08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "31Jul08",
            "arrival_date": "03Aug08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "07Aug08",
            "arrival_date": "09Aug08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "07Aug08",
            "arrival_date": "10Aug08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "14Aug08",
            "arrival_date": "16Aug08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "14Aug08",
            "arrival_date": "17Aug08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "21Aug08",
            "arrival_date": "23Aug08",
            "departure_city": "BUSAN"
        }, {
            "arrival_city": "TOKYO",
            "departure_date": "21Aug08",
            "arrival_date": "24Aug08",
            "departure_city": "BUSAN"
        }],
        "name": "Schedule"
    }]
}
위의 JSON 코드를 넣으니 아래 테이블로 표시되네요..

dataset
columnInforowsname
typesizename
string10departure_city
string10departure_date
string10arrival_city
string10arrival_date
arrival_citydeparture_datearrival_datedeparture_city
TOKYO03Jul0805Jul08BUSAN
TOKYO03Jul0806Jul08BUSAN
TOKYO10Jul0812Jul08BUSAN
TOKYO10Jul0813Jul08BUSAN
TOKYO17Jul0819Jul08BUSAN
TOKYO17Jul0820Jul08BUSAN
TOKYO24Jul0826Jul08BUSAN
TOKYO24Jul0827Jul08BUSAN
TOKYO31Jul0802Aug08BUSAN
TOKYO31Jul0803Aug08BUSAN
TOKYO07Aug0809Aug08BUSAN
TOKYO07Aug0810Aug08BUSAN
TOKYO14Aug0816Aug08BUSAN
TOKYO14Aug0817Aug08BUSAN
TOKYO21Aug0823Aug08BUSAN
TOKYO21Aug0824Aug08BUSAN
Schedule
109ms

  • 추후 업데이트될 수도 있는(?) 기능들..
    • JSON 데이타를 포맷팅해주는 기능 (보기 편하게)
    • 색상등으로 좀 더 보기 편하게 해주는 기능
    • 두가지 이상의 JSON 데이타를 서로 비교-분석 해주는 기능
    • 많은 케이스에 대해서 테스트가 이뤄지지 않은 상태라 버그가 있을 가능성이 높음. -> 디버깅..
Posted by 아즈키
javascript2008/06/10 15:12
소스1.
var input = document.createElement("input");
input.setAttribute("type", "text");
document.body.appendChild(input);

소스1. 적용 이후 다음 소스가 적용되지 않는다.. IE 에서만 ^^;

소스2.
input.setAttribute("type", "password");

IE 에서 나타나는 에러 메시지는 "이 명령은 지원하지 않습니다."

물론, setAttribute 메소드를 사용하지 않고 input.type = "..."; 로 적용시켜도 에러가 남.

FF2, Opera9, Safari3 에서는 정확히 잘 동작한다. IE6, IE7, IE8 beta1 에선 에러가 난다..


프로젝트에서는 아래와 같은 코드로 대체했다
 
if (Prototype.Browser.IE) {
    var outerHTML = this._input.outerHTML;
    outerHTML = outerHTML.replace(/type=[a-z]*/, "");
    outerHTML = outerHTML.replace(/value=""/, "value=\""+this._getText()+"\"");
    // IE 에서는 한번 지정된 type을 변경할 수 없어서 새로운 Element 를 만들어야 함.
    // IE 에서 password 타입의 텍스트 박스는 outerHTML 에서 value 값이 나타나지 않아서 다시 넣어줘야함.
    var newInput = document.createElement(outerHTML);
    if (this._getPassword()) {
        newInput.setAttribute("type", "password");
    }
    this._input.parentNode.replaceChild(newInput, this._input);
   
    //이벤트등록해제 등등 reference value 에 관련된 모든 것들 해제
    //...
    this._input = newInput;
    //...
    //이벤트등록 등등 reference value 에 관련된 모든 것들 재등록
}
else {
    this._input.setAttribute("type", this._getPassword()? "password": "text");
}

ps. 이벤트 등 element 값 자체를 등록시켜놓은 부분에 대해 수정이 반드시 필요하다.

참고로 이 문제의 다른 해결 방법이 없는지.. 구글을 찾아보니 역시나 비슷한게 있었다
http://codingforums.com/showthread.php?t=107073
Change input type="text" to input type="password"

Code:
<script type="text/javascript">
function passit(ip){
var np=ip.cloneNode(true);
np.type='password';
if(np.value!=ip.value)
np.value=ip.value;
ip.parentNode.replaceChild(np,ip);
}
</script>

<form id="login" action="#" method="post">
<input id="username-field" type="text" name="username" title="Username" onmousedown="javascript:this.value=''; javascript:this.focus();" value="Username" tabindex="1" />
<input id="password-field" type="text" name="password" title="Password" onmousedown="javascript:this.value=''; passit(this.form[0]); javascript:this.focus();" value="Password" tabindex="2" />
<input type="submit" name="submit" value="sign in" tabindex="3" />
</form>


나도 처음에 cloneNode 메소드를 생각했었는데, 사용하지 않았다..
이유는 type="text" 인 input 을 type="password" 로 변경은 가능하지만..
반대로는 불가능했기 때문이다. -ㅁ-
어째뜬..
IE does not like to change dynamically the type, thus one solution might be to replace entirely the object.
Posted by 아즈키
javascript2008/05/26 19:22
소스1.
<button style="
    width: 152px;
    height: 100px;
    background: red;
    border: 15px solid blue;
    overflow: hidden;
    position: absolute;
">
<div style="
    width: 122px;
    position: absolute;
    left: 0px; top: 0px;
    background: green;
">
azki's test
</div>
</button>

출력물1. (FF2)


출력물2. (IE6, IE7 도 동일하게 나온다)


출력물3. (왼쪽부터 Opera9, Safari3... 비슷함)



직관적으론 출력물3 처럼 나와야 하겠지만 불행히도 FF와 IE에서는 이상하게 나온다..
내부 div 에 top 과 left 속성을 제거해보자.. 더욱 더 가관이다.

소스2.
<button style="
    width: 152px;
    height: 100px;
    background: red;
    border: 15px solid blue;
    overflow: hidden;
    position: absolute;
">
<div style="
    width: 122px;
    position: absolute;
    background: green;
">
azki's test
</div>
</button>

출력물1. (FF2)


출력물2. (IE6, IE7 도 동일하게 나온다)


출력물3. (Opera9)


출력물4. (Safari3)



내가 원하는 것은 소스1의 출력물3과 같은 형태인데,
참 어려운것 같다 ㅡㅡ
더욱 재미난 것은... FF 의 디버깅 도구 firebug 에서 보여지는 부분이다. (소스1)

날 약올리듯이? 내가 원하는 부분을 정확하게 가르키고 있다.

일단 하나 하나를 분석해보니..

border 가 좌우 좌표를 이상하게 만드는 것 같았다. (IE와 FF에서)

그리고 FF 에서는 padding 이 또 문제를 안쪽 div의 위치를 움직이고 있었다.

소스1에서 border 와 padding 을 모두 0px 로 준 결과를 살펴보면 다음과 같다

소스3.
<button style="
    width: 152px;
    height: 100px;
    background: red;
    border: 0px;
    padding: 0px;
    overflow: hidden;
    position: absolute;
">
<div style="
    width: 122px;
    position: absolute;
    left: 0px; top: 0px;
    background: green;
">
azki's test
</div>
</button>

출력물1. (FF2)

출력물2. (IE6, IE7, Opera9, Safari3)



결국 적절한 해답은 못 찾았고..

소스3의 상태에서 FF만 따로 위치를 잡아주는 식으로 처리를 했다
left 속성: -3 , top 속성: -(높이/2+1)


부록::
프로젝트에서는 javascript 로 이런식으로 구성되어 있다 ㅡㅡㅋ

initialize: function() {//컴포넌트 객체를 생성할 때 호출됨..
        //...
        if (Prototype.Browser.Gecko) {
            this._label.setX(-3);
        }
        else {
            this._label.setX(0);
            this._label.setY(0);
        }
}
,
//...
,
onresize: function() {//사이즈 변경시에 호출됨..
        //...
        if (Prototype.Browser.Gecko) {
            this._label.setY(-1-Math.floor(height/2));
        }
}

Posted by 아즈키
javascript2008/05/21 10:57

Javascript 로 지정한 style 의 경우 구하는 예
element.style["fontSize"]

IE 의 경우 구하는 예
element.currentStyle["fontSize"]

FF 의 경우 구하는 예
document.defaultView.getComputedStyle(element, "").getPropertyValue("font-size")


참고: IE 의 경우 filter 값을 구하는 방법의 예.
element.filters.item("alpha").opacity

Posted by 아즈키
javascript2008/05/14 09:27
예전부터 알고 있었던거라 그때 정리해 쓸려했는데..
조금 더 보편화된 패턴이 발견되면 정리할려다 시간이 많이 흘러 이렇게 그냥 정리.. (결국 보편화된 패턴이나 다른 이상 증상은 아직 발견하지 못했습니다. 발견하신분이나 이 문제에 대해 이견이 있으신분은 꼭 리플을 달아주시면 감사드리겠습니다.)

이제라도 증상에 대해 기록해 두어야 될거 같아 정리해 올림-.-

  • 증상 & 분석
IE 에서는 eval 구문에 다음 스트링을 사용하였을 때 반환이 되지 않음.
"(function() {})"
다른 4대 브라우저(FF,Opera,Safari) 에서는 반환이 된다.

typeof eval("(function() {})");
가 IE 에서만 "undefined" 가 나온다
나머지 브라우저에서는 잘 된다 ("function" 반환)

IE가 eval 안에서 function 구문이 동작하지 않는 건 아닌거 같다
typeof eval("(function() {return function() {};})();")
은 또 "function" 으로 나오기 때문이다

  • 대안
그냥 function 을 eval 로 정리해서 쓰고 싶을 땐.. (function 내용을 스트링 값으로 선언하고 싶을 때?)
  1. function 구문을 eval 밖으로 빼고 소스 부분만 eval 로 넣는다.
    var a = eval("function() { var a=1; alert(++a); return a; }");
    대신
    var a = function() { eval("var a=1; alert(++a); return a; ") };
    를 사용한다.

  2. 그냥 eval 대신 Function 을 사용한다.
    var a = eval("function() { var a=1; alert(++a); return a; }");
    대신
    var a = new Function("var a=1; alert(++a); return a;");
    를 사용한다.
ps. 필자는 2번 방식을 좋아한다. 속도가 더 빠르기 때문이다. (똑같은 구문이라면 eval을 사용하는 것이 거의 속도가 큰 차이로 떨어진다. 그렇기 때문에 난 왠만하면 eval 은 쓰지 않는다.)
Posted by 아즈키
javascript2008/05/14 09:27
업무 or 개인 프로젝트 시 자주 쓰게 되는 배열 변수 메소드를 정리하였습니다.

  • .sort
sort ([sortFunction: function]) : array
해당 배열 자신을 정렬한다. (기존 배열 변경)
sortFunction 을 생략하면 charCode 값을 기준으로 오름차순으로 정렬한다.
반환값은 자기 자신의 레퍼런스다. (non copy)
sortFunction 은 function 타입이며, 두개의 인자를 받는다. sortFunction 이 음수를 반환하면 그 두 아이템을 스왑한다. (양수나 0을 반환시에는 스왑하지 않는다.)
각 배열 아이템의 짝을 모두 수행하는 것은 똑같지만 수행하는 순서는 브라우저 별로 조금 다르다.
배열 ["a", "b", "c"] 를 .sort 메소드로 sortFunction 에 던질 경우 FF 는
sortFunction ("a", "b") -> sortFunction ("c", "a") -> sortFunction ("b", "a")
순으로 던지고, IE 에서는
sortFunction ("b", "b") -> sortFunction ("c", "a") -> sortFunction ("b", "a")
순으로 던진다.
sortFunction 이 무조건 음수를 반환하는 경우 결과값 또한 다르게 나온다. (물론 정상적인 비교를 수행하는 함수라면 같은 결과가 나오겠지만, 같은 코드가 다른 결과값을 낸 다는 사실에 흥미를 갖고 수행시켜보았다)
FF: ["c", "a", "b"]
IE: ["b", "c", "a"]

  • .reverse
reverse () : void
해당 배열 자신을 뒤집는다.

  • .push
push ([item1 : mixed [, item2 : mixed [, item3 : mixed, ...]]]) : item
푸시하고 마지막으로 추가된 아이템을 반환한다. (3개의 item을 추가했을 경우 item3을 반환)

  • .pop
pop () : item
팝한다. 비어있는 경우엔 undefined 를 반환한다.

  • .shift
shift () : item
시프트한다. 팝을 기능을 반대방향으로 수행한다.

  • .unshift
unshift ([item1 : mixed [, item2 : mixed [, item3 : mixed, ...]]]) : void
언시프트한다. 푸쉬의 기능을 반대방향으로 수행한다. 반환값은 브라우저별로 다르므로 사용하지 않는 것이 좋다. (예로 IE6 에서는 undefined 을 반환하지만, FF2 에서는 push와 마찬가지로 마지막 인자값을 반환한다)

  • .slice
slice (start : int [, end : int]) : array
지정된 부분을 복사해 새로운 배열을 반환한다. start는 포함하지만, end는 포함하지 않는다.
start 가 음수면 legnth + start 로 처리한다.
end 가 음수면 length + end 로 처리한다.
end 가 생략되면 배열의 끝까지 추출한다.
원래 배열변수에 영향을 주진 않는다. (복사해서 새로운 배열을 만듬)

  • .splice
splice (start : int, deleteCount : int, [item1 : mixed [, item2 : mixed [, item3 : mixed, ...]]]) : array
지정된 부분을 삭제하고, 그 부분에 새로운 아이템을 추가한다. 그리고 반환은 삭제된 아이템들을 가진 새로운 배열이다. (deleteCount 가 0 일 경우 빈 배열이, 1 일 경우 아이템이 1개인 배열이 반환)
deleteCount 가 0 이면 삭제되는 것이 없다.
item 을 생략하면 삭제만 수행한다.
배열 가운대 인자를 추가할 경우(deleteCount = 0)나 배열 중간에 있는 인자를 삭제할 경우(item 생략) 활용가능하다.

  • .concat
concat ([item1 : mixed [, item2 : mixed [, item3 : mixed, ...]]]) : array
배열에 아이템들을 추가한 새로운 배열을 반환한다. 푸쉬와 비슷하게 추가되지만, 기존 배열에 영향을 미치지 않고 새로운 배열을 반환한다는 점에서 다르다.
추가되는 순서는 당연히 왼쪽에서 오른쪽으로 순서대로이다.

  • .join
join ([separator : string]) : string
배열 요소들 사이에 separator 을 넣어서 하나의 string을 만들어 반환한다. separator 를 생략할 경우 ","(ascii 44)로 처리한다.


ps. 배열 변수는 레퍼런스 값이다.즉,
var a = b = [1];
var c = [1];
에서
a == b 는 true 지만 a == c 는 false 다.
Posted by 아즈키
javascript2008/05/14 09:27
업무용(?)으로 종종 쓰고 있는, User preferences for colors 입니다.

개인적으로 보기 위해 테이블로 작성하였습니다.

  • URL
http://upct.azki.org/

  • 소개
윈도우에서 설정한(디스플레이 설정에서 화면배색 부분) 색상들을 HTML 에서 가져다 쓰는 것 입니다.
CSS2 에서 추가되었다고 합니다. 참고로 꼭 윈도우즈에서만 적용되는 건 아닙니다. 우분투에서 파이어폭스로 테스트 해본 결과 됩니다.
4 대 브라우저(FF,IE,Opera,Safari)에서 다 적용됩니다. 다만 윈도우 버전 Safari에서는 설정값을 윈도우즈의 것으로 가져오지 않는군요. (내부적으로 설정된 컬러를 쓰더군요, Mac 에서는 어떤지 모르겠습니다. 아마 잘 되겠죠?)

  • 기반 자료 출처
이용석의 JavaScript & DHTML (http://user.chollian.net/~spacekan/css/preferences-colors.htm)
아주 오래전부터 알고 다니는 사이트인데 지금 봐도 참 좋은 사이트입니다. ^^
Posted by 아즈키
javascript2008/05/14 09:26
개인적으로 관심이 있는 분야라서 코드 실행시간을 체크하는 스크립트를 짰습니다..

  • URL
http://jpt.azki.org/ 입니다

  • 소개
code A 에 테스트할 코드를 넣고 Test! 버튼을 누르면 그 코드가 Loop Count 만큼 실행됩니다
그리고 그 시간을 체크하여 화면에 표시해주는 프로그램입니다

  • 예제
code A 에 다음 코드를 넣습니다
a = 0;
code B 에 다음 코드를 넣습니다
var a = 0;
Loop Count
500000
으로 적어줍니다

code A 밑의 버튼 Test! 를 누릅니다
저의 경우 (FF2) 다음과 같은 결과값이 나오네요.
*Func Time: 1015 ms
*All: 2187 ms
*Empty Func: 1172 ms
code B 밑의 버튼 Test! 를 누릅니다
*Func Time: 78 ms
*All: 1250 ms
*Empty Func: 1172 ms
*All 에 해당되는 것은 코드를 Loop Count 만큼 반복해서 수행시킬 때 걸린 시간이며, *Empty Func 에 해당되는 것은 코드를 넣지 않고 Loop Count 만큼 반복만 수행했을 때 걸린 시간입니다. 그러므로 실제적으로 코드에 의해 걸린 시간은 *Func Time 시간 = ( *Empty Func 시간 - *All 시간 ) 이라는 논리입니다 ^^

결론: 변수 하나를 쓰더라도 var 를 붙여 주어 지역변수로 명확하게 표현해 사용하는 것이 빠르군요^^;


  • 추후 업데이트될 수도 있는(?) 기능들..
    • 타이머를 두어서 너무 시간이 오래걸리는 코드를 중도에 멈춤?
    • 실행시간을 계산해서 적절한 count 반복.
    • 두가지 이상의 코드에 대해 결과값 비교.
    • 입력한 시간을 기준으로 그 시간동안 몇번 실행되는지 체크.
Posted by 아즈키
javascript2008/05/14 09:24
웹에서 파일 업로드시에 프로그레스 모니터 (흔히 ProgressBar 형태로 많이 쓰죠) 구현에 대한 글 입니다

짧은 지식과 소견으로 이루어진 글이므로, 틀리거나 이후 시대가 변해 달라진 내용이 많을 것 입니다 :]

많은 분들께 도움이 되길 바랍니다만 출처를 포함하지 않은 불펌은 자제해주시기를 -ㅁ-zz


이전에 프로그레스 바를 구현하기 위해서는 웹브라우저 자체로만은 힘들었고 (제가 아는한, 제대로 구현된 경우가 별로 없었고) ActiveX 를 설치해야 되는 경우가 많았지요

하지만 Ajax 시대가 초래됨에 따라 -.- activeX 사용을 자제하기 시작했지요

아무튼 유명 포탈사이트 플러그인도 깔기 싫은 (워낙 스파이웨어 이딴 것들이 판을 쳐서요) 시대라서 다른 방법을 생각하게 된거 같습니다


뭔가 잡담이길어지네요 . . . . 본론을 쓰겠습니다 :]


일단 많이 쓰는 방식으로
어도비 플래시(adobe flash)를 이용한 방법이 있습니다
플래시8부터 업로드 컴포넌트를 지원한다고 들은거 같습니다
제가 쓰는 텍스트큐브(태터툴즈)도 파일을 업로드할 때 플래시를 이용하네요
사실 플래시도 activeX 의 종류이긴하나 정말로.. activeX 가 아닌 것 처럼 쓰이고 있기때문에..
특별하지 않은 경우에는 문제가 되지 않죠
서버 세팅이 특별하게 필요하지 않아서 호스팅 받는 개인이 쓰기에 편한 방법이기도 합니다
현재는 순수한 JS와 HTML로 불가능한 다중선택 파일 선택 다이얼로그가 가능하고, 업로드 전에 파일 사이즈도 알아낼 수 있습니다.
제가 생각하기엔 특별한 경우가 아닌 이상 제일 괜찮은 방법이라고 생각합니다..
업로드 데모와 프로그램은 http://swfupload.mammon.se/ 를 보세요 =_=


그리고, AJAX를 이용한 방법이 있습니다
확실히 플래시에 비해 약하지만 진정한 non-download (no activeX) 이므로, 쓸데없다고 할 수는 없겠죠.
ASP, JSP, PHP 모두 가능합니다
ASP는 확인을 해보지 못했으나 된다하고, JSP와 PHP는 실제 코드를 작성하여 확인을 해보았습니다.

그 중 PHP 를 이용하는 방법을 소개하겠습니다
APC(Alternative PHP Cache) 모듈을사용하는 방법이 있습니다
다운로드는 http://pecl.php.net/package/APC/ 를 이용하시면 됩니다
윈도우 환경에서 Apache2 + PHP5 를 이용하시면 http://www.php.net/downloads.php 에서 버전에 맞는 PECL Win32 binaries 찾아서 받아 쓰면 됩니다
윈도우 환경 기준으로 설명드리면
extension_dir 을 설정하시고,
예:
extension_dir = "C:/php/ext/"

그 디렉토리에 php_apc.dll 파일을 복사하고 (다른 dll은 안넣으셔도 됩니다) 아래와 같이 설정합니다
extension = php_apc.dll
[apc]
apc.rfc1867 = "1"

Apache를 재시작하면 작동합니다

rfc1867 라는 옵션이 바로 그 기능(프로그레스-바를 만들 수 있는 기능)을 하는 옵션입니다
자세한 기능은 이곳을 참고하세요 http://www.php.net/manual/en/ref.apc.php
관련된 기능에 대한 간략한 설명.
apc.rfc1867
"0" 이면 사용하지 않는 것이고 "1"은 사용
apc.rfc1867_prefix
apc_fetch 로 뽑아올 때 사용할 키의 앞부분이죠 기본값은 "upload_"
apc.rfc1867_name
업 로드시에 파일 식별자를 넣어줄 파라메터의 이름 입니다. 이는 input 태그를 사용해서 넣어주고요. 보통 hidden 속성을 적용하여 사용합니다(type='hidden'). 값은 보통 Javascript 서 Math.random() 등으로 넣어주고요. 나중에 프로그레스 상태를 받을 요청을 할 때 사용합니다. 기본값은 "APC_UPLOAD_PROGRESS" 입니다.
apc.rfc1867_freq
"The frequency that updates should be made to the user cache entry for upload progress." 라는군요..

아무튼 사용법은 간단합니다
업로드하는 폼에 hidden 타입의 input을 하나 더 추가해서 apc.rfc1867_name 값을 이름으로 합니다 (기본값은 APC_UPLOAD_PROGRESS 입니다.)
간단하게 코드로 표현하면 이렇습니다
<form enctype="multipart/form-data" method="post" action="">
    <input type="hidden" name="APC_UPLOAD_PROGRESS" value="TEST123"/>
    <input type="file" name="f"/>
</form>

name이 APC_UPLOAD_PROGRESS 인 input 의 value가 가 됩니다 (임의로 TEST123을 넣었습니다, 랜덤값등을 생성하여 넣는 편이 좋겠지요)
action에 해당하는 PHP 파일에서는 프로그레스 모니터를 위해 따로 작업할 필요가 없습니다
다른 PHP 파일에서 아래와 같이 값을 이용해서 현재의 업로드 상태를 가져올 수 있습니다
<?php
print_r(apc_fetch("upload_TEST123"));
?>
결과값은 다음과 같습니다 (파일 업로드가 진행중일 경우)
Array
(
    [total] => 1488687
    [current] => 205020
    [filename] => test.exe
    [name] => f
    [done] => 0
    [start_time] => 1194251194.69
)
감이 오시겠지만 'total' 과 'current' 를 이용해서 프로그레스를 나타낼 수 있습니다. 'start_time' 도 쓸만하겠군요. 더 응용하면 업로드 속도까지 나타낼 수 있겠군요

AJAX를 이용해서 실시간으로 이를 나타낼려면 form의 target을 숨겨진 iframe으로 하고 submit 후에 (페이지가 바뀌지않게) ajax 통신을 시작해서 정보를 가져와야겠지요

차후 이 AJAX 코드에 관해서는 다시 예제와 함께 글을 올릴 생각입니다 ^^;
Posted by 아즈키
javascript2008/05/07 17:51
createElement 사용에 관련된  W3C DOM 에 대한 글을 보면 다음과 같다
The W3C DOM spec is supposed to be "the name of the element type to instantiate" (e.g., createElement('input'))

하지만 IE에선 이런 방법도 가능하다
var radio1 = document.createElement("<input type=radio name=onandoff value=on>");
var radio2 = document.createElement("<input type=radio name=onandoff value=off>");
document.body.appendChild(radio1);
document.body.appendChild(radio2);

FF, Opera, Safari 등에서도 작동할 수 있도록 짜면 다음과 같다
var radio1 = document.createElement("input");
var radio2 = radio1.cloneNode(false);
radio1.value = "on";
radio2.value = "off";
document.body.appendChild(radio1);
document.body.appendChild(radio2);

첫번째 방법을 사용하면 FF에서는 error가 발생한다
크로스 브라우징을 위해선 두번째 방법을 사용하는 것이 좋겠다

하지만, 두번째 방법으로 사용시 IE6과 IE7에서는 문제가 있다
직 관적으로 생각하면 위의 두가지 코드는 아래의 HTML 코드와 같기 때문에 하나를 선택하면 다른 하나가 선택해제되는 radio 버튼의 작동을 해야 정상이지만 두번째 코드를 사용하면 IE에서는 동작하지 않는다. (클릭을 해도 선택이 되지 않음)
<input type="radio" name="onandoff" value="on"/>
<input type="radio" name="onandoff" value="off"/>

속성값이 잘 적용되지 않을 때 setAttribute 메소드를 사용한 우회적인 방법으로 작동시킨 경험이 몇번 있어서 이번에도 아래와 같이 사용해 보았지만 결과는 똑같았다 (FF에서는 되고 IE에서는 작동안하고.)
var radio1 = document.createElement("input");
radio1.setAttribute("name", "onandoff");
radio1.setAttribute("type", "radio");
var radio2 = radio1.cloneNode(false);
radio1.value = "on";
radio2.value = "off";
document.body.appendChild(radio1);
document.body.appendChild(radio2);

찾은 해결책은 innerHTML 을 이용하는 방법과 try ~ catch 문을 사용하는 것..

innerHTML 을 사용하는 건 다음과 같다
document.body.innerHTML += "<input type=radio name=onandoff value=on>";
document.body.innerHTML += "<input type=radio name=onandoff value=off>";
다 만 Element 의 Reference 값을 얻을려면 좀 우회해야 한다. innerHTML 의 뒤에 추가하고 바로 lastChild 로 찾는 방법이 있지만 좀 모듈화 시켜보면 (보다 돌아가는 방법이지만.) 이런 코드를 사용할 수도 있다
function createRadioButtonElement () {
    var tempTag = document.createElement('temp');
    tempTag.innerHTML = "<input type=radio name=/>";
    var radioButtonElement = tempTag.removeChild(tempTag.firstChild);
    delete tempTag;
    return radioButtonElement;
}
var radio1 = createRadioButtonElement();
radio1.name = "onandoff";
var radio2 = radio1.cloneNode(false);
radio1.value = "on";
radio2.value = "off";
document.body.appendChild(radio1);
document.body.appendChild(radio2);

try ~ catch 문을 사용하는 예제는 다음과 같다
var radio1;
try {
  radio1 = document.createElement("<input type='radio' name='onandoff'>");
}
catch (e) {
  radio1 = document.createElement('input');
  radio1.type = 'radio';
  radio1.name = 'onandoff';
}
var radio2 = radio1.cloneNode(false);
radio1.value = 'on';
radio2.value = 'off';
document.body.appendChild(radio1);
document.body.appendChild(radio2);

결론: IE 에서는 radio 버튼에 name 속성을 적용시켜 동작하게 할려면 createElement("input") 외의 다른 우회적 방법이 필요하다.
Posted by 아즈키
javascript2008/05/07 17:50
이 테이블은 자바스크립트의 느슨한 비교(==)와 엄격한 비교(===)를 설명합니다. 이는 타입 저글링과도 관련이 있고 변수에 대한 이해를 도울 수 있을 것입니다.
테 이블을 이용하기 전에 자바스크립트 타입과 각 타입의 의미를 어느정도는 이해하여야 합니다. 예를 들면 "1"는 string 타입이고, 반면에 1은 number타입입니다. 또 true는 boolean타입이며, [1]은 object타입입니다(배열).
방금 나열한 4가지는 모두 다른 타입이고 엄격한 비교시 모두 다르다고 나옵니다(false). 하지만 느슨한 비교시에는 모두 서로 같다고 나옵니다(true).

기본 샘플:
TypesComparisonsTable.html

느슨한 비교 (==) 테이블

TypesComparisonsTable2.html

엄격한 비교 (===) 테이블

느슨한 비교:

more..

== true false 1 0 -1 NaN "1" "0" "-1" "" "javascript" [] [0] [1] [2] [1,0] {} {1:1} null undefined new Boolean() new Number() new String() new Array() new Object() ==
true true false true false false false true false false false false false false true false false false false false false false false false false false true
false false true false true false false false true false true false true true false false false false false false false true true true true false false
1 true false true false false false true false false false false false false true false false false false false false false false false false false 1
0 false true false true false false false true false true false true true false false false false false false false true true true true false 0
-1 false false false false true false false false true false false false false false false false false false false false false false false false false -1
NaN false false false false false false false false false false false false false false false false false false false false false false false false false NaN
"1" true false true false false false true false false false false false false true false false false false false false false false false false false "1"
"0" false true false true false false false true false false false false true false false false false false false false true true false false false "0"
"-1" false false false false true false false false true false false false false false false false false false false false false false false false false "-1"
"" false true false true false false false false false true false true false false false false false false false false true true true true false ""
"javascript" false false false false false false false false false false true false false false false false false false false false false false false false false "javascript"
[] false true false true false false false false false true false false false false false false false false false false false false false false false []
[0] false true false true false false false true false false false false false false false false false false false false false false false false false [0]
[1] true false true false false false true false false false false false false false false false false false false false false false false false false [1]
[2] false false false false false false false false false false false false false false false false false false false false false false false false false [2]
[1,0] false false false false false false false false false false false false false false false false false false false false false false false false false [1,0]
{} false false false false false false false false false false false false false false false false false false false false false false false false false {}
{1:1} false false false false false false false false false false false false false false false false false false false false false false false false false {1:1}
null false false false false false false false false false false false false false false false false false false true true false false false false false null
undefined false false false false false false false false false false false false false false false false false false true true false false false false false undefined
new Boolean() false true false true false false false true false true false false false false false false false false false false false false false false false new Boolean()
new Number() false true false true false false false true false true false false false false false false false false false false false false false false false new Number()
new String() false true false true false false false false false true false false false false false false false false false false false false false false false new String()
new Array() false true false true false false false false false true false false false false false false false false false false false false false false false new Array()
new Object() false false false false false false false false false false false false false false false false false false false false false false false false false new Object()
== true false 1 0 -1 NaN "1" "0" "-1" "" "javascript" [] [0] [1] [2] [1,0] {} {1:1} null undefined new Boolean() new Number() new String() new Array() new Object() ==

엄격한 비교:

more..

=== true false 1 0 -1 NaN "1" "0" "-1" "" "javascript" [] [0] [1] [2] [1,0] {} {1:1} null undefined new Boolean() new Number() new String() new Array() new Object() ===
true true false false false false false false false false false false false false false false false false false false false false false false false false true
false false true false false false false false false false false false false false false false false false false false false false false false false false false
1 false false true false false false false false false false false false false false false false false false false false false false false false false 1
0 false false false true false false false false false false false false false false false false false false false false false false false false false 0
-1 false false false false true false false false false false false false false false false false false false false false false false false false false -1
NaN false false false false false false false false false false false false false false false false false false false false false false false false false NaN
"1" false false false false false false true false false false false false false false false false false false false false false false false false false "1"
"0" false false false false false false false true false false false false false false false false false false false false false false false false false "0"
"-1" false false false false false false false false true false false false false false false false false false false false false false false false false "-1"
"" false false false false false false false false false true false false false false false false false false false false false false false false false ""
"javascript" false false false false false false false false false false true false false false false false false false false false false false false false false "javascript"
[] false false false false false false false false false false false false false false false false false false false false false false false false false []
[0] false false false false false false false false false false false false false false false false false false false false false false false false false [0]
[1] false false false false false false false false false false false false false false false false false false false false false false false false false [1]
[2] false false false false false false false false false false false false false false false false false false false false false false false false false [2]
[1,0] false false false false false false false false false false false false false false false false false false false false false false false false false [1,0]
{} false false false false false false false false false false false false false false false false false false false false false false false false false {}
{1:1} false false false false false false false false false false false false false false false false false false false false false false false false false {1:1}
null false false false false false false false false false false false false false false false false false false true false false false false false false null
undefined false false false false false false false false false false false false false false false false false false false true false false false false false undefined
new Boolean() false false false false false false false false false false false false false false false false false false false false false false false false false new Boolean()
new Number() false false false false false false false false false false false false false false false false false false false false false false false false false new Number()
new String() false false false false false false false false false false false false false false false false false false false false false false false false false new String()
new Array() false false false false false false false false false false false false false false false false false false false false false false false false false new Array()
new Object() false false false false false false false false false false false false false false false false false false false false false false false false false new Object()
=== true false 1 0 -1 NaN "1" "0" "-1" "" "javascript" [] [0] [1] [2] [1,0] {} {1:1} null undefined new Boolean() new Number() new String() new Array() new Object() ===
Posted by 아즈키