javascript

IE6(internet Explorer 6) 에서 jQuery history plugin사용중에 hash값을 잘못 가져오는 현상

jeeyong 2011. 2. 24. 14:48

테스트 URL ) http://iamnotokay.com/main.htm#a.htm?id=123
위의 URL의 hash값을 가져오려고 할때

일반 IE6를 제외한 브라우저는 parameter값을 포함한 #a.htm?id=123 값을 가져오는 반면,

IE6 브라우저에선 parameter값을 포함하지 않은 #a.htm 값만 가져온다.

그로인해 jQuery history plugin을(2010-09-11 까지 릴리즈)  사용할경우 위와 같은 페이지를 가져오려고 하면 오류가 날 수밖에 없다. 

해결방법은 기존 소스에 hash 태그를 가져오는 방법을 수정하는 수 밖에 없기때문에 plugin 수정이 불가피하다.

문제가 되는 소스 부분은

jquery.history.js 원본 소스

var locationWrapper = {
        put: function(hash, win) {
            (win || window).location.hash = this.encoder(hash);
        },
        get: function(win) {
            var hash = ((win || window).location.hash).replace(/^#/, '');
            try {
                return $.browser.mozilla ? hash : decodeURIComponent(hash);
            }
            catch (error) {
                return hash;
            }
        },
        encoder: encodeURIComponent
    };

위 빨간 글씨 부분이 된다. 위 소스에서 보면 location.hash 객체로 값을 가져오려고 하는데 대부분의 브라우저에서는 parameter 값이 포함되지 않는다.

수정된 소스

var locationWrapper = {
        put: function(hash, win) {
            (win || window).location.hash = this.encoder(hash);
        },
        get: function(win) {
         /*
         * modified by jeeyong
         * start.
         */
            var hash;
            if($.browser.version == 6  || document.documentMode == 6){
             hash = ((win || window).location.href).substring(((win || window).location.href).indexOf("#")+1,(win || window).location.href.length);
            }else{
             hash = ((win || window).location.hash).replace(/^#/, '');
            }
            /*
         * modified by jeeyong
         * end.
         */
            try {
                return $.browser.mozilla ? hash : decodeURIComponent(hash);
            }
            catch (error) {
                return hash;
            }
        },
        encoder: encodeURIComponent
    };

그렇기 때문에 IE6에선 hash 객체로 가져오는 것이 아닌 location.href 객체를 통해 full url 주소를 가져와서 hash값만 따오는 것으로 오류를 방지할수있다.

작업을 하면서 오류가 될만한 문제를 하나더 찾았는데

jquery.history.js 원본 소스

implementations.iframeTimer = {
        _appState: undefined,
        _init: function() {
            var current_hash = locationWrapper.get();
            self._appState = current_hash;
            iframeWrapper.init().put(current_hash);
            self.callback(current_hash);
            setInterval(self.check, 100);
        },
        check: function() {
            var iframe_hash = iframeWrapper.get(),
                location_hash = locationWrapper.get();

            if (location_hash != iframe_hash) {
                if (location_hash == self._appState) {    // user used Back or Forward button
                    self._appState = iframe_hash;
                    locationWrapper.put(iframe_hash);
                    self.callback(iframe_hash); 
                } else {                              // user loaded new bookmark
                    self._appState = location_hash;  
                    iframeWrapper.put(location_hash);
                    self.callback(location_hash);
                }
            }
        },
        load: function(hash) {
            if(hash != self._appState) {
                locationWrapper.put(hash);
                iframeWrapper.put(hash);
                self._appState = hash;
                self.callback(hash);
            }
        }
    };

위 소스에서 빨간 글씨로 되어있는 setInterval 함수가 그것이다.
IE6에서는 저 함수로 계속 url주소를 체크하도록 되어있는데 왜 저렇게 되어있는지는 해당 플러그인 사이트의 history를 통해 확인해보고 

수정된 소스

implementations.iframeTimer = {
        _appState: undefined,
        _init: function() {
            var current_hash = locationWrapper.get();
            self._appState = current_hash;
            iframeWrapper.init().put(current_hash);
            self.callback(current_hash);
            // modified by jeeyong
            if($.browser.version != 6  || document.documentMode != 6)
             setInterval(self.check, 100);
        },
        check: function() {
            var iframe_hash = iframeWrapper.get(),
                location_hash = locationWrapper.get();

            if (location_hash != iframe_hash) {
                if (location_hash == self._appState) {    // user used Back or Forward button
                    self._appState = iframe_hash;
                    locationWrapper.put(iframe_hash);
                    self.callback(iframe_hash);
                } else {                              // user loaded new bookmark
                    self._appState = location_hash;
                    iframeWrapper.put(location_hash);
                    self.callback(location_hash);
                }
            }
        },
        load: function(hash) {
            if(hash != self._appState) {
                locationWrapper.put(hash);
                iframeWrapper.put(hash);
                self._appState = hash;
                self.callback(hash);
            }
        }
    };

IE6에서는 호출하지않도록 막아놨다. 저렇게 하지 않으면 계속 호출을 하게되는 현상이 발생해서 브라우저가 다운되버리는 버그가 생긴다.