docs: function( options ){
        var eles = this;
  
        options = $$.util.extend({
          includeNodes: true,
          includeEdges: true,
          includeLabels: true
        }, options);
  
        // recalculate projections etc
        this.cy().recalculateRenderedStyle();
  
        var x1 = Infinity;
        var x2 = -Infinity;
        var y1 = Infinity;
        var y2 = -Infinity;
  
        // find bounds of elements
        for( var i = 0; i < eles.length; i++ ){
          var ele = eles[i];
          var ex1, ex2, ey1, ey2, x, y;
          var includedEle = false;
  
          if( ele.css('display') === 'none' ){ continue; } // then ele doesn't take up space      
  
          if( ele.isNode() && options.includeNodes ){
            includedEle = true;
  
            var pos = ele._private.position;
            x = pos.x;
            y = pos.y;
            var w = ele.outerWidth();
            var halfW = w/2;
            var h = ele.outerHeight();
            var halfH = h/2;
  
            // handle node dimensions
            /////////////////////////
  
            ex1 = x - halfW;
            ex2 = x + halfW;
            ey1 = y - halfH;
            ey2 = y + halfH;
  
            x1 = ex1 < x1 ? ex1 : x1;
            x2 = ex2 > x2 ? ex2 : x2;
            y1 = ey1 < y1 ? ey1 : y1;
            y2 = ey2 > y2 ? ey2 : y2;
  
          } else if( ele.isEdge() && options.includeEdges ){ 
            includedEle = true;
  
            var n1pos = ele.source()[0]._private.position;
            var n2pos = ele.target()[0]._private.position;
  
            // handle edge dimensions (rough box estimate)
            //////////////////////////////////////////////
  
            var rstyle = ele._private.rstyle || {};
  
            ex1 = n1pos.x;
            ex2 = n2pos.x;
            ey1 = n1pos.y;
            ey2 = n2pos.y;
  
            if( ex1 > ex2 ){
              var temp = ex1;
              ex1 = ex2;
              ex2 = temp;
            }
  
            if( ey1 > ey2 ){
              var temp = ey1;
              ey1 = ey2;
              ey2 = temp;
            }
  
            x1 = ex1 < x1 ? ex1 : x1;
            x2 = ex2 > x2 ? ex2 : x2;
            y1 = ey1 < y1 ? ey1 : y1;
            y2 = ey2 > y2 ? ey2 : y2;
  
            // handle points along edge (sanity check)
            //////////////////////////////////////////
  
            var bpts = rstyle.bezierPts || [];
            var w = ele._private.style['width'].pxValue;
            for( var j = 0; j < bpts.length; j++ ){
              var bpt = bpts[j];
  
              x1 = bpt.x - w < x1 ? bpt.x - w : x1;
              x2 = bpt.x + w > x2 ? bpt.x + w : x2;
              y1 = bpt.y - w < y1 ? bpt.y - w : y1;
              y2 = bpt.y + w > y2 ? bpt.y + w : y2;
            }
  
          }
  
          // handle label dimensions
          //////////////////////////
  
          var style = ele._private.style;
          var rstyle = ele._private.rstyle;
          var label = style['content'].strValue;
          var fontSize = style['font-size'];
          var halign = style['text-halign'];
          var valign = style['text-valign'];
          var labelWidth = rstyle.labelWidth;
          var labelHeight = rstyle.labelHeight;
          var labelX = rstyle.labelX;
          var labelY = rstyle.labelY;
  
          if( includedEle && options.includeLabels && label && fontSize && labelHeight != undefined && labelWidth != undefined && labelX != undefined && labelY != undefined && halign && valign ){
            var lh = labelHeight;
            var lw = labelWidth;
            var lx1, lx2, ly1, ly2;
  
            if( ele.isEdge() ){
              lx1 = labelX - lw/2;
              lx2 = labelX + lw/2;
              ly1 = labelY - lh/2;
              ly2 = labelY + lh/2;
            } else {
              switch( halign.value ){
                case 'left':
                  lx1 = labelX - lw;
                  lx2 = labelX;
                  break;
  
                case 'center':
                  lx1 = labelX - lw/2;
                  lx2 = labelX + lw/2;
                  break;
  
                case 'right':
                  lx1 = labelX;
                  lx2 = labelX + lw;
                  break;
              }
  
              switch( valign.value ){
                case 'top':
                  ly1 = labelY - lh;
                  ly2 = labelY;
                  break;
  
                case 'center':
                  ly1 = labelY - lh/2;
                  ly2 = labelY + lh/2;
                  break;
  
                case 'bottom':
                  ly1 = labelY;
                  ly2 = labelY + lh;
                  break;
              }
            }
  
            x1 = lx1 < x1 ? lx1 : x1;
            x2 = lx2 > x2 ? lx2 : x2;
            y1 = ly1 < y1 ? ly1 : y1;
            y2 = ly2 > y2 ? ly2 : y2;
          }
        } // for
  
        return {
          x1: x1,
          x2: x2,
          y1: y1,
          y2: y2,
          w: x2 - x1,
          h: y2 - y1
        };
      }