/**

 * SWFAddress 2.1: Deep linking for Flash and Ajax - http://www.asual.com/swfaddress/

 *

 * SWFAddress is (c) 2006-2007 Rostislav Hristov and is released under the MIT License:

 * http://www.opensource.org/licenses/mit-license.php

 *

 */



if (typeof com == "undefined") var com = {};

if (typeof com.asual == "undefined") com.asual = {};

if (typeof com.asual.util == "undefined") com.asual.util = {};

   

/**

 * @class Utility class that provides detailed browser information.

 * @static

 * @ignore

 */

com.asual.util.Browser = new function() {



    var _version = -1;

    var _agent = navigator.userAgent;

    var _ie = false, _camino = false, _safari = false, _opera = false, 

        _firefox = false, _netscape = false, _mozilla = false;



    var _getVersion = function(s, i) {

        return parseFloat(_agent.substr(_agent.indexOf(s) + i));

    }

    

    if (_ie = /MSIE/.test(_agent))

        _version = _getVersion('MSIE', 4);

        

    if (_safari = /AppleWebKit/.test(_agent))

        _version = _getVersion('Safari', 7);

        

    if (_opera = /Opera/.test(_agent))

        _version = parseFloat(navigator.appVersion);

        

    if (_camino = /Camino/.test(_agent))

        _version = _getVersion('Camino', 7);

        

    if (_firefox = /Firefox/.test(_agent))

        _version = _getVersion('Firefox', 8);

        

    if (_netscape = /Netscape/.test(_agent))

        _version = _getVersion('Netscape', 9);

        

    if (_mozilla = /Mozilla/.test(_agent) && /rv:/.test(_agent))

        _version = _getVersion('rv:', 3);





    /**

     * Detects the version of the browser.

     * @return {Number}

     * @static

     */

    this.getVersion = function() {

        return _version;

    }



    /**

     * Detects if the browser is Internet Explorer.

     * @return {Boolean}

     * @static

     */

    this.isIE = function() {

        return _ie;

    }



    /**

     * Detects if the browser is Safari.

     * @return {Boolean}

     * @static

     */

    this.isSafari = function() {

        return _safari;

    }



    /**

     * Detects if the browser is Opera.

     * @return {Boolean}

     * @static

     */

    this.isOpera = function() {

        return _opera;

    }



    /**

     * Detects if the browser is Camino.

     * @return {Boolean}

     * @static

     */

    this.isCamino = function() {

        return _camino;

    }



    /**

     * Detects if the browser is Firefox.

     * @return {Boolean}

     * @static

     */

    this.isFirefox = function() {

        return _firefox;

    }



    /**

     * Detects if the browser is Netscape.

     * @return {Boolean}

     * @static

     */

    this.isNetscape = function() {

        return _netscape;

    }

        

    /**

     * Detects if the browser is Mozilla.

     * @return {Boolean}

     * @static

     */

    this.isMozilla = function() {

        return _mozilla;

    }

}



/**

 * @class Utility class that provides event helpers.

 * @static

 * @ignore

 */

com.asual.util.Events = new function() {



    var _cache = [];

    var _browser = com.asual.util.Browser;

    var _dcl = 'DOMContentLoaded';



    if (_browser.isIE() || _browser.isSafari()) {

        (function (){

            try {

                if (_browser.isIE() || !/loaded|complete/.test(document.readyState))

                    document.documentElement.doScroll('left');

            } catch(e) {

                return setTimeout(arguments.callee, 0);

            }

            for (var i = 0, e; e = _cache[i]; i++)

                if (e.t == _dcl) e.l.call(null);

        })();

    }



    /**

     * Adds an event listener to an object.

     * @param {Object} obj The object that provides events.

     * @param {String} type The type of the event.

     * @param {Function} listener The event listener function.

     * @return {void}

     * @static

     */

    this.addListener = function(obj, type, listener) {

        _cache.push({o: obj, t: type, l: listener});

        if (!(type == _dcl && (_browser.isIE() || _browser.isSafari()))) {

            if (obj.addEventListener)

                obj.addEventListener(type, listener, false);

            else if (obj.attachEvent)

                obj.attachEvent('on' + type, listener);

        }

    }



    /**

     * Removes an event listener from an object.

     * @param {Object} obj The object that provides events.

     * @param {String} type The type of the event.

     * @param {Function} listener The event listener function.

     * @return {void}     

     * @static

     */

    this.removeListener = function(obj, type, listener) {

        for (var i = 0, e; e = _cache[i]; i++) {

            if (e.o == obj && e.t == type && e.l == listener) {

                _cache.splice(i, 1);

                break;

            }

        }

        if (!(type == _dcl && (_browser.isIE() || _browser.isSafari()))) {

            if (obj.removeEventListener)

                obj.removeEventListener(type, listener, false);

            else if (obj.detachEvent)

                obj.detachEvent('on' + type, listener);

        }

    }



    var _unload = function() {

        for (var i = 0, evt; evt = _cache[i]; i++) {

            if (evt.t != _dcl)

                com.asual.util.Events.removeListener(evt.o, evt.t, evt.l);

        }

    }



    this.addListener(window, 'unload', _unload);

}



/**

 * Creates a new SWFAddress event.

 * @class Event class for SWFAddress.

 * @param {String} type Type of the event.

 */

SWFAddressEvent = function(type) {

    

    /**

     * String representation of this object.

     * @ignore

     */

    this.toString = function() {

        return '[object SWFAddressEvent]';

    }



    /**

     * The type of this event.

     * @type String

     */

    this.type = type;



    /**

     * The target of this event.

     * @type Function

     */

    this.target = [SWFAddress][0];



    /**

     * The value of this event.

     * @type String

     */

    this.value = SWFAddress.getValue();



    /**

     * The path of this event.

     * @type String

     */

    this.path = SWFAddress.getPath();

    

    /**

     * The folders in the deep linking path of this event.

     * @type Array

     */

    this.pathNames = SWFAddress.getPathNames();



    /**

     * The parameters of this event.

     * @type Object

     */

    this.parameters = {};



    var _parametersNames = SWFAddress.getParameterNames();

    for (var i = 0, l = _parametersNames.length; i < l; i++)

        this.parameters[_parametersNames[i]] = SWFAddress.getParameter(_parametersNames[i]);

    

    /**

     * The parameters names of this event.

     * @type Array     

     */

     this.parametersNames = _parametersNames;

}



/**

 * Init event.

 * @type String

 * @memberOf SWFAddressEvent

 * @static

 */

SWFAddressEvent.INIT = 'init';



/**

 * Change event.

 * @type String

 * @memberOf SWFAddressEvent

 * @static 

 */

SWFAddressEvent.CHANGE = 'change';



/**

 * @class The SWFAddress class can be configured with query parameters using the following format:

 * swfaddress.js?html=false&history=1&tracker=pageTracker._trackPageview&strict=1.<br /> 

 * The list of supported options include:<br /><br />

 * <code>history:Boolean</code> - Enables or disables the creation of history entries.<br />

 * <code>html:Boolean</code> - Enables or disables the usage of swfaddress.html.<br />

 * <code>strict:Boolean</code> - Enables or disables the strict mode.<br />

 * <code>tracker:String</code> - Sets a function for page view tracking.<br />

 * @static 

 */ 

SWFAddress = new function() {



    var _browser = com.asual.util.Browser;

    var _events = com.asual.util.Events;

    var _version = _browser.getVersion();

    var _supported = false;



    if (_browser.isIE()) 

        _supported = _version >= 6;

        

    if (_browser.isSafari())

        _supported = _version >= 312;

        

    if (_browser.isOpera())

        _supported = _version >= 9.02;

        

    if (_browser.isCamino()) 

        _supported = _version >= 1;

        

    if (_browser.isFirefox())

        _supported = _version >= 1;

        

    if (_browser.isNetscape())

        _supported = _version >= 8;

        

    if (_browser.isMozilla())

        _supported = _version >= 1.8;



    var _t = top;

    var _d = _t.document;

    var _h = _t.history;

    var _l = _t.location;

    var _st = setTimeout;

    

    var FUNCTION = 'function';

    var UNDEFINED = 'undefined';

    var SWFADDRESS = 'swfaddress';



    var _iframe, _form, _url;

    var _title = _d.title;

    var _length = _h.length;

    var _silent = false;

    var _listeners = {};

    var _stack = [];

    var _ids = [];

    

    var _opts = {};

    _opts.history = true;

    _opts.html = false;

    _opts.strict = true;

    _opts.tracker = '_trackDefault';

    

    if ((!_supported && _l.href.indexOf('#') != -1) || 

        (_browser.isSafari() && _version < 412 && _l.href.indexOf('#') != -1 && _l.search != '')){

        _d.open();

        _d.write('<html><head><meta http-equiv="refresh" content="0;url=' + 

            _l.href.substr(0, _l.href.indexOf('#')) + '" /></head></html>');

        _d.close();

    }



    var _getHash = function() {

        var index = _l.href.indexOf('#');

        if (index != -1) {

            var hash = unescape(_l.href.substr(index + 1));

            if (/^[a-z0-9 ,=_&\-\.\?\+\/]*$/i.test(hash))

                return hash;

            else

                _l.replace(_l.href.substr(0, index));

        }

        return '';

    }



    var _value = _getHash();



    var _strictCheck = function(value, force) {

        if (_opts.strict)

            value = force ? (value.substr(0, 1) != '/' ? '/' + value : value) : (value == '' ? '/' : value);

        return value;

    }



    var _ieLocal = function(value) {

        return (_browser.isIE() && _l.protocol == 'file:') ? _value.replace(/\?/, '%3F') : value;    

    }



    var _searchScript = function(el) {

        if (el.src && /swfaddress\.js(\?.*)?$/.test(el.src)) return el;

        for (var i = 0, l = el.childNodes.length, s; i < l; i++)

            if (s = _searchScript(el.childNodes[i])) return s;

    }

    

    var _titleCheck = function() {

        if (_browser.isIE() && _d.title != _title)

            SWFAddress.setTitle(_title);

    }



    var _listen = function() {

        if (!_silent) {

            var hash = _getHash();

            if (_browser.isIE()) {

                if (_value != hash) {

                    if (_version < 7)

                        _l.reload();

                    else

                        SWFAddress.setValue(hash);

                }

            } else if (_browser.isSafari() && _version < 523) {

                if (_length != _h.length) {

                    _length = _h.length;

                    if (typeof _stack[_length - 1] != UNDEFINED)

                        _value = _stack[_length - 1];

                    _update();

                }

            } else if (_value != hash) {

                _value = hash;

                _update();

            }

            _titleCheck();

        }

    }



    var _jsDispatch = function(type) {

        if (SWFAddress.hasEventListener(type))

            SWFAddress.dispatchEvent(new SWFAddressEvent(type));

        type = type.substr(0, 1).toUpperCase() + type.substr(1);

        if(typeof SWFAddress['on' + type] == FUNCTION)

            SWFAddress['on' + type]();

    }



    var _jsInit = function() {

        _jsDispatch('init');

    }



    var _jsChange = function() {

        _jsDispatch('change');

    }



    var _swfChange = function() {

        for (var i = 0, id, value = SWFAddress.getValue(), setter = 'setSWFAddressValue'; id = _ids[i]; i++) {

            var obj = document.getElementById(id);

            if (obj) {

                if (obj.parentNode && typeof obj.parentNode.so != UNDEFINED) {

                    obj.parentNode.so.call(setter, value);

                } else {

                    if (!(obj && typeof obj[setter] != UNDEFINED)) {

                        var objects = obj.getElementsByTagName('object');

                        var embeds = obj.getElementsByTagName('embed');

                        obj = ((objects[0] && typeof objects[0][setter] != UNDEFINED) ? 

                            objects : ((embeds[0] && typeof embeds[0][setter] != UNDEFINED) ? 

                                embeds[0] : null));

                    }

                    if (obj)

                        obj[setter](value);

                } 

            } else if (obj = document[id]) {

                if (typeof obj[setter] != UNDEFINED)

                    obj[setter](value);

            }

        }

    }



    var _update = function() {

        _swfChange();

        _jsChange();

        _st(_track, 10);

    }



    var _trackDefault = function(value) {

        if (typeof urchinTracker == FUNCTION) 

            urchinTracker(value);

        if (typeof pageTracker != UNDEFINED && typeof pageTracker._trackPageview == FUNCTION)

            pageTracker._trackPageview(value);

    }

    

    eval('var _trackDefault = ' + _trackDefault + ';');

    

    var _track = function() {

        if (typeof _opts.tracker != UNDEFINED && eval('typeof ' + _opts.tracker + ' != "' + UNDEFINED + '"')) {

            var fn = eval(_opts.tracker);

            if (typeof fn == FUNCTION)

                fn((_l.pathname + (/\/$/.test(_l.pathname) ? '' : '/') + SWFAddress.getValue()).replace(/\/\//, '/').replace(/^\/$/, ''));

        }

    }

    

    var _htmlWrite = function() {

        var doc = _iframe.contentWindow.document;

        doc.open();

        doc.write('<script>var ' + SWFADDRESS + ' = "' + _getHash() + '";</script>');

        doc.close();

    }



    var _htmlLoad = function() {

        var win = _iframe.contentWindow;

        if (_opts.html) {

            var src = win.location.href;

            _value = (src.indexOf('?') > -1) ? src.substr(src.indexOf('?') + 1) : '';

        } else {

            _value = (typeof win[SWFADDRESS] != UNDEFINED) ? win[SWFADDRESS] : '';

        }

        win.document.title = _d.title;

        if (_value != _getHash()) {

            _update();

            _l.hash = _ieLocal(_value);

        }

    }



    var _load = function() {

        var attr = 'id="' + SWFADDRESS + '" style="position:absolute;top:-9999px;"';

        if (_browser.isIE()) {

            document.body.appendChild(document.createElement('div')).innerHTML = '<iframe ' + attr + ' src="' + 

                (_opts.html ? _url.replace(/\.js(\?.*)?$/, '.html') + '?' + _getHash() : 'javascript:false;') + 

                '" width="0" height="0"></iframe>';

            _iframe = document.getElementById(SWFADDRESS);

            _st(function() {

                _events.addListener(_iframe, 'load', _htmlLoad);            

                if (!_opts.html && typeof _iframe.contentWindow[SWFADDRESS] == UNDEFINED) 

                    _htmlWrite();

            }, 10);

        } else if (_browser.isSafari()) {

            if (_version < 412) {

                document.body.innerHTML += '<form ' + attr + ' method="get"></form>';

                _form = document.getElementById(SWFADDRESS);

            }

            if (typeof _l[SWFADDRESS] == UNDEFINED) _l[SWFADDRESS] = {};

            if (typeof _l[SWFADDRESS][_l.pathname] != UNDEFINED) _stack = _l[SWFADDRESS][_l.pathname].split(',');

        } else if (_browser.isOpera() && _ids.length == 0 && typeof navigator.plugins['Shockwave Flash'] == 'object') {

            document.body.innerHTML += '<embed ' + attr + ' src="' + _url.replace(/\.js(\?.*)?$/, '.swf') + 

                '" type="application/x-shockwave-flash" />';

        }

        _st(_jsInit, 1);

        _st(_jsChange, 2);

        _st(_track, 10);

        setInterval(_listen, 50);

    }



    /**

     * Init event.

     * @type Function

     * @event

     * @static

     */

    this.onInit = null;

    

    /**

     * Change event.

     * @type Function

     * @event

     * @static

     */

    this.onChange = null;

    

    /**

     * String representation of this class.

     * @ignore

     */

    this.toString = function() {

        return '[class SWFAddress]';

    }



    /**

     * Loads the previous URL in the history list.

     * @return {void}

     * @static

     */

    this.back = function() {

        _h.back();

    }



    /**

     * Loads the next URL in the history list.

     * @return {void}

     * @static

     */

    this.forward = function() {

        _h.forward();

    }



    /**

     * Loads a URL from the history list.

     * @param {Number} delta An integer representing a relative position in the history list.

     * @return {void}

     * @static

     */

    this.go = function(delta) {

        _h.go(delta);

    }



    /**

     * Opens a new URL in the browser. 

     * @param {String} url The resource to be opened.

     * @param {String} target Target window.

     * @return {void}

     * @static

     */

    this.href = function(url, target) {

        target = (typeof target != UNDEFINED) ? target : '_self';     

        if (target == '_self')

            self.location.href = url; 

        if (target == '_top')

            _l.href = url; 

        if (target == '_blank')

            window.open(url); 

        else

            _t.frames[target].location.href = url; 

    }



    /**

     * Opens a browser popup window. 

     * @param {String} url Resource location.

     * @param {String} name Name of the popup window.

     * @param {String} options Options which get evaluted and passed to the window.open() method.

     * @param {String} handler Optional JavaScript code for popup handling.    

     * @return {void}

     * @static

     */

    this.popup = function(url, name, options, handler) {

        var popup = window.open(url, name, eval(options));

        eval(handler);

    }



    /**

     * Registers an event listener.

     * @param {String} type Event type.

     * @param {Function} listener Event listener.

     * @return {void}

     * @static

     */

    this.addEventListener = function(type, listener) {

        if (typeof _listeners[type] == UNDEFINED)

            _listeners[type] = [];

        _listeners[type].push(listener);

    }



    /**

     * Removes an event listener.

     * @param {String} type Event type.

     * @param {Function} listener Event listener.

     * @return {void}

     * @static     

     */

    this.removeEventListener = function(type, listener) {

        if (typeof _listeners[type] != UNDEFINED) {

            for (var i = 0, l; l = _listeners[type][i]; i++)

                if (l == listener) break;

            _listeners[type].splice(i, 1);

        }

    }



    /**

     * Dispatches an event to all the registered listeners. 

     * @param {Object} event Event object.

     * @return {Boolean}

     * @static

     */

    this.dispatchEvent = function(event) {

        if (typeof _listeners[event.type] != UNDEFINED && _listeners[event.type].length) {

            event.target = this;

            for (var i = 0, l; l = _listeners[event.type][i]; i++)

                l(event);

            return true;           

        }

        return false;

    }



    /**

     * Checks the existance of any listeners registered for a specific type of event. 

     * @param {String} event Event type.

     * @return {Boolean}

     * @static

     */

    this.hasEventListener = function(type) {

        return (typeof _listeners[type] != UNDEFINED && _listeners[type].length > 0);

    }

    

    /**

     * Provides the base address of the document. 

     * @return {String}

     * @static

     */

    this.getBaseURL = function() {

        var url = _l.href;

        if (url.indexOf('#') != -1)

            url = url.substr(0, url.indexOf('#'));

        if (url.substr(url.length - 1) == '/')

            url = url.substr(0, url.length - 1);

        return url;

    }



    /**

     * Provides the state of the strict mode setting. 

     * @return {Boolean}

     * @static

     */

    this.getStrict = function() {

        return _opts.strict;

    }



    /**

     * Enables or disables the strict mode.

     * @param {Boolean} strict Strict mode state.

     * @return {void}

     * @static

     */

    this.setStrict = function(strict) {

        _opts.strict = strict;

    }



    /**

     * Provides the state of the history setting. 

     * @return {Boolean}

     * @static

     */

    this.getHistory = function() {

        return _opts.history;

    }



    /**

     * Enables or disables the creation of history entries.

     * @param {Boolean} history History state.

     * @return {void}

     * @static

     */

    this.setHistory = function(history) {

        _opts.history = history;

    }



    /**

     * Provides the tracker function.

     * @return {String}

     * @static

     */

    this.getTracker = function() {

        return _opts.tracker;

    }



    /**

     * Sets a function for page view tracking. The default value is 'urchinTracker'.

     * @param {String} tracker Tracker function.

     * @return {void}

     * @static

     */

    this.setTracker = function(tracker) {

        _opts.tracker = tracker;

    }



    /**

     * Provides a list of all the Flash objects registered. 

     * @return {Array}

     * @static

     */

    this.getIds = function() {

        return _ids;

    }



    /**

     * Provides the id the first and probably the only Flash object registered. 

     * @return {String}

     * @static

     */

    this.getId = function(index) {

        return _ids[0];

    }



    /**

     * Sets the id of a single Flash object which will be registered for deep linking.

     * @param {String} id ID of the object.

     * @return {void}

     * @static

     */

    this.setId = function(id) {

        _ids[0] = id;

    }



    /**

     * Adds an id to the list of Flash object registered for deep linking.

     * @param {String} id ID of the object.

     * @return {void}

     * @static

     */

    this.addId = function(id) {

        this.removeId(id);

        _ids.push(id);

    }



    /**

     * Removes an id from the list of Flash object registered for deep linking.

     * @param {String} id ID of the object.

     * @return {void}

     * @static

     */

    this.removeId = function(id) {

        for (var i = 0; i < _ids.length; i++) {

            if (id == _ids[i]) {

                _ids.splice(i, 1);

                break;

            }

        }

    }



    /**

     * Provides the title of the HTML document.

     * @return {String}

     * @static

     */

    this.getTitle = function() {

        return _d.title;

    }



    /**

     * Sets the title of the HTML document.

     * @param {String} title Title value.

     * @return {void}

     * @static

     */

    this.setTitle = function(title) {

        if (!_supported) return null;

        if (typeof title == UNDEFINED) return;

        if (title == 'null') title = '';

        _title = _d.title = title;

        _st(function() {

            if (_iframe && _iframe.contentWindow && _iframe.contentWindow.document && _iframe.contentWindow.title)

                _iframe.contentWindow.document.title = _title;

         }, 1000);

    }



    /**

     * Provides the status of the browser window.

     * @return {String}

     * @static

     */

    this.getStatus = function() {

        return _t.status;

    }



    /**

     * Sets the status of the browser window.

     * @param {String} status Status value.

     * @return {void}

     * @static

     */

    this.setStatus = function(status) {

        if (!_supported) return null;

        if (typeof status == UNDEFINED) return;

        if (!_browser.isSafari()) {

            status = _strictCheck((status != 'null') ? status : '', true);

            if (status == '/') status = '';

            if (!(/http(s)?:\/\//.test(status))) {

                var index = _l.href.indexOf('#');

                status = (index == -1 ? _l.href : _l.href.substr(0, index)) + '#' + status;

            }

            _t.status = status;

        }

    }



    /**

     * Resets the status of the browser window.

     * @return {void}

     * @static

     */

    this.resetStatus = function() {

        _t.status = '';

    }



    /**

     * Provides the current deep linking value.

     * @return {String}

     * @static

     */

    this.getValue = function() {

        if (!_supported) return null;

        return _strictCheck(_value, false);

    }



    /**

     * Sets the current deep linking value.

     * @param {String} value A value which will be appended to the base link of the HTML document.

     * @return {void}

     * @static

     */

    this.setValue = function(value) {

        if (!_supported) return null;

        if (typeof value == UNDEFINED) return;

        if (value == 'null') value = ''

        value = _strictCheck(value, true);

        if (value == '/') value = '';

        if (_value == value) return;

        _value = value;

        _silent = true;

        _update();

        _stack[_h.length] = _value;

        if (_browser.isSafari()) {

            if (_opts.history) {

                _l[SWFADDRESS][_l.pathname] = _stack.toString();

                _length = _h.length + 1;

                if (_version < 412) {

                    if (_l.search == '') {

                        _form.action = '#' + _value;

                        _form.submit();

                    }

                } else if (_version < 523){

                    var evt = document.createEvent('MouseEvents');

                    evt.initEvent('click', true, true);

                    var anchor = document.createElement('a');

                    anchor.href = '#' + _value;

                    anchor.dispatchEvent(evt);                

                } else {

                    _l.hash = '#' + _value;

                }

            } else {

                _l.replace('#' + _value);

            }

        } else if (_value != _getHash()) {

            if (_opts.history)

                _l.hash = '#' + _ieLocal(_value);

            else

                _l.replace('#' + _value);

        }

        if (_browser.isIE() && _opts.history) {

            if (_opts.html) {

                var loc = _iframe.contentWindow.location;

                loc.assign(loc.pathname + '?' + _getHash());

            } else {

                _htmlWrite();

            }

        }

        if (_browser.isSafari())

            _st(function(){ _silent = false; }, 1);

        else

            _silent = false;

    }



    /**

     * Provides the deep linking value without the query string.

     * @return {String}

     * @static

     */

    this.getPath = function() {

        var value = this.getValue();

        return (value.indexOf('?') != -1) ? value.split('?')[0] : value;

    }



    /**

     * Provides a list of all the folders in the deep linking path.

     * @return {Array}

     * @static

     */

    this.getPathNames = function() {

        var path = SWFAddress.getPath();

        var names = path.split('/');

        if (path.substr(0, 1) == '/')

            names.splice(0, 1);

        if (path.substr(path.length - 1, 1) == '/')

            names.splice(names.length - 1, 1);

        return names;

    }



    /**

     * Provides the query string part of the deep linking value.

     * @return {String}

     * @static

     */

    this.getQueryString = function() {

        var value = this.getValue();

        var index = value.indexOf('?');

        return (index != -1 && index < value.length) ? value.substr(index + 1) : '';

    }



    /**

     * Provides the value of a specific query parameter.

     * @param {String} param Parameter name.

     * @return {String}

     * @static

     */

    this.getParameter = function(param) {

        var value = this.getValue();

        var index = value.indexOf('?');

        if (index != -1) {

            value = value.substr(index + 1);

            var params = value.split('&');

            var p, i = params.length;

            while(i--) {

                p = params[i].split('=');

                if (p[0] == param)

                    return p[1];

            }

        }

        return '';

    }



    /**

     * Provides a list of all the query parameter names.

     * @return {Array}

     * @static

     */

    this.getParameterNames = function() {

        var value = this.getValue();

        var index = value.indexOf('?');

        var names = [];

        if (index != -1) {

            value = value.substr(index + 1);

            if (value != '' && value.indexOf('=') != -1) {

                var params = value.split('&');

                var i = 0;

                while(i < params.length) {

                    names.push(params[i].split('=')[0]);

                    i++;

                }

            }

        }

        return names;

    }



    if (_supported) {

    

        for (var i = 1; i < _length; i++)

            _stack.push('');

            

        _stack.push(_getHash());

    

        if (_browser.isIE() && _l.hash != _getHash())

            _l.hash = '#' + _ieLocal(_getHash());

    

        try {

            _url = String(_searchScript(document).src);

            var qi = _url.indexOf('?');

            if (_url && qi > -1) {

                var param, params = _url.substr(qi + 1).split('&');

                for (var i = 0, p; p = params[i]; i++) {

                    param = p.split('=');

                    if (/^(history|html|strict)$/.test(param[0]))

                        _opts[param[0]] = (isNaN(param[1]) ? eval(param[1]) : (parseFloat(param[1]) > 0));

                    if (/^tracker$/.test(param[0]))

                        _opts[param[0]] = param[1];

                }

            }

        } catch(e) {}

        if (/file:\/\//.test(_l.href)) _opts.html = false;

    

        _titleCheck();

        _events.addListener(document, 'DOMContentLoaded', _load);

    

    } else {

        _track();

    }

}



/**

 * SWFAddress embed hooks.

 * @ignore

 */

new function() {



    var _func, _args;

    var UNDEFINED = 'undefined';



    if (typeof swfobject != UNDEFINED) SWFObject = swfobject;

    if (typeof FlashObject != UNDEFINED) SWFObject = FlashObject;

    

    if (typeof SWFObject != UNDEFINED) {

        if (SWFObject.prototype && SWFObject.prototype.write) {

            _func = SWFObject.prototype.write;

            SWFObject.prototype.write = function() {

                _args = arguments;

                if (this.getAttribute('version').major < 8) {

                    this.addVariable('$swfaddress', SWFAddress.getValue());

                    ((typeof _args[0] == 'string') ? 

                        document.getElementById(_args[0]) : _args[0]).so = this;

                }

                var success;

                if (success = _func.apply(this, _args))

                    SWFAddress.addId(this.getAttribute('id'));

                return success;

            }

        } else {

            _func = SWFObject.registerObject;

            SWFObject.registerObject = function() {

                _args = arguments;

                _func.apply(this, _args);

                SWFAddress.addId(_args[0]);            

            }

            _func = SWFObject.createSWF;

            SWFObject.createSWF = function() {

                _args = arguments;

                _func.apply(this, _args);

                SWFAddress.addId(_args[0].id);            

            }

            _func = SWFObject.embedSWF;

            SWFObject.embedSWF = function() {

                _args = arguments;

                _func.apply(this, _args);

                SWFAddress.addId(_args[8].id);            

            }

        }

    }

    

    if (typeof UFO != UNDEFINED) {

        _func = UFO.create;

        UFO.create = function() {

            _args = arguments;

            _func.apply(this, _args);

            SWFAddress.addId(_args[0].id);        

        }

    }

    

    if (typeof AC_FL_RunContent != UNDEFINED) {

        _func = AC_FL_RunContent;

        AC_FL_RunContent = function() {

            _args = arguments;        

            _func.apply(this, _args);

            for (var i = 0, l = _args.length; i < l; i++)

                if (_args[i]== 'id') SWFAddress.addId(_args[i+1]);

        }

    }

}