0

I am developing a view for some items in my web site. Currently I have the items displayed in the HTML but now I need to draw some lines between the elements that will represent a connection between them, it's like a Gantt Chart but it doesn't include any time functionality, I only need to connect the items with the ones associated to them. I'm using JSTL to bring some data from a controller and I managed to draw the elements like the following image: http://i271.photobucket.com/albums/jj131/djrickel/before.png

And the way I need to display is in the following image: http://i271.photobucket.com/albums/jj131/djrickel/after.png

This is how I'm creating my table containing the elements that I want to display:

    <div class="container">
        <table>
            <tbody>
                <c:forEach items="${nodeGraphs}" var="nodeGraph">
                    <tr>
                        <c:forEach var="i" begin="0" end="5">
                            <td>
                                <c:if test="${nodeGraph.columnID == i}">
                                    <label class="label label-default">${nodeGraph.nodeObject.item.type}${nodeGraph.nodeObject.item.contextId}</label>
                                </c:if>
                            </td>
                        </c:forEach>
                    </tr>
                </c:forEach>
            </tbody>
        </table>
    </div>  

Does anyone know a way to create connecting lines between the elements using JQuery, JSon, Javascript or any HTML process? I can change from the table I'm using to div or span without any issue. I'm just looking the best way to display the information. Thanks in advance.

rickel
  • 1
  • 1

1 Answers1

-1

Probably the best way to do that is use HTML5 canvas, but if You want use div's try use this code:

(On JSFiddle: http://fiddle.jshell.net/22rar61n/9/)

var Line = (function() {

  var diff = function(a, b) {
    var d = Math.abs(a - b);
    if (d === 0) {
      d = 1;
    }
    return d;
  }

  var countWidth = function(line) {
    return diff(line.endX, line.startX);
  };

  var countHeight = function(line) {
    return diff(line.endY, line.startY);
  };

  var Line = function(options) {
    this.startX = options.startX;
    this.startY = options.startY;
    this.endX = options.endX;
    this.endY = options.endY;
  }

  Line.prototype.drowIn = function($container) {
    var self = this;
    var line = jQuery("<div></div>", {
      class: "line " + self.LineType(),
      css: {
        "color": "red",
        "top": self.startY,
        "left": self.startX,
        "width": countWidth(self),
        "height": countHeight(self),
        "background-color": "#000"
      }
    });

    $container.append(line);
  };

  Line.prototype.LineType = function() {
    if (this.startX != this.endX) {
      return "horizontal";
    }
    return "vertical";
  }

  return Line;
})();

var Arrow = (function() {
  var Arrow = function(start, end) {
    this.start = start;
    this.end = end;
  }

  Arrow.prototype.drowIn = function($container) {
    var ArrowContainer = jQuery("<div></div>", {
      class: "arrowContainer"
    });

    var line1 = new Line({
      startX: this.start.x,
      startY: this.start.y,
      endX: this.start.x,
      endY: this.end.y
    });
    line1.drowIn(ArrowContainer);

    var line2 = new Line({
      startX: this.start.x,
      startY: this.end.y,
      endX: this.end.x,
      endY: this.end.y
    });
    line2.drowIn(ArrowContainer);

    $container.append(ArrowContainer);
  }

  return Arrow;
})();

var Element = (function() {
  var Element = function(options) {
    var op = jQuery.extend({}, options);

    this.x = op.x || -1;
    this.y = op.y || -1;
    this.content = op.content || "";
    this.container = op.$container || "";
    this.node = null;
    this.subElements = [];
  };

  Element.prototype.addSubElement = function(element) {
    element.container = this.container;

    element.content = this.content + "." + (this.subElements.length + 1);
    this.subElements.push(element);
  };

  Element.prototype.drow = function() {
    var self = this;
    this.node = jQuery("<div></div>", {
      class: "element",
      text: this.content,
      css: {
        top: self.y,
        left: self.x
      }
    });

    this.container.append(this.node);
    var nexLvl = 0;
    var lastHeight = nexLvl;
    var lastLvl = 0;
    var oldIndex = -1;
    var outerHeightAndTop = jQuery(self.node).outerHeight() + jQuery(self.node).offset().top;

    jQuery.each(this.subElements, function(index, element) {
      var height = outerHeightAndTop * (index + 1 + lastLvl);
      if (lastHeight != 0) {
        height = lastHeight + outerHeightAndTop;
      }
      if (nexLvl != 0) {
        oldIndex = index;
        height = height + ((jQuery(self.node).outerHeight()) * nexLvl);
        lastLvl = nexLvl;
      }

      lastHeight = height;
      nexLvl = element.getMaxLevel();
      element.x = jQuery(self.node).outerWidth() + jQuery(self.node).offset().left;
      element.y = height;
      element.drow();
      self.connectWith(element);
    });
  };

  Element.prototype.connectWith = function(element) {
    var startY = jQuery(this.node).outerHeight() + this.y;
    var startX = (jQuery(this.node).outerWidth() / 2) + this.x;

    var endY = (jQuery(element.node).outerHeight() / 2) + element.y;
    var arrow = new Arrow({
      x: startX,
      y: startY
    }, {
      x: element.x,
      y: endY
    });
    arrow.drowIn(this.container);
  };

  function getLevelOnPosition(index) {
    return this.subElements[index].getMaxLevel();
  }

  Element.prototype.getMaxLevel = function(initLvl) {
    var lvl = initLvl || 0;
    var maxLvl = lvl;
    if (this.subElements.length > 0) {
      maxLvl = lvl++;
    }
    jQuery.each(this.subElements, function(index, element) {
      lvl = element.getMaxLevel(lvl);
      if (lvl > maxLvl) {
        maxLvl = lvl;
      }
    });
    return maxLvl;
  }

  return Element;
})();

jQuery(document).ready(function() {
  var container = jQuery("#container");


  var e = new Element({
    x: 10,
    y: 10,
    content: "a1",
    $container: container
  });

  var sube = new Element();
  e.addSubElement(sube);
  var sube2 = new Element();
  sube.addSubElement(sube2);
  sube2.addSubElement(new Element());
  var e2 = new Element();
  e.addSubElement(e2);
  e2.addSubElement(new Element());
  e.addSubElement(new Element());
  e.drow();
});
#container {
  position: relative;
}
#container > .element {
  position: absolute;
  border: 1px solid black;
  background-color: gray;
  color: white;
  padding: 2px;
  z-index: 10;
}
#container > .arrowContainer {
  position: absolute;
}
#container > .arrowContainer > .line {
  position: absolute;
  z-index: 50;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container"></div>
Alcadur
  • 681
  • 1
  • 8
  • 22