﻿//Author - Korochkin Vadim (2009) qstream@ngs.ru


function extendClass(derived, base) {
    try {
        var baseName = reflection(base).name;
        reflection(base).baseTypes.push(baseName);

        for (var f in base) {
            if (!derived[f]) {
                derived[f] = base[f];
            }
            else {
                var shadowName = baseName + '$' + f;
                derived[shadowName] = base[f];
            }
        }
    }
    catch (e) {

        Audit.exception(e.message);
    }
}


function instance(classObject) {
    var a = function() { };
    a.prototype = classObject;
    return new a();
}


function reflection(jObj, info) {

    if (info) {
        jObj.reflection = info;
        jObj.reflection.baseTypes = [];

        return jObj;
    }

    return jObj.reflection;
}



jObject =
{
    create: function(obj) {
        var inst = instance(this);
        inst.init(obj);

        return inst;
    },

    __noSuchMethod__: function(name, args) {
        Audit.exception('Функция не определена: ' + name, args);
    }
}

reflection(jObject, { name: 'jObject', v: '1.2', author: 'Vadim Korochkin' });




//Простой класс
Control =
{
    id: null,

    self: null,

    enabled: true,
    _stateOn: true,

    _check: function() {
        this.self = $('#' + this.id);

        try {
            document.getElementById(this.id).control = this;
        }
        catch (e) {
            Audit.exception('Элемент [' + this.id + '] (this.id) не существует :' + e.message);
        }

        this.self.enableValidation(this._enableValidation);
    },

    _stateOnEvents: null,

    init: function(obj) {
        this.id = obj.id;
        this._stateOnEvents = QSystem.Events.CreateEvent('stateOn', this);

        this._enableValidation = isNull(obj.enableValidation, true);
        var isEnabled = isNull(obj.enabled, true);

        this.enabled = function(value) {
            if (value != undefined) {
                isEnabled = value;

                return this;
            }

            return isEnabled;
        }

        this._check();
    },

    tune: function(obj) {

        if (obj.cssClass)
            this.self.addClass(obj.cssClass);

        this.self.css(obj);

        return this;
    },

    _enableValidation: false,

    enableValidation: function(value) {

        if (value != undefined) {
            this._enableValidation = value;
            this.self.enableValidation(value);

            return this;
        }

        return this._enableValidation;

    },

    on: function() {
        this._stateOn = true;
        this._stateOnEvents.run();
        return this;
    },

    off: function() {
        this._stateOn = false;
        return this;
    },

    visible: function(value) {
        return this.self.visible(value);
    }

};

reflection(Control, { name: 'Control', v: '1.0', author: 'Vadim Korochkin' });

extendClass(Control, jObject);


//Абстрактный класс (существует для наседования) (не наследуется от jObject)
PostBackControl =
{
    autoPostBack: false,
    _afterPostBack: null,
    _postBackEvents: null,

    init: function(obj) {
        this.autoPostBack = isNull(obj.autoPostBack, false);
        this._afterPostBack = QSystem.Events.CreateEvent('onAfterPostBack', this);
        this._postBackEvents = QSystem.Events.CreateEvent('onBeforePostBack', this);
        this.onBeforePostBack(

    function(sender, e) {
        var info = sender._getPostBackInfo();
        __doPostBack(sender.id, info);
    });

        var c = this;
        QSystem.onReady(

        function() {
            QSystem.Page.everyLoad(
                function() {
                    c._afterPostBack.run();
                }
            );
        });
    },


    _getPostBackInfo: function() {
        return '';
    },


    _doPostBack: function(sender, e) {
        if (sender.autoPostBack && sender._enablePostBack) {
            sender._postBackEvents.run();
        }
    },



    _enablePostBack: true,

    disallowPostBack: function() {
        this._afterPostBack.off();
        this._postBackEvents.off();

        return this;
    },

    allowPostBack: function() {
        this._afterPostBack.on();
        this._postBackEvents.on();

        return this;
    }

}

reflection(PostBackControl, { name: 'PostBackControl', v: '1.0', author: 'Vadim Korochkin' });





DataControl =
{
    _dataSource: null,

    dataSource: function(data) {
        if (data) {
            this._dataSource = data;
            return this;
        }

        return this._dataSource;

    },

    _dataBindingEvents: null,
    _dataBoundEvents: null,


    init: function(obj) {
        this._dataBindingEvents = QSystem.Events.CreateEvent('onDataBinding', this);
        this._dataBoundEvents = QSystem.Events.CreateEvent('onDataBound', this);
    },


    _bind: function(data) {
        for (var i = 0; i < data.length; i++) {
            this._bindOne(data[i]);
        }
    },

    dataBind: function() {


        this._check();
        this.self.empty();
        this._dataBindingEvents.run();

        //if (console) console.profile();

        var data;
        if (typeof (this._dataSource) == 'object') data = this._dataSource;
        else if (typeof (this._dataSource) == 'string') eval('data =' + this._dataSource);


        if (data) {
            this._bind(data);

        } else {
            Audit.exception('Неизвестный формат данных! [DataControl.Bind] + id:' + this.id);
        }

        //if (console) console.profileEnd();


        this._dataBoundEvents.run();

        return this;
    },

    _bindOne: function(oneData) {
    }

};


reflection(DataControl, { name: 'DataControl', v: '1.0', author: 'Vadim Korochkin' });


ProgressControl =
{
    progressBarClass: null,

    showProgressBar: function(sender) {

        sender = sender ? sender : this;
        var pos = sender.self.position();
        if ($('body').find('div.controlBinding[id="' + sender.id + '"]').length > 0) return;

        var wr = $('body');
        var bar = $('<div class="controlBinding">').attr('id', sender.id).appendTo(wr)
        .css('left', pos.left + parseInt(sender.self.css('width')) + 'px')
        .css('top', pos.top + 'px'); //parseInt(sender.self.css('height')) / 2 + 'px');

        if (sender.progressBarClass) bar.addClass(sender.progressBarClass);

        return sender;

    },


    hideProgressBar: function(sender) {
        sender = sender ? sender : this;
        $('body').find('div.controlBinding[id="' + sender.id + '"]').remove();
        return sender;
    },






    init: function(obj) {


        this.DataControl$init(obj);
        this.PostBackControl$init(obj);

        if (obj.progressBarClass)
            this.progressBarClass = obj.progressBarClass;

        this.onBeforePostBack(function(sender) {
            ProgressControl.showProgressBar(sender);
        }),

        this.onDataBinding(function(sender) {
            ProgressControl.showProgressBar(sender);
        }),


        this.onAfterPostBack(function(sender) {
            ProgressControl.hideProgressBar(sender);
        });

        this.onDataBound(function(sender) {
            ProgressControl.hideProgressBar(sender);
        });
    }
}


reflection(ProgressControl, { name: 'ProgressControl', v: '1.0', author: 'Vadim Korochkin' });
extendClass(ProgressControl, PostBackControl);
extendClass(ProgressControl, DataControl);

DropDownControl =
{

    _hideDropDown: function() {
        this.self.parent().hide();
        DropDownControl.lastOpened = null;
        return this;
    },

    _showDropDown: function() {
        DropDownControl.lastOpened = this;
        var ofs = this.self.parents('.extendDropDown').position(); //.offset(); //!!! todo!
        this.self.parent().show();
        this.self.parent().css('left', ofs.left + 'px');
        this.self.parent().css('top', ofs.top + parseInt(this.dropDownExtender.css('height')) + 'px');
        if (this._onShowDropDown) this._onShowDropDown();
    },


    faceHeight: function(px) {
        this.dropDownExtender.css('height', px);
        this.faceBtn.css('height', px);
    },


    loadFaceWidth: function() {
        this.dropDownWrapper.css('width', this.self.css('width'));
        this.dropDownExtender.css('width', this.self.css('width'));
    },

    init: function(obj) {


        obj = obj || new Object();

        var c = this;



        var controlDropDown = function(subToggle) {

            if (DropDownControl.lastOpened == c) {
                c._hideDropDown();
            }
            else {
                if (DropDownControl.lastOpened) DropDownControl.lastOpened.self.parent().hide()
                c._showDropDown();
            }

            return false;
        };



        this.self.wrap('<div class="controlWrap"/>');
        this.dropDownWrapper = this.self.parent();


        this.dropDownWrapper.wrap('<div class="extendDropDown"/>');
        this.dropDownExtender = this.dropDownWrapper.parent();

        obj.face = obj.face || '<input readonly="readonly" type="text" class="txt">';

        this.face = $(obj.face).click(controlDropDown);
        this.faceBtn = $('<input class="btn" type="button" />').click(controlDropDown);

        this.dropDownExtender
        .prepend(this.face)
        .prepend(this.faceBtn);




        if ($.browser.msie && parseInt($.browser.version) <= 6.5)
            this.self.parent().append('<!--[if lte IE 6.5]><iframe style="display:none;display:block;position:absolute;top:0;left:0;z-index:-1;filter:mask();width:100%; height:500px;"></iframe><![endif]-->');





        if (!DropDownControl.bodyControlled) {

            DropDownControl.bodyControlled = true;

            $('body').click(function(e) {

                if (DropDownControl.lastOpened) {

                    e = e || event;

                    var onSelf = Area.IsEventOnObj(e, DropDownControl.lastOpened.dropDownWrapper);

                    if (!onSelf) {
                        DropDownControl.lastOpened._hideDropDown();
                    }
                }
            });
        }


        this._hideDropDown();



        obj.faceHeight = obj.faceHeight || '16px';

        this.faceHeight(obj.faceHeight);




        this.loadFaceWidth();
    },


    tune: function(obj) {
        this.loadFaceWidth();
    },



    showSelected: function(text) {
        this.self.parents('.extendDropDown').find('input.txt').attr('value', text);
        this._hideDropDown();
    }

}

reflection(DropDownControl, { name: 'DropDownControl', v: '1.0', author: 'Vadim Korochkin' });





Area =
{
    isInArea: function(point, area) {
        return this.isInX(point, area) && this.isInY(point, area);
    },

    isInX: function(point, area) {
        var inX = (point.left < area.maxLeft && point.left > area.minLeft);
        // console.log('inX:' + inX);
        return inX;
    },

    isInY: function(point, area) {
        var inY = (point.top < area.maxTop && point.top > area.minTop);
        // console.log('inY:' + inY);
        return inY;
    },


    getArea: function(jObj) {

        var pos = jObj.offset();

        var sq =
        {
            minLeft: pos.left,
            maxLeft: pos.left + parseInt(jObj.css('width')),
            minTop: pos.top,
            maxTop: pos.top + parseInt(jObj.css('height'))
        }

        return sq;
    },

    IsEventOnObj: function(e, jObj) {

        var point = { left: e.pageX, top: e.pageY }; //{ left: e.clientX, top: e.clientY };
        var area = Area.getArea(jObj);
        var inArea = Area.isInArea(point, area);

        return inArea;
    }
};




Audit =
{

    debug: true,

    exception: function(head, text) {

        var msg = String.format('head: {0}, text:{1}', head, text);

        if (this.debug) {
            alert(msg);

            if (window['console']) {
                console.log(msg);
            }
        }

        this._writeException(head, text);
    },

    log: function(str) {
        if (!this.debug) return;


        if (window['console']) {
            console.log(str);
        }
        else {
//            alert(str);
            //Uses.dump.dump();

        }
    },

    _writeException: function(head, text) {
        if (text) {
            //AuditWriter.WriteException(head, text);
        }
        else {
            //AuditWriter.WriteException(head);
        }
    }
}


$(window).error(

function(message, url, line) {
   // Audit.exception('Неизвестная ошибка на странице:' + url, message + '. Line:' + line);
}

);

