npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

miller-columns

v0.17.0

Published

Miller Columns in ES6 Modules JavaScript

Readme

miller-columns

ES6 Modules adaptation and expansion of http://jsfiddle.net/yckart/cbtnemc7/

Screenshots

Multiple columns

Features

  • Good output for styling control
    • Works with semantically correct <ul> (or <ol>) lists
    • Well-namespaced CSS classes and data-* attributes ("miller-" by default).
    • Available stylesheet for basic styling
  • Keyboard control
    • Using up/down/right/left arrows for navigation
    • Using escape key for resetting to beginning
    • Type not only first letter, but buffering to allow multiple keystrokes rapidly after one another for items sharing the same initial letters
  • Mouse control
    • Click listeners for navigation, including on any breadcrumbs
  • Complementary navigation controls
    • Default ability to display breadcrumbs (overridable)
  • Reasonable ancillary behaviors/features
    • Auto-selection of first item if none chosen
    • Default ability to reset the column browser when clicking within the browser area but not on a column
    • Default ability for animation (or overridable), including setting the delay
    • Ability to register callback to be triggered with current selection (or upon reset)

Installation

npm install miller-columns --save

Set-up

ES6 Module-supporting browsers

<!-- See comment in JavaScript example on current need for this here-->
<script src="node_modules/jquery/dist/jquery.js"></script>
<!-- Let your main.js do the imports as in the example below -->
<script type="module" src="main.js"></script>

Older browsers

<script src="node_modules/jquery/dist/jquery.js"></script>
<script src="node_modules/miller-columns/dist/index-umd.js"></script>
<script src="main.js"></script>

Expected HTML data format

In order to take advantage of the default stylesheet, you should:

  1. Put the class miller-columns on the element on which you will invoke our jQuery plug-in for adding Miller columns. The nestable <ul> or <ol> lists you create (with <li> children) will be automatically given the miller-column and possibly the miller-collapse class and its <li> any of these classes: miller-parent or miller-selected. If you do not wish one of the lists within miller-columns to be treated as part of the Miller columns, give it a miller-no-selected class.
  2. Add miller-breadcrumbs for whichever element you want to be the container for breadcrumbs. Those individual breadcrumbs will be given the miller-breadcrumb class and will be added automatically.

Note that miller-breadcrumbs is the only class expected to be present by our JavaScript code, and that is only if you are not overriding the breadcrumbs option, and also if you have not changed the default namespace to something other than "miller".

(Also as far as namespacing, the library uses jQuery's .data() with miller-ancestor and miller-child (which can also be altered by the namespace option), but these are stored internally by jQuery).)

Example (ES6)

// Though on Roadmap for 3.4.0 (see https://github.com/jquery/jquery/wiki/Roadmap),
//  jQuery doesn't have ES6 either as source or in a distribution, so you
//  currently have to use Rollup with CommonJS plugins to get this next line
//  working (or just add the script non-modularly to HTML and use the global `$`)
import $ from 'jquery';

import addMillerColumnPlugin from './node_modules/miller-columns/dist/index-es.min.js';

// The second options argument is optional
await addMillerColumnPlugin($, {stylesheets: ['path/to/extra-stylesheet.css', '@default']});

$('div.miller-columns').millerColumns({
  // Options:
  current ($item, $cols) {
    console.log('User selected:', $item);
  }
});

Constructor

Returns a promise resolving when all supplied stylesheets (if any) have been loaded.

  • $ - The instance of jQuery to which you are adding the plug-in.
  • options
    • stylesheets - An optional array of stylesheet paths to be loaded in parallel. Is meant for this plug-in, but you could include any stylesheets to benefit from them loading together in parallel. Using @default will provide (an attempt to) load the default stylesheet. Due to current browser limitations, we can only guess the location of our module URL.
    • namespace - Defaults to miller. The default must be kept if one wishes to use the provided miller-columns.css stylesheet without modification.

Plugin options

  • animation - Optional callback for ensuring the viewport shows the entire newly expanded item. Defaults to an internal method. Passed the column item and columns jQuery objects as arguments.
  • breadcrumb - Optional callback for adding the breadcrumb path using the chain of selected items. Defaults to an internal method. Optionally passed the columns jQuery object as an argument.
  • breadcrumbRoot - Optional string that defines the text to display as the root link at the start of the breadcrumb path. Clicking this link resets the column browser. Set to an empty string to disable the root link. Defaults to "Root".
  • current - Optional callback; defaults to a noop. Called upon selection. Passed the column item and columns jQuery object as arguments.
  • reset - Optional callback; defaults to a noop. Called upon reset (by user hitting escape key or any time clicking an element). Passed the columns jQuery object and resetByUser boolean indicating whether this reset was user-initiated (true) or an internally-generated rebuild (false) as arguments
  • preview - Optional callback; defaults to null. Passed the column item and columns jQuery object as arguments. The return result should be an HTML string which is used to fill the list item which functions as the preview pane when selecting a final item (an item without children).
  • onPreview - Optional callback; defaults to null. Passed the event object and the <ul> and columns jQuery objects as arguments. Called upon clicking the preview pane.
  • delay - Optional integer indicating animation delay. Defaults to 500ms.
  • outsideClickBehavior - Optionally set to "reset" to have the column browser reset to the beginning upon clicking within the columns area where it is not a column. If set to select-parent, will select the parent column where the node was clicked. If set to none, will do nothing. Defaults to "select-parent".

Dynamic Item Management

After initializing the miller-columns plugin, you can dynamically add new items:

addItem(item, $parent)

Adds a new item to the column browser. The item can contain nested lists which will be automatically unnested and integrated into the column structure.

Parameters:

  • item (string | jQuery) - An HTML string or jQuery element representing the new list item (<li>). Can include nested <ul> or <ol> elements.
  • $parent (jQuery, optional) - A jQuery object representing the parent item to which this item should be added as a child. If omitted, the item is added to the root level (first column).

Returns: jQuery object representing the newly added item.

Example:

const $columns = $('div.miller-columns').millerColumns({
  current ($item, $cols) {
    console.log('User selected:', $item);
  }
});

// Add a simple item to the root level
$columns.addItem('<li><a href="#">New Root Item</a></li>');

// Add an item with nested children (automatically unnested)
$columns.addItem(`
  <li><a href="#">Parent Item</a>
    <ul>
      <li><a href="#">Child 1</a></li>
      <li><a href="#">Child 2</a>
        <ul>
          <li><a href="#">Grandchild</a></li>
        </ul>
      </li>
    </ul>
  </li>
`);

// Add a child to an existing item
const $existingParent = $('.miller-column li').first();
$columns.addItem('<li><a href="#">New Child</a></li>', $existingParent);

The addItem method automatically:

  • Unnests any nested lists within the new item
  • Preserves hierarchy through data attributes
  • Sets up proper parent-child relationships
  • Adds appropriate CSS classes
  • Registers click event handlers
  • Integrates seamlessly with existing column navigation

destroy()

Destroys the miller-columns instance and restores the original structure. This method removes all event handlers, data attributes, CSS classes, and structural changes made by the plugin.

Returns: jQuery object with the original structure restored.

Example:

const $columns = $('div.miller-columns').millerColumns({
  current ($item, $cols) {
    console.log('User selected:', $item);
  }
});

// Use the columns...

// Later, clean up and restore original structure
$columns.destroy();

The destroy method:

  • Removes all event handlers (click, keydown)
  • Restores the original nested HTML structure
  • Removes all CSS classes (miller-column, miller-collapse, miller-parent, miller-selected)
  • Removes all data attributes (miller-ancestor, miller-child)
  • Removes preview columns
  • Removes the addItem and destroy methods themselves

To-dos

  1. Stop jolting when switching between those with preview panes at same level and which are already scrolled (new scrollIntoView code?)
  2. Any way to avoid restructuring of DOM for sake of accessibility?
  3. Support JSON (as with routine for converting internally to HTML)
    1. Parse lazily from JSON (or HTML) data sources (using ES6 generator)
  4. Allow for Preview column for <ul>/<ol>
  5. Support <dl> parsing with <dt> as text that shows and <dd> as meta-data to show in where the Mac Finder would show its preview area
  6. Editing
    1. Option to create
    2. Option to delete
    3. Option to rename (and trigger event) by clicking into cell
    4. Option to move (by drag and drop and cut-paste key commands)
  7. Adapt from https://bitbucket.org/brettz9/colbrowser?