     @rootNode = document
     @pathStartNode = @getBody() 
 
+  # Notify the library that the document has changed.
+  # This means that subsequent calls can not safely re-use previously cached
+  # data structures, so some calculations will be necessary again.
+  #
+  # The usage of this feature is not mandatorry; if not receiving change notifications,
+  # the library will just assume that the document can change anythime, and therefore
+  # will not assume any stability.
+  documentChanged: ->
+    @lastDOMChange = @timestamp()
+    console.log "Registered document change."
+
   # The available paths which can be scanned
-  # 
+  #
   # An map is returned, where the keys are the paths, and the values are objects with the following fields:
   #   path: the valid path value
   #   node: reference to the DOM node
   #   content: the text content of the node, as rendered by the browser
   #   length: the length of the next content
   getAllPaths: ->
+#    console.log "in getAllPaths"
+    if @domStableSince @lastCollectedPaths
+      # We have a valid paths structure!
+#      console.log "We have a valid cache."
+      return if @restricted then @cleanPaths else @allPaths
+
+    console.log "No valid cache, will have to calculate getAllPaths."
     @saveSelection()
     @allPaths = @collectPathsForNode @pathStartNode
     @restoreSelection()
-    @allPaths
+    @lastCollectedPaths = @timestamp()
+    if @restricted
+      @cleanPaths = {}
+      for path, info of @allPaths
+        cleanInfo = $.extend({}, info);
+        delete cleanInfo.node
+        @cleanPaths[path] = cleanInfo
+      @cleanPaths
+    else
+      @allPaths
 
   # Return the default path
   getDefaultPath: -> @getPathTo @pathStartNode
 
   # Select the given path (for visual identification), and optionally scroll to it
-  selectPath: (path, scroll = false) -> @selectNode @allPaths[path].node, scroll
+  selectPath: (path, scroll = false) ->
+    info = @allPaths[path]
+    @selectNode info.node ? @lookUpNode info.path
 
   # Scan the given part of the document.
   # 


  # Convert "display" text indices to "source" text indices.
  computeSourcePositions: (match) ->
    sourceText = match.element.pathInfo.node.data.replace /\n/g, " "
    # the HTML source of the text inside a text element.

    displayText = match.element.pathInfo.content
    # what gets displayed, when the node is processed by the browser.

    displayStart = if match.start? then match.start else 0
    displayEnd = if match.end? then match.end else displayText.length
    # The selected range in displayText.

    sourceIndex = 0
    displayIndex = 0

        endOffset: endOffset
        endInfo: endInfo
    }
#    console.log "Done collecting"
    result

  # ===== Private methods (never call from outside the module) =======

  timestamp: -> new Date().getTime()

  domChangedSince: (timestamp) ->
#    console.log "Has the DOM changed since " + timestamp + "?"
    if @lastDOMChange? and timestamp? then @lastDOMChange > timestamp else true
#    if @lastDOMChange? and timestamp?
#      console.log "We have a timestamp, checking..."
#      result = @lastDOMChange > timestamp
#      console.log result
#    else
#      console.log "We don't have a timestamp (or a reference), assuming it has changed."
#      true        

  domStableSince: (timestamp) -> not @domChangedSince timestamp

  getProperNodeName: (node) ->
    nodeName = node.nodeName
