# Popup (alert / confirm / prompt) Links: [Home](../index.md) Modal dialogs over a full-screen overlay: `alert()` with any number of buttons, `confirm()` (yes / no), `prompt()` (one text input) and a bare `popup()` you fill with your own DOM. Written by SGApps.IO; depends only on the framework's `extensions/prototype` (the `_()` DOM chain) and `uri-load` (for `elements/popup/style.css`). ## Loading the Module ```js Application.require("elements/popup").then(function (Popup) { // Popup is a plain object: { popup, alert, prompt, confirm } Popup.alert('Saved', 'Your document has been saved.'); }); ``` **Dependencies:** `extensions/prototype`, `uri-load`. The module links `elements/popup/style.css` (overlay, layout) when it loads. The dialog's look -- buttons, spacing, the icon font, the fade / bounce animation -- comes from the class names of the SGApps **RegalRoyal** theme (`rr-button`, `rr-block-space`, `rr-widget-box`, `rr-text-danger`, `websymbols`, `animated fadeIn` / `bounceIn`, `regal-royal--dark-theme`); with the theme stylesheet on the page (`https://sgapps.io/addons/RegalRoyal/styles/less/style.less.cache.css`) the dialogs look as in the playground, without it they get the browser's default buttons and no animation. The module works either way. ## The dialog structure Every dialog is one `` overlay appended to `document.body` by `show()` and removed by `hide()`: ```html
popup.space -- fixed, full screen, z-index 30199999, white 89 % + texture
-- the backdrop: click handling (see onOutsideClick)
popup.body -- the dialog box (50 % width, 350-800 px), theme classes go here
popup.header
popup.content / popup.container -- your content, max-height 80vh, scrolls popup.footer -- the buttons
``` ## API ### `Popup.popup([node], [showOnLoad])` Builds a bare dialog and returns the **popup object**. | Parameter | Type | Default | Description | |---|---|---|---| | `node` | `HTMLElement` | -- | Appended into `popup.content` when given | | `showOnLoad` | `boolean` | `true` | `false` builds the dialog without showing it; `true` or omitted calls `show()` right away | ```js var content = document.createElement('div'); content.innerHTML = '

Custom content

Any DOM goes here.

'; var popup = Popup.popup(content); // shown immediately popup.footer.appendChild(closeButton); // build your own buttons popup.theme('dark'); ``` #### The popup object | Member | Type | Description | |---|---|---| | `show()` | method | Appends the overlay to `document.body` (no-op when already attached) | | `hide()` | method | Removes the overlay from the DOM (the object stays usable, `show()` brings it back) | | `theme(name)` | method | `'light'` -- `regal-royal` on the body, dark class removed; `'dark'` -- adds `regal-royal--dark-theme`; `'clean'` -- removes both classes. Anything else is ignored | | `space` | `HTMLTableElement` | The overlay (`.module__widget_popup`) | | `body` | `HTMLDivElement` | The dialog box (`.regal-royal`) -- getter | | `header` | `HTMLDivElement` | `.module__widget_popup_controls` -- getter | | `content`, `container` | `HTMLDivElement` | `.module__widget_popup_content` -- `content` is a getter, `container` the same node as a plain property | | `footer` | `HTMLDivElement` | `.module__widget_popup_footer` -- getter | | `onOutsideClick` | `boolean` or `function(popup, isBackdrop)` | Click handling on the backdrop cell, see below. Default `true` for `popup()`, `false` for `alert()` / `confirm()` / `prompt()` | `header`, `content`, `body` and `footer` also have **setters, which do not work** (a string is silently dropped, a node is inserted as the text `[object HTMLElement]`). Always write through the getters: `popup.content.innerHTML = '...'`, `popup.footer.appendChild(button)`. #### `onOutsideClick` The `` that fills the overlay listens to `click`: | `popup.onOutsideClick` | Effect of a click | |---|---| | `false` | a click on the backdrop itself (outside the dialog box) calls `hide()`; clicks inside the box do nothing | | `true` | nothing (the dialog can only be closed by its buttons or by `hide()`) | | `function` | called for **every** click inside the overlay, inside the box included: `fn.call(td, popup, isBackdrop)` with `isBackdrop === true` when the click hit the backdrop -- decide yourself what to do | `popup()` starts with `true` (backdrop clicks ignored); `alert()` (and therefore `confirm()` / `prompt()`) sets it to the **negation** of its `onOutsideClick` configuration key, so an alert closes on a backdrop click by default. ### `Popup.alert(title, [text], [callback])` / `Popup.alert(config)` Builds a dialog with an icon, a title, a text and a row of buttons, shows it and returns the popup object (extended with `attachButton()` and `buttons`). The first two arguments are flexible: a **string** is the title / text, an **Element** is inserted as is, a **function** becomes the callback of a single OK button, and a plain **object** is merged into the configuration -- so `alert('Title', 'Text')`, `alert('Title', 'Text', onOk)`, `alert({ title: ..., buttons: [...] })` and `alert(titleNode, { theme: 'dark' })` are all valid. | Config key | Type | Default | Description | |---|---|---|---| | `title` | string, Element | `""` | Title line. With `html: true` a string is inserted as HTML | | `text` | string, Element, `false` | `""` | Body text (a string is wrapped in `
`); with `html: true` inserted as HTML | | `icon` | string, Element | `"N"` | A **websymbols glyph**: `" [colour]"`, e.g. `"N danger"` -- the first token is the glyph, the second becomes the class `rr-text-` (`regular` when omitted). An Element is inserted as is; with `html: true` the string is inserted as HTML. Falsy: no icon | | `theme` | string | `""` | Passed to `popup.theme()` when set: `'light'`, `'dark'`, `'clean'` | | `buttons` | Array | `[{ text: 'OK', callback: hide, focused: true }]` | Button configurations, see `attachButton()`. An empty array gives a dialog without buttons | | `html` | boolean | `false` | Insert `title`, `text` and `icon` strings as HTML instead of text | | `focus` | boolean | `true` | Focus the button whose configuration has `focused: true` after showing | | `focusWindow` | boolean | `true` | Call `window.focus()` after showing | | `animate` | boolean | `true` | Add `animated fadeIn` to the overlay and `animated bounceIn` to the box (theme classes; the icon also gets `rotateInDownLeft`) | | `visible` | boolean | `true` | Show the dialog now; `false` builds it hidden -- call `popup.show()` later | | `onOutsideClick` | boolean, function | `false` | Close on a backdrop click? `true` **and omitted**: a click on the backdrop (outside the box) closes the dialog; `false`: backdrop clicks are ignored; a function is stored as is and called with `(popup, isBackdrop)` for every click in the overlay. (A boolean you pass is stored **negated** in `popup.onOutsideClick`, where `false` means "closes" -- see above; the default configuration is that internal `false`, hence "omitted" behaves like `true`) | The generated content, inside `popup.content`: ```html
N
Delete 3 files?
This cannot be undone.
``` #### `popup.attachButton(buttonConfig)` and `popup.buttons` `alert()` runs every entry of `config.buttons` through `attachButton()`; you can call it later to add more. | Button config key | Type | Default | Description | |---|---|---|---| | `text` | string, Element | `""` | Label | | `callback` | `function (event, button)` | `function () { this.hide(); }` | Called with `this` = the popup object. Its return value is returned from the click handler (return `false` to cancel the event's default) | | `className` | string | `""` | Extra class(es) on the `