Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Random page
Help about MediaWiki
Search
Search
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Module:NavboxMobile
Module
Discussion
English
Read
Edit source
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit source
View history
Move
General
What links here
Related changes
Special pages
Page information
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
-- Module:NavboxMobile -- This module implements {{navbox}} for MobileFrontend local p = {} require('strict') local cfg = mw.loadData('Module:NavboxMobile/configuration') local navbar = require('Module:Navbar')._navbar local getArgs -- Lazily initialized local inArray = require('Module:TableTools').inArray local format = string.format local args local tableRowAdded = false local border local listnums = {} -- Function to check if the given HTML class is a list class local function has_list_class(htmlclass) local patterns = { '^' .. htmlclass .. '$', '%s' .. htmlclass .. '$', '^' .. htmlclass .. '%s', '%s' .. htmlclass .. '%s' } for arg, _ in pairs(args) do if type(arg) == 'string' and mw.ustring.find(arg, cfg.pattern.class) then for _, pattern in ipairs(patterns) do if mw.ustring.find(args[arg] or '', pattern) then return true end end end end return false end -- Function to check if the navbar is enabled local function has_navbar() return args[cfg.arg.navbar] ~= cfg.keyword.navbar_off and args[cfg.arg.navbar] ~= cfg.keyword.navbar_plain and ( args[cfg.arg.name] or mw.getCurrentFrame():getParent():getTitle():gsub(cfg.pattern.sandbox, '') ~= cfg.pattern.navbox ) end local function add_list_styles() local frame = mw.getCurrentFrame() local function add_list_templatestyles(htmlclass, templatestyles) if has_list_class(htmlclass) then return frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles } } else return '' end end local hlist_styles = add_list_templatestyles('hlist', cfg.hlist_templatestyles) local plainlist_styles = add_list_templatestyles('plainlist', cfg.plainlist_templatestyles) -- a second workaround for [[phab:T303378]] -- when that issue is fixed, we can actually use has_navbar not to emit the -- tag here if we want if has_navbar() and hlist_styles == '' then hlist_styles = frame:extensionTag{ name = 'templatestyles', args = { src = cfg.hlist_templatestyles } } end -- hlist -> plainlist is best-effort to preserve old Common.css ordering. -- this ordering is not a guarantee because most navboxes will emit only -- one of these classes [hlist_note] return hlist_styles .. plainlist_styles end -- Analogous function to add_navbox_styles from Module:Navbox local function add_navbox_mobile_styles(hiding_templatestyles) local frame = mw.getCurrentFrame() -- Function to add user-defined templatestyles local function add_user_styles(templatestyles) if templatestyles and templatestyles ~= '' then return frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles } } end return '' end -- Combine list styles with base and user styles local list_styles = add_list_styles() local base_templatestyles = cfg.templatestyles local templatestyles = add_user_styles(args[cfg.arg.templatestyles]) local child_templatestyles = add_user_styles(args[cfg.arg.child_templatestyles]) -- Combine all styles into a single <div> return mw.html.create('div') :addClass(cfg.class.navbox_styles) :wikitext( list_styles .. base_templatestyles .. templatestyles .. child_templatestyles .. table.concat(hiding_templatestyles) ) :done() end -- Work around for style markers (similar to Navbox) local function move_hiding_templatestyles(args) local gfind = string.gmatch local gsub = string.gsub local templatestyles_markers = {} local strip_marker_pattern = '(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)' for k, arg in pairs(args) do for marker in gfind(arg, strip_marker_pattern) do table.insert(templatestyles_markers, marker) end args[k] = gsub(arg, strip_marker_pattern, '') end return templatestyles_markers end -- Helper function to trim whitespace local function trim(s) return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1")) end -- Helper function to add newlines based on content local function addNewline(s) if s:match('^[*:;#]') or s:match('^{|') then return '\n' .. s ..'\n' else return s end end local function processItem(item, nowrapitems) if not item then return '' -- Prevent nil errors end if item:sub(1, 2) == '{|' then -- Applying nowrap to lines in a table does not make sense. -- Add newlines to compensate for trim of x in |parm=x in a template. item = item:gsub('|%s*width%s*=%s*"[%d%w]+"', '| width="100%"') return '\n' .. item .. '\n' end if nowrapitems == cfg.keyword.nowrapitems_yes or true then local lines = {} for line in (item .. '\n'):gmatch('([^\n]*)\n') do local prefix, content = line:match('^([*:;#]+)%s*(.*)') if prefix and not content:match(cfg.pattern.nowrap) then line = format(cfg.nowrap_item, prefix, content) end table.insert(lines, line) end item = table.concat(lines, '\n') end if item:match('^[*:;#]') then return '\n' .. item .. '\n' end -- Ensure no excessive whitespace item = mw.ustring.gsub(item, "%s+", " ") return item end -- Function to add a new table row with optional gutter local function addTableRow(tbl) -- Check if the spacer rows are necessary based on the listclass or bodyclass local suppressSpacer = false if args.listclass then suppressSpacer = suppressSpacer or args.listclass:find("hlist") end if args.bodyclass then suppressSpacer = suppressSpacer or args.bodyclass:find("hlist") end -- Only add spacer rows if they are not explicitly suppressed if tableRowAdded and not suppressSpacer then tbl:tag('tr') :css('height', '2px') :tag('td') :attr('colspan', 2) :css('background-color', 'transparent') -- Ensure spacer is invisible end tableRowAdded = true return tbl:tag('tr') end -- Function to render the navigation bar local function renderNavBar(cell) if args.navbar == 'off' then return -- Don't render anything if Navbar is off end -- Render the Navbar cell:wikitext(navbar{ args.name, mini = 1, fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') .. ';background:none transparent;border:none;' }) end -- -- Title row -- local function renderTitleRow(tbl) if not args.title then return end local titleRow = addTableRow(tbl) local titleCell = titleRow:tag('th'):attr('scope', 'col') :addClass('navboxMobile-title') :addClass(cfg.class.navbox_list) :addClass(args[cfg.arg.titleclass]) :attr('data-level', 1) :attr('colspan', 2) :cssText(args.basestyle) :cssText(args.titlestyle) :css('position', 'relative') -- Ensure relative positioning for absolute children -- Add the title content, centered across the full width titleCell :tag('div') :css('margin', '0 auto') :css('text-align', 'center') :wikitext(addNewline(args.title)) -- Add the navbar, positioned absolutely in the top-right corner if has_navbar() then titleCell :tag('div') :addClass('navboxMobile-navbar') :css('position', 'absolute') :css('top', '0') :css('right', '0') :css('padding', '0.2em') -- Optional: Adjust padding for alignment :wikitext(navbar{ args.name, mini = 1, fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') .. ';background:none transparent;border:none;' }) end end -- -- Above/Below rows -- local function getAboveBelowColspan() return 2 end local function renderAboveRow(tbl) if not args.above then return end addTableRow(tbl) :tag('td') :addClass('navboxMobile-abovebelow-content') :addClass(cfg.class.navbox_list) -- Add consistent list styling :addClass(args.aboveclass) :cssText(args.basestyle) :cssText(args.abovestyle) :css('padding', args[cfg.arg.abovepadding] or '0.5em') -- Optional padding :attr('colspan', getAboveBelowColspan()) :tag('div') :wikitext(addNewline(args.above)) end local function renderBelowRow(tbl) if not args.below then return end addTableRow(tbl) :tag('td') :addClass('navboxMobile-abovebelow-content') :addClass(cfg.class.navbox_list) -- Add consistent list styling :addClass(args.belowclass) :cssText(args.basestyle) :cssText(args.belowstyle) :css('padding', args[cfg.arg.belowpadding] or '0.5em') -- Optional padding :attr('colspan', getAboveBelowColspan()) :tag('div') :wikitext(addNewline(args.below)) end local function renderListRow(tbl, path, parentLevel) -- Initialize path and parentLevel path = path or "" parentLevel = parentLevel or 2 -- Start at level 2 for child groups -- Keep track of rendered children to avoid duplicates local renderedChildren = {} for i = 1, 10 do local groupKey = (path ~= "" and "child" .. path .. "_" or "") .. "group" .. i local listKey = (path ~= "" and "child" .. path .. "_" or "") .. "list" .. i -- Skip if this group has already been rendered if not renderedChildren[listKey] and args[listKey] then renderedChildren[listKey] = true -- Track rendered lists -- Render the group (heading) local groupRow = addTableRow(tbl) local groupCell = groupRow:tag('th') :attr('scope', 'row') :addClass('navboxMobile-group-content') :addClass('navboxMobile-group-level' .. parentLevel) -- Correct level :attr('data-level', parentLevel) -- Optional attribute for CSS targeting :wikitext(processItem(args[groupKey])) -- Check if the list is non-empty before rendering content if args[listKey] and args[listKey] ~= "" then if args[listKey] == "child" then -- Check if the child contains valid groups or lists local childHasContent = false for j = 1, 10 do local childGroupKey = "child" .. (path ~= "" and path .. "_" or "") .. i .. "_group" .. j local childListKey = "child" .. (path ~= "" and path .. "_" or "") .. i .. "_list" .. j if args[childGroupKey] or args[childListKey] then childHasContent = true break end end if childHasContent then -- Recursively render child lists local newPath = (path ~= "" and path .. "_" or "") .. i renderListRow(tbl, tostring(newPath), parentLevel + 1) end else -- Render flat lists local listRow = addTableRow(tbl) local listCell = listRow:tag('td') :attr('colspan', 2) :addClass('navboxMobile-list-content') -- Base content class :addClass('navboxMobile-list-level' .. parentLevel) -- Correct level :addClass((i % 2 == 1) and 'navboxMobile-odd' or 'navboxMobile-even') -- Odd/even class :addClass(args.listclass or '') -- Apply `listclass` if defined in the template :wikitext(processItem(args[listKey], args.nowrapitems)) end end end end end -- -- Tracking categories -- local function needsHorizontalLists() if border == 'child' or border == 'subgroup' or args.tracking == 'no' then return false end local listClasses = {'plainlist', 'hlist', 'hlist hnum', 'hlist hwrap', 'hlist vcard', 'vcard hlist', 'hlist vevent'} for _, cls in ipairs(listClasses) do if args.listclass == cls or args.bodyclass == cls then return false end end return true end local function hasBackgroundColors() return mw.ustring.match(args.titlestyle or '', 'background') or mw.ustring.match(args.groupstyle or '', 'background') or mw.ustring.match(args.basestyle or '', 'background') end local function isIllegible() local styleratio = require('Module:Color contrast')._styleratio for key, style in pairs(args) do if tostring(key):match("style$") then if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then return true end end end return false end local function getTrackingCategories() local cats = {} if needsHorizontalLists() then table.insert(cats, cfg.category.horizontal_lists) end if hasBackgroundColors() then table.insert(cats, cfg.category.background_colors) end if isIllegible() then table.insert(cats, cfg.category.illegible) end if border == 'subgroup' then table.insert(cats, cfg.category.subgroup) end if args.tracking == 'no' then table.insert(cats, cfg.category.no_tracking) end return cats end local function renderTrackingCategories(builder) local title = mw.title.getCurrentTitle() if title.namespace ~= 10 then return end -- Not in template space local subpage = title.subpageText if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then return end for _, cat in ipairs(getTrackingCategories()) do builder:wikitext('[[Category:' .. cat .. ']]') end end -- -- Main navboxMobile tables -- local function renderMainTable() local tbl = mw.html.create('table') :addClass('nowraplinks') :addClass(cfg.class.navbox) :addClass(args.bodyclass) :addClass(args.listclass or '') -- Apply the `listclass` argument globally if applicable :cssText(args.bodystyle) :cssText(args.style) :css('margin-top', '0') :css('margin-bottom', '0') -- Add the title row renderTitleRow(tbl) -- Add the above row renderAboveRow(tbl) -- Render all group and list rows for _, listnum in ipairs(listnums) do local listKey = "list" .. listnum local groupKey = "group" .. listnum if args[listKey] then -- Render group row local groupRow = addTableRow(tbl) local groupCell = groupRow:tag('th') :attr('scope', 'row') :addClass('navboxMobile-group-content') :addClass('navboxMobile-group-level1') :addClass(args.listclass or '') -- Apply `listclass` for group rows :wikitext(processItem(args[groupKey])) -- Render list row if args[listKey] == 'child' then renderListRow(tbl, tostring(listnum), 2) else local listRow = addTableRow(tbl) listRow:tag('td') :attr('colspan', 2) :addClass('navboxMobile-list-content') :addClass((listnum % 2 == 1) and 'navboxMobile-odd' or 'navboxMobile-even') :addClass(args.listclass or '') -- Apply `listclass` to flat rows :wikitext(processItem(args[listKey])) end end end -- Add the below row renderBelowRow(tbl) return tbl end -- -- Main NavboxMobile Function -- -- In the main navboxMobile function function p._navboxMobile(navboxMobileArgs) args = navboxMobileArgs -- Reset state variables to prevent state leakage between invocations tableRowAdded = false listnums = {} -- Move and collect hiding templatestyles local hiding_templatestyles = move_hiding_templatestyles(args) -- Collect top-level list numbers (list1, list2, etc.) for k, v in pairs(args) do if type(k) == 'string' then local listnum = k:match('^list(%d+)$') if listnum then table.insert(listnums, tonumber(listnum)) end end end table.sort(listnums) border = trim(args.border or args[1] or '') if border == cfg.keyword.border_child then border = cfg.keyword.border_subgroup end -- Render the main body of the navboxMobile local tbl = renderMainTable() -- Create the final HTML with styles local res = mw.html.create() res:node(add_navbox_mobile_styles(hiding_templatestyles)) res:node(tbl) return tostring(res) end -- -- Main NavboxMobile Function -- function p.navboxMobile(frame) if not getArgs then getArgs = require('Module:Arguments').getArgs end args = getArgs(frame, {wrappers = 'Template:Navbox'}) -- Read the arguments in the order they'll be output in, to make references number in the right order. local _ _ = args.title _ = args.above for i = 1, 20 do _ = args["group" .. tostring(i)] _ = args["list" .. tostring(i)] end _ = args.below return p._navboxMobile(args) end return p
Summary:
Please note that all contributions to Ikwipedia are considered to be released under the Creative Commons Attribution-ShareAlike (see
Ikwipedia:Copyrights
for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Templates used on this page:
Template:Template link
(
edit
)
Template:Tl
(
edit
)
Module:NavboxMobile/doc
(
edit
)
Toggle limited content width