Files
RecoReco/Asset/js/recoreco-modal.js

138 lines
5.8 KiB
JavaScript

/*
* RecoReco -- keep the "days before" field within one period of the selected frequency.
*
* The Recurring schedule modal is injected by AJAX, so we react to the frequency <select> both when
* it appears (MutationObserver) and when it changes (delegated event). Daily -> field disabled (0);
* weekly -> max 6; monthly -> max 27; yearly -> max 364. The server clamps too, so this is only the
* UI guard.
*/
(function () {
"use strict";
var CAPS = { daily: 0, weekly: 6, monthly_day: 27, monthly_dow: 27, yearly: 364 };
function apply(select) {
// "days before" ceiling / disable by frequency.
var input = document.querySelector('input[name="recoreco_days_before"]');
if (input) {
var max = CAPS.hasOwnProperty(select.value) ? CAPS[select.value] : 27;
if (max === 0) {
input.value = 0;
input.setAttribute("max", "0");
input.disabled = true;
} else {
input.disabled = false;
input.setAttribute("max", String(max));
if (parseInt(input.value, 10) > max) {
input.value = max;
}
}
}
// The last-day/weekday checkbox only means something for monthly and yearly.
var lastday = document.querySelector(".recoreco-lastday");
if (lastday) {
var monthlyOrYearly = select.value === "monthly_day" || select.value === "monthly_dow" || select.value === "yearly";
lastday.style.display = monthlyOrYearly ? "" : "none";
}
}
// "Follow FinanceBuddy installments": when on, the current/limit fields mirror FinanceBuddy's
// live installment current/total and are disabled (so they do not post, keeping FinanceBuddy the
// single source of truth); when off, they restore RecoReco's own stored values.
function applyFollow(checkbox) {
var group = checkbox.closest(".recoreco-limit-group");
if (!group) { return; }
var count = group.querySelector('input[name="recoreco_count"]');
var limit = group.querySelector('input[name="recoreco_limit"]');
if (!count || !limit) { return; }
if (checkbox.checked) {
count.value = group.getAttribute("data-fb-current");
limit.value = group.getAttribute("data-fb-total");
} else {
count.value = group.getAttribute("data-rr-count");
limit.value = group.getAttribute("data-rr-limit");
}
count.disabled = checkbox.checked;
limit.disabled = checkbox.checked;
}
// Trigger column: it can never be the target, so hide+disable that option and reset to Any if it
// was selected; the invert checkbox only means something for a specific column.
function applyTrigger() {
var target = document.querySelector('select[name="recoreco_target_column"]');
var trigger = document.querySelector('select[name="recoreco_trigger_column"]');
var invert = document.querySelector('input[name="recoreco_trigger_invert"]');
if (!target || !trigger) { return; }
for (var i = 0; i < trigger.options.length; i++) {
var isTarget = trigger.options[i].value === target.value;
trigger.options[i].hidden = isTarget;
trigger.options[i].disabled = isTarget;
}
if (trigger.value === target.value) { trigger.value = "any"; }
if (invert) { invert.disabled = (trigger.value === "any"); }
}
// Move-mode makes copies moot, so grey out "Link copies to the template" while it is checked
// (disabled -> it won't post, so the saved value is 0).
function applyMove() {
var move = document.querySelector('input[name="recoreco_move"]');
var link = document.querySelector('input[name="recoreco_link_copies"]');
if (!move || !link) { return; }
link.disabled = move.checked;
var label = link.closest("label");
if (label) { label.style.opacity = move.checked ? "0.5" : ""; }
}
// Italicize the card's current column in the target/trigger dropdowns, so you can see where it
// sits right now. (<option> styling is honored by Chrome/Firefox; Safari may ignore it.)
function applyCurrentItalic() {
var form = document.querySelector('form[data-recoreco-current]');
if (!form) { return; }
var current = form.getAttribute("data-recoreco-current");
var selects = form.querySelectorAll('select[name="recoreco_target_column"], select[name="recoreco_trigger_column"]');
for (var s = 0; s < selects.length; s++) {
for (var i = 0; i < selects[s].options.length; i++) {
if (selects[s].options[i].value === current) {
selects[s].options[i].style.fontStyle = "italic";
}
}
}
}
document.addEventListener("change", function (e) {
if (e.target && e.target.name === "recoreco_frequency") {
apply(e.target);
}
if (e.target && e.target.name === "recoreco_follow_finance") {
applyFollow(e.target);
}
if (e.target && (e.target.name === "recoreco_target_column" || e.target.name === "recoreco_trigger_column")) {
applyTrigger();
}
if (e.target && e.target.name === "recoreco_move") {
applyMove();
}
});
if (window.MutationObserver) {
new MutationObserver(function () {
var select = document.querySelector('select[name="recoreco_frequency"]:not([data-recoreco-init])');
if (select) {
select.setAttribute("data-recoreco-init", "1");
apply(select);
applyTrigger();
applyMove();
applyCurrentItalic();
}
}).observe(document.body, { childList: true, subtree: true });
}
})();