title: move multiple elements with raphael javascript
body: <p>I'm creating an image tagging ability for a CMS using Raphael javascript based on one of the examples given on the Raphael website (curver example). It works by letting the user add arrows (paths) and labels (text) to images and move them around to mark structures in the image ("points of interest"). I've got it working for one path pr. label (<a href="http://jsfiddle.net/nartex1234/9m5d7fqd/" rel="nofollow">jsfiddle.net/nartex1234/9m5d7fqd/</a>), but struggling to make it work for more than one path pr. label (<a href="http://jsfiddle.net/nartex1234/wm1odgtz/" rel="nofollow">jsfiddle.net/nartex1234/wm1odgtz/</a>).</p>
  
  <p>I feel it all comes down to the limit of my programming skills. I really donæt know how to grasp the solution. I've included the code for the working example below. Any suggestions or hints on how to get this working is most welcome.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="true">
  <div class="snippet-code snippet-currently-hidden">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>// Create canvas
  var R = Raphael(0, 0, "100%", "100%");
  
  // This is the style objects for the article labels
  var labelattr = {
    font: "30px Helvetica",
    "font-weight": "bold",
    opacity: 0.9,
    fill: "#fff",
    "stroke-width": 1,
    stroke: "#000"
  };
  
  var discattr = {
    fill: "#f0f",
    stroke: "none",
    opacity: 0.3 // normaly set to 0.01 so that it is not visible
  };
  
  var arrowattr = {
    "stroke-width": 3,
    "stroke-linecap": "round",
    "arrow-end": "classic -wide"
  };
  
  // The JSON data object (normally provided via AJAX from a database)
  var data = [{
    "label": "Red",
    "articlelabelid": "12",
    "labelid": "28",
    "x1": "400",
    "y1": "150",
    "pois": [{
      "articlelabelid": "12",
      "poid": "3",
      "x2": "300",
      "y2": "400"
    }]
  }, {
    "label": "Yellow",
    "articlelabelid": "13",
    "labelid": "30",
    "x1": "300",
    "y1": "500",
    "pois": [{
      "articlelabelid": "13",
      "poid": "4",
      "x2": "400",
      "y2": "600"
    }, {
      "articlelabelid": "13",
      "poid": "5",
      "x2": "450",
      "y2": "600"
    }, {
      "articlelabelid": "13",
      "poid": "6",
      "x2": "200",
      "y2": "500"
    }]
  }, {
    "label": "Blue",
    "articlelabelid": "14",
    "labelid": "29",
    "x1": "700",
    "y1": "450",
    "pois": [{
      "articlelabelid": "14",
      "poid": "13",
      "x2": "900",
      "y2": "800"
    }, {
      "articlelabelid": "14",
      "poid": "14",
      "x2": "800",
      "y2": "700"
    }]
  }, {
    "label": "Black",
    "articlelabelid": "15",
    "labelid": "31",
    "x1": "100",
    "y1": "100",
    "pois": [{
      "articlelabelid": "15",
      "poid": "15",
      "x2": "200",
      "y2": "200"
    }]
  }];
  
  
  // The start, move and up functions
  function start() {}
  
  function move(dx, dy) {
    this.update(dx - (this.dx || 0), dy - (this.dy || 0));
    this.dx = dx;
    this.dy = dy;
  }
  
  function up() {
    this.dx = this.dy = 0;
    switch (this.type) {
      case "text":
        x = this.attr("x"), y = this.attr("y"), objclass = 'articlelabel_' + this.node.id;
        break;
      case "circle":
        x = this.attr("cx"), y = this.attr("cy"), objclass = 'poi_' + this.node.id;
        break;
    }
  }
  
  
  
  // Function to draw the labels and lines, but only the first line/poi (point of interest) in the object
  function labeline(object) {
    // Find coordinates of label
    var x = parseInt(object.x1, 10);
    var y = parseInt(object.y1, 10);
    // Number of pois (points of interest) for this label
    var poi_count = Object.keys(object.pois).length;
  
    var ax = parseInt(object['pois'][0]['x2'], 10);
    var ay = parseInt(object['pois'][0]['y2'], 10);
    var label = object.label;
    var articlelabelid = object.articlelabelid;
    var poid = object['pois'][0]['poid'];
  
    // The path - creates an array with two arrays within it
    var path = [
        ["M", x, y],
        ["L", ax, ay]
      ],
  
  
      // The set
      controls = R.set(
        R.path(path).attr(arrowattr), // Controls [0]
        R.circle(ax, ay, 9).attr(discattr), // Controls [1]
        R.text(x, y, label).attr(labelattr) // Controls [2]
      );
  
    controls[2].update = function(x, y) {
      this.node.id = articlelabelid;
      var X = this.attr("x") + x,
        Y = this.attr("y") + y;
      this.attr({
        x: X,
        y: Y
      });
      path[0][1] = X;
      path[0][2] = Y;
      controls[0].attr({
        path: path
      });
    };
    controls[1].update = function(x, y) {
      this.node.id = poid;
      var X = this.attr("cx") + x,
        Y = this.attr("cy") + y;
      this.attr({
        cx: X,
        cy: Y
      });
      path[1][1] = X;
      path[1][2] = Y;
      controls[0].attr({
        path: path
      });
    };
    controls.drag(move, start, up);
  }
  
  // Run function for every label in the JSON data object
  for (var i = 0; i &lt; data.length; i++) {
    labeline(data[i]);
  }</code></pre>
  </div>
  </div>
  </p>