@web-atoms/core
Version:
630 lines (629 loc) • 23.7 kB
JavaScript
System.register(["tslib", "../../core/AtomDisposableList", "../../core/InheritedProperty", "../../core/types", "../../core/XNode", "../controls/AtomControl", "./PopupService.global.css", "./PopupWindow"], function (_export, _context) {
"use strict";
var __awaiter, __rest, AtomDisposableList, getOwnInheritedProperty, CancelToken, XNode, AtomControl, PopupWindowA, ConfirmPopup, PopupControl, PopupService, PopupWindow, popupCss, disableContain, popupId, lastTarget;
function findHostAndPosition(opener) {
let root = opener;
const body = document.body;
let rect = opener.getBoundingClientRect();
const offset = {
x: rect.left,
y: rect.top,
handler: null,
root
};
do {
root = root.parentElement;
if (root === body) {
break;
}
if (root.parentElement.classList.contains("page-host")) {
break;
}
if (root.classList.contains("popup-host")) {
break;
}
if (root.getAttribute("data-pop-up-host") === "yes") {
break;
}
} while (true);
rect = root.getBoundingClientRect();
offset.x -= rect.x;
offset.y -= rect.y;
offset.root = root;
return offset;
}
function findHost(opener, offset) {
var _a, _b;
let host = opener.offsetParent;
while (host) {
const current = host;
if (host === document.body) {
return host;
}
if (host.classList.contains("popup-host")) {
return host;
}
if (host.dataset.popUpHost === "yes") {
return host;
}
const parent = (_a = host.offsetParent) !== null && _a !== void 0 ? _a : host.parentElement;
host = parent;
if (host.classList.contains("page-host")) {
host = current;
return host;
}
if (!host) {
continue;
}
if (!offset) {
continue;
}
offset.x += host.offsetLeft;
offset.y += host.offsetTop - ((_b = parent === null || parent === void 0 ? void 0 : parent.scrollTop) !== null && _b !== void 0 ? _b : 0);
}
return host !== null && host !== void 0 ? host : document.body;
}
function closeHandler(host, opener, container, close) {
let handler = null;
handler = e => {
var _a;
if (container === null || container === void 0 ? void 0 : container.element) {
const ce = new CustomEvent("outsideClick", {
detail: e,
cancelable: true,
bubbles: true
});
container.element.dispatchEvent(ce);
if (ce.defaultPrevented) {
return;
}
}
let start = e.target;
if (e.defaultPrevented) {
return;
}
while (start) {
if (start === host) {
break;
}
if (start === opener) {
return;
}
if (start === container.element) {
return;
}
start = start.parentElement;
}
close();
e.preventDefault();
(_a = e.stopImmediatePropagation) === null || _a === void 0 ? void 0 : _a.call(e);
};
document.body.addEventListener("click", handler, true);
container.registerDisposable(() => document.body.removeEventListener("click", handler, true));
const onBack = e => {
var _a;
e.preventDefault();
(_a = e.stopImmediatePropagation) === null || _a === void 0 ? void 0 : _a.call(e);
e.stopPropagation();
close();
};
window.addEventListener("backButton", onBack, true);
container.registerDisposable(() => window.removeEventListener("backButton", onBack, true));
setTimeout(() => {
container.registerDisposable(disableContain(container.element));
}, 10);
}
_export("PopupControl", void 0);
return {
setters: [function (_tslib) {
__awaiter = _tslib.__awaiter;
__rest = _tslib.__rest;
}, function (_coreAtomDisposableList) {
AtomDisposableList = _coreAtomDisposableList.AtomDisposableList;
}, function (_coreInheritedProperty) {
getOwnInheritedProperty = _coreInheritedProperty.getOwnInheritedProperty;
}, function (_coreTypes) {
CancelToken = _coreTypes.CancelToken;
}, function (_coreXNode) {
XNode = _coreXNode.default;
}, function (_controlsAtomControl) {
AtomControl = _controlsAtomControl.AtomControl;
}, function (_PopupServiceGlobalCss) {}, function (_PopupWindow) {
PopupWindowA = _PopupWindow.default;
ConfirmPopup = _PopupWindow.ConfirmPopup;
}],
execute: function () {
_export("PopupWindow", PopupWindow = PopupWindowA);
document.body.addEventListener("click", e => {
if (e.target.offsetParent) {
PopupService.lastTarget = e.target;
}
});
popupCss = "web-atoms-popup-local";
_export("PopupControl", PopupControl = class PopupControl extends AtomControl {
static showControl(opener, _a = {}) {
var {
onClick = "close"
} = _a,
options = __rest(_a, ["onClick"]);
let openerElement = options === null || options === void 0 ? void 0 : options.parentElement;
let app;
if (opener instanceof AtomControl) {
openerElement !== null && openerElement !== void 0 ? openerElement : openerElement = opener.element;
app = opener.app;
} else {
openerElement !== null && openerElement !== void 0 ? openerElement : openerElement = opener;
let start = opener;
while (!start.atomControl) {
start = start.parentElement;
}
if (!start) {
return Promise.reject("Could not create popup as target is not attached");
}
app = start.atomControl.app;
}
const popup = new this(app);
if (onClick === "close") {
popup.bindEvent(popup.element, "click", () => setTimeout(() => popup.close(), 10));
} else if (onClick === "cancel") {
popup.bindEvent(popup.element, "click", () => setTimeout(() => popup.cancel(), 10));
}
const p = PopupService.show(openerElement, popup.element, options);
return new Promise((resolve, reject) => {
let resolved = false;
popup.close = r => {
if (resolved) {
return;
}
resolved = true;
PopupService.lastTarget = openerElement;
resolve(r);
p.dispose();
};
popup.cancel = e => {
if (resolved) {
return;
}
resolved = true;
PopupService.lastTarget = openerElement;
reject(e);
p.dispose();
};
});
}
});
_export("disableContain", disableContain = ce => {
const containNoneList = [];
while (ce) {
const style = window.getComputedStyle(ce);
const isNotNone = style.contain !== "none";
if (isNotNone) {
ce.setAttribute("data-force-contain", "none");
containNoneList.push(ce);
}
ce = ce.parentElement;
}
return () => {
for (const iterator of containNoneList) {
iterator.removeAttribute("data-force-contain");
}
};
});
popupId = 1001;
lastTarget = {
element: null,
x: 10,
y: 10
};
PopupService = class PopupService {
static get lastTarget() {
var _a, _b, _c;
const {
element,
x = 0,
y = 0
} = lastTarget;
if (element === null || element === void 0 ? void 0 : element.isConnected) {
return element;
}
const targets = this.targetPath;
if (targets) {
for (;;) {
const first = targets[0];
if (!first) {
break;
}
if (first.isConnected) {
lastTarget = {
element: first,
x,
y
};
return first;
}
targets.splice(0, 1);
}
}
let e = (_b = (_a = document.elementFromPoint) === null || _a === void 0 ? void 0 : _a.call(document, x, y)) !== null && _b !== void 0 ? _b : document.body;
if (((_c = this.defaultElementTarget) === null || _c === void 0 ? void 0 : _c.isConnected) && (e === document.documentElement || e === document.body)) {
e = this.defaultElementTarget;
}
PopupService.lastTarget = e;
return e;
}
static set lastTarget(element) {
if (!element.isConnected) {
return;
}
if (element === document.documentElement) {
return;
}
let start = element;
const targets = [start];
while (start) {
start = start.parentElement;
if (start) {
targets.push(start);
}
}
this.targetPath = targets;
if (!this.defaultElementTarget && element !== document.body && element !== document.documentElement) {
this.defaultElementTarget = element;
}
const rect = element.getBoundingClientRect();
lastTarget = {
element,
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2
};
}
static alert(_a) {
return __awaiter(this, arguments, void 0, function* ({
message,
detail,
title = "Alert",
yesLabel = "Ok"
}) {
var _b, _c;
try {
const isMsgXNode = message instanceof XNode;
const isDetailXNode = detail && detail instanceof XNode;
if (isMsgXNode) {
((_b = message.attributes) !== null && _b !== void 0 ? _b : message.attributes = {})["data-element"] = "message";
}
if (isDetailXNode) {
((_c = detail.attributes) !== null && _c !== void 0 ? _c : detail.attributes = {})["data-element"] = "details";
}
const popup = class extends ConfirmPopup {
create() {
this.render(XNode.create("div", null, isMsgXNode ? message : XNode.create("div", {
"data-element": "message",
text: message
}), detail && (isDetailXNode ? detail : XNode.create("details", {
"data-element": "details"
}, XNode.create("pre", {
text: detail
})))));
}
};
return yield popup.showModal({
parameters: {
message,
detail,
yesLabel,
noLabel: ""
},
title
});
} catch (e) {
if (CancelToken.isCancelled(e)) {
return false;
}
throw e;
}
});
}
static confirm(_a) {
return __awaiter(this, arguments, void 0, function* ({
message,
title = "Confirm",
yesLabel = "Yes",
noLabel = "No",
cancelLabel = null
}) {
try {
const popup = class extends ConfirmPopup {
create() {
this.render(XNode.create("div", null, message instanceof XNode ? message : XNode.create("div", {
text: message
})));
}
};
return yield popup.showModal({
parameters: {
message,
yesLabel,
noLabel,
cancelLabel
},
title
});
} catch (e) {
if (CancelToken.isCancelled(e)) {
return false;
}
throw e;
}
});
}
static showWindow(opener, popupClass, popupOptions) {
return new Promise((resolve, reject) => {
var _a, _b;
var _c;
const activeElement = document.activeElement;
const previousTarget = opener;
const parent = AtomControl.from(opener);
const control = new popupClass(parent.app, document.createElement("div"));
const vm = (_a = getOwnInheritedProperty(control, "viewModel")) !== null && _a !== void 0 ? _a : "parameters" in control ? (_b = (_c = control).parameters) !== null && _b !== void 0 ? _b : _c.parameters = {} : control;
let element = control.element;
element.style.zIndex = `${popupId++}`;
let resolved = false;
const close = r => {
setTimeout(() => {
if (!resolved) {
resolved = true;
setTimeout(resolve, 1, r);
if (control.element) {
control.element.remove();
control.dispose();
}
element === null || element === void 0 ? void 0 : element.remove();
element = undefined;
PopupService.lastTarget = previousTarget;
try {
activeElement === null || activeElement === void 0 ? void 0 : activeElement.focus();
} catch (error) {
console.error(error);
}
}
}, 1);
};
const cancel = r => {
setTimeout(() => {
if (!resolved) {
resolved = true;
setTimeout(reject, 1, r !== null && r !== void 0 ? r : "cancelled");
if (control.element) {
control.element.remove();
control.dispose();
}
element === null || element === void 0 ? void 0 : element.remove();
element = undefined;
PopupService.lastTarget = previousTarget;
try {
activeElement === null || activeElement === void 0 ? void 0 : activeElement.focus();
} catch (error) {
console.error(error);
}
}
}, 1);
};
let isModal = false;
if (popupOptions) {
const {
width,
height,
minHeight,
maxHeight,
minWidth,
maxWidth,
maximize,
title,
parameters,
cancelToken,
modal
} = popupOptions;
if (title) {
vm.title = title;
}
let widthSet = false;
let heightSet = false;
if (maximize) {
element.setAttribute("data-maximize", "true");
widthSet = heightSet = true;
} else {
if (width) {
element.style.width = typeof width === "number" ? width + "px" : width;
widthSet = true;
}
if (height) {
element.style.height = typeof height === "number" ? height + "px" : height;
heightSet = true;
}
if (minWidth) {
element.style.minWidth = typeof minWidth === "number" ? minWidth + "px" : minWidth;
widthSet = true;
}
if (minHeight) {
element.style.minHeight = typeof minHeight === "number" ? minHeight + "px" : minHeight;
heightSet = true;
}
if (maxWidth) {
element.style.maxWidth = typeof maxWidth === "number" ? maxWidth + "px" : maxWidth;
widthSet = true;
}
if (maxHeight) {
element.style.maxHeight = typeof maxHeight === "number" ? maxHeight + "px" : maxHeight;
heightSet = true;
}
}
if (!widthSet) {
element.setAttribute("data-no-width", "true");
}
if (!heightSet) {
element.setAttribute("data-no-height", "true");
}
if (parameters) {
for (const key in parameters) {
if (Object.prototype.hasOwnProperty.call(parameters, key)) {
const e = parameters[key];
vm[key] = e;
}
}
const init = control.init;
if (init) {
const c = control.init();
if (c === null || c === void 0 ? void 0 : c.then) {
c.then(() => control.element.dispatchEvent(new CustomEvent("popupReady", {
bubbles: true
})), error => {
control.element.dispatchEvent(new CustomEvent("popupReady", {
bubbles: true
}));
if (!CancelToken.isCancelled(error)) {
console.error(error);
}
});
} else {
setTimeout(() => control.element.dispatchEvent(new CustomEvent("popupReady", {
bubbles: true
})), 1);
}
} else {
setTimeout(() => control.element.dispatchEvent(new CustomEvent("popupReady", {
bubbles: true
})), 1);
}
} else {
setTimeout(() => control.element.dispatchEvent(new CustomEvent("popupReady", {
bubbles: true
})), 1);
}
cancelToken === null || cancelToken === void 0 ? void 0 : cancelToken.registerForCancel(cancel);
isModal = modal;
}
const host = findHost(opener);
host.appendChild(control.element);
vm.cancel = cancel;
vm.close = close;
if (vm !== control) {
control.cancel = cancel;
control.close = close;
}
if (isModal) {
const bg = document.createElement("div");
bg.setAttribute("data-window-modal-background", "background");
host.appendChild(bg);
const onBack = e => {
var _a, _b, _c;
e.preventDefault();
(_a = e.stopImmediatePropagation) === null || _a === void 0 ? void 0 : _a.call(e);
e.stopPropagation();
(_c = (_b = control).requestCancel) === null || _c === void 0 ? void 0 : _c.call(_b);
};
window.addEventListener("backButton", onBack, true);
control.registerDisposable({
dispose: () => {
bg.remove();
window.removeEventListener("backButton", onBack, true);
}
});
} else {
closeHandler(host, opener, control, cancel);
}
});
}
static show(opener, popup, options) {
var _a, _b;
const previousTarget = opener;
const container = {
element: document.createElement("div"),
disposables: new AtomDisposableList(),
registerDisposable: null,
dispose: null
};
container.registerDisposable = f => container.disposables.add(f);
let alignment = (_a = options === null || options === void 0 ? void 0 : options.alignment) !== null && _a !== void 0 ? _a : "auto";
if (alignment === "auto") {
const rect = opener.getBoundingClientRect();
const w = window.visualViewport.width;
if (rect.left > w / 2) {
alignment = "bottomRight";
}
}
const isCenterOfScreen = alignment === "centerOfScreen";
const popupStyle = (_b = options === null || options === void 0 ? void 0 : options.popupStyle) !== null && _b !== void 0 ? _b : popupCss;
container.element._logicalParent = opener;
container.element.classList.add(popupStyle);
if (isCenterOfScreen) {
container.element.dataset.centerPopup = "center";
} else {
container.element.dataset.inlinePopup = "left";
const alignPopup = () => {
switch (alignment) {
case "bottomRight":
container.element.style.top = opener.offsetTop + opener.offsetHeight + "px";
container.element.style.right = "0px";
container.element.dataset.inlinePopup = "right";
opener.insertAdjacentElement("afterend", container.element);
break;
case "topRight":
case "right":
container.element.style.top = opener.offsetTop + "px";
container.element.style.left = opener.offsetWidth + "px";
opener.insertAdjacentElement("afterend", container.element);
break;
case "bottomLeft":
container.element.dataset.inlinePopup = "inline-left";
container.element.style.top = opener.offsetTop + opener.offsetHeight + "px";
opener.insertAdjacentElement("beforebegin", container.element);
break;
default:
container.element.style.top = opener.offsetTop + opener.offsetHeight + "px";
opener.insertAdjacentElement("afterend", container.element);
break;
}
};
if (opener.offsetParent !== opener.parentElement) {
opener.parentElement.style.position = "relative";
setTimeout(alignPopup, 5);
} else {
alignPopup();
}
}
const parent = AtomControl.from(opener);
if (popup instanceof XNode) {
parent.render(popup, container);
} else {
container.element.appendChild(popup);
}
const style = container.element.style;
style.zIndex = `${popupId++}`;
container.dispose = () => {
if (!container.disposables) {
return;
}
container.disposables.dispose();
parent.dispose(container.element);
container.element.remove();
container.disposables = null;
PopupService.lastTarget = previousTarget;
};
closeHandler(opener.parentElement, opener, container, () => {
const e = container.element;
container.dispose();
e.remove();
});
const ct = options === null || options === void 0 ? void 0 : options.cancelToken;
if (ct) {
ct.registerForCancel(() => container.dispose());
}
return container;
}
};
PopupService.targetPath = [];
_export("default", PopupService);
}
};
});
//# sourceMappingURL=PopupService.js.map