Documentation for this module may be created at Module:ToggleUtil/doc
local util_vars = require('Module:VarsUtil')
local i18n = require('Module:I18nUtil')
local h = {}
function h.getShowData(data, isSection)
local default_text = isSection and 'Show All' or 'show'
local new_data = mw.clone(data)
new_data.text = data.show_text or default_text
new_data.verb = 'show'
new_data.id = data.show_id
return new_data
end
function h.getHideData(data, isSection)
local default_text = isSection and 'Hide All' or 'hide'
local new_data = mw.clone(data)
new_data.text = data.hide_text or default_text
new_data.verb = 'hide'
new_data.show_attr = data.hide_attr
new_data.hide_attr = data.show_attr
new_data.hide_class = data.show_class
new_data.initshown = not data.initshown
new_data.id = data.hide_id
return new_data
end
function h.addButton(div, data, addSectionClass)
local span = div:tag('span')
:addClass('sections-toggler')
:attr('data-toggler-hiddenclass', data.hiddenclass)
:attr('data-toggler-show', data.show_attr)
:attr('data-toggler-hide', data.hide_attr)
:attr('id', data.id)
:addClass(data.hide_class or data.hide_attr) -- hide yourself, and get shown by other
:wikitext(data.text)
if data.initshown then
span:addClass(data.hiddenclass or 'toggle-section-hidden')
end
if addSectionClass then
span:addClass('toggler-section-' .. data.verb) -- purely for style
end
end
local p = {}
-- for individual show/hides that need a single show-hide all
function p.prepDataByWeek(data, i)
-- to be used by a parent function before sending stuff here
-- replaces instances in classes as needed with the current week
data.show_attr = data.show_attr:format(i)
data.hide_attr = data.hide_attr:format(i)
data.show_class = data.show_class:format(i)
data.hide_class = data.hide_class:format(i)
end
function p.prepDataByWeekAndGame(data, i, j)
data.show_attr = data.show_attr:format(i, j)
data.hide_attr = data.hide_attr:format(i, j)
data.show_class = data.show_class:format(i, i, j)
data.hide_class = data.hide_class:format(i, i, j)
end
-- to be called directly from a parent function
function p.printToggleHeader(tbl, colspan, display, data)
local th = tbl:tag('tr')
:tag('th')
:attr('colspan',colspan or 1)
local div = th:tag('div')
:cssText('position:relative;')
:tag('div')
:addClass('table-header-showhide')
p.printToggleButton(div, data)
th:wikitext(display)
end
-- in theory could be called directly but mostly should be called from above
function p.printToggleButton(div, data)
if not data then data = h.makeDefaultSectionToggleData('set') end
div:wikitext('[')
h.addButton(div, h.getShowData(data))
h.addButton(div, h.getHideData(data))
div:wikitext(']')
end
-- intended to be called externally, makes a section Show All button
function p.printSectionToggler(tbl, data)
if not tbl then tbl = mw.html.create() end
local div = tbl:tag('div'):addClass('expand-contract-button'):addClass(data.cssclass)
local showData = h.getShowData(data, true)
local hideData= h.getHideData(data, true)
h.addButton(div, showData, true)
h.addButton(div, hideData, true)
return tbl
end
-- end tab/all toggles
-----------------------------------------------
-- simple toggle
-- uses section javascript
----------------------------------------------
function p.printSimpleToggleButton(div, isHidden)
local data = h.makeDefaultSectionToggleData('set', isHidden)
div:wikitext('[')
h.addButton(div, h.getShowData(data))
h.addButton(div, h.getHideData(data))
div:wikitext(']')
end
function p.tagSimpleToggledContent(div, isHidden)
local data = h.makeDefaultSectionToggleData('get', isHidden)
div:addClass(data.contentClass)
if isHidden then div:addClass('toggle-section-hidden') end
end
function h.makeDefaultSectionToggleData(verb, isHidden)
local index = util_vars[verb .. 'GlobalIndex']('TOGGLE_SECTION_INDEX')
local contentClass = 'default-content-toggle-' .. index
local buttonClass = 'default-button-toggle-' .. index
local ret = {
contentClass = contentClass,
show_attr = isHidden and contentClass or buttonClass,
hide_attr = isHidden and buttonClass or contentClass,
}
return ret
end
-- separate from the above
-- this assumes a simple single class & single attr
function p.initSectionToggler()
util_vars.setGlobalIndex('SECTION_TOGGLE_SHOW')
util_vars.setGlobalIndex('SECTION_TOGGLE_HIDE')
end
function p.tagSectionToggler(tbl, isReversed, hiddenclass)
local show = 'SECTION_SHOW' .. util_vars.getGlobalIndex('SECTION_TOGGLE_SHOW')
local hide = 'SECTION_HIDE' .. util_vars.getGlobalIndex('SECTION_TOGGLE_HIDE')
local showNew = isReversed and hide or show
local hideNew = isReversed and show or hide
tbl:addClass('sections-toggler')
:attr('data-toggler-hiddenclass', hiddenclass)
:attr('data-toggler-show', showNew)
:attr('data-toggler-hide', hideNew)
p.tagSectionToggle(tbl, isReversed, hiddenClass)
end
function p.tagSectionToggle(tbl, isReversed, hiddenclass)
if isReversed then
tbl:addClass(hiddenclass or 'toggle-section-hidden')
tbl:addClass('SECTION_SHOW' .. util_vars.getGlobalIndex('SECTION_TOGGLE_SHOW'))
else
tbl:addClass('SECTION_HIDE' .. util_vars.getGlobalIndex('SECTION_TOGGLE_HIDE'))
end
end
-- end simple section toggler
-- option from list stuff
-- call printOptionFromListTogglers to make the toggles, and oflCellClasses to make the toggled data
-- if the toggled data is physically above the togglers, then call oflInit before doing anything else
function p.oflInit(data)
-- only run this one time
if data._INITIALIZED then return end
local n = util_vars.setGlobalIndex('OFLToggler')
h.oflInitClasses(data, n)
data.all = data.all or ('ofl-toggler-%s-all'):format(n)
data.section = data.section or ('ofl-toggler-%s-section'):format(n)
data.init = data.init or data.order[1]
-- make sure this doesn't run again
data._INITIALIZED = true
-- allow this to be called by string if desired
h.recordDataByKey(data)
end
function p.printOptionFromListTogglers(tbl, data)
-- @param tbl: HTML object
-- @param data: table of toggle data, requires key order = array of classes to provide ordering
-- print the togglers at the start of a section
-- then call oflCellClasses on each of the things we want to show
data = h.findData(data)
-- guarantee pass a table to oflInit, which will do nothing if it's been run for this object before
p.oflInit(data)
if not tbl then tbl = mw.html.create() end
if not data.displays then data.displays = {} end
local len = #data.order
for i, val in ipairs(data.order) do
local span = h.oflPrintOneToggler(tbl, data, val)
h.oflTogglersAttrs(span, data.attrs, val)
if i < len then
tbl:wikitext(data.sep or '|')
end
end
return tbl
end
function p.oflCellClasses(tbl, data, this)
-- @param tbl: HTML object
-- @param data: data object from printOptionFromListTogglers, or string key to look up via findData
-- @param this: one of the classes from data.order
data = h.findData(data)
tbl:addClass(data.classes[this])
:addClass(data.all)
if data.showall then
tbl:addClass(data.classes[data.showall])
end
if h.oflDoWeAddHiddenclass(data, this) then
tbl:addClass(data.hiddenclass or 'toggle-section-hidden')
end
return tbl
end
function h.recordDataByKey(data)
-- singleton object to record all active toggles by key
-- currently only supports same-Lua-session toggles, no variable support
if not data.key then return end
if not TOGGLE_DATA_LOOKUPS then TOGGLE_DATA_LOOKUPS = {} end
TOGGLE_DATA_LOOKUPS[data.key] = data
end
function h.findData(data)
if type(data) == 'table' then return data end
if not TOGGLE_DATA_LOOKUPS[data] then
error(("Trying to look up a key (%s) that doesn't exist"):format(data))
end
return TOGGLE_DATA_LOOKUPS[data]
end
function h.oflInitClasses(data, n)
if data.classes then return end
data.classes = {}
for k, v in ipairs(data.order) do
data.classes[v] = ('ofl-toggle-%s-%s'):format(n, k)
end
end
function h.oflPrintOneToggler(tbl, data, val, text, isActive)
if not tbl then tbl = mw.html.create() end
local span = tbl:tag('span')
:addClass('optionfromlist-toggler')
:addClass(data.section)
:attr('data-toggle-section', data.section)
:attr('data-toggler-show', data.classes[val])
:attr('data-toggler-hide', data.all)
:wikitext(h.getDisplay(data, val))
if (data.init or data.order[1]) == val then
span:addClass('active')
end
if data.hiddenclass then
span:attr('data-toggler-hiddenclass', data.hiddenclass)
end
return span
end
function h.getDisplay(data, val)
local output
if i18n.exists() then
output = i18n.print(val .. 'Toggle')
end
if not output then
output = data.displays[val] or val
end
return output
end
function h.oflTogglersAttrs(span, attrs, val)
if not attrs then return end
for attr, data in pairs(attrs) do
span:attr(attr, data[val])
end
end
function h.oflDoWeAddHiddenclass(data, this)
if data.showall == data.init then
return false
end
return this ~= data.init
end
-- always active stuff
function p.printSepToggler(tbl, data, isHideButton)
local suffix = '_opposite'
local class = isHideButton and (data.class .. suffix) or data.class
local otherClass = isHideButton and data.class or (data.class .. suffix)
local showText = data.show_text or 'show'
local hideText = data.hide_text or 'hide'
local text = isHideButton and hideText or showText
local span = tbl:tag('span')
:addClass('sections-toggler')
:wikitext(i18n.print(text .. 'Toggle') or text)
:attr('data-toggler-show', class)
:attr('data-toggler-hide', otherClass)
end
function p.sepCellClasses(tbl, data, isActive)
local class = isActive and (data.class .. '_opposite') or data.class
tbl:addClass(class)
if not isActive then
tbl:addClass(data.hiddenclass or 'toggle-section-hidden')
end
end
-- popup button
-- all popup buttons are pretty, but we have the choice of what actions to additionally bind
-- by optionally calling the default popupButton or popupButtonLazy
function p.popupButton(tbl, class)
-- default popup button
local popup = p.popupButtonPretty(tbl, class)
popup.button:addClass('popup-button-action')
return popup
end
function p.popupButtonLazy(tbl, class, parse)
-- content inside will be computed lazily
-- the js adds {{}} for you, so only provide the part inside that
local button = p.popupButton(tbl, class)
button.button:addClass('popup-button-lazy')
:attr('data-parse-text', parse)
return button
end
function p.popupButtonPretty(tbl, class)
-- does NOT add a button action, can be called directly or via p.popupButton
-- p.popupButton fetches this then adds the button action and returns
-- class can be specified to add custom popup-content, popup-button, and popup-wrapper class names
if not tbl then tbl = mw.html.create() end
local span = tbl:tag('span')
local button = span:tag('div')
:addClass('popup-button-pretty')
:wikitext('')
local wrapper = button:tag('div')
:addClass('popup-content-wrapper-pretty')
:addClass('popup-content-wrapper-action')
:addClass('popup-content-hidden')
local inner = wrapper:tag('div')
:addClass('popup-content-inner-pretty')
:addClass('popup-content-inner-action')
if class then
inner:addClass('popup-content-' .. class)
button:addClass('popup-button-' .. class)
wrapper:addClass('popup-wrapper-' .. class)
end
return {
tbl = tbl,
span = span,
button = button,
wrapper = wrapper,
inner = inner
}
end
function p.allToggleAll(tbl, key)
if not tbl then tbl = mw.html.create('') end
local button = tbl:tag('div')
:addClass('all-toggle-all-toggler')
:addClass('active')
:attr('data-all-toggle-key', key)
local button2 = tbl:tag('div')
:addClass('all-toggle-all-toggler')
:addClass('toggle-section-hidden')
:attr('data-all-toggle-key', key)
local content = tbl:tag('div')
:addClass('toggle-section-hidden')
:addClass('all-toggle-all-toggle')
:attr('data-all-toggle-key', key)
return {
tbl = tbl,
button = button,
button2 = button2,
content = content,
}
end
return p