Module:SongsTable
Work in Progress!!
This module is supposed to provide access to the list of song titles Angelina did. To (most of) the song titles also a selection of videos was attached (now removed). This list is stored in JSON format in the Data:Songs.json page.
The song data has initially be derived from the listing on the Songs page. The intention is, that listing can be instead genereated by this module. But in addition, it should be possible to use the data on other pages.
For example, a page for a song could use it to list the most relevant example renditions of that song.
The idea is not, that all details of the songs data, like the song info box on the songs page, is stored in this list.
In the past, the videos were stored in the Data:SongsToVideos.json JSON data together with the songs listing, which is assumed to be alphabetic. That was not the long term solution, and in the meantime the videos were removed and the page renamed to Data:Songs.json. It's envisioned, that this will later be generated from more generic tables. See User:Most2dot0/Ideas for more ideas on this.
ToDo
- Add more representations of data, e.g. like on the "Songs" page.
- Consider to have a seperate reference field ( or a list of references )
- Either integrate AtoZ bar in table section headers, or a link to jump to it above
- Add access with filters, e.g.
- - for song title
- - for orginals
- Don't rely on videos included, but generate by using a seperate performances table, which links performances to songs, events, locations and videos.
- Present some sort of "quality" indication
Examples
Complete Table
A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
Code
local p = {}
-- Function to load JSON content from a page
function p.loadJsonContent(jsonPage)
-- Check if jsonPage is a valid string
if type(jsonPage) ~= 'string' then
return nil, "Invalid argument: JSON page name must be a string."
end
-- Try to load the page content
local title = mw.title.new(jsonPage)
if not title then
return nil, "Failed to create title object for page: " .. jsonPage
end
local content = title:getContent()
if not content then
return nil, "Failed to load content for page: " .. jsonPage
end
-- Try to decode the JSON content
local data = mw.text.jsonDecode(content)
if type(data) ~= 'table' then
return nil, "Invalid JSON data in page: " .. jsonPage
end
return data, nil
end
local function fetchData()
local data, err = p.loadJsonContent('Data:SongsToVideos')
if err then
return nil, err
end
return data
end
local function extractVideoID(url)
local match = mw.ustring.match(url, "v=([%w_-]+)")
return match
end
local function generateCollapsibleTableRow(song, index, count)
local title = song.title
local linkTarget = title
local displayTitle = title
if song.disambiguation then
linkTarget = title .. " (" .. song.disambiguation .. ")"
displayTitle = title .. " ''(" .. song.disambiguation .. ")''"
end
if song.type == "redirect" and song.actual then
displayTitle = " ''" .. title .. "'' → ''' [[" .. song.actual .. "|" .. song.actual .. "]] '''"
else
if song.disambiguation then
displayTitle = count .. ". '''[[" .. linkTarget .. "|" .. title .. "]]''' ''(" .. song.disambiguation .. ")''"
else
displayTitle = count .. ". '''[[" .. linkTarget .. "|" .. title .. "]]'''"
end
end
local type = song.type or "cover"
local typeDescription
if type == "original" then
typeDescription = "Original"
elseif type == "redirect" and song.actual then
typeDescription = "Redirect"
else
typeDescription = "Cover"
end
local button = ""
local videosSection = ""
if song.videos and #song.videos > 0 then
button = ' <span class="mw-customtoggle-' .. index .. '" style="cursor:pointer; color:blue;">[Show/Hide Videos]</span>'
local videoIDs = {}
for _, video in ipairs(song.videos) do
local videoID = extractVideoID(video.url)
if videoID then
table.insert(videoIDs, videoID)
end
end
local placeholderDiv = '<div class="youtube-player-placeholder" data-videos="' .. table.concat(videoIDs, ",") .. '"></div>'
videosSection = '<tr class="mw-collapsible mw-collapsed" id="mw-customcollapsible-' .. index .. '">\n'
videosSection = videosSection .. '<td colspan="2" style="padding-left: 1em;">' .. placeholderDiv .. '<ul>\n'
for _, video in ipairs(song.videos) do
videosSection = videosSection .. '<li>[' .. video.url .. ' ' .. video.title .. '] (' .. video.user .. ', accessed ' .. video.accessed .. ')</li>\n'
end
videosSection = videosSection .. '</ul></td></tr>\n'
end
local row = "|-\n| style=\"background-color:#f2f2f2;\" | " .. displayTitle .. button .. " || style=\"background-color:#f2f2f2;\" | " .. typeDescription .. "\n"
row = row .. videosSection
return row
end
function p.renderCollapsibleTable(frame)
local data, err = fetchData()
if not data then
return '<div class="error">Error: ' .. err .. '</div>'
end
local wikitable = '{| class="wikitable"\n|-\n! Song Title !! Type\n'
local count = 0
local currentLetter = ""
local alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
local alphabetIndex = 1
local lastRelevantLetter = ""
for index, song in ipairs(data) do
local firstLetter = mw.ustring.upper(mw.ustring.gsub(mw.ustring.sub(song.title, 1, 1), "%W", ""))
local relevantLetter = mw.ustring.match(song.title, "%w") or ""
relevantLetter = mw.ustring.upper(relevantLetter)
-- Skip titles starting with a digit
if not mw.ustring.match(firstLetter, "%d") then
while alphabetIndex <= #alphabet and alphabet:sub(alphabetIndex, alphabetIndex) < firstLetter do
wikitable = wikitable .. '|-\n| colspan="2" style="text-align:center;" | {{a|' .. alphabet:sub(alphabetIndex, alphabetIndex) .. '|}}\n'
alphabetIndex = alphabetIndex + 1
end
if relevantLetter ~= lastRelevantLetter and mw.ustring.match(relevantLetter, "%a") then
currentLetter = relevantLetter
wikitable = wikitable .. '|-\n| colspan="2" style="text-align:center;" | {{a|' .. currentLetter .. '}}\n'
lastRelevantLetter = relevantLetter
alphabetIndex = alphabetIndex + 1
end
end
if song.type ~= "redirect" then
count = count + 1
end
wikitable = wikitable .. generateCollapsibleTableRow(song, index, count)
end
while alphabetIndex <= #alphabet do
wikitable = wikitable .. '|-\n| colspan="2" style="text-align:center;" | {{a|' .. alphabet:sub(alphabetIndex, alphabetIndex) .. '|}}\n'
alphabetIndex = alphabetIndex + 1
end
wikitable = wikitable .. "|}"
return frame:preprocess(wikitable)
end
return p