blob: a5f9a6c690ac4073db09adf0e36c4ca00ac540a6 [file] [log] [blame]
"use strict";
function pluginit(KorAPugin) {
var container = document.querySelector(".container");
if (!container) return;
var serviceURL = container.dataset.serviceUrl;
var cookieName = container.dataset.cookieName || "km-config";
var requestMappingDivs = container.querySelectorAll('.mapping[data-mode="request"]');
var responseMappingDivMap = {};
var requestCfgPreview = container.querySelector(".request-cfg-preview");
var responseCfgPreview = container.querySelector(".response-cfg-preview");
var responseMappingDivs = container.querySelectorAll('.mapping[data-mode="response"]');
for (var i = 0; i < responseMappingDivs.length; i++) {
responseMappingDivMap[responseMappingDivs[i].dataset.id] = responseMappingDivs[i];
}
// Cookie helpers
function readCookie() {
var prefix = cookieName + "=";
var parts = document.cookie.split("; ");
for (var i = 0; i < parts.length; i++) {
if (parts[i].indexOf(prefix) === 0) {
try {
return JSON.parse(decodeURIComponent(parts[i].substring(prefix.length)));
} catch (e) {
return null;
}
}
}
return null;
}
function writeCookie(state) {
var value = encodeURIComponent(JSON.stringify(state));
document.cookie = cookieName + "=" + value + "; path=/; SameSite=Lax; max-age=31536000";
}
function deleteCookie() {
document.cookie = cookieName + "=; path=/; SameSite=Lax; max-age=0";
}
// Form state
function reverseDir(dir) {
return dir === "atob" ? "btoa" : "atob";
}
function rowFieldClasses(mode) {
return {
foundryA: "." + mode + "-foundryA",
layerA: "." + mode + "-layerA",
foundryB: "." + mode + "-foundryB",
layerB: "." + mode + "-layerB",
fieldA: "." + mode + "-fieldA",
fieldB: "." + mode + "-fieldB",
dirArrow: "." + mode + "-dir-arrow"
};
}
function inputValue(parent, selector) {
var el = parent.querySelector(selector);
return el ? el.value : "";
}
function getModeState(div, mode) {
var classes = rowFieldClasses(mode);
var arrow = div.querySelector(classes.dirArrow);
return {
enabled: div.querySelector("." + mode + "-cb").checked,
dir: arrow ? arrow.dataset.dir : "atob",
foundryA: inputValue(div, classes.foundryA),
layerA: inputValue(div, classes.layerA),
foundryB: inputValue(div, classes.foundryB),
layerB: inputValue(div, classes.layerB),
fieldA: inputValue(div, classes.fieldA),
fieldB: inputValue(div, classes.fieldB)
};
}
function getFormState() {
var state = { mappings: [] };
for (var i = 0; i < requestMappingDivs.length; i++) {
var requestDiv = requestMappingDivs[i];
var responseDiv = responseMappingDivMap[requestDiv.dataset.id];
var entry = {
id: requestDiv.dataset.id
};
entry.request = getModeState(requestDiv, "request");
entry.response = responseDiv ? getModeState(responseDiv, "response") : { enabled: false };
state.mappings.push(entry);
}
return state;
}
// Restore form from cookie
function setInputValue(parent, selector, value) {
if (value === undefined) return;
var el = parent.querySelector(selector);
if (el) el.value = value;
}
function setArrowDirection(div, selector, dir) {
var arrow = div.querySelector(selector);
if (!arrow || !dir) return;
arrow.dataset.dir = dir;
arrow.textContent = dir === "atob" ? "\u2192" : "\u2190";
}
function restoreModeState(div, mode, modeState) {
if (!modeState) return;
var classes = rowFieldClasses(mode);
var checkbox = div.querySelector("." + mode + "-cb");
if (checkbox) checkbox.checked = !!modeState.enabled;
setArrowDirection(div, classes.dirArrow, modeState.dir);
setInputValue(div, classes.foundryA, modeState.foundryA);
setInputValue(div, classes.layerA, modeState.layerA);
setInputValue(div, classes.foundryB, modeState.foundryB);
setInputValue(div, classes.layerB, modeState.layerB);
setInputValue(div, classes.fieldA, modeState.fieldA);
setInputValue(div, classes.fieldB, modeState.fieldB);
}
function restoreFormState(saved) {
if (!saved || !saved.mappings) return;
var byId = {};
for (var i = 0; i < saved.mappings.length; i++) {
byId[saved.mappings[i].id] = saved.mappings[i];
}
for (var i = 0; i < requestMappingDivs.length; i++) {
var requestDiv = requestMappingDivs[i];
var responseDiv = responseMappingDivMap[requestDiv.dataset.id];
var entry = byId[requestDiv.dataset.id];
if (!entry) continue;
if (requestDiv.dataset.type !== "corpus") {
// Backward compatibility with old cookie schema.
if (entry.request && typeof entry.request === "object") {
restoreModeState(requestDiv, "request", entry.request);
if (responseDiv) {
restoreModeState(responseDiv, "response", entry.response);
}
} else {
var requestLegacy = {
enabled: !!entry.request,
dir: entry.dir || "atob",
foundryA: entry.foundryA,
layerA: entry.layerA,
foundryB: entry.foundryB,
layerB: entry.layerB
};
var responseLegacy = {
enabled: !!entry.response,
dir: reverseDir(entry.dir || "atob"),
foundryA: entry.foundryA,
layerA: entry.layerA,
foundryB: entry.foundryB,
layerB: entry.layerB
};
restoreModeState(requestDiv, "request", requestLegacy);
if (responseDiv) {
restoreModeState(responseDiv, "response", responseLegacy);
}
}
} else {
// Backward compatibility with old cookie schema.
if (entry.request && typeof entry.request === "object") {
restoreModeState(requestDiv, "request", entry.request);
if (responseDiv) {
restoreModeState(responseDiv, "response", entry.response);
}
} else {
var requestCb = requestDiv.querySelector(".request-cb");
var responseCb = responseDiv ? responseDiv.querySelector(".response-cb") : null;
if (requestCb) {
requestCb.checked = !!entry.request;
}
if (responseCb) {
responseCb.checked = !!entry.response;
}
}
}
}
}
// cfg parameter building
// Returns "" when the input matches its default (compact URL).
function cfgFieldValue(div, inputSelector, defaultDataAttr) {
var el = div.querySelector(inputSelector);
if (!el) return "";
var val = el.value;
var def = div.dataset[defaultDataAttr] || "";
return val === def ? "" : val;
}
function buildCfgParam(mode) {
var parts = [];
var classes = rowFieldClasses(mode);
var mappingDivs = mode === "request" ? requestMappingDivs : responseMappingDivs;
for (var i = 0; i < mappingDivs.length; i++) {
var div = mappingDivs[i];
var cbClass = mode === "request" ? ".request-cb" : ".response-cb";
var cb = div.querySelector(cbClass);
if (!cb || !cb.checked) continue;
var id = div.dataset.id;
var dir = "atob";
var arrow = div.querySelector(classes.dirArrow);
dir = arrow ? arrow.dataset.dir : "atob";
if (div.dataset.type !== "corpus") {
var fA = cfgFieldValue(div, classes.foundryA, "defaultFoundryA");
var lA = cfgFieldValue(div, classes.layerA, "defaultLayerA");
var fB = cfgFieldValue(div, classes.foundryB, "defaultFoundryB");
var lB = cfgFieldValue(div, classes.layerB, "defaultLayerB");
if (fA || lA || fB || lB) {
parts.push(id + ":" + dir + ":" + fA + ":" + lA + ":" + fB + ":" + lB);
} else {
parts.push(id + ":" + dir);
}
} else {
var fieldA = cfgFieldValue(div, classes.fieldA, "defaultFieldA");
var fieldB = cfgFieldValue(div, classes.fieldB, "defaultFieldB");
if (fieldA || fieldB) {
parts.push(id + ":" + dir + ":" + fieldA + ":" + fieldB);
} else {
parts.push(id + ":" + dir);
}
}
}
return parts.join(";");
}
// Active state tracking
var isPluginActive = false;
var activeCheckbox = container.querySelector("#check-active");
function setActiveState(value) {
isPluginActive = !!value;
if (activeCheckbox) {
activeCheckbox.checked = isPluginActive;
}
syncPipes();
}
// Kalamar pipe registration
function encodePathCfg(cfg) {
return encodeURIComponent(cfg).replace(/%3A/gi, ':').replace(/%3B/gi, ';');
}
function buildPipeURL(pipeType, cfg) {
if (!cfg) return "";
return serviceURL.replace(/\/+$/, "") + "/" + pipeType + "/" + encodePathCfg(cfg);
}
var lastQueryPipe = null;
var lastResponsePipe = null;
function removePipes() {
if (typeof KorAPugin === "undefined") return;
if (lastQueryPipe) {
KorAPlugin.sendMsg({ action: "pipe", job: "del", service: lastQueryPipe });
lastQueryPipe = null;
}
if (lastResponsePipe) {
KorAPlugin.sendMsg({ action: "pipe", job: "del-after", service: lastResponsePipe });
lastResponsePipe = null;
}
}
function registerPipes() {
var queryCfg = buildCfgParam("request");
var responseCfg = buildCfgParam("response");
if (requestCfgPreview) {
requestCfgPreview.value = queryCfg;
}
if (responseCfgPreview) {
responseCfgPreview.value = responseCfg;
}
if (!isPluginActive) {
removePipes();
return;
}
var newQueryPipe = buildPipeURL("query", queryCfg);
var newResponsePipe = buildPipeURL("response", responseCfg);
if (newQueryPipe === lastQueryPipe && newResponsePipe === lastResponsePipe) return;
if (typeof KorAPlugin !== "undefined") {
if (newQueryPipe !== lastQueryPipe) {
if (lastQueryPipe) {
KorAPlugin.sendMsg({ action: "pipe", job: "del", service: lastQueryPipe });
}
if (newQueryPipe) {
KorAPlugin.sendMsg({ action: "pipe", job: "add", service: newQueryPipe });
}
}
if (newResponsePipe !== lastResponsePipe) {
if (lastResponsePipe) {
KorAPlugin.sendMsg({ action: "pipe", job: "del-after", service: lastResponsePipe });
}
if (newResponsePipe) {
KorAPlugin.sendMsg({ action: "pipe", job: "add-after", service: newResponsePipe });
}
}
}
lastQueryPipe = newQueryPipe;
lastResponsePipe = newResponsePipe;
}
function syncPipes() {
if (isPluginActive) {
registerPipes();
} else {
removePipes();
}
}
// Change handler
function onChange() {
writeCookie(getFormState());
registerPipes();
}
// Initialisation
var saved = readCookie();
if (saved) {
restoreFormState(saved);
}
var checkboxes = container.querySelectorAll('input[type="checkbox"]:not(#check-active)');
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].addEventListener("change", onChange);
}
var textInputs = container.querySelectorAll('input[type="text"]');
for (var i = 0; i < textInputs.length; i++) {
textInputs[i].addEventListener("input", onChange);
}
var arrows = container.querySelectorAll(".request-dir-arrow, .response-dir-arrow");
for (var i = 0; i < arrows.length; i++) {
(function (arrow) {
arrow.addEventListener("click", function () {
var next = reverseDir(arrow.dataset.dir);
arrow.dataset.dir = next;
arrow.textContent = next === "atob" ? "\u2192" : "\u2190";
onChange();
});
})(arrows[i]);
}
// Reset button
function resetForm() {
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = false;
}
for (var i = 0; i < textInputs.length; i++) {
textInputs[i].value = "";
}
var requestArrows = container.querySelectorAll(".request-dir-arrow");
for (var i = 0; i < requestArrows.length; i++) {
requestArrows[i].dataset.dir = "atob";
requestArrows[i].textContent = "\u2192";
}
var responseArrows = container.querySelectorAll(".response-dir-arrow");
for (var i = 0; i < responseArrows.length; i++) {
responseArrows[i].dataset.dir = "btoa";
responseArrows[i].textContent = "\u2190";
}
deleteCookie();
registerPipes();
}
var resetBtn = container.querySelector("#reset-btn");
if (resetBtn) {
resetBtn.addEventListener("click", resetForm);
}
// When the active checkbox in the iframe is toggled,
// send the new state to the host button.
if (activeCheckbox) {
activeCheckbox.addEventListener("change", function () {
isPluginActive = activeCheckbox.checked;
if (typeof KorAPlugin !== "undefined") {
KorAPlugin.sendMsg({
action: "set",
key: "Active",
value: isPluginActive
});
}
syncPipes();
});
}
// Don't register pipes until we know the active state
KorAPugin.requestMsg({
'action': 'get',
'key': 'Active'
}, function (msg) {
setActiveState(msg.value);
});
KorAPugin.onMessage = function(msg) {
if (msg.action === 'state' && msg.key === 'active') {
setActiveState(msg.value);
return;
}
};
};