d3.demo.handle = function() { "use strict"; var width = 8, height = 20, x = 0, y = 0, type = null, base = null; var dispatch = d3.dispatch( "handleMouseover", "handleMouseout", "handleDragStart", "handleDrag", "handleDragEnd"); function handle(selection, evented) { base = selection; evented.on("shapeResize", function() { //log("handle: shapeResize()"); }); selection.each(function(d, i) { var parent = d3.select(this); var container = parent.append("g") .attr("class", "handle") .attr("transform", "translate(" + x + "," + y + ")"); handle.node = container.node(); var background = container.append("rect") .attr("class", "background") .attr("width", width) .attr("height", height) .on("mouseover", function(event) { d3.select(this).classed("hover", true); dispatch.handleMouseover({ handle: this, pos: [d3.event.x, d3.event.y] }); }) .on("mouseout", function(event) { d3.select(this).classed("hover", false); dispatch.handleMouseout({ handle: this, pos: [d3.event.x, d3.event.y] }); }); switch(type) { case handle.TYPE_TOP: case handle.TYPE_BOTTOM: background.classed("vertical", true); break; case handle.TYPE_LEFT: case handle.TYPE_RIGHT: background.classed("horizontal", true); break; default: break; } var drag = d3.behavior.drag() .origin(Object) .on("dragstart", function(d) { d3.event.sourceEvent.stopImmediatePropagation(); container.classed("dragging", true); dispatch.handleDragStart({ handle: this, pos: [d3.event.x, d3.event.y] }); }) .on("drag", function(d) { d3.event.sourceEvent.stopImmediatePropagation(); var selection = d3.select(this); switch(type) { case handle.TYPE_TOP: y += d3.event.dy; break; case handle.TYPE_BOTTOM: y += d3.event.dy; break; case handle.TYPE_LEFT: x += d3.event.dx; break; case handle.TYPE_RIGHT: x += d3.event.dx; break; default: break; } container.attr("transform", "translate(" + x + "," + y + ")"); dispatch.handleDrag({ handle: this, pos: [d3.event.x, d3.event.y] }); }) .on("dragend", function(d) { d3.event.sourceEvent.stopImmediatePropagation(); dispatch.handleDragEnd({ handle: this, pos: [d3.event.x, d3.event.y] }); container.classed("dragging", false); }); container.call(drag); handle.render = function() { container.attr("transform", "translate(" + x + "," + y + ")"); }; container.call(drag); }); } handle.x = function(value) { if (!arguments.length) return x; x = parseInt(value, 10); return this; }; handle.y = function(value) { if (!arguments.length) return y; y = parseInt(value, 10); return this; }; handle.width = function(value) { if (!arguments.length) return width; width = parseInt(value, 10); return this; }; handle.height = function(value) { if (!arguments.length) return height; height = parseInt(value, 10); return this; }; handle.type = function(value) { if (!arguments.length) return type; type = value; return this; }; handle.TYPE_RIGHT = "right"; handle.TYPE_LEFT = "left"; handle.TYPE_TOP = "top"; handle.TYPE_BOTTOM = "bottom"; d3.rebind(handle, dispatch, "on"); return handle; };