No edit summary Tag: Reverted |
No edit summary Tag: Reverted |
||
Line 14: | Line 14: | ||
return tostring( self:renderInfobox() ) |
return tostring( self:renderInfobox() ) |
||
end |
end |
||
--- Wrapper function for Module:i18n.translate |
--- Wrapper function for Module:i18n.translate |
||
Line 23: | Line 22: | ||
return i18n:translate( key ) |
return i18n:translate( key ) |
||
end |
end |
||
--- Helper function to restore underscore from space |
--- Helper function to restore underscore from space |
||
Line 34: | Line 32: | ||
--- Helper function to format string to number with separators |
--- Helper function to format string to number with separators |
||
--- It is usually |
--- It is usually used to re-format raw numbers from SMW into a more readable format |
||
local function formatNumber( s ) |
local function formatNumber( s ) |
||
local lang = mw.getContentLanguage() |
local lang = mw.getContentLanguage() |
||
Line 52: | Line 50: | ||
end |
end |
||
--- Helper function to generate <details> and <summary> tags |
|||
--- |
|||
--- @param data table {details = {class, content, open}, summary = {class, content}} |
|||
--- @return string HTML of the <details> component |
|||
local function getDetailsHTML( data ) |
local function getDetailsHTML( data ) |
||
-- Check if data is provided and valid |
|||
if not data or not data.details or not data.summary then |
|||
return '' |
|||
end |
|||
-- Create the <summary> tag |
-- Create the <summary> tag |
||
local summary = mw.html.create( 'summary' ) |
local summary = mw.html.create( 'summary' ) |
||
:addClass( data.summary.class ) |
:addClass( data.summary.class or '' ) -- Default to empty if no class |
||
:wikitext( data.summary.content ) |
:wikitext( data.summary.content or '' ) -- Default to empty if no content |
||
-- Create the <details> tag |
-- Create the <details> tag |
||
local details = mw.html.create( 'details' ) |
local details = mw.html.create( 'details' ) |
||
:addClass( data.details.class ) |
:addClass( data.details.class or '' ) -- Default to empty if no class |
||
:node( summary ) -- Add the summary as a child |
:node( summary ) -- Add the summary as a child |
||
:wikitext( data.details.content ) -- |
:wikitext( data.details.content or '' ) -- Default to empty if no content |
||
-- Add the 'open' attribute |
-- Add the 'open' attribute if specified |
||
if data.details.open then |
if data.details.open then |
||
details:attr( 'open', nil ) |
details:attr( 'open', nil ) -- Adds the attribute without a value |
||
end |
end |
||
Line 72: | Line 79: | ||
end |
end |
||
--- Example method: Render a full infobox |
|||
--- Put table values into a comma-separated list |
|||
--- |
|||
--- @param data table |
|||
--- @return string |
|||
function methodtable.tableToCommaList( data ) |
|||
if type( data ) == 'table' then |
|||
return table.concat( data, ', ' ) |
|||
else |
|||
return data |
|||
end |
|||
end |
|||
--- Show range if value1 and value2 are different |
|||
--- |
|||
--- @param s1 string|nil |
|||
--- @param s2 string|nil |
|||
--- @return string|nil |
|||
function methodtable.formatRange( s1, s2, formatNum ) |
|||
if s1 == nil and s2 == nil then |
|||
return |
|||
end |
|||
formatNum = formatNum or false |
|||
if formatNum then |
|||
if s1 then |
|||
s1 = formatNumber( s1 ) |
|||
end |
|||
if s2 then |
|||
s2 = formatNumber( s2 ) |
|||
end |
|||
end |
|||
if s1 and s2 and s1 ~= s2 then |
|||
return s1 .. ' – ' .. s2 |
|||
end |
|||
return s1 or s2 |
|||
end |
|||
--- Append unit to the value if exists |
|||
--- |
|||
--- @param s string |
|||
--- @param unit string |
|||
--- @return string|nil |
|||
function methodtable.addUnitIfExists( s, unit ) |
|||
if s == nil then |
|||
return |
|||
end |
|||
return s .. ' ' .. unit |
|||
end |
|||
--- Shortcut to return the HTML of the infobox message component as string |
|||
--- |
|||
--- @param data table {title, desc) |
|||
--- @return string html |
|||
function methodtable.renderMessage( self, data, noInsert ) |
|||
checkType( 'Module:InfoboxNeue.renderMessage', 1, self, 'table' ) |
|||
checkType( 'Module:InfoboxNeue.renderMessage', 2, data, 'table' ) |
|||
checkType( 'Module:InfoboxNeue.renderMessage', 3, noInsert, 'boolean', true ) |
|||
noInsert = noInsert or false |
|||
local item = self:renderSection( { content = self:renderItem( { data = data.title, desc = data.desc } ) }, noInsert ) |
|||
if not noInsert then |
|||
table.insert( self.entries, item ) |
|||
end |
|||
return item |
|||
end |
|||
--- Return the HTML of the infobox image component as string |
|||
--- |
|||
--- @param filename string |
|||
--- @return string html |
|||
function methodtable.renderImage( self, filename ) |
|||
checkType( 'Module:InfoboxNeue.renderImage', 1, self, 'table' ) |
|||
local hasPlaceholderImage = false |
|||
if type( filename ) ~= 'string' and self.config.displayPlaceholder == true then |
|||
hasPlaceholderImage = true |
|||
filename = self.config.placeholderImage |
|||
-- Add tracking category for infoboxes using placeholder image |
|||
table.insert( self.categories, |
|||
string.format( '[[Category:%s]]', t( 'category_infobox_using_placeholder_image' ) ) |
|||
) |
|||
end |
|||
if type( filename ) ~= 'string' then |
|||
return '' |
|||
end |
|||
local parts = mw.text.split( filename, ':', true ) |
|||
if #parts > 1 then |
|||
table.remove( parts, 1 ) |
|||
filename = table.concat( parts, ':' ) |
|||
end |
|||
local html = mw.html.create( 'div' ) |
|||
:addClass( 'infobox__image' ) |
|||
:wikitext( string.format( '[[File:%s|400px]]', filename ) ) |
|||
if hasPlaceholderImage == true then |
|||
local icon = mw.html.create( 'span' ):addClass( 'citizen-ui-icon mw-ui-icon-wikimedia-upload' ) |
|||
-- TODO: Point the Upload link to a specific file name |
|||
html:tag( 'div' ):addClass( 'infobox__image-upload' ) |
|||
:wikitext( string.format( '[[%s|%s]]', 'Special:UploadWizard', |
|||
tostring( icon ) .. t( 'label_upload_image' ) ) ) |
|||
end |
|||
local item = tostring( html ) |
|||
table.insert( self.entries, item ) |
|||
return item |
|||
end |
|||
--- Return the HTML of the infobox indicator component as string |
|||
--- |
|||
--- @param data table {data, class, color, nopadding) |
|||
--- @return string html |
|||
function methodtable.renderIndicator( self, data ) |
|||
checkType( 'Module:InfoboxNeue.renderIndicator', 1, self, 'table' ) |
|||
checkType( 'Module:InfoboxNeue.renderIndicator', 2, data, 'table' ) |
|||
if data == nil or data[ 'data' ] == nil or data[ 'data' ] == '' then return '' end |
|||
local html = mw.html.create( 'div' ):addClass( 'infobox__indicators' ) |
|||
local htmlClasses = { |
|||
'infobox__indicator' |
|||
} |
|||
if data[ 'class' ] then |
|||
table.insert( htmlClasses, data[ 'class' ] ) |
|||
end |
|||
if data[ 'color' ] then |
|||
table.insert( htmlClasses, 'infobox__indicator--' .. data[ 'color' ] ) |
|||
end |
|||
if data[ 'nopadding' ] == true then |
|||
table.insert( htmlClasses, 'infobox__indicator--nopadding' ) |
|||
end |
|||
html:wikitext( |
|||
self:renderItem( |
|||
{ |
|||
[ 'data' ] = data[ 'data' ], |
|||
[ 'class' ] = table.concat( htmlClasses, ' ' ), |
|||
row = true, |
|||
spacebetween = true |
|||
} |
|||
) |
|||
) |
|||
local item = tostring( html ) |
|||
table.insert( self.entries, item ) |
|||
return item |
|||
end |
|||
--- Return the HTML of the infobox header component as string |
|||
--- |
|||
--- @param data table {title, subtitle, badge) |
|||
--- @return string html |
|||
function methodtable.renderHeader( self, data ) |
|||
checkType( 'Module:InfoboxNeue.renderHeader', 1, self, 'table' ) |
|||
checkTypeMulti( 'Module:InfoboxNeue.renderHeader', 2, data, { 'table', 'string' } ) |
|||
if type( data ) == 'string' then |
|||
data = { |
|||
title = data |
|||
} |
|||
end |
|||
if data == nil or data[ 'title' ] == nil then return '' end |
|||
local html = mw.html.create( 'div' ):addClass( 'infobox__header' ) |
|||
if data[ 'badge' ] then |
|||
html:tag( 'div' ) |
|||
:addClass( 'infobox__item infobox__badge' ) |
|||
:wikitext( data[ 'badge' ] ) |
|||
end |
|||
local titleItem = mw.html.create( 'div' ):addClass( 'infobox__item' ) |
|||
titleItem:tag( 'div' ) |
|||
:addClass( 'infobox__title' ) |
|||
:wikitext( data[ 'title' ] ) |
|||
if data[ 'subtitle' ] then |
|||
titleItem:tag( 'div' ) |
|||
-- Subtitle is always data |
|||
:addClass( 'infobox__subtitle infobox__data' ) |
|||
:wikitext( data[ 'subtitle' ] ) |
|||
end |
|||
html:node( titleItem ) |
|||
local item = tostring( html ) |
|||
table.insert( self.entries, item ) |
|||
return item |
|||
end |
|||
--- Wrap the HTML into an infobox section |
|||
--- |
|||
--- @param data table {title, subtitle, content, border, col, class} |
|||
--- @param noInsert boolean whether to insert this section into the internal table table |
|||
--- @return string html |
|||
function methodtable.renderSection( self, data, noInsert ) |
|||
checkType( 'Module:InfoboxNeue.renderSection', 1, self, 'table' ) |
|||
checkType( 'Module:InfoboxNeue.renderSection', 2, data, 'table' ) |
|||
checkType( 'Module:InfoboxNeue.renderSection', 3, noInsert, 'boolean', true ) |
|||
noInsert = noInsert or false |
|||
if type( data.content ) == 'table' then |
|||
data.content = table.concat( data.content ) |
|||
end |
|||
if data == nil or data[ 'content' ] == nil or data[ 'content' ] == '' then return '' end |
|||
local html = mw.html.create( 'div' ):addClass( 'infobox__section' ) |
|||
if data[ 'title' ] then |
|||
local header = html:tag( 'div' ):addClass( 'infobox__sectionHeader' ) |
|||
header:tag( 'div' ) |
|||
:addClass( 'infobox__sectionTitle' ) |
|||
:wikitext( data[ 'title' ] ) |
|||
if data[ 'subtitle' ] then |
|||
header:tag( 'div' ) |
|||
:addClass( 'infobox__sectionSubtitle' ) |
|||
:wikitext( data[ 'subtitle' ] ) |
|||
end |
|||
end |
|||
local content = html:tag( 'div' ) |
|||
content:addClass( 'infobox__sectionContent' ) |
|||
:wikitext( data[ 'content' ] ) |
|||
if data[ 'border' ] == false then html:addClass( 'infobox__section--noborder' ) end |
|||
if data[ 'col' ] then content:addClass( 'infobox__grid--cols-' .. data[ 'col' ] ) end |
|||
if data[ 'class' ] then html:addClass( data[ 'class' ] ) end |
|||
local item = tostring( html ) |
|||
if not noInsert then |
|||
table.insert( self.entries, item ) |
|||
end |
|||
return item |
|||
end |
|||
--- Return the HTML of the infobox link button component as string |
|||
--- |
|||
--- @param data table {label, link, page} |
|||
--- @return string html |
|||
function methodtable.renderLinkButton( self, data ) |
|||
checkType( 'Module:InfoboxNeue.renderLinkButton', 1, self, 'table' ) |
|||
checkType( 'Module:InfoboxNeue.renderLinkButton', 2, data, 'table' ) |
|||
if data == nil or data[ 'label' ] == nil or (data[ 'link' ] == nil and data[ 'page' ] == nil) then return '' end |
|||
--- Render multiple linkButton when link is a table |
|||
if type( data[ 'link' ] ) == 'table' then |
|||
local htmls = {} |
|||
for i, url in ipairs( data[ 'link' ] ) do |
|||
table.insert( htmls, |
|||
self:renderLinkButton( { |
|||
label = string.format( '%s %d', data[ 'label' ], i ), |
|||
link = url |
|||
} ) |
|||
) |
|||
end |
|||
return table.concat( htmls ) |
|||
end |
|||
local html = mw.html.create( 'div' ):addClass( 'infobox__linkButton' ) |
|||
if data[ 'link' ] then |
|||
html:wikitext( string.format( '[%s %s]', restoreUnderscore( data[ 'link' ] ), data[ 'label' ] ) ) |
|||
elseif data[ 'page' ] then |
|||
html:wikitext( string.format( '[[%s|%s]]', data[ 'page' ], data[ 'label' ] ) ) |
|||
end |
|||
return tostring( html ) |
|||
end |
|||
--- Return the HTML of the infobox footer component as string |
|||
--- |
|||
--- @param data table {content, button} |
|||
--- @return string html |
|||
function methodtable.renderFooter( self, data ) |
|||
checkType( 'Module:InfoboxNeue.renderFooter', 1, self, 'table' ) |
|||
checkType( 'Module:InfoboxNeue.renderFooter', 2, data, 'table' ) |
|||
if data == nil then return '' end |
|||
-- Checks if an input is of type 'table' or 'string' and if it is not empty |
|||
local function isNonEmpty( input ) |
|||
return (type( input ) == 'table' and next( input ) ~= nil) or (type( input ) == 'string' and #input > 0) |
|||
end |
|||
local hasContent = isNonEmpty( data[ 'content' ] ) |
|||
local hasButton = isNonEmpty( data[ 'button' ] ) and isNonEmpty( data[ 'button' ][ 'content' ] ) and |
|||
isNonEmpty( data[ 'button' ][ 'label' ] ) |
|||
if not hasContent and not hasButton then return '' end |
|||
local html = mw.html.create( 'div' ):addClass( 'infobox__footer' ) |
|||
if hasContent then |
|||
local content = data[ 'content' ] |
|||
if type( content ) == 'table' then content = table.concat( content ) end |
|||
html:addClass( 'infobox__footer--has-content' ) |
|||
html:tag( 'div' ) |
|||
:addClass( 'infobox__section' ) |
|||
:wikitext( content ) |
|||
end |
|||
if hasButton then |
|||
html:addClass( 'infobox__footer--has-button' ) |
|||
local buttonData = data[ 'button' ] |
|||
local button = html:tag( 'div' ):addClass( 'infobox__button' ) |
|||
local label = button:tag( 'div' ):addClass( 'infobox__buttonLabel' ) |
|||
if buttonData[ 'icon' ] ~= nil then |
|||
label:wikitext( string.format( '[[File:%s|16px|link=]]%s', buttonData[ 'icon' ], buttonData[ 'label' ] ) ) |
|||
else |
|||
label:wikitext( buttonData[ 'label' ] ) |
|||
end |
|||
if buttonData[ 'type' ] == 'link' then |
|||
button:tag( 'div' ) |
|||
:addClass( 'infobox__buttonLink' ) |
|||
:wikitext( buttonData[ 'content' ] ) |
|||
elseif buttonData[ 'type' ] == 'popup' then |
|||
button:tag( 'div' ) |
|||
:addClass( 'infobox__buttonCard' ) |
|||
:wikitext( buttonData[ 'content' ] ) |
|||
end |
|||
end |
|||
local item = tostring( html ) |
|||
table.insert( self.entries, item ) |
|||
return item |
|||
end |
|||
--- Return the HTML of the infobox footer button component as string |
|||
--- |
|||
--- @param data table {icon, label, type, content} |
|||
--- @return string html |
|||
function methodtable.renderFooterButton( self, data ) |
|||
checkType( 'Module:InfoboxNeue.renderFooterButton', 1, self, 'table' ) |
|||
checkType( 'Module:InfoboxNeue.renderFooterButton', 2, data, 'table' ) |
|||
if data == nil then return '' end |
|||
return self:renderFooter( { button = data } ) |
|||
end |
|||
--- Return the HTML of the infobox item component as string |
|||
--- |
|||
--- @param data table {label, data, desc, class, tooltip, icon, row, spacebetween, colspan) |
|||
--- @param content string|number|nil optional |
|||
--- @return string html |
|||
function methodtable.renderItem( self, data, content ) |
|||
checkType( 'Module:InfoboxNeue.renderItem', 1, self, 'table' ) |
|||
checkTypeMulti( 'Module:InfoboxNeue.renderItem', 2, data, { 'table', 'string' } ) |
|||
checkTypeMulti( 'Module:InfoboxNeue.renderItem', 3, content, { 'string', 'number', 'nil' } ) |
|||
-- The arguments are not passed as a table |
|||
-- Allows to call this as box:renderItem( 'Label', 'Data' ) |
|||
if content ~= nil then |
|||
data = { |
|||
label = data, |
|||
data = content |
|||
} |
|||
end |
|||
if data == nil or data[ 'data' ] == nil or data[ 'data' ] == '' then return '' end |
|||
if self.config.removeEmpty == true and data[ 'data' ] == self.config.emptyString then |
|||
return '' |
|||
end |
|||
local html = mw.html.create( 'div' ):addClass( 'infobox__item' ) |
|||
if data[ 'class' ] then html:addClass( data[ 'class' ] ) end |
|||
if data[ 'tooltip' ] then html:attr( 'title', data[ 'tooltip' ] ) end |
|||
if data[ 'row' ] == true then html:addClass( 'infobox__grid--row' ) end |
|||
if data[ 'spacebetween' ] == true then html:addClass( 'infobox__grid--space-between' ) end |
|||
if data[ 'colspan' ] then html:addClass( 'infobox__grid--col-span-' .. data[ 'colspan' ] ) end |
|||
local textWrapper = html |
|||
if data[ 'link' ] then |
|||
html:addClass( 'infobox__itemButton' ) |
|||
html:tag( 'div' ) |
|||
:addClass( 'infobox__itemButtonLink' ) |
|||
:wikitext( string.format( '[%s]', data[ 'link' ] ) ) |
|||
elseif data[ 'page' ] then |
|||
html:addClass( 'infobox__itemButton' ) |
|||
html:tag( 'div' ) |
|||
:addClass( 'infobox__itemButtonLink' ) |
|||
:wikitext( string.format( '[[%s]]', data[ 'link' ] ) ) |
|||
end |
|||
if data[ 'icon' ] then |
|||
html:addClass( 'infobox__item--hasIcon' ) |
|||
html:tag( 'div' ) |
|||
:addClass( 'infobox__icon' ) |
|||
:wikitext( string.format( '[[File:%s|16px|link=]]', data[ 'icon' ] ) ) |
|||
-- Create wrapper for text to align with icon |
|||
textWrapper = html:tag( 'div' ):addClass( 'infobox__text' ) |
|||
end |
|||
local dataOrder = { 'label', 'data', 'desc' } |
|||
for _, key in ipairs( dataOrder ) do |
|||
if data[ key ] then |
|||
if type( data[ key ] ) == 'table' then |
|||
data[ key ] = table.concat( data[ key ], ', ' ) |
|||
end |
|||
textWrapper:tag( 'div' ) |
|||
:addClass( 'infobox__' .. key ) |
|||
:wikitext( data[ key ] ) |
|||
end |
|||
end |
|||
-- Add arrow indicator as affordnance |
|||
if data[ 'link' ] or data[ 'page' ] then |
|||
html:tag( 'div' ):addClass( 'infobox__itemButtonArrow citizen-ui-icon mw-ui-icon-wikimedia-collapse' ) |
|||
end |
|||
return tostring( html ) |
|||
end |
|||
--- Wrap the infobox HTML |
|||
--- |
--- |
||
--- @param |
--- @param self table |
||
--- @param |
--- @param innerHtml string Inner HTML of the infobox |
||
--- @ |
--- @param snippetText string Optional snippet for mobile view |
||
--- @return string Full infobox HTML |
|||
function methodtable.renderInfobox( self, innerHtml, snippetText ) |
function methodtable.renderInfobox( self, innerHtml, snippetText ) |
||
checkType( 'Module:InfoboxNeue.renderInfobox', 1, self, 'table' ) |
checkType( 'Module:InfoboxNeue.renderInfobox', 1, self, 'table' ) |
||
Line 552: | Line 106: | ||
local html = mw.html.create() |
local html = mw.html.create() |
||
html:tag( 'div' ) |
html:tag( 'div' ) |
||
:addClass( 'citizen-ui-icon mw-ui-icon-wikimedia-collapse' ) |
:addClass( 'citizen-ui-icon mw-ui-icon-wikimedia-collapse' ) |
||
Line 567: | Line 121: | ||
end |
end |
||
local frame = |
local frame = mw.getCurrentFrame() |
||
local output = getDetailsHTML( { |
local output = getDetailsHTML( { |
||
details = { |
details = { |
||
class = 'infobox floatright', |
class = 'infobox floatright', |
||
content = renderContent() |
content = renderContent(), |
||
open = true |
|||
}, |
}, |
||
summary = { |
summary = { |
||
Line 577: | Line 132: | ||
content = renderSnippet() |
content = renderSnippet() |
||
} |
} |
||
} |
} ) |
||
return frame:extensionTag { |
return output .. frame:extensionTag { |
||
name = 'templatestyles', args = { src = 'Module:InfoboxNeue/styles.css' } |
name = 'templatestyles', args = { src = 'Module:InfoboxNeue/styles.css' } |
||
} |
} .. table.concat( self.categories ) |
||
end |
|||
--- Just an accessor for the class method |
|||
function methodtable.showDescIfDiff( s1, s2 ) |
|||
return InfoboxNeue.showDescIfDiff( s1, s2 ) |
|||
end |
|||
--- Format text to show comparison as desc text if two strings are different |
|||
--- |
|||
--- @param s1 string|nil base |
|||
--- @param s2 string|nil comparsion |
|||
--- @return string|nil html |
|||
function InfoboxNeue.showDescIfDiff( s1, s2 ) |
|||
if s1 == nil or s2 == nil or s1 == s2 then return s1 end |
|||
return string.format( '%s <span class="infobox__desc">(%s)</span>', s1, s2 ) |
|||
end |
end |
||
--- New Instance |
--- New Instance |
||
--- |
--- |
||
--- @ |
--- @param config table Optional configuration |
||
--- @return table InfoboxNeue instance |
|||
function InfoboxNeue.new( self, config ) |
function InfoboxNeue.new( self, config ) |
||
local baseConfig = { |
local baseConfig = { |
||
Line 627: | Line 168: | ||
return instance |
return instance |
||
end |
|||
--- Create an Infobox from args |
|||
--- |
|||
--- @param frame table |
|||
--- @return string |
|||
function InfoboxNeue.fromArgs( frame ) |
|||
local instance = InfoboxNeue:new() |
|||
local args = require( 'Module:Arguments' ).getArgs( frame ) |
|||
local sections = { |
|||
{ content = {}, col = args[ 'col' ] or 2 } |
|||
} |
|||
local sectionMap = { default = 1 } |
|||
local currentSection |
|||
if args[ 'image' ] then |
|||
instance:renderImage( args[ 'image' ] ) |
|||
end |
|||
if args[ 'indicator' ] then |
|||
instance:renderIndicator( { |
|||
data = args[ 'indicator' ], |
|||
class = args[ 'indicatorClass' ] |
|||
} ) |
|||
end |
|||
if args[ 'title' ] then |
|||
instance:renderHeader( { |
|||
title = args[ 'title' ], |
|||
subtitle = args[ 'subtitle' ], |
|||
} ) |
|||
end |
|||
for i = 1, 50, 1 do |
|||
if args[ 'section' .. i ] then |
|||
currentSection = args[ 'section' .. i ] |
|||
table.insert( sections, { |
|||
title = currentSection, |
|||
subtitle = args[ 'section-subtitle' .. i ], |
|||
col = args[ 'section-col' .. i ] or args[ 'col' ] or 2, |
|||
content = {} |
|||
} ) |
|||
sectionMap[ currentSection ] = #sections |
|||
end |
|||
if args[ 'label' .. i ] and args[ 'content' .. i ] then |
|||
table.insert( sections[ sectionMap[ (currentSection or 'default') ] ].content, |
|||
instance:renderItem( args[ 'label' .. i ], args[ 'content' .. i ] ) ) |
|||
end |
|||
end |
|||
for _, section in ipairs( sections ) do |
|||
instance:renderSection( { |
|||
title = section.title, |
|||
subtitle = section.subtitle, |
|||
col = section.col, |
|||
content = section.content, |
|||
} ) |
|||
end |
|||
return instance:renderInfobox( nil, args[ 'snippet' ] ) |
|||
end |
end |
||
Revision as of 19:21, 19 November 2024
{{Documentation}}
/{{No documentation}}
to the calling template's or parent's module documentation.Function list |
---|
L 21 — t L 29 — restoreUnderscore L 35 — formatNumber L 56 — getDetailsHTML L 87 — methodtable.renderInfobox L 97 — renderContent L 104 — renderSnippet L 145 — InfoboxNeue.new |
|type = website |description = Module:InfoboxNeue is a template page used on the TCG Card Shop Simulator Wiki. Templates are pages that are embedded (transcluded) into other pages to allow for the repetition of information. |site_name = TCG Card Shop Simulator Wiki |locale = en }}
This module is used by Lua modules to build infobox.
Components
Lua error in Module:InfoboxNeue/example at line 7: attempt to call method 'renderImage' (a nil value).
Image
infobox:renderImage( 'TCG Cards.jpg' )
Indicator
Parameter | Description | Type | Status |
---|---|---|---|
data |
Data of the indicator | string | required |
desc |
Description of the indicator | string | optional |
class |
HTML classes to be added to the indicator | string | optional |
infobox:renderIndicator( { data = 'Indicator' } )
Header
Parameter | Description | Type | Status |
---|---|---|---|
title |
Title of the infobox | string | required |
subtitle |
Subtitle of the infobox | string | optional |
infobox:renderHeader( { title = 'Title', subtitle = 'Subtitle' } )
Message
This is a shortcut way to create a message wrapped in a section.
Parameter | Description | Type | Status |
---|---|---|---|
title |
Title of the message | string | required |
desc |
Description of the message | string | optional |
infobox:renderMessage( { title = 'Message title', desc = 'Message description' } )
Item
Parameter | Description | Type | Status |
---|---|---|---|
data |
Data of the item | string | required |
label |
Label of the item | string | optional |
desc |
Description of the item | string | optional |
row |
Whether to display the item in a row | boolean | optional |
spacebetween |
Whether to put space between elements in the item | boolean | optional |
colspan |
Number of columns that the item spans | int | optional |
infobox:renderItem( { label = 'Item label', data = 'Item data' } )
Section
This is used to wrap items into a section.
Parameter | Description | Type | Status |
---|---|---|---|
content |
Content of the section | string | required |
title |
Title of the section | string | optional |
subtitle |
Subtitle of the section | string | optional |
col |
Number of columns in the section | int | optional |
class |
HTML classes to be added to the section | string | optional |
infobox:renderSection( { title = 'Section title', content = table.concat( sectionTable ), col = 3 } )
Layout
Row
Lua error in Module:InfoboxNeue/example at line 50: attempt to call method 'renderItem' (a nil value).
-- Create items sectionTable = { infobox:renderItem( { label = 'Bacon', data = 'Good', row = true, spacebetween = true } ), infobox:renderItem( { label = 'Pancetta', data = 'Great', row = true, spacebetween = true } ), infobox:renderItem( { label = 'Prosciutto', data = 'Wonderful', row = true, spacebetween = true } ) } -- Create section with items infobox:renderSection( { title = 'Row layout', subtitle = 'This is an example of the row layout.', content = table.concat( sectionTable ) } )
List
Lua error in Module:InfoboxNeue/example at line 83: attempt to call method 'renderItem' (a nil value).
-- Create items sectionTable = { infobox:renderItem( { data = 'Bacon is good', desc = 'Bacon ipsum dolor amet burgdoggen boudin spare ribs pork pork chop drumstick beef. Jowl turkey pork, kevin shankle shank shoulder. ', } ), infobox:renderItem( { data = 'Pancetta is great', desc = 'Kevin pig fatback, alcatra pancetta sirloin venison tri-tip shankle kielbasa meatloaf spare ribs beef. Corned beef salami kielbasa tenderloin swine spare ribs andouille.', } ), infobox:renderItem( { data = 'Prosciutto is wonderful', desc = 'Venison chicken meatloaf, ground round swine short ribs shankle short loin tenderloin jerky capicola. Prosciutto venison sirloin beef brisket pancetta.', } ) } -- Create section with items infobox:renderSection( { title = 'List layout', subtitle = 'This is an example of the list layout.', content = table.concat( sectionTable ) } )
Grid
Lua error in Module:InfoboxNeue/example at line 110: attempt to call method 'renderItem' (a nil value).
-- Create items sectionTable = { infobox:renderItem( { label = 'Bacon', data = 'Good' } ), infobox:renderItem( { label = 'Pancetta', data = 'Great' } ), infobox:renderItem( { label = 'Prosciutto', data = 'Wonderful' } ), infobox:renderItem( { label = 'Capicola', data = 'Delightful' } ) } -- Create section with items infobox:renderSection( { title = '2 col grid layout', subtitle = 'This is an example of the two column grid layout.', content = table.concat( sectionTable ), col = 2 } ) infobox:renderSection( { title = '3 col grid layout', subtitle = 'This is an example of the three column grid layout.', content = table.concat( sectionTable ), col = 3 } ) infobox:renderSection( { title = '4 col grid layout', subtitle = 'This is an example of the four column grid layout.', content = table.concat( sectionTable ), col = 4 } )
local InfoboxNeue = {}
local metatable = {}
local methodtable = {}
local libraryUtil = require( 'libraryUtil' )
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
local i18n = require( 'Module:i18n' ):new()
metatable.__index = methodtable
metatable.__tostring = function ( self )
return tostring( self:renderInfobox() )
end
--- Wrapper function for Module:i18n.translate
---
--- @param key string The translation key
--- @return string If the key was not found, the key is returned
local function t( key )
return i18n:translate( key )
end
--- Helper function to restore underscore from space
--- so that it does not screw up the external link wikitext syntax
--- For some reason SMW property converts underscore into space
--- mw.uri.encode can't be used on full URL
local function restoreUnderscore( s )
return s:gsub( ' ', '%%5F' )
end
--- Helper function to format string to number with separators
--- It is usually used to re-format raw numbers from SMW into a more readable format
local function formatNumber( s )
local lang = mw.getContentLanguage()
if s == nil then
return
end
if type( s ) ~= 'number' then
s = tonumber( s )
end
if type( s ) == 'number' then
return lang:formatNum( s )
end
return s
end
--- Helper function to generate <details> and <summary> tags
---
--- @param data table {details = {class, content, open}, summary = {class, content}}
--- @return string HTML of the <details> component
local function getDetailsHTML( data )
-- Check if data is provided and valid
if not data or not data.details or not data.summary then
return ''
end
-- Create the <summary> tag
local summary = mw.html.create( 'summary' )
:addClass( data.summary.class or '' ) -- Default to empty if no class
:wikitext( data.summary.content or '' ) -- Default to empty if no content
-- Create the <details> tag
local details = mw.html.create( 'details' )
:addClass( data.details.class or '' ) -- Default to empty if no class
:node( summary ) -- Add the summary as a child
:wikitext( data.details.content or '' ) -- Default to empty if no content
-- Add the 'open' attribute if specified
if data.details.open then
details:attr( 'open', nil ) -- Adds the attribute without a value
end
return tostring( details )
end
--- Example method: Render a full infobox
---
--- @param self table
--- @param innerHtml string Inner HTML of the infobox
--- @param snippetText string Optional snippet for mobile view
--- @return string Full infobox HTML
function methodtable.renderInfobox( self, innerHtml, snippetText )
checkType( 'Module:InfoboxNeue.renderInfobox', 1, self, 'table' )
checkTypeMulti( 'Module:InfoboxNeue.renderInfobox', 2, innerHtml, { 'table', 'string', 'nil' } )
checkType( 'Module:InfoboxNeue.renderInfobox', 3, snippetText, 'string', true )
innerHtml = innerHtml or self.entries
if type( innerHtml ) == 'table' then
innerHtml = table.concat( self.entries )
end
local function renderContent()
local html = mw.html.create( 'div' )
:addClass( 'infobox__content' )
:wikitext( innerHtml )
return tostring( html )
end
local function renderSnippet()
if snippetText == nil then snippetText = mw.title.getCurrentTitle().text end
local html = mw.html.create()
html:tag( 'div' )
:addClass( 'citizen-ui-icon mw-ui-icon-wikimedia-collapse' )
:done()
:tag( 'div' )
:addClass( 'infobox__data' )
:wikitext( string.format( '%s:', t( 'label_quick_facts' ) ) )
:done()
:tag( 'div' )
:addClass( 'infobox__desc' )
:wikitext( snippetText )
return tostring( html )
end
local frame = mw.getCurrentFrame()
local output = getDetailsHTML( {
details = {
class = 'infobox floatright',
content = renderContent(),
open = true
},
summary = {
class = 'infobox__snippet',
content = renderSnippet()
}
} )
return output .. frame:extensionTag {
name = 'templatestyles', args = { src = 'Module:InfoboxNeue/styles.css' }
} .. table.concat( self.categories )
end
--- New Instance
---
--- @param config table Optional configuration
--- @return table InfoboxNeue instance
function InfoboxNeue.new( self, config )
local baseConfig = {
-- Flag to discard empty rows
removeEmpty = false,
-- Optional string which is valued as empty
emptyString = nil,
-- Display a placeholder image if addImage does not find an image
displayPlaceholder = true,
-- Placeholder Image
placeholderImage = 'Platzhalter.webp',
}
for k, v in pairs( config or {} ) do
baseConfig[ k ] = v
end
local instance = {
categories = {},
config = baseConfig,
entries = {}
}
setmetatable( instance, metatable )
return instance
end
return InfoboxNeue