Ajax 뒤로가기 문제 해결

2015. 3. 11. 15:10프로그래밍/Javascript

    목차
ajax 사용시 뒤로가기 버튼을 사용하게 되면 기존에 값을 유지하지 못하는 문제가 발생하는데

그 문제를 해결할만한 코드를 발견하여 남겨 놓는다.


- PDF 화면

- 원문 URL
http://firejune.com/981/Ajax+%EC%9A%94%EC%B2%AD%EC%8B%9C+%EB%92%A4%EB%A1%9C%EA%B0%80%EA%B8%B0(%EB%B0%B1%EB%B2%84%ED%8A%BC)+%EB%AC%B8%EC%A0%9C+%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0


[원문]

최근 블로그에 Ajax를 반영하면서 맞닥드린 난관은 브라우저의 뒤로가기, 앞으로가기 그리고 새로고침 버튼입니다. Ajax로 불러들인 문서는 페이지를 로드하지 않고 필요한 부분만 가지고 오기 때문에 브라우저의 히스토리에 흔적을 남기지 않습니다. 덕분에 유저들이 가장 많이 사용하는 브라우저의 기본기능 중 하나인 뒤로가기 버튼이 제대로 작동하지 않아 혼란을 겪게되고, 방문객은 본의 아니게 사이트를 떠나게 될수도 있다고 경고하는 출판물을 접한적이 있습니다.

이 문제를 해결하고자 이곳 저곳을 싸돌아 다니던 중 The Rails-spinoffs Archives에 'Ajax Bookmarks & Browser Navigation'라는 주제로 작성된 Ajax사용시 백버튼 이슈 중에서 Siegfried Puchbauer씨가 작성한 내용과 코드를 발견했습니다. Prototype의 Ajax.request 또는 Ajax.update를 사용할 때 해시 히스토리를 만들어 앞으로/뒤로 가기 문제를 해결하고 있습니다. 이것은 구글이 즐겨 사용하는 Ajax트릭과 흡사합니다.(예를 들면 피카사 웹앨범)

[코드]


Ajax.History = {
    initialize: function(options) {
        this.options = Object.extend({
            interval: 200
        },options||{});
        this.callback = this.options.callback || Prototype.emtpyfunction;
        if(navigator.userAgent.toLowerCase().indexOf('msie') > 0)
            this.locator = new Ajax.History.Iframe('ajaxHistoryHandler', this.options.iframeSrc);
        else
            this.locator = new Ajax.History.Hash();
        this.currentHash = '';
        this.locked = false;
    },
    add: function(hash) {
        this.locked = true;
        clearTimeout(this.timer);
        this.currentHash = hash;
        this.locator.setHash(hash);
        this.timer = setTimeout(this.checkHash.bind(this), this.options.interval);
        this.locked = false;
    },
    checkHash: function(){
        if(!this.locked){
            var check = this.locator.getHash();

            if(check != this.currentHash){
                this.callback(check);
                this.currentHash = check;
            }
        }
        this.timer = setTimeout(this.checkHash.bind(this), this.options.interval);
    },
    getBookmark: function(){
        return this.locator.getBookmark();
    }
};

// Hash Handler for IE (Tested with IE6)
Ajax.History.Iframe = Class.create();
Ajax.History.Iframe.prototype = {
    initialize: function(id, src) {
        this.url = '';
        this.id = id || 'ajaxHistoryHandler';
        this.src = src || '';
        document.write('<iframe src="'+this.src+'" id="'+this.id+'"name="'+this.id+'" style="display: none;" ></iframe>');
    },
    setHash: function(hash){
        try {
            $(this.id).setAttribute('src', this.src + '?' + hash);
        }catch(e) {}
        window.location.href = this.url + '#' + hash;
    },
    getHash: function(){
        try {
            return (document.frames[this.id].location.href||'?').split('?')[1];
        }catch(e){ return ''; }
    },
    getBookmark: function(){
        try{
            return window.location.href.split('#')[1]||'';
        }catch(e){ return ''; }
    }
};

// Hash Handler for a modern browser (tested with firefox 1.5)
Ajax.History.Hash = Class.create();
Ajax.History.Hash.prototype = {
    initialize: function(){
    },
    setHash: function(hash){
        window.location.hash = hash;
    },
    getHash: function(){
        return window.location.hash.substring(1)||'';
    },
    getBookmark: function(){
        try{
            return window.location.hash.substring(1)||'';
        }catch(e){ return ''; }
    }



[사용방법]

위와 같은 코드를 로드한 후 아래처럼 콜백 메서드를 히스토리 핸들러에 Ajax 요청을 보낼 수 있습니다.


var historyUpdate = function(hash) {

new Ajax.Request(

....

}


Prototype의 Ajax.Request 또는 Ajax.Updater를 사용할 때 onSuccess 및 onComplete 메서드에 히스토리를 아래와 같이 추가할 수 있습니다.


var handleSuccess = function(request){

    //... update DOM or smth like that

    Ajax.History.add(request.options.parameters)

    ...

}


그리고 페이지 푸터에 아래의 코드를 실행하도록 합니다.

var historyHandler = Ajax.History.initialize({
    callback: historyUpdate,
    iframeSrc: '_blank.html' // 비어있는 임시 html 페이지 경로
});