180 lines
5.9 KiB
JavaScript
180 lines
5.9 KiB
JavaScript
/*
|
|
* This file is part of Toolkit.
|
|
*
|
|
* Toolkit is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* Toolkit is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General
|
|
* Public License along with this program; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA
|
|
*/
|
|
"use strict";
|
|
(function(w, TK){
|
|
|
|
function extract_matrix (t) {
|
|
var a = t.indexOf("matrix(");
|
|
if (a < 0) return;
|
|
t = t.substr(a+7);
|
|
return (t.split(")"))[0].split(",").map(function(v){return parseInt(v.trim())});
|
|
}
|
|
|
|
function xy_from_transform (t) {
|
|
var mx = extract_matrix(t);
|
|
return (!mx || !mx.length) ? [0, 0] : [mx[4], mx[5]];
|
|
}
|
|
|
|
function startdrag(e, drag) {
|
|
this._dragged = 0;
|
|
var O = this.options;
|
|
if (!O.active) return;
|
|
if (e.button !== void(0) && e.button > 0) return;
|
|
this._xstart = this._xlast = e.pageX;
|
|
this._ystart = this._ylast = e.pageY;
|
|
if (O.transform) {
|
|
var xy = xy_from_transform(this._style.transform);
|
|
this._xpos = xy[0];
|
|
this._ypos = xy[1];
|
|
} else {
|
|
this._xpos = O.node.offsetLeft;
|
|
this._ypos = O.node.offsetTop;
|
|
}
|
|
TK.add_class(O.node, "toolkit-dragging");
|
|
}
|
|
function stopdrag(e, drag) {
|
|
if (!this.options.active) return;
|
|
if (e.button !== void(0) && e.button > 0) return;
|
|
TK.remove_class(this.options.node, "toolkit-dragging");
|
|
}
|
|
function dragging(e, drag) {
|
|
var O = this.options;
|
|
if (!O.active) return;
|
|
if (e.button !== void(0) && e.button > 0) return;
|
|
this._dragged += (Math.abs(e.pageX - this._xlast)
|
|
+ Math.abs(e.pageY - this._ylast)) / 2;
|
|
if (this._dragged < O.initial) return;
|
|
this._xlast = e.pageX;
|
|
this._ylast = e.pageY;
|
|
var x = this._xpos + e.pageX - this._xstart;
|
|
var y = this._ypos + e.pageY - this._ystart;
|
|
if (O.min.x !== false) x = Math.max(O.min.x, x);
|
|
if (O.max.x !== false) x = Math.min(O.max.x, x);
|
|
if (O.min.y !== false) y = Math.max(O.min.y, y);
|
|
if (O.max.y !== false) y = Math.min(O.max.y, y);
|
|
if (O.transform) {
|
|
var t = this._style.transform;
|
|
var mx = extract_matrix(t);
|
|
mx[4] = x;
|
|
mx[5] = y;
|
|
var nt = t.replace(/matrix\([0-9 \,]*\)/, "matrix(" + mx.join(",") + ")");
|
|
O.node.style.transform = nt;
|
|
} else {
|
|
O.node.style.top = y + "px";
|
|
O.node.style.left = x + "px";
|
|
}
|
|
}
|
|
function set_handle() {
|
|
var h = this.options.handle;
|
|
if (this.drag)
|
|
this.drag.destroy();
|
|
var range = new TK.Range({});
|
|
this.drag = new TK.DragValue(this, {
|
|
node: h,
|
|
range: function () { return range; },
|
|
get: function() { return 0; },
|
|
set: function(v) { return; },
|
|
});
|
|
}
|
|
/**
|
|
* TK.Drag enables dragging of elements on the screen positioned absolutely or by CSS transformation.
|
|
*
|
|
* @param {Object} [options={ }] - An object containing initial options.
|
|
*
|
|
* @property {HTMLElement|SVGElement} options.node - The element to drag.
|
|
* @property {HTMLElement|SVGElement} [options.handle] A DOM node to be used as a handle. If not set, <code>options.node</code> is used.
|
|
* @property {Boolean} [options.active=true] - Enable or disable dragging
|
|
* @property {Object|Boolean} [options.min={x: false, y: false}] - Object containing the minimum positions for x and y. A value of <code>false</code> is interpreted as no minimum.
|
|
* @property {Object|Boolean} [options.max={x: false, y: false}] - Object containing the maximum positions for x and y. A value of <code>false</code> is interpreted as no maximum.
|
|
* @property {Number} [options.initial=2] - Number of pixels the user has to move until dragging starts.
|
|
* @property {Boolean} [options.transform=false] - Use CSS transformations instead of absolute positioning.
|
|
*
|
|
* @extends TK.Base
|
|
*
|
|
* @class TK.Drag
|
|
*/
|
|
TK.Drag = TK.class({
|
|
_class: "Drag",
|
|
Extends: TK.Base,
|
|
_options: {
|
|
node : "object",
|
|
handle : "object",
|
|
active : "boolean",
|
|
min : "object",
|
|
max : "object",
|
|
initial : "number",
|
|
transform : "boolean",
|
|
},
|
|
options: {
|
|
node : null,
|
|
handle : null,
|
|
active : true,
|
|
min : {x: false, y: false},
|
|
max : {x: false, y: false},
|
|
initial : 2,
|
|
transform : false,
|
|
},
|
|
/**
|
|
* The user is dragging this item.
|
|
*
|
|
* @event TK.Drag#dragging
|
|
*
|
|
* @param {DOMEvent} event - The native DOM event.
|
|
*/
|
|
/**
|
|
* The user started dragging this item.
|
|
*
|
|
* @event TK.Drag#startdrag
|
|
*
|
|
* @param {DOMEvent} event - The native DOM event.
|
|
*/
|
|
/**
|
|
* The user stopped dragging this item.
|
|
*
|
|
* @event TK.Drag#stopdrag
|
|
*
|
|
* @param {DOMEvent} event - The native DOM event.
|
|
*/
|
|
static_events: {
|
|
startdrag: startdrag,
|
|
dragging: dragging,
|
|
stopdrag: stopdrag,
|
|
},
|
|
initialize: function (options) {
|
|
TK.Base.prototype.initialize.call(this, options);
|
|
this.set("handle", this.options.handle);
|
|
this.set("node", this.options.node);
|
|
},
|
|
// GETTERS & SETTERS
|
|
set: function (key, value) {
|
|
if (key === "node")
|
|
this._style = window.getComputedStyle(value);
|
|
if (key === "handle" && !value)
|
|
value = this.options.node;
|
|
|
|
TK.Base.prototype.set.call(this, key, value);
|
|
|
|
if (key === "handle")
|
|
set_handle.call(this);
|
|
if (key === "initial" && this.drag)
|
|
this.drag.set("initial", value);
|
|
}
|
|
});
|
|
})(this, this.TK);
|