Дополнительные действия
DarkMuse (обсуждение | вклад) Нет описания правки |
DarkMuse (обсуждение | вклад) Нет описания правки |
||
| Строка 23: | Строка 23: | ||
args = args or {} | args = args or {} | ||
-- Читаем аргументы и проверяем их корректность | |||
local tabArgs = Tabs._readArguments(args, {allowThis2 = true}) | local tabArgs = Tabs._readArguments(args, {allowThis2 = true}) | ||
local tabCount = #tabArgs | local tabCount = #tabArgs | ||
if tabCount == 0 then return '' end | if tabCount == 0 then | ||
return '<div class="error">Ошибка: Не переданы табы.</div>' | |||
end | |||
-- Устанавливаем активные табы | |||
Tabs._setThis(tabArgs) | Tabs._setThis(tabArgs) | ||
-- Создаём список табов | |||
local tabs = mw.html.create('ul') | local tabs = mw.html.create('ul') | ||
: | :addClass('nav nav-tabs navigation-not-searchable tabs tabs' .. tabCount) | ||
:attr('data-nosnippet') | :attr('data-nosnippet', '') | ||
local subTabs = mw.html.create() | local subTabs = mw.html.create() | ||
for _, tab in ipairs(tabArgs) do | |||
local name = tab.name or (tab.link and Tabs._getDisplayNameFromLink(tab.link)) or 'Таб без имени' | |||
local text = tab.link and Page.makeInternalLink({}, name, tab.link) or tab.name or 'Таб без ссылки' | |||
tabs:tag('li'):addClass(tab.this and 'active' or nil):wikitext(text) | |||
subTabs:node(tab.this and tab.tabs or nil) | |||
end | |||
-- Возвращаем HTML-код | |||
return mw.html.create() | return mw.html.create() | ||
:tag('div') | :tag('div') | ||
| Строка 51: | Строка 56: | ||
:node(subTabs) | :node(subTabs) | ||
end | end | ||
---Creates dynamic tabs. | ---Creates dynamic tabs. | ||
Текущая версия от 23:56, 10 января 2025
Модуль Module:Tabs используется для создания вкладок на страницах iCCup, предоставляя как статические, так и динамические табы для организации и структурирования информации.
API[править код]
-
Программное имя: Tabs
Создает статические вкладки.
Создает динамические вкладки.
Обрабатывает аргументы, переданные в шаблон, и определяет, какие из них использовать для создания вкладок.
Устанавливает текущую вкладку на основе текущего URL или других условий.
Создает контейнер для содержания вкладок.
Создает одиночную вкладку, если передан только один аргумент.
Получает имя для отображения из ссылки.
Посмотрите всю нашу документацию iCCup здесь.
Пример использования[править код]
Пример 1: Статические вкладки[править код]
{{#invoke:Tabs|static|name1=Вкладка 1|link1=Page1|name2=Вкладка 2|link2=Page2}}
Этот пример создаст две статические вкладки: "Вкладка 1" и "Вкладка 2", каждая из которых будет ссылаться на Page1 и Page2 соответственно.
Пример 2: Динамические вкладки[править код]
<pre> {{#invoke:Tabs|dynamic|name1=Вкладка 1|content1=Содержание 1|name2=Вкладка 2|content2=Содержание 2}} </pre>
Этот пример создаст две динамические вкладки, переключаясь между "Содержание 1" и "Содержание 2" при нажатии на "Вкладка 1" и "Вкладка 2".
Параметры[править код]
- name<sub>n</sub>: Название вкладки, где
n— номер вкладки. - link<sub>n</sub>: Ссылка для вкладки, если вкладка должна быть статической.
- content<sub>n</sub>: Содержимое вкладки, если вкладка динамическая.
- tabs<sub>n</sub>: Дополнительные вкладки, которые могут быть вложены в текущую.
- This: Указывает, какая вкладка должна быть активной.
- This2: Дополнительный параметр для указания активной вкладки.
---
-- @iCCup
-- wiki=commons
-- page=Module:Tabs
--
-- This module is adapted for iCCup.
--
local Array = require('Module:Array')
local Class = require('Module:Class')
local Logic = require('Module:Logic')
local Operator = require('Module:Operator')
local Page = require('Module:Page')
local Table = require('Module:Table')
local Tabs = {}
---Creates static tabs.
---Entry point of Template:Tabs static
---@param args table?
---@return Html|string?
function Tabs.static(args)
args = args or {}
-- Читаем аргументы и проверяем их корректность
local tabArgs = Tabs._readArguments(args, {allowThis2 = true})
local tabCount = #tabArgs
if tabCount == 0 then
return '<div class="error">Ошибка: Не переданы табы.</div>'
end
-- Устанавливаем активные табы
Tabs._setThis(tabArgs)
-- Создаём список табов
local tabs = mw.html.create('ul')
:addClass('nav nav-tabs navigation-not-searchable tabs tabs' .. tabCount)
:attr('data-nosnippet', '')
local subTabs = mw.html.create()
for _, tab in ipairs(tabArgs) do
local name = tab.name or (tab.link and Tabs._getDisplayNameFromLink(tab.link)) or 'Таб без имени'
local text = tab.link and Page.makeInternalLink({}, name, tab.link) or tab.name or 'Таб без ссылки'
tabs:tag('li'):addClass(tab.this and 'active' or nil):wikitext(text)
subTabs:node(tab.this and tab.tabs or nil)
end
-- Возвращаем HTML-код
return mw.html.create()
:tag('div')
:addClass('tabs-static')
:attr('data-nosnippet', '')
:node(tabs)
:done()
:node(subTabs)
end
---Creates dynamic tabs.
---Entry point of Template:Tabs dynamic
---@param args table
---@return Html|string?
function Tabs.dynamic(args)
args = args or {}
local tabArgs = Tabs._readArguments(args, {removeEmptyTabs = Logic.readBool(args.removeEmptyTabs)})
local tabCount = #tabArgs
if tabCount == 0 then return '' end -- Возвращаем пустую строку, если табов нет
local hasContent = Array.all(tabArgs, function(tab) return Logic.isNotEmpty(tab.content) end)
local allEmpty = Array.all(tabArgs, function(tab) return Logic.isEmpty(tab.content) end)
assert(hasContent or allEmpty, 'Some of the tabs have contents while others do not')
local isSingular = tabCount == 1 and hasContent
if isSingular and not Logic.readBool(args.showSingularAsTab) then
return Tabs._single(tabArgs[1], not Logic.readBool(args.suppressHeader))
end
local tabs = mw.html.create('ul')
:addClass('nav nav-tabs tabs tabs' .. tabCount)
if not Array.any(tabArgs, Operator.property('this')) then
tabArgs[1].this = true
end
local build = function(obj, elementType, content, class, isActive)
if not obj or not elementType then return end -- Проверка аргументов
local element = mw.html.create(elementType)
:addClass(class)
:addClass(isActive and 'active' or nil)
:newline()
:node(content)
obj:newline():node(element)
end
for tabIndex, tabData in ipairs(tabArgs) do
build(tabs, 'li', tabData.name, 'tab' .. tabIndex, tabData.this)
end
for tabIndex, tabData in ipairs(tabArgs) do
build(contents, 'div', tabData.content, 'content' .. tabIndex, tabData.this)
end
if not Logic.nilOr(Logic.readBoolOrNil(args['hide-showall']), isSingular) then
tabs:tag('li')
:addClass('show-all')
:wikitext('Show All')
end
tabs:newline()
local contents = Tabs._buildContentDiv(
hasContent,
Logic.readBool(args['hybrid-tabs']),
Logic.readBool(args['no-padding'])
)
if not hasContent then
return '<div class="tabs-dynamic navigation-not-searchable" data-nosnippet>\n'
.. tostring(tabs) .. contents
end
Array.forEach(tabArgs, function(tabData, tabIndex)
build(contents, 'div', tabData.content, 'content' .. tabIndex, tabData.this)
end)
return mw.html.create('div')
:addClass('tabs-dynamic navigation-not-searchable')
:attr('data-nosnippet')
:node(tabs)
:newline()
:node(contents)
end
---@param args table
---@param options {allowThis2: boolean?, removeEmptyTabs: boolean?}
---@return {name: string?, link: string?, content: string|Html?, tabs: string|Html?, this: boolean}[]
function Tabs._readArguments(args, options)
local tabArgs = {}
local tabIndex = 1
local thisTab = tonumber(args.This)
local this2Tab = tonumber(args.This2)
while args['name' .. tabIndex] or args['link' .. tabIndex] do
if args['content' .. tabIndex] or not options.removeEmptyTabs then
table.insert(tabArgs, {
name = Table.extract(args, 'name' .. tabIndex),
link = Table.extract(args, 'link' .. tabIndex),
content = Table.extract(args, 'content' .. tabIndex),
tabs = Table.extract(args, 'tabs' .. tabIndex),
this = thisTab == tabIndex or (options.allowThis2 and this2Tab == tabIndex),
})
end
tabIndex = tabIndex + 1
end
if Logic.readBool(args.returnIfEmpty) then
return tabArgs
end
assert(Logic.isNotEmpty(tabArgs), 'You are trying to add a "Tabs" template without arguments for names nor links')
return tabArgs
end
---@param tabArgs {name: string?, link: string?, content: string|Html?, tabs: string|Html?, this: boolean}[]
function Tabs._setThis(tabArgs)
if Array.any(tabArgs, Operator.property('this')) then return end
local fullPageName = mw.title.getCurrentTitle().prefixedText
local this
local maxLinkLength = -1
for tabIndex, tab in ipairs(tabArgs) do
local link = tab.link
if not link then return end
link = link:gsub('_', ' ')
local linkLength = string.len(link)
local charAfter = string.sub(fullPageName, linkLength + 1, linkLength + 1)
local pagePartial = string.sub(fullPageName, 1, linkLength)
if pagePartial == link and (charAfter == '/' or charAfter == '') and linkLength > maxLinkLength then
maxLinkLength = linkLength
this = tabIndex
end
end
if not this then return end
tabArgs[this].this = true
end
---@param hasContent boolean
---@param hybridTabs boolean
---@param noPadding boolean
---@return Html|string
function Tabs._buildContentDiv(hasContent, hybridTabs, noPadding)
if hasContent then
local contentDiv = mw.html.create('div')
:addClass('tabs-content')
if hybridTabs then
contentDiv
:css('border-style', 'none !important')
:css('padding', '0 !important')
elseif noPadding then
contentDiv
:css('padding', '0 !important')
end
return contentDiv
end
local style = ''
if hybridTabs then
style = 'border-style:none !important; padding:0 !important;'
elseif noPadding then
style = 'padding:0 !important;'
end
return '\n<div class="tabs-content" style="' .. style .. '">'
end
---@param tab {name: string?, link: string?, content: string|Html?, tabs: string|Html?, this: boolean}
---@param showHeader boolean
---@return Html
function Tabs._single(tab, showHeader)
local header
if showHeader then
header = mw.html.create()
:tag('h6'):wikitext(tab.name):done()
:newline()
end
return mw.html.create()
:node(header)
:node(tab.content)
end
---@param link string
---@return string
function Tabs._getDisplayNameFromLink(link)
local linkParts = mw.text.split(link, '/', true)
return linkParts[#linkParts]
end
return Class.export(Tabs)