Module:Listbox: Difference between revisions

From Zelda Dungeon Wiki
Jump to navigation Jump to search
Want an adless experience? Log in or Create an account.
(use Args.fromFrame which also pulls from the parent frame)
m (change label class to zdw-label to distinguish from bootstrap)
 
(25 intermediate revisions by the same user not shown)
Line 1: Line 1:
local Args = require( 'Module:Args' )
local Args = require( 'Module:Args' )
local Box = require( 'Module:Box' ).Box
local Listing = require( 'Module:Listing' )
local Lazy = require( 'Module:Lazy' ) -- may load: Tabs, Gallery


function getCategoryProps( categoryName )
function buildHList( parent, sections )
   local categoryContent = mw.title.new( categoryName, 'Category' ):getContent()
   local list = parent:addClass( 'hlist' )
   local props = {}
    :tag( 'ul' )
 
   for _, section in ipairs( sections ) do
  for match in string.gmatch( categoryContent, '{{Prop|([^}]*)}}' ) do
    -- !!!! This may break if Template:Main is modified !!!!
     local prop, value = unpack(mw.text.split( match, '|' ))
    local expandedMainTemplate = section.summary:match( 'Main article: %[%[(.-)]]' )
 
     local link = expandedMainTemplate and mw.text.split( expandedMainTemplate, '|' )[1]
     -- table if multiple values, value if one value, true if no values (i.e. flag)
     list:tag( 'li' )
    props[prop] = value and string.match( value, ',' ) and mw.text.split( value, ',' ) or value or true
      :wikitext( '[[' .. (link or section.name) .. '|' .. section.name .. ']]' )
   end
   end
  return props
end
end


function getPageGroups( categoryName, getPageProps )
local Navbox = Listing.Navbox
  -- get all pages in the category
  local pages = mw.ext.dpl.getPages{ category = categoryName, ordermethod = 'sortkey', order = 'ascending' }


  -- organize them by group
local Listbox = setmetatable( {}, Navbox )
  local groups = { default = {} }
Listbox.__index = Listbox
  for _, page in ipairs( pages ) do
    -- remove extra from sortkey
    if page.extra then page.sortkey = string.sub( page.sortkey, 1, -string.len( page.extra ) - 2 ) end


    if getPageProps then
function Listbox.new( args )
      local pageContent = mw.title.new( page.text ):getContent()
  local obj = Navbox.new( args )
      page.args = Args.fromPageContent( pageContent, 'Cat%s*|%s*' .. categoryName )
  return setmetatable( obj, Listbox )
    else
      page.args = {}
    end
 
    -- add page to group
    page.args.group = page.extra or 'default'
    page.__index = page -- allow variants to fall back to page
    page.args.__index = page.args -- allow variants' args to fall back to page's args
    local variants = page.args.variant or {{}} -- that's a table containing a single table (variant) with no properties (overrides)
    for _, variant in ipairs( variants ) do
      setmetatable( variant, page.args )
      if not variant.exclude then
        groups[variant.group] = groups[variant.group] or {}
        groups[variant.group][#groups[variant.group] + 1] = setmetatable( { args = variant }, page )
      end
    end
  end
 
  return groups
end
end


function buildGallery( pages )
-- override
  local Gallery = Lazy.load( 'Module:Gallery' ).Gallery
function Listbox:renderContent()
  local gallery = Gallery.new{
   local listing = Listing._parseListing( self.subject )
    widths = '62px',
    heights = '62px'
  }
  for _, page in ipairs( pages ) do
    gallery:addFile( page.args.image or 'No Image.png', '[[' .. page.text .. '|' .. (page.args.name or page.text) .. ']]', {
      link = page.text,
      alt = page.args.name or page.text
    } )
  end
 
  return gallery:render()
end
 
 
function buildGalleries( categoryProps, pageGroups )
   local Gallery = Lazy.load( 'Module:Gallery' ).Gallery
 
  local defaultGallery = nil
  if pageGroups.default then
    defaultGallery = buildGallery( pageGroups.default )
  end


   if categoryProps.groups then
   -- If categories weren't set already (because caller used single arg), then use the ones parsed from the page.
    local Tabs = Lazy.load( 'Module:Tabs' ).Tabs
  -- CODE SMELL: setting unrelated state. this only works because renderFooter is called after renderContent.
    local tabs = Tabs.new()
  if #self.categories == 0 then self.categories = listing.categories end


    if defaultGallery then
      tabs:addTabTopWithContent{
        contentId = 'General',
        content = defaultGallery
      }
    end
    -- coerce it to a table for easier processing
    local groups = type( categoryProps.groups ) == 'table' and categoryProps.groups or { categoryProps.groups }
    for index, group in ipairs( groups ) do
      if pageGroups[group] then
        tabs:addTabTopWithContent{
          contentId = group,
          content = buildGallery( pageGroups[group] )
        }
      end
    end
    return tabs:render()
  end
  return defaultGallery
end
function renderHList( parent, pages )
  local list = parent:addClass( 'hlist' )
    :tag( 'ul' )
  for _, page in ipairs( pages ) do
    list:tag( 'li' )
      :wikitext( '[[' .. page.text .. '|' .. (page.args.name or page.text) .. ']]' )
  end
end
function buildTable( categoryProps, pageGroups )
   local content = mw.html.create( 'table' )
   local content = mw.html.create( 'table' )
   if #pageGroups.default then
   if #listing.topLevelLeaves > 0 then
     local defaultCell = content:tag( 'tr' )
     local defaultCell = content:tag( 'tr' )
       :tag( 'td' )
       :tag( 'td' )
Line 122: Line 39:
       :attr( 'colspan', '2' )
       :attr( 'colspan', '2' )
       :css( 'text-align', 'center' )
       :css( 'text-align', 'center' )
     renderHList( defaultCell, pageGroups.default )
     buildHList( defaultCell, listing.topLevelLeaves )
   end
   end
   if categoryProps.groups then
   if #listing.groups > 0 then
    -- coerce it to a table for easier processing
     for index, group in ipairs( listing.groups ) do
    local groups = type( categoryProps.groups ) == 'table' and categoryProps.groups or { categoryProps.groups }
       local row = content:tag( 'tr' )
     for index, group in ipairs( groups ) do
      row:tag( 'th' )
       if pageGroups[group] then
        :addClass( 'zdw-label' )
        local row = content:tag( 'tr' )
        :wikitext( group.name )
        row:tag( 'th' )
      local cell = row:tag( 'td' )
          :addClass( 'label' )
        :addClass( (index + (#listing.topLevelLeaves > 0 and 1 or 0)) % 2 == 0 and 'even' or 'odd' )
          :wikitext( group )
      buildHList( cell, group.sections )
        local cell = row:tag( 'td' )
          :addClass( (index + (#pageGroups.default and 1 or 0)) % 2 == 0 and 'even' or 'odd' )
        renderHList( cell, pageGroups[group] )
      end
     end
     end
   end
   end
Line 143: Line 56:
end
end


local Navbox = Box.new()
local p = {}
Navbox.__index = Navbox
setmetatable( Navbox, Box )
 
function Navbox.new( format, args )
  local subject = args[1] .. ' ' .. args[2]
  args.class = 'navbox'
  args.title = subject
  args.edit = subject
  args.hide = 'show' -- TODO count number of navboxes, hide after the second or third (could relegate to the calling template)
  local obj = Box.new( 'light', args )
  obj.format = format
  obj.subject = subject
  obj.categories = { args[1], subject, args[2] }
  return setmetatable( obj, Navbox )
end
 
function Navbox:renderContent()
  local categoryProps = getCategoryProps( self.subject )
  local pageGroups = getPageGroups( self.subject, self.format == 'gallery' )
  local build = setmetatable( {
    gallery = buildGalleries
  }, {
    __index = function() return buildTable end -- default
  } )
  return build[self.format]( categoryProps, pageGroups )
end
 
local p, mt = {}, {}


function p._main( format, args )
function p.main( frame )
   local navbox = Navbox.new( format, args )
   local listbox = Listbox.new( Args.fromFrame( frame ) )
  return navbox:render()
   return listbox:render()
end
 
-- translates p.function( frame ) to p._main( function, args )
function mt.__index( table, key )
   return function ( frame )
    return table._main( key, Args.fromFrame( frame ) )
  end
end
end


-- for use in the debug console:
-- for use in the debug console:
-- =p.list(p.debugframe)
-- =p.main(p.debugframe)
p.debugframe = {
p.debugframe = {
   args = {
   args = {},
     [1] = "The Legend of Zelda",
  getParent = function() return {
     [2] = "Enemies",
     args = {
   }
      [1] = "The Legend of Zelda Locations"
     }
   } end
}
}


return setmetatable( p, mt )
return p

Latest revision as of 02:17, November 16, 2020

Documentation for this module may be created at Module:Listbox/doc

local Args = require( 'Module:Args' )
local Listing = require( 'Module:Listing' )

function buildHList( parent, sections )
  local list = parent:addClass( 'hlist' )
    :tag( 'ul' )
  for _, section in ipairs( sections ) do
    -- !!!! This may break if Template:Main is modified !!!!
    local expandedMainTemplate = section.summary:match( 'Main article: %[%[(.-)]]' )
    local link = expandedMainTemplate and mw.text.split( expandedMainTemplate, '|' )[1]
    list:tag( 'li' )
      :wikitext( '[[' .. (link or section.name) .. '|' .. section.name .. ']]' )
  end
end

local Navbox = Listing.Navbox

local Listbox = setmetatable( {}, Navbox )
Listbox.__index = Listbox

function Listbox.new( args )
  local obj = Navbox.new( args )
  return setmetatable( obj, Listbox )
end

-- override
function Listbox:renderContent()
  local listing = Listing._parseListing( self.subject )

  -- If categories weren't set already (because caller used single arg), then use the ones parsed from the page.
  -- CODE SMELL: setting unrelated state. this only works because renderFooter is called after renderContent.
  if #self.categories == 0 then self.categories = listing.categories end

  local content = mw.html.create( 'table' )
  if #listing.topLevelLeaves > 0 then
    local defaultCell = content:tag( 'tr' )
      :tag( 'td' )
      :addClass( 'odd' )
      :attr( 'colspan', '2' )
      :css( 'text-align', 'center' )
    buildHList( defaultCell, listing.topLevelLeaves )
  end
  if #listing.groups > 0 then
    for index, group in ipairs( listing.groups ) do
      local row = content:tag( 'tr' )
      row:tag( 'th' )
        :addClass( 'zdw-label' )
        :wikitext( group.name )
      local cell = row:tag( 'td' )
        :addClass( (index + (#listing.topLevelLeaves > 0 and 1 or 0)) % 2 == 0 and 'even' or 'odd' )
      buildHList( cell, group.sections )
    end
  end

  return content
end

local p = {}

function p.main( frame )
  local listbox = Listbox.new( Args.fromFrame( frame ) )
  return listbox:render()
end

-- for use in the debug console:
-- =p.main(p.debugframe)
p.debugframe = {
  args = {},
  getParent = function() return {
    args = {
      [1] = "The Legend of Zelda Locations"
    }
  } end
}

return p