Skip to content

Endpoint types should support Anchor parameter #77

Closed
damjanaleksiev opened this Issue Aug 13, 2013 · 16 comments

2 participants

@damjanaleksiev

I am building an UI were I have multiple boxes that can be connected together. Each box has 1 target and 3 sources, made with the makeTarget and makeSource methods called upon the same box DOM element. The code looks something like this:

jsPlumb.makeTarget($('#box_id'), targetData);
jsPlumb.makeSource($('#box_id'), sourceData1);
jsPlumb.makeSource($('#box_id'), sourceData2);
jsPlumb.makeSource($('#box_id'), sourceData3);

And each of the sources is distinguished by the filter property that connects it to a different part of the box:

sourceData1.filter = '.filter_1';
sourceData2.filter = '.filter_2';
sourceData3.filter = '.filter_3';

Connections are possible to be made only between the sources of one box and the target of another box. The target anchors are Continuous.

This arrangement works perfectly for what I need as far as working with the boxes and dragging and dropping connections.

The problem arises when I want to recreate a saved UI from a JSON object. I can recreate the position of the boxes without a problem, but I cannot find a way to recreate the connections to start from the correct source of the 3 available on the box.

I tried to re-connect using the saved uuids, but it turned out the endpoints don't exist yet before the connections are created.
The other method I tried is to connect just the source and target box ids:

jsPlumb.connect({ 
    source:"box_id1", 
    target:"box_id2",
});

But this never connects the correct source to the target and the connections are not exactly the same as the user made them. If a connection started from source 1, with this method it can start from source 3 for example.

Basically I am asking is it possible to programmatically connect sources and targets before the endpoints are created using the jsPlumb API?

So is it possible to recreate the connections in these circumstances or should I look for other solutions?

Thanks.

@sporritt
Owner

The filter is only used when dragging new connections, right? So wouldn't this UI just show all your connections as belonging to the box, not to some specific children of the box?

@damjanaleksiev

Yes, and that is exactly what the problem is. When you create a connection from a specific filter it has a unique starting point and a unique style associated with it. But when I recreate the connection using just the id of the box, all of this information is presented incorrectly. I am not able to replicate neither the style nor the connection starting point. That's why I am looking for a way to instruct the connection to start from an exact filter and inherit its style.

@sporritt
Owner

oh yes i see. well, have you considered using connection types?

http://jsplumbtoolkit.com/doc/types

@damjanaleksiev

That seems like it would take care of the style of the connections, but how can I position the connection properly (so that they start from the correct filters)?

@sporritt
Owner

this is the bit about your issue that i do not understand: the filter is the place from which the connection can be dragged. but once the connection has been established it switches to the main element. unless you are using a custom anchor to place connections on these filter elements.

@damjanaleksiev

Yes, i am using a custom anchor for each of the sources. Basically once the connection is dragged from the filter it gets positioned on the anchor (which is basically a thin line on the edge of the filter).

This is what the object for defining the sources looks like (the other two sources are defined similarly just with different anchor positions and connection styles):

var source1 = { 
        anchor: [0, 1, 0, 1, 35, -3],
        filter: '.source_1',
        endpoint: 'Rectangle',     
        maxConnections: -1,  
        isTarget: false,
        isSource: true,         
        paintStyle: {
            fillStyle: 'transparent',
            width: '68',
            height: '4'
        },
        hoverPaintStyle:  {
            fillStyle: 'transparent',
            width: '68',
            height: '4'
        },
        connector: ['Flowchart', { 
            stub: [40, 60], 
            cornerRadius: 5, 
            alwaysRespectStubs: true 
        }],  
        connectorStyle: {
            lineWidth: 3,
            strokeStyle: '#56b339'
        },
        connectorHoverStyle: {
            lineWidth: 3,
            strokeStyle: '#56b339'
        }
};

And the target is defined like this:

var target = {
        endpoint: 'Rectangle',
        maxConnections: -1,
        isTarget: true,
        isSource: false,
        paintStyle: { 
            fillStyle: 'transparent',
        },                                         
        hoverPaintStyle: {
            fillStyle: 'transparent'

        },
        anchor: [ 'Continuous', { faces: ['top'] } ], 
        dropOptions: { hoverClass: 'conn_drag_hover' }    
    };

I hope its clearer now what is going on.

@sporritt
Owner

so it's a bummer for you that endpoint types don't support anchors, then, I guess. if endpoint types supported anchors you'd be good to go.

@damjanaleksiev

So basically it is impossible to do this right now. Another option I can think of to create UI like this, would be to use ordinary endpoints instead of sources and than connect using their uuids.
The problem with this approach is that the endpoint params don't support the filter property and I need the connection to start not from the drag point (where the user clicked) but from the border of the element.
If its is somehow possible to set where the connection starts from after being dragged from the endpoint, that would be another solution.

@sporritt
Owner
sporritt commented Sep 3, 2013

it is impossible right now, but getting endpoint types to support anchors is probably not very much work. if you would like me to take a look i can do so.

@damjanaleksiev

If i understand correctly, done this way, I would recreate my connections using connections types, similar to this example:

jsPlumb.registerConnectionStyle("boz",{ 
  paintStyle: { 
    strokeStyle:"${color}", 
    lineWidth:"${width}" 
  } 
}
var c = jsPlumb.connect({ source:"s", target:"t" });
c.addType("boz",{ color:"green", width:23 });

I don't understand how will endpoint types work though, since I'm using sources and targets and not endpoints.
But if you think that its possible that way, than yes, by all means, it would be great if you could implement that feature :)

@sporritt
Owner
sporritt commented Sep 3, 2013

makeSource and makeTarget take an object that is identical to that which addEndpoint takes. so if you set a type parameter then the endpoint will have that type. i'll try to get to this in the next few days.

@sporritt
Owner
sporritt commented Sep 5, 2013

in 1.5.3 dev, endpoint types now support anchor:

jsPlumb.registerEndpointType("basic", {
    paintStyle:{fillStyle:"blue"},
    anchor:"Left"
});

i will be releasing 1.5.3 soon.

@damjanaleksiev

Thanks, I'll try it out as soon as possible.

@sporritt
Owner
sporritt commented Sep 5, 2013

ok. but note 1.5.3 is on a branch, right? dev/1.5.3. you'll have to build it yourself to get a concatenated version.

@damjanaleksiev

Unfortunately I have not found a way to implement the solution using endpoint types. The toggleType method returns an error when used on a source (probably because the endpoint does not exist before the connection is created from this source). But even if it worked I still don't think that this is the right answer for the problem.

To clarify things more, here are screenshots from the UI I am working on. I'm sorry I wasn't able to provide you with this sooner, but I had no access to this project for the last couple of weeks.

Step 1. Two boxes without any connections. Default state.
boxes_1

Step 2. A connection is being dragged from the source to the target. The source in this case is the true element on the bottom of the upper box. The other two possible sources are the next and false elements next to it. The target is the whole box number two.
boxes_2

Step 3. A connection is established. After dropping the connection on top of box two, the starting anchor is placed on the thin green line below the source. The end anchor is placed on the top side of the target box.
boxes_3

This whole thing works great with the settings for the sources and targets I posted in the above comment. The only problem I have is how to replicate this same UI from the saved JSON data. I can replicate the boxes and their positions but I have found no way to create the same connection from the above images on the fly, programmatically, using methods from the API.

I know how to establish connections once the endpoints are in place (the easiest way I found in this case is using their uuids). But the problem here is that this operation is supposed to happen before there any endpoints created, only sources and targets.

Thanks for the help so far, I hope it is clearer now what I am trying to accomplish.

@sporritt
Owner

hi...sorry for the delay on this. i looked at it this afternoon and put this together:

http://jsfiddle.net/nFyQJ/32/

the key point here is that if you make a connection from some element that has been configured as a source, jsPlumb realises that and uses the settings you provided. so to recreate your UI you can just configure the sources as you like and then connect using them as the source parameter.

@sporritt sporritt closed this Oct 13, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.