document.observe('dom:loaded', function(){
    var grids = $$(GridSelector);
    for (i = 0; i < grids.length; i++)
    {
        if (Object.isUndefined(grids[i].control)) new GridControl(grids[i]);
    }
});

var GRID_FIELDTYPE_TEXTBOX       = 1;
var GRID_FIELDTYPE_SELECT        = 2;
var GRID_FIELDTYPE_CHECKBOX      = 3;
var GRID_FIELDTYPE_DATEPICKER    = 4;
var GRID_FIELDTYPE_IMAGE         = 5;
var GRID_FIELDTYPE_TEXTAREA      = 6;
var GRID_FIELDTYPE_TREE          = 7;
var GRID_FIELDTYPE_TREE_SELECT   = 8;
var GRID_FIELDTYPE_GRID_SELECT   = 9;
var GRID_FIELDTYPE_CURRENCY      = 10;
var GRID_FIELDTYPE_HTML          = 11;
var GRID_FIELDTYPE_PASSWORD      = 12;
var GRID_FIELDTYPE_POINT         = 13;

var GridSelector = '.gridsolo';
var GridControl = Class.create(FormControl, {
    selector:GridSelector,
    newIndex:null,
    rowSelector:null,
    cellSelector:null,
    filterSelector:null,
    actionSelector:null,
    actionRowSelector: null,
    editboxSelector:null,
    fieldSelect:null,

    initialize: function($super, element)
    {                 
        this.newIndex = 0;
        this.rowSelector = '.row';
        this.cellSelector = '.cell';
        this.filterSelector = '.filter';
        this.actionSelector = '.action_item';
        this.actionRowSelector = this.rowSelector +' '+ this.actionSelector;
        this.editboxSelector = '.editbox';
        $super(element);
        this.fieldSelect = this.view.getAttribute('fieldselect');
    },

    ajaxComplete: function()
    {
        this.view.find(GridSelector).each(function(e){new GridControl(e)});

        //init gridlist
        if (this.view.next())
            this.view.next().find(GridSelector).each(function(e){new GridControl(e)});
    },

    setFilter: function(key, value)
    {
        this.setValue(this.findOne(this.filterSelector+'.field-'+key+' .box'), value);
    },

    addHiddenFilter: function(key, value)
    {
        var filter_div = new Element('div')
        filter_div.addClassName('filter');
        filter_div.addClassName('field-' + key);

        var filter_box = new Element('input', {type: 'hidden'});
        filter_box.name = this.view.id + '[filter][' + key + ']';
        filter_box.value = value;
        filter_box.addClassName('box');
        filter_box.addClassName('filtered');

        filter_div.appendChild(filter_box);

        var hidden_filter = this.view.down('.hidden_filter');
        hidden_filter.appendChild(filter_div);
    },

    removeHiddenFilter: function(key)
    {
        var hidden_filter = this.view.down('.hidden_filter');
        var filter_div = hidden_filter.down('.field-' + key);
        if (filter_div)
            filter_div.parentNode.removeChild(filter_div);
    },

    hasHiddenFilter: function(key)
    {
        var hidden_filter = this.view.down('.hidden_filter');
        var filter_div = hidden_filter.down('.field-' + key);
        if (filter_div)
            return true;
        else
            return false;
    },

    observeEvent: function($super)
    {
        this.beforeContainer();
                    
        $super();   

        //Use thread to avoid "Unresponsive script" 
        var array = [];
        array.push( this.observeRowsClick.bind(this));
        array.push( this.observeBasicActions.bind(this));
        array.push( this.observeRowsAlternate.bind(this));
        array.push( this.observeRowsCheckbox.bind(this));
        
        if (!this.view.hasClassName('nothumb'))
            array.push( this.observeRowsThumb.bind(this));
            
        if (!this.view.hasClassName('norowaction'))
            array.push( this.observeRowsAction.bind(this));
            
        if (!this.view.hasClassName('nocelledit'))
            array.push( this.observeCells.bind(this));
            
        if (!this.view.hasClassName('noactionbox'))
            array.push( this.observeActionBox.bind(this));   

        array.push( this.observeFilter.bind(this));

        if (!this.view.hasClassName('noselectaction'))
            array.push( this.observeSelectActions.bind(this));
            
        if (!this.view.hasClassName('nomassaction'))
            array.push( this.observeMassActions.bind(this));
            
        if (!this.view.hasClassName('nocolumnresize'))
            array.push( this.observeColumnResize.bind(this));
                          
        //create our new class
        var work = new threadedLoop(array, 1);

        //create the action to compare each item with
        work.action = function(item, index, total) {
            item();
        };

        //and start our 'thread'
        work.start();

                      
        this.afterContainer();
    },

    getSelectedRowIds: function()
    {
        var control = this;
        var ids = new Array();
        this.findRow('.selected').each(function(e){
            ids.push(control.getRecordId(e));
        });
        return ids;
    },

    getSelectedRows: function()
    {
        return this.findRow('.selected');
    },

    getRecordId: function(row)
    {
        return row ? row.getAttribute('key') : null;
    },

    findRow: function(selector)
    {
        selector = Object.isUndefined(selector) ? '' : selector;
        result = false;
        try
        {
            result = this.find(this.rowSelector + selector);
        }
        catch (e)
        {
            result = false;
        }
        return result ? result : $A(new Array()); 
    },

    findCell: function(selector)
    {
        selector = Object.isUndefined(selector) ? '' : selector;
        result = false;
        try
        {
            result = this.find(this.cellSelector + selector);
        }
        catch (e)
        {
            result = false;
        }
        return result ? result : $A(new Array());
    },

    findFilter: function(selector)
    {
        selector = Object.isUndefined(selector) ? '' : selector;
        return this.find(this.filterSelector + selector);
    },

    observeRowsAlternate: function()
    {
        var control = this;
        this.findRow(':nth-child(2n)').invoke('addClassName', 'alternate');
    },

    observeRowsClick: function()
    {
        var control = this;
        this.findRow().invoke('observe', 'click', function(event){control.toggleRowSelect(this, event)});
    },
    
    observeRowsCheckbox: function()
    {
        var control = this;
        this.findRow(' input.check[type="checkbox"]').invoke('observe', 'click', function(event){control.checkboxClick(this, event)});
    },
    
    observeRowsThumb: function()
    {
        var control = this;
        this.findRow(' .thumbimg').each(function(e){
            var cell = e.up(control.cellSelector);
            var src = cell.getAttribute('value');
            new Tooltip(cell, '<img class="tooltip_img" src="'+src+'" />')
        });
    },
                        
    observeRowsAction: function()
    {
        var control = this;
        this.find(this.actionRowSelector+'.delete').invoke('observe', 'click', function(event){control.deleteItem(this, event)});
        this.find(this.actionRowSelector+'.inline_edit').each(function(e){
            e.toggleRowEdit = control.toggleRowEdit;
            e.observe('click', control.toggleRowEdit);
        });
                        
    },
    
    observeCells: function()
    {                  
        var control = this;
        
        this.findCell().each(function(e){
            var i = e.down('.box');
            if (i) i.observe('change', control.inputChanged);

            e.observe('click', function(event){
                if (event.altKey){
                    this.toggleClassName('selected');
                    event.stopPropagation();
                }
            })
            e.observe('dblclick', function(event){
                control.toggleCellEdit(this);
                event.stopPropagation();
            })
            if (e.hasClassName('oneclickedit'))
                e.observe('click', function(event){
                    if (!this.hasClassName('editing')) control.enableCellEdit(e);
                    event.stopPropagation();
                })
        });
    },

    observeBasicActions: function()
    {
        var control = this;
        this.view.control = this;
        this.find('input.check_all').invoke('observe', 'click', function(){control.setAllCheckbox(this.checked)});
        this.find('input.group_select_all').invoke('observe', 'click', function(e){control.selectAllGroup(e, this.checked)});
        this.find('.pager select').invoke('observe', 'change', function(){control.refresh();});
        this.find('.pager .page').invoke('observe', 'click', function(){
            var page = this.value;
            control.find('.pager_input').each(function(e){
                e.value = page;
            });
            control.refresh();
        });
        this.find('.sortable').invoke('observe', 'click', function(){control.sortColumn(this)});
    },

    observeFilter: function()
    {
        var control = this;
        this.findFilter(' .box').each(function(e){
            e.originValue = e.value;
            e.observe('change', control.inputChanged);
            if (e.value) e.addClassName('filtered');
        })

        this.findFilter(' select').invoke('observe', 'change', function(){
            control.refresh()
        });

        this.find('.clear_filter').invoke('observe', 'click', function(){control.clearFilter()});
        this.findFilter(' input.daterange_picker').each(function(e){
            var dr = new DaterangeControl(e);
            dr.applyCallback = function(){
                control.refresh();
            }
        });

        this.findFilter(' '+GridSelectSelector).each(function(e){
            if (Object.isUndefined(e.control))
            {
                new GridselectControl(e);
                e.control.observeFilter();
                e.control.observe('rowselect', function(){control.refresh()});
            }
        });
    },

    observeActionBox: function()
    {                
        this.findRow(' .actionbox').each(function(e){
            if (e.down('.action_wrapper')){
                e.observe('mouseover', function(){
                    if (e.menuTimerOut)
                        clearTimeout(e.menuTimerOut);

                    var menu = this.down('div.action_wrapper');
                    if ($(menu.parentNode).cumulativeOffset().left + e.getWidth() > getViewportsize().width)
                    {
                        menu.setStyle({marginLeft:-menu.getWidth() - e.getWidth() + "px"});
                    }
                    else
                    {
                        menu.setStyle({marginLeft: "0px"});
                    }

                    e.menuTimerIn = setTimeout(function(){menu.show()}.bind(menu), 100);

                });
                e.observe('mouseout', function(){
                    if (e.menuTimerIn)
                        clearTimeout(e.menuTimerIn);

                    e.menuTimerOut = setTimeout(function (){this.down('div.action_wrapper').hide()}.bind(this), 100);
                });
            }
        });
    },

    observeColumnResize: function()
    {
        this.find('thead .caption th').each(function(e){
			new ResizerW(e);
            e.setStyle({width:e.getStyle('width')});
        });
        updateAllResizers();
    },

    observeSelectActions: function()
    {
        var control = this;
        this.find('.select_all').invoke('observe', 'click', function(){
            control.selectAll();
        });

        this.find('.select_none').invoke('observe', 'click', function(){
            control.selectNone();
        });

        this.find('.select_editing').invoke('observe', 'click', function(){
            control.selectEditing();
        });

        this.find('.select_inverse').invoke('observe', 'click', function(){
            control.selectInverse();
        });
    },

    observeMassActions: function()
    {
        var control = this;
        this.find('.add_new').invoke('observe', 'click', function(){
            control.addNew();
        });

        this.find('.toogle_edit').invoke('observe', 'click', function(){
            control.editSelected();
        });

        this.find('.mass_action').invoke('observe', 'click', function(){
            var action = this.getAttribute('action');
            var confirm = !this.hasClassName('noconfirm');
            var selected_check = !this.hasClassName('noselected');
            var file_export = this.hasClassName('file_export');       
            control.actOnSelecteds(action, confirm, selected_check, file_export, this.innerHTML);
        });
    },

    formBeforeSubmit: function()
    {
        this.removeUnchangedFilter();
        this.find(this.editboxSelector).invoke('remove');
    },

    removeUnchangedInputs: function()
    {                        
        var control = this;                  
        this.findRow('.editing .inline_edit').each(function(e){
            if (!e.up(control.rowSelector).down('.changed') && e.toggleRowEdit)
                e.toggleRowEdit();
        });
        this.findCell('.editing input:not(.changed)').each(function(e){control.undoEdit(e)});
        this.findCell('.editing select:not(.changed)').each(function(e){control.undoEdit(e)});
        this.findCell('.editing input[type=checkbox].changed').each(function(e){control.undoCheckboxEdit(e)});
    },

    removeUnchangedFilter: function()
    {
        this.findFilter(' .box').each(function(e){ if(e.value=='') e.disable()}); 
    },

    beforeContainer: function()
    {
        if (this.view.hasClassName('xcontainer'))
        {
            this.view.grids = new Array();
            this.view.getElementsBySelector('.grid').each(function(e){this.view.grids[this.view.grids.length] = new Array(e.id, e.innerHTML); e.update('');}.bind(this));
        }
    },

    afterContainer: function()
    {                
        if (this.view.hasClassName('xcontainer'))
        {
            if (this.view.grids)
            {
                $A(this.view.grids).each(function(e){ $(e[0]).update(e[1]); if ($(e[0]).hasClassName('tree')) new GridtreeControl($(e[0])); else new GridControl($(e[0]));});    
            }
        }
    },

    undoCheckboxEdit: function(checkbox)
    {
        var cell = checkbox.up(this.cellSelector);
        if (cell.hasClassName('keepedit')) return;

        checkbox.hide().checked = true;
        cell.insert(checkbox.value);
    },

    undoEdit: function(input)
    {                        
        this.cancelCellEdit(input.up(this.cellSelector));
    },

    checkForChanges: function()
    {            
        var control = this;       
        var notChanges = this.findCell('.editing input:not(.changed)');     
        if (notChanges) 
        {
            notChanges.each(function(e){
                if (e.value != e.up(control.cellSelector).getAttribute('value')){
                    e.addClassName('changed');
                }
            });
        } 
        this.removeUnchangedInputs();  
        var changes = this.findCell('.editing .box.changed');
        if (changes)
            changes = changes.length;
        else
            changes = 0;
            
        return changes>0;
    },

    checkForFilterChanges: function()
    {
        this.findFilter('.editing .box').each(function(e){
            if (e.value != e.originValue) e.addClassName('changed');
            else e.removeClassName('changed');
        });
        var changes = this.findFilter('.editing input.changed').length;

        return changes>0;
    },

    editSelected: function()
    {
        this.findRow('.selected .inline_edit').invoke('toggleRowEdit');
        //this.findCell('.selected.editable').each(this.toggleCellEdit);
    },

    toggleCellEdit: function(e)
    {
        if (!e.hasClassName('editable')) return;
        var editing = e.hasClassName('editing');
        if (!editing) this.enableCellEdit(e);
        else this.cancelCellEdit(e);
        updateAllResizers();
    },

    toggleRowEdit: function(event)
    {
        var control = this.up('.grid').control;
        var row = this.up(control.rowSelector);
        var cells = row.find(control.container + control.cellSelector+'.editable');
        var editing = row.hasClassName('editing');
        if (!editing)
        {
            cells.each(function(e){control.enableCellEdit(e)});
            row.addClassName('editing');
            this.update('Cancel');
        }
        else
        {
            cells.each(control.cancelCellEdit);
            row.removeClassName('editing');
            this.update('Edit');
        }
        if (event) event.stopPropagation();
        updateAllResizers();
    },

    //hoannd: Add Cell change event
    cellChange: function(cell)
    {
        var relating_fields = cell.getAttribute('relating_fields');
        var related_fields  = cell.getAttribute('related_fields');

        if (!Object.isUndefined(relating_fields) && relating_fields != null)
        {
            if (relating_fields != '')
            {
                relating_fields_arr = relating_fields.split(",");

                for (i = 0; i < relating_fields_arr.length; i++)
                {
                    var relating_cell = cell.up('.row').down('.cell[field=' + relating_fields_arr[i] + ']');
                    var relating_cell_box = relating_cell.down('.box');

                    var relating_cell_fieldtype = relating_cell.getAttribute('fieldtype');

                    if (relating_cell_box)
                    {
                        if (relating_cell_fieldtype == GRID_FIELDTYPE_GRID_SELECT)
                        {
                            relating_cell_box.control.setValue('');
                            relating_cell_box.control.setDisplayValue('');

                            this.refreshGridSlectCell(relating_cell, relating_cell_box);
                        }

                        if (relating_cell_fieldtype == GRID_FIELDTYPE_SELECT)
                        {
                            this.refreshSelectCell(relating_cell);
                        }
                    }

                }
            }
        }

        if (!Object.isUndefined(related_fields) && related_fields != null)
        {
            if (related_fields != '')
            {
                related_fields_arr = related_fields.split(",");

                for (i = 0; i < related_fields_arr.length; i++)
                {
                    var related_cell = cell.up('.row').down('.cell[field=' + related_fields_arr[i] + ']');
                }
            }
        }
    },

    refreshSelectCell: function (cell)
    {
        var related_fields  = cell.getAttribute('related_fields');

        if (!Object.isUndefined(related_fields) && related_fields != null)
        {
            if (related_fields != '')
            {
                related_fields_arr = related_fields.split(",");

                var cell_fieldtype = cell.getAttribute('fieldtype');

                for (i = 0; i < related_fields_arr.length; i++)
                {
                    var related_cell = cell.up('.row').down('.cell[field=' + related_fields_arr[i] + ']');
                    var related_cell_box = related_cell.down('.box');
                    var related_value = related_cell_box ? related_cell_box.value : related_cell.getAttribute('value');

                    if (cell_fieldtype == GRID_FIELDTYPE_SELECT)
                    {
                        this.removeHiddenFilter(related_fields_arr[i]);
                        this.addHiddenFilter('cell_filter_' + related_fields_arr[i], related_value);
                    }
                }

                if (cell_fieldtype == GRID_FIELDTYPE_SELECT)
                {
                    this.removeHiddenFilter('cell_filter_field');
                    this.addHiddenFilter('cell_filter_field', cell.getAttribute('field'));

                    oldAction = this.getFormAction();
                    this.setFormAction('cell_filter').refreshWithHandler(
                        function(obj, response)
                        {
                            res = response.evalJSON();

                            oldValue = cell.getAttribute('value');
                            if (Object.isUndefined(res[oldValue]))
                            {
                                cell.setAttribute('value', '');
                            }

                            cell_box = cell.down('.box');

                            if (cell_box)
                            {
                                if (cell_box.selectedIndex >= 0)
                                    oldValue = cell_box.options[cell_box.selectedIndex].value;

                                cell_box.originValue = '';

                                cell_box.options.length = 1;
                                var sel = -1;
                                var ic = 0;
                                for( var b in res )
                                {
                                    ic = ic + 1;
                                    if (b == oldValue)
                                        sel = ic;

                                    cell_box.options.add(new Option(res[b], b));
                                }

                                if (sel >= 0)
                                    cell_box.selectedIndex = sel;
                            }
                        }
                        , true);

                    this.setFormAction(oldAction);

                    this.removeHiddenFilter('cell_filter_field');
                    for (i = 0; i < related_fields_arr.length; i++)
                        this.removeHiddenFilter('cell_filter_' + related_fields_arr[i]);
                }
            }
        }
    },

    refreshGridSlectCell: function(cell, gridModel)
    {
        var related_fields  = cell.getAttribute('related_fields');

        if (!Object.isUndefined(related_fields) && related_fields != null)
        {
            if (related_fields != '')
            {
                related_fields_arr = related_fields.split(",");

                var cell_fieldtype = cell.getAttribute('fieldtype');

                for (i = 0; i < related_fields_arr.length; i++)
                {
                    var related_cell = cell.up('.row').down('.cell[field=' + related_fields_arr[i] + ']');
                    var related_cell_box = related_cell.down('.box');
                    var related_value = related_cell_box ? related_cell_box.value : related_cell.getAttribute('value');

                    if (cell_fieldtype == GRID_FIELDTYPE_GRID_SELECT)
                    {
                        gridModel.control.removeHiddenFilter(related_fields_arr[i]);
                        gridModel.control.addHiddenFilter(related_fields_arr[i], related_value);
                    }
                }

                if (cell_fieldtype == GRID_FIELDTYPE_GRID_SELECT)
                {
                    gridModel.control.refresh();
                }
            }
        }
    },

    enableCellEdit: function(cell)
    {
        this.saveCellFormatedValue(cell);
        var cell_value = cell.getAttribute('value');
        var editbox = this.getEditbox(cell, cell_value);

        var input_hidden = cell.addClassName('editing').update(editbox).down('.box').observe('change', this.inputChanged);

        if (input_hidden.type!='checkbox')
        {
            input_hidden.value = input_hidden.originValue = cell_value;
            if (input_hidden.getAttribute('type')=='datetime')
            {
                this.initDatepicker(input_hidden);
            }
            else if (input_hidden.hasClassName('gridselect_ready'))
            {
                input_hidden.addClassName('gridselect');
                new GridselectControl(input_hidden);
                input_hidden.control.observeFilter();
            }
        }

        //hoannd: process for filter cell
        var relating_fields = cell.getAttribute('relating_fields');
        var related_fields  = cell.getAttribute('related_fields');

        if (!Object.isUndefined(relating_fields) && relating_fields != null)
        {
            if (relating_fields != '')
            {
                relating_fields_arr = relating_fields.split(",");

                for (i = 0; i < relating_fields_arr.length; i++)
                {
                    var relating_cell = cell.up('.row').down('.cell[field=' + relating_fields_arr[i] + ']');
                    var relating_cell_box = relating_cell.down('.box');

                    var relating_cell_fieldtype = relating_cell.getAttribute('fieldtype');

                    if (relating_cell_box)
                    {
//                        if (relating_cell_fieldtype == GRID_FIELDTYPE_GRID_SELECT)
//                            relating_cell_box.control.refresh();
                    }

                }
            }
        }

        if (!Object.isUndefined(related_fields) && related_fields != null)
        {
            if (related_fields != '')
            {
                var cell_fieldtype = cell.getAttribute('fieldtype');

                if (cell_fieldtype == GRID_FIELDTYPE_GRID_SELECT)
                    this.refreshGridSlectCell(cell, input_hidden);

                if (cell_fieldtype == GRID_FIELDTYPE_SELECT)
                   this.refreshSelectCell(cell);
            }
        }

        this.fire('celledit', {cell: cell});
    },

    getEditbox: function(cell, cell_value)
    {
        var editbox_template = this.findOne(this.editboxSelector+' .edit-'+cell.getAttribute('field'));
        var id = this.getRecordId(cell.up(this.rowSelector));

        var editbox = editbox_template.innerHTML.gsub(/#id/, id).gsub(/#v/, cell_value);     
        var display = cell.down('.displayvalue');
        display = display ? display.innerHTML : '';
        editbox = editbox.gsub(/#f/, display);       

        var checked = cell_value>0 ? 'checked="checked"' : '';
        return editbox.gsub(/#checked/, checked);
    },

    saveCellFormatedValue: function(e)
    {
        if (!e.formated){
            var value = e.down();
            // :BUG: hoannd012 - IE6,7,8 can not automaticlly clone element, value is a pointer, it losts the content when js change it for editing
            // Solution: Clone it
            e.formated = value ? $(value).cloneNode(true) : e.innerHTML;
        }
    },

    initDatepicker: function(e)
    {
        e.observe('click', function(){
            new CalendarDateSelect(this);
        }).observe('blur', this.inputChanged)
    },

    cancelCellEdit: function(cell)
    {
        if ($(cell).hasClassName('keepedit')) return;
        // :BUG: hoannd013 - IE6,7,8 can not automaticlly clone element, cell.formated is a pointer, next edit step, it losts the content
        // Solution: Clone it

        var f = $(cell).formated == '' ? '' : ($($(cell).formated) == null ? $(cell).formated : $($(cell).formated).cloneNode(true));
        $(cell).removeClassName('editing').update(f);
    },

    inputChanged: function()
    {
        if (this.type=='checkbox') this.value = this.checked ? 1:0;

        if (this.value != this.originValue)
            this.addClassName('changed');
        else
            this.removeClassName('changed');
    },

    clearFilter: function()
    {
        var control = this;
        this.find('.filterrow .filter input', '.filter select').each(function(e){
            control.setValue(e, '');
        });
        this.refresh();
    },

    sortColumn: function(e)
    {
        var sort_order = this.findOne('.sort_order');
        var sort_field = this.findOne('.sort_field');

        if (e.hasClassName('asc')) this.setValue(sort_order, 'desc');
        else if(e.hasClassName('desc')) this.setValue(sort_order, '');
        else this.setValue(sort_order, 'asc');
        this.setValue(sort_field, sort_order.value? e.title:null);
        this.refresh();
    },

    discardAllChanges: function()
    {
        var control = this;
        this.findRow('.editing .inline_edit').each(function(e){
            if (e.toggleRowEdit) e.toggleRowEdit();
        })
        this.findCell('.editing').each(function(e){
            control.cancelCellEdit(e);
        })
    },

    actOnSelecteds: function(action, confirmRequired, selected_check, file_export, label)
    {
        if (!label) label = action;
        if (selected_check && this.getSelectedRows().length < 1) {alert('No item selected!');return;}
        if (confirmRequired && !confirm('Do you want to `'+label+'` selected items?')) return;                   
        this.setFormAction(action);                                                                  

        if (file_export) {               
            this.submitFormNoajax();                 
            this.setFormAction('');
        }
        else
            this.refresh();
    },

    processAction: function(action)
    {
        this.setFormAction(action).refresh();
    },

    deleteItem: function(e, event)
    {
        this.selectNone();
        var row = e.up(this.rowSelector);
        row.addClassName('editing');
        this.selectRow(row, true);
        if (confirm('Do you want to delete this item?'))
        {
            this.setFormAction('delete');
            this.refresh();
        }
        else
            row.removeClassName('editing');
        event.stopPropagation();
    },

    checkboxClick: function(e, event)
    {
        var row = e.up(this.rowSelector);
        if(e.checked)
            row.addClassName('selected')
        else
            row.removeClassName('selected')
        event.stopPropagation();
    },

    toggleRowSelect: function(e, event)
    {
        var element = event.element();
        if (element.tagName != 'INPUT'
            && element.tagName != 'SELECT'
            && !element.hasClassName('node_icon')
            && !element.hasClassName('action_item'))
        {
            var c = e.down('input'+this.container+'.check[type="checkbox"]');
            if (c) this.selectRow(e, !c.checked, c);
        }

        var id = this.getRecordId(e);
        // :BUG: hoannd016 Sometime, fieldname is invalid. Solution: check it
        var display = this.fieldSelect ? this.getFieldValue(e, this.fieldSelect) : id;
        if (display == null) display = id;
        this.fire('rowselect', {id:id, display:display});
    },

    getFieldValue: function(row, fieldname)
    {
        // :BUG: hoannd016 Sometime, fieldname is invalid. Solution: check it
        var elm = row.down('.cell[field='+fieldname+']');
        return elm ? elm.getAttribute('value') : null;
    },

    setAllCheckbox: function(checked)
    {
        var control = this;
        this.findRow().each(function(row){
            control.selectRow(row, checked)
        });
    },

    selectRow: function(row, checked, e)
    {
        if (!e) e = row.down('input[type="checkbox"]');
        e.checked = checked;
        if(e.checked)
            row.addClassName('selected')
        else
            row.removeClassName('selected')
    },

    selectAll: function()
    {
        this.findOne('input.check_all').checked = true;
        this.setAllCheckbox(true);
    },

    selectAllGroup: function(e, checked)
    {
        groupkey = e.element().getAttribute('groupkey');
        this.setAllGroupCheckbox(checked, groupkey);
    },

    setAllGroupCheckbox: function(checked, groupkey)
    {
        var control = this;
        this.findRow().each(function(row){
            if (row.getAttribute('groupkey') == groupkey) control.selectRow(row, checked);
        });
    },

    selectNone: function()
    {
        this.find('input.check_all[type="checkbox"]').first().checked = false;
        this.setAllCheckbox(false);
        this.findCell('.selected').each(function(e){e.removeClassName('selected')});
    },

    selectEditing: function()
    {
        var control = this;
        this.findRow().each(function(row){control.selectRow(row, false)});
        this.findRow('.editing').each(function(row){control.selectRow(row, true)});
        this.findRow(':not(.selected) '+this.cellSelector+'.editing').each(function(e){e.toggleClassName('selected')});
    },

    selectInverse: function()
    {
        var control = this;
        var selected = this.getSelectedRows();
        this.findRow(':not(.selected)').each(function(row){control.selectRow(row, true)});
        selected.each(function(row){control.selectRow(row, false)});
    },

    addNew: function()
    {
        var control = this;
        var new_id = "new_" + this.newIndex++;
        this.findOne('tbody').insert('<tr class="row addnew editing '+new_id+'" key="'+new_id+'"></tr>')
        var editbox = this.findOne(this.editboxSelector);

        var row = this.findOne('.'+new_id);
        row.update(editbox.innerHTML);

        row.find(this.container+this.cellSelector+'.editable').each(function(e)
        {
            e.update('');
            control.enableCellEdit(e);
            var box = e.down('.box');
            var filter = control.findOne(control.filterSelector+'.field-'+e.getAttribute('field')+' select');
            if (filter && filter.value) box.value = filter.value;

            if (box.value && box.value != '#NULL') box.addClassName('changed');

            filter = control.findOne(control.filterSelector+'.field-'+e.getAttribute('field')+' '+GridSelectSelector);
            if (filter)
            {
                box = e.down(GridSelectSelector);
                if (box && (filter.value != ''))
                {
                    box.control.setValue(filter.value);
                    box.control.setDisplayValue(filter.getAttribute('display'));
                }
            }
        });

        var cancel = row.down('.inline_edit');
        cancel.toggleRowEdit = function(){this.up(control.rowSelector+'.editing').remove()};
        cancel.observe('click', function(){this.toggleRowEdit()});
    },

    // :BUG: hoannd002 IE can not automatically observe event when replace elements with the same HTML content element
    //  Solution: observe all after update.
    ajaxComplete: function($super)
    {
        $super();
                                       
        var grids = $$(GridSelector); 
        for (i = 0; i < grids.length; i++)
        {                             
            if (Object.isUndefined(grids[i].control)) new GridControl(grids[i]);
        }
    }
});
