neyric/wireit

View on GitHub
sandbox/grouping/js/RubberBand.js

Summary

Maintainability
D
1 day
Test Coverage
(function() {

/**
 * A CanvasElement widget to hand-draw a selection
 * @class RubberBand
 * @extends CanvasElement
 */
Y.RubberBand = function(grouper) {
    
    Y.RubberBand.superclass.constructor.call(this, grouper.layer.el);
    
    this.grouper = grouper;
    var self = this;
    this.scrollThreshold = 150;
    this.scrollAmount = 20;
    this.directions = {};
    
    grouper.layer.el.addEventListener("mousemove",  function(event)  { 
        var elem = self.grouper.layer.el;
        var rect = elem.getBoundingClientRect();
        
        var xNoScroll = event.clientX-rect.left;
        var yNoScroll = event.clientY-rect.top;
        
        self.lastX = xNoScroll + elem.scrollLeft;
        self.lastY = yNoScroll + elem.scrollTop;
        
        self.directions = {};
        if (xNoScroll < self.scrollThreshold) {
            // Near the left edge so scroll left
            self.directions.left = true;
        }
        else if ((rect.right - event.clientX) < self.scrollThreshold) {
            // Near the right edge
            self.directions.right = true;
        }
        
        if (yNoScroll < self.scrollThreshold) {
            // Near top
            self.directions.up = true;
        }
        else if ((rect.bottom - event.clientY) < self.scrollThreshold) {
            // Near bottom
            self.directions.down = true;
        }
        
   }, false);

};


/**
 * Delay in ms between two points of the RubberBand when drawing
 * @static
 */
Y.RubberBand.defaultDelay = 50;


Y.extend(Y.RubberBand, Y.CanvasElement, {
    
    /**
     * Check if clicked in the layer and start the drawing mode
     */
    layerMouseDown: function(event) {
       var elem = this.grouper.layer.el;
       var rect = elem.getBoundingClientRect();
        
       var xNoScroll = event.clientX-rect.left;
       var yNoScroll = event.clientY-rect.top;
        
       if (xNoScroll < elem.clientWidth && yNoScroll < elem.clientHeight) {
            this.start();
        }
    },
    
    /**
     * Start the drawing mode
     */
    start: function() {
        this.show();
        
        this.SetCanvasRegion(0, 0, this.grouper.layer.el.scrollWidth, this.grouper.layer.el.scrollHeight);
        var ctxt = this.getContext();
        ctxt.beginPath();
        ctxt.moveTo(this.lastX, this.lastY);
        this.startX = this.lastX;
        this.startY = this.lastY;
        this.timer = Y.later(Y.RubberBand.defaultDelay, this, function()  { 
            this.nextPoint(this.lastX, this.lastY);
            this.scroll(this.directions);
            }, 0, true);
    },

    /**
     * Scroll the associated Y.Layer
     */
    scroll: function(directions) {
        var elem = this.grouper.layer.el;
        
        if (directions.left)
        elem.scrollLeft = Math.max(0, elem.scrollLeft-this.scrollAmount);
        else if (directions.right)
        elem.scrollLeft = Math.min(elem.scrollWidth, elem.scrollLeft+this.scrollAmount);
        
        if (directions.up)
        elem.scrollTop = Math.max(0, elem.scrollTop-this.scrollAmount);
        else if (directions.down)
        elem.scrollTop = Math.min(elem.scrollHeight, elem.scrollTop+this.scrollAmount);
    },

    /**
     * End the drawing mode
     */
    finish: function() {
        if (Y.Lang.isObject(this.timer)) {
            this.timer.cancel();
            this.timer = null;
        
            var ctxt = this.getContext();
            this.nextPoint(this.startX, this.startY);
    
            Y.later(1000, this, this.hide, 0, false);
        }
    },

    /**
     * Hide the RubberBand
     */
    hide: function() {
       if (!Y.Lang.isValue(this.element.style))
            this.element.style = {};
            
       this.element.style.display = "none";        
    },
    
    /**
     * Show the RubberBand
     */
    show: function() {
        if (!Y.Lang.isValue(this.element.style))
            this.element.style = {};
            
        this.element.style.display = "";        
    },
    
    /**
     * Add a point to the RubberBand
     */
    nextPoint: function(x, y) {
        if (Y.Lang.isValue(x) && Y.Lang.isValue(y)) {
            var ctxt = this.getContext();
        
            // Draw the inner bezier curve
            ctxt.lineCap= "round";
            ctxt.strokeStyle="green";
            ctxt.lineWidth="3";

            ctxt.lineTo(x, y);
            ctxt.stroke();
       }
    },

    /**
     * Check if the given (x,y) is within the RubberBand path
     */
    pointIsInside: function(x, y) {
        return (this.getContext().isPointInPath(x, y));
    }

});



})();