/**
@fileOverview
Part of the QlikView WorkBench Javascript Library (http://www.qlikwebworkbench.com)<br /><br />
Copyright (c) 2009 QlikTech International AB (http://www.qliktech.com)<br /><br />
All Rights Reserved. Email support@qliktech.com for licensing and support information.<br /><br />
@author <a href="mailto:email@industrialcodebox.com">Industrial CodeBox</a>
*/

Qww.Ctls.FlexiGrid = {};

/**
Constructs a new Qww.Ctls.FlexiGrid.Mgr instance.
@class JavaScript control to render the contents of a QlikView table in a flexible grid format where the developer 
specifies JavaScript functions to run to render the different components. This also supports rendering the contents 
of a listbox in the same way.<br />

@param {Object} cfg JSON object to configure Qww.Ctls.FlexiGrid.Mgr.

@param {String} cfg.ObjectID Id of the table or listbox in the QlikView document.

@param {Qww.QlikViewObjectType} [cfg.SourceQlikviewObjectType=Qww.QlikViewObjectType.TableBox] Type of object which 
flexi grid will render. If you specify Qww.QlikViewObjectType.TableBox.ListBox you can simulate columns of data by concatenating 
entries in the listbox using the '#' character.

@param {String} cfg.ElementToShowResultsIn ID of html element to show results grid in.

@param {Function} cfg.OnRenderRecord Function to call to render the current record, should take the following 
three parameters (flexiGrid, record, numberOfResults). Record will either be a Qww.Table.Row or a Qww.ListBox.Item depending 
on the cfg.SourceQlikviewObjectType setting. This function should return an object with EITHER a .Html property containing 
the html string to represent the record in the flexi grid or a .Element property containing a DOM element representing the 
record.

@param {String} [cfg.ElementToShowResultsSummaryIn] ID of html element to show results summary in.

@param {String} [cfg.ElementToShowSortControlIn] ID of html element to show sort control in.

@param {String} [cfg.ElementToShowPagingIn] ID of html element to show paging control in.

@param {Int} [cfg.TableSelectColumn=0] If a tabular control is used behind the flexigrid then this specifies which column is used for selections.

@param {Int} [cfg.NumberOfColumns=5] Number of columns for the flexi grid.

@param {Int} [cfg.NumberOfRows=10] Number of rows for the flexi grid.

@param {Function} [cfg.OnInitialised] Function to call after the control has been initialised. This should accept a single parameter 
(a reference to this control).

@param {String} [cfg.SortAscendingIcon=../images/QvExFlexiGridCtl/SortAsc.png] Path to sort ascending icon.

@param {String} [cfg.SortDescendingIcon=../images/QvExFlexiGridCtl/SortDesc.png] Path to sort ascending icon.

@param {String} [cfg.Theme=Default] Theme to use (this string gets used in css class names, for example QwwJs_FlexiGridCtl-PagingLink-ThemeName).

@param {String} [cfg.UpdatingHtml] Html to show in the flexi grid whilst it is updating. This can be used, for example, to show an animated GIF during 
updates.

@param {Function} [cfg.OnRenderSummary] Function to call to render the summary string for the control. This should accept a single parameter 
(a reference to this control) and return an object with either a .Html property containing the html string to represent the summary or a 
.Element property containing a DOM element representing the summary.

@param {Function} [cfg.OnRenderPaging] Function to call to render the paging control. This should accept a single parameter 
(a reference to this control) and return an object with either a .Html property containing the html string to represent the paging control or a 
.Element property containing a DOM element representing the paging control.

@param {Function} [cfg.OnInitialised] Function to call when the control has been initialised.

@param {Function} [cfg.OnRenderBegin] Function to call when the control is about to re-render.

@param {Function} [cfg.OnRenderComplete] Function to call when the control is about to complete rendering.

@param {String} [cfg.ApplicationID=null] Id/Name of the QlikView document. Note this is <strong>only</strong> necessary when 
multiple QlikView documents are being used on the same web page and should otherwise be set to null.
*/
Qww.Ctls.FlexiGrid.Mgr = function(cfg) {
    /*
    AVAILABLE MEMBERS

    //
    // The following are actual functions which can be called.
    //
    flexiGrid.SelectSingleRecord = function(RecordNumber)
    flexiGrid.PageDown()
    flexiGrid.PageUp()
    flexiGrid.SetPage(pageNumber)

    //
    // The following are the string names of functions which can be called.
    // Useful if you are building html strings rather than DOM elements.
    // e.g. var html = "<img onclick='" + 
    //                  flexiGrid.SelectSingleRecordMethodAsString + 
    //                  "(" + record.RecordNumber + ");'/>";
    //
    flexiGrid.PageUpMethodAsString
    flexiGrid.PageDownMethodAsString
    flexiGrid.SetPageMethodAsString
    flexiGrid.SelectSingleRecordMethodAsString

    //
    // Public properties reflecting current data in flexi grid.
    //
    flexiGrid.NumberOfPages
    flexiGrid.TotalSize
    flexiGrid.PageSize
    flexiGrid.CurrentPage
    flexiGrid.NoRows
    */

    /** 
    Number of rows in the current page of data (note that it may be less than the PageSize if it's the last page of data).
    @type Int
    */
    this.NumberOfPages = -1;

    /** 
    Total number of rows in the table or listbox.
    @type Int
    */
    this.TotalSize = -1;

    /** 
    Number of rows per page of data received for the table. This will be the number of rows x number of columns in the flexi grid.
    @type Int
    */
    this.PageSize = -1;

    /**
    Returns the current page number which the TableMgr holds data for.
    @property
    @type Int
    */
    this.CurrentPage = -1;

    /** 
    Number of rows in the current page of data (note that it may be less than the 
    PageSize if it's the last page of data).
    @type Int
    */
    this.NoRows = -1;

    /**
    Reference to the configuration object which was used to create construct the object. This 
    allows certain properties to be updated after initial instantiation.
    @type Object
    */
    this.Cfg = cfg;

    /**
    Reference to the TableMgr instance being used to communication with the underlying table. 
    Note that this will be null if the cfg.SourceQlikviewObjectType was set to Qww.QlikViewObjectType.ListBox 
    when the control was constructed.
    @type Qww.Table.Mgr
    */
    this.TableMgr = null;

    /**
    Reference to the ListBoxMgr instance being used to communication with the underlying listbox. 
    Note that this will be null if the cfg.SourceQlikviewObjectType was NOT set to Qww.QlikViewObjectType.ListBox 
    when the control was constructed.
    @type Qww.ListBox.Mgr
    */
    this.ListBoxMgr = null;

    /**
    Name of method to call to call page up function. Useful, for example, when contatenating html strings in OnRenderPaging if 
    returning a string rather than a DOM object.
    @example
    var pageUpHtml = "&lt;a href='#' onlclick='" + 
    flexiGrid.PageUpMethodAsString + "();" + 
    "'&gt;Page Up&lt;/a&gt;"
    */
    this.PageUpMethodAsString = null;

    /**
    Name of method to call to call page up function. Useful, for example, when contatenating html strings in OnRenderPaging if 
    returning a string rather than a DOM object.
    @example
    var pageUpHtml = "&lt;a href='#' onlclick='" + 
    flexiGrid.PageDownMethodAsString + "();" + 
    "'&gt;Page Down&lt;/a&gt;"
    */
    this.PageDownMethodAsString = null;

    /**
    Name of method to call to call set page function. Useful, for example, when contatenating html strings in OnRenderPaging if 
    returning a string rather than a DOM object.
    @example
    var setFirstPageHtml = "&lt;a href='#' onlclick='" + 
    flexiGrid.SetPageMethodAsString + "(1);" + 
    "'&gt;First Page&lt;/a&gt;"
    */
    this.SetPageMethodAsString = null;

    /**
    Name of method to call to call set page function. Useful, for example, when contatenating html strings in OnRenderRecord if 
    returning a string rather than a DOM object.
    @example
    var selectRecordHtml = "&lt;a href='#' onlclick='" + 
    flexiGrid.SelectSingleRecordMethodAsString + "(" + record.RecordNumber + " )" + 
    "'&gt;Select&lt;/a&gt;"
    */
    this.SelectSingleRecordMethodAsString = null;

    var me = this;

    this.ObjectName = "FlexiGridCtl";

    var dataProvider;
    var _maxNumberOfProductsToShow;

    // -------------------------------------------------------------
    // Start of setting up defaults
    if (!this.Cfg.SourceQlikViewObjectType)
        this.Cfg.SourceQlikViewObjectType = Qww.QlikViewObjectType.TableBox;

    if (!this.Cfg.NumberOfColumns)
        this.Cfg.NumberOfColumns = 5;

    if (!this.Cfg.TableSelectColumn)
        this.Cfg.TableSelectColumn = 0;

    if (!this.Cfg.NumberOfRows)
        this.Cfg.NumberOfRows = 10;

    if (!this.Cfg.Theme)
        this.Cfg.Theme = "Default";

    if (this.Cfg.OnInitialised)
        this.Cfg.OnInitialised(me);

    if (!this.Cfg.SortAscendingIcon)
        this.Cfg.SortAscendingIcon = "../images/QvExFlexiGridCtl/SortAsc.png";

    if (!this.Cfg.SortDescendingIcon)
        this.Cfg.SortDescendingIcon = "../images/QvExFlexiGridCtl/SortDesc.png";

    var webRoot = "../";

    var sortElement = null;
    var sortSelect = null;
    var sortImageButtonSpan = null;

    function showLoadingContent() {
        if (me.Cfg.UpdatingHtml)
            document.getElementById(me.Cfg.ElementToShowResultsIn).innerHTML = me.Cfg.UpdatingHtml;
    }

    this.OnDocumentLoaded = function() {
        try {
            if (me.Cfg.OnInitialised)
                me.Cfg.OnInitialised(me);
        } catch (e) { }

        showLoadingContent();

        if (!me.Cfg.ElementToShowResultsIn && me.Cfg.ElementToShowResultsIn.length > 0)
            me.UserAlert("Constructed with no 'ElementToShowResultsIn' property.");
        else {

            var elem = me.GetElement(me.Cfg.ElementToShowResultsIn);

            if (elem != null) {

                me.RenderPagingDefault = renderPagingDefault;
                me.RenderSummaryDefault = renderSummaryDefault;

                me.PageUpMethodAsString = getFlexiGridMethod("PageUp");
                me.PageDownMethodAsString = getFlexiGridMethod("PageDown");
                me.SetPageMethodAsString = getFlexiGridMethod("SetPage");
                me.SelectSingleRecordMethodAsString = getFlexiGridMethod("SelectSingleRecord");

                //                if (me.Cfg.SourceQlikViewObjectType == Qww.QlikViewObjectType.TableBox || me.Cfg.SourceQlikViewObjectType == Qww.QlikViewObjectType.Chart_Table) {

                //                    var tblMgrCfg = {};

                //                    tblMgrCfg.ObjectID = me.Cfg.ObjectID;
                //                    tblMgrCfg.ColumnIndexes = me.Cfg.ColumnIndexes;
                //                    tblMgrCfg.PageSize = (me.Cfg.NumberOfRows * 1) * (me.Cfg.NumberOfColumns * 1);
                //                    tblMgrCfg.OnUpdate = updateTable;

                //                    _maxNumberOfProductsToShow = tblMgrCfg.PageSize;

                //                    me.TableMgr = new Qww.Table.Mgr(tblMgrCfg);

                //                    me.Headers = me.TableMgr.Headers;

                //                    dataProvider = me.TableMgr;
                //                }
                //                else if (me.Cfg.SourceQlikViewObjectType == Qww.QlikViewObjectType.ListBox) {

                //                    var pageSize = (me.Cfg.NumberOfRows * 1) * (me.Cfg.NumberOfColumns * 1);
                //                    me.ListBoxMgr = new Qww.ListBox.Mgr({ ObjectID: me.Cfg.ObjectID, PageSize: pageSize, OnUpdate: updateTable });
                //                    _maxNumberOfProductsToShow = pageSize;

                //                    dataProvider = me.ListBoxMgr;
                //                }
                //                else {
                //                    me.UserAlert("SourceQlikViewObjectType '" + me.Cfg.SourceQlikViewObjectType + "' not supported.");
                //                }

                me.DataProvider = dataProvider;

                // Tag the element with the FLexiGridMgr so that late we can pass through the object
                // to call select and paging methods on.
                elem.FlexiGridCtl = me;
            }
            else
                me.UserAlert("Cannot find element this.Cfg.ElementToShowResultsIn = " + me.Cfg.ElementToShowResultsIn);
        }
    }

    // End of setting up defaults
    // -------------------------------------------------------------

    /** 
    Selects a single record in the flexi grid. Note that if a table is being used as the underlying control 
    to provide the data then the column used for the selection will be that of the optional .TableSelectColumn specified on the configuration 
    object used to construct this control (which defaults to 0). If a ListBox is being used to provide the data then the argument should be 
    the value of the underlying item. Otherwise it should be the record number of the row in the table.
    @param {Int} recordNumber Record number to select.
    */
    this.SelectSingleRecord = function(recordNumberOrListItemValue) {
        showLoadingContent();
        dataProvider.SelectSingleRecord(recordNumberOrListItemValue, me.Cfg.TableSelectColumn); // Note - 2nd argument only relevant if dataProvider is TableMgr
    };

    /** 
    Moves to the next page of data in the table/listbox.
    @returns {Bool} Returns true if the page was changed (if the table 
    was already set to the last page then false will be returned).
    */
    this.PageDown = function() {

        var updating = false;

        if (me.CurrentPage > 1)
            updating = dataProvider.PageDown();

        if (updating)
            showLoadingContent();
    };

    /** 
    Moves to the previous page of data in the table/listbox.
    @returns {Bool} Returns true if the page was changed (if the table 
    was already set to the first page then false will be returned).
    */
    this.PageUp = function() {

        var updating = false;

        if (me.CurrentPage < me.NumberOfPages)
            updating = dataProvider.PageUp();

        if (updating)
            showLoadingContent();
    };

    /** 
    Moves to the page number specified. Note that the first page is 1.
    @param {Int} pageNumber Page number to move to.
    */
    this.SetPage = function(page) {

        showLoadingContent();
        dataProvider.SetPage(page);
    };

    function renderPagingDefault() {
        var noRowsToPassToRenderer = me.NoRows;

        // ListBox is a special case as normally making a select still
        // shows all items in the flexigrid (even though one is in the 
        // selected state.
        if (me.ListBoxMgr && me.ListBoxMgr.Results.GetSelected().length == 1)
            noRowsToPassToRenderer = 1;

        if (noRowsToPassToRenderer > 1) {
            if (me.NumberOfPages > 1) {
                var pagingLinkClass = me.GetClassNameWithThemePostfix("PagingLink");

                var fistPage = "<a class='" + pagingLinkClass + "' style='cursor:pointer' alt='First Page' onclick='" + me.SetPageMethodAsString + "(1);'>|</a>";
                var pageUp = "<a class='" + pagingLinkClass + "' style='cursor:pointer' alt='Page Up' onclick='" + me.PageUpMethodAsString + "();'>&gt;&gt;</a>";
                var pageDown = "<a class='" + pagingLinkClass + "' style='cursor:pointer' alt='Page Down' onclick='" + me.PageDownMethodAsString + "();'>&lt;&lt;</a>";
                var lastPage = "<a class='" + pagingLinkClass + "' style='cursor:pointer' alt='Last Page' onclick='" + me.SetPageMethodAsString + "(" + me.NumberOfPages + ");'>|</a>";

                var obj = {};

                obj.Html = "Displaying Page " + me.CurrentPage + " Of " + me.NumberOfPages + "&nbsp;-&nbsp;"
                        + fistPage + " " + pageDown + " " + pageUp + " " + lastPage;

                return obj;
            }
            else {
                return "Displaying Page 1 of 1";
            }
        }
        else {
            return "&nbsp;";
        }
    };

    function renderSummaryDefault(args) {
        var obj = {};
        if (me.TableMgr)
            obj.Html = "Displaying " + args.NoRows + " out of " + args.TotalSize + " matches.";
        else
            obj.Html = "Displaying " + args.NoRows + " out of " + args.TotalSize + ".";

        return obj;
    };

    function getFlexiGridMethod(methodName) {
        var method = "document.getElementById(\"" + me.Cfg.ElementToShowResultsIn + "\").FlexiGridCtl";
        return method + "." + methodName;
    };


    function updatePaging() {
        if (cfg.ElementToShowPagingIn) {
            var res;
            var useDefaultRenderer = false;

            if (me.Cfg.OnRenderPaging) {
                res = me.Cfg.OnRenderPaging(me);
                if (res == null)
                    useDefaultRenderer = true;
            }
            else
                useDefaultRenderer = true;

            if (useDefaultRenderer)
                res = renderPagingDefault();

            setContents(cfg.ElementToShowPagingIn, res);
        }
    };

    function updateSummary() {
        if (me.Cfg.ElementToShowResultsSummaryIn) {
            var res;
            var useDefaultRenderer = false;

            if (me.Cfg.OnRenderSummary) {
                res = me.Cfg.OnRenderSummary(me);
                if (res == null)
                    useDefaultRenderer = true;
            }
            else
                useDefaultRenderer = true;

            if (useDefaultRenderer)
                res = renderSummaryDefault(me);

            setContents(cfg.ElementToShowResultsSummaryIn, res);
        }
    };

    function setContents(elementId, res) {
        if (res.Html) {
            document.getElementById(elementId).innerHTML = res.Html;
        }
        else if (res.Element) {

            var elem = me.GetElement(elementId);

            while (elem.childNodes.length >= 1)
                elem.removeChild(elem.firstChild);

            elem.appendChild(res.Element);
        }
        else {
            document.getElementById(elementId).innerHTML = res;
        }
    };

    function renderRecord(record, noResults) {
        try {
            if (me.Cfg.OnRenderRecord)
                return me.Cfg.OnRenderRecord(me, record, noResults);
            else
                return "No OnRenderRecord specified.";
        }
        catch (e) {
            alert(QwwJs.Alert("QwwJs_FlexiGridCtlMgr.renderRecord:" + e.message));
        }
    };

    function setSortImage(isAscending) {
        var image = me.Cfg.SortAscendingIcon;

        if (!isAscending)
            image = me.Cfg.SortDescendingIcon;

        sortImageButtonSpan.innerHTML = "<img class='" + me.GetClassNameWithThemePostfix("SortButtonIcon") + "' src='" + image + "' />";
    };

    function buildSortControl() {
        if (sortSelect != null)
            return;

        var dp = me.DataProvider;

        if (!dp.SupportsSorting)
            return;

        if (!me.Cfg.ElementToShowSortControlIn)
            return;

        var elem = document.getElementById(me.Cfg.ElementToShowSortControlIn);

        if (!elem)
            return;

        sortElement = elem;

        if (dp.Headers) // ListBox provider wont have headers..
        {
            var select = document.createElement("select");
            sortSelect = select;

            sortImageButtonSpan = document.createElement("span");
            //span.innerHTML = "&nbsp;Sort";
            setSortImage(true);

            sortImageButtonSpan.style.cursor = 'hand';

            sortImageButtonSpan.onclick = function() {
                me.DataProvider.Sort(select.value);
            };

            select.onchange = function() {
                me.DataProvider.Sort(select.value);
            };

            var headers = dp.Headers;

            var sortableColumnIndexes = null;

            if (me.Cfg.SortableColumnIndexes != null && me.Cfg.SortableColumnIndexes != "*") {
                try {
                    sortableColumnIndexes = me.Cfg.SortableColumnIndexes.split(",");
                }
                catch (e) {
                    // There might be a problem with the string in which case use all headers.
                    sortableColumnIndexes = new Array(headers.length);

                    var arrLength = headers.length;

                    for (j = 0; j < arrLength; j++) {
                        sortableColumnIndexes[j] = headers[j].HeaderIndex;
                    }
                }
            }
            else {
                sortableColumnIndexes = new Array(headers.length);

                var arrLength = headers.length;

                for (j = 0; j < arrLength; j++) {
                    sortableColumnIndexes[j] = headers[j].HeaderIndex;
                }
            }

            sortSelect.Items = new Array();

            var getHeaderFromIndex = function(index) {

                var arrLength = headers.length;

                for (k = 0; k < arrLength; k++) {
                    if (headers[k].HeaderIndex == index) {
                        return headers[k];
                    }
                }

                return null;
            };

            var arrLength = sortableColumnIndexes.length;
            
            for (var i = 0; i < arrLength; i++) {
                var header = getHeaderFromIndex(sortableColumnIndexes[i]);

                var option = document.createElement("OPTION");
                option.setAttribute("value", header.HeaderSortIndex);

                // Seem to need both the following to ensure text appears in IE, Safari and Firefox
                //option.innerText = header.HeaderText;
                //option.text = header.HeaderText;

                jQuery(option).text(header.HeaderText);

                option.Header = header;
                select.appendChild(option);

                sortSelect.Items[sortSelect.Items.length] = option;
            }

            while (elem.childNodes.length >= 1)
                elem.removeChild(elem.firstChild);

            elem.appendChild(select);
            elem.appendChild(sortImageButtonSpan);
        }
    }

    function selectSortedColumnInDropDown() {
        if (dataProvider.Headers) {
            var sortHeader = null;

            var arrLength = dataProvider.Headers.length;
            
            for (h = 0; h < arrLength; h++) {
                var header = dataProvider.Headers[h];

                if (header.SortDirection) {
                    sortHeader = header;
                    break;
                }
            }

            if (sortHeader) {

                var arrLength = sortSelect.Items.length;
                
                for (i = 0; i < arrLength; i++) {
                    var header = sortSelect.Items[i].Header;

                    if (header.HeaderSortIndex == sortHeader.HeaderSortIndex) {
                        sortSelect.selectedIndex = i;

                        setSortImage(sortHeader.SortDirection == "asc");
                        break;
                    }
                }
            }
        }
    }

    function buildTableUsingHtmlStringsUsingDom() {
        var ids = new Array();

        var currentProduct = 0;

        var rowIndex = 1;
        var rowIndexOffset = me.PageSize * (me.CurrentPage - 1);

        var hasOneResultBeenRendered = false;

        if (me.Cfg.OnRenderBegin)
            me.Cfg.OnRenderBegin(me);

        // creates <table> and <tbody> elements
        var mytable = document.createElement("table");
        mytable.style.width = "100%";
        var mytablebody = document.createElement("tbody");
        mytable.className = me.GetClassNameWithThemePostfix("ResultsTable");

        var mycurrent_cell;

        var noRows = me.NoRows;

        for (var i = 0; i < noRows; i++) {
            mycurrent_row = document.createElement("tr");

            var arrLength = me.Cfg.NumberOfColumns;
            
            for (c = 0; c < arrLength; c++) {
                mycurrent_cell = document.createElement("td");

                if ((currentProduct < noRows) &&
                    (currentProduct <= _maxNumberOfProductsToShow)) {
                    var resultRow;

                    if (me.TableMgr) {
                        resultRow = me.TableMgr.GetRow(currentProduct);

                        while (resultRow.IsHeader) {
                            currentProduct++;
                            resultRow = me.TableMgr.GetRow(currentProduct);
                        }
                    }
                    else {
                        if (me.ListBoxMgr.Results.GetSelected().length == 1 && hasOneResultBeenRendered == true)
                            continue;

                        hasOneResultBeenRendered = true;

                        //                        var row = me.ListBoxMgr.Results.All[currentProduct];
                        //                        resultRow = new Array();
                        //                        resultRow.State = row.State;
                        //                        resultRow.RecordNumber = row.Value;
                        //                        resultRow.StateAsString = Qww.ListBox.Mgr.ItemState.GetStateAsString(row.State);

                        //                        var parts = row.Text.split("#");

                        //                        for (var x = 0; x < parts.length; x++) {
                        //                            resultRow[x] = {};
                        //                            resultRow[x].Text = parts[x];
                        //                        }

                        // This should be a Qww.ListBox.Item instance.
                        var resultRow = me.ListBoxMgr.Results.All[currentProduct];
                        //resultRow = new Array();
                        //resultRow.State = row.State;
                        resultRow.RecordNumber = resultRow.Value;
                        //resultRow.StateAsString = Qww.ListBox.Mgr.ItemState.GetStateAsString(row.State);

                        resultRow.ParseCellsFromText("#");
                    }

                    //resultRow.RowIndex = rowIndex++ + rowIndexOffset;

                    if (currentProduct > _maxNumberOfProductsToShow) {
                        //currenttext = document.createTextNode("&nbsp;");
                    }
                    else {
                        var noRowsToPassToRenderer = noRows;

                        // ListBox is a special case as normally making a select still
                        // shows all items in the flexigrid (even though one is in the 
                        // selected state.
                        if (me.ListBoxMgr && me.ListBoxMgr.Results.GetSelected().length == 1)
                            noRowsToPassToRenderer = 1;

                        var obj = renderRecord(resultRow, noRowsToPassToRenderer);

                        if (obj.Element) {
                            mycurrent_cell.appendChild(obj.Element);
                        }
                        else {
                            var innerHtml = "";

                            if (obj.Html || obj.Html == "")
                                innerHtml = obj.Html;
                            else
                                innerHtml = obj;

                            mycurrent_cell.innerHTML = innerHtml;
                        }

                        mycurrent_row.appendChild(mycurrent_cell);
                    }

                    currentProduct++
                }

                //                mycurrent_row.appendChild(mycurrent_cell);
            }

            mytablebody.appendChild(mycurrent_row);

            if (currentProduct >= noRows || currentProduct > _maxNumberOfProductsToShow) {
                break;
            }
        }

        //        var style = "";
        //        if(me.Cfg.Width) style += "width:" + me.Cfg.Width + ";";
        //        if(me.Cfg.Height) style += "height:" + me.Cfg.Height + ";";
        //        
        //        mytable.setAttribute("style", style);

        var elem = me.GetElement(cfg.ElementToShowResultsIn);

        while (elem.childNodes.length >= 1)
            elem.removeChild(elem.firstChild);

        mytable.appendChild(mytablebody);

        elem.appendChild(mytable);

        if (me.Cfg.OnRenderComplete)
            me.Cfg.OnRenderComplete(me);
    };

    function updateTable(arg1, arg2) {

        if (arg1.Mode != Qww.QlikViewObjectState.Hidden) {
            $("#" + me.Cfg.ElementToShowResultsIn).show();
        }
        else {
            $("#" + me.Cfg.ElementToShowResultsIn).hide();
            return;
        }

        if (me.Cfg.OnRenderBegin)
            me.Cfg.OnRenderBegin(me);

        buildSortControl();

        if (me.Cfg.SourceQlikViewObjectType == Qww.QlikViewObjectType.TableBox ||
                me.Cfg.SourceQlikViewObjectType == Qww.QlikViewObjectType.Chart_Table) {

            var flex = arg1;

            me.NumberOfPages = me.TableMgr.NoPages;
            me.TotalSize = me.TableMgr.TotalSize;
            me.PageSize = me.TableMgr.PageSize;
            me.CurrentPage = me.TableMgr.CurrentPage;
            me.NoRows = me.TableMgr.NoRows;
        }
        else {
            var flex = arg2;
            var lisBoxMgr = arg1;

            me.NumberOfPages = lisBoxMgr.NoPages;
            me.TotalSize = lisBoxMgr.TotalSize;
            me.PageSize = lisBoxMgr.PageSize;
            me.CurrentPage = lisBoxMgr.CurrentPage;
            me.NoRows = lisBoxMgr.Results.All.length;
        }

        buildTableUsingHtmlStringsUsingDom();
        updatePaging();
        updateSummary();

        //        var newResults = new Array();

        //        for (var i = 0; i < me.NoRows; i++) {
        //            if (me.Cfg.SourceQlikViewObjectType == Qww.QlikViewObjectType.TableBox ||
        //                me.Cfg.SourceQlikViewObjectType == Qww.QlikViewObjectType.Chart_Table) {

        //                var row = dataProvider.GetRow(i);
        //                newResults[newResults.length] = row;
        //            }
        //            else {
        //                if (me.ListBoxMgr.Results.GetSelected().length == 1 && hasOneResultBeenRendered == true)
        //                    continue;

        //                hasOneResultBeenRendered = true;

        //                var row = me.ListBoxMgr.Results.all[i];
        //                resultRow = new Array();
        //                resultRow.State = row.State;
        //                resultRow.RecordNumber = row.Value;
        //                resultRow.StateAsString = Qww.ListBox.Mgr.ItemState.GetStateAsString(row.State);

        //                var parts = row.Text.split("#");

        //                for (var x = 0; x < parts.length; x++) {
        //                    resultRow[x] = {};
        //                    resultRow[x].Text = parts[x];
        //                }

        //                newResults[newResults.length] = resultRow;
        //            }
        //        }


        if (sortElement) {
            if (me.NoRows <= 1) {
                sortElement.style.display = 'none';
            }
            else {
                sortElement.style.display = '';
                selectSortedColumnInDropDown();
            }
        }

        if (me.Cfg.OnRenderComplete)
            me.Cfg.OnRenderComplete(me);

    };

    (function() {
        if (me.Cfg.SourceQlikViewObjectType == Qww.QlikViewObjectType.TableBox || me.Cfg.SourceQlikViewObjectType == Qww.QlikViewObjectType.Chart_Table) {

            var tblMgrCfg = {};

            tblMgrCfg.ObjectID = me.Cfg.ObjectID;
            tblMgrCfg.ColumnIndexes = me.Cfg.ColumnIndexes;
            tblMgrCfg.PageSize = (me.Cfg.NumberOfRows * 1) * (me.Cfg.NumberOfColumns * 1);
            tblMgrCfg.OnUpdate = updateTable;

            _maxNumberOfProductsToShow = tblMgrCfg.PageSize;

            me.TableMgr = new Qww.Table.Mgr(tblMgrCfg);

            me.Headers = me.TableMgr.Headers;

            dataProvider = me.TableMgr;
        }
        else if (me.Cfg.SourceQlikViewObjectType == Qww.QlikViewObjectType.ListBox) {

            var pageSize = (me.Cfg.NumberOfRows * 1) * (me.Cfg.NumberOfColumns * 1);
            me.ListBoxMgr = new Qww.ListBox.Mgr({ ObjectID: me.Cfg.ObjectID, PageSize: pageSize, OnUpdate: updateTable });
            _maxNumberOfProductsToShow = pageSize;

            dataProvider = me.ListBoxMgr;
        }
        else {
            me.UserAlert("SourceQlikViewObjectType '" + me.Cfg.SourceQlikViewObjectType + "' not supported.");
        }
    })();

    if (qwwHub)
        qwwHub.Register(this);
};

Qww.Ctls.FlexiGrid.Mgr.prototype = new Qww.ControlBase("QwwJs_FlexiGridCtl");
