Module:Navbox: Difference between revisions
rewrite with htmlbuilder
m>Toohool (fix for lists in image and imageleft) |
m>Toohool (rewrite with htmlbuilder) |
||
Line 2: | Line 2: | ||
-- This module will implement {{Navbox}} | -- This module will implement {{Navbox}} | ||
-- | -- | ||
local p = {} | local p = {} | ||
local HtmlBuilder = require('Module:Sandbox/Toohool/HtmlBuilder') | |||
local | local args | ||
local tableRowAdded = false | |||
local border | local border | ||
local listnums = {} | local listnums = {} | ||
function trim(s) | function trim(s) | ||
return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1")) | return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1")) | ||
end | |||
function addTableRow(tbl) | |||
-- If any other rows have already been added, then we add a 2px gutter row. | |||
if tableRowAdded then | |||
tbl | |||
.tag('tr') | |||
.css('height', '2px') | |||
.tag('td') | |||
end | |||
tableRowAdded = true | |||
return tbl.tag('tr') | |||
end | end | ||
function renderTitleRow( | |||
-- | |||
-- Title row | |||
-- | |||
function renderTitleRow(tbl) | |||
if not args.title then return end | if not args.title then return end | ||
local titleRow = addTableRow(tbl) | |||
if args.titlegroup then | |||
titleRow | |||
.tag('th') | |||
.attr('scope', 'row') | |||
.addClass('navbox-group') | |||
.addClass(args.titlegroupclass) | |||
.cssText(args.basestyle) | |||
.cssText(args.groupstyle) | |||
.cssText(args.titlegroupstyle) | |||
.wikitext(args.titlegroup) | |||
end | |||
local titleCell = titleRow.tag('th').attr('scope', 'col') | |||
if args.titlegroup then | if args.titlegroup then | ||
titleCell | |||
.css('border-left', '2px solid #fdfdfd') | |||
.css('width', '100%') | |||
end | end | ||
local | |||
if args.imageleft then | local titleColspan = 2 | ||
if args.image then | if args.imageleft then titleColspan = titleColspan + 1 end | ||
if args.titlegroup then | if args.image then titleColspan = titleColspan + 1 end | ||
if args.titlegroup then titleColspan = titleColspan - 1 end | |||
titleCell | |||
.cssText(args.basestyle) | |||
.cssText(args.titlestyle) | |||
.addClass('navbox-title') | |||
.attr('colspan', titleColspan) | |||
renderNavBar(titleCell) | |||
titleCell | |||
.tag('div') | |||
.addClass(args.titleclass) | |||
.css('font-size', '110%') | |||
.newline() | |||
.wikitext(args.title) | |||
end | |||
function renderNavBar(titleCell) | |||
local addStateLinkPlaceholder = false | |||
if args.navbar == 'plain' or args.navbar == 'off' or (not args.name and (border == 'subgroup' or border == 'child' or border == 'none')) then | if args.navbar == 'plain' or args.navbar == 'off' or (not args.name and (border == 'subgroup' or border == 'child' or border == 'none')) then | ||
if args.navbar == 'off' then | if args.navbar == 'off' then | ||
addStateLinkPlaceholder = (args.state == 'plain') | |||
else | else | ||
addStateLinkPlaceholder = (args.state ~= 'plain') | |||
end | end | ||
else | else | ||
if args.name then | if args.name then | ||
titleCell.wikitext(mw.getCurrentFrame():expandTemplate{ title = 'navbar', args = { | |||
args.name, | args.name, | ||
mini = 1, | mini = 1, | ||
Line 53: | Line 96: | ||
}}) | }}) | ||
else | else | ||
titleCell | |||
.tag('span') | |||
.addClass('error') | |||
.css('float', 'left') | |||
.css('white-space', 'nowrap') | |||
.wikitext('Error: No name provided') | |||
addStateLinkPlaceholder = (args.state == 'plain') | |||
end | end | ||
end | end | ||
if addStateLinkPlaceholder then | |||
titleCell | |||
.tag('span') | |||
.css('float', 'right') | |||
.css('width', '6em') | |||
.wikitext(' ') | |||
end | |||
end | |||
function renderAboveRow( | -- | ||
-- Above/Below rows | |||
-- | |||
function renderAboveRow(tbl) | |||
if not args.above then return end | if not args.above then return end | ||
addTableRow(tbl) | |||
.tag('td') | |||
.addClass('navbox-abovebelow') | |||
.addClass(args.aboveclass) | |||
.cssText(args.basestyle) | |||
.cssText(args.abovestyle) | |||
.attr('colspan', getAboveBelowColspan()) | |||
.tag('div') | |||
.newline() | |||
.wikitext(args.above) | |||
end | end | ||
function renderBelowRow( | |||
function renderBelowRow(tbl) | |||
if not args.below then return end | |||
addTableRow(tbl) | |||
.tag('td') | |||
.addClass('navbox-abovebelow') | |||
.addClass(args.belowclass) | |||
.cssText(args.basestyle) | |||
.cssText(args.belowstyle) | |||
.attr('colspan', getAboveBelowColspan()) | |||
.tag('div') | |||
.newline() | |||
.wikitext(args.below) | |||
end | end | ||
function getAboveBelowColspan( | |||
function getAboveBelowColspan() | |||
local ret = 2 | local ret = 2 | ||
if args.imageleft then ret = ret + 1 end | if args.imageleft then ret = ret + 1 end | ||
Line 83: | Line 155: | ||
return ret | return ret | ||
end | end | ||
function renderFirstListRow( | |||
-- | |||
-- List rows | |||
-- | |||
function renderFirstListRow(tbl) | |||
if not args.list1 then return end | if not args.list1 then return end | ||
local row = addTableRow(tbl) | |||
if args.imageleft then | if args.imageleft then | ||
row | |||
.tag('td') | |||
.addClass('navbox-image') | |||
.addClass(args.imageclass) | |||
.css('width', '0%') | |||
.css('padding', '0px 2px 0px 0px') | |||
.cssText(args.imageleftstyle) | |||
.attr('rowspan', 2 * #listnums - 1) | |||
.tag('div') | |||
.newline() | |||
.wikitext(args.imageleft) | |||
end | end | ||
if args.group1 then | |||
local groupCell = row.tag('th') | |||
groupCell | |||
.attr('scope', 'row') | |||
.addClass('navbox-group') | |||
.addClass(args.groupclass) | |||
.cssText(args.basestyle) | |||
if args.groupwidth then | |||
groupCell.css('width', args.groupwidth) | |||
end | |||
groupCell | |||
.cssText(args.groupstyle) | |||
.cssText(args.group1style) | |||
.wikitext(args.group1) | |||
end | |||
local listCell = row.tag('td') | |||
if args.group1 then | if args.group1 then | ||
listCell | |||
.css('text-align', 'left') | |||
.css('border-left-width', '2px') | |||
.css('border-left-style', 'solid') | |||
else | else | ||
listCell.attr('colspan', 2) | |||
end | end | ||
if not args.groupwidth then | |||
if not args.groupwidth then | |||
listCell.css('width', '100%') | |||
end | end | ||
local evenOdd = args.evenodd or 'odd' | |||
if args.evenodd == 'swap' then evenOdd = 'even' end | |||
listCell | |||
.css('padding', '0px') | |||
.cssText(args.liststyle) | |||
.cssText(args.oddstyle) | |||
.cssText(args.list1style) | |||
.addClass('navbox-list') | |||
.addClass('navbox-' .. evenOdd) | |||
.addClass(args.listclass) | |||
.tag('div') | |||
.css('padding', args.list1padding or args.listpadding or '0em 0.25em') | |||
.newline() | |||
.wikitext(args.list1) | |||
if args.image then | if args.image then | ||
row | |||
.tag('td') | |||
.addClass('navbox-image') | |||
.addClass(args.imageclass) | |||
.css('width', '0%') | |||
.css('padding', '0px 0px 0px 2px') | |||
.cssText(args.imagestyle) | |||
.attr('rowspan', 2 * #listnums - 1) | |||
.tag('div') | |||
.newline() | |||
.wikitext(args.image) | |||
end | |||
end | |||
function renderNthListRow(tbl, listnum) | |||
local row = addTableRow(tbl) | |||
if args['group' .. listnum] then | |||
local groupCell = row.tag('th') | |||
groupCell | |||
.attr('scope', 'row') | |||
.addClass('navbox-group') | |||
.addClass(args.groupclass) | |||
.cssText(args.basestyle) | |||
if args.groupwidth then | |||
groupCell.css('width', args.groupwidth) | |||
end | |||
groupCell | |||
.cssText(args.groupstyle) | |||
.cssText(args['group' .. listnum .. 'style']) | |||
.wikitext(args['group' .. listnum]) | |||
end | end | ||
local listCell = row.tag('td') | |||
if args['group' .. listnum] then | if args['group' .. listnum] then | ||
listCell | |||
.css('text-align', 'left') | |||
.css('border-left-width', '2px') | |||
.css('border-left-style', 'solid') | |||
else | else | ||
listCell.attr('colspan', 2) | |||
end | |||
if not args.groupwidth then | |||
listCell.css('width', '100%') | |||
end | end | ||
local isOdd = (listnum % 2) == 1 | local isOdd = (listnum % 2) == 1 | ||
local rowstyle = args.evenstyle | local rowstyle = args.evenstyle | ||
if isOdd then rowstyle = args.oddstyle end | if isOdd then rowstyle = args.oddstyle end | ||
local evenOdd | |||
if args.evenodd == 'swap' then | |||
if isOdd then evenOdd = 'even' else evenOdd = 'odd' end | |||
else | |||
if isOdd then evenOdd = args.evenodd or 'odd' else evenOdd = args.evenodd or 'even' end | |||
end | |||
listCell | |||
.css('padding', '0px') | |||
.cssText(args.liststyle) | |||
.cssText(rowstyle) | |||
.cssText(args['list' .. listnum .. 'style']) | |||
.addClass('navbox-list') | |||
.addClass('navbox-' .. evenOdd) | |||
.addClass(args.listclass) | |||
.tag('div') | |||
.css('padding', args.listpadding or '0em 0.25em') | |||
.newline() | |||
.wikitext(args['list' .. listnum]) | |||
end | end | ||
function | |||
-- | |||
-- Main navbox tables | |||
-- | |||
function renderMainTable() | |||
local tbl = HtmlBuilder.create('table') | |||
.attr('cellspacing', 0) | |||
.addClass('nowraplinks') | |||
.addClass(args.bodyclass) | |||
if args.title and (args.state ~= 'plain' and args.state ~= 'off') then | if args.title and (args.state ~= 'plain' and args.state ~= 'off') then | ||
tbl | |||
.addClass('collapsible') | |||
.addClass(args.state or 'autocollapse') | |||
end | end | ||
tbl.css('border-spacing', 0) | |||
if border == 'subgroup' or border == 'child' or border == 'none' then | if border == 'subgroup' or border == 'child' or border == 'none' then | ||
tbl | |||
else | .addClass('navbox-subgroup') | ||
.cssText(args.bodyStyle) | |||
.cssText(args.style) | |||
else -- regular navobx - bodyStyle and style will be applied to the wrapper table | |||
tbl | |||
.addClass('navbox-inner') | |||
.css('background', 'transparent') | |||
.css('color', 'inherit') | |||
end | end | ||
tbl.cssText(args.innerstyle) | |||
renderTitleRow( | renderTitleRow(tbl) | ||
renderAboveRow( | renderAboveRow(tbl) | ||
renderFirstListRow( | renderFirstListRow(tbl) | ||
-- render lists 2 through N | -- render lists 2 through N | ||
for i, listnum in ipairs(listnums) do | for i, listnum in ipairs(listnums) do | ||
if listnum > 1 then | if listnum > 1 then | ||
renderNthListRow( | renderNthListRow(tbl, listnum) | ||
end | end | ||
end | end | ||
renderBelowRow(tbl) | |||
return tbl | |||
end | |||
function p._navbox(navboxArgs) | |||
args = navboxArgs | |||
for k, v in pairs(args) do | |||
local listnum = ('' .. k):match('^list(%d+)$') | |||
if listnum then table.insert(listnums, tonumber(listnum)) end | |||
end | |||
table.sort(listnums) | |||
border = trim(args.border or args[1] or '') | |||
-- render the main body of the navbox | |||
local tbl = renderMainTable() | |||
-- render the appropriate wrapper around the navbox, depending on the border param | |||
local res = HtmlBuilder.create() | |||
if border == 'subgroup' or border == 'child' then | if border == 'subgroup' or border == 'child' then | ||
res | |||
.tag('/div', {unclosed = true}) | |||
.done() | |||
.node(tbl) | |||
.tag('div', {unclosed = true}) | |||
elseif border ~= 'none' then | elseif border ~= 'none' then | ||
res | |||
.tag('table') | |||
.attr('cellspacing', 0) | |||
.addClass('navbox') | |||
.css('border-spacing', 0) | |||
.cssText(args.bodystyle) | |||
.cssText(args.style) | |||
.tag('tr') | |||
.tag('td') | |||
.css('padding', '2px') | |||
.node(tbl) | |||
end | end | ||
-- TODO: add tracking categories | -- TODO: add tracking categories | ||
return | return tostring(res) | ||
end | end | ||
function p.navbox(frame) | function p.navbox(frame) | ||
return p._navbox(frame:getParent().args) | return p._navbox(frame:getParent().args) | ||
end | end | ||
return p | return p |