docs: function(self, session) {
      var container = session.container;
  
      var i, r, node, nodeSelection;
      // collect information about deletions during the check
      var cmds = [];
      var viewEditor = _getEditor(self, {type: "view", id: container.name});
  
      var nodeSelections = session.selection.getNodeSelections();
      var first = nodeSelections[0];
      var last = nodeSelections[nodeSelections.length-1];
  
      // Preparation: check that all deletions can be applied and
      // prepare commands for an easy deletion
      for (i = 0; i < nodeSelections.length; i++) {
        nodeSelection = nodeSelections[i];
        node = nodeSelection.node;
        var canDelete;
        var editor;
  
  
        // if it is a full selection schedule a command to delete the node
        var isFull = nodeSelection.isFull();
  
        // HACK: if the last is an empty node it will show always as fully selected
        // In that case it should remain only if the first one is fully selected.
        if (isFull && nodeSelection === last && first.isFull() &&
            nodeSelection.ranges.length === 1 &&
            nodeSelection.ranges[0].component.length === 0) {
          isFull = false;
        }
  
        if (isFull) {
          editor = viewEditor;
          canDelete = editor.canDeleteNode(session, node);
          cmds.push({type: "node", editor: editor, node: node});
  
          if (!canDelete) {
            // TODO: we need add a mechanism to provide a feedback about that, e.g., so that the UI can display some
            // kind of messsage
            console.log("Can't delete node:", node);
            return false;
          }
        }
        // otherwise schedule a command for trimming the node for each of the
        // node's component.
        else {
          editor = _getEditor(self, node);
  
          for (var j=0; j<nodeSelection.ranges.length; j++) {
            r = nodeSelection.ranges[j];
            canDelete = editor.canDeleteContent(session, r.component, r.start, r.end);
            cmds.push({type: "content", editor: editor, range: r});
  
            if (!canDelete) {
              console.log("Can't delete component:", r.component);
              return false;
            }
          }
        }
      }
  
      // If the first and the last selected node have been partially selected
      // then we will try to join these nodes
      var doJoin = (first && first.isPartial() &&
                    last && last.isPartial());
  
      // Perform the deletions
  
      // ATTENTION: we have to perform the deletions in inverse order so that the node positions remain valid
      for (i = cmds.length - 1; i >= 0; i--) {
        var cmd = cmds[i];
  
        if (cmd.type === "content") {
          r = cmd.range;
          cmd.editor.deleteContent(session, r.component, r.start, r.end);
        } else {
          node = cmd.node;
          cmd.editor.deleteNode(session, node);
          // TODO: in theory it might be possible that nodes are referenced somewhere else
          // however, we do not yet consider such situations and delete the node instantly
          session.document.delete(node.id);
        }
      }
  
      // ATTENTION: after this point the range objects are invalid as some components may have been deleted
  
      // Perform a join
      if (doJoin) {
        _join(self, session, first.node, last.node);
      }
  
      return true;
    }