septemberbrain
septemberbrain

Reputation: 1008

Setting event handler for each Raphael object

I have a simple script that is creating several Raphael objects from an array and then assigning event handlers to each. Problem is that only the last event handler is executing for all objects. What am I doing wrong here?

var blockDiagram = {
    "block" :[
     {
        "width": 100,
        "height": 100,
        "text" : "this is block 1",
        "cx": 10,
        "cy": 10,
        "fill" : "blue"
     },
     {
        "width": 100,
        "height": 100,
        "text" : "this is block 2",
        "cx": 120,
        "cy": 10,
        "fill" : "yellow" 
     },
     {
        "width": 100,
        "height": 100,
        "text" : "this is block 3",
        "cx": 230,
        "cy": 10,
        "fill" : "red" 
     }
    ]
 };

var paper = new Raphael("holder", 700, 700)

for ( i=0;  i< blockDiagram.block.length; i++)
{
     ms = 500;
    width = blockDiagram.block[i].width;
    height = blockDiagram.block[i].height;
    text = blockDiagram.block[i].text;
    cx = blockDiagram.block[i].cx;
    cy = blockDiagram.block[i].cy;
    fill = blockDiagram.block[i].fill;
    p = paper.rect(cx,cy, width, height).attr({"fill": fill});
    txt = paper.text(cx ,cy, text).attr({fill: 'black', stroke: "none", opacity: 0, "font-size": 15});
    p.mouseover(function () {               
            txt.stop().animate({opacity: 1}, ms);
        }).mouseout(function () {
            txt.stop().animate({opacity: 0}, ms);
        });

 }

Upvotes: 1

Views: 953

Answers (2)

septemberbrain
septemberbrain

Reputation: 1008

Found another solution based on this example. For anyone else who might be interested.

var blockDiagram = {
    "block" :[
     {
        "width": 100,
        "height": 200,
        "text" : "this is block 1",
        "cx": 10,
        "cy": 10,
        "fill" : "blue"
     },
     {
        "width": 100,
        "height": 100,
        "text" : "this is block 2",
        "cx": 120,
        "cy": 10,
        "fill" : "yellow" 
     },
     {
        "width": 100,
        "height": 100,
        "text" : "this is block 3",
        "cx": 230,
        "cy": 10,
        "fill" : "red" 
     }
    ]
 };


Raphael.fn.BlockDiagram = function (blockDiagram) {
var paper = this,      
    Blocks = this.set();

function square(cx, cy, width, height, params) {       
    return paper.rect(cx, cy, width,height).attr(params);
 }

var process = function (i) {
        var width = blockDiagram.block[i].width,
            height = blockDiagram.block[i].height,
            text = blockDiagram.block[i].text,
            cx = blockDiagram.block[i].cx,
            cy = blockDiagram.block[i].cy,
            fill = blockDiagram.block[i].fill,               
            ms = 500,                
            p = square(cx, cy, width, height,{fill: fill}),
            txt = paper.text(cx , cy, text).attr({fill: fill, stroke: "none", opacity: 0, "font-size": 20});
        p.mouseover(function () {
            p.stop().animate({transform: "s1.1 1.1 " + cx + " " + cy}, ms, "gradient");
            txt.stop().animate({opacity: 1}, ms, "gradient");
        }).mouseout(function () {
            p.stop().animate({transform: ""}, ms, "gradient");
            txt.stop().animate({opacity: 0}, ms);
        });
        Blocks.push(p);
        Blocks.push(txt);
    };

for (i = 0; i < blockDiagram.block.length; i++) {
    process(i);
}
return Blocks;
};

$(function () { 
Raphael("holder", 500, 500).BlockDiagram(blockDiagram);
});

Upvotes: 0

dan-lee
dan-lee

Reputation: 14492

You can make element lists with Paper.set()

var set = paper.set();

for(var i = 0; i< blockDiagram.block.length; i++) {
  var width = blockDiagram.block[i].width,
    height = blockDiagram.block[i].height,
    text = blockDiagram.block[i].text,
    cx = blockDiagram.block[i].cx,
    cy = blockDiagram.block[i].cy,
    fill = blockDiagram.block[i].fill;

  var p = paper.rect(cx,cy, width, height).attr({
    block: blockDiagram.block[i], // here the custom attribute gets set (block object)
    fill: fill
  });
  set.push(p);
}

What I added as attribute block is a custom attributes created withPaper.customAttributes. So you can attach information to any element.

That's how I created the block attribute:

paper.customAttributes.block = function(block) {
  return {
    block: block
  };
};

So when calling the attribute with parameter it will be set otherwise it returns the value set before

Now, the best part, we can attach handlers to an entire set and get the information set in the extra attribute!

var txt;
set.mouseover(function (e) {
  var block = this.attr('block'); // getting the attribute (the block object with the data)

  txt = paper.text(block.cx ,block.cy, block.text).attr({fill: "black", stroke: "none", opacity: 0, "font-size": 15});
  txt.stop().animate({opacity: 1}, ms);
}).mouseout(function (e) {
    txt.stop().animate({opacity: 0}, ms);
});

I made a fiddle for you to check it out. Of course it can be improved but I hope you get the idea.

Upvotes: 2

Related Questions