Skip to content

Library: popup

Eugene Lazutkin edited this page Mar 31, 2020 · 11 revisions

popup module is a library to control a pop-up singleton, which is a container to host other content. Only one popup can be shown a time. It is a foundation of reno-popup.

Usage

In a module-enabled environment (like Babel) it can be accessed like that:

import * as popup from '@researchnow/reno/src/utils/popup';

In global-based environments (like a browser) it is frequently mapped to Reno.utils.popup.

open(options)

This function shows a popup. It takes the following arguments:

  • options is an object with the following properties:
    • anchor is a DOM node to use as an anchor for a popup.
    • content is a value accepted by hyperHTML as a possible content of a popup. For example, it can be a string or a DOM node.
      • If it is a DOM node, it will be appended to a popup, then discarded.
    • data is an optional data source.
    • loading is an optional value accepted by hyperHTML as a placeholder, which can be used to load an asynchronous content.
      • If it is a DOM node, it can be appended to a popup, then discarded.
    • placement is an optional string, which defines a position where to show a popup in relation to anchor:
      • left — on the left.
      • right — on the right.
      • top — at the top;
      • bottom (the default) — at the bottom.
      • If a popup becomes outside of the visible portion of a screen, it is repositioned on the opposite side.
    • alignment is an optional string, which defines how to align a popup on anchor's side defined by placement:
      • left — move to the far left.
      • right — move to the far right.
      • top — move to the top.
      • bottom — move to the bottom.
      • center (the default) — centered horizontally (for top/bottom placement) or vertically.
    • eventHandler(evt) is an optional function, which is called when a user clicks inside of a popup. It takes one argument: an original event object. The default does nothing.

open() uses a DOM node with the reno-popup-container identifier attached to a document of node. If it is not there, <div id="reno-popup-container"> is created and attached to the body. Usually, the container is absolutely positioned.

If a data source is defined, it is assumed to be a function, which is called without arguments to produce a content. Otherwise, a content is used.

The content produced by a data source can be any type consumed by hyperHTML: a text, a DOM node, a Promise instance, which eventually returns a text or a DOM node. The same is true for a loading placeholder.

close(doc)

This function hides a popup. It takes the following arguments:

  • doc is an optional document, which should be used to find a popup. The default: document.

isOpen(doc)

This function returns a boolean value: truthy when a popup is created and open or falsy otherwise. It takes the following arguments:

  • doc is an optional document, which should be used to find a popup. The default: document.

enhanceListContent(data, clickCallback, render=defaultRender, selector='[renoindex]')

This is a helper function, which renders data using render(), then it calls clickCallback() when a user clicks on rendered DOM nodes that satisfy CSS selector. It is frequently used to show search results, e.g., with reno-search.

It takes the following arguments:

  • data is an opaque data source. If it is a Promise instance, it will be resolved eventually and the result will be passed to render.
  • clickCallback is a function, which is called when a user clicked a specially marked DOM node. It will be called with the following arguments:
    • a clicked node
    • a data property, which value is identified in an attribute defined by selector.
  • render is a function, which takes data and returns a DOM node that represents it. The default:
    • data is assumed to be an array, the following template is used:
      <div class="content list">
        // data content
      </div>
    • a data content can be:
      • a list of items <div renoindex="${index}">${value.name}</div>, where value is an array item, and index is an item's index in the array.
      • for empty arrays it is <div>No results found.</div>.
  • selector is a CSS selector to find a clicked DOM node. The default render() assumes that it is always in the form [attributeName]. The default: [renoindex].

It returns a Promise object, which eventually resolves to a DOM node with a visual representation of data and can be used to select individual items.

hidePopup(evt)

This is a helper function, which helps to close a popup when a user clicks outside of it.

It takes the following arguments:

  • evt is an event object, which is produced by user's actions.

hidePopup() checks if evt.target is not a descendant of the popup and closes it or ignore the event otherwise.

CSS

The following CSS variables are used by popups:

  • $reno-popup-default-padding is used for most padding around the popup. It uses $reno-spacing-default.
  • $reno-popup-double-padding is occasionally used when more padding is needed around the popup. It is double the value of $reno-popup-default-padding.

The following CSS classes are used by popups:

  • On body:
    • reno-popup-open is used when there is a visible popup.
    • reno-popup-close is used when a popup is closed.
      • This CSS class is assigned only when a popup is closed. Before showing any popups it is not present.
      • It is better to use reno-popup-open and its absence for styling open popups, and surroundings.
  • On div with class child-container:
    • padd-top adds $reno-popup-default-padding to the top.
    • height-padd adds -$reno-popup-default-padding to the bottom. This is used in conjunction with a max-height.
    • height-dbl-padd adds -$reno-popup-double-padding to the bottom. This is used when aligning popups to the top of the page because there are so many items inside that it needs more room.
    • width-padd adds $reno-popup-default-padding to the right. This is used in conjunction with a max-width.
    • padd-left adds $reno-popup-default-padding to the left.

The default styling can be found in https://github.com/researchnow/reno/blob/master/src/styles/popup.scss

Examples

This example is similar to the demo: https://researchnow.github.io/reno/pages/component-popup.html

<div id="search-popup" alignment="left">
  <reno-search placeholder="Placeholder"></reno-search>
  <div class="content" url="data/data.json"></div>
</div>
const handle = on(document, 'click', Reno.utils.popup.hidePopup);

const popupComponent = document.getElementById('search-popup');
popupComponent.addEventListener('reno-change', function(e) {

  const popupContent = popupComponent.querySelector('.content') || popupComponent;
  const url = popupContent && popupContent.getAttribute('url') || 'data/data.json';

  // customize these
  const data = heya.io.get(url).
    then(data => data
      .filter(item => item.name.toLowerCase().includes(e.detail.value.toLowerCase()))
      .map(item => ((item.id = item.name), item))
    );
  const clickCallback = (node, item) => {
    on.closest(e.target, 'reno-search').setAttribute('value', '');
    alert(JSON.stringify(item, null, '  '));
  };

  Reno.utils.popup.open(popupComponent.querySelector('reno-search'), {
    data: () => Reno.utils.popup.enhanceListContent(data, clickCallback)
  });
  Reno.utils.popup.isOpen() && e.detail.value == '' && Reno.utils.popup.close();
});

Clone this wiki locally