add rating input |
set default for input-length-trigger (1) |
||
| (7 tussenliggende versies door dezelfde gebruiker niet weergegeven) | |||
| Regel 3: | Regel 3: | ||
--local frame = mw.getCurrentFrame() | --local frame = mw.getCurrentFrame() | ||
--[[ | |||
@name string | |||
@attributes table | |||
@val string|nil | |||
]]-- | |||
p.createTextInput = function( name, attributes, val ) | p.createTextInput = function( name, attributes, val ) | ||
attributes["type"] = "text" | attributes["type"] = "text" | ||
| Regel 9: | Regel 14: | ||
attributes['class'] = attributes['class'] or "form-control" | attributes['class'] = attributes['class'] or "form-control" | ||
if val ~= nil then | if val ~= nil then | ||
attributes['value'] = mw.text.trim(val) | -- 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 | end | ||
local res = mw.text.tag( "_input", attributes, false ) | local res = mw.text.tag( "_input", attributes, false ) | ||
| Regel 18: | Regel 25: | ||
Almost identical to createTextInput | Almost identical to createTextInput | ||
]]-- | ]]-- | ||
p.createNumberInput = function( name, attributes, val ) | p.createNumberInput = function( name, attributes, val ) | ||
attributes["type"] = "number" | attributes["type"] = "number" | ||
| Regel 71: | Regel 77: | ||
local textareaStr = "<textarea " .. attrStr .. ">" .. content .. "</textarea>" | local textareaStr = "<textarea " .. attrStr .. ">" .. content .. "</textarea>" | ||
]]-- | ]]-- | ||
-- output | |||
local textarea = mw.text.tag( 'textarea', attributes, content ) | local textarea = mw.text.tag( 'textarea', attributes, content ) | ||
local div = mw.text.tag( 'div', { class = "grow-wrap" }, textarea ) | 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 | end | ||
| Regel 86: | Regel 98: | ||
]]-- | ]]-- | ||
p.createTokenField = function( name, attributes, selectedvalues, options ) | p.createTokenField = function( name, attributes, selectedvalues, options ) | ||
nameWithoutBrackets = string.gsub( attributes.name, "%[%]", "" ) | local nameWithoutBrackets = string.gsub( attributes.name, "%[%]", "" ) | ||
attributes.name = nameWithoutBrackets .. "[]" | attributes.name = nameWithoutBrackets .. "[]" | ||
-- @todo make default class Boottrap-independent | -- @todo make default class Boottrap-independent | ||
| Regel 92: | 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" | |||
optionFields = "" | local optionFields = "" | ||
if ( attributes.query ~= nil and attributes.query ~= "" ) then | if ( attributes.query ~= nil and attributes.query ~= "" ) then | ||
-- version1: use query | -- version1: use query | ||
| Regel 127: | Regel 141: | ||
local nameWithoutBrackets = string.gsub( attributes.name, "%[%]", "" ) | local nameWithoutBrackets = string.gsub( attributes.name, "%[%]", "" ) | ||
attributes.name = nameWithoutBrackets | attributes.name = nameWithoutBrackets | ||
attributes['class'] = attributes['class'] or "form-control" | |||
local optionFields = p.createOptionsFromOptionsTable( | local optionFields = p.createOptionsFromOptionsTable( | ||
selectedvalues, | selectedvalues, | ||
| Regel 175: | Regel 190: | ||
end | end | ||
return | 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 | end | ||
| Regel 233: | Regel 256: | ||
--[[ | --[[ | ||
Dedicated input for ratings | Dedicated input for ratings, adapted from Template:Wsrating | ||
@name string - input name | @name string - input name | ||
@selectedVal string - selected value if any | @selectedVal string - selected value if any | ||
| Regel 245: | Regel 265: | ||
@cancelTitle | @cancelTitle | ||
@static | @static | ||
]]-- | ]]-- | ||
p.createRatingField = function( name, selectedVal, steps, starLabel, starsLabel, isCancellable, cancelTitle, static ) | p.createRatingField = function( name, selectedVal, steps, starLabel, starsLabel, isCancellable, cancelTitle, static ) | ||
local name = | 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 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 star = starLabel or "ster" | ||
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
