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.
(saving WIP for gallery layout. realized this will be much easier if I first convert Tab (and maybe Gallery too))
(implement gallery mode (has a few bugs I think))
Line 1: Line 1:
local Box = require( 'Module:Box' ).Box
local Box = require( 'Module:Box' ).Box
local Lazy = require( 'Module:Lazy' ) -- may load: Tabs, Gallery


function getCategoryProps( categoryName )
function getCategoryProps( categoryName )
Line 52: Line 53:
end
end


function buildGallery( categoryProps, pageTree )
function buildGallery( pages )
   local tabGroupId = 'TODO' -- mw.getCurrentFrame():expandTemplate{ title = 'Zelda', args = { game } } .. category -- or strip whitespace from self.subject
   local Gallery = Lazy.load( 'Module:Gallery' ).Gallery
  local gallery = Gallery.new() -- TODO define appropriate args. CD/Header has: {{Gallery|size={{#ifeq:{{{size|}}}|large|95|62}}|pad=1|square={{{square|true}}}}}
  for _, page in ipairs( pages ) do
    defaultGallery:addFile( 'No Image.png', '[[' .. page.text .. '|' .. page.extra.name or page.text .. ']]', {
      link = page.text,
      alt = page.extra.name or page.text
    } )
  end
 
  return gallery:render()
end
 
 
function buildGalleries( categoryProps, pageTree )
  local Gallery = Lazy.load( 'Module:Gallery' ).Gallery
 
  local defaultGallery = nil
  if pageTree.default then
    defaultGallery = buildGallery( pageTree.default )
  end
 
  if categoryProps.groups then
    local Tabs = Lazy.load( 'Module:Tabs' ).Tabs
    local tabs = Tabs.new()


  -- from TabSettings: {{#vardefine:TabsID|{{{1|}}}}}{{#vardefine:TabsDefault|{{#if:{{{2|}}}|{{{2|}}}|1}}}} 
    if defaultGallery then
  -- from CD/Decorator: {{#vardefine:cd-dec|gallery}}{{#vardefine:cd-tabindex|0}}{{TabSettings|{{{2|{{PAGENAME}}}}}}}<div class{{=}}"tab"><ul></ul></div><div class{{=}}"tabcontent">


  local content = mw.html.create( 'div' )
      tabs:addTabTopWithContent{
  content:tag( 'div' )
        contentId = 'General',
    :addClass( 'tab' )
        content = defaultGallery
     :tag( 'ul' )
      }
  local tabcontent = content:tag( 'div' )
     end
    :addClass( 'tabcontent' )


  -- from CD/Header:
    -- coerce it to a table for easier processing
--{{#if: {{{1|}}}
    local groups = type( categoryProps.groups ) == 'table' and categoryProps.groups or { categoryProps.groups }
--  | {{Tab|{{#vardefineecho:cd-tabindex|{{#expr:{{#var:cd-tabindex}}+1}}}}|{{{1|}}}}}
    for index, group in ipairs( groups ) do
--<div class{{=}}"_toggle {{#var:TabsID}}tab{{#var:cd-tabindex}} {{#var:TabsID}}tabs" {{#ifeq:{{#var:TabsDefault}}|{{#var:cd-tabindex}}|style{{=}}"display: none;"|}}></div><div class{{=}}"_toggle {{#var:TabsID}}tab{{#var:cd-tabindex}} {{#var:TabsID}}tabs" {{#ifeq:{{#var:TabsDefault}}|{{#var:cd-tabindex}}||style{{=}}"display: none;"}}>
      if pageTree[group] then
--  | <div>
        tabs:addTabTopWithContent{
--  }}{{Gallery|size={{#ifeq:{{{size|}}}|large|95|62}}|pad=1|square={{{square|true}}}}}
          contentId = group,
          content = buildGallery( pageTree[group] )
        }
      end
    end


  -- from CD:
    return tabs:render()
--{{#if:{{{caption1|}}}
  end
--  | {{#forargs:caption|key|val
--    | {{#ifexpr:{{#var:key}}>1|{{N}}}}{{Gallery/Box
--      | file = {{{file{{#var:key}}|{{{file|}}}}}}
--      | link = {{{link{{#var:key}}|{{{link|}}}}}}
--      | tip = {{{tip{{#var:key}}|{{{tip|{{#var:val}}}}}}}}
--      | caption = [[{{{link{{#var:key}}|{{{link|}}}}}}|{{#var:val}}]]}}
--    }}
--  | {{Gallery/Box|file={{{file|}}}|link={{{link|}}}|tip={{{tip|{{{caption|{{{link|}}}}}}}}}|caption=[[{{{link|}}}|{{{caption|{{{link|}}}}}}]]}}
--  }}


  -- from CD/End: {{Gallery/Bottom}}</div>
   return defaultGallery
   return content
end
end


Line 93: Line 109:
   for _, page in ipairs( pages ) do
   for _, page in ipairs( pages ) do
     list:tag( 'li' )
     list:tag( 'li' )
       :wikitext( '[[' .. page.text .. '|' .. (page.extra.name or page.sortkey or page.text) .. ']]' )
       :wikitext( '[[' .. page.text .. '|' .. (page.extra.name or page.text) .. ']]' )
   end
   end
end
end
Line 109: Line 125:
   if categoryProps.groups then
   if categoryProps.groups then
     -- coerce it to a table for easier processing
     -- coerce it to a table for easier processing
     local groups = type(categoryProps.groups) == 'table' and categoryProps.groups or { categoryProps.groups }
     local groups = type( categoryProps.groups ) == 'table' and categoryProps.groups or { categoryProps.groups }
     for index, group in ipairs(groups) do
     for index, group in ipairs( groups ) do
       if( pageTree[group] ) then
       if pageTree[group] then
         local row = content:tag( 'tr' )
         local row = content:tag( 'tr' )
         row:tag( 'th' )
         row:tag( 'th' )

Revision as of 02:01, June 25, 2020

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

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 getPageTree( categoryName, expandVariants )
  -- get all pages in the category
  local pages = mw.ext.dpl.getPages{ category = categoryName, ordermethod = 'sortkey', order = 'ascending' }

  -- organize them according to metadata
  local pageTree = { default = {} }
  for _, page in ipairs( pages ) do
    -- get metadata
    if page.extra then
      -- remove extra from sortkey
      page.sortkey = string.sub( page.sortkey, 1, -string.len( page.extra ) - 2 )

      local success, result = pcall( mw.text.jsonDecode, page.extra )
      if success then
        page.extra = result
      else
        page.sortkey = page.text .. mw.getCurrentFrame():expandTemplate{ title = 'Tt', args = { 'PARSING ERROR: Please ensure the argument to \'extra\' in this page\'s invocation of \'Cat\' is valid JSON' } }
        page.extra = {}
      end
    else page.extra = {}
    end

    -- add page to group
    page.__index = page -- allow variants to fall back to page
    page.extra.__index = page.extra -- allow variants' extra to fall back to page's extra
    local variants = expandVariants and page.extra.variants or {{}} -- that's a table containing a single table (variant) with no properties (overrides)
    for _, variant in ipairs( variants ) do
      setmetatable( variant, page.extra )
      if not variant.group then variant.group = 'default' end
      if not pageTree[variant.group] then pageTree[variant.group] = {} end
      pageTree[variant.group][#pageTree[variant.group] + 1] = setmetatable( { extra = variant }, page )
    end
  end

  return pageTree
end

function buildGallery( pages )
  local Gallery = Lazy.load( 'Module:Gallery' ).Gallery
  local gallery = Gallery.new() -- TODO define appropriate args. CD/Header has: {{Gallery|size={{#ifeq:{{{size|}}}|large|95|62}}|pad=1|square={{{square|true}}}}}
  for _, page in ipairs( pages ) do
    defaultGallery:addFile( 'No Image.png', '[[' .. page.text .. '|' .. page.extra.name or page.text .. ']]', {
      link = page.text,
      alt = page.extra.name or page.text
    } )
  end

  return gallery:render()
end


function buildGalleries( categoryProps, pageTree )
  local Gallery = Lazy.load( 'Module:Gallery' ).Gallery

  local defaultGallery = nil
  if pageTree.default then
    defaultGallery = buildGallery( pageTree.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 pageTree[group] then
        tabs:addTabTopWithContent{
          contentId = group,
          content = buildGallery( pageTree[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.extra.name or page.text) .. ']]' )
  end
end

function buildTable( categoryProps, pageTree )
  local content = mw.html.create( 'table' )
  if #pageTree.default then
    local defaultCell = content:tag( 'tr' )
      :tag( 'td' )
      :addClass( 'odd' )
      :attr( 'colspan', '2' )
      :css( 'text-align', 'center' )
    renderHList( defaultCell, pageTree.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 pageTree[group] then
        local row = content:tag( 'tr' )
        row:tag( 'th' )
          :addClass( 'label' )
          :wikitext( group )
        local cell = row:tag( 'td' )
          :addClass( (index + (#pageTree.default and 1 or 0)) % 2 == 0 and 'even' or 'odd' )
        renderHList( cell, pageTree[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 = '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 pageTree = getPageTree( self.subject, self.format == 'gallery' )
  local build = setmetatable( {
    gallery = buildGallery
  }, {
    __index = function() return buildTable end -- default
  } )
  return build[self.format]( categoryProps, pageTree )
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, frame.args )
  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 )