Semantic MediaWikiDit bericht verdwijnt nadat alle relevante taken zijn afgerond.

Er is één onvoltooide of openstaande taak, die nodig is om het bijwerken van Semantic MediaWiki te voltooien. Een beheerder of gebruiker met voldoende rechten kan deze uitvoeren. Dit moet worden gedaan voordat nieuwe gegevens worden toegevoegd om tegenstrijdigheden te voorkomen.

Geen bewerkingssamenvatting
set default for input-length-trigger (1)
 
Regel 104: Regel 104:
-- make sure tokens come with unique ids
-- make sure tokens come with unique ids
attributes.id = attributes.id or "tokener-" .. tostring( math.random(100000,999999) )
attributes.id = attributes.id or "tokener-" .. tostring( math.random(100000,999999) )
-- 1 is the preferred default on Fandata
attributes["input-length-trigger"] = attributes["input-length-trigger"] or "1"


local optionFields = ""
local optionFields = ""

Huidige versie van 1 sep 2025 09:45

Documentatie voor deze module kan aangemaakt worden op de volgende pagina: Module:FFInput/doc

local p = {}

--local frame = mw.getCurrentFrame()

--[[
@name string
@attributes table
@val string|nil
]]--
p.createTextInput = function( name, attributes, val )
	attributes["type"] = "text"
	attributes['name'] = name
	-- @todo Bootstrap-independent default class
	attributes['class'] = attributes['class'] or "form-control"
	if val ~= nil then
		-- Is mw.text.encode enough to ensure 'val' is safe with quotes?
		-- cf. Template:Format for WSForm
		attributes['value'] = mw.text.encode( mw.text.trim(val) )
	end
	local res = mw.text.tag( "_input", attributes, false )
	return res
end

--[[
Almost identical to createTextInput
]]--
p.createNumberInput = function( name, attributes, val )
	attributes["type"] = "number"
	attributes['name'] = name
	-- @todo Bootstrap-independent default class
	attributes['class'] = attributes['class'] or "form-control"
	if val ~= nil then
		attributes['value'] = mw.text.trim(val)
	end
	local res = mw.text.tag( "_input", attributes, false )
	return res
end

--[[
@name string
@attributes table
@val string|nil
]]--
p.createDateInput = function( name, attributes, val )
	attributes["type"] = "date"
	attributes["name"] = name
	if val ~= nil then
		attributes["value"] = mw.text.trim(val)
	end
	return mw.text.tag( '_input', attributes, false )
end

--[[
@name
@attributes
@content string|table |?nil
]]--
p.createTextarea = function( name, attributes, content )
	--attributes.name = name
	if ( type(content) == "table" ) then
		-- todo shouldn't be happening
		content = table.concat(content,",")
	end
	-- prevent expansion
	-- mw.log( 'content for textarea: ' .. content )
	content = mw.text.nowiki( content or "" )
	-- nowiki converted \r to 
 - remove from the output 
	content = string.gsub( content, "
", "" )
	--test!

	--[[ alternative with same outcome: string things together ourselves
	attrStr = ""
	for k,v in pairs(attributes) do
		attr = k .. '="' .. v .. '" '
		attrStr = attrStr .. attr
	end
	local textareaStr = "<textarea " .. attrStr .. ">" .. content .. "</textarea>"
	]]--

	-- output
	local textarea = mw.text.tag( 'textarea', attributes, content )
	if ( attributes["editor"] ~= nil and attributes["editor"] == "ve" ) then
		return textarea
	else
		local div = mw.text.tag( 'div', { class = "grow-wrap" }, textarea )
		return div
	end
end

--[[
version1: use query 
version2: use options

@name string
@attributes table
@selectedvalues string|table|nil
@options table|nil
]]--
p.createTokenField = function( name, attributes, selectedvalues, options )
	local nameWithoutBrackets = string.gsub( attributes.name, "%[%]", "" )
	attributes.name = nameWithoutBrackets .. "[]"
	-- @todo make default class Boottrap-independent
	attributes.class = attributes.class or "w-100"
	-- make sure tokens come with unique ids
	attributes.id = attributes.id or "tokener-" .. tostring( math.random(100000,999999) )
	-- 1 is the preferred default on Fandata
	attributes["input-length-trigger"] = attributes["input-length-trigger"] or "1"

	local optionFields = ""
	if ( attributes.query ~= nil and attributes.query ~= "" ) then
		-- version1: use query
		optionFields = p.createOptions(
			selectedvalues,
			attributes.separator or ",",
			attributes.returntext or "",
			nameWithoutBrackets
		)
	else
		-- version2: use options
		--test @todo
		optionFields = p.createOptionsFromOptionsTable(
			selectedvalues,
			attributes.separator or ",",
			options or {},
			nameWithoutBrackets
		)
	end

	local forminput = mw.text.tag( '_token', attributes, optionFields )
	return forminput
end

--[[
@name
@attributes, 
@selectedvalues string|table|nil
@options 
]]--
p.createSelectField = function( name, attributes, selectedvalues, options )
	-- make sure select doesn't use brackets
	local nameWithoutBrackets = string.gsub( attributes.name, "%[%]", "" )
	attributes.name = nameWithoutBrackets
	attributes['class'] = attributes['class'] or "form-control"
	local optionFields = p.createOptionsFromOptionsTable(
		selectedvalues,
		attributes.separator or ",",
		options or {},
		nameWithoutBrackets
	)
	--mw.log( "createSelectField, selectedvalues: " .. selectedvalues or "no selected values" )
	return mw.text.tag( 'select', attributes, optionFields )
end

--[[
@checkType string - "checkbox" or "radio"
@name string
@attributes table
@selectedvalues string|table|nil
@options table|nil
]]--
p.createCheckInputField = function( checkType, name, attributes, selectedvalues, options )
	nameWithoutBrackets = string.gsub( attributes.name, "%[%]", "" )
	--attributes.name = nameWithoutBrackets .. "[]"
	selectedValTbl = p.getSelectedValuesTable( selectedvalues, attributes.sep or "," )
	options = options or nil
	
	checkInputs = ""
	showOnChecked = nil
	showOnUnchecked = nil
	for k,val in ipairs( options ) do
		local id = p.createId( name, k )
		if type(val) == "string" then
			valVal = val
			valLabel = val
		elseif type(val) == "table" then
			valVal = mw.text.trim( val["value"] or "" )
			valLabel = mw.text.trim( val["label"] or "" )
			-- Show on select options
			if val["show-on-checked"] ~= nil then showOnChecked = val["show-on-checked"] end
			if val["show-on-unchecked"] ~= nil then showOnUnchecked = val["show-on-unchecked"] end
		end
		isChecked = nil
		for _,sv in ipairs(selectedValTbl) do
			if sv == valVal then isChecked = "checked" end
		end
		checkInputs = checkInputs .. p.createCheckInput( checkType, valVal, isChecked, id, name, valLabel, showOnChecked or nil, showOnUnchecked or nil )
		-- reset
		showOnChecked = nil
		showOnUnchecked = nil
	end

	local res = ""
	if ( checkType == "checkbox" ) then
		-- wrapper
		res = mw.text.tag( "div", { class = "ff-checkboxes" }, checkInputs )
	else
		-- @todo consider a wrapper for radio buttons, e.g. generic ff-check-inputs for both
		res = checkInputs
	end
	return res
end

--[[
@checkType string either "checkbox" or "radio"
@val string|nil
@isChecked string|nil
@id string
@name string
@labelName string
@showOnChecked string|nil - option for ShowOnSelect
@showOnUnchecked string|nil - option for ShowOnSelect
]]--
p.createCheckInput = function( checkType, val, isChecked, id, name, labelName, showOnChecked, showOnUnchecked )
	-- create input
	local args = { ["type"] = checkType, checked = isChecked, name = name, id = id }
	if val ~= nil then args["value"] = val end
	if isChecked ~= nil then args.checked = isChecked end
	showOnChecked = showOnChecked or nil
	if showOnChecked ~= nil then args["show-on-checked"] = showOnChecked end
	if showOnUnchecked ~= nil then args["show-on-unchecked"] = showOnUnchecked end
	local checkInput = mw.text.tag( '_input', args, "" )
	--mw.log( "checkInput: " .. checkInput .. "; ")

	-- create label
	local labelArgs = {}
	labelArgs["for"] = id -- 'for' has special meaning
	local labelInput = mw.text.tag( 'label', labelArgs, labelName )

	local res = '<span class="ff-labelled-input">' .. checkInput .. labelInput .. '</span>'
	return res
end
	
--[[
Accept a delimited string of values and return option inputs as concatenated string
@values string|table|nil
@sep
@displayprop 
@inputname
]]--
p.createOptions = function( values, sep, displayprop, inputname )
	valTbl = p.getSelectedValuesTable( values, sep or "," )

	str = ''
	for k, val in ipairs( valTbl ) do
		local label = p.smwgetlabel( val, displayprop ) or val
		local inputTbl = {
			['type'] = 'option',
			['value'] = mw.text.trim( val ),
			['selected'] = 'selected'
	    }
	    local optionInput = mw.text.tag( '_input', inputTbl, label )
		str = str .. optionInput
	end
	return str
end

--[[
Dedicated input for ratings, adapted from Template:Wsrating
@name string - input name
@selectedVal string - selected value if any
@steps string - semi-colon-delimited string
@starLabel
@starsLabel
@isCancellable
@cancelTitle
@static 
]]--
p.createRatingField = function( name, selectedVal, steps, starLabel, starsLabel, isCancellable, cancelTitle, static )
	local name = name or "rating"
	local steps = steps or "10;9.5;9;8.5;8;7.5;7;6.5;6;5.5;5;4.5;4;3.5;3;2.5;2;1.5;1;0.5"
	local star = starLabel or "ster"
	local stars = starsLabel or "sterren"
	local checked = selectedVal or ""
	local cancellable = isCancellable or "false"
	local cancelTitle = cancelTitle or "Annuleren"
	local static = static or "false"

	-- create radio inputs with labels
	local stepSequence = mw.text.split( steps, ";" )
	local checkInputs = ""
	for i,step in ipairs(stepSequence) do
		local id = name .. "-"  .. string.gsub(step, "%.", "-") --{{{name|rating}}}-{{#var:@numericid}}
		local isChecked = ""
		if ( step == checked ) then isChecked = "checked" end
		local class = ""
		-- eg 9.5 sterren, 1 ster
		local title = step .. " "
		if ( step == "1" or step == "0.5" ) then title = title .. star else title = title .. stars end
		local labelClass = "ws-star half"
		if string.find(step, ".5") == nil then
			labelClass = "ws-star whole"
		end
		checkInputs = checkInputs .. p.createRatingCheckInput( "radio", step, isChecked, id, name, "", labelClass, title )
	end
	
	-- optionally add a radio input for cancelling value (= no value)
	local cancelInput = ""
	if cancellable == "true" then
		cancelId = name .. "-cancel"
		cancelClass = "ws-cancel-stars"
		checkInputs = checkInputs .. p.createRatingCheckInput( "radio", "", "", cancelId, name, "", cancelClass, cancelTitle )
	end

	-- wrap everything in fieldset and div container
	local fieldsetClass = { class = "rate", enabled = "enabled" }
	if ( static == "true" ) then fieldsetClass["disabled"] = "disabled" end
	local fieldset = mw.text.tag(
		"fieldset",
		fieldsetClass,
		checkInputs
	)
	local res = mw.text.tag( "div", { class = "ws-star-ratings" }, fieldset )
	
	return res
	--return frame:preprocess(res)
end

p.createRatingCheckInput = function( checkType, val, isChecked, id, name, labelName, labelClass, title, showOnChecked, showOnUnchecked )
	-- (1) create input
	local args = { ["type"] = checkType, name = name, id = id }
	if val ~= nil then args["value"] = val end
	if isChecked ~= nil then args.checked = isChecked end
	
	-- currently unused but may be helpful if additional visuals are needed
	local showOnChecked = showOnChecked or nil
	if showOnChecked ~= nil then args["show-on-checked"] = showOnChecked end
	if showOnUnchecked ~= nil then args["show-on-unchecked"] = showOnUnchecked end
	
	local checkInput = mw.text.tag( '_input', args, "" )

	-- (2) create label
	local labelArgs = { class = labelClass, title = title, ["for"] = id }
	local labelInput = mw.text.tag( "label", labelArgs, labelName )

	-- (3) Join and return
	local res = checkInput .. labelInput
	return res
end

--[[
Used for selects and tokens
	@todo - allow for optgroups with selects
@selectedvalues - string|table|nil
@sep string
@options table
@inputname string
]]--
p.createOptionsFromOptionsTable = function( selectedvalues, sep, options, inputname )
	selectedvalTbl = p.getSelectedValuesTable( selectedvalues, sep or "," )

	local options = options or {}
	local str = ""
	for _,val in ipairs( options ) do
		local inputAttributes = {}
		-- todo label stuff
		local valLabel = ""
		-- going for text values
		if type(val) == "string" then
			-- values with identical labels
			local val = mw.text.trim( val )
			-- 	local label = p.smwgetlabel( val, displayprop ) or val
			inputAttributes = {
				['type'] = 'option',
				['value'] = val
			}
			valLabel = val
			-- check if value matches selected value
			for _,optionv in ipairs( selectedvalTbl ) do
				if optionv == val then
					inputAttributes.selected = "selected"
				end
			end
		elseif type(val) == "table" then
			-- values and distinct labels
			inputAttributes["type"] = "option"
			-- copy read-only
			for k,v in pairs( val ) do inputAttributes[k] = v end
			-- do we still need to add type?
			inputAttributes["label"] = nil
			local valVal = mw.text.trim( val["value"] or "" )
			inputAttributes["value"] = valVal
			valLabel = mw.text.trim( val["label"] or "" )
			for _,optionv in ipairs( selectedvalTbl ) do
				if optionv == valVal then
					inputAttributes.selected = "selected"
				end
			end
		else
			--str = str .. "(not a string)"
		end

	    local optionInput = mw.text.tag( 'option', inputAttributes, valLabel )
		str = str .. optionInput
	end
	return str
end

p.smwgetlabel = function( pagename, propname )
	if ( propname == nil ) then
		return pagename
	end
	if not mw.smw then
        return "mw.smw module not found"
	end
	
	local qarg = "[[" .. pagename .. "]][[Modification date::+]]|?" .. propname .. "=title|link=none"
	local qres = mw.smw.ask( qarg )
	
	local res = ''
	if ( qres ~= nil ) then
		label = qres[1].title or ''
	end
	
	return label
end

--[[
Create unique lowercase identifier
]]--
p.createId = function( name, indx )
	name = string.gsub( name, " ", "-" )
	if indx == nil then
		indx = tostring( math.random(100000,999999) )
	end
	local idName = 'ff-' .. string.gsub( name, "%[%]", "" )
	local idName = string.lower( idName )
	-- @todo maybe replace any spaces from the name, too
	return idName .. "-" .. indx
end

p.getSelectedValuesTable = function( values, sep )
	newValues = {}
	if type(values) == "table" then
		newValues = values
	elseif values ~= nil and values ~= "" then
		newValues = mw.text.split( values, sep )
	end
	return p.encodeValuesTable( newValues )
end

--[[
@vals table
Primarily because apostrophes may be a problem
]]--
p.encodeValuesTable = function( vals )
	local newVals = {}
	for _,v in ipairs(vals) do
		table.insert( newVals, mw.text.encode(v) ) 
	end
	return newVals
end

return p