HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Algorithmic simplification of Miller Columns

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
algorithmicmillercolumnssimplification

Problem

Background

Unsatisfied with existing implementations of Miller Columns (used to edit hierarchical data), I decided to re-invent the wheel.

Problem

Most of the existing implementations are too complex, offer extraneous functionality, reliance on complex (or unavailable) frameworks, have numerous dependencies, are riddled with severe bugs, or require non-hierarchical data.

Source

The source code has two parts. The JavaScript code performs a breadth-first traversal of an arbitrarily nested set of lists and wraps them into a consecutive, flattened hierarchy surrounded by div tags. The CSS code places the divs in left-floating columns (and applies superficial presentation items).



`(function( $ ) {
$.fn.millerColumns = function() {
var $list = $(this).first();
var $columns = $(this);

// Breadth-first traversal to rearrange list items into
// consecutively ordered div wrapper elements.
while( ($list = $list.children()).length ) {
$list.each( function( index, element ) {
var $parent = $(element).parent();

if( $(element).is( "li" ) ) {
$parent = $($parent).parent();
}

// Store the parent id for showing child columns.
var id = $($parent).attr( "id" );

if( $(element).is( "ul" ) ) {
// The parent element shall be marked as 0.
if( id === undefined ) {
id = 0;
}

var $item = $("li#" + id);
$item.addClass( "parent" );

$item.on( "click", function() {
// Hide everything.
$("div.column[data-parent!=0]").addClass( "collapsed" );
$("li").removeClass( "selection" );

// The "id" for the clicked list item becomes the start of
// the ancestral chain.
var $child = $("div.column[data-parent=" + id + "]" );
$child.removeClass( "collapsed" );

var $li = $("li.parent[id=" + id + "]");
var $ancestor = $li.parent().

Solution

A few observations :

  • You should be able to write this so that it doesn't rely on id. The code should be able to detect the hierarchy without being told.



  • Several chaining simplifications are possible - eg. var $breadcrumb = $("div.breadcrumb").empty()



  • Vars should be declared up front in their respective functions, in a single var statement.



  • Combined assignment and test is bad practice and makes code hard to read - while( ($list = $list.children()).length ) {.



  • $ancestor.data('parent') is much more efficient than $ancestor.attr('data-parent') The former involves only javascript while the latter involves the DOM.



  • The need to clone jQuery objects is rare - As far as I can see, $($parent) will simplify to $parent without consequence.

Context

StackExchange Code Review Q#70788, answer score: 3

Revisions (0)

No revisions yet.