Module:Tablebuilder

-- --|Creates a new html table using the functions and mw.html library ---Variables prefixed with h are mw.html nodes. e.g. hTable is created using mw.html.create('table') local p = {} local tableModel = {} local libraryUtil = require( 'libraryUtil' )

-- //Lazy load methods local createCol,appendRow,appendCol,createRow

--% Creates table model --@ arrTable (table) A Two dimensional array of the table ,e.g. {{'header','header2'},{"cell1","cell2"}} --@ sTableDescription (string) Caption of the table (e.g."green") --@ sStyle (string) Table style ( e.g. sStyle="color:green") --@ tClass (table)- Table classes (e.g. {"wikitable","sortable"}) --: (table) a tablemodel "class" that allows users to create tables function tableModel.new(arrExtData,sTableDescription, sStyle,tClass) local self = {} local checkSelf = libraryUtil.makeCheckSelfFunction( 'tableModel', 'obj', self, 'tableModel object' )

self.tableFormatting = {caption="",class={},style=""} self.arrTable = {}

--% Outputs the attributes of a html table --@ iRow (number) Row number --@ iCol (number) Column number --: (table) attributes for a specific cell (row + col) function self:getAttribs(iRow, iCol) checkSelf(self,"getAttribs") if (self.arrTable[iRow] and self.arrTable[iRow][iCol]) then return self.arrTable[iRow][iCol] end end --% Sets an attribute to a cell --@ iRow (number) Row number --@ iCol (number) Column number --@ oCellAttributes (table) Attributes to be set, a single string attribute or many as a table --@ oAttrVal (string) attribute to be set function self:setCellAttr(iRow,iCol, oCellAttributes, oAttrVal) checkSelf(self,"setCellAttr") if (self.arrTable[iRow] and self.arrTable[iRow][iCol] ) then local oTableData = self:getAttribs(iRow,iCol) local sCellVal = oTableData.sValue if oCellAttributes and type (oCellAttributes)=="string" then oTableData.oFormatting = {[oCellAttributes]=oAttrVal} end if (type(oCellAttributes)=="table" and next(oCellAttributes)) then oTableData.oFormatting = oCellAttributes end end end --% Sets a value to a cell --@ sValue (string) Value to be set to a table --@ iRow (number) Row number --@ iCol (number) Column number --@ formatting (table) Formatting to be set, e.g. {"style"="color:red"} --@ header (boolean) Sets this cell to a header (true to set, false to remove) function self:setCell (sValue,iRow,iCol,oFormatting,bHeader) checkSelf(self,"setCell") if self.arrTable[iRow] and (self.arrTable[iRow][iCol]) then local oTableData = self:getAttribs(iRow,iCol) oTableData.sValue = sValue oTableData.bHeader = bHeader if (not(self.arrTable[iRow]["rowdata"])) then self.arrTable[iRow]["rowdata"]={} end self:setCellAttr(iRow,iCol,oFormatting) end end --% Imports a lua table, changes it to an html table --@ arrInput (table) Table two dimensional (e.g. ) function self:setTable(arrInput) checkSelf(self,"setTable") local bHeader if arrInput and type(arrInput) =="table" then for iRow,tCols in pairs(arrInput) do               if type(tCols)=="table" then self.arrTable[iRow] = {} for iCol,sValue in ipairs(tCols) do                       bHeader = (iRow==1) self.arrTable[iRow][iCol]={} self:setCell (sValue,iRow,iCol,{},bHeader) end else bHeader = true self.arrTable[1] = self.arrTable[1] or {} local iCol = #self.arrTable[1]+1 self.arrTable[1][iCol] = {} self:setCell (tCols,1,iCol,{},bHeader) end end end end

--% Sets data to a cell --@ iRow (number) Row number --@ iCol (number) Column number --@ sField (string) internal table field to set data --@ sNewValue (string) new value function self:setData(iRow,iCol,sField, sNewValue) checkSelf(self,"setData") if (self.arrTable[iRow] and self.arrTable[iRow][iCol]           and self.arrTable[iRow][iCol][sField]) then local arrMetaData = self.arrTable[iRow][iCol] arrMetaData[sField] = sNewValue end end --% Gets a cell from a table --@ iRow (number) Row number --@ iCol (number) Column number --: (table) attributes for a specific cell (row + col) function self:getCell(iRow,iCol) checkSelf(self,"getCell") if self.arrTable[iRow] and self.arrTable[iRow][iCol] then return self.arrTable[iRow][iCol].sValue end end --% Sets the style of a cell --@ iRow (number) Row number --@ iCol (number) Column number --@ sCellStyle (string) Cell style, e.g. ("color") --@ sAttrVal (string) Cell attribute, e.g. ("blue") function self:setCellStyle(iRow,iCol,sCellStyle,sAttrVal) self:setCellAttr(iRow,iCol,sCellStyle,sAttrVal) end --% Sets a cell as a header --@ iRow (number) Row number --@ iCol (number) Column number --@ bHeader (boolean) true if header function self:setCellHeader(iRow,iCol,bHeader) checkSelf(self,"setCellHeader") if self.arrTable[iRow] and self.arrTable[iRow][iCol] then local oTableData = self:getAttribs(iRow,iCol) local sCellVal = oTableData.sValue if (type(bHeader)=="boolean") then oTableData["bHeader"] = bHeader end end end

--% Creates a row --@ tFormatting (string) Formatting to be set, e.g. {"style"="color:red"}.)   --: (table) A mw.html node containing a row    function createRow(tFormatting)        local hTableRow= mw.html.create('tr')        if(tFormatting and type(tFormatting)=="table" and next(tFormatting)) then            hTableRow:attr(tFormatting)            hTableRow:node(sHeadingCol)         end        hTableRow:done        return hTableRow    end    --% Appends a row to a table     --@ hTable (table) hTable mw.html table node --e.g. mw.html.create('table')) --@ tFormatting (table) {["style"]="color:green"} --: (table) A full mw.html table function appendRow(hTable, hRow,tFormatting) if(tFormatting and type(tFormatting)=="table" and next(tFormatting)) then hRow:attr(tFormatting) end if (hRow) and (hTable) then hTable:node(hRow) else return "Syntax error: Row and table cannot be nil!" end return hTable:done end --% Creates a new column --@ sColValue (string) Value of table column --@ tFormatting (table) Formatting to be set, e.g. {"style"="color:red"}. --@ bHeader (boolean) Returns true if header --: (table) A full mw.html node containing a "td" function createCol(sColValue,tFormatting,bHeader) local sTagCol = "td" if (bHeader) then sTagCol ="th" end local hHeadingCol =mw.html.create(sTagCol) if (sColValue and type(sColValue)=="string") or  sColValue =="" or type(sColValue)=="number"  then hHeadingCol:wikitext(sColValue) end if (tFormatting and type(tFormatting)=="table") then local sAttribute, sValues = next(tFormatting) if (type(sAttribute)=="string" and sValues) then hHeadingCol :attr(tFormatting ) else if (sAttribute) then return "Error: Attributes need Key and value ({[key]='value'}), e.g. {['style']='color:blue'}" end end end hHeadingCol:done return hHeadingCol end --% Appends a column cell to a row --@ hColumn (table) A mw.html node containing a column (html th) --@ hTableRow (table) A mw.html node containing a cell (html td) --@ tFormatting (table) Formatting to be set, e.g. {"style"="color:red"}. --: (string) An error if the table is invalid or nil if not function appendCol(hTableRow,hColumn,tFormatting) local sColType = type (hColumn) if sColType =="string" or sColType =="number" or  sColType =="boolean" then hColumn = createCol(hColumn) end if(tFormatting and type(tFormatting)=="table" and next(tFormatting)) then local sAttribute, sValues = next(tFormatting) if (type(sAttribute)=="string" and sValues) then hHeadingCol :attr(tFormatting ) else if (sAttribute) then return "Error: Attributes need Key and value ({[key]='value'}), e.g. {['style']='color:blue'}" end end end if (hTableRow and hColumn and type(hColumn)=="table" ) then hTableRow = hTableRow:node(hColumn) else return "Syntax error: Table row and table column cannot be nil!" end end --% Outputs the html table --: (table) An mw.html node containing the whole table function self:getTable checkSelf(self,"getTable") local hRow,hCell local hTable = mw.html.create("table") hTable:tag("caption") :wikitext(self.tableFormatting.caption) hTable:cssText(self.tableFormatting.style) for i,sClassName in pairs(self.tableFormatting.class) do           if type(sClassName) == "string" then hTable:addClass(sClassName) end end for iRow,tRow in pairs(self.arrTable) do           if (self.arrTable[iRow]) then tRowFormat = self.arrTable[iRow]["rowdata"] end hRow = createRow(tRowFormat) for iCol,oCell in ipairs(tRow) do                if (oCell) then hCell = createCol(oCell.sValue,oCell.oFormatting,oCell.bHeader) appendCol(hRow,hCell) end end appendRow(hTable, hRow) end return hTable:done end --% Sets the rows and columns of table --iRows (number) Number of rows in the table --iColumns (number) Number of columns in the table function self:setGrid(iRows,iColumns) checkSelf(self,"setGrid") local bHeader

for iRowCount=0,iRows do            self.arrTable[iRowCount] = {} bHeader = false for iColCount=0, iColumns do               bHeader = (iRowCount==1) self.arrTable[iRowCount][iColCount] ={["sValue"]= "",["oFormatting"] = {},["bHeader"] =  bHeader} end end end --% Prints out text representation of the table --: (string) text representation of the table function self:getGrid checkSelf(self,"getGrid") local sGrid = "\tCol1\tCol2\n" local sValue for iRow =1,#self.arrTable do           sGrid = sGrid ..iRow.."\t|" for iCol =1, #self.arrTable[iRow] do               sValue = self:getCell(iRow,iCol) or "" sGrid = sGrid .."\t" .. sValue .. "\t|" end sGrid = sGrid .."\n" end return sGrid end --% Sets the styling of a table --@ sTableDescription (string) Description or caption of the table --@ sStyle (string) the styles (e.g. "color:green") --@ tClass (table) the css classes the table will use (e.g.{"bluetable","greentext"}    function self:setTableFormat(sTableDescription, sStyle,tClass)        checkSelf(self,"setTableFormat")        if sTableDescription and type(sTableDescription)=="string"  then              self.tableFormatting.caption = sTableDescription        end        if (tClass) then            if type(tClass)=="table" and next(tClass) then                  self.tableFormatting.class= tClass            end        end         if(sStyle and  type(sStyle)=="string" and sStyle~="") then            self.tableFormatting.style =sStyle        end    end     --% Sets the formatting of a table    --@ iRow (number) The row to add the styling    --@ tFormatting (table) Formatting to be set, e.g. {"style"="color:red"}.    function self:setRowFormat(iRow,tFormatting)        checkSelf(self,"setRowFormat")        if (iRow and  self.arrTable[iRow] and self.arrTable[iRow]["rowdata"]) then self.arrTable[iRow]["rowdata"] = tFormatting end end --% Adds a new row to a table --@ iRow (number) The index of the row to add function self:addRow(iRow) checkSelf(self,"addRow") local sValue ="" local tColumns ={} local iRowToAdd = tonumber(iRow) or 1 if iRow and (iRow>=(#self.arrTable +2) or iRow<1) then return end if self.arrTable and self.arrTable[1] then iRowToAdd = iRow or #self.arrTable+1 for i=1,#self.arrTable[1] do               tColumns[i] = {} end end table.insert(self.arrTable,iRowToAdd,tColumns) end --% Removes a row from the table --@ iRow (number) The index of the row to remove function self:removeRow(iRow) checkSelf(self,"removeRow") if self.arrTable[iRow] then table.remove(self.arrTable,iRow) end end --% Sets the contents of a row --@ iRow (number) The index of the row to set --@ tTable (table) contents (e.g. {2,3}) function self:setRow(iRow,tTable) checkSelf(self,"setRow") if iRow and self.arrTable[iRow] and tTable then for iCol,sValue in pairs(tTable) do               self:setCell(sValue,iRow,iCol) end end end --% Adds a new column to the table --@ sColName(string) Name of the column --@ iCol (number) The index of the column to set function self:addCol(sColName,iCol) checkSelf(self,"addCol")

if iCol and self.arrTable and self.arrTable[1] and (iCol>=#self.arrTable[1] +2 or iCol<1) then return end

if self.arrTable and self.arrTable[1] and not(iCol) then iCol = #self.arrTable[1]+1 end

if self.arrTable[1] then table.insert(self.arrTable[1],iCol,{}) self:setCell(sColName,1,iCol,{},true) end end --% Removes a new column to the table --@ iCol (number) The index of the column to remove function self:removeCol(iCol) checkSelf(self,"removeCol")

if iCol then for i,v in pairs(self.arrTable) do               if self.arrTable[i] and self.arrTable[i][iCol] then table.remove(self.arrTable[i],iCol) end end end end --% Gets number of rows in table --: (number) Number of rows function self:getRowCount checkSelf(self,"getRowCount") return #self.arrTable end --% Gets number of columns in table --: (number) Number of columns function self:getColCount(iRow) checkSelf(self,"getColCount") iRow = iRow or 1 if self.arrTable[iRow] then return #self.arrTable[iRow] end return 0 end --% Initializes the tablebuilder (internal use) function initialize self.setTableFormat(self,sTableDescription, sStyle,tClass) self:setTable(arrExtData) end -- //Constructor initialize return self end --% Create a new table builder --@ arrExtData (table) A two dimensional array containing a table e.g {{"Girls","Boys"},{"Xena","Hercules"}} --@ sTableDescription (string) A caption for the table e.g. "Table of boys and girls --@ sStyle (string) Basic styling for the table  e.g. "background:green" --@ tClass (table) CSS classes for the whole table e.g. {"boysandgirls","red"} function p.new(arrExtData,sTableDescription, sStyle,tClass)    return tableModel.new(arrExtData,sTableDescription, sStyle,tClass) end

-- Test code function p.test(frame) -- Array consisting of rows and columns local tRowData = { -- Row Columns {"1","2"},       {"44","3"},         {"6","8"},     }

local c = tableModel.new(tRowData,"Table","",{"wikitable"}) local row1 = 4 local col1 = 1 local celltext = "green" local cellFormat = {["style"]="color:green"} c:addRow c:setCell("7",row1,col1) c:setCell("2",row1,2) local row2 = 1 local col2 = 1 c:setCell(celltext,row2,col2,cellFormat) return c:getTable end -- End Test code return p