Misplaced Pages

Module:Track listing: Difference between revisions

Article snapshot taken from Wikipedia with creative commons attribution-sharealike license. Give it a read and then ask your questions in the chat. We can research this topic together.
Browse history interactively← Previous editNext edit →Content deleted Content added
Revision as of 05:36, 23 October 2015 view sourceMr. Stradivarius (talk | contribs)Edit filter managers, Administrators59,192 edits fix call to Track:exportRow← Previous edit Revision as of 03:50, 26 October 2015 view source Mr. Stradivarius (talk | contribs)Edit filter managers, Administrators59,192 edits more work on TrackListing:__tostringNext edit →
Line 156: Line 156:
self = data self = data
end end
-- Evaluate boolean properties
self.collapsed = yesno(self.collapsed, false)


-- Make track objects -- Make track objects
Line 204: Line 207:


return self return self
end

function TrackListing:makeIntro()
local ret = ''
if self.all_writing then
ret = ret .. string.format(
'All songs written and composed by %s. ',
self.all_writing
)
else
if self.all_lyrics then
ret = ret .. 'All lyrics written by ' .. self.all_lyrics
if self.all_music then
ret = ret .. ','
else
ret = ret .. '.'
end
ret = ret .. ' '
end
if self.all_music then
if self.all_lyrics then
ret = ret .. 'All'
else
ret = ret .. 'all'
end
ret = ret .. ' music composed by ' .. self.all_music .. '.'
end
end
return ret
end end


function TrackListing:__tostring() function TrackListing:__tostring()
local root = mw.html.create('table') local root = mw.html.create()

-- Find columns to output
local columns = {'number', 'title'} local columns = {'number', 'title'}
if self.optionalColumns.writer then if self.optionalColumns.writer then
Line 218: Line 252:
columns = 'music' columns = 'music'
end end
end
if self.optionalColumns.extra then
columns = 'extra'
end end
columns = 'length' columns = 'length'


-- Find number of columns
local nColumns = #columns

-- Intro
root:node(self:makeIntro())

-- Start table
local tableRoot = root:tag('table')
tableRoot
:addClass('tracklist')
:addClass(self.collapsed and 'collapsible collapsed' or nil)
:css('display', 'block')
:css('border-spacing', '0px')
:css('border-collapse', 'collapse')
:css('border', self.collapsed and '#aaa 1px solid' or nil)
:css('padding', self.collapsed and '3px' or '4px')

-- Headline
if self.headline then
tableRoot:tag('tr'):tag('th')
:addClass('tlheader mbox-text')
:attr('colspan', nColumns)
:css('text-align', 'left')
:css('background-color', '#fff')
:wikitext(self.headline)
end

-- Header row for collapsed track listings
if self.collapsed then
tableRoot:tag('tr'):tag('th')
:addClass('tlheader mbox-text')
:attr('colspan', nColumns)
:css('text-align', 'left')
:css('background-color', '#fff')
:wikitext('Track listing')
end

-- Headers
local headerRow = tableRoot:tag('tr')
local titleColumnWidth, optionalColumnWidth
if nColumns >= 6 then
titleColumnWidth = '40%'
optionalColumnWidth = '20%'
elseif nColumns >= 5 then
titleColumnWidth = '40%'
optionalColumnWidth = '30%'
elseif nColumns >= 4 then
titleColumnWidth = '60%'
optionalColumnWidth = '40%'
else
-- If there are three
titleColumnWidth = '100%'
end

--- Track number
headerRow
:tag('th')
:addClass('tlheader')
:attr('scope', 'col')
:css('width', '2em')
:css('padding-left', '10px')
:css('padding-right', '10px')
:css('text-align', 'right')
:css('background-color', '#eee')
:wikitext('No.')

--- Title
headerRow:tag('th')
:addClass('tlheader')
:attr('scope', 'col')
:css('width', titleColumnWidth)
:css('text-align', 'left')
:css('background-color', '#eee')
:wikitext('Title')
-- Writer
if self.optionalColumns.writer then
headerRow
:tag('th')
:addClass('tlheader')
:attr('scope', 'col')
:css('width', optionalColumnWidth)
:css('text-align', 'left')
:css('background-color', '#eee')
:wikitext('Writer(s)')
end
for i, track in ipairs(self.tracks) do for i, track in ipairs(self.tracks) do
root:node(track:exportRow({columns = columns})) root:node(track:exportRow({columns = columns}))

Revision as of 03:50, 26 October 2015

Module documentation[view] [edit] [history] [purge]
WarningThis Lua module is used on approximately 114,000 pages.
To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own module sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them.
CSSThis module uses TemplateStyles:
This module depends on the following other modules:
This module is used by one or more bots.
If you intend to make significant changes to this module, move it, or nominate it for deletion, please notify the bot operator(s) in advance. The relevant bots are: User:cewbot/log/20201008/configuration.

This module implements {{track listing}}. Please see the template page for documentation.

The above documentation is transcluded from Module:Track listing/doc. (edit | history)
Editors can experiment in this module's sandbox (edit | diff) and testcases (create) pages.
Subpages of this module.

-- This module implements ]

local yesno = require('Module:Yesno')

--------------------------------------------------------------------------------
-- Track class
--------------------------------------------------------------------------------

local Track = {}
Track.__index = Track

Track.fields = {
	number = true,
	title = true,
	note = true,
	length = true,
	lyrics = true,
	music = true,
	writer = true,
	extra = true,
}

Track.cellMethods = {
	number = 'makeNumberCell',
	title = 'makeTitleCell',
	writer = 'makeWriterCell',
	lyrics = 'makeLyricsCell',
	music = 'makeMusicCell',
	extra = 'makeExtraCell',
	length = 'makeLengthCell',
}

function Track.new(data)
	local self = setmetatable({}, Track)
	for field in pairs(Track.fields) do
		self = data
	end
	self.number = assert(tonumber(self.number))
	return self
end

function Track:getLyricsCredit()
	return self.lyrics
end

function Track:getMusicCredit()
	return self.music
end

function Track:getWriterCredit()
	return self.writer
end

function Track:getExtraField()
	return self.extra
end

-- Note: called with single dot syntax
function Track.makeSimpleCell(wikitext)
	return mw.html.create('td')
		:css('vertical-align', 'top')
		:wikitext(wikitext or ' ')
end

function Track:makeNumberCell()
	return mw.html.create('td')
		:css('padding-right', '10px')
		:css('text-align', 'right')
		:css('vertical-align', 'top')
		:wikitext(self.number .. '.')
end

function Track:makeTitleCell()
	local titleCell = mw.html.create('td')
	titleCell
		:css('text-align', 'left')
		:css('vertical-align', 'top')
		:wikitext(self.title and string.format('"%s"', self.title) or 'Untitled')
		:wikitext(' ')
	if self.note then
		titleCell:tag('span')
			:css('font-size', '85%')
			:wikitext(string.format('(%s)', self.note))
	else
		titleCell:wikitext(' ')
	end
	return titleCell
end

function Track:makeWriterCell()
	return Track.makeSimpleCell(self.writer)
end

function Track:makeLyricsCell()
	return Track.makeSimpleCell(self.lyrics)
end

function Track:makeMusicCell()
	return Track.makeSimpleCell(self.music)
end

function Track:makeExtraCell()
	return Track.makeSimpleCell(self.extra)
end

function Track:makeLengthCell()
	return mw.html.create('td')
		:css('padding-right', '10px')
		:css('text-align', 'right')
		:css('vertical-align', 'top')
		:wikitext(self.length or ' ')
end

function Track:exportRow(options)
	options = options or {}
	local columns = options.columns or {}
	local row = mw.html.create('tr')
	row:css('background-color', options.color or '#fff')
	for i, column in ipairs(columns) do
		local method = Track.cellMethods
		if method then
			row:node(self(self))
		end
	end
	return row
end

--------------------------------------------------------------------------------
-- TrackListing class
--------------------------------------------------------------------------------

local TrackListing = {}
TrackListing.__index = TrackListing

TrackListing.fields = {
	all_writing = true,
	all_lyrics = true,
	all_music = true,
	collapsed = true,
	headline = true,
	extra_column = true,
	total_length = true,
}

TrackListing.deprecatedFields = {
	writing_credits = true,
	lyrics_credits = true,
	music_credits = true,
}

function TrackListing.new(data)
	local self = setmetatable({}, TrackListing)

	-- Add properties
	for field in pairs(TrackListing.fields) do
		self = data
	end
	
	-- Evaluate boolean properties
	self.collapsed = yesno(self.collapsed, false)

	-- Make track objects
	self.tracks = {}
	for i, trackData in ipairs(data.tracks or {}) do
		table.insert(self.tracks, Track.new(trackData))
	end

	-- Find which of the optional columns we have.
	-- We could just check every column for every track object, but that would
	-- be no fun^H^H^H^H^H^H inefficient, so we use four different strategies
	-- to try and check only as many columns and track objects as necessary.
	do
		local optionalColumns = {}
		local columnMethods = {
			lyrics = 'getLyricsCredit',
			music = 'getMusicCredit',
			writer = 'getWriterCredit',
			extra = 'getExtraField',
		}
		local doneWriterCheck = false
		for i, trackObj in ipairs(self.tracks) do
			for column, method in pairs(columnMethods) do
				if trackObj(trackObj) then
					optionalColumns = true
					columnMethods = nil
				end
			end
			if not doneWriterCheck and optionalColumns.writer then
				doneWriterCheck = true
				optionalColumns.lyrics = nil
				optionalColumns.music = nil
				columnMethods.lyrics = nil
				columnMethods.music = nil
			end
			if not next(columnMethods) then
				break
			end
		end
		self.optionalColumns = optionalColumns
	end

	-- Count the number of optional columns.
	self.nOptionalColumns = 0
	for k in pairs(self.optionalColumns) do
		self.nOptionalColumns = self.nOptionalColumns + 1
	end

	return self
end

function TrackListing:makeIntro()
	local ret = ''
	if self.all_writing then
		ret = ret .. string.format(
			'All songs written and composed by %s. ',
			self.all_writing
		)
	else
		if self.all_lyrics then
			ret = ret .. 'All lyrics written by ' .. self.all_lyrics
			if self.all_music then
				ret = ret .. ','
			else
				ret = ret .. '.'
			end
			ret = ret .. ' '
		end
		if self.all_music then
			if self.all_lyrics then
				ret = ret .. 'All'
			else
				ret = ret .. 'all'
			end
			ret = ret .. ' music composed by ' .. self.all_music .. '.'
		end
	end
	return ret
end

function TrackListing:__tostring()
	local root = mw.html.create()

	-- Find columns to output
	local columns = {'number', 'title'}
	if self.optionalColumns.writer then
		columns = 'writer'
	else
		if self.optionalColumns.lyrics then
			columns = 'lyrics'
		end
		if self.optionalColumns.music then
			columns = 'music'
		end
	end
	if self.optionalColumns.extra then
		columns = 'extra'
	end
	columns = 'length'

	-- Find number of columns
	local nColumns = #columns

	-- Intro
	root:node(self:makeIntro())

	-- Start table
	local tableRoot = root:tag('table')
	tableRoot
		:addClass('tracklist')
		:addClass(self.collapsed and 'collapsible collapsed' or nil)
		:css('display', 'block')
		:css('border-spacing', '0px')
		:css('border-collapse', 'collapse')
		:css('border', self.collapsed and '#aaa 1px solid' or nil)
		:css('padding', self.collapsed and '3px' or '4px')

	-- Headline
	if self.headline then
		tableRoot:tag('tr'):tag('th')
			:addClass('tlheader mbox-text')
			:attr('colspan', nColumns)
			:css('text-align', 'left')
			:css('background-color', '#fff')
			:wikitext(self.headline)
	end

	-- Header row for collapsed track listings
	if self.collapsed then
		tableRoot:tag('tr'):tag('th')
			:addClass('tlheader mbox-text')
			:attr('colspan', nColumns)
			:css('text-align', 'left')
			:css('background-color', '#fff')
			:wikitext('Track listing')
	end		

	-- Headers
	local headerRow = tableRoot:tag('tr')
	local titleColumnWidth, optionalColumnWidth
	if nColumns >= 6 then
		titleColumnWidth = '40%'
		optionalColumnWidth = '20%'
	elseif nColumns >= 5 then
		titleColumnWidth = '40%'
		optionalColumnWidth = '30%'
	elseif nColumns >= 4 then
		titleColumnWidth = '60%'
		optionalColumnWidth = '40%'
	else
		-- If there are three
		titleColumnWidth = '100%'
	end

	--- Track number
	headerRow
		:tag('th')
			:addClass('tlheader')
			:attr('scope', 'col')
			:css('width', '2em')
			:css('padding-left', '10px')
			:css('padding-right', '10px')
			:css('text-align', 'right')
			:css('background-color', '#eee')
			:wikitext('No.')

	--- Title
	headerRow:tag('th')
		:addClass('tlheader')
		:attr('scope', 'col')
		:css('width', titleColumnWidth)
		:css('text-align', 'left')
		:css('background-color', '#eee')
		:wikitext('Title')	
	
	-- Writer
	if self.optionalColumns.writer then
		headerRow
			:tag('th')
				:addClass('tlheader')
				:attr('scope', 'col')
				:css('width', optionalColumnWidth)
				:css('text-align', 'left')
				:css('background-color', '#eee')
				:wikitext('Writer(s)')
	end
	
	for i, track in ipairs(self.tracks) do
		root:node(track:exportRow({columns = columns}))
	end
	
	return tostring(root)
end

--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------

local p = {}

function p._main(args)
	-- Process numerical args so that we can iterate through them.
	local data, tracks = {}, {}
	for k, v in pairs(args) do
		if type(k) == 'string' then
			local prefix, num = k:match('^(%D.-)(%d+)$')
			if prefix and Track.fields and (num == '0' or num:sub(1, 1) ~= '0') then
				-- Allow numbers like 0, 1, 2 ..., but not 00, 01, 02...,
				-- 000, 001, 002... etc.
				num = tonumber(num)
				tracks = tracks or {}
				tracks = v
			else
				data = v
			end
		end
	end
	data.tracks = (function (t)
		-- Compress sparse array
		local ret = {}
		for num, trackData in pairs(t) do
			trackData.number = num
			table.insert(ret, trackData) 
		end
		table.sort(ret, function (t1, t2)
			return t1.number < t2.number
		end)
		return ret
	end)(tracks)

	return tostring(TrackListing.new(data))
end

function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame, {
		wrappers = 'Template:Track listing'
	})
	return p._main(args)
end

return p
Category: