Module:Probox and Module:Probox/sandbox: Difference between pages
(Difference between pages)
imported>Uzume Update from master using Synchronizer #synchronizer |
imported>Prahlad balaji Create sandbox version of Module:Probox |
||
| Line 6: | Line 6: | ||
local p = {} | local p = {} | ||
function addTemplates(frame, data, args) | |||
-- adds additional template to the top of the page, above the infobox | -- adds additional template to the top of the page, above the infobox | ||
local page_template | local page_template | ||
-- local tmplt_args = {} | -- local tmplt_args = {} | ||
local template_div = mw.html.create('div') | local template_div = mw.html.create('div') | ||
for k,v in pairs(data.templates) do -- if there is a matching arg, and it has a table of template possibilities | for k,v in pairs(data.templates) do -- if there is a matching arg, and it has a table of template possibilities | ||
if (args[k] and string.len(args[k]) > 0 and type(data.templates[k]) == "table") then --convert args to lowercase before checking them against cats | if (args[k] and string.len(args[k]) > 0 and type(data.templates[k]) == "table") then --convert args to lowercase before checking them against cats | ||
| Line 37: | Line 19: | ||
:wikitext(frame:expandTemplate{title=data.templates[k][tmplt_key], args={status = stringFirstCharToUpper(args[k])}}) --status is special casing. need to pass generic arg keys | :wikitext(frame:expandTemplate{title=data.templates[k][tmplt_key], args={status = stringFirstCharToUpper(args[k])}}) --status is special casing. need to pass generic arg keys | ||
:done() | :done() | ||
break | break | ||
elseif (stringToLowerCase(args[k]) == tmplt_key and mw.title.new("Template:" .. tmplt_val).exists) then | elseif (stringToLowerCase(args[k]) == tmplt_key and mw.title.new("Template:" .. tmplt_val).exists) then | ||
template_div | template_div | ||
| Line 48: | Line 30: | ||
-- if (type(tmplt_val) == "string" and stringToLowerCase(args[k]) == tmplt_key and mw.title.new("Template:" .. tmplt_val).exists) then | -- if (type(tmplt_val) == "string" and stringToLowerCase(args[k]) == tmplt_key and mw.title.new("Template:" .. tmplt_val).exists) then | ||
end | end | ||
end | end | ||
end | end | ||
page_template = tostring(template_div) | page_template = tostring(template_div) | ||
return page_template | return page_template | ||
end | end | ||
function addCategories(data, args, open_roles) | |||
-- will also look for numbered categories | -- will also look for numbered categories | ||
local cat_list = {} | local cat_list = {} | ||
| Line 63: | Line 45: | ||
if data.categories.default then | if data.categories.default then | ||
table.insert(cat_list, data.categories.default) | table.insert(cat_list, data.categories.default) | ||
end | end | ||
if data.categories.roles then | if data.categories.roles then | ||
role_cat = data.categories.roles | role_cat = data.categories.roles | ||
| Line 83: | Line 65: | ||
end | end | ||
end | end | ||
end | end | ||
local page_categories = " [[" .. tostring(table.concat(cat_list, "]] [[")) .. "]]" | |||
local | |||
return page_categories | return page_categories | ||
end | |||
function makeTextField(field, field_div) | |||
-- makes a formatted text field for output, based on parameter | -- makes a formatted text field for output, based on parameter | ||
-- values or on default values provided for that field | -- values or on default values provided for that field | ||
| Line 123: | Line 79: | ||
:tag('span') | :tag('span') | ||
:cssText(field.style2)--inconsistent use of styles 2/3 here | :cssText(field.style2)--inconsistent use of styles 2/3 here | ||
:wikitext(field.title)--we probably aren't using this for most things now, after Heather's redesign | :wikitext(field.title)--we probably aren't using this for most things now, after Heather's redesign | ||
:done() | :done() | ||
:tag('span') | :tag('span') | ||
:cssText(field.style3) | :cssText(field.style3) | ||
:wikitext(field.values[1]) | :wikitext(field.values[1]) | ||
:done() | :done() | ||
elseif field.vtype2 == "title" then | elseif field.vtype2 == "title" then | ||
field_div | field_div | ||
| Line 134: | Line 90: | ||
:cssText(field.style3) | :cssText(field.style3) | ||
:wikitext(field.values[1]) | :wikitext(field.values[1]) | ||
:done() | :done() | ||
elseif field.vtype2 == "link" then | elseif field.vtype2 == "link" then | ||
field_div | field_div | ||
:tag('span') | :tag('span') | ||
:cssText(field.style3) | :cssText(field.style3) | ||
:wikitext("[[" .. field.values[1] .. "|<span style='" .. field.style2 .. "'>" .. field.title .."</span>]]") | :wikitext("[[" .. field.values[1] .. "|<span style='" .. field.style2 .. "'>" .. field.title .."</span>]]") | ||
:done() | :done() | ||
| Line 144: | Line 100: | ||
field_div:done() | field_div:done() | ||
return field_div | return field_div | ||
end | end | ||
function makeImageField(field, field_div) | |||
-- makes a formatted image field for output, based on parameter values | -- makes a formatted image field for output, based on parameter values | ||
-- provided in the calling template or its parent template, or on default | -- provided in the calling template or its parent template, or on default | ||
| Line 154: | Line 110: | ||
:tag('span') | :tag('span') | ||
:cssText(field.style3) | :cssText(field.style3) | ||
if field.vtype2 == "thumb" then | if field.vtype2 == "thumb" then | ||
field_div | field_div | ||
:wikitext("[[" .. field.values[1] .. "|right|" .. field.width .."]]") | :wikitext("[[" .. field.values[1] .. "|right|" .. field.width .."]]") | ||
elseif field.vtype2 == "link" then | elseif field.vtype2 == "link" then | ||
field_div | field_div | ||
| Line 167: | Line 120: | ||
field_div | field_div | ||
:wikitext("[[" .. field.icon .. "|" .. field.alignment .. "|" .. field.width .."|link=" .. field.values[1] .. "]] " .. "[" .. field.values[1] .. " " .. field.title .. "]") | :wikitext("[[" .. field.icon .. "|" .. field.alignment .. "|" .. field.width .."|link=" .. field.values[1] .. "]] " .. "[" .. field.values[1] .. " " .. field.title .. "]") | ||
end | end | ||
elseif field.vtype2 == "ui_button" then | elseif field.vtype2 == "ui_button" then | ||
field_div | field_div | ||
:addClass(field.class) | :addClass(field.class) | ||
:wikitext(field.title) | :wikitext(field.title) | ||
:done() | :done() | ||
end | end | ||
field_div:done() | field_div:done() | ||
return field_div | return field_div | ||
end | end | ||
function makeParticipantField(field, ftype) | |||
local field_div = mw.html.create('div') | local field_div = mw.html.create('div') | ||
local title_span | local title_span | ||
| Line 185: | Line 138: | ||
else | else | ||
title_span = field.title | title_span = field.title | ||
end | end | ||
field_div | field_div | ||
:cssText(field.style) | :cssText(field.style) | ||
| Line 206: | Line 159: | ||
else | else | ||
v = "• " .. "[[User:" .. v .. "|" .. v .. "]]" | v = "• " .. "[[User:" .. v .. "|" .. v .. "]]" | ||
end | end | ||
field_div | field_div | ||
:tag('span') | :tag('span') | ||
:cssText(field.style3) | :cssText(field.style3) | ||
:wikitext(v) | :wikitext(v) | ||
-- :wikitext("• " .. "[[User:" .. v .. "|" .. v .. "]]") | -- :wikitext("• " .. "[[User:" .. v .. "|" .. v .. "]]") | ||
:done() | :done() | ||
i = i + 1 | i = i + 1 | ||
end | end | ||
end | end | ||
field_div:allDone() | field_div:allDone() | ||
return field_div | return field_div | ||
end | end | ||
function makeSectionDiv(sec_fields, sec_style) | |||
local sec_div = mw.html.create('div'):cssText(sec_style) | local sec_div = mw.html.create('div'):cssText(sec_style) | ||
sec_fields = TableTools.compressSparseArray(sec_fields) | sec_fields = TableTools.compressSparseArray(sec_fields) | ||
for findex, sec_field in ipairs(sec_fields) do -- should put this at the end of the function, and just append the other stuff | for findex, sec_field in ipairs(sec_fields) do -- should put this at the end of the function, and just append the other stuff | ||
sec_div:node(sec_field) | sec_div:node(sec_field) | ||
end | end | ||
return sec_div | return sec_div | ||
end | end | ||
function makeParticipantsSection(frame, args, data, filled_role_data, open_roles) | |||
local filled_role_fields = {} | local filled_role_fields = {} | ||
for role, val_table in pairs(filled_role_data) do | for role, val_table in pairs(filled_role_data) do | ||
local field = data.fields[role] | local field = data.fields[role] | ||
field.title = mw.text.trim(frame:expandTemplate{title=args.translations, args={field.key}}) | field.title = mw.text.trim(frame:expandTemplate{title=args.translations, args={field.key}}) | ||
field.values = {} | field.values = {} | ||
for val_num, val_text in ipairs(filled_role_data[role]) do | for val_num, val_text in ipairs(filled_role_data[role]) do | ||
field.values[#field.values + 1] = val_text | field.values[#field.values + 1] = val_text | ||
end | end | ||
local filled_field_div = makeParticipantField(field, "filled") | local filled_field_div = makeParticipantField(field, "filled") | ||
filled_role_fields[field.rank] = filled_field_div | filled_role_fields[field.rank] = filled_field_div | ||
end | end | ||
local sec_div = makeSectionDiv(filled_role_fields, data.styles.section["participants"]) | local sec_div = makeSectionDiv(filled_role_fields, data.styles.section["participants"]) | ||
| Line 245: | Line 198: | ||
-- if (args.portal == "Idealab" or args.portal == "Research") then -- beware, exceptions everywhere | -- if (args.portal == "Idealab" or args.portal == "Research") then -- beware, exceptions everywhere | ||
sec_div:tag('span'):cssText("font-style:italic; color: #888888"):wikitext(mw.text.trim(frame:expandTemplate{title=args.translations, args={data.fields.more_participants.key}})):done() | sec_div:tag('span'):cssText("font-style:italic; color: #888888"):wikitext(mw.text.trim(frame:expandTemplate{title=args.translations, args={data.fields.more_participants.key}})):done() | ||
-- elseif args.portal == "Patterns" then | -- elseif args.portal == "Patterns" then | ||
-- sec_div:tag('span'):cssText("font-style:italic; color: #888888"):wikitext("a learning pattern for..."):done() | -- sec_div:tag('span'):cssText("font-style:italic; color: #888888"):wikitext("a learning pattern for..."):done() | ||
-- else | -- else | ||
for role, val in pairs(open_roles) do -- should make these ordered using compressSparseArray, as above | for role, val in pairs(open_roles) do -- should make these ordered using compressSparseArray, as above | ||
local field = data.fields[role] | local field = data.fields[role] | ||
| Line 253: | Line 206: | ||
if field.icon then | if field.icon then | ||
field.icon = field.icon_inactive | field.icon = field.icon_inactive | ||
end | end | ||
local open_field_div = makeParticipantField(field, "open") | local open_field_div = makeParticipantField(field, "open") | ||
sec_div:node(open_field_div) | sec_div:node(open_field_div) | ||
end | end | ||
end | end | ||
sec_div:allDone() | sec_div:allDone() | ||
return sec_div | return sec_div | ||
end | end | ||
function makeSectionFields(args, field) | |||
-- ui button is separate | -- ui button is separate | ||
local field_div = mw.html.create('div'):cssText(field.style) --why declare this here? | local field_div = mw.html.create('div'):cssText(field.style) --why declare this here? | ||
| Line 268: | Line 221: | ||
if (field.isRequired == true or (args[field.arg] and string.len(args[field.arg]) > 0)) then --should move this up, may not just apply to images | if (field.isRequired == true or (args[field.arg] and string.len(args[field.arg]) > 0)) then --should move this up, may not just apply to images | ||
field_div = makeImageField(field, field_div) | field_div = makeImageField(field, field_div) | ||
end | end | ||
elseif field.vtype == "text" then | elseif field.vtype == "text" then | ||
field_div = makeTextField(field, field_div) | field_div = makeTextField(field, field_div) | ||
else | else | ||
end | end | ||
return field_div -- make sure div is 'done' | return field_div -- make sure div is 'done' | ||
end | end | ||
function makeSection(frame, args, data, box_sec) | |||
-- return a div for a section of the box including child divs | -- return a div for a section of the box including child divs | ||
-- for each content field in that section | -- for each content field in that section | ||
-- local sec_div = mw.html.create('div'):cssText(data.styles.section[box_sec]) | -- local sec_div = mw.html.create('div'):cssText(data.styles.section[box_sec]) | ||
local sec_fields = {} | local sec_fields = {} | ||
for k,v in pairs(data.fields) do | for k,v in pairs(data.fields) do | ||
| Line 290: | Line 243: | ||
if field.toLowerCase == true then -- special casing to make IEG status=SELECTED to display in lowercase | if field.toLowerCase == true then -- special casing to make IEG status=SELECTED to display in lowercase | ||
field.values[1] = stringToLowerCase(field.values[1]) | field.values[1] = stringToLowerCase(field.values[1]) | ||
end | end | ||
local field_div = makeSectionFields(args, field) | local field_div = makeSectionFields(args, field) | ||
sec_fields[field.rank] = field_div | sec_fields[field.rank] = field_div | ||
elseif field.isRequired == true then | elseif field.isRequired == true then | ||
if field.vtype == "text" then | if field.vtype == "text" then | ||
| Line 300: | Line 253: | ||
end | end | ||
local field_div = makeSectionFields(args, field) | local field_div = makeSectionFields(args, field) | ||
sec_fields[field.rank] = field_div | sec_fields[field.rank] = field_div | ||
else | else | ||
--don't make a section for this field | --don't make a section for this field | ||
| Line 308: | Line 261: | ||
local sec_div = makeSectionDiv(sec_fields, data.styles.section[box_sec]) | local sec_div = makeSectionDiv(sec_fields, data.styles.section[box_sec]) | ||
return sec_div | return sec_div | ||
end | end | ||
function makeInfobox(frame, args, data, filled_role_data, open_roles) | |||
-- builds the infobox. Some content sections are required, others | -- builds the infobox. Some content sections are required, others | ||
-- are optional. Optional sections are defined in the stylesheet. | -- are optional. Optional sections are defined in the stylesheet. | ||
| Line 318: | Line 271: | ||
local sec_top = makeSection(frame, args, data, "above") | local sec_top = makeSection(frame, args, data, "above") | ||
box:node(sec_top) | box:node(sec_top) | ||
end | end | ||
if data.sections.nav == true then | if data.sections.nav == true then | ||
local sec_nav = makeSection(frame, args, data, "nav") | local sec_nav = makeSection(frame, args, data, "nav") | ||
box:node(sec_nav) | box:node(sec_nav) | ||
end | end | ||
local sec_head = makeSection(frame, args, data, "head") | local sec_head = makeSection(frame, args, data, "head") | ||
inner_box:node(sec_head) | inner_box:node(sec_head) | ||
| Line 333: | Line 286: | ||
if data.sections.cta == true then | if data.sections.cta == true then | ||
local sec_cta = makeSection(frame, args, data, "cta") | local sec_cta = makeSection(frame, args, data, "cta") | ||
inner_box:node(sec_cta) | inner_box:node(sec_cta) | ||
inner_box:tag('div'):cssText("clear:both | inner_box:tag('div'):cssText("clear:both"):done() --clears buttons in the cta sections | ||
end | end | ||
inner_box:allDone() | inner_box:allDone() | ||
box:node(inner_box) | box:node(inner_box) | ||
| Line 342: | Line 294: | ||
local sec_bottom = makeSection(frame, args, data, "below") | local sec_bottom = makeSection(frame, args, data, "below") | ||
box:node(sec_bottom) | box:node(sec_bottom) | ||
end | end | ||
box:allDone() | box:allDone() | ||
return box | return box | ||
end | end | ||
function orderStringtoNumber(array, val, num) | |||
if num > table.getn(array) then | if num > table.getn(array) then | ||
array[#array+1] = val | array[#array+1] = val | ||
else | else | ||
table.insert(array, num, val) | table.insert(array, num, val) | ||
end | end | ||
return array | return array | ||
end | end | ||
function isJoinable(args, data) | |||
if args.more_participants == "NO" then | if args.more_participants == "NO" then | ||
data.fields.join = nil | data.fields.join = nil | ||
data.fields.endorse.style = "display:inline; float:right;" | |||
end | |||
end | |||
return data | return data | ||
end | end | ||
function deepCopyTable(data) | |||
-- the deep copy is a workaround step to avoid the restrictions placed on | -- the deep copy is a workaround step to avoid the restrictions placed on | ||
-- tables imported through loadData | -- tables imported through loadData | ||
| Line 380: | Line 330: | ||
end | end | ||
function getPortalData(args) | |||
-- loads the relevant stylesheet, if a sub-template was called with a portal | -- loads the relevant stylesheet, if a sub-template was called with a portal | ||
-- argument and a stylesheet exists with the same name. For example, calling | -- argument and a stylesheet exists with the same name. For example, calling | ||
-- {{#invoke:Probox|main|portal=Idealab}} would load the Module:Probox/Idealab | -- {{#invoke:Probox/Idealab|main|portal=Idealab}} would load the | ||
-- Module:Probox/Idealab stylesheet | |||
local data_readOnly = {} | local data_readOnly = {} | ||
local data_writable = {} | local data_writable = {} | ||
| Line 391: | Line 341: | ||
else | else | ||
data_readOnly = mw.loadData("Module:Probox/Default") | data_readOnly = mw.loadData("Module:Probox/Default") | ||
end | end | ||
-- data_writable = TableTools.shallowClone(data_readOnly) | -- data_writable = TableTools.shallowClone(data_readOnly) | ||
data_writable = deepCopyTable(data_readOnly) | data_writable = deepCopyTable(data_readOnly) | ||
| Line 397: | Line 347: | ||
end | end | ||
function string.starts(String,Start) | |||
return string.sub(String,1,string.len(Start))==Start | |||
end | |||
function stringToLowerCase(value) | |||
return mw.ustring.lower(value) | |||
end | |||
function stringSpacesToUnderscores(value) | |||
return mw.ustring.gsub(value, " ", "_") | |||
end | |||
function stringFirstCharToUpper(str) | |||
return (str:gsub("^%l", string.upper)) | |||
end | |||
function TCTlookup(args) | |||
local tct_path = tostring(args.translations) | local tct_path = tostring(args.translations) | ||
--mw.log(mw.title.getCurrentTitle().subpageText) | --mw.log(mw.title.getCurrentTitle().subpageText) | ||
| Line 410: | Line 376: | ||
-- mw.log(tct_path) | -- mw.log(tct_path) | ||
return tct_path | return tct_path | ||
end | end | ||
function getRoleArgs(args, available_roles) | |||
-- returns: | -- returns: | ||
-- 1) a table of ordered values for valid role params, | -- 1) a table of ordered values for valid role params, | ||
| Line 422: | Line 388: | ||
if available_roles.default then -- some boxes have default role to join | if available_roles.default then -- some boxes have default role to join | ||
open_roles[available_roles.default] = true | open_roles[available_roles.default] = true | ||
end | end | ||
for rd_key, rd_val in pairs(available_roles) do | for rd_key, rd_val in pairs(available_roles) do | ||
for a_key, a_val in pairs(args) do | for a_key, a_val in pairs(args) do | ||
if | if string.starts(a_key, rd_key) then | ||
if string.len(a_val) == 0 then | if string.len(a_val) == 0 then | ||
open_roles[rd_key] = true | open_roles[rd_key] = true | ||
| Line 434: | Line 400: | ||
filled_role_data[rd_key] = orderStringtoNumber(filled_role_data[rd_key], a_val, arg_num) | filled_role_data[rd_key] = orderStringtoNumber(filled_role_data[rd_key], a_val, arg_num) | ||
else | else | ||
table.insert(filled_role_data[rd_key], 1, a_val) | table.insert(filled_role_data[rd_key], 1, a_val) | ||
end | end | ||
end | end | ||
end | end | ||
end | end | ||
end | end | ||
return filled_role_data, open_roles | return filled_role_data, open_roles | ||
end | end | ||
function p.main(frame) | function p.main(frame) | ||
| Line 452: | Line 418: | ||
-- mw.log(args.translations) | -- mw.log(args.translations) | ||
-- if the TCT content index is under translation, check for translations in the subpage language | -- if the TCT content index is under translation, check for translations in the subpage language | ||
if mw.title.new("Template:" .. args.translations .. "/en").exists then | if mw.title.new("Template:" .. args.translations .. "/en").exists then | ||
args.translations = TCTlookup(args) | args.translations = TCTlookup(args) | ||
end | end | ||
if data.sections.cta == true then | if data.sections.cta == true then | ||
args.talk = tostring(mw.title.getCurrentTitle().talkPageTitle) -- expensive | args.talk = tostring(mw.title.getCurrentTitle().talkPageTitle) -- expensive | ||
end | end | ||
local filled_role_data, open_roles = getRoleArgs(args, data.roles) | local filled_role_data, open_roles = getRoleArgs(args, data.roles) | ||
local box = makeInfobox(frame, args, data, filled_role_data, open_roles) | local box = makeInfobox(frame, args, data, filled_role_data, open_roles) | ||
local infobox = tostring(box) | local infobox = tostring(box) | ||
-- only add cats if not in Template or User | -- only add cats if not in Template or User ns | ||
if (data.categories and (mw.title.getCurrentTitle().nsText ~= "Template" and mw.title.getCurrentTitle().nsText ~= "User" and mw.title.getCurrentTitle().nsText ~= "Meta") and not args.noindex) then | if (data.categories and (mw.title.getCurrentTitle().nsText ~= "Template" and mw.title.getCurrentTitle().nsText ~= "User" and mw.title.getCurrentTitle().nsText ~= "Meta") and not args.noindex) then | ||
-- FIXME specify namespace in config, so that categories only appear if template is translcuded in that namespace | -- FIXME specify namespace in config, so that categories only appear if template is translcuded in that namespace | ||
page_categories = addCategories(data, args, open_roles) | |||
infobox = infobox .. page_categories | infobox = infobox .. page_categories | ||
end | end | ||
if data.templates then | if data.templates then | ||
local top_template = addTemplates(frame, data, args) | local top_template = addTemplates(frame, data, args) | ||
infobox = top_template .. infobox | infobox = top_template .. infobox | ||
end | end | ||
return infobox | return infobox | ||
end | end | ||
return p | return p | ||