/* Set up done marks for steps */ nodeListToArray(document.querySelectorAll('.g-Recipe__Content ol > li')).forEach(todo => { todo.onclick = e => { toggleClassName(todo, 'g-Recipe__Completed') e.stopPropagation() } }) function toggleClassName(node: Element, className: string) { if (node.className === className) { node.className = '' } else { node.className = className } } /* Set up inputs for the ingredients */ const itemEntries = nodeListToArray(document.querySelectorAll('.g-Recipe__Content ul > li')) .map(itemNode => ({ tag: 'li', node: itemNode })) const h1 = document.querySelector('.g-Recipe__Content h1') if (h1 !== null) { itemEntries.push( { tag: 'h1' , node: h1 } ) } const inputs = setInputs(itemEntries) inputs.map(input => { input.node.oninput = e => { if (e.target !==null) { const parsed: ParsedNumber | undefined = parseNumber((e.target as HTMLInputElement).value) if (parsed !== undefined && parsed.before === '' && parsed.after === '') { const factor = parsed.number / input.number inputs.map(input2 => input2.node.value = prettyPrintNumber(input2.number * factor)) } } } }) interface InputEntry { tag: string; node: HTMLElement; } interface InputResult { number: number, node: HTMLInputElement } function setInputs(xs: Array): Array { const res: Array = [] xs.forEach(x => { const parsed = parseNumber(x.node.innerText) if (parsed !== undefined) { const numberNode = parsedNumberNode(x.tag, parsed) const parentNode = x.node.parentNode if (parentNode) { parentNode.replaceChild(numberNode.all, x.node) res.push({ number: parsed.number, node: numberNode.number }) } } }) return res } function parsedNumberNode(tag: string, parsedNumber: ParsedNumber) { const node = document.createElement(tag) node.appendChild(document.createTextNode(parsedNumber.before)) const numberNode = document.createElement('input') numberNode.className = 'g-Number' numberNode.value = prettyPrintNumber(parsedNumber.number) node.appendChild(numberNode) node.appendChild(document.createTextNode(parsedNumber.after)) return { all: node, number: numberNode, } } interface ParsedNumber { before: string; number: number; after: string; } function parseNumber(str: string): ParsedNumber | undefined { for (var start = 0; start < str.length; start++) { if (isDigit(str.charAt(start))) { break } } if (start === str.length) { return undefined } // Integer part var integerPart = ''; for (var end = start; end < str.length; end++) { const c = str.charAt(end) if (!isDigit(c)) { break } else { integerPart += c } } // Decimal sign if (end < str.length && (str.charAt(end) === '.' || str.charAt(end) === ',')) { end++ } // Decimal part var decimalPart = ''; for (; end < str.length; end++) { const c = str.charAt(end) if (!isDigit(c)) { break } else { decimalPart += c } } return { before: str.substring(0, start), number: parseFloat(integerPart + (decimalPart !== '' ? '.' + decimalPart : '')), after: str.substring(end, str.length) } } function isDigit(c: string) { return c >= '0' && c <= '9' } function nodeListToArray(nodeList: NodeListOf): Array { const xs: Array = []; nodeList.forEach(node => xs.push(node)) return xs } function prettyPrintNumber(n: number): string { const xs = n.toString().split('.') if (xs.length == 2) { return xs[0] + ',' + xs[1].substring(0, 2) } else { return xs[0] } }