Skip to content

Commit

Permalink
fix: popup window size (#744)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasvinclav authored Sep 15, 2024
1 parent 1a51a25 commit 5a77b44
Showing 1 changed file with 295 additions and 0 deletions.
295 changes: 295 additions & 0 deletions src/unfold/static/admin/js/admin/RelatedObjectLookups.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,295 @@
/*global SelectBox, interpolate*/
// Handles related-objects functionality: lookup link for raw_id_fields
// and Add Another links.
"use strict";
{
const $ = django.jQuery;
let popupIndex = 0;
const relatedWindows = [];

function dismissChildPopups() {
relatedWindows.forEach(function (win) {
if (!win.closed) {
win.dismissChildPopups();
win.close();
}
});
}

function setPopupIndex() {
if (document.getElementsByName("_popup").length > 0) {
const index = window.name.lastIndexOf("__") + 2;
popupIndex = parseInt(window.name.substring(index));
} else {
popupIndex = 0;
}
}

function addPopupIndex(name) {
return name + "__" + (popupIndex + 1);
}

function removePopupIndex(name) {
return name.replace(new RegExp("__" + (popupIndex + 1) + "$"), "");
}

function showAdminPopup(triggeringLink, name_regexp, add_popup) {
const name = addPopupIndex(triggeringLink.id.replace(name_regexp, ""));
const href = new URL(triggeringLink.href);
if (add_popup) {
href.searchParams.set("_popup", 1);
}
const win = window.open(
href,
name,
"height=768,width=1024,resizable=yes,scrollbars=yes"
);
relatedWindows.push(win);
win.focus();
return false;
}

function showRelatedObjectLookupPopup(triggeringLink) {
return showAdminPopup(triggeringLink, /^lookup_/, true);
}

function dismissRelatedLookupPopup(win, chosenId) {
const name = removePopupIndex(win.name);
const elem = document.getElementById(name);
if (elem.classList.contains("vManyToManyRawIdAdminField") && elem.value) {
elem.value += "," + chosenId;
} else {
document.getElementById(name).value = chosenId;
}
const index = relatedWindows.indexOf(win);
if (index > -1) {
relatedWindows.splice(index, 1);
}
win.close();
}

function showRelatedObjectPopup(triggeringLink) {
return showAdminPopup(triggeringLink, /^(change|add|delete)_/, false);
}

function updateRelatedObjectLinks(triggeringLink) {
const $this = $(triggeringLink);
const siblings = $this.nextAll(
".view-related, .change-related, .delete-related"
);
if (!siblings.length) {
return;
}
const value = $this.val();
if (value) {
siblings.each(function () {
const elm = $(this);
elm.attr(
"href",
elm.attr("data-href-template").replace("__fk__", value)
);
elm.removeAttr("aria-disabled");
});
} else {
siblings.removeAttr("href");
siblings.attr("aria-disabled", true);
}
}

function updateRelatedSelectsOptions(
currentSelect,
win,
objId,
newRepr,
newId,
skipIds = []
) {
// After create/edit a model from the options next to the current
// select (+ or :pencil:) update ForeignKey PK of the rest of selects
// in the page.

const path = win.location.pathname;
// Extract the model from the popup url '.../<model>/add/' or
// '.../<model>/<id>/change/' depending the action (add or change).
const modelName = path.split("/")[path.split("/").length - (objId ? 4 : 3)];
// Select elements with a specific model reference and context of "available-source".
const selectsRelated = document.querySelectorAll(
`[data-model-ref="${modelName}"] [data-context="available-source"]`
);

selectsRelated.forEach(function (select) {
if (
currentSelect === select ||
(skipIds && skipIds.includes(select.id))
) {
return;
}

let option = select.querySelector(`option[value="${objId}"]`);

if (!option) {
option = new Option(newRepr, newId);
select.options.add(option);
// Update SelectBox cache for related fields.
if (
window.SelectBox !== undefined &&
!SelectBox.cache[currentSelect.id]
) {
SelectBox.add_to_cache(select.id, option);
SelectBox.redisplay(select.id);
}
return;
}

option.textContent = newRepr;
option.value = newId;
});
}

function dismissAddRelatedObjectPopup(win, newId, newRepr) {
const name = removePopupIndex(win.name);
const elem = document.getElementById(name);
if (elem) {
const elemName = elem.nodeName.toUpperCase();
if (elemName === "SELECT") {
elem.options[elem.options.length] = new Option(
newRepr,
newId,
true,
true
);
updateRelatedSelectsOptions(elem, win, null, newRepr, newId);
} else if (elemName === "INPUT") {
if (
elem.classList.contains("vManyToManyRawIdAdminField") &&
elem.value
) {
elem.value += "," + newId;
} else {
elem.value = newId;
}
}
// Trigger a change event to update related links if required.
$(elem).trigger("change");
} else {
const toId = name + "_to";
const toElem = document.getElementById(toId);
const o = new Option(newRepr, newId);
SelectBox.add_to_cache(toId, o);
SelectBox.redisplay(toId);
if (toElem && toElem.nodeName.toUpperCase() === "SELECT") {
const skipIds = [name + "_from"];
updateRelatedSelectsOptions(toElem, win, null, newRepr, newId, skipIds);
}
}
const index = relatedWindows.indexOf(win);
if (index > -1) {
relatedWindows.splice(index, 1);
}
win.close();
}

function dismissChangeRelatedObjectPopup(win, objId, newRepr, newId) {
const id = removePopupIndex(win.name.replace(/^edit_/, ""));
const selectsSelector = interpolate("#%s, #%s_from, #%s_to", [id, id, id]);
const selects = $(selectsSelector);
selects
.find("option")
.each(function () {
if (this.value === objId) {
this.textContent = newRepr;
this.value = newId;
}
})
.trigger("change");
updateRelatedSelectsOptions(selects[0], win, objId, newRepr, newId);
selects
.next()
.find(".select2-selection__rendered")
.each(function () {
// The element can have a clear button as a child.
// Use the lastChild to modify only the displayed value.
this.lastChild.textContent = newRepr;
this.title = newRepr;
});
const index = relatedWindows.indexOf(win);
if (index > -1) {
relatedWindows.splice(index, 1);
}
win.close();
}

function dismissDeleteRelatedObjectPopup(win, objId) {
const id = removePopupIndex(win.name.replace(/^delete_/, ""));
const selectsSelector = interpolate("#%s, #%s_from, #%s_to", [id, id, id]);
const selects = $(selectsSelector);
selects
.find("option")
.each(function () {
if (this.value === objId) {
$(this).remove();
}
})
.trigger("change");
const index = relatedWindows.indexOf(win);
if (index > -1) {
relatedWindows.splice(index, 1);
}
win.close();
}

window.showRelatedObjectLookupPopup = showRelatedObjectLookupPopup;
window.dismissRelatedLookupPopup = dismissRelatedLookupPopup;
window.showRelatedObjectPopup = showRelatedObjectPopup;
window.updateRelatedObjectLinks = updateRelatedObjectLinks;
window.dismissAddRelatedObjectPopup = dismissAddRelatedObjectPopup;
window.dismissChangeRelatedObjectPopup = dismissChangeRelatedObjectPopup;
window.dismissDeleteRelatedObjectPopup = dismissDeleteRelatedObjectPopup;
window.dismissChildPopups = dismissChildPopups;

// Kept for backward compatibility
window.showAddAnotherPopup = showRelatedObjectPopup;
window.dismissAddAnotherPopup = dismissAddRelatedObjectPopup;

window.addEventListener("unload", function (evt) {
window.dismissChildPopups();
});

$(document).ready(function () {
setPopupIndex();
$("a[data-popup-opener]").on("click", function (event) {
event.preventDefault();
opener.dismissRelatedLookupPopup(window, $(this).data("popup-opener"));
});
$("body").on(
"click",
'.related-widget-wrapper-link[data-popup="yes"]',
function (e) {
e.preventDefault();
if (this.href) {
const event = $.Event("django:show-related", { href: this.href });
$(this).trigger(event);
if (!event.isDefaultPrevented()) {
showRelatedObjectPopup(this);
}
}
}
);
$("body").on("change", ".related-widget-wrapper select", function (e) {
const event = $.Event("django:update-related");
$(this).trigger(event);
if (!event.isDefaultPrevented()) {
updateRelatedObjectLinks(this);
}
});
$(".related-widget-wrapper select").trigger("change");
$("body").on("click", ".related-lookup", function (e) {
e.preventDefault();
const event = $.Event("django:lookup-related");
$(this).trigger(event);
if (!event.isDefaultPrevented()) {
showRelatedObjectLookupPopup(this);
}
});
});
}

0 comments on commit 5a77b44

Please sign in to comment.