파일을 업로드 할 서버가 마땅한 곳이 없어서 티스토리 스킨에 업로드했다.

http://goo.gl/b4qHK 에서 직접 확인 가능!

소스보기를 해보면 알겠지만 어떤 크기의 네모로직도 문제없도록 만들었다.


 


License
달리 정하지 않는 한, 이 저작물 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
Except where otherwise noted, this content is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 2.0 Korea License
한RSS에서 돌아가는 코드


License
달리 정하지 않는 한, 이 저작물 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
Except where otherwise noted, this content is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 2.0 Korea License
출처: http://ruru.tistory.com/entry/HTTP-Cookie-Javascript

clear가 제대로 동작하지 않아 새로 작성했다.
    var Cookies = {};
    Cookies.set = function(name, value){
         var argv = arguments;
         var argc = arguments.length;
         var expires = (argc > 2) ? argv[2] : null;
         var path = (argc > 3) ? argv[3] : '/';
         var domain = (argc > 4) ? argv[4] : null;
         var secure = (argc > 5) ? argv[5] : false;
         document.cookie = name + "=" + escape (value) +
           ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
           ((path == null) ? "" : ("; path=" + path)) +
           ((domain == null) ? "" : ("; domain=" + domain)) +
           ((secure == true) ? "; secure" : "");
         
    };

    Cookies.get = function(name){
     var arg = name + "=";
     var alen = arg.length;
     var clen = document.cookie.length;
     var i = 0;
     var j = 0;
     while(i < clen){
      j = i + alen;
      if (document.cookie.substring(i, j) == arg)
       return Cookies.getCookieVal(j);
      i = document.cookie.indexOf(" ", i) + 1;
      if(i == 0)
       break;
     }
     return null;
    };

    Cookies.clear = function(name) {
      if(Cookies.get(name)){
      	var today = new Date();
      	today.setFullYear(today.getFullYear()-1);
        Cookies.set(name, "", today);
      }
    };

    Cookies.getCookieVal = function(offset){
       var endstr = document.cookie.indexOf(";", offset);
       if(endstr == -1){
           endstr = document.cookie.length;
       }
       return unescape(document.cookie.substring(offset, endstr));
    };


License
달리 정하지 않는 한, 이 저작물 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
Except where otherwise noted, this content is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 2.0 Korea License
파이어준님의 블로그에 엄청나게 좋은 글이 있었는데 저작권이 CC라서 보관도 할겸 가져왔다.
바로 프로토타입을 효과적으로 활용하는 방법에 관한 건데.
초반부를 보면서는 "음 나도 좀 쓰고있군" 했는데 update나 invoke, Ajax.Request 에서 parameters 쓰기 등에서 좌절. Template은 존재 여부도 모르고 있었다. 알게되었으니 유용하게 사용해야겠다.

//바르지 못한 방법:
document.getElementById("foo ")
//적당한 방법: 놀랍게도 어떤 사람들은 이것에 대해 잘 모른다.
$("foo ")

//바르지 못한 방법:
var woot = document.getElementById("bar").value
var woot = $("bar").value
//적당한 방법: 폼 값의 편리하고 빠른 호출
var woot = $F("bar")

//바르지 못한 방법:
$('footer').style.height = '100px';
$('footer').style.background = '#ffc';    
//적당한 방법: 모든 브라우저가 W3C의 권고를 따르고 있지 않다.
$('footer').setStyle({
    height: '100px',
    background: '#ffc'
})

//바르지 못한 방법:
$('coolestWidgetEver').innerHTML = 'some nifty content'
//적당한 방법:
$('coolestWidgetEver').update('some nifty content')
// 아래와 같은 문법 구사가 가능해 지므로
$('coolestWidgetEver').update('some nifty content').addClassName('highlight').next().hide()

//바르지 못한 방법:
new Ajax.Request('ninja.php?weapon1=foo&weapon2=bar')
//적당한 방법: 보기 좋으며 보다 나은 파라메터 구조 사용
new Ajax.Request('ninja.php', {
    parameters: {
        weapon1: 'foo',
        weapon2: 'bar'
    }
})

//바르지 못한 방법:
new Ajax.Request('blah.php', {
    method: 'POST',
    asynchronous: true,
    contentType: 'application/x-www-form-urlencoded',
    encoding: 'UTF-8',
})
//적당한 방법: 기본옵션은 생략하라!
new Ajax.Request('blah.php')

//바르지 못한 방법:
Event.observe('myContainer', 'click', doSomeMagic)
//적당한 방법: 논쟁의 여지가 있지만 객체지향적이다!
$('myContainer').observe('click', doSomeMagic)

//바르지 못한 방법:
$$('div.hidden').each(function(el){
    el.show();
})
//적당한 방법: 슬프게도 이 사용법을 아는 사람들이 많지 않다는 사실.
$$('div.hidden').invoke('show')

//바르지 못한 방법:
$$('div.collapsed').each(function(el){
    el.observe('click', expand);
})
//적당한 방법: invoke를 이용한 이벤트 핸들링, 졸라 쉽다!
$$('div.collapsed').invoke('observe', 'click', expand)

//바르지 못한 방법:
$$('input.date').invoke('observe', 'focus', onFocus);
$$('input.date').invoke('observe', 'blur', onBlur);
//적당한 방법: $$는 오버해드가 크기 때문에 invoke를 사용하면 $$를 여러번 사용할 필요도 없다.
$$('input.date').invoke('observe', 'focus', onFocus).invoke('observe', 'blur', onBlur)

//바르지 못한 방법:
$('productTable').innerHTML =
    $('productTable').innerHTML +
    '<tr><td>' + productId + ' '
    + productName + '</td></tr><tr><td>'
    + productId + ' ' + productPrice +
    '</td></tr>'
//적당한 방법: Template 클래스는 정말 쓸만한 DOM 솔루션이다. 하지만 잘 사용되고 있지 않는 것 같다.
var rowTemplate = new Template('<tr><td>#{id} #{name}</td></tr><tr><td>#{id} #{price}</td></tr>');
$('productTable').insert(
    rowTemplate.evaluate({
        id: productId,
        name: productName,
        price: productPrice
    }))
)

invoke에 인자로 넘어가는 function 이름이 string길래 순간 eval인가? 라는 말도안되는 생각에 설마하면서 소스를 뒤져보니 다행히 eval은 아니었고(당연하지!) invoke의 소스는 아래와 같이 되어있었다.
invoke: function(method) {
    var args = $A(arguments).slice(1);
    return this.map(function(value) {
        return value[method].apply(value, args);
    });
}

function명과 추가적인 인자들을 넘겨주면 해당 function에 자신과 인자들을 넣어서 실행하는 것 같다.
eval 대신에 그냥 맵처럼 function을 호출할 수 있다는건 조금 신기하기도 했고.

프로토타입은 쓰면 쓸수록 맘에 든다. 이 포스팅이 좀더 잘 활용할 수 있는 계기가 되길 바란다.


License
달리 정하지 않는 한, 이 저작물 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
Except where otherwise noted, this content is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 2.0 Korea License
얼마전 알바로 들어온 회사에서 프로젝트를 살짝 끝냈다.
개발자의 필수코스인 주말출근에 밤도 새면서(ㅠㅠ) 열심히 만들었는데,
예전엔 mootools같은 js라이브러리를 썼다가 안쓰고 만들려니, 크로스브라우징이 내 발목을 잡았다.

이번 프로젝트의 목표 브라우저는 Internet Explorer(이하 ie)와 Firefox(이하 ff).
그런데 내가 짠 자바스크립트가 둘중하나에서 동작을 안했던 경우가 있어
다른 개발자분들의 삽질을 조금이나마 줄여보고자. 이 포스트를 남긴다.


첫째. 동적으로 input을 생성할때.

우선 element를 만드는 명령어는 널리 알려져있다.
var input = document.createElement('input');

이렇게 하면 input라는 태그가 만들어진다.
<input />가 만들어진다고 생각하면 된다.

그런데 ie에서는 아래 명령어가 먹지않는다.
input.type = 'hidden';

그래서 해결하고자 ie는 아래와 같은 방법을 썼다.
var input = document.createElement('<input type="hidden" />');

단, 조심할것은 위 코드는 ie에서만 되는것 같다. ff에서는 확실히 안된다.



둘째. 공백을 노드로 인식하느냐 안하느냐 하는 문제.

우선 아래와 같은 HTML 코드가 있다고 하자.
<div id="div1">
    <span id="span1">내용1</span>
   <span id="span2">내용2</span>
   <span id="span3">내용3</span>
    ...(span이 동적이라 몇개가 될지 모름)
</div>



위와같은 상황에서. 모든 span에 특정 동작을 줘야할때.
난 보통 아래처럼 코딩한다.
var spans = document.getElementById('div1').childNodes;
for(var i=0; i<spans.length; i++){
    var span = spans.item(i);
    (span에 이짓저짓)
}


그런데 ff에서 문제가 발생했다.
난 이유를 알 수 없었다. 당연히 되야될 것 같았다.

그러나 저 이짓저짓부분에
alert(span.nodeType);

을 넣어보고 원인을 알 수 있었다.

ie에서는 whitespace(공백,엔터,탭 등)만으로 이루어진 공간을 무시하는데 비해
ff에서는 하나의 textnode로 취급하기때문에 생긴 에러였다.

그러니 이짓저짓 부분에 span.id 따위의 접근을 하면 에러가 날수밖에 없었다.
그래서 해결책으로 아래처럼 if를 추가했다.

var spans = document.getElementById('div1').childNodes;
for(var i=0; i<spans.length; i++){
    var span = spans.item(i);
   if(span.nodeType == 1){
       (span에 이짓저짓)
    }
}

저렇게 if문을 넣어놓으면 textnode를 피해갈 수 있다.
참고로 textnode의 타입은 3이다.

이 프로젝트를 하면서 결심했다.
자바스크립트 노가다에 시간을 쓰느니 걍 prototype쓰자. ㄷㄷㄷ

이 포스트가 여러분의 웹표준 개발에 조금이나마 도움이 되길 바라면서....
사용자 삽입 이미지



License
달리 정하지 않는 한, 이 저작물 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
Except where otherwise noted, this content is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 2.0 Korea License
Mootools에는 Tips라는 클래스가 있다.
이 객체는 Drag.Move클래스처럼 new 키워드로 생성만 해주면 작동하는 방식인데
지정된 객체위에 마우스가 올라가면 선언할때 생성된 div를 마우스 옆에 따라다니도록 만든다.
사용법은 아래와 같다.

var myTips = new Tips(Element들이 들어있는 리스트, 옵션);
예)
var myTips = new Tips($$('img.toolTip'), {maxTitleChars: 50, offsets: {'x': 16, 'y': 16} });





하지만 이번에 Tips를 사용하는 중에 스크롤해도 툴팁은 스크롤을 따라오지못하는 문제를 발견했다.
소스를 공개하자면,

1. 툴팁을 띄울 이미지.
<img id="mapimg" class="toolTip" title="클릭하면 큰화면으로 볼 수 있습니다." src="images/handbook/map.jpg">


2. 스크립트(body의 onload에 실행됨)
var myTips = new Tips($$('img.toolTip'), {
     offsets: {'x': 0, 'y': 20}
});


3. css파일에 툴팁스타일 추가(툴팁의 className은 디폴트가 tool-tip이다)
.tool-tip{
     padding: 3px;
     border: 1px solid rgb(102,102,102);
     background-color: rgb(255,255,153);
}


4. imgElement.href를 하면 src의 내용이 나오기때문에 이미지에서도 주소가 나타나는 문제가 있어서 build메소드에 if 추가
(아마 IE문제인듯.)
...
...
build: function(el){
     if(el.getTag() != 'img') el.myTitle = el.href ? el.href.replace('http://', '') : (el.rel || false);
...
...

*변경결과:
사용자 삽입 이미지

변경 전




사용자 삽입 이미지

변경 후




하지만 스크롤시 문제가 발생! 참고로 브라우저는 IE7이다.

사용자 삽입 이미지

스크롤 전

























사용자 삽입 이미지

스크롤 후














원인을 찾아보니 Tips 클래스에서 마우스 이동시마다 툴팁의 위치를 바꿔주는 locate메소드가 문제였다.
코드를 보면,

locate: function(event){
     var win = {'x': window.getWidth(), 'y': window.getHeight()};
     var scroll = {'x': window.getScrollLeft(), 'y': window.getScrollTop()};
     var tip = {'x': this.toolTip.offsetWidth, 'y': this.toolTip.offsetHeight};
     var prop = {'x': 'left', 'y': 'top'};
     for (var z in prop){
          var pos = event.page[z] + this.options.offsets[z];
          if ((pos + tip[z] - scroll[z]) > win[z]) pos = event.page[z] - this.options.offsets[z] - tip[z];
          this.toolTip.setStyle(prop[z], pos + 'px');
     };
     event.stop();
},


위에 진하게 표시한 부분이 현재 스크롤 위치를 알아내는 부분인데,
window.getScrollTop()의 코드를 보니
getScrollTop: function(){
     return this.pageYOffset || document.documentElement.scrollTop;
},

인데, 테스트해보니 document.documentElement.scrollTop은 항상 0을 리턴하고,
document.body.scrollTop을 써야 제대로 리턴이 되는 것이었다.
(이건 혹시 IE7의문제???)
그래서 일단 위의 getScrollTop메소드를
getScrollTop: function(){
     return this.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
},


로 바꾸어서 body를 먼저 참조하고 undifined일때 documentElement를 참조하도록 했다.
그리고 windows내의 documentElement를 사용하는 모든 메소드에 body참조를 추가했다
(window.getWidth(), window.getHeight(), window.getScrollLeft(), window.getScrollTop() 등등..)

바꾸고나니까 잘 작동한다. 후후후...

하지만,
가면갈수록 싫어지는 IE..
dlrtmvmffhfj wnrdjfk~


License
달리 정하지 않는 한, 이 저작물 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
Except where otherwise noted, this content is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 2.0 Korea License
난 태그를 자바스크립트로 동적 생성할때는 아래처럼 쓰는 버릇이 있었다.

...
var input = document.createElement('input');
input.name = 'id';
input.type = 'text';
form.appendChild(input);
...


MooTools(이하 무툴)를 쓰게 된 이후로는 아래처럼 됐다.


...
var input = new Element('input');
input.setProperties({name: 'id', type: 'text'});
form.adopt(input);
...


이렇게 잘 쓰고 있는데 이상하게 ie6에서만 name이 지정 안되길래 무툴의 소스를 봤더니,


...
setProperties: function(source){
    for (var property in source) this.setProperty(property, source[property]);
    return this;
}

setProperty: function(property, value){
    switch (property){
        case 'class': this.className = value; break;
        case 'style': this.setStyles(value); break;
        case 'name': if (window.ie6){
            var el = $(document.createElement('<'+this.getTag()+' name="'+value+'" />'));
            $each(this.attributes, function(attribute){
                if (attribute.name != 'name') el.setProperty(attribute.name, attribute.value);
            });
            if (this.parentNode) this.replaceWith(el);
            return el;
        }
        default: this.setAttribute(property, value);
    }
    return this;
}
...


이 소스를 보면 name속성 코드가 ie6을 위해 따로 제작되어있다.
하지만 ie6용 코드에서는 자기자신을 바꾸지 않는다. 부모노드를 가진 객체일경우만 새로 생성해서 바꿔준다.
그러나 위에 내가 짠 코드는 속성을 설정한 후에 부모에 붙이기때문에 ie에서 작동하지 않았다..

저 오류를 발견한건 이미 저런 코딩이 몇개 더 있는 상황이라 무툴의 소스를 살짝 고쳐봤다.


setProperty: function(property, value){
    switch (property){
        case 'class': this.className = value; break;
        case 'style': this.setStyles(value); break;
        case 'name': if (window.ie6){
            if (this.parentNode){
                var el = $(document.createElement('<'+this.getTag()+' name="'+value+'" />'));
                $each(this.attributes, function(attribute){
                    if (attribute.name != 'name') el.setProperty(attribute.name, attribute.value);
                });
                this.replaceWith(el);
                return el;
            }else{
                this.name = value;
                break;
            }
        }
        default: this.setAttribute(property, value);
    }
    return this;
}
...


이렇게 바꿔서 잘 되기는 하는데 뭔가 문제가 생길지도..

그런데 이문제는 내 코딩습관이 잘못된건가.. 아님 무툴에서 구현을 잘못한건가...
나도 잘 모르겠다.


License
달리 정하지 않는 한, 이 저작물 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
Except where otherwise noted, this content is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 2.0 Korea License

난 처음엔 시멘틱 웹이라는게 뭔지 몰랐다..
존재자체도 몰랐다

어느날 인터넷 여기저기서 웹 2.0이다 뭐다 하고 떠들어대고 난 후에 AJAX를 알았고
웹2.0에 대에 조사를 하기 시작했다.
AJAX를 코딩해보니 AJAX는 그냥 javascript라는걸 알게 되었다.
그리고 웹2.0에 대해 알면 알수록,
시멘틱웹에 대해 알면 알수록,
다 개소리라는걸 알았다.

그렇다.. 다 개소리다..

시맨틱웹? 웹2,0?
뜬구름잡는 이야기다.
그냥 웹이 발전될 뿐 웹2.0이라는 패러다임은 없다.
웹은 웹이다.



License
달리 정하지 않는 한, 이 저작물 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
Except where otherwise noted, this content is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 2.0 Korea License

+ Recent posts