Module:Calculator

.mw-parser-output .documentation,.mw-parser-output .documentation-metadata{border:1px solid var(--border-color-base,#a2a9b1);background-color:#ecfcf4;color:inhe

Module:Calculator
local Calculator = {}
Calculator.__index__ = Calculator

function Calculator:new(params)
	params = params or {}

	local root = params.root or mw.html.create(getElement(params))
	if params.scoped ~= false then
		root:addClass('calculator-container')
			:attr('data-calculator-refresh-on-load', boolString(params.refreshOnLoad))
	end
	root:addClass(params.class)
		:attr('style', params.style)
	
	local obj = {
		root = root,
		noJSFallback = '',
		templatestyles = {}
	}

	if params.noJSFallback then
		-- If fallback exists, wrap with calculatorgadget-enabled class
		root:addClass('calculatorgadget-enabled')
			:css('display', 'none')
		
		-- No need to create html node for fallback if it's an empty string
		if params.noJSFallback ~= '' then
	 		obj.noJSFallback = tostring(
				mw.html.create(getElement(params))
					:addClass('calculatorgadget-fallback')
					:wikitext(params.noJSFallback)
			)
		end
	end

	self.__index = self
	return setmetatable(obj, Calculator)
end

function Calculator:field(params)
	return self.root:tag('span')
		:addClass('calculator-field')
		:addClass(params.class)
		:attr('id', params.id and ('calculator-field-' .. params.id) or nil)
		:attr('data-calculator-type', params.type or 'number')
		:attr('style', params.style)
		:css('display', params.type == 'hidden' and 'none' or nil)
		:attr('data-calculator-formula', params.formula)
		:attr('data-calculator-readonly', boolString(params.readonly))
		:attr('data-calculator-size', params.size)
		:attr('data-calculator-max', params.max)
		:attr('data-calculator-min', params.min)
		:attr('data-calculator-placeholder', params.placeholder)
		:attr('data-calculator-name', params.name)
		:attr('data-calculator-precision', params.precision)
		:attr('data-calculator-exponential-precision', params['exponential-precision'])
		:attr('data-calculator-decimals', params.decimals)
		:attr('data-calculator-nan-text', params['NaN-text'])
		:attr('data-calculator-class', params['class-live'])
		:attr('aria-describedby', params['aria-describedby'])
		:attr('aria-labelledby', params['aria-labelledby'])
		:attr('aria-label', params['aria-label'])
		:attr('data-calculator-enterkeyhint', params.enterkeyhint)
		:attr('data-calculator-mapping', params.mapping)
		:attr('data-calculator-aria-role', params.role)
		:attr('data-calculator-aria-atomic', params['aria-atomic'])
		:attr('data-calculator-aria-relevant', params['aria-relevant'])
		:attr('data-calculator-aria-live', params['aria-live'])
		:attr('data-calculator-checked', boolString(params.checked))
		:attr('data-calculator-value', params.value)
		:attr('data-calculator-inputmode', params.inputmode or
			(params.type == 'text' and params.mapping == nil and 'numeric' or nil))
		:attr('data-calculator-step', params.step)
		:wikitext(params.default or '')
end

function Calculator:button(params)
	local button = self.root:tag('span')
		:addClass('calculator-field-button')
		:addClass(params.class)
		:attr('id', params.id)
		:attr('title', params.title)
		:attr('style', params.style)
		:attr('data-calculator-alt', params.alt)
		:attr('data-calculator-disabled', boolString(params.disabled))
		:attr('data-calculator-for', params['for'])
		:attr('data-calculator-formula', params.formula)
		:attr('role', params.role)
		:attr('data-calculator-aria-live', params['aria-live'])
		:attr('data-calculator-delay', params.delay)
		:attr('data-calculator-max-iterations', params['max iterations'])
		:attr('data-calculator-toggle', params.toggle)
		:attr('data-calculator-class', params['class-live'])
		:wikitext(params.contents or params.text or params[1] or 'Click me')

	local type = params.type or 'plain'
	if type ~= 'plain' then
		button:addClass('cdx-button')
		button:addClass('cdx-button--action-'..type)
		button:addClass('cdx-button--weight-'..(params.weight or 'normal'))
		button:addClass('cdx-button--size-'..(params.size or 'medium'))
	end
	return button
end

function Calculator:hidden(params)
	params.type = 'hidden'
	return self:field(params)
end

function Calculator:plain(params)
	params.type = 'plain'
	return self:field(params)
end

function Calculator:text(params)
	params.type = 'text'
	return self:field(params)
end

function Calculator:radio(params)
	params.type = 'radio'
	return self:field(params)
end

function Calculator:checkbox(params)
	params.type = 'checkbox'
	return self:field(params)
end

function Calculator:codexText(params)
	params.type = 'text'
	params['class-live'] = 'cdx-text-input__input ' .. (params['class-live'] or '')
	return self:field(params)
end

function Calculator:codexRadio(params)
	params.type = 'radio'
	params['class-live'] = 'cdx-radio__input ' .. (params['class-live'] or '')
	
	local outer = self:subContainer({ 
		class = 'cdx-radio ' 
			.. (params.inline and 'cdx-radio--inline' or '') 
			.. (params['codex-div-class'] or '')
	})
	local inner = outer:subContainer({
		class = 'cdx-radio__wrapper'
	})

	inner:field(params)
	inner:tag('span'):addClass('cdx-radio__icon')
	inner:codexLabel({
		['codex-class'] = 'cdx-radio__label',
		['for'] = params.id,
		description = params.description,
		label = params.label
	})

	if params.custominput then 
		outer:tag('div')
			:addClass('cdx-radio__custom-input')
			:wikitext(params.custominput)
	end
	
	return outer
end

function Calculator:codexCheckbox(params)
	params.type = 'checkbox'
	params['class-live'] = 'cdx-checkbox__input ' .. (params['class-live'] or '')
	
	local outer = self:subContainer({ 
		class = 'cdx-checkbox ' 
			.. (params.inline and 'cdx-checkbox--inline' or '') 
			.. (params['codex-div-class'] or '')
	})
	local inner = outer:subContainer({
		class = 'cdx-checkbox__wrapper'
	})

	inner:field(params)
	inner:tag('span'):addClass('cdx-checkbox__icon')
	inner:codexLabel({
		['codex-class'] = 'cdx-checkbox__label',
		['for'] = params.id,
		description = params.description,
		label = params.label
	})
	
	if params.custominput then 
		outer:tag('div')
			:addClass('cdx-checkbox__custom-input')
			:wikitext(params.custominput)
	end
	
	return outer
end

function Calculator:codexToggle(params)
	params.type = 'checkbox'
	params['class-live'] = 'cdx-toggle-switch__input ' .. (params['codex-live'] or '')
	params.default = '<span style="display:none">' .. (params.default or '') .. '</span>'
	
	local container = self:subContainer({
		element = 'span',
		class = 'cdx-toggle-switch'
	})
	container:field(params)
	container:tag('span'):addClass('cdx-toggle-switch__switch')
		:tag('span'):addClass('cdx-toggle-switch__switch__grip')
		
	container:codexLabel({
		['codex-class'] = 'cdx-toggle-switch__label ' 
			..	(params.hiddendescription and 'cdx-label--visually-hidden' or ''),
		['for'] = params.id,
		description = params.description,
		label = params.label,
		style = params.labelstyle
	})
	return container
end

function Calculator:passthru(params)
	params.type = 'passthru'
	return self:field(params)
end

function Calculator:label(params)
	if params.codex then
		return self:codexLabel(params)
	end
	return self.root:tag('span')
		:addClass('calculator-field-label')
		:addClass(params.class)
		:attr('data-for', params['for'] and ('calculator-field-'.. params['for']) or nil)
		:attr('data-calculator-class', params['class-live'])
		:attr('title', params.title)
		:attr('id', params.id)
		:attr('style', params.style)
		:wikitext(params.label or params[1])
end

function Calculator:codexLabel(params)
	local div = self.root:tag('div')
		:addClass('cdx-label')
		:addClass(params['codex-class'])
		
	local outerSpan = div:tag('span')
		:addClass('calculator-field-label cdx-label__label')
		:addClass(params.class)
		:attr('data-for', params['for'] and ('calculator-field-' .. params['for']) or nil)
		:attr('data-calculator-class', params['class-live'])
		:attr('title', params.title)
		:attr('id', params.id)
		:attr('style', params.style)
	
	outerSpan:tag('span')
		:addClass('cdx-label__label__text')
		:wikitext(params.label or params[1])
		
	if params.flag then
		outerSpan:tag('span')
			:addClass('cdx-label__label__optional-flag')
			:wikitext(' ' .. params.flag)
	end
	
	if params.description then
		-- Note: this doesn't yet set proper aria-describedby on the input widget
		div:tag('span')
			:addClass('cdx-label__description')
			:attr('id', params['description-id'])
			:wikitext(params.description)
	end
	return div
end

function Calculator:hideIfZero(params)
	table.insert(self.templatestyles, 'Template:Calculator-hideifzero/styles.css')
	
	return self.root:tag(getElement(params))
		:addClass('calculator-field calculator-hideifzero')
		:addClass(params.starthidden and 'calculator-value-false' or nil)
		:addClass(params.class)
		:attr('data-calculator-type', 'passthru')
		:attr('style', params.style)
		:attr('data-calculator-formula', params.formula)
		:attr('data-calculator-aria-live', params['aria-live'])
		:attr('data-calculator-aria-atomic', params['aria-atomic'])
		:attr('role', params.role)
		:attr('data-calculator-class', params['class-live'])
		:wikitext(params.text or params[1])
end

-- Add arbitrary wikitext within the calculator container
function Calculator:wikitext(text)
	self.root:wikitext(text)
end

-- Add arbitrary html node within the calculator container.
-- Note: if you would need to add calculator fields within that 
-- node, use subContainer() instead.
function Calculator:tag(tagName)
	return self.root:tag(tagName)	
end

-- Add a wrapper html node within the calculator container,
-- for instance for styling. Additional calculator fields can 
-- be added inside it.
function Calculator:subContainer(params)
	params = params or {}
	local subRoot = self.root:tag(getElement(params))
	return Calculator:new({ 
		root = subRoot, 
		scoped = false, 
		class = params.class, 
		style = params.style,
		noJSFallback = params.noJSFallback
	})
end

function Calculator:__tostring()
	local frame = mw.getCurrentFrame()

	local styles = ''
	for idx, page in ipairs(self.templatestyles) do
		styles = styles .. frame:extensionTag('templatestyles', '', {src = page})
	end
	return styles
		.. tostring(self.root) 
		.. self.noJSFallback
		.. '[[Category:Pages using gadget Calculator]]'
end

function getElement(params)
	return params.element or (params.block == false and 'span' or 'div')
end

function boolString(value)
	return value and tostring(value) or nil
end

return Calculator

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.