{{ macros.taint_js() }}
function update_form() {
- // catch and empty table
- const table = document.getElementById("dat_lines");
- table.innerHTML = "";
-
- // basic helpers
- function add_button(parent_td, label, disabled, onclick) {
- // add button to td to run onclick (after updating dat_lines from inputs,
- // and followed by calling taint and update_form
- const btn = document.createElement("button");
- parent_td.appendChild(btn);
- btn.textContent = label;
- btn.type = "button"; // otherwise will act as form submit
- btn.disabled = disabled;
- btn.onclick = function() {
- let n_lines_jumped = 0;
- for (let i = 0; i < table.rows.length; i++) {
- const row = table.rows[i];
- if (row.classList.contains('warning')) {
- n_lines_jumped++;
- continue;
+ // catch and empty table
+ const table = document.getElementById("dat_lines");
+ table.innerHTML = "";
+
+ // basic helpers
+ function add_button(parent_td, label, disabled, onclick) {
+ // add button to td to run onclick (after updating dat_lines from inputs,
+ // and followed by calling taint and update_form
+ const btn = document.createElement("button");
+ parent_td.appendChild(btn);
+ btn.textContent = label;
+ btn.type = "button"; // otherwise will act as form submit
+ btn.disabled = disabled;
+ btn.onclick = function() {
+ let n_lines_jumped = 0;
+ for (let i = 0; i < table.rows.length; i++) {
+ const row = table.rows[i];
+ if (row.classList.contains('warning')) {
+ n_lines_jumped++;
+ continue;
+ };
+ for (const input of table.rows[i].querySelectorAll('td input')) {
+ const line_to_update = dat_lines[i - n_lines_jumped];
+ if (input.name.endsWith('comment')) {
+ line_to_update.comment = input.value;
+ } else if (input.name.endsWith('error')) {
+ line_to_update.code = input.value;
+ } else if (input.name.endsWith('date')) {
+ line_to_update.booked.date = input.value;
+ } else if (input.name.endsWith('target')) {
+ line_to_update.booked.target = input.value;
+ } else if (input.name.endsWith('account')) {
+ line_to_update.booked.account = input.value;
+ } else if (input.name.endsWith('amount')) {
+ line_to_update.booked.amount = input.value;
+ } else if (input.name.endsWith('currency')) {
+ line_to_update.booked.currency = input.value;
+ }
+ }
+ }
+ onclick();
+ taint();
+ update_form();
};
- for (const input of table.rows[i].querySelectorAll('td input')) {
- const line_to_update = dat_lines[i - n_lines_jumped];
- if (input.name.endsWith('comment')) {
- line_to_update.comment = input.value;
- } else if (input.name.endsWith('error')) {
- line_to_update.code = input.value;
- } else if (input.name.endsWith('date')) {
- line_to_update.booked.date = input.value;
- } else if (input.name.endsWith('target')) {
- line_to_update.booked.target = input.value;
- } else if (input.name.endsWith('account')) {
- line_to_update.booked.account = input.value;
- } else if (input.name.endsWith('amount')) {
- line_to_update.booked.amount = input.value;
- } else if (input.name.endsWith('currency')) {
- line_to_update.booked.currency = input.value;
- }
- }
- }
- onclick();
- taint();
- update_form();
- };
- }
- function add_td(tr, colspan=1) {
- const td = document.createElement("td");
- tr.appendChild(td);
- td.colSpan = colspan;
- return td;
- }
-
- for (let i = 0; i < dat_lines.length; i++) {
- const dat_line = dat_lines[i];
- const tr = document.createElement("tr");
- table.appendChild(tr);
-
- // add line inputs
- function setup_input_td(tr, colspan) {
- const td = add_td(tr, colspan);
- if (dat_line.error) { td.classList.add("invalid"); };
- return td;
}
- function add_input(td, name, value, size) {
- const input = document.createElement("input");
- td.appendChild(input);
- input.name = `line_${i}_${name}`;
- input.value = value.trim();
- input.size = size;
- input.oninput = taint;
- return input;
- }
- function add_td_input(name, value, size=20, colspan=1) {
- return add_input(setup_input_td(tr, colspan), name, value, size);
+ function add_td(tr, colspan=1) {
+ const td = document.createElement("td");
+ tr.appendChild(td);
+ td.colSpan = colspan;
+ return td;
}
- // movement buttons
- const td_btns_updown = add_td(tr);
- if (i > 0) {
- [{label: '^', earlier_idx: i-1, enabled: i > 1},
- {label: 'v', earlier_idx: i, enabled: i && i+1 < dat_lines.length}
- ].forEach((kwargs) => {
- add_button(td_btns_updown, kwargs.label, ! kwargs.enabled, function() {
- const other_line = dat_lines[kwargs.earlier_idx];
- dat_lines.splice(kwargs.earlier_idx, 1);
- dat_lines.splice(kwargs.earlier_idx + 1, 0, other_line);
- });
- });
- }
+ for (let i = 0; i < dat_lines.length; i++) {
+ const dat_line = dat_lines[i];
+ const tr = document.createElement("tr");
+ table.appendChild(tr);
- // actual input lines
- if (dat_line.is_intro) {
- const td = setup_input_td(tr, 3);
- const date_input = add_input(td, 'date', dat_line.booked.date, 10)
- date_input.classList.add('date_input');
- add_input(td, 'target', dat_line.booked.target, 37)
- } else if (!dat_line.error) { // i.e. valid TransferLine
- const acc_input = add_td_input('account', dat_line.booked.account, 30);
- acc_input.setAttribute ('list', 'all_accounts');
- acc_input.autocomplete = 'off';
- // not using input[type=number] cuz no minimal step size, therefore regex test instead
- const amt_input = add_td_input('amount', dat_line.booked.amount == 'None' ? '' : dat_line.booked.amount, 12);
- amt_input.pattern = '^-?[0-9]+(\.[0-9]+)?$';
- amt_input.classList.add("number_input");
- // ensure integer amounts at least line up with double-digit decimals
- if (amt_input.value.match(/^-?[0-9]+$/)) { amt_input.value += '.00'; }
- // imply that POST handler will set '€' currency if unset, but amount set
- const curr_input = add_td_input('currency', dat_line.booked.currency, 3);
- curr_input.placeholder = '€';
- } else {
- add_td_input('error', dat_line.code, 20, 3)
- }
- add_td_input('comment', dat_line.comment, 40);
+ // add line inputs
+ function setup_input_td(tr, colspan) {
+ const td = add_td(tr, colspan);
+ if (dat_line.error) { td.classList.add("invalid"); };
+ return td;
+ }
+ function add_input(td, name, value, size) {
+ const input = document.createElement("input");
+ td.appendChild(input);
+ input.name = `line_${i}_${name}`;
+ input.value = value.trim();
+ input.size = size;
+ input.oninput = taint;
+ return input;
+ }
+ function add_td_input(name, value, size=20, colspan=1) {
+ return add_input(setup_input_td(tr, colspan), name, value, size);
+ }
- // line deletion and addition buttons
- td_add_del = add_td(tr);
- add_button(td_add_del, 'add new', false, function() {
- new_line = {error: '', comment: '', booked: {account: '', amount: '', currency: ''}};
- dat_lines.splice(i + 1, 0, new_line);
- });
- if (i > 0) {
- add_button(td_add_del, 'delete', i > 0 ? false : true, function() {
- dat_lines.splice(i, 1);
- });
- }
+ // movement buttons
+ const td_btns_updown = add_td(tr);
+ if (i > 0) {
+ [{label: '^', earlier_idx: i-1, enabled: i > 1},
+ {label: 'v', earlier_idx: i, enabled: i && i+1 < dat_lines.length}
+ ].forEach((kwargs) => {
+ add_button(td_btns_updown, kwargs.label, ! kwargs.enabled, function() {
+ const other_line = dat_lines[kwargs.earlier_idx];
+ dat_lines.splice(kwargs.earlier_idx, 1);
+ dat_lines.splice(kwargs.earlier_idx + 1, 0, other_line);
+ });
+ });
+ }
+
+ // actual input lines
+ if (dat_line.is_intro) {
+ const td = setup_input_td(tr, 3);
+ const date_input = add_input(td, 'date', dat_line.booked.date, 10)
+ date_input.classList.add('date_input');
+ add_input(td, 'target', dat_line.booked.target, 37)
+ } else if (!dat_line.error) { // i.e. valid TransferLine
+ const acc_input = add_td_input('account', dat_line.booked.account, 30);
+ acc_input.setAttribute ('list', 'all_accounts');
+ acc_input.autocomplete = 'off';
+ // not using input[type=number] cuz no minimal step size, therefore regex test instead
+ const amt_input = add_td_input('amount', dat_line.booked.amount == 'None' ? '' : dat_line.booked.amount, 12);
+ amt_input.pattern = '^-?[0-9]+(\.[0-9]+)?$';
+ amt_input.classList.add("number_input");
+ // ensure integer amounts at least line up with double-digit decimals
+ if (amt_input.value.match(/^-?[0-9]+$/)) { amt_input.value += '.00'; }
+ // imply that POST handler will set '€' currency if unset, but amount set
+ const curr_input = add_td_input('currency', dat_line.booked.currency, 3);
+ curr_input.placeholder = '€';
+ } else {
+ add_td_input('error', dat_line.code, 20, 3)
+ }
+ add_td_input('comment', dat_line.comment, 40);
- // add error explanation row if necessary
- if (dat_line.error) {
- const tr = document.createElement("tr");
- table.appendChild(tr);
- const td = add_td(tr, 3);
- tr.appendChild(document.createElement("td"));
- td.textContent = dat_line.error;
- tr.classList.add("warning");
+ // line deletion and addition buttons
+ td_add_del = add_td(tr);
+ add_button(td_add_del, 'add new', false, function() {
+ new_line = {error: '', comment: '', booked: {account: '', amount: '', currency: ''}};
+ dat_lines.splice(i + 1, 0, new_line);
+ });
+ if (i > 0) {
+ add_button(td_add_del, 'delete', i > 0 ? false : true, function() {
+ dat_lines.splice(i, 1);
+ });
+ }
+
+ // add error explanation row if necessary
+ if (dat_line.error) {
+ const tr = document.createElement("tr");
+ table.appendChild(tr);
+ const td = add_td(tr, 3);
+ tr.appendChild(document.createElement("td"));
+ td.textContent = dat_line.error;
+ tr.classList.add("warning");
+ }
}
- }
- // make all rows alternate background color for better readability
- Array.from(table.rows).forEach((tr) => {
- tr.classList.add('alternating');
- });
+ // make all rows alternate background color for better readability
+ Array.from(table.rows).forEach((tr) => {
+ tr.classList.add('alternating');
+ });
}
function replace() {
- const from = document.getElementById("replace_from").value;
- const to = document.getElementById("replace_to").value;
- dat_lines.forEach((dat_line) => {
- dat_line.comment = dat_line.comment.replaceAll(from, to);
- if ('code' in dat_line) {
- dat_line.code = dat_line.code.replaceAll(from, to);
- }
- ['date', 'target', 'account', 'amount', 'currency'].forEach((key) => {
- if (key in dat_line.booked) {
- dat_line.booked[key] = dat_line.booked[key].replaceAll(from, to);
- }
- });
- });
- taint();
- update_form();
+ const from = document.getElementById("replace_from").value;
+ const to = document.getElementById("replace_to").value;
+ dat_lines.forEach((dat_line) => {
+ dat_line.comment = dat_line.comment.replaceAll(from, to);
+ if ('code' in dat_line) {
+ dat_line.code = dat_line.code.replaceAll(from, to);
+ }
+ ['date', 'target', 'account', 'amount', 'currency'].forEach((key) => {
+ if (key in dat_line.booked) {
+ dat_line.booked[key] = dat_line.booked[key].replaceAll(from, to);
+ }
+ });
+ });
+ taint();
+ update_form();
}
function mirror() {
- dat_lines.slice(1).forEach((dat_line) => {
- let inverted_amount = `-${dat_line.booked.amount}`;
- if (inverted_amount.startsWith('--')) {
- inverted_amount = inverted_amount.slice(2);
- }
- dat_lines.push({
- error: '',
- comment: '',
- booked: {
- account: '?',
- amount: inverted_amount,
- currency: dat_line.booked.currency
- }
- });
- })
- taint();
- update_form();
+ dat_lines.slice(1).forEach((dat_line) => {
+ let inverted_amount = `-${dat_line.booked.amount}`;
+ if (inverted_amount.startsWith('--')) {
+ inverted_amount = inverted_amount.slice(2);
+ }
+ dat_lines.push({
+ error: '',
+ comment: '',
+ booked: {
+ account: '?',
+ amount: inverted_amount,
+ currency: dat_line.booked.currency
+ }
+ });
+ })
+ taint();
+ update_form();
}
window.onload = update_form;