     @getMappedData = (url, pin, map={}, wrap=true) =>
       @getData url, (data) => @mapData(data, pin, map, wrap)
 
-    # Parse a flat node list, injecting children arrays for traversal
+    # Parse node array into a flat, keyed boject, injecting children for traversal
     @parseNodes = (data, pin, keyed={}) ->
       root = {}
 

          $("#indexInputModal").modal "hide"
          console.log "Error (#{jqXHR.status}): errorThrown"

    @ # Return ourself

  popoverOptions =

        else # Invalid root node!
          delete keyed[id] # Pew Pew!

      # And run a chillin' parseage
      for id of keyed
        parseChildren keyed[id]

      pin keyed if pin? # Update pin with keyed
      root # Return root for mapping

    # Process nodes and map to pin
    @updateNodes = (data, pin, keys) =>
      @mapData @parseNodes(data, pin, keys), pin

    # Get and process nodes from url
    @getNodes = (url, pin, keys) =>
      @getData url, (data) =>
        @updateNodes data, pin, keys

    # Temp storage for node mapping
    @wsTemp = ko.observableArray()
    # Computed wrapper for coalescing changes
    @wsItems = ko.computed =>
      @wsTemp()
    # Enable coalesced node changes (x msec settling period)
    @wsItems.extend throttle: config?.coalesce ? 500

    # Execution plans
    @wsPlans = ko.observableArray()

    # Flat node list, keyed by id
    @wsKeys = {}

    @poll = (url, cb, timeout=@config?.timeout?.long ? 30000) =>
