Question

I'm trying to update the information of a series or circles that get created through a click event using Raphael.js along with some HTML tags. When they get created, the html generated keeps the information of the circle with the position of its X, Y and its radius, which can be dynamically changed when I move the circle around or change its size, this JSFiddle shows it more clearly:

http://jsfiddle.net/mauricioSanchez/L4mAL/

I have my event listeners

    canvasHandler.mouseup(function (e) {

    var mouseX = e.offsetX;
    var mouseY = e.offsetY;
    if (circlePickerSelector) {
        makeCircle(mouseX, mouseY);
        circlePickerSelector = false;
    }       
});

circlePicker.click(function () {
    circlePickerSelector = !circlePickerSelector;

});

This is the main function that gets called in the first eventListener. Which creates the circle and the HTML elements for that

function makeCircle(mouseX, mouseY) {
    //We call it before our circles are dragged so that their array is waiting to store the information
    // addingArrays(circleCounter);
    var radius;
    var fill;
    var circle = canvas.circle(mouseX, mouseY, 50).attr({
        fill: "hsb(.8, 1, 1)",
        stroke: "none",
        opacity: .5,
    });
    // console.log(circles);
    // We add an ID and a class to the circle
    var ourCircle = $("circle").last();
    ourCircle.attr("class", circleCounter);
    // And then finally push it to our array of circles
    circles.push(circle);
    var handlerPos = [mouseX + 35, mouseY + 35];
    var s = canvas.circle(handlerPos[0], handlerPos[1], 10).attr({
        fill: "hsb(.8, .5, .5)",
        stroke: "none",
        opacity: .5
    });
    //We add an id and a class to our little circle.
    s.node.id = sizerCounter;
    var sizerClass = $('circle').last();
    sizerClass.attr("class", "main-circle sizer");
    var newSizerClass = $(".sizer");
    // console.log(s);
    s.hide();
    //We now assign a handler for each little circle added and a main circle in order to hide them
    var circleClass = $("." + String(circleCounter));
    var sizerID = $("#" + String(sizerCounter));
    circleClass.mouseenter(function () {
        sizerID.toggle();
    });
    circleClass.mouseleave(function () {
        sizerID.hide();
    });
    sizerID.mouseenter(function () {
        $(this).toggle();
    });
    sizerID.mouseleave(function () {
        $(this).hide();
    });
    // console.log(circleClass);
    //We add some resizing and dragging properties
    var start = function () {
        //storing original coordinates
        this.ox = this.attr("cx");
        this.oy = this.attr("cy");
        this.sizer.ox = this.sizer.attr("cx");
        this.sizer.oy = this.sizer.attr("cy")
        this.attr({
            opacity: 1
        });
        this.sizer.attr({
            opacity: 1
        });
    }, move = function (dx, dy) {
            // move will be called with dx and dy
            this.attr({
                cx: this.ox + dx,
                cy: this.oy + dy
            });
            this.sizer.attr({
                cx: this.sizer.ox + dx,
                cy: this.sizer.oy + dy
            });
            //This is the key function to change 
            updateModel(this.attrs.cx, this.attrs.cy, this.node.className.baseVal, this.attrs.r);
        }, up = function () {
            // restoring state
            this.attr({
                opacity: .5
            });
            this.sizer.attr({
                opacity: .5
            });
        }, rstart = function () {
            // storing original coordinates
            this.ox = this.attr("cx");
            this.oy = this.attr("cy");
            this.big.or = this.big.attr("r");
        }, rmove = function (dx, dy) {
            // move will be called with dx and dy
            this.attr({
                cx: this.ox + dy,
                cy: this.oy + dy
            });
            this.big.attr({
                r: this.big.or + (dy < 0 ? -1 : 1) * Math.sqrt(2 * dy * dy)
            });
            updateModel(this.attrs.cx, this.attrs.cy, this.node.className.baseVal, this.attrs.r);
        };
    circle.drag(move, start, up);
    circle.sizer = s;
    s.drag(rmove, rstart);
    s.big = circle;
    //Here we create
    var myCodeList = $(".code-list");
    var htmlString = "<li class='" + circleCounter + "'> <span class='circle-color'> var color = <div class='circle-color-input' contentEditable autocorrect='off'> type a color</div> ; </span> <br> <span class='circle-radius'> This is a test </span> <br> <span class='circle'> This is a test </span> </li>";
    myCodeList.append(htmlString);
    updateList();
    circleCounter++;
    sizerCounter++;     
}

Finally this two functions allow the html and the position of the circle to be updated:

function updateModel(x, y, _class, r) {
    var len = circles.length;
    for (var i = 0; i < len; i++) {
        if (circles[i].node.className.baseVal == _class) {
            circles[i].attrs.cx = x;
            circles[i].attrs.cy = y;
            circles[i].attrs.r = r;
        }
    }
    updateList();

}

function updateList() {
    //To change that one I have put a class or an id
    var listItems = $('.code-list').find('li.' + circleCounter);
    // console.log(listItems);
    var len = circles.length;
    for (var i = 0; i < circles.length; i++) {
        //We create one reference. This makes looking for one element more effective. Unless we need to search for a particular element
        var currentItem = circles[i];
        var updateStringRadius = "var radius = " + parseInt(currentItem.attrs.r) + ";";
        var updateStringCircle = "circle (" + currentItem.attrs.cx + " ," + currentItem.attrs.cy + ", radius)";
        //This is the div Item for the particular div of each element
        var divItem = $(listItems[i]);
        var radiusItem = divItem.find("span.circle-radius");
        var circleItem = divItem.find("span.circle");
        // console.log(currentItem.attrs.cx);
        radiusItem.text(updateStringRadius);
        console.log($('.circle-radius').html());
        circleItem.text(updateStringCircle);
        // divItem.text(updateString);
        // console.log(divItem);
    }
}

If you take a look at the JSfiddle and create three circles for example. it will only update the information of the first one after a circle is created, but now when moved or when resized doesn't change.

Was it helpful?

Solution

I figured it out. So the problem was in this function:

function updateList() {
//To change that one I have put a class or an id
var listItems = $('.code-list').find('li.' + circleCounter);
// console.log(listItems);
var len = circles.length;
for (var i = 0; i < circles.length; i++) {
    //We create one reference. This makes looking for one element more effective. Unless we need to search for a particular element
    var currentItem = circles[i];
    var updateStringRadius = "var radius = " + parseInt(currentItem.attrs.r) + ";";
    var updateStringCircle = "circle (" + currentItem.attrs.cx + " ," + currentItem.attrs.cy + ", radius)";
    //This is the div Item for the particular div of each element
    var divItem = $(listItems[i]);
    var radiusItem = divItem.find("span.circle-radius");
    var circleItem = divItem.find("span.circle");
    // console.log(currentItem.attrs.cx);
    radiusItem.text(updateStringRadius);
    console.log($('.circle-radius').html());
    circleItem.text(updateStringCircle);
    // divItem.text(updateString);
    // console.log(divItem);
}

}

I changed the way I was initiating the handler and finding its children for this:

function updateList(){     
 var len = circles.length;
 for (var i = 0; i < circles.length; i++) {
  var currentItem = circles[i];
  var updateStringRadius = "var radius = " + parseInt(currentItem.attrs.r) + ";";
  var updateStringCircle = "circle (" + currentItem.attrs.cx + " ," + currentItem.attrs.cy + ", radius)";
  var divItem = $('.code-list').find('li.circle-' + (i+1))
  var radiusItem = divItem.find("span.circle-radius");
  var circleItem = divItem.find("span.circle");
  radiusItem.text(updateStringRadius);
  circleItem.text(updateStringCircle);
}

I wasn't iterating through the elements properly. I was also recommended that for best practices to change my class from class="1" to class="circle-1".

Here is the JSfiddle

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top