Module:Tabular data

#invoke:documentation

local p = {}
local lang = mw.getContentLanguage()
local navbar = require("Module:Navbar")

local messages = {
	["true"] = "Yes",
	["false"] = "No",
	null = "N/A",
}

local bgColors = {
	["true"] = "#9f9",
	["false"] = "#f99",
	null = "#ececec",
}

local colors = {
	null = "#2c2c2c",
}

function p._cell(args)
	local data = args.data or mw.ext.data.get(args[1])
	local rowIdx = tonumber(args.output_row)
	local outputFormat = args.output_format
	
	local outputColumnNames = {
		args.output_column1 or args.output_column,
	}
	while args["output_column" .. #outputColumnNames + 1] do
		table.insert(outputColumnNames, args["output_column" .. #outputColumnNames + 1])
	end
	
	local outputColumnIdxs = {}
	local numOutputColumnIdxs = 0
	for i, field in ipairs(data.schema.fields) do
		for j, outputColumnName in ipairs(outputColumnNames) do
			if field.name == outputColumnName then
				outputColumnIdxs[outputColumnName] = i
				numOutputColumnIdxs = numOutputColumnIdxs + 1
			end
		end
		if numOutputColumnIdxs == #outputColumnNames then
			break
		end
	end
	if numOutputColumnIdxs < #outputColumnNames then
		for i, outputColumnName in ipairs(outputColumnNames) do
			assert(outputColumnIdxs[outputColumnName],
				mw.ustring.format("Output column “%s” not found.", outputColumnName))
		end
	end
	
	if rowIdx > 0 then
		rowIdx = (rowIdx - 1) % #data.data + 1
	elseif rowIdx < 0 then
		rowIdx = rowIdx % #data.data + 1
	else
		error("0 is not a valid row index.")
	end
	
	local record = data.data[rowIdx]
	if record ~= nil then
		if outputFormat or numOutputColumnIdxs > 1 then
			local values = {}
			for i, columnName in ipairs(outputColumnNames) do
				local columnIdx = outputColumnIdxs[columnName]
				table.insert(values, record[columnIdx])
			end
			if outputFormat then
				return mw.ustring.format(outputFormat, unpack(values))
			else
				return mw.text.listToText(values)
			end
		else
			local columnIdx = outputColumnIdxs[outputColumnNames[1]]
			return record[columnIdx]
		end
	end
end

--- Returns the value of the cell at the given row index and column name.
--- A row index of 1 refers to the first row in the table. A row index of -1
--- refers to the last row in the table. It is an error to specify a row index
--- of 0.
--- Usage: {{#invoke:Tabular data | cell | Table name | output_row = Index of row to output | output_column = Name of column to output }}
function p.cell(frame)
	return p._cell(frame.args)
end

function p._lookup(args)
	local data = args.data or mw.ext.data.get(args[1])
	local searchValue = args.search_value
	local searchPattern = args.search_pattern
	local searchColumnName = args.search_column
	
	local searchColumnIdx
	for i, field in ipairs(data.schema.fields) do
		if field.name == searchColumnName then
			searchColumnIdx = i
		end
		if searchColumnIdx then
			break
		end
	end
	assert(searchColumnIdx, mw.ustring.format("Search column “%s” not found.", searchColumnName))
	
	local occurrence = tonumber(args.occurrence) or 1
	
	local numMatchingRecords = 0
	for i = (occurrence < 0 and #data.data or 1),
		(occurrence < 0 and 1 or #data.data),
		(occurrence < 0 and -1 or 1) do
		local record = data.data[i]
		if (searchValue and record[searchColumnIdx] == searchValue) or
			(searchPattern and mw.ustring.match(tostring(record[searchColumnIdx]), searchPattern)) then
			numMatchingRecords = numMatchingRecords + 1
			if numMatchingRecords == math.abs(occurrence) then
				local args = mw.clone(args)
				args.data = data
				args.output_row = i
				return p._cell(args)
			end
		end
	end
end

--- Returns the value of the cell(s) in the given output column(s) of the row
--- matching the search key and column.
--- Reminiscent of LOOKUP() macros in popular spreadsheet applications, except
--- that the search key must match exactly. (On the other hand, this means the
--- table does not need to be sorted.)
--- Usage: {{#invoke: Tabular data | lookup | Table name | search_value = Value to find in column | search_pattern = Pattern to find in column | search_column = Name of column to search in | occurrence = 1-based index of the matching row to output | output_column = Name of column to output | output_column2 = Name of another column to output | … | output_format = String format to output the values in }}
function p.lookup(frame)
	return p._lookup(frame.args)
end

function p._wikitable(args)
	local pageName = args[1]
	local data = mw.ext.data.get(pageName)
	
	local datatypes = {}
	
	local htmlTable = mw.html.create("table")
		:addClass("wikitable sortable")
	htmlTable
		:tag("caption")
		:wikitext(navbar.navbar({
			template = ":c:Data:" .. pageName,
			mini = "y",
			style = "float: right;",
			"view", "edit",
		}))
		:wikitext(data.description)
	
	local headerRow = htmlTable
		:tag("tr")
	for i, field in ipairs(data.schema.fields) do
		headerRow
			:tag("th")
			:attr("scope", "col")
			:attr("data-sort-type", datatypes[j] == "text" and "string" or datatypes[j])
			:wikitext(field.title)
		datatypes[i] = field.type
	end
	
	for i, record in ipairs(data.data) do
		local row = htmlTable:tag("tr")
		for j = 1, #data.schema.fields do
			local cell = row:tag("td")
			if record[j] then
				local formattedData = record[j]
				if datatypes[j] == "number" then
					formattedData = lang:formatNum(formattedData)
					cell:attr("align", "right")
				elseif datatypes[j] == "boolean" then
					cell
						:addClass(record[j] and "table-yes" or "table-no")
						:css({
							background = record[j] and bgColors["true"] or bgColors["false"],
							color = record[j] and colors["true"] or colors["false"],
							["vertical-align"] = "middle",
							["text-align"] = "center",
						})
						:wikitext(record[j] and messages["true"] or messages["false"])
				end
				cell:wikitext(formattedData)
			else
				cell
					:addClass("mw-tabular-value-null")
					:addClass("table-na")
					:css({
						background = bgColors.null,
						color = colors.null,
						["vertical-align"] = "middle",
						["text-align"] = "center",
					})
					:wikitext(messages.null)
			end
		end
	end
	
	local footer = htmlTable
		:tag("tr")
		:tag("td")
		:addClass("sortbottom")
		:attr("colspan", #data.schema.fields)
	footer:wikitext(data.sources)
	footer:tag("br")
	
	local licenseText = mw.message.new("Jsonconfig-license",
		mw.ustring.format("[%s %s]", data.license.url, data.license.text))
	footer
		:tag("i")
		:wikitext(tostring(licenseText))
	
	return htmlTable
end

--- Returns a tabular data page as a wikitext table.
--- Usage: {{#invoke:Tabular data | wikitable | Table name }}
function p.wikitable(frame)
	return p._wikitable(frame.args)
end

return p

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.