docs: function(json, opt, extraModes) {
          var viz = this.viz;
          var options = $.merge(this.options, viz.controller, opt), root = viz.root;
          var graph;
          //TODO(nico) this hack makes morphing work with the Hypertree. 
          //Need to check if it has been solved and this can be removed.
          viz.root = opt.id || viz.root;
          switch(options.type) {
              case 'nothing':
                  graph = viz.construct(json);
                  graph.eachNode(function(elem) {
                    var nodeExists = viz.graph.hasNode(elem.id);  
                    elem.eachAdjacency(function(adj) {
                      var adjExists = !!viz.graph.getAdjacence(adj.nodeFrom.id, adj.nodeTo.id);
                      viz.graph.addAdjacence(adj.nodeFrom, adj.nodeTo, adj.data);
                      //Update data properties if the node existed
                      if(adjExists) {
                        var addedAdj = viz.graph.getAdjacence(adj.nodeFrom.id, adj.nodeTo.id);
                        for(var prop in (adj.data || {})) {
                          addedAdj.data[prop] = adj.data[prop];
                        }
                      }
                    });
                    //Update data properties if the node existed
                    if(nodeExists) {
                      var addedNode = viz.graph.getNode(elem.id);
                      for(var prop in (elem.data || {})) {
                        addedNode.data[prop] = elem.data[prop];
                      }
                    }
                  });
                  viz.graph.eachNode(function(elem) {
                      elem.eachAdjacency(function(adj) {
                          if(!graph.getAdjacence(adj.nodeFrom.id, adj.nodeTo.id)) {
                              viz.graph.removeAdjacence(adj.nodeFrom.id, adj.nodeTo.id);
                          }
                      });
                      if(!graph.hasNode(elem.id)) viz.graph.removeNode(elem.id);
                  });
                  
                  break;
              
              case 'replot':
                  viz.labels.clearLabels(true);
                  this.morph(json, { type: 'nothing' });
                  viz.refresh(true);
                  viz.refresh(true);
                  break;
                  
              case 'fade:seq': case 'fade': case 'fade:con':
                  that = this;
                  graph = viz.construct(json);
                  //preprocessing for nodes to delete.
                  viz.graph.eachNode(function(elem) {
                    var graphNode = graph.getNode(elem.id);   
                    if(!graphNode) {
                        elem.setData('alpha', 1);
                        elem.setData('alpha', 1, 'start');
                        elem.setData('alpha', 0, 'end');
                        elem.ignore = true;
                      } else {
                        //Update node data information
                        var graphNodeData = graphNode.data;
                        for(var prop in graphNodeData) {
                          if(prop[0] == '$' && prop != '$type') {
                            elem.endData[prop] = graphNodeData[prop];
                          } else {
                            elem.data[prop] = graphNodeData[prop];
                          }
                        }
                      }
                  }); 
                  viz.graph.eachNode(function(elem) {
                      if(elem.ignore) return;
                      elem.eachAdjacency(function(adj) {
                          if(adj.nodeFrom.ignore || adj.nodeTo.ignore) return;
                          var nodeFrom = graph.getNode(adj.nodeFrom.id);
                          var nodeTo = graph.getNode(adj.nodeTo.id);
                          if(!nodeFrom.adjacentTo(nodeTo)) {
                              var adj = viz.graph.getAdjacence(nodeFrom.id, nodeTo.id);
                              fadeEdges = true;
                              adj.setData('alpha', 1);
                              adj.setData('alpha', 1, 'start');
                              adj.setData('alpha', 0, 'end');
                          }
                      });
                  }); 
                  //preprocessing for adding nodes.
                  var fadeEdges = this.preprocessSum(graph);
  
                  var modes = !fadeEdges? ['node-property:alpha'] : 
                                          ['node-property:alpha', 
                                           'edge-property:alpha'];
                  //Append extra node-property animations (if any)
                  modes[0] = modes[0] + ((extraModes && ('node-property' in extraModes))? 
                      $.splat(extraModes['node-property']).join(':') : '');
                  //Append extra edge-property animations (if any)
                  modes[1] = (modes[1] || 'edge-property:alpha') + ((extraModes && ('edge-property' in extraModes))? 
                      $.splat(extraModes['edge-property']).join(':') : '');
                  //Add label-property animations (if any)
                  if(extraModes && ('label-property' in extraModes)) {
                    modes.push('label-property' + $.splat(extraModes['label-property']).join(':'))
                  }
                  viz.reposition();
                  viz.graph.eachNode(function(elem) {
                      if (elem.id != root && elem.pos.getp().equals(Polar.KER)) {
                        elem.pos.set(elem.endPos); elem.startPos.set(elem.endPos);
                      }
                  });
                  viz.fx.animate($.merge(options, {
                      modes: ['polar'].concat(modes),
                      onComplete: function() {
                          viz.graph.eachNode(function(elem) {
                              if(elem.ignore) viz.graph.removeNode(elem.id);
                          });
                          viz.graph.eachNode(function(elem) {
                              elem.eachAdjacency(function(adj) {
                                  if(adj.ignore) viz.graph.removeAdjacence(adj.nodeFrom.id, adj.nodeTo.id);
                              });
                          });
                          options.onComplete();
                      }
                  }));
                  break;
  
              default:;
          }
      }