UNPKG

@web-atoms/core-docs

Version:
431 lines 18.7 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; (function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports", "../../App", "../../Atom", "../../core/AtomLoader", "../../core/AtomUri", "../../core/FormattedError", "../../core/FormattedString", "../../di/Inject", "../../di/RegisterSingleton", "../../di/ServiceCollection", "../../services/JsonService", "../../services/NavigationService", "../../view-model/AtomWindowViewModel", "../../web/core/AtomUI", "../controls/AtomAlertWindow", "../controls/AtomNotification", "../controls/AtomWindow", "../styles/AtomPopupStyle", "../styles/AtomStyleSheet", "../styles/StyleBuilder"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WindowService = void 0; const App_1 = require("../../App"); const Atom_1 = require("../../Atom"); const AtomLoader_1 = require("../../core/AtomLoader"); const AtomUri_1 = require("../../core/AtomUri"); const FormattedError_1 = require("../../core/FormattedError"); const FormattedString_1 = require("../../core/FormattedString"); const Inject_1 = require("../../di/Inject"); const RegisterSingleton_1 = require("../../di/RegisterSingleton"); const ServiceCollection_1 = require("../../di/ServiceCollection"); const JsonService_1 = require("../../services/JsonService"); const NavigationService_1 = require("../../services/NavigationService"); const AtomWindowViewModel_1 = require("../../view-model/AtomWindowViewModel"); const AtomUI_1 = require("../../web/core/AtomUI"); const AtomAlertWindow_1 = require("../controls/AtomAlertWindow"); const AtomNotification_1 = require("../controls/AtomNotification"); const AtomWindow_1 = require("../controls/AtomWindow"); const AtomPopupStyle_1 = require("../styles/AtomPopupStyle"); const AtomStyleSheet_1 = require("../styles/AtomStyleSheet"); const StyleBuilder_1 = require("../styles/StyleBuilder"); let WindowService = class WindowService extends NavigationService_1.NavigationService { constructor(app, jsonService) { super(app); this.jsonService = jsonService; this.targetStack = []; this.popups = []; this.hostForElementFunc = []; this.lastPopupID = 0; this.screen = app.screen; let st = "desktop"; if (/mobile|android|ios/i.test(window.navigator.userAgent)) { st = "mobile"; if (/tablet/i.test(window.navigator.userAgent)) { st = "tablet"; } } this.screen.screenType = st; if (window) { window.addEventListener("click", (e) => { // this.currentTarget = e.target as HTMLElement; this.closePopup(e); }); const update = (e) => { this.refreshScreen(); }; // we don't do this in mobile.. if (st !== "mobile") { window.addEventListener("resize", update); window.addEventListener("scroll", update); document.body.addEventListener("scroll", update); document.body.addEventListener("resize", update); } setTimeout(() => { update(null); }, 1000); } } get currentTarget() { const ts = this.targetStack; return ts.length > 0 ? ts[ts.length - 1] : undefined; } set currentTarget(v) { const ts = this.targetStack; const nts = []; if (v === null) { // special case... remove all non existent elements... for (const iterator of ts) { if (iterator.parentElement) { nts.push(iterator); } } this.targetStack = nts; return; } if (ts.length === 0 && ts[ts.length - 1] === v) { return; } ts.push(v); } /** * Get current window title * * @type {string} * @memberof BrowserService */ get title() { return window.document.title; } /** * Set current window title * @memberof BrowserService */ set title(v) { window.document.title = v; } /** * Gets current location of browser, this does not return * actual location but it returns values of browser location. * This is done to provide mocking behavior for unit testing. * * @readonly * @type {AtomLocation} * @memberof BrowserService */ get location() { return new AtomUri_1.AtomUri(location.href); } set location(v) { location.href = v.toString(); } registerHostForWindow(f) { this.hostForElementFunc.push(f); return { dispose: () => { this.hostForElementFunc.remove(f); } }; } /** * Navigate current browser to given url. * @param {string} url * @memberof BrowserService */ navigate(url) { location.href = url; } back() { window.history.back(); } register(id, type) { ServiceCollection_1.ServiceCollection.instance.register(type, null, ServiceCollection_1.Scope.Transient, id); } confirm(message, title) { return __awaiter(this, void 0, void 0, function* () { try { return yield this.openPage(AtomAlertWindow_1.default, { okTitle: "Yes", cancelTitle: "No", title: title || "Confirm", message }); } catch (e) { if (/canceled|cancelled/i.test(e)) { return false; } throw e; } }); } alert(message, title) { if (!(message instanceof FormattedString_1.default || typeof message === "string")) { if (message instanceof FormattedError_1.default) { message = message.formattedMessage; } else { message = message.message ? message.message : message.toString(); } } return this.openPage(AtomAlertWindow_1.default, { message, title, okTitle: "Ok", cancelTitle: "" }).catch((e) => { // do nothing... // tslint:disable-next-line: no-console console.warn(e); }); } closePopup(e) { // need to simulate parent click if we are inside an iframe... const fe = typeof frameElement !== "undefined" ? frameElement : null; if (fe) { fe.click(); const pe = fe.ownerDocument ? fe.ownerDocument.defaultView : null; if (pe && pe.simulateParentClick) { pe.simulateParentClick(); } } let target = this.currentTarget; const et = e.target; if (!et.parentElement) { // probably the window/popup was just disposed.. // ignore it... // if mouse click was outside body and within the window // target element will be HTML // in that case we have to dispose the top popup if (!/html/i.test(et.tagName)) { return; } // we need to manually override target so popup will be disposed target = et; } this.currentTarget = e.target; if (!this.popups.length) { return; } const peek = this.popups[this.popups.length - 1]; const element = peek.element; while (target) { if (target === element) { // do not close this popup.... return; } if (element._logicalParent === target) { return; } target = target.parentElement; } this.remove(peek); } refresh() { location.reload(true); } getHostForElement() { const ce = this.currentTarget; if (!ce) { return null; } for (const iterator of this.hostForElementFunc) { const e = iterator(ce); if (e) { return e; } } return null; } refreshScreen() { const height = this.screen.height = window.innerHeight || document.body.clientHeight; const width = this.screen.width = window.innerWidth || document.body.clientWidth; this.screen.scrollLeft = window.scrollX || document.body.scrollLeft || 0; this.screen.scrollTop = window.scrollY || document.body.scrollTop || 0; this.screen.orientation = width > height ? "landscape" : "portrait"; } notify(message, title, type, delay) { this.app.runAsync(() => this.openPage(AtomNotification_1.default, { message, title, type: type || NavigationService_1.NotifyType.Information, timeout: delay })); } registerForPopup() { if (window) { window.addEventListener("click", (e) => { this.closePopup(e); }); } } openWindow(url, options) { return __awaiter(this, void 0, void 0, function* () { // this is because current target is not yet set yield Atom_1.Atom.delay(1); const lastTarget = this.currentTarget; const { view: popup, returnPromise, disposables } = yield AtomLoader_1.AtomLoader.loadView(url, this.app, true, () => this.app.resolve(AtomWindowViewModel_1.AtomWindowViewModel, true)); if (options && options.onInit) { options.onInit(popup); } const cancelToken = options.cancelToken; if (cancelToken) { if (cancelToken.cancelled) { this.app.callLater(() => { this.remove(popup, true); }); } cancelToken.registerForCancel(() => { this.remove(popup, true); }); } const e = popup.element; let isPopup = true; if (popup instanceof AtomWindow_1.AtomWindow) { isPopup = false; e.style.opacity = "0"; } e._logicalParent = lastTarget; e.sourceUrl = url; const pvm = popup.viewModel; if (pvm) { let ce = this.currentTarget; if (ce) { while (!ce.atomControl) { ce = ce.parentElement; if (!ce) { break; } } if (ce && ce.atomControl && ce.atomControl.viewModel) { pvm.parent = ce.atomControl.viewModel; } } } const theme = this.app.get(AtomStyleSheet_1.AtomStyleSheet).getNamedStyle(AtomPopupStyle_1.AtomPopupStyle); e.style.zIndex = 10000 + this.lastPopupID + ""; const isNotification = popup instanceof AtomNotification_1.default; if (isPopup) { const sr = AtomUI_1.AtomUI.screenOffset(this.currentTarget); const x = sr.x; const y = sr.y; const h = sr.height; e.style.position = "absolute"; e.style.left = x + "px"; e.style.top = (y + h) + "px"; e.classList.add(theme.name); this.popups.push(popup); disposables.add(() => { this.popups.remove(popup); }); document.body.appendChild(e); if (isNotification) { e.style.opacity = "0"; this.centerElement(popup); } } else { const eHost = (options === null || options === void 0 ? void 0 : options.modal) ? null : this.getHostForElement(); if (eHost) { eHost.appendChild(e); } else { const host = document.createElement("div"); document.body.appendChild(host); host.style.position = "absolute"; host.appendChild(e); disposables.add({ dispose() { host.remove(); } }); this.refreshScreen(); popup.bind(host, "styleLeft", [["this", "scrollLeft"]], false, StyleBuilder_1.cssNumberToString, this.screen); popup.bind(host, "styleTop", [["this", "scrollTop"]], false, StyleBuilder_1.cssNumberToString, this.screen); popup.bind(host, "styleWidth", [["this", "width"]], false, StyleBuilder_1.cssNumberToString, this.screen); popup.bind(host, "styleHeight", [["this", "height"]], false, StyleBuilder_1.cssNumberToString, this.screen); } } this.currentTarget = e; popup.bindEvent(document.body, "keyup", (keyboardEvent) => { if (keyboardEvent.key === "Escape") { this.app.runAsync(() => this.remove(popup)); } }); disposables.add({ dispose: () => { e.innerHTML = ""; e.remove(); this.currentTarget = null; } }); return yield returnPromise; }); } centerElement(c) { const e = c.element; const parent = e.parentElement; if (parent === window || parent === document.body) { setTimeout(() => { const ew = (document.body.offsetWidth - e.offsetWidth) / 2; const eh = window.scrollY + ((window.innerHeight - e.offsetHeight) / 2); e.style.left = `${ew}px`; e.style.top = `${eh}px`; e.style.removeProperty("opacity"); }, 200); return; } if (parent.offsetWidth <= 0 || parent.offsetHeight <= 0) { setTimeout(() => { this.centerElement(c); }, 100); return; } if (e.offsetWidth <= 0 || e.offsetHeight <= 0) { setTimeout(() => { this.centerElement(c); }, 100); return; } const x = (parent.offsetWidth - e.offsetWidth) / 2; const y = (parent.offsetHeight - e.offsetHeight) / 2; e.style.left = `${x}px`; e.style.top = `${y}px`; e.style.removeProperty("opacity"); } }; /** * This is just to preload Alert window. */ WindowService.alertWindow = AtomAlertWindow_1.default; WindowService = __decorate([ RegisterSingleton_1.RegisterSingleton, __param(0, Inject_1.Inject), __param(1, Inject_1.Inject), __metadata("design:paramtypes", [App_1.App, JsonService_1.JsonService]) ], WindowService); exports.WindowService = WindowService; }); //# sourceMappingURL=WindowService.js.map