Rubberband

This tutorial will show you, how to create a simple rubberband, to select one or more of your diagram-items. The code we create here is not directly related with jsplumb. It would work with any html-items.

Ok, lets get started. What do we need for it?

  • A Rubberband itself
  • Selection-Algorithm for diagram items

The rubberband

In this first part, we’ll cover only the code for the rubberband. As it contains quite a bit of code, I recommend you to open the example in parallel!

We will create a simple-div with the id rubberband inside the diagramContainer, which we can style later in any way we like. The html for it looks as simple as this:

<div id="diagramContainer">
	<div id="rubberband" style="border:1px solid green;display:none;"></div>
</div>

We will control the rubberband with the help of javascript and css. To do so, we need to register the following events on the diagramContainer:

  • mousedown
  • mousemove
  • mouseup

We do this within the jsPlumb.ready-function to be sure, jsPlumb is ready as well. After this codeblock, we’ll cover each of these methods in detail!

jsPlumb.ready(function() {
	$("#diagramContainer").mousedown(diagramContainer_MouseDown);
	$("#diagramContainer").mousemove(diagramContainer_MouseMove);
	$("#diagramContainer").mouseup(diagramContainer_MouseUp);
});

mousedown

In the diagramContainer_MouseDown-method we

  • store the startPoint
  • initialize the rubberband
  • and show it!
function diagramContainer_MouseDown(event) {
	startPoint.x = event.pageX;         
	startPoint.y = event.pageY;
            
	$("#rubberband").css({top:startPoint.y, left:startPoint.x, height:1, width:1, position:'absolute'});
	$("#rubberband").show();
}

mousemove

In the method diagramContainer_MouseMove is the place, where the magic happens! Each time the mouse is moved, the rubberband is recalculated. The values we need to set on our rubberband (a div) are the top, left, width and height. We do this by simply updating the div‘s css values.

function diagramContainer_MouseMove(event) {
	if($("#rubberband").is(":visible") !== true) { return; }
        
	// Get the top- and left values
	var t = (event.pageY > startPoint.y) ? startPoint.y : event.pageY;
	var l = (event.pageX >= startPoint.x) ? startPoint.x : event.pageX;
            
 	// Get the width of the rubberband
	wcalc = event.pageX - startPoint.x;
	var w = (event.pageX > startPoint.x) ? wcalc : (wcalc * -1); 
       
	// Get the height of the rubberband     
	hcalc = event.pageY - startPoint.y;
	var h = (event.pageY > startPoint.y) ? hcalc : (hcalc * -1); 

	// Update the rubberband with the new values
	$("#rubberband").css({top:t, left:l, height:h, width:w, position:'absolute'});
}

mouseup

When the user finished dragging the rubberband, it must disappear. Thats what the method diagramContainer_MouseUp will do for us:

function diagramContainer_MouseUp(event) {
	$("#rubberband").hide();
}

The selection algorithm

Typically, there are two kinds of algorithms possible. In the first of them, a selection happens, when the item is partially within the rubberband. The second type selects items only if they are completly within the borders of the rubberband. In this tutorial we’ll implement the later of them!

Important: Please note, that this example will only work with the vanilla-jsplumb, as it is the only version, which supports dragging of multiple items!

As with the first part, I recommend you to open the example in parallel to make it easyer for you to understand everything! As you’ll see, I already added two items in the same manner, as we did in the drag- and resize tutorial.

Finding items within the rubberband

To be able to check, if an item is within the rubberband, we need to know the positions of the items and of the rubberband as well. Therefore, we create a little helper-functions, which returns us the distances to the left and to the top.

function getTopLeftOffset(element) {
	var elementDimension = {};
	elementDimension.left = element.offset().left;
	elementDimension.top =  element.offset().top;

	// Distance to the left is: left + width
	elementDimension.right = elementDimension.left + element.outerWidth();

	// Distance to the top is: top + height
	elementDimension.bottom = elementDimension.top + element.outerHeight();
    
	return elementDimension;
}

The following method uses the above method getTopLeftOffset and checks, if an item is completly within the rubberband, by comparing the elementDimensions of the rubberband and item. If so, it ads the css-class selected and adds the item to the dragSelection of jsPlumb by calling the method jsPlumb.addToDragSelection.

function diagramContainer_FindSelectedItem() {
	if($("#rubberband").is(":visible") !== true) { return; }
            
	var rubberbandOffset = getTopLeftOffset($("#rubberband"));

	$(".item").each(function() {
		var itemOffset = getTopLeftOffset($(this));
		if( itemOffset.top > rubberbandOffset.top &&
			itemOffset.left > rubberbandOffset.left &&
			itemOffset.right < rubberbandOffset.right &&
			itemOffset.bottom < rubberbandOffset.bottom) {
			$(this).addClass("selected");

			var elementid = $(this).attr('id');
			jsPlumb.addToDragSelection(elementid);
		}
	});
}

Finally we call the diagramContainer_FindSelectedItem-method within the mouseup-event.

function diagramContainer_MouseUp(event) {
	diagramContainer_FindSelectedItem();
	$("#rubberband").hide();
}

Reseting the selection

Reseting the selection is the final part of this tutorial. We do this by registering and implementing a click-method. The registration is as simple as follows:

jsPlumb.ready(function() {
	// ...
	$("#diagramContainer").click(diagramContainer_Click);
	// ...
}

The implementation needs a little trick. As dragging is a click as well, we need to check, if the user is dragging or only clicking. We do this, by checking the mouseposition first.

function diagramContainer_Click(event) {
	if(startPoint.x === event.pageX && startPoint.y === event.pageY)
	{
		jsPlumb.clearDragSelection();
		$(".item").each(function() {
			$(this).removeClass("selected");
		});
	}
}

If you have any questions, suggestions or have done something cool with jsPlumb, feel free to contact me!