           $("#indexInputModal").modal "hide"
           console.log "Error (#{jqXHR.status}): errorThrown"
 
+    ko.bindingHandlers.sortable.afterMove = (options) =>
+      parent = options.sourceParentNode.attributes["data-id"].value
+      ntrapy.post "/roush/facts/",
+        JSON.stringify
+          key: "parent_id"
+          value: parent
+          node_id: options.item.id()
+      , (data) ->
+        null # TODO: Do something with success?
+      , (jqXHR) =>
+        console.log "Error: ", jqXHR
+        @updateNodes null, @wsTemp, @wsKeys # Remap from keys on fails
+
     @ # Return ourself
 
   popoverOptions =

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

      for id of keyed
        parseChildren keyed[id]

      pin keyed if pin? # Update pin with keyed
      children: root # Return in format appropriate for mapping

    @updateNodes = (data, pin, keys) =>
      @mapData @parseNodes(data, pin, keys), pin

    @getNodes = (url, pin, keys) =>
      @getData url, (data) =>
        @updateNodes data, pin, keys

    @wsTemp = ko.observableArray()
    @wsItems = ko.computed(=>
      @wsTemp()?[0]?.children ? []).extend throttle: 100 # Coalesce node changes

    @wsPlans = ko.observableArray()
    @wsKeys = {}

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

    @getMappedData = (url, pin, map={}, wrap=true) =>
      @getData url, (data) => @mapData(data, pin, map, wrap)

    # Parse node array into a flat, keyed boject, injecting children for traversal
    @parseNodes = (data, pin, keyed={}) ->
      root = {}

