/* Copyright (c) 2011, Geert Bergman (geert@scrivo.nl) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of "Scrivo" nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * $Id: Dragger.js 616 2013-04-22 23:48:38Z geert $ */ "use strict"; SUI.Dragger = SUI.defineClass( /** @lends SUI.Dragger.prototype */{ /** @ignore */ baseClass: SUI.Box, /** * @class * A dragger is a box that you can drag with the mouse between certain * restriction. It is a utility component that is used when certain parts * of a component need to make draggable. You can set the restrictions and * direction you want to drag and the dragger will follow the mouse within * the allowed region. * * @augments SUI.Box * * @description * Create a dragger component. * * @constructs * @param see base class */ initializer: function(arg) { SUI.Dragger.initializeBase(this, arg); // set initial values to window size this._xMin = 0; this._yMin = 0; this._xMax = SUI.browser.viewportWidth; this._yMax = SUI.browser.viewportHeight; }, /** * Constant to use when you want to drag into the east direction. */ EAST: "e", /** * Constant to use when you want to drag into the horizontal direction. */ HORIZONTAL: "h", /** * Constant to use when you want to drag into the north direction. */ NORTH: "n", /** * Constant to use when you want to drag into the south direction. */ SOUTH: "s", /** * Constant to use when you want to drag into the vertical direction. */ VERTICAL: "v", /** * Constant to use when you want to drag into the west direction. */ WEST: "w", /** * Set the drag direction. * @param {const} dir Direction into which to drag. */ direction: function(dir) { this._dir = dir; }, /** * The onEndDrag event handler: this method will be called when the user * stops dragging. */ onEndDrag: function() { }, /** * The onDrag event handler: this method will be called while the user * is dragging. */ onDrag: function() { }, /** * Start the dragging action. This will initialize the dragging action * and will typically be called in the onmousedown handler of the box * that must trigger the drag action. * @param {SUI.Event} e An onmousedown event. */ start: function(e) { // make sure the dragger is on top of everything this.el().style.zIndex = 1000; // get the current mouse position this._xPos = SUI.browser.getX(e.event); this._yPos = SUI.browser.getY(e.event); // and the start positions/dimension this._lStart = this.left(); this._hStart = this.height(); this._tStart = this.top(); this._wStart = this.width(); var that = this; // set the onmousemove event handler to _drag() SUI.browser.addEventListener( document, "mousemove", this._ehDrag = function(e) { if (!that._drag(new SUI.Event(this, e))) { SUI.browser.noPropagation(e); } } ); // set the onmouseup event handler to _endDrag() SUI.browser.addEventListener( document, "mouseup", this._ehEndDrag = function(e) { if (!that._endDrag()) { SUI.browser.noPropagation(e); } } ); }, /** * Set the maximum x position (at document level) for the dragging motion. * @param {int} xMax maximum x position (at document level) for the * dragging motion. */ xMax: function(xMax) { this._xMax = xMax; }, /** * Set the minimum x position (at document level) for the dragging motion. * @param {int} xMin minimum x position (at document level) for the * dragging motion. */ xMin: function(xMin) { this._xMin = xMin; }, /** * Set the maximum y position (at document level) for the dragging motion. * @param {int} yMax maximum y position (at document level) for the * dragging motion. */ yMax: function(yMax) { this._yMax = yMax; }, /** * Set the minimum y position (at document level) for the dragging motion. * @param {int} yMin minimum y position (at document level) for the * dragging motion. */ yMin: function(yMin) { this._yMin = yMin; }, // direction for dragging motion _dir: "", // reference to the drag function (for unregistering) _ehDrag: null, // reference to the endDrag function (for unregistering) _ehEndDrag: null, // dragger height at start dragging action _hStart: 0, // dragger left at start dragging action _lStart: 0, // dragger top at start dragging action _tStart: 0, // dragger width at start dragging action _wStart: 0, // maximum x position for the dragging action _xMax: 0, // minimum x position for the dragging action _xMin: 0, // current x position during the dragging action _xPos: 0, // maximum y position for the dragging action _yMax: 0, // minimum y position for the dragging action _yMin: 0, // current y position during the dragging action _yPos: 0, /* Function to keep variable value within boundaries. */ _bounds: function(v, min, max) { return v < min ? min : v > max ? max : v; }, /* Drag the component: set the new position and size based on the current * mouse position. */ _drag: function(e) { // get the current mouse position var x = SUI.browser.getX(e.event); var y = SUI.browser.getY(e.event); // if we're dragging in horizontal direction just set the left position // of the dragger if (this._dir.indexOf("h") != -1) { var t = this._lStart + x - this._xPos; t = this._bounds(t, this._xMin, this._xMax); this.left(t); } // if we're dragging in vertical direction just set the top position // of the dragger if (this._dir.indexOf("v") != -1) { var l = this._tStart + y - this._yPos; l = this._bounds(l, this._yMin, this._yMax); this.top(l); } // if we're dragging into the east direction just set the width // of the dragger if (this._dir.indexOf("e") != -1) { var w = this._wStart + x - this._xPos; w = this._bounds(w, this._xMin, this._xMax); this.width(w); } // if we're dragging into the west direction set the width and the // left position of the dragger if (this._dir.indexOf("w") != -1) { var w = this._wStart - x + this._xPos; w = this._bounds(w, this._xMin, this._xMax); var l = this._lStart - (w - this._wStart); this.width(w); this.left(l); } // if we're dragging into the north direction set the height and the // top position of the dragger if (this._dir.indexOf("n") != -1) { var h = this._hStart - y + this._yPos; h = this._bounds(h, this._yMin, this._yMax); var t = this._tStart - (h - this._hStart); this.height(h); this.top(t); } // if we're dragging into the south direction just set the height // of the dragger if (this._dir.indexOf("s") != -1) { var h = this._hStart + y - this._yPos; h = this._bounds(h, this._yMin, this._yMax); this.height(h); } // now set the CSS dimensions of the dragger this.setDim(); // ... and call the onDrag event handler this.callListener("onDrag"); }, /* End the dragging motion */ _endDrag: function() { // Unregister the event handlers ... SUI.browser.removeEventListener(document, "mousemove", this._ehDrag); SUI.browser.removeEventListener(document, "mouseup", this._ehEndDrag); // ... and call the onEndDrag event handler this.callListener("onEndDrag"); } });