Base = {
    rand : function() {
        return Math.floor(Math.random(Date.getTime)*100000+Math.random(1000)*100000)
    },
    months : new Array(0, 'Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec'),
    fLabel : function(s) {
        s = s.split('.');
        ext = s.pop().toLowerCase();
        name = s.join('.');
        return new Array (ext, name);
    },
    fSize : function(s) {

        d = new Array('kB', 'MB', 'GB');
        for (i=0;s>1000;i++) {
            s = s / 1000;
            u = d[i];
        }
        if (typeof(u) != "undefined") {
            return Math.round(s) + u;
        }else {
            return Math.round(s);
        }

    },
    cDate : function(d) {
        if (typeof(d) != "undefined") {
            d = d.split('.');
            if (d[0][0] == "0") d[0] = d[0].substring(1,2);
            if (d[1][0] == "0") d[1] = d[1].substring(1,2);
            d = d.join('.');
        }

        return d;
    },
    vSrc : '/data/admin/data/visual/',
    pSrc : '/data/admin/data/process/',
    uSrc : '/data/user/',
    // cross browser adding event listeners; type, expression, element
    addListener : function(t,e,l) {
        l = l || window;
        if (window.addEventListener) {
            l.addEventListener(t,e,false);
            return true;
        } else if (window.attachEvent) {
            l.attachEvent('on' + t,e);
            return true;
        }else {
            return false;
        }
    },
removeListener: function (element, event, listener) {
if (typeof element == "string")
element = document.getElementById(element);
var eventId = getEventId(element, event, listener);
if (!eventId in listeners)
return false
var proxy = listeners[eventId].proxy;
delete listeners[eventId];
if (element.removeEventListener)
element.removeEventListener(event, proxy, false);
else if (element.detachEvent)
element.detachEvent('on' + event, proxy);
return true;
}
}

FE = {
    confirmCancel: function(c) {
        q = window.confirm(c);
        return q;
    },
    popup: function(o, id, i) {
        el = $(id);
        el.style.display = 'block';
        if (!i) {
            i = 0;
        }
        var parentWidth = o.offsetWidth + i;
        var margin = (parentWidth - el.offsetWidth) + 'px';
        el.style.marginLeft = margin;
        o.onmouseout = function() {
            el.style.display = 'none';
        }

    },
    // expects key=val;key=val;key=val
    // returns an object with adequate values
    getArgs: function(v) {
        r = v.split(';');
        obj = {};
        for(i=0;i<r.length;i++) {
            pair = r[i].split('=');
            code = pair[0];
            val = pair[1];
            obj[code] = val;
        }
        return obj;
    },
    docSize: function() {
        var docWidth;
        var docHeight;
        
        var D = document;
        docHeight = Math.max(
            Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
            Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
            Math.max(D.body.clientHeight, D.documentElement.clientHeight)
        );        
        
        docWidth = Math.max(
            Math.max(D.body.scrollWidth, D.documentElement.scrollWidth),
            Math.max(D.body.offsetWidth, D.documentElement.offsetWidth),
            Math.max(D.body.clientWidth, D.documentElement.clientWidth)
        );        
        
        return new Array(docWidth, docHeight);        
    },
    viewportSize: function() {
        var viewportwidth;
        var viewportheight;
        
        if (typeof window.innerWidth != 'undefined') {
            viewportwidth = window.innerWidth,
            viewportheight = window.innerHeight
        } else if (typeof document.documentElement != 'undefined'
        && typeof document.documentElement.clientWidth !=
        'undefined' && document.documentElement.clientWidth != 0) {
            viewportwidth = document.documentElement.clientWidth,
            viewportheight = document.documentElement.clientHeight
        } else {
            viewportwidth = document.getElementsByTagName('body')[0].clientWidth,
            viewportheight = document.getElementsByTagName('body')[0].clientHeight
        }
        return new Array(viewportwidth, viewportheight)      
    },
    scrollOffset: function() {
        D = document.body;
        var iebody = (document.compatMode && document.compatMode != "BackCompat")? document.documentElement : document.body
        
        var left = document.all? iebody.scrollLeft : pageXOffset
        var top = document.all? iebody.scrollTop : pageYOffset
        
        return new Array(left, top);
    }
}

FE.KeyEvents = {
    register: new Array(),
    init: function() {
        window.addEventListener('keydown', this.resolve);
    },
    add: function(code, charcode, fn) {
        if (typeof(this.register[charcode]) == 'undefined') {
            this.register[charcode] = new Array();
        }
        this.register[charcode].push(this.Item(code, fn));
        
    },
    rm: function(code, charcode) {
        if (typeof(this.register[charcode] != 'undefined')) {
            var arr = this.register[charcode];
            if (arr.length) {
                for(i=0;i<arr.length;i++) {
                    var item = arr[i];
                    if (typeof(item) != 'undefined' && item != null) {
                        if (item.code == code) {
                            arr[i] = null;
                        }                        
                    }

                }
                
            }
        }   
    },
    resolve: function(e) {
        var sc = FE.KeyEvents;
        if (e.which == null) {
            keycode = event.keyCode;
        } else {
            keycode = e.which;
        } 
        if (typeof(sc.register[keycode]) != 'undefined') {
            var arr = sc.register[keycode];
            if (arr.length) {
                for(i=0;i<arr.length;i++) {
                    var item = arr[i];
                    if (typeof(item) != 'undefined' && item != null) {
                        if (typeof(item.fn) == 'function') {
                            item.fn();
                        }
                    }
                }
            }
        }      
    }
}

FE.KeyEvents.init();

FE.KeyEvents.Item = function(code, fn) {
    this.code = code;
    this.fn = fn;
    return this;
}

//document.onkeydown = FE.KeyEvents.resolve(event);

FE.Tabs = {
    recentNodes: new Array(),
    recentFile: null,
    innerId: null,
    allow: false,
    swap: function(o,file,code,args) {
        if (typeof(o) == 'string') {
            var id = o;
        } else {
            p = o.parentNode;
            var nodes;
            nodes = p.getElementsByClassName('tab link focus');
            nodes[0].className = 'tab link';
            o.className = 'tab link focus';

            nodes = p.getElementsByClassName('inner');
            var id = nodes[0].id;
        }

        $('tab_selected').value = code;

        if (this.recentNodes[file]) {
            if (file != this.recentFile) {
                $(id).innerHTML = null;
                $(id).appendChild(this.recentNodes[file]);
            }
            FE.Tabs.inputs();
        } else {
            this.innerId = id;
            AJAX.init(file, {node: $(id), onFinish: FE.Tabs.save}, args);
        }
        this.recentFile = file;
        if ((file == 'demand.form' || file == 'order.form') && $('newUserLogin')) {
            $('newUserLogin').style.display =  ($('tab_selected').value == 'newreg' ? 'block' : 'none');
        }
    },
    inputs: function() {
        var code = $('tab_selected').value;
        if (code == 'noreg' || code == 'newreg') {
            var inputs = new Array('username', 'password', 'password_check');
            var dis = null;
            if (code == 'noreg') {
                dis = true;
            } else if (code == 'newreg') {
                dis = false;
            }
            for (i=0;i<inputs.length;i++) {
                $('input_'+inputs[i]).disabled = dis;
            }
        }
    },
    save: function() {
        id = FE.Tabs.innerId;
        o = $(id);
        var div = document.createElement('div');
        // flush parent container
        var temp = o.innerHTML;
        o.innerHTML = null;
        // append child container; insert parent content
        o.appendChild(div);
        div.innerHTML = temp;
        // save child container for later use
        FE.Tabs.recentNodes[FE.Tabs.recentFile] = div;
        FE.Tabs.inputs();
    },
    demandLogin: function() {
        var user = $('input_userName').value;
        var pw = $('input_password').value;
        var mode = $('tab_selected').value;

        AJAX.init('demand.login', {onComplete: function(r){
            if (r) {
                FE.Tabs.update('demand.login', r);
            } else {
                alert(FE.val('login.failed'));
            }
        }}, 'userName='+user+';password='+pw+';mode='+mode);

        return false;
    },
    orderLogin: function() {
        var user = $('input_userName').value;
        var pw = $('input_password').value;
        var mode = $('tab_selected').value;

        AJAX.init('order.login', {onComplete: function(r){
            if (r) {
                FE.Tabs.update('order.login', r);
            } else {
                alert(FE.val('login.failed'));
            }
        }}, 'userName='+user+';password='+pw+';mode='+mode);

        return false;
    },
    update: function(file, cont) {
        d = this.recentNodes[file];
        d.innerHTML = cont;
        // specific issues
        return true;
    },
    sendCtrl: function() {
        if (!fCtrl.exec()) {
            return false;
        }
        o = $('input_username');
        if ($('input_decoy_tos_confirm') != null) {
            if ($('input_decoy_tos_confirm').value == '0') {

                alert(FE.val('must_agree'));
                return false;
            }
        }

        if (o && $('tab_selected').value == 'newreg') {
            var pass = $('input_password').value;
            var check = $('input_password_check').value;
            if (o.value == '' || pass == '') {
                alert(FE.val('login.failed'));
                return false;
            }
            if (pass != check) {
                alert(FE.val('pass.mismatch'));
                return false;
            }
            // needs to be inspected
            if (this.allow) {
                return false;
            } else {
                AJAX.init('customerName.check', {onComplete: function(r){
                        if (r == '') {
                            FE.Tabs.allow = true;
                            if (Act.preAct()) {
                                $('demandCustForm').submit();
                            } else {
                                return false;
                            }
                            
                        } else {
                            alert(FE.val('username.na'));
                        }
                }}, 'username='+o.value);
            }
        } else {
            return true;
        }
        return true;
    }
}

FE.ParamInput = {
    active: false,
    node: false,
    init: function(o,i) {
        if (this.active) {
            this.revert();
        }
        p = o.parentNode;
        this.paramId = i;
        this.active = true;
        this.node = p;
        this.cache = o;
        AJAX.init('param.alter', {onFinish: function(r) {
                p.innerHTML = r;
                sel = $('paramInputSelector');
                i = sel.selectedIndex;
                FE.ParamInput.refId = sel.options[i].value;
        }}, 'refId='+i+';init=true', 'post');
    },
    revert: function(u, v) {
        if (this.active) {
            this.node.innerHTML = '';
            this.node.appendChild(this.cache);
        }
        if (u) {
            u.value = v;
        }
        this.active = false;
        this.paramId = null;
    },
    clear: function(o,id) {
        var node = o.nextSibling.firstChild;
        var val = o.options[o.selectedIndex].value;
        AJAX.init('param.alter', {onFinish: function(r) {
                FE.ParamInput.revert();
                node.value = '';
        }}, 'refId='+id+';paramValue='+val+';clear=true', 'post');
    },
    update: function(o, id) {
        if (id != this.refId) {
            this.refId = id;

            var inputs;
            inputs = $('paramInputs').getElementsByTagName('input');
            for(i=0;i<inputs.length;i++) {
                item = inputs[i];
                // save user defined value
                $('input_'+item.id+'_val').value = item.value;

                res = item.id.split('_');
                res.shift();
                res[res.length-2] = id;
                code = res.join('_');

                val = $('input_decoy_'+code+'_val').value;
                item.value = val;
                item.id = 'decoy_'+code;
            }
        }
    },
    save: function() {
        sel = $('paramInputSelector');
        i = sel.selectedIndex;
        val = sel.options[i].value;

        var inputs;
        inputs = $('paramInputs').getElementsByTagName('input');
        var values = '';
        for(i=0;i<inputs.length;i++) {
            item = inputs[i];
            res = item.id.split('_');
            values += ';val_'+res.pop()+'='+item.value;
        }
        AJAX.init('param.alter', {onFinish: function(r) {
            FE.ParamInput.revert();
            FE.ParamInput.node.firstChild.value = r;
        }}, 'process=true;refId='+this.paramId+';valueId='+val+values, 'post');
    }
}

FE.Calendar = {
    active: false,
    init: function(obj, ref, all) {
        this.all = all || false;
        if (this.active) {
            if (obj == this.obj) {
                this.exit();
                return false;
            } else {
                this.exit();
            }
        }
        this.active = true;
        this.obj = obj;
        this.ref = $(ref);
        // create calendar element
        pa = obj.parentNode;
        cal = document.createElement('div');
        cal.id = 'calendar';

        cal.style.marginTop = obj.offsetHeight + 3 + 'px';
        pa.insertBefore(cal,pa.firstChild);
        this.cal = cal;
        this.draw();
    },
    draw: function() {
        // get default values

        dt = new Date();
        res = this.ref.value.split('-');
        if (res == '') {
            res[0] = '0000';
            res[1] = '00';
            res[2] = '00';
        }
        if (!this.y) {
            y = (res[0] != '0000' ? res[0] : dt.getFullYear());
            this.y = parseInt(y);
        }
        if (!this.m) {
            if (!this.m) m = (res[1] != '00' ? res[1] : dt.getMonth() + 1);
            if (m[0] == '0') m = m[1];
            this.m = parseInt(m);
        }
        if (!this.d) {
            if (!this.d) d = (res[2] != '00' ? res[2] : dt.getDate());
            if (d[0] == '0') d = d[1];
            this.d = parseInt(d);
        }
        currentMonth = dt.getMonth() + 1;
        currentDay = dt.getDate();
        
        c = '<span class="floatR pointer arr" onclick="FE.Calendar.slide(+1)">&gt;</span>' +
            '<span class="floatL pointer arr" onclick="FE.Calendar.slide(-1)">&lt;</span>' +
            '<div class="month">' + FE.val('month_'+this.m) + ' ' + this.y + '</div>';

        // get first day of the month position
        pos = new Date(this.y, this.m - 1, 1).getDay();
        if (!pos) {
            pos = 6
        } else {
            pos--;
        }

        date = new Date(this.y, this.m - 1, this.d);
        d = 1;
        p = 1;
        no = date.monthDays() + pos;
        for(i=0;i<no;i++) {
            if (pos > 0) {
                val = '';
                pos--;
            } else {
                if (d == currentDay && this.m == currentMonth) {
                    val = '<strong>' + d + '</strong>';
                } else {
                    val = d;
                }
                d++;
            }
            skip = (Date.isPast(d,this.m,this.y) ? true : false);

            if (this.all) skip = false;

            c += '<div '+(!skip ?  'onclick="FE.Calendar.update('+(d-1)+')" ' : '')+'class="day'+(pos == 0 && d != 1 && !skip ? ' pointer' : ' past')+(p>=6 ? ' weekend' : '')+'">' + val + '</div>';
            p++;
            if (p > 7) p = 1;
        }
        this.cal.innerHTML = c;
    },
    update: function(i) {
        if (i) {
            m = this.m;
            this.obj.value = i + '.' + m + '.' + this.y;

            var month = m+'';
            if (month.length == 1) {
                month = '0' + month;
            }
            var day = i+'';
            if (day.length == 1) {
                day = '0' + day;
            }
            year = this.y;
            output = year + '-' + month + '-' + day;


            this.ref.value = output;
            this.exit();
        } else {
            return false;
        }
    },
    slide: function(move) {
        this.m += move;
        if (this.m == 13) {
            this.y++;
            this.m = 1;
        }
        if (this.m == 0) {
            this.y--;
            this.m = 12;
        }
        this.draw();
    },
    exit: function() {
        this.active = false;
        pa = this.obj.parentNode;
        pa.removeChild(pa.firstChild);
        this.obj = null;
        this.ref = null;
        this.y = null;
        this.m = null;
        this.d = null;
    }
}

FE.Curtain = {
    obj: null,
    show: function() {
        if (this.obj == null) {
            n = document.createElement('div');
            this.obj = n;
            n.setAttribute('id', 'feCurtain');
        } else {
            n = this.obj;    
        }
        
        res = FE.docSize();
        width = res[0];
        height = res[1];
        
        n.style.width = width+"px";
        n.style.height = height+"px";
        document.body.appendChild(n);
        
        FE.KeyEvents.add('hideCurtain', 27, FE.Curtain.hide);
    },
    hide: function() {
        obj = FE.Curtain.obj;
        n = obj.parentNode;
        n.removeChild(obj);
        FE.KeyEvents.rm('hideCurtain', 27);
    },
    repos: function() {
        var n = this.obj;
        var res = FE.viewportSize(); 
        n.style.width = res[0]+'px';
        var pop = $('fePopup');
        var popHeight = (pop.style.top.replace('px', '')*1) + pop.offsetHeight + 20;
        n.style.height = (popHeight > res[1] ? popHeight : res[1])+'px';
    }
}

FE.Popup = {
    maxHeight: 800,
    maxWidth: 1000,
    minVertPad: 50,
    minHorizPad: 50,
    setWidth: 824,
    show: function(src, args, h, w, fn) {
        
        window.addEventListener('resize', this.update);
        
        var sc = this;
        if (this.obj == null) {
            node = document.createElement('div');
            this.obj = node;
            node.setAttribute('id', 'fePopup');
        } else {
            node = this.obj;
        }
        node.setAttribute('class', h===null ? '': 'overflow');
        FE.Curtain.show();
        FE.KeyEvents.add('hidePopup', 27, FE.Popup.hide);
        
        document.body.appendChild(node);
        
        AJAX.init(src, {onComplete: function(r) {
            var close = document.createElement('span');
            close.setAttribute('class', 'floatR close link');
            close.setAttribute('onclick', 'FE.Popup.hide()');
            close.innerHTML = FE.val('close');
            
            node.appendChild(close);
            node.innerHTML += r;
            
            var res = FE.viewportSize();
            var width = res[0];
            var height = res[1];

            var res = FE.scrollOffset();
            var left = res[0];
            var top = res[1];  

            var widthLimit = w || sc.maxWidth;
            widthLimit += 2 * sc.minHorizPad;
            if (width > widthLimit) {
                innerW = widthLimit;
            } else {
                innerW = width;
            }        
            innerW -= 2*sc.minHorizPad;

            var heightLimit = (h === null ? node.offsetHeight : h) || sc.maxHeight;
            heightLimit += 2 * sc.minVertPad;

            if (height > heightLimit) {
                innerH = heightLimit;
            } else {
                innerH = height;
            }
            innerH -= 2*sc.minVertPad;

            horizPad = (width - innerW) / 2;
            vertPad = (height - innerH) / 2;
            node.style.left = horizPad+left+"px";
            node.style.top = vertPad+top+"px";



            node.style.width = innerW+'px';
            if (h !== null) {
                node.style.height = innerH+'px';            
            }
            
            if (fn) {
                fn(node);
            }
            
        }}, args);

        FE.Curtain.obj.onclick = function(){
            FE.Popup.hide();
        }
    },
    hide: function() {
        FE.Curtain.hide();
        FE.KeyEvents.rm('hidePopup', 27);
        
        obj = FE.Popup.obj;
        obj.innerHTML = '';
        n = obj.parentNode;
        n.removeChild(obj); 
    },
    update: function() {
        FE.Popup.repos();
        FE.Curtain.repos();
    },
    repos: function() {
        // vertical repositioning
        var nd = $('fePopup');
        var h = nd.offsetHeight;

        var res = FE.viewportSize();
        var height = res[1];
        
        var res = FE.scrollOffset();
        var top = res[1];        
        
        if (h < height) {
            var vertPad = (height - h) / 2;
            if (vertPad > this.minVertPad) {
                nd.style.top = vertPad+top+"px";
            } else {
                nd.style.top = this.minVertPad+top+"px";
            }
            
        } else {
            nd.style.top = this.minVertPad+top+"px";
        }
        
        
    }
}

Date.prototype.monthDays = function (){
  return 32 - new Date(this.getFullYear(), this.getMonth(), 32).getDate();
}
Date.isPast = function(d, m, y) {
    date = new Date();
    day = date.getDate();
    month = date.getMonth() + 1;
    year = date.getFullYear();
    if (y < year) {
        return true;
    } else if (m < month && y == year) {
        return true;
    } else if (d <= day && m == month && y == year) {
        return true;
    } else {
        return false;
    }
}
/* specific methods */
FE.Popup.recommendItem = function() {
    v = Act.getVals($('fePopup'));
    AJAX.init('customer.recommend.item',{onComplete: function(r) {
        if (r == 'sent') {
            alert(FE.val('mail.sent'));
            FE.Popup.hide();
        }
    }},v+'&sent=true&refId='+this.i,'post');
}

FLExi = {
    response: null,
    getMovie: function(code) {
        var isIE = navigator.appName.indexOf("Microsoft") != -1;
        return (isIE) ? window[code] : document[code];
    },
    sendToFlash: function(fn, args) {
        // need to be yet implemented
    },
    getFromFlash: function(fn, args) {
        return eval(fn+'(\''+args+'\');');
    }
}

FE.FlashMap = {
    relocate: function(a) {
        a = FE.getArgs(a);
        Act.relocate('../'+a.url+'/?reg='+a.region);
    },
    setDemandRegion: function(a) {
        a = FE.getArgs(a);
        FE.Popup.hide();
        location.href = '?country='+a.country;
    }
}

FE.ReferentsInput = {
    index: 0,
    // sets the actual value of a select input to the hidden input
    update: function(o,i) {
        var inp = $('referentInput_'+i);
        var val = o.options[o.selectedIndex].value;
        inp.value = val;
    },
    // adds a new select input
    add: function(i) {
        if (!this.index) {
            this.index = i;
        }
        var d='';
        AJAX.init('sub/region.addRef', {onComplete: function(r){
            d = document.createElement('div');
            d.innerHTML = r;
            $('referentsMain').appendChild(d);
        }}, 'index='+this.index);
        this.index++;
    }
}

function SessionHandler() {
    this.data = null;
    this.timer = null;
    this.interval = 60;
    this.init = function(data) {
        var obj = this;
        this.data = data;
        this.timer = window.setInterval(function(){obj.cycle()}, this.interval * 1000);
    }

    this.cycle = function() {
        AJAX.init('sub/sessionHandler', {}, this.data);
    }

}

FE.Vars = {
    addInput: function(i, s) {
        var obj = $('varInput_'+i);

        if (obj != null) {
            if (s == 0 || s == '0') {
                s = false;
            }
            if (typeof(obj.state) == 'undefined') {
                obj.state = s;
            }            
            if (!obj.state || obj.state == 0) {
                obj.state = obj.state == 1 ? false : true;
                obj.src = '/data/shared/visual/vars'+(obj.state ? 'On' : 'Off')+'.png';
                AJAX.init('/shared/process/vars.update', {onComplete: function(r){}}, 'id='+i+';state='+obj.state);
            }

            return false;  
        }
        
    }
}

var JSON;if(!JSON){JSON={}}(function(){function str(a,b){var c,d,e,f,g=gap,h,i=b[a];if(i&&typeof i==="object"&&typeof i.toJSON==="function"){i=i.toJSON(a)}if(typeof rep==="function"){i=rep.call(b,a,i)}switch(typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i){return"null"}gap+=indent;h=[];if(Object.prototype.toString.apply(i)==="[object Array]"){f=i.length;for(c=0;c<f;c+=1){h[c]=str(c,i)||"null"}e=h.length===0?"[]":gap?"[\n"+gap+h.join(",\n"+gap)+"\n"+g+"]":"["+h.join(",")+"]";gap=g;return e}if(rep&&typeof rep==="object"){f=rep.length;for(c=0;c<f;c+=1){if(typeof rep[c]==="string"){d=rep[c];e=str(d,i);if(e){h.push(quote(d)+(gap?": ":":")+e)}}}}else{for(d in i){if(Object.prototype.hasOwnProperty.call(i,d)){e=str(d,i);if(e){h.push(quote(d)+(gap?": ":":")+e)}}}}e=h.length===0?"{}":gap?"{\n"+gap+h.join(",\n"+gap)+"\n"+g+"}":"{"+h.join(",")+"}";gap=g;return e}}function quote(a){escapable.lastIndex=0;return escapable.test(a)?'"'+a.replace(escapable,function(a){var b=meta[a];return typeof b==="string"?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function f(a){return a<10?"0"+a:a}"use strict";if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(a){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;if(typeof JSON.stringify!=="function"){JSON.stringify=function(a,b,c){var d;gap="";indent="";if(typeof c==="number"){for(d=0;d<c;d+=1){indent+=" "}}else if(typeof c==="string"){indent=c}rep=b;if(b&&typeof b!=="function"&&(typeof b!=="object"||typeof b.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":a})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&typeof e==="object"){for(c in e){if(Object.prototype.hasOwnProperty.call(e,c)){d=walk(e,c);if(d!==undefined){e[c]=d}else{delete e[c]}}}}return reviver.call(a,b,e)}var j;text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}})()
                    
// object.watch
if (!Object.prototype.watch)
    Object.prototype.watch = function (prop, handler) {
        var val = this[prop],
        getter = function () {
                return val;
        },
        setter = function (newval) {
                return val = handler.call(this, prop, val, newval);
        };
        if (delete this[prop]) { // can't watch constants
                if (Object.defineProperty) // ECMAScript 5
                        Object.defineProperty(this, prop, {
                                get: getter,
                                set: setter
                        });
                else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) { // legacy
                        Object.prototype.__defineGetter__.call(this, prop, getter);
                        Object.prototype.__defineSetter__.call(this, prop, setter);
                }
        }
    };

// object.unwatch
if (!Object.prototype.unwatch)
    Object.prototype.unwatch = function (prop) {
        var val = this[prop];
        delete this[prop]; // remove accessors
        this[prop] = val;
    };

Array.prototype.search = function(val) {
    var i;
    for(i=0;i<this.length;i++) {
        if (this[i] == val) {
            return i;
        }
    }
    return -1;
}

Array.prototype.add = function(key, val) {
    return this[key] = val;
}

String.prototype.isImage = function() {
    var imgs = new Array('jpeg', 'jpg', 'png', 'gif');
    var ext = this.split('.').pop();
    if (imgs.search(ext) != -1) {
        return true;
    } else {
        return false;
    }
}

String.prototype.crop = function(length, brackets) {
    var limit = length-1;
    if (this.length > limit) {
        var str = this.substr(0, limit);
        if (brackets) {
            str += '(…)';
        } else {
            str += '…';
        }
        return str;
    } else {
        return this;
    }
}

String.prototype.isNumeric = function() {
  return !isNaN(parseFloat(this)) && isFinite(this);
}

String.prototype.isOdd = function() {
    return this%2;
}


HTMLFormElement.prototype.getValues = function() {
    var inputs = this.getElementsByTagName('input');
    var r = {};
    var item = null;
    for(i=0;i<inputs.length;i++) {
        item = inputs[i];
        if (item['name']) {
            r[item['name']] = item['value'];
        }
        
    }
    return r;
}

HTMLElement.prototype.getElementByArgument = function(arg, val) {
    var html = document.body.parentNode;
    var el = this;
    while (el) {
        if (el === html) {
            return false;
        }
        if ((el[arg] == val && val) || (el[arg] && !val)) {
            return el;
        }
        el = el.parentNode;
    }
    return false;
}

HTMLElement.prototype.swapNode = function(tgt) {
    if (isInDocument(this) && this !== tgt) {
        var copy = this.cloneNode(true);
        tgt.parentNode.replaceChild(copy, tgt);
        this.parentNode.replaceChild(tgt, this);        
    }
}

HTMLElement.prototype.insertAfter = function(newNode, refNode) {
	if(refNode.nextSibling) {
		return this.insertBefore(newNode, refNode.nextSibling);
	} else {
		return this.appendChild(newNode);
	}
}

HTMLElement.prototype.isBefore = function(obj) {
    var nodes = obj.parentNode.childNodes;
    var src = 0;
    var tgt = 0;
    var i;
    for (i=0;i<nodes.length;i++) {
        if (nodes[i] === this) {
            src = i;
        }
        if (nodes[i] === obj) {
            tgt = i;
        }
    }
    return (src < tgt);
}

HTMLElement.prototype.elPos = function() {
    var ref = this.parentNode;
    for(i=0;i<ref.childNodes.length;i++) {
        if (ref.childNodes[i] === this) {
            return i;
        }
    }
    return false;
}

function isInDocument(el) {
    var html = document.body.parentNode;
    while (el) {
        if (el === html) {
            return true;
        }
        el = el.parentNode;
    }
    return false;
}



