﻿function hash_library() {
    var _hash = '';
    var _iframe;
    var _iframe_name = 'hash_history_iframe';
    var _initialized = false;
    var _callback_function = false;

    function _callback() {
        if (_hash != _get_hash()) {
            if (typeof (_callback_function) == 'function') {
                try {
                    _callback_function();
                } catch (e) { }
            }

            _hash = _get_hash();
        }
    }

    function _initialize() {
        if (!_initialized) {
            _hash = _get_hash();

            if (window && window.history && window.history.navigationMode) {
                window.history.navigationMode = 'compatible';
            }

            if (window && 'onhashchange' in window) {
                if (typeof window.addEventListener != 'undefined') {
                    window.addEventListener('hashchange', _callback, false);
                }
                else if (typeof window.attachEvent != 'undefined') {
                    window.attachEvent('onhashchange', _callback);
                }
                else {
                    window.onhashchange = _callback;
                }

                _initialized = true;
            }
            else {
                if (document && document.body && document.body.firstChild && 'createElement' in document) {
                    _iframe = document.createElement('iframe');

                    if (_iframe && _iframe.style) {
                        _iframe.style.visibility = 'hidden';
                        _iframe.style.display = 'none';
                        _iframe.style.position = 'absolute';
                        _iframe.style.zIndex = '-9999';
                        _iframe.style.left = '0px';
                        _iframe.style.top = '0px';
                        _iframe.style.width = '1px';
                        _iframe.style.height = '1px';
                        _iframe.name = _iframe.id = _iframe_name;

                        _iframe = document.body.insertBefore(_iframe, document.body.firstChild);

                        _set_iframe(_get_hash());

                        _initialized = true;
                    }
                }
            }
        }
    }

    function _get_hash() {
        var ret = '';

        if (!ret) {
            if (window && window.location && window.location.href) {
                var index = location.href.lastIndexOf('#');

                if (index >= 0) {
                    ret = location.href.substr(index + 1);
                }
            }
        }

        if (!ret) {
            if (window && window.location && window.location.hash) {
                ret = window.location.hash;
            }
        }

        if (ret) {
            ret = ret.replace('#', '');
        }

        return ret;
    }

    function _set_iframe(hash) {
        if (_iframe) {
            if (_iframe.contentWindow && _iframe.contentWindow.document) {
                _iframe.contentWindow.document.open();
                _iframe.contentWindow.document.write('<html><head><title></title><script language="javascript" type="text/javascript">_onload = function() { if (window && window.parent && window.parent._hash && window.parent._hash.set_hash) { window.parent._hash.set_hash("' + hash + '", true); } }</script></head><body onload="_onload();"></body></html>');
                _iframe.contentWindow.document.close();
            }
            else if (window && window.frames[_iframe_name]) {
                window.frames[_iframe_name].location = _root + 'hash_history.htm?' + hash;
            }
            else {
                _iframe.src = _root + 'hash_history.htm?' + hash;
            }
        }
    }

    function _set_hash(hash, from_iframe) {

        if (_hash != hash) {
            if (window && window.location) {
                _initialize();

                if (_get_hash() != hash) {
                    window.location.hash = hash;
                }

                if (!from_iframe) {
                    _hash = hash;             
                    _set_iframe(hash);
                }
                else {
                    _callback();
                    _hash = hash;             
                }                
            }
        }
    }

    function _set_callback(callback) {
        _callback_function = callback;
    }

    var _root = '/';

    this.set_root = function(r) { _root = r; };
    this.set_hash = _set_hash;
    this.get_hash = _get_hash;
    this.set_callback = _set_callback;
}
