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.
(accept 'hide' arg)
(change how to exclude, from "exclude=true" to "group=exclude" - so we get it from 'extra' instead of parsing the page)
Line 24: Line 24:
   local groups = { default = {} }
   local groups = { default = {} }
   for _, page in ipairs( pages ) do
   for _, page in ipairs( pages ) do
     -- remove extra from sortkey
     if page.extra ~= 'exclude' then
    if page.extra then page.sortkey = string.sub( page.sortkey, 1, -string.len( page.extra ) - 2 ) end
      -- remove extra from sortkey
      if page.extra then page.sortkey = string.sub( page.sortkey, 1, -string.len( page.extra ) - 2 ) end


    if getPageProps then
      if getPageProps then
      local pageContent = mw.title.new( page.text ):getContent()
        local pageContent = mw.title.new( page.text ):getContent()
      page.args = Args.fromPageContent( pageContent, 'Cat%s*|%s*' .. categoryName )
        page.args = Args.fromPageContent( pageContent, 'Cat%s*|%s*' .. categoryName )
    else
      else
      page.args = {}
        page.args = {}
    end
      end


    -- add page to group
      -- add page to group
    page.args.group = page.extra or 'default'
      page.args.group = page.extra or 'default'
    page.__index = page -- allow variants to fall back to page
      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
      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)
      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
      for _, variant in ipairs( variants ) do
      setmetatable( variant, page.args )
        setmetatable( variant, page.args )
      if not variant.exclude then
         groups[variant.group] = groups[variant.group] or {}
         groups[variant.group] = groups[variant.group] or {}
         groups[variant.group][#groups[variant.group] + 1] = setmetatable( { args = variant }, page )
         groups[variant.group][#groups[variant.group] + 1] = setmetatable( { args = variant }, page )

Revision as of 02:10, July 20, 2020

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

local Args = require( 'Module:Args' )
local Box = require( 'Module:Box' ).Box
local Lazy = require( 'Module:Lazy' ) -- may load: Tabs, Gallery

function getCategoryProps( categoryName )
  local categoryContent = mw.title.new( categoryName, 'Category' ):getContent()
  local props = {}

  for match in string.gmatch( categoryContent, '{{Prop|([^}]*)}}' ) do
    local prop, value = unpack(mw.text.split( match, '|' ))

    -- table if multiple values, value if one value, true if no values (i.e. flag)
    props[prop] = value and string.match( value, ',' ) and mw.text.split( value, ',' ) or value or true
  end

  return props
end

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

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

      if getPageProps then
        local pageContent = mw.title.new( page.text ):getContent()
        page.args = Args.fromPageContent( pageContent, 'Cat%s*|%s*' .. categoryName )
      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 )
        groups[variant.group] = groups[variant.group] or {}
        groups[variant.group][#groups[variant.group] + 1] = setmetatable( { args = variant }, page )
      end
    end
  end

  return groups
end

function buildGallery( pages )
  local Gallery = Lazy.load( 'Module:Gallery' ).Gallery
  local gallery = Gallery.new{
    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
    local Tabs = Lazy.load( 'Module:Tabs' ).Tabs
    local tabs = Tabs.new()

    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' )
  if #pageGroups.default then
    local defaultCell = content:tag( 'tr' )
      :tag( 'td' )
      :addClass( 'odd' )
      :attr( 'colspan', '2' )
      :css( 'text-align', 'center' )
    renderHList( defaultCell, pageGroups.default )
  end
  if categoryProps.groups then
    -- 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
        local row = content:tag( 'tr' )
        row:tag( 'th' )
          :addClass( 'label' )
          :wikitext( group )
        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

  return content
end

local Navbox = Box.new()
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 = args.hide or 'show'
  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 )
  local navbox = Navbox.new( format, args )
  return navbox: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

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

return setmetatable( p, mt )