Module:Tablebuilder
Jump to navigation
Jump to search
Documentation for this module may be created at Module:Tablebuilder/doc
-- <nowiki>
--|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. {{'f','z'}})
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