3.1.5 • Published 1 year ago

mnstr v3.1.5

Weekly downloads
178
License
MIT
Repository
-
Last release
1 year ago

What?

MNSTR is designed to render large lists of data in no time by only rendering what is actually visible in the viewport (like UITableView, for example). It does not require you to provide cell heights and keeps the amount of DOM elements as low as possible.

Demo

Specs

  • no dependencies
  • native browser scrolling
  • support for tree data
  • restorable state
  • responsive

Install

Download or clone this repository or use npm.

npm install mnstr

Webpack / ESM

import MNSTR from 'mnstr'

Note: Depending on your build target you might need to pass this module to babel.

RequireJS / Browserify

require('mnstr')

Browser

<script type="text/javascript" src="dist/mnstr.umd.js"></script>

Usage

Javascript

new MNSTR({
  parentNode: document.body,
  getData: _ => ['The', 'quick', 'brown', ...]
  getCellRenderer: element => {
    var node = document.createElement('span')
    node.innerHTML = element
    return node
  }
})

CSS

.mnstr {
  width: 100%;
  height: 100%;
}

Important: You need to set height or max-height of the list, or else it will just render all your data, not only what is its viewport. Also make sure that by the time the list renders (either when it is initialized or by calling render()), its parent is part of the DOM. Otherwise the list can not measure its or its cell heights.

Options

nametypedefaultdescription
contextobjectlistThe context that callbacks are called in.
parentNodeHTMLElementdocument.bodyThe DOM node this list will be appended to.
classNamestringmonsterlistCSS classname of the list and also the namespace for its children (e.g. monsterlist-cell for the cells).
renderOnInitializebooltrueIf true, the list will automatically be rendered when initialized. if false, use render() to render the list manually.
initialScrollToElementobject-Set the element (of your data) to which the list will automatically scroll when rendered the first time.
observeCellBoundsboolfalseIf true, an iFrame will be used for each cell to observe if the bounds change. Use this, if cell bounds are highly volatile. Caution: iFrame rendering is very expensive. This might cause initial rendering delays.
rememberChildrenExpandsbooltrueIf set and an expanded node, which has children that are also expanded, is collapsed and re-expanded, the children will be re-expanded, too.
updateThresholdRatiofloat0.5Ratio (proportional to the list height) at which the top and bottom update thresholds will be placed. Higher means more cells will be rendered at a time.
useTransformbooltrueUse transform instead of top to position cells. When using transform (default), z-index will break when trying to overlap subsequent cells. Using top will negatively impact performance, since we don't render cells on their own layer anymore.
virtualEnvironmentboolfalseSet this to true if MNSTR should be used in a vDOM environment like Vue or React, for example. Also make sure to implement needUpdateVirtualDOM (see callbacks below).

Methods

nameparameter typesdescription
render(parentNode)HTMLElement (optional)If renderOnInitialize is false, call this method to render the list. Make sure that by the time calling, the parent node is part of the DOM.
addEventListener(event, listener)string, functionSubscribe to an event. See the events section below for a list of available events.
removeEventListener(event, listener)string, functionUnsubscribe from an event.
getNode()Returns the root HTMLElement of the list.
needUpdate()Call this when you want the list to update its data but NOT to update the cells. Under normal circumstances update() is what you want, but sometimes you don't want the list to render the update immediately but do other things instead.
update(force, retainPosition)bool, boolCall this when your list data has been updated and you want the list to update, too. If you set force to true, all cells will be rerendered, even if their data item did not change. Setting retainPosition to true will make sure the list will not jump to the beginning after updating the data.
cellBoundsUpdated()Unless observeCellBounds is true, you need to call this every time a cell manually (not by resizing the whole list) changed its bounds. The list will then reposition all cells accordingly.
expandElement(element)objectExpands an element and exposes its children, fetched by getElementChildren directly below the elements cell.
collapseElement(element)objectDoes the opposite of the method above.
toggleExpandElement(element)objectToggle the things above.
isElementExpanded(element)objectReturns the current expand state of an element.
exportRestoreState()Retrieve an object which you can pass to restoreState() to restore the list state.
restoreState(state, parentNode)object, HTMLElement (optional)Pass the object from exportRestoreState() to restore the list state. Make sure that you passed the correct data in getData. Also set renderOnInitialize to false when restoring.
scrollToElement(element, options)object, object (optional)Scrolls the list to the given element. options are: nearest (bool. Determines if the list should scroll so that the element is placed at the top or bottom of the viewport, depending on the current elements position relative to the current scroll position), bottom (bool. Force to scroll so that the element is at the bottom of the viewport.), force (bool. Force to scroll, even if the element is already in the viewport.), offset (float. Adds an offset to the target scroll position.).
destroy()Not implemented yet. But it should be, right?

Callbacks

Pass callbacks along with args when initializing the list, as in the example above.

namereturn typedescription
getData(list)arrayRequired. If you want to display something and not to crash anything.
getCellRenderer(element, index, isExpanded, list)HTMLElement or stringRequired. Unless you still don't want to display anything.
getElementChildren(element, list)arrayOptional. Used for tree data.
needUpdateVirtualDOM(element, complete)void 0Required when MNSTR has to work within a virtual environment. elements is the current array of elements that need to be rendered. complete is the callback that needs to be called when rendering elements is complete.

Events

All events are also available as callbacks. For the sake of DRY they are not listed separately.

nameparametersdescription
didRenderFirstElementelement, listTriggered every time the first element of your data is rendered.
didRenderLastElementelement, listTriggered every time the last element of your data is rendered.
firstInBoundsElementChangedelement, listTriggered every time the first visible element of the list changed.
lastInBoundsElementChangedelement, listTriggered every time the last visible element of the list changed.
cellsUpdatedcells, listTriggered every time any cell has been updated. Cells is a sorted array of the DOM elements.

Tree data

The list is capable of handling tree data. Each cell has a data-level attribute, which indicates the level of the element. Root elements are level 0, their children are level 1 and so on. If there is a need to visualize a hierarchy, you can set styles for each level like this:

.mnstr-cell[data-level="1"] .myCellRenderer {
  padding-left: 25px;
}
.mnstr-cell[data-level="2"] .myCellRenderer {
  padding-left: 50px;
}

Remember that .mnstr is the default CSS class name / namespace. You can always provide another class name, if you wish. See options for details.

VDOM

Since 2.0 and ES6/ES8 features like promises and async/await MNSTR is designed to be compatible with environments that relay on virtual DOM (like Vue or React, for example). The setup is quite different, though. I'm working on wrappers for Vue and React along with comforting ways to create own wrappers or implementations. I will link them here when they are ready for usage.

Compatibility

All mature browsers and IE11+.

Downsides

None. Well, actually, there is one. MNSTR does not calculate its height by provided cell heights, it estimates by averages. When cell renderers have different heights, this might lead to scrollbar jumping at the end or the beginning of the list, as these are the moments where the deviations between estimating and the real world are corrected.

Limits

The browsers have a height limitation on DOM elements, it means that currently the list cannot display more than ~500k items depending on the browser.

Blink deferred a task [...]. When using MNSTR you may come across this (Chrome) or a similar warning. See https://stackoverflow.com/a/37367801/258931 on how to track if your cell renderers might be a cause for that. But don't panic. At least Chrome likes to trigger this warning even if there are no events taking more than 5ms.

General rule: Try to keep your cell renderers and the initialization of them as simple as possible. Try to test your list on slow devices or use cpu throttling.

License

MIT

3.1.5

1 year ago

3.1.4

3 years ago

3.1.3

3 years ago

3.1.2

4 years ago

3.1.1

4 years ago

3.1.0

4 years ago

3.0.9

4 years ago

3.0.8

4 years ago

3.0.7

4 years ago

3.0.6

4 years ago

3.0.5

4 years ago

3.0.4

4 years ago

3.0.3

4 years ago

3.0.2

4 years ago

3.0.1

4 years ago

3.0.0

4 years ago

2.0.2

5 years ago

2.0.1

5 years ago

2.0.0

5 years ago