 class window.DomTextMapper
   constructor: ->
     @setRealRoot()
+    @restrictToSerializable false
 
   # ===== Public methods =======
+
+  # Switch the library into "serializable-only" mode.
+  # If set to true, all public API calls will be restricted to return
+  # strictly serializable data structures.
+  # (References to DOM objects will be omitted.)
+  restrictToSerializable: (value = true) -> @restricted = value
 
   # Consider only the sub-tree beginning with the given node.
   # 

  # If no path is given, the whole sub-tree is scanned,
  # starting with the configured root node.
  #
  # The "rescan" parameter specifies whether the scan should be run again
  # even if the specified region is the same one that has been scanned
  # the last time.
  #
  # Nothing is returned; the following properties are populated:
  #
  #  mappings will contain the created mappings
  #  corpus will contain the text content of the selected path# 
  #  scannedPath will be set to the path
  scan: (path = null, rescan = false) ->
    path ?= @getDefaultPath()
    if path is @scannedPath and not rescan then return
#    console.log "Scanning path: " + path
    node = @allPaths[path].node
    @mappings = {}
    @saveSelection()        
    @collectStrings node, path, null, 0, 0
    @restoreSelection()
    @scannedPath = path
    @corpus = @mappings[path].pathInfo.content
#    console.log "Corpus is: " + @corpus
    null

  getRangeForPath: (path) -> @mappings[path]

  # Get the matching DOM elements for a given text range
  # 
  # If the "path" argument is supplied, scan is called automatically.
  # (Except if the supplied path is the same as the last scanned path,
  # and rescan is false.)
  getMappingsForRange: (start, end, path = null, rescan = false) ->
    unless (start? and end?) then throw new Error "start and end is required!"    
#    console.log "Collecting matches for [" + start + ":" + end + "]"    
    if path?
      @scan(path, rescan) 
    else
      if not @scannedPath?
        throw new Error "Can not run getMappingsFor() without existing mappings. Either supply a path to scan, or call scan() beforehand!"

    # Collect the matching mappings     
    matches = []
    for p, mapping of @mappings when mapping.atomic and @regions_overlap mapping.start, mapping.end, start, end
      do (mapping) =>
        match =
          element: mapping
        full_match = start <= mapping.start and mapping.end <= end

    cont = @getNodeContent node, false
    if cont.length then results[path] =
      path: path
      content: cont
      length: cont.length
      node : node
    
    if node.hasChildNodes
      children = node.childNodes
      i = 0
      while i < children.length
        @collectPathsForNode children[i], results
        i++
    results

