var WebApp = (function() {
    var L2R = +1;
    var R2L = -1;
    var INV = -1;    // INVERT

    var HEAD = 0;
    var HOME = 1;
    var BACK = 2;
    var LEFT = 3;
    var RIGHT = 4;
    var TITLE = 5;

    var _def, _headView, _head;
    var _webapp, _group, _bdo;

    var _prev        = -1;
    var _historyPos  = -1;    // warning: must order properly var names for reduction script
    var _location    = [];
    var _history     = [];
    var _scroll      = [];
    var _loader      = [];
    var _fading      = [];
    var _header      = [];
    var _ajax        = [];
    var _initialNav  = history.length;
    var _sliding     = 0;
    var _hold        = false;
    var _baseTitle   = "";
    var _baseBack    = "";
    var _lockCnt     = 0;
    var _width       = 0;
    var _lastScroll  = 1;
    var _dialog      = null;
    var _v2          = 0 && !(!document.getElementsByClassName) && Contains("WebKit", navigator.userAgent);
    var _moving      = -1;
    var _fullscreen  = false;
    var _proxy       = "";

    var _handler     = {};
    _handler.load    = [];
    _handler.beginslide = [];
    _handler.endslide   = [];
    _handler.orientationchange = [];
    _handler.error             = [];

/* Public */
    __p = {
        SetDefault: function(layer) { _def = layer },
        Proxy: function(url) { _proxy = url; },

        HideBar: function() {
            window.scrollTo(0, 1);
            return false;
        },

        Header: function(show, what) {
            Buttons(show);
            Display(_headView, 0);
            _headView = $(what);
            Display(_headView, !show);
            return false;
        },

        Tab: function(id, active) {
            var o = $(id);
            ShowTab(o, $$("li", o)[active]);
        },

        AddEventListener: function(evt, handler) {
            if (typeof _handler[evt] != "undefined")
                if (_handler[evt].indexOf(handler) == -1)
                    _handler[evt].push(handler);
        },

        Toggle: function() {
            if (_history.length > 1) {
                if (_historyPos == _history.length - 1)
                    history.back();
                else
                    history.forward();
            }
            return false;
        },

        Back: function() {
            if (_hold)
                return (_hold = false);

            if (history.length - _initialNav == _historyPos)
                history.back();
            else
                location = _location[_historyPos - 1] || "#";
            return false;
        },

        Home: function() {
            if (history.length - _initialNav == _historyPos)
                history.go(-_historyPos);
            else
                location = "#";
            return (_hold = false);
        },

        Form: function(frm) {
            var s, a, b, c, o, f;

            a = $(frm);
            b = $(_history[_historyPos]);
            s = (a.style.display != "block");

            f = GetName(a) == "form" ? a : GetParent(a, "form");
            o = f.onsubmit;
            if (!s) {
                f.onsubmit = f.onsubmit(null, true);
            } else {
                a.style.top = parseInt($("__wa_shadow").style.top) - 2 + "px";

                f.onsubmit = function(e, b) {
                    if (b) return o;
                    if (o) o(e);

                    e.preventDefault();
                    __p.Submit(this);
                };
            }

            AdjustView();
            Shadow(s);
            Display(a, s);
            SetTitle(s ? $$("legend", a)[0].innerHTML : 
                            (_historyPos ? b.title : null) );

            _dialog = (s) ? a : null;
            if (s) { c = a; a = b; b = c }

            DelLayerButtons(a);
            AddLayerButtons(b, s);

            if (s)    __p.Header(s);
            else    Buttons(!s);

            return false;
        },

        Submit: function(frm, e) {
            if (!e) if (window.event) e = window.event;
            if (!e) if (typeof(event) != 'undefined') e = event;
            
            var f = $(frm);
            if(f && GetName(f) != "form") f = GetParent(f, "form");
            if (f) {
                var _ = function(i, f) {
                    var q = "";
                    for (var n = 0; n < i.length; n++)
                        if (i[n].name && !i[n].disabled && (f ? f(i[n]) : 1))
                            q += "&" + i[n].name + "=" + encodeURIComponent(i[n].value);
                    return q;
                }

                var q  = _($$("input", f),
                    function(i) {
                        with(i) return ((Contains(type, ["text", "password", "hidden", "search"]) ||
                                        (Contains(type, ["radio", "checkbox"]) && checked)))
                    });
                    q += _($$("select", f));
                    q += _($$("textarea", f));

                var a  = !a ? GetLink(e.target) : a;
                if (!a) FocusFixer();
                q += "&" + (a && a.id ? a.id : "__submit") + "=1";
                q  = q.substr(1);

                BasicAsync(f.action || self.location.href, null, q);
                if (_dialog) __p.Form(_dialog);
            }
            return false;
        },

        Postable: function(keys, values) {
            var q = "";
            for (var i = 1; i < values.length && i <= keys.length; i++)
                q += "&" + keys[i - 1] + "=" + encodeURIComponent(values[i]);
            return q.replace(/&=/g, "&").substr(1);
        },

        Request: function(url, prms, cb, async, loader) {
            // If it's android webapp, start the loading icon
            if (typeof(window.tsheets) != 'undefined') window.tsheets.startIndeterminate();

            cb = cb == -1 ? DefaultCallback() : cb;

            var o = new XMLHttpRequest();
            var c = function() { __callback(o, cb, loader) };
            var m = prms ? "post" : "get";

            async = (!async ? false : true);
            if (loader) __p.Loader(loader, true);
            if (_handler.error.length > 0)
                _ajax[_ajax.length] = [o, url, prms];

            url = AddParam(url, "__async", "true");
            url = AddParam(url, "__source", _history[_historyPos]);
            url = SetURL(url);

            o.open(m, url, async);
            if (prms) o.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            o.onreadystatechange = (async) ? c : null;
            o.send(prms);

            if (!async) c();
        },

        Loader: function(obj, show) {
            var o = obj;
            var h = HasClass(o, "__lod");
            if (h == show)
                return h;
            // Show the loader icon
            if (show) {
                AddClass(o, "__lod");
                _loader.push(o);
                // If it's android webapp, start the loading icon
                if (typeof(window.tsheets) != 'undefined') window.tsheets.startIndeterminate();
            }
            // Hide the loader icon
            else {
                DelClass(o, "__lod");
                // If it's android webapp, stop the loading icon
                if (typeof(window.tsheets) != 'undefined') window.tsheets.stopIndeterminate();
            }

            ApplyMore(o);
            return h;
        },
        
        Player: function(src) {
            src = src || GetLink(event.target).href;
            if (!IsMobile()) {
                window.open(src);
            } else {
                var o = $("__wa_media");
                if (o) delete _webapp.removeChild(o);

                o = NewItem("iframe");
                o.id = "__wa_media";
                o.src = src;            /* must be before appendChild to prevent Safari weird behavior */

                _webapp.appendChild(o);
            }
            return false;
        },

        FullScreen: function() {
            if (_v2) {
                var fnd = false;
                var mta = $$("meta");
                for (var i = 0; i < mta.length && !fnd; i++)
                    fnd = (mta[i].name == "apple-touch-fullscreen");
                if (fnd) mta = mta[i - 1];

                var arg = arguments;
                if (arg.length) {
                    if (!fnd) {
                        mta = NewItem("meta");
                        mta.name = "apple-touch-fullscreen";
                        $$("head")[0].appendChild(mta);
                    }
                    mta.content = arg[0] ? "YES" : "NO";
                }
                if (mta) _fullscreen = (mta.content == "YES");
            }

            return _fullscreen;
        }
    }

    function ApplyMore(o) {
        if (HasClass(o, "iMore")) {
            var a = $$("a", o)[0];
            if (a.title) {
                o = a.innerHTML;
                a.innerHTML = a.title;
                a.title = o;
            }
        }
    }

    function FocusFixer() {
        var i = NewItem("input");
        _group.appendChild(i);
        i.type = "text";
        i.focus();
        Display(i, 0);
        setTimeout(function() { delete _group.removeChild(i) }, 5);
    }

    function Buttons(s) {
        if (!_head)
            return;
        for (var i = 1; i < _header.length; i++)
            Display(_header[i], s);

        Display(_header[BACK], s && !_header[LEFT] && _historyPos);
        Display(_header[HOME], s && !_header[RIGHT] && _historyPos > 1);
    }

    function AddLayerButtons(lay, ignore) {
        if (!_head)
            return;

        var a = $$("a", lay);
        var p = RIGHT;

        for (var i = 0; i < a.length && p >= LEFT; i++) {
            if (_header[p] && !ignore) { i--; p--; continue; }

            if (HasToken(a[i].rel, "action") ||
                HasToken(a[i].rel, "back")) {

                AddClass(a[i], p == RIGHT ? "iRightButton" : "iLeftButton");
                Display(a[i], 1);
                _header[p--] = a[i];
                _head.appendChild(a[i--]);
            }
        }
    }

    function DelLayerButtons(lay) {
        if (!_head)
            return;

        for (var i = LEFT; i <= RIGHT; i++) {
            var a = _header[i];
            if (a && (    HasToken(a.rel, "action") ||
                        HasToken(a.rel, "back")) ) {

                Display(a, 0);
                DelClass(a, i == RIGHT ? "iRightButton" : "iLeftButton");
                lay.insertBefore(a, lay.firstChild);
            }
        }
        _header[RIGHT] = $("waRightButton");
        _header[LEFT] = $("waLeftButton");
    }

/* Private */
    function Contains(o, a) { return a.indexOf(o) != -1 }
    function IsAsync(o) { return HasToken(o.rev, "async") || HasToken(o.rev, "async:np"); }

    function $(i) { return typeof i == "string" ? document.getElementById(i) : i; }
    function $$(t, o) { return (o || document).getElementsByTagName(t); }
    function NewItem(t) { return document.createElement(t); }
    function GetLink(o) { return GetName(o) == "a" ? o : GetParent(o, "a") }
    function GetName(o) { return o.localName.toLowerCase() }
    function HasToken(o, t) { return o && Contains(t, o.toLowerCase().split(" ")); }

    function HasClass(o, c) { return Contains(c, GetClass(o)); }
    function GetClass(o) { return o.className.split(" "); }
    function AddClass(o, c) {
        var h = HasClass(o, c);
        if (!h) o.className += " " + c;
        return h;
    }
    function DelClass(o) {
        var c = GetClass(o);
        var a = arguments;
        for (var i = 1; i < a.length; i++) {
            var p = c.indexOf(a[i]);
            if (p != -1) c.splice(p, 1);
        }
        o.className = c.join(" ");
    }
    function GetParent(o, t) {
        while ((o = o.parentNode) && (o.nodeType != 1 || GetName(o) != t));
        return o;
    }    
    function AnyOf(o, c) {
        while ((o = o.parentNode) && (o.nodeType != 1 || !HasClass(o, c)));
        return o;
    }    
    function GetText(o) {
        var o = o.childNodes;
        for (var i = 0; i < o.length; i++)
            if (o[i].nodeType == 3)
                return o[i].nodeValue.replace(/^\s+|\s+$/g, "");
        return null;
    }

    function InitVars() {
        _webapp    = $("WebApp");
        _group    = $("iGroup");
        _header[HEAD] = $("iHeader");
        _header[BACK] = $("waBackButton");
        _header[HOME] = $("waHomeButton");
        _header[RIGHT] = $("waRightButton");
        _header[LEFT] = $("waLeftButton");
        _header[TITLE] = $("waHeadTitle");

        _bdo = (document.body.dir == "rtl") ? -1 : +1;
    }

    function Display(o, s) { if (o) o.style.display = s ? "block" : "none" }

    function Show(o) {
        Display(o, 1);
        o.style.width = "100%";
    }

    function Shadow(s) {
        Display($("__wa_shadow"), s);
    }

    function Lock() {
        if (!_lockCnt++)
            Display($("__wa_noclick"), 1);
    }
    function Unlock() {
        if (!--_lockCnt)
            Display($("__wa_noclick"), 0);
    }

    function Historize(o, l) {
        if (o) {
            _history.splice(++_historyPos, _history.length);
            _history.push(o);

            _location.splice(_historyPos, _location.length);
            _location.push(l ? location.hash : null);
            
            _scroll.splice(_historyPos, _scroll.length);
            _scroll.push(_lastScroll);
        }
    }

    function Cleanup() {
        var s, i, c;

        while (s = _loader.pop())
            __p.Loader(s, 0);

        s = $$("li");
        for (i = 0; i < s.length; i++)
            if (HasClass(s[i], "__sel"))
                DelClass(s[i], "__sel");
    }

    function ParseRewrite(s) {
        
    }

    function ParseParams(s, np) {
        var ed = s.indexOf("#_");
        if (ed == -1)
            return null;

        var rs = "";
        var bs = SplitURL(s);
        if (!np) for (var i = 0; i < bs[1].length; i++)
                    rs += "/" + bs[1][i].split("=").pop();

        return bs[2] + rs;
    }

    function FadeItem(o, show, next) {
        if (!next) {
            if (!o || _fading.indexOf(o) != -1)
                return;
            _fading.push(o);
        }

        with (o.style) {
            if ((!show && opacity > 0) || (show && opacity < 1)) {
                if (show) display = "block";
                opacity = parseFloat(opacity) + (show ? +0.5 : -0.5);
                setTimeout(function() { FadeItem(o, show, 1) }, 0);
            } else {
                display = (opacity == 0) ? "none" : "block";
                _fading.splice(_fading.indexOf(o), 1);
            }
        }
    }

    function IsMobile() {
        with (navigator.userAgent)
            return (indexOf("iPhone") + indexOf("iPod") > -2);
    }

    function Resizer() {
        if (_sliding)
            return;
            
        var w = (window.innerWidth >= 480) ? 480 : 320;
        if (w != _width) {
            _width = w;
            _webapp.style.minHeight = ((w == 320) ? 417 : 269) + "px";
            _webapp.className = (w == 320) ? "portrait" : "landscape";
            CallListeners("orientationchange");
        }
    }

    function Locator() {
        if (_sliding || _hold == location.href)
            return;
        _hold = false;

        var act = GetActive();
        if (act == null)
            if (location.hash.length > 0)    // there is a simple anchor, jump to it
                return;
            else                            // No? should slide back to home
                act = _history[0];

        var pos = _history.indexOf(act);
        var cur = _history[_historyPos];

        if (act == cur)
            return;

        if (pos != -1 && pos < _historyPos) {
            _historyPos = pos + 1;
            InitSlide(cur, act, L2R);
        } else {
            SlideTo(act);
        }
    }

    function CallListeners(evt, ctx) {
        var e = {};
        e.type = evt;
        e.context = ctx || Explode(_location[_historyPos]);
        e.windowWidth = _width;
        e.windowHeight = _webapp.offsetHeight;

        var k = true;
        for (var i = 0; i < _handler[evt].length; i++)
            k = k && (_handler[evt][i](e) == false ? false : true);
        return k;
    }

    function Init() {
        InitVars();
        InitCheck();
        InitRadio();
        InitTab();
        InitHeader();
        InitLock();
        InitShadow();

        var l = $("iLoader");
        if (l) Display(l, 0);

        if (!_def)
            _def = GetLayers()[0].id;
        Historize(_def);

        var a = GetActive();
        if (a != _def) Historize(a, true);
        if (!a) a = _def;

        Show($(a));
        AddLayerButtons($(a));

        Display(_header[BACK], (!_header[LEFT] && _historyPos));
        Display(_header[HOME], (!_header[RIGHT] && _historyPos > 1 && a != _def));

        if (_header[BACK])
            _baseBack = _header[BACK].innerHTML;
        if (_header[TITLE]) {
            _baseTitle = _header[TITLE].innerHTML;
            _header[TITLE].innerHTML = GetTitle($(a));
        }

        setInterval(Resizer, 100);
        setInterval(Locator, 100);
        setTimeout(function() { CallListeners("load") }, 100);
        setTimeout(AdjustView, 500);
    }

/* Event */
    function ShowTab(ul, li, h) {
        var al = $$("li", ul);
        for (var i = 0; i < al.length; i++) {
            Display($(ul.id + i), (!h && al[i] == li));
            DelClass(al[i], "__act");
        }
        AddClass(li, "__act");
    }

    function ListenClick(e, b) {
        if (_sliding) {
            e.preventDefault();
            return;
        }

        /* Checkbox */
        var o = e.target;
        var n = GetName(o);
        if (n == "label") {
            var f = $(o.getAttribute("for"));
            if (HasClass(f, "iToggle")) {
                setTimeout(function() {
                    FlipCheck(f.previousSibling.childNodes[1], true) }, 1);
            }
            return;
        }

        /* Radio parent */
        var li = GetParent(o, "li");        
        if (li && HasClass(li, "iRadio")) {
            AddClass(li, "__sel");
            ShowRadio(li);
            return;
        }

        /* Tab */
        var ul = GetParent(o, "ul");
        var pr = !ul ? null : ul.parentNode;
        var a  = GetLink(o);
        if (ul && HasClass(pr, "iTab")) {
            var h = $(ul.id + "-loader");
            Display(h, 0);

            if (IsAsync(a)) {
                Display(h, 1);
                BasicAsync(a, function(o) {
                    Display(h, 0);
                    ShowTab(ul, li, null);
                    Display(ShowAsync(o)[0], 1);
                });

            } else { h = null }
            ShowTab(ul, li, h);
            e.preventDefault();
            return;
        }
        
        /* Common button */
        if (a && !a.onclick &&
            Contains(a.id, ["waBackButton", "waHomeButton"])) {

            if (a.id == "waBackButton")    __p.Back();
            else                        __p.Home();

            e.preventDefault();
            return;
        }

        /* Radio list */
        if (ul && HasClass(ul, "iCheck")) {
            var al = $$("li", ul);
            for (var i = 0; i < al.length; i++)
                DelClass(al[i], "__act", "__sel");
            AddClass(li, "__act __sel");
            setTimeout(function() { DelClass(li, "__sel") }, 1000);
            e.preventDefault();
            return;
        }

        /* Menu and list */
        if (ul && 
            ((HasClass(ul, "iMenu") || HasClass(pr, "iMenu")) ||
             (HasClass(ul, "iList") || HasClass(pr, "iList"))) ) {

            if (a && !HasClass(a, "iButton")) {
                var c = AddClass(li, "__sel");
                if (IsAsync(a)) {
                    if (!c) BasicAsync(a);
                    e.preventDefault();
                }
                if (HasToken(a.rev, "media")) {
                    __p.Player(a.href);
                    setTimeout(function() { DelClass(li, "__sel") }, 500);
                    e.preventDefault();
                }
            }
            return;
        }

        /* More */
        var dv = AnyOf(o, "iMore");
        if (dv) {
            if (!__p.Loader(dv, 1) && IsAsync(o))
                BasicAsync(o, MoreAsync);
            e.preventDefault();
            return;
        }

        /* Top form button */
        if (a && _dialog && !a.onclick) {
            if (HasToken(a.rel, "back"))
                __p.Form(_dialog, a);
            if (HasToken(a.rel, "action"))
                __p.Submit(_dialog, a);
            e.preventDefault();
            return;
        }

        /* Media player */
        if (a && HasToken(a.rev, "media")) {
            __p.Player(a.href);
            e.preventDefault();
        }

        /* Basic link */
        if (n == "a" && IsAsync(o)) {
            BasicAsync(o);
            e.preventDefault();
        }
    }

/* Animate */
    function SlideTo(to) {
        if (_history[_historyPos] != to)
            InitSlide(_history[_historyPos], to);
        return false;
    }

    function InitSlide(src, dst, dir) {
        if (_sliding)
            return;

        AdjustView();
        Lock();

        if (dst == _history[0])    // TODO: check this
            _initialNav = history.length;

        dir = dir || R2L;
        src = $(src);
        dst = $(dst);

        FadeItem(_head, 0);
        if (_dialog) __p.Form(_dialog);
        Display($("iFooter"), 0);
        Display(_headView, 0);

        _sliding = 1;
        DoSlide(src, dst, dir);
    }

    function SlideInfo(d) {
        return [Explode(_location[_prev]), Explode(location.hash), d];
    }

    function DoSlide(src, dst, dir) {
        if (_fading.length > 0) {
            setTimeout(function() { DoSlide(src, dst, dir) }, 5);
            return;
        }

        _prev = _historyPos;
        CallListeners("beginslide", SlideInfo(dir));
        DelLayerButtons(src);
        AddLayerButtons(dst);
        InitCheck(dst);
        InitRadio(dst);

        Show(src);
        Show(dst);

        var s = 0;
        var w = src.offsetWidth;
        var c = (_v2) ? _group : document.body;    // use body instead of _webapp for RTL support

          c.style.width = "200%";
        src.style.width = "50%";
        dst.style.width = "50%";

        if (dir == R2L) {
            src.parentNode.insertBefore(src, dst);
            if (_v2) _group.style.left = 0;
            Historize(dst.id, true);
        } else {
            dst.parentNode.insertBefore(dst, src);
            while (_historyPos && _history[--_historyPos] != dst.id);
            if (_v2) _group.style.left = _bdo * -100 + "%";
        }
        if (!_v2 && dir * _bdo != R2L) { window.scrollTo(w, 1); }

        // Sliding effect for v2.x Safari Mobile
        if (_v2) {
            AddClass(_group, "__wa_slide");
            setTimeout(function() { _group.style.left = dir == R2L ? _bdo * -100 + "%" : 0 }, 0);
            setTimeout(function() { EndSlide(src, dst, dir) }, 410 );

        // Sliding effect for v1.x Safari Mobile
        } else setTimeout(function() {
            while (s <= w) {
                s += Math.max((w - s) / 16, 4);
                window.scrollTo((w + w * dir * _bdo) / 2 - Math.min(s, w) * dir * _bdo, 1);
            }

            var c = dst.cloneNode(true);
            dst.parentNode.insertBefore(c, dst);
            Display(src, 0);

            setTimeout(function() {
                var o = c.parentNode.removeChild(c);
                delete o;
                EndSlide(src, dst, dir);
            }, 0);
        }, 5);
    }

    function EndSlide(src, dst, dir) {
        Cleanup();

        if (_header[BACK]) {
            var txt;
            if (dir == R2L)
                txt = src.title || _baseBack;
            else if (_historyPos)
                txt = $(_history[_historyPos - 1]).title || _baseBack;
            if (txt) _header[BACK].innerHTML = txt;
        }

        Display(_header[BACK], !_header[LEFT] && _historyPos);
        Display(_header[HOME], !_header[RIGHT] && _historyPos > 1);
        Display(_header[LEFT], 1);
        Display(_header[RIGHT], 1);
        Display($("iFooter"), 1);
        SetTitle(GetTitle(dst));
        FadeItem(_head, 1);

        if (_v2) {
            DelClass(_group, "__wa_slide");
            Display(src, 0);
            _group.style.left = 0;
            _group.style.width = "";
        } else {
            document.body.style.width = "100%";
        }

        Show(dst);
        CleanSlide(dir);
        CallListeners("endslide", SlideInfo(dir));
        _prev = -1;
    }

    function CleanSlide(dir) {
        if (_fading.length > 0) {
            setTimeout(function() { CleanSlide(dir) }, 5);
            return;
        }
        Unlock();
        setTimeout(function() {
            AdjustView((dir == L2R) ? _scroll[_historyPos + 1] : null) }, 0);
        _sliding = 0;
    }

    function SetTitle(title/*, hide*/) {
        var o;
        if (o = _header[TITLE]) {
            o.innerHTML = title || GetTitle($(GetActive())) || _baseTitle;
            //Display(o, !hide);
        }
    }

    function FlipCheck(o, dontChange) {
        var i = $(o.parentNode.title);

        var txt = i.title.split("|");
        if (txt.length != 2)
            txt = ["ON", "OFF"];

        if (!dontChange)
            i.click();

        o.nextSibling.innerHTML = txt[i.checked ? 0 : 1];
        if (i.checked) {
            o.style.left = "";
            o.style.right = "-1px";
            o.parentNode.className = "iToggleOn";
            o.nextSibling.style.left = "0";
            o.nextSibling.style.right = "";
        } else {
            o.style.left = "-1px";
            o.style.right = "";
            o.parentNode.className = "iToggle";
            o.nextSibling.style.left = "";
            o.nextSibling.style.right = "0";
        }
    }

    function AdjustView(to) {
        _lastScroll = window.pageYOffset;

        var s = 1;
        var h = to || _lastScroll;
        var dir = !to ? +1 : -1;

        while (s <= h) {
            s += Math.max((h - s) / 10, 1);
            window.scrollTo(0, (h + h * dir) / 2 - Math.min(s, h) * dir);
        }
        if(!to) __p.HideBar();
    }

    function Explode(loc) {
        if (loc) {
            var pos = loc.indexOf("#_");
            var vis = [];

            if (pos != -1) {
                loc = loc.substring(pos + 2).split("/");
                vis = GetLayers().filter(
                        function(l) { return l.id == "wa" + loc[0] });
            }
            if (vis.length) {
                loc[0] = vis[0].id;
                return loc;
            }
        }
        return [];
    }

    function GetLayers() {
        var lay = [];
        var src = _group.childNodes;
        for (var i = 0; i < src.length; i++)
            if (src[i].nodeType == 1 && HasClass(src[i], "iLayer"))
                lay.push(src[i]);
        return lay;
    }

    function GetTitle(o) {
        return (!_historyPos && _baseTitle) ? _baseTitle : o.title;
    }

    function GetActive() {
        return Explode(location.hash)[0];
    }

    function SetURL(url) {
        var d = url.match(/[a-z]+:\/\/(.+:.*@)?([a-z0-9-\.]+)((:\d+)?\/.*)?/i);
        return (!_proxy || !d || d[2] == location.hostname)
            ? url : _proxy + "?__url=" + encodeURIComponent(url);
    }

    function SplitURL(u) {
        var s, q, d;

        s = u.replace(/&amp;/g, "&");
        d = s.indexOf("#");
        d = s.substr(d != -1 ? d : s.length);
        s = s.substr(0, s.length - d.length);
        q = s.indexOf("?");
        q = s.substr(q != -1 ? q : s.length);
        s = s.substr(0, s.length - q.length);
        q = !q ? [] : q.substr(1).split("&");

        return [s, q, d];
    }

    function AddParam(u, k, v) {
        u = SplitURL(u);
        var q = u[1].filter(
                function(o) { return o && o.indexOf(k + "=") != 0 });    /* != 0 ??? */
        q.push(k + "=" + encodeURIComponent(v));
        return u[0] + "?" + q.join("&") + u[2];
    }

    function BasicAsync(item, cb, q) {
        var h, o, u;

        u = (typeof item == "object" ? item.href : item);
        o = GetParent(item, "li");

        if (!cb) cb = DefaultCallback(u, HasToken(item.rev, "async:np"));
        __p.Request(u, q, cb, true, o);
    }

    function DefaultCallback(i, np) {
        return function(o) {
            var u = i ? ParseParams(i, np) : null;
            var g = ShowAsync(o);

            if (g && (g[1] || u))
                location = g[1] || u;
            else
                setTimeout(Cleanup, 250);

            return null;
        };
    }

    function ShowAsync(o) {
        if (o.responseXML) {
            o = o.responseXML.documentElement;

            /* force jump to a given layer */
            var g = $$("go", o);
            g = (g.length != 1) ? null : g[0].getAttribute("to");

            /* get all parts to update */
            var f, p = o.getElementsByTagName("part");
            if (p.length == 0) p = [o];

            for (var z = 0; z < p.length; z++) {
                var dst = $$("destination", p[z])[0];
                var mod = dst.getAttribute("mode");
                var txt = $$("data", p[z])[0].firstChild.nodeValue;
                var i = dst.getAttribute("zone");
                
                /* custom js tag code here */
                var js_list = p[z].getElementsByTagName("js");
                var js = '';
                if (js_list.length > 0)
                    js = $$("js", p[z])[0].firstChild.nodeValue;
                
                if (dst.getAttribute("create") == "true" &&
                    i.substr(0, 2) == "wa" && !$(i)) {

                    var n = NewItem("div");
                    n.className = "iLayer";
                    n.id = i;
                    _group.appendChild(n);
                }

                f = f || i;
                g = g || dst.getAttribute("go");        // For compatibility with older version
                i = $(i || dst.firstChild.nodeValue);    // For compatibility with older version

                /* update content */
                SetContent(i, txt, mod, js);
            }

            /* Custom title for the given layer */
            var t = $$("title", o);
            if (t.length == 1) {
                var s = t[0].getAttribute("set");
                $(s).title = t[0].firstChild.nodeValue;
                if (GetActive() == s) SetTitle(null, 1);
            }

            return [f, g ? "#_" + g.substr(2) : null];
        }

        throw "Invalid asynchronous response received.";
    }

    function MoreAsync(o) {
        ShowAsync(o);    /* TODO */
        // update more content ?
    }
    
    function SetContent(o, c, m, js) {
        if (m == "append") {
            o.innerHTML += c;
        } else if (m == "replace") {
            o.innerHTML = c;

        // after - before - self
        } else {
            var p = o.parentNode;
            var a = (m == "self") ? o : NewItem("div");

            a.innerHTML = c;
            if (m != "self")
                p.insertBefore(a, m == "after" ? o.nextSibling : o);
            while (a.hasChildNodes())
                p.insertBefore(a.firstChild, a);
            p.removeChild(a);
            delete a;
        }
        
        /* evaluate js passed in from <js></js> */
        if (typeof(js) == 'string' && js.length > 0)
          eval(js);
    }

    function __callback(o, cb, lr) {
        if (o.readyState != 4)
            return;

        var er, ld, ob;
        er = (o.status != 200 && o.status != 0);
        if (!er) {
//            if (lr) lr.className += " __sel";
            try { if (cb) ld = cb(o, lr); } catch (ex) { er = ex; console.error(er); }
            //if (typeof ld == "object") lr = ld;
        }
        ob = _ajax.filter(function(a) { return o == a[0] })[0];
        if (lr) __p.Loader(lr, 0);
        if (er) { if (lr) DelClass(lr, "__sel"); CallListeners("error", ob); }
        if (ob) _ajax.splice(_ajax.indexOf(ob), 1);
        delete o;
        // If it's android webapp, stop the loading icon
        if (typeof(window.tsheets) != 'undefined') window.tsheets.stopIndeterminate();
    }

/* Render */
    function InitHeader() {
        var hd = _header[HEAD];
        if (hd) {
            var dv = NewItem("div");
            dv.style.opacity = 1;
            while (hd.hasChildNodes())
                dv.appendChild(hd.firstChild);
            hd.appendChild(dv);
            _head = dv;
        }
    }

    function InitTab() {    // TODO: use showtab
        var o = $$("ul");
        for(var i = 0; i < o.length; i++) {
            var p = o[i].parentNode;
            if (p && HasClass(p, "iTab")) {
                AddClass($$("li", o[i])[0], "__act");
                if (p = $(o[i].id + "0"))
                    Display(p, 1);
            }
        }
    }

    function InitRadio(p) {
        var o = $$("li", p);

        for (var i = 0; i < o.length; i++) {
            if (HasClass(o[i], "iRadio") && !HasClass(o[i], "__done")) {
                var lnk = NewItem("a");
                var sel = NewItem("span");
                var cpy = o[i].childNodes;
                var inp = $$("input", o[i]);
                for (var j = 0; j < inp.length; j++) {
                    with (inp[j]) if (type == "radio" && checked) {
                        sel.innerHTML = GetText(parentNode);
                        break;
                    }                    
                }
                lnk.appendChild(sel);
                while (o[i].hasChildNodes())
                    lnk.appendChild(o[i].firstChild);
                o[i].appendChild(lnk);
                lnk.href = "#";
                lnk.onclick = function() { _hold = location.href; return SlideTo("waRadio") };
                AddClass(o[i], "__done");
            }
        }

        var d = NewItem("div");
        d.className = "iLayer";
        d.id = "waRadio";
        _group.appendChild(d);
    }

    function ClickRadio(a, p, u) {
        var x = $$("input", p);
        var y = $$("a", u);
        for (var i = 0; i < y.length; i++)
            if (y[i] == a) {
                x[i].checked = true;
                $$("span", p)[0].innerHTML = GetText(x[i].parentNode);
                break;
            }
    }

    function ShowRadio(p) {
        var o = $$("input", p);
        var dv = NewItem("div");
        var ul = NewItem("ul");
        ul.className = "iCheck";

        for (var i = 0; i < o.length; i++) {
            if (o[i].type == "radio") {
                var li = NewItem("li");
                var a = NewItem("a");
                a.innerHTML = o[i].nextSibling.nodeValue;
                a.href = "#";
                a.onclick = function() { ClickRadio(this, p, ul) };
                li.appendChild(a);
                ul.appendChild(li);

                if (o[i].checked) li.className = "__act";
            }
        }

        dv.className = "iMenu";
        dv.appendChild(ul);

        o = $("waRadio");
        if (o.firstChild)
            delete o.removeChild(o.firstChild);
        o.title = GetText(p.firstChild);
        o.appendChild(dv);
    }

    function InitLock() { InitObj("div", "__wa_noclick") }
    function InitShadow() {
        var o = InitObj("div", "__wa_shadow");
        var h = _header[HEAD];
        o.style.top = (h ? (h.offsetTop + h.offsetHeight) : 0) + "px";
    }    
    function InitObj(t, i) {
        var o = NewItem(t);
        o.id = i;
        _webapp.appendChild(o);
        return o;
    }

    function InitCheck(p) {
        var o = $$("input", p);

        for (var i = 0; i < o.length; i++) {
            if (o[i].type == "checkbox" && HasClass(o[i], "iToggle") && !HasClass(o[i], "__done")) {

                if (!o[i].id)
                    o[i].id = "__" + Math.random();
                if (!o[i].title)
                    o[i].title = "ON|OFF";

                var txt = o[i].title.split("|");

                var b1 = NewItem("b");
                var b2 = NewItem("b");
                var i1 = NewItem("i");
                b1.className = "iToggle";
                b1.title = o[i].id;
                b1.innerHTML = "&nbsp;";
                i1.innerHTML = txt[1];
                b1.appendChild(b2);
                b1.appendChild(i1);
                o[i].parentNode.insertBefore(b1, o[i]);
                b2.onclick = function() { FlipCheck(this); };
                FlipCheck(b2, true);
                AddClass(o[i], "__done");
            }
        }
    }

/* PreLoad */
    addEventListener("load", Init, true);
    addEventListener("click", ListenClick, true);

/* Static */
    return __p;
})();

var WA = WebApp;

function el(id) { return document.getElementById(id); };
function getcookie(cookiename) {
    var cookiestring=""+document.cookie;
    var index1=cookiestring.indexOf(cookiename);
    if (index1==-1 || cookiename=="") return "";
    var index2=cookiestring.indexOf(';',index1);
    if (index2==-1) index2=cookiestring.length;
    return unescape(cookiestring.substring(index1+cookiename.length+1,index2));
};
function getexpirydate(nodays){
    var UTCstring;
    var Today = new Date();
    var nomilli=Date.parse(Today);
    Today.setTime(nomilli+nodays*24*60*60*1000);
    return Today.toUTCString();
};
function setcookie(name,value,duration_days) {
    var cookiestring=name+"="+escape(value)+";EXPIRES="+getexpirydate(duration_days);
    document.cookie=cookiestring;
};

// function to stip dashes
function dashclean (mystring) {
    return mystring.replace(/^-+ /, '');
}