added scrollbar support for container DOM, structured the unittests a bit better, and did some minor refactoring

This commit is contained in:
Eric Rowell
2012-03-17 10:28:25 -07:00
parent 039c9059a0
commit ed35c6dbba
19 changed files with 2246 additions and 2168 deletions

View File

@@ -6,7 +6,7 @@ To build a development version of the library, run `thor build:dev VERSION`, whe
If you add a file in the src directory, be sure to add the filename to the filename array in the Thorfile. If you add a file in the src directory, be sure to add the filename to the filename array in the Thorfile.
#Tests #Tests
To run unit tests, open the `unitTests.html` file in the `tests` directory. To run functional tests, open the `functionalTests.html` file. The tests output the results to the console via `console.log()` so be sure to have it open. To run unit tests, open the `unitTests.html` file in the `tests/html` directory. To run functional tests, open the `functionalTests.html` file. The tests output the results to the console via `console.log()` so be sure to have it open.
#Pull Requests #Pull Requests
I'd be happy to review any pull requests that may better the KineticJS project, in particular if you have a bug fix or a new shape (see `src/shapes` for examples). Before doing so, please first make sure that all of the unit tests and functional tests pass. I'd be happy to review any pull requests that may better the KineticJS project, in particular if you have a bug fix or a new shape (see `src/shapes` for examples). Before doing so, please first make sure that all of the unit tests and functional tests pass.

206
dist/kinetic-core.js vendored
View File

@@ -3,7 +3,7 @@
* http://www.kineticjs.com/ * http://www.kineticjs.com/
* Copyright 2012, Eric Rowell * Copyright 2012, Eric Rowell
* Licensed under the MIT or GPL Version 2 licenses. * Licensed under the MIT or GPL Version 2 licenses.
* Date: Mar 13 2012 * Date: Mar 17 2012
* *
* Copyright (C) 2011 - 2012 by Eric Rowell * Copyright (C) 2011 - 2012 by Eric Rowell
* *
@@ -75,7 +75,7 @@ Kinetic.GlobalObject = {
for(var key in config) { for(var key in config) {
if(config.hasOwnProperty(key)) { if(config.hasOwnProperty(key)) {
if(config[key].x !== undefined || config[key].y !== undefined) { if(config[key].x !== undefined || config[key].y !== undefined) {
var propArray = ["x", "y"]; var propArray = ['x', 'y'];
for(var n = 0; n < propArray.length; n++) { for(var n = 0; n < propArray.length; n++) {
var prop = propArray[n]; var prop = propArray[n];
if(config[key][prop] !== undefined) { if(config[key][prop] !== undefined) {
@@ -94,7 +94,7 @@ Kinetic.GlobalObject = {
for(var key in config) { for(var key in config) {
if(config.hasOwnProperty(key)) { if(config.hasOwnProperty(key)) {
if(config[key].x !== undefined || config[key].y !== undefined) { if(config[key].x !== undefined || config[key].y !== undefined) {
var propArray = ["x", "y"]; var propArray = ['x', 'y'];
for(var n = 0; n < propArray.length; n++) { for(var n = 0; n < propArray.length; n++) {
var prop = propArray[n]; var prop = propArray[n];
if(config[key][prop] !== undefined) { if(config[key][prop] !== undefined) {
@@ -228,7 +228,7 @@ Kinetic.Node = function(config) {
y: 0 y: 0
}; };
this.eventListeners = {}; this.eventListeners = {};
this.dragConstraint = "none"; this.dragConstraint = 'none';
this.dragBounds = {}; this.dragBounds = {};
this._draggable = false; this._draggable = false;
@@ -237,13 +237,13 @@ Kinetic.Node = function(config) {
for(var key in config) { for(var key in config) {
// handle special keys // handle special keys
switch (key) { switch (key) {
case "draggable": case 'draggable':
this.draggable(config[key]); this.draggable(config[key]);
break; break;
case "listen": case 'listen':
this.listen(config[key]); this.listen(config[key]);
break; break;
case "rotationDeg": case 'rotationDeg':
this.rotation = config[key] * Math.PI / 180; this.rotation = config[key] * Math.PI / 180;
break; break;
default: default:
@@ -270,24 +270,24 @@ Kinetic.Node.prototype = {
* mouseout, mousedown, mouseup, click, dblclick, touchstart, touchmove, * mouseout, mousedown, mouseup, click, dblclick, touchstart, touchmove,
* touchend, dbltap, dragstart, dragmove, and dragend. Pass in a string * touchend, dbltap, dragstart, dragmove, and dragend. Pass in a string
* of event types delimmited by a space to bind multiple events at once * of event types delimmited by a space to bind multiple events at once
* such as "mousedown mouseup mousemove". include a namespace to bind an * such as 'mousedown mouseup mousemove'. include a namespace to bind an
* event by name such as "click.foobar". * event by name such as 'click.foobar'.
* @param {String} typesStr * @param {String} typesStr
* @param {function} handler * @param {function} handler
*/ */
on: function(typesStr, handler) { on: function(typesStr, handler) {
var types = typesStr.split(" "); var types = typesStr.split(' ');
/* /*
* loop through types and attach event listeners to * loop through types and attach event listeners to
* each one. eg. "click mouseover.namespace mouseout" * each one. eg. 'click mouseover.namespace mouseout'
* will create three event bindings * will create three event bindings
*/ */
for(var n = 0; n < types.length; n++) { for(var n = 0; n < types.length; n++) {
var type = types[n]; var type = types[n];
var event = (type.indexOf('touch') === -1) ? 'on' + type : type; var event = (type.indexOf('touch') === -1) ? 'on' + type : type;
var parts = event.split("."); var parts = event.split('.');
var baseEvent = parts[0]; var baseEvent = parts[0];
var name = parts.length > 1 ? parts[1] : ""; var name = parts.length > 1 ? parts[1] : '';
if(!this.eventListeners[baseEvent]) { if(!this.eventListeners[baseEvent]) {
this.eventListeners[baseEvent] = []; this.eventListeners[baseEvent] = [];
@@ -302,18 +302,18 @@ Kinetic.Node.prototype = {
/** /**
* remove event bindings from the node. Pass in a string of * remove event bindings from the node. Pass in a string of
* event types delimmited by a space to remove multiple event * event types delimmited by a space to remove multiple event
* bindings at once such as "mousedown mouseup mousemove". * bindings at once such as 'mousedown mouseup mousemove'.
* include a namespace to remove an event binding by name * include a namespace to remove an event binding by name
* such as "click.foobar". * such as 'click.foobar'.
* @param {String} typesStr * @param {String} typesStr
*/ */
off: function(typesStr) { off: function(typesStr) {
var types = typesStr.split(" "); var types = typesStr.split(' ');
for(var n = 0; n < types.length; n++) { for(var n = 0; n < types.length; n++) {
var type = types[n]; var type = types[n];
var event = (type.indexOf('touch') === -1) ? 'on' + type : type; var event = (type.indexOf('touch') === -1) ? 'on' + type : type;
var parts = event.split("."); var parts = event.split('.');
var baseEvent = parts[0]; var baseEvent = parts[0];
if(this.eventListeners[baseEvent] && parts.length > 1) { if(this.eventListeners[baseEvent] && parts.length > 1) {
@@ -399,7 +399,7 @@ Kinetic.Node.prototype = {
var x = this.x; var x = this.x;
var y = this.y; var y = this.y;
var parent = this.getParent(); var parent = this.getParent();
while(parent.className !== "Stage") { while(parent.className !== 'Stage') {
x += parent.x; x += parent.x;
y += parent.y; y += parent.y;
parent = parent.parent; parent = parent.parent;
@@ -537,7 +537,7 @@ Kinetic.Node.prototype = {
var absAlpha = 1; var absAlpha = 1;
var node = this; var node = this;
// traverse upwards // traverse upwards
while(node.className !== "Stage") { while(node.className !== 'Stage') {
absAlpha *= node.alpha; absAlpha *= node.alpha;
node = node.parent; node = node.parent;
} }
@@ -652,7 +652,7 @@ Kinetic.Node.prototype = {
if(config.hasOwnProperty(key)) { if(config.hasOwnProperty(key)) {
if(config[key].x !== undefined || config[key].y !== undefined) { if(config[key].x !== undefined || config[key].y !== undefined) {
changes[key] = {}; changes[key] = {};
var propArray = ["x", "y"]; var propArray = ['x', 'y'];
for(var n = 0; n < propArray.length; n++) { for(var n = 0; n < propArray.length; n++) {
var prop = propArray[n]; var prop = propArray[n];
if(config[key][prop] !== undefined) { if(config[key][prop] !== undefined) {
@@ -710,7 +710,7 @@ Kinetic.Node.prototype = {
_initDrag: function() { _initDrag: function() {
var go = Kinetic.GlobalObject; var go = Kinetic.GlobalObject;
var that = this; var that = this;
this.on("mousedown.initdrag touchstart.initdrag", function(evt) { this.on('mousedown.initdrag touchstart.initdrag', function(evt) {
var stage = that.getStage(); var stage = that.getStage();
var pos = stage.getUserPosition(); var pos = stage.getUserPosition();
@@ -725,8 +725,8 @@ Kinetic.Node.prototype = {
* remove drag and drop event listener * remove drag and drop event listener
*/ */
_dragCleanup: function() { _dragCleanup: function() {
this.off("mousedown.initdrag"); this.off('mousedown.initdrag');
this.off("touchstart.initdrag"); this.off('touchstart.initdrag');
}, },
/** /**
* handle node events * handle node events
@@ -744,7 +744,7 @@ Kinetic.Node.prototype = {
} }
} }
if(obj.parent.className !== "Stage") { if(obj.parent.className !== 'Stage') {
handle(obj.parent); handle(obj.parent);
} }
} }
@@ -813,9 +813,10 @@ Kinetic.Container.prototype = {
var children = this.children; var children = this.children;
for(var n = 0; n < children.length; n++) { for(var n = 0; n < children.length; n++) {
var child = children[n]; var child = children[n];
if(child.className === "Shape") { if(child.className === 'Shape') {
child._draw(child.getLayer()); child._draw(child.getLayer());
} else { }
else {
child._draw(); child._draw();
} }
} }
@@ -843,25 +844,26 @@ Kinetic.Container.prototype = {
* from the container except the buffer and backstage canvases * from the container except the buffer and backstage canvases
* and then readd all the layers * and then readd all the layers
*/ */
if(this.className === "Stage") { if(this.className === 'Stage') {
var canvases = this.container.children; var canvases = this.content.children;
var bufferCanvas = canvases[0]; var bufferCanvas = canvases[0];
var backstageCanvas = canvases[1]; var backstageCanvas = canvases[1];
this.container.innerHTML = ""; this.content.innerHTML = '';
this.container.appendChild(bufferCanvas); this.content.appendChild(bufferCanvas);
this.container.appendChild(backstageCanvas); this.content.appendChild(backstageCanvas);
} }
for(var n = 0; n < this.children.length; n++) { for(var n = 0; n < this.children.length; n++) {
this.children[n].index = n; this.children[n].index = n;
if(this.className === "Stage") { if(this.className === 'Stage') {
this.container.appendChild(this.children[n].canvas); this.content.appendChild(this.children[n].canvas);
} }
} }
} }
}; };
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Stage // Stage
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
@@ -874,8 +876,10 @@ Kinetic.Container.prototype = {
* @param {int} height * @param {int} height
*/ */
Kinetic.Stage = function(cont, width, height) { Kinetic.Stage = function(cont, width, height) {
this.className = "Stage"; this.className = 'Stage';
this.container = typeof cont === "string" ? document.getElementById(cont) : cont; this.container = typeof cont === 'string' ? document.getElementById(cont) : cont;
this.content = document.createElement('div');
this.width = width; this.width = width;
this.height = height; this.height = height;
this.scale = { this.scale = {
@@ -905,10 +909,18 @@ Kinetic.Stage = function(cont, width, height) {
this.onFrameFunc = undefined; this.onFrameFunc = undefined;
/* /*
* Layer roles * build DOM
* - buffer: canvas compositing */
* - backstage: path detection
*/ // content
this.content.style.width = width + 'px';
this.content.style.height = height + 'px';
this.content.style.position = 'relative';
this.content.style.display = 'inline-block';
this.content.className = 'kineticjs-content';
this.container.appendChild(this.content);
// default layers
this.bufferLayer = new Kinetic.Layer(); this.bufferLayer = new Kinetic.Layer();
this.backstageLayer = new Kinetic.Layer(); this.backstageLayer = new Kinetic.Layer();
@@ -919,26 +931,25 @@ Kinetic.Stage = function(cont, width, height) {
// customize back stage context // customize back stage context
var backstageLayer = this.backstageLayer; var backstageLayer = this.backstageLayer;
this._stripLayer(backstageLayer); this._stripLayer(backstageLayer);
this.bufferLayer.getCanvas().style.display = 'none'; this.bufferLayer.getCanvas().style.display = 'none';
this.backstageLayer.getCanvas().style.display = 'none'; this.backstageLayer.getCanvas().style.display = 'none';
// add buffer layer // add buffer layer
this.bufferLayer.canvas.width = this.width; this.bufferLayer.canvas.width = this.width;
this.bufferLayer.canvas.height = this.height; this.bufferLayer.canvas.height = this.height;
this.container.appendChild(this.bufferLayer.canvas); this.content.appendChild(this.bufferLayer.canvas);
// add backstage layer // add backstage layer
this.backstageLayer.canvas.width = this.width; this.backstageLayer.canvas.width = this.width;
this.backstageLayer.canvas.height = this.height; this.backstageLayer.canvas.height = this.height;
this.container.appendChild(this.backstageLayer.canvas); this.content.appendChild(this.backstageLayer.canvas);
// listen for events and prepare drag and drop
this._listen(); this._listen();
this._prepareDrag(); this._prepareDrag();
// add stage to global object // add stage to global object
var stages = Kinetic.GlobalObject.stages; Kinetic.GlobalObject.stages.push(this);
stages.push(this);
// call super constructor // call super constructor
Kinetic.Container.apply(this, []); Kinetic.Container.apply(this, []);
@@ -1083,7 +1094,7 @@ Kinetic.Stage.prototype = {
*/ */
remove: function(layer) { remove: function(layer) {
// remove layer canvas from dom // remove layer canvas from dom
this.container.removeChild(layer.canvas); this.content.removeChild(layer.canvas);
this._remove(layer); this._remove(layer);
}, },
@@ -1094,7 +1105,7 @@ Kinetic.Stage.prototype = {
* @param {function} handler * @param {function} handler
*/ */
on: function(typesStr, handler) { on: function(typesStr, handler) {
var types = typesStr.split(" "); var types = typesStr.split(' ');
for(var n = 0; n < types.length; n++) { for(var n = 0; n < types.length; n++) {
var baseEvent = types[n]; var baseEvent = types[n];
this.container.addEventListener(baseEvent, handler, false); this.container.addEventListener(baseEvent, handler, false);
@@ -1114,7 +1125,7 @@ Kinetic.Stage.prototype = {
// draw layer and append canvas to container // draw layer and append canvas to container
layer.draw(); layer.draw();
this.container.appendChild(layer.canvas); this.content.appendChild(layer.canvas);
}, },
/** /**
* get mouse position for desktop apps * get mouse position for desktop apps
@@ -1172,14 +1183,14 @@ Kinetic.Stage.prototype = {
if(!isDragging && this.mouseDown) { if(!isDragging && this.mouseDown) {
this.mouseDown = false; this.mouseDown = false;
this.clickStart = true; this.clickStart = true;
shape._handleEvents("onmousedown", evt); shape._handleEvents('onmousedown', evt);
return true; return true;
} }
// handle onmouseup & onclick // handle onmouseup & onclick
else else
if(this.mouseUp) { if(this.mouseUp) {
this.mouseUp = false; this.mouseUp = false;
shape._handleEvents("onmouseup", evt); shape._handleEvents('onmouseup', evt);
// detect if click or double click occurred // detect if click or double click occurred
if(this.clickStart) { if(this.clickStart) {
@@ -1188,10 +1199,10 @@ Kinetic.Stage.prototype = {
* event * event
*/ */
if((!go.drag.moving) || !go.drag.node) { if((!go.drag.moving) || !go.drag.node) {
shape._handleEvents("onclick", evt); shape._handleEvents('onclick', evt);
if(shape.inDoubleClickWindow) { if(shape.inDoubleClickWindow) {
shape._handleEvents("ondblclick", evt); shape._handleEvents('ondblclick', evt);
} }
shape.inDoubleClickWindow = true; shape.inDoubleClickWindow = true;
setTimeout(function() { setTimeout(function() {
@@ -1206,7 +1217,7 @@ Kinetic.Stage.prototype = {
else else
if(this.touchStart) { if(this.touchStart) {
this.touchStart = false; this.touchStart = false;
shape._handleEvents("touchstart", evt); shape._handleEvents('touchstart', evt);
if(el.ondbltap && shape.inDoubleClickWindow) { if(el.ondbltap && shape.inDoubleClickWindow) {
var events = el.ondbltap; var events = el.ondbltap;
@@ -1227,14 +1238,14 @@ Kinetic.Stage.prototype = {
else else
if(this.touchEnd) { if(this.touchEnd) {
this.touchEnd = false; this.touchEnd = false;
shape._handleEvents("touchend", evt); shape._handleEvents('touchend', evt);
return true; return true;
} }
// handle touchmove // handle touchmove
else else
if(!isDragging && el.touchmove) { if(!isDragging && el.touchmove) {
shape._handleEvents("touchmove", evt); shape._handleEvents('touchmove', evt);
return true; return true;
} }
@@ -1247,7 +1258,7 @@ Kinetic.Stage.prototype = {
if(this.targetShape) { if(this.targetShape) {
var oldEl = this.targetShape.eventListeners; var oldEl = this.targetShape.eventListeners;
if(oldEl) { if(oldEl) {
this.targetShape._handleEvents("onmouseout", evt); this.targetShape._handleEvents('onmouseout', evt);
} }
} }
@@ -1256,14 +1267,14 @@ Kinetic.Stage.prototype = {
this.targetFound = true; this.targetFound = true;
// handle onmouseover // handle onmouseover
shape._handleEvents("onmouseover", evt); shape._handleEvents('onmouseover', evt);
return true; return true;
} }
// handle onmousemove // handle onmousemove
else else
if(!isDragging) { if(!isDragging) {
shape._handleEvents("onmousemove", evt); shape._handleEvents('onmousemove', evt);
return true; return true;
} }
} }
@@ -1271,7 +1282,7 @@ Kinetic.Stage.prototype = {
else else
if(!isDragging && this.targetShape && this.targetShape.id === shape.id) { if(!isDragging && this.targetShape && this.targetShape.id === shape.id) {
this.targetShape = undefined; this.targetShape = undefined;
shape._handleEvents("onmouseout", evt); shape._handleEvents('onmouseout', evt);
return true; return true;
} }
@@ -1286,7 +1297,7 @@ Kinetic.Stage.prototype = {
// propapgate backwards through children // propapgate backwards through children
for(var i = children.length - 1; i >= 0; i--) { for(var i = children.length - 1; i >= 0; i--) {
var child = children[i]; var child = children[i];
if(child.className === "Shape") { if(child.className === 'Shape') {
var exit = this._detectEvent(child, evt); var exit = this._detectEvent(child, evt);
if(exit) { if(exit) {
return true; return true;
@@ -1339,18 +1350,18 @@ Kinetic.Stage.prototype = {
var that = this; var that = this;
// desktop events // desktop events
this.container.addEventListener("mousedown", function(evt) { this.container.addEventListener('mousedown', function(evt) {
that.mouseDown = true; that.mouseDown = true;
that._handleEvent(evt); that._handleEvent(evt);
}, false); }, false);
this.container.addEventListener("mousemove", function(evt) { this.container.addEventListener('mousemove', function(evt) {
that.mouseUp = false; that.mouseUp = false;
that.mouseDown = false; that.mouseDown = false;
that._handleEvent(evt); that._handleEvent(evt);
}, false); }, false);
this.container.addEventListener("mouseup", function(evt) { this.container.addEventListener('mouseup', function(evt) {
that.mouseUp = true; that.mouseUp = true;
that.mouseDown = false; that.mouseDown = false;
that._handleEvent(evt); that._handleEvent(evt);
@@ -1358,26 +1369,26 @@ Kinetic.Stage.prototype = {
that.clickStart = false; that.clickStart = false;
}, false); }, false);
this.container.addEventListener("mouseover", function(evt) { this.container.addEventListener('mouseover', function(evt) {
that._handleEvent(evt); that._handleEvent(evt);
}, false); }, false);
this.container.addEventListener("mouseout", function(evt) { this.container.addEventListener('mouseout', function(evt) {
that.mousePos = undefined; that.mousePos = undefined;
}, false); }, false);
// mobile events // mobile events
this.container.addEventListener("touchstart", function(evt) { this.container.addEventListener('touchstart', function(evt) {
evt.preventDefault(); evt.preventDefault();
that.touchStart = true; that.touchStart = true;
that._handleEvent(evt); that._handleEvent(evt);
}, false); }, false);
this.container.addEventListener("touchmove", function(evt) { this.container.addEventListener('touchmove', function(evt) {
evt.preventDefault(); evt.preventDefault();
that._handleEvent(evt); that._handleEvent(evt);
}, false); }, false);
this.container.addEventListener("touchend", function(evt) { this.container.addEventListener('touchend', function(evt) {
evt.preventDefault(); evt.preventDefault();
that.touchEnd = true; that.touchEnd = true;
that._handleEvent(evt); that._handleEvent(evt);
@@ -1420,9 +1431,9 @@ Kinetic.Stage.prototype = {
var obj = this.container; var obj = this.container;
var top = 0; var top = 0;
var left = 0; var left = 0;
while(obj && obj.tagName !== "BODY") { while(obj && obj.tagName !== 'BODY') {
top += obj.offsetTop; top += obj.offsetTop - obj.scrollTop;
left += obj.offsetLeft; left += obj.offsetLeft - obj.scrollLeft;
obj = obj.offsetParent; obj = obj.offsetParent;
} }
return { return {
@@ -1460,7 +1471,7 @@ Kinetic.Stage.prototype = {
if(go.drag.node) { if(go.drag.node) {
if(go.drag.moving) { if(go.drag.moving) {
go.drag.moving = false; go.drag.moving = false;
go.drag.node._handleEvents("ondragend", evt); go.drag.node._handleEvents('ondragend', evt);
} }
} }
go.drag.node = undefined; go.drag.node = undefined;
@@ -1471,20 +1482,20 @@ Kinetic.Stage.prototype = {
_prepareDrag: function() { _prepareDrag: function() {
var that = this; var that = this;
this.on("mousemove touchmove", function(evt) { this.on('mousemove touchmove', function(evt) {
var go = Kinetic.GlobalObject; var go = Kinetic.GlobalObject;
var node = go.drag.node; var node = go.drag.node;
if(node) { if(node) {
var pos = that.getUserPosition(); var pos = that.getUserPosition();
var ds = node.dragConstraint; var ds = node.dragConstraint;
var db = node.dragBounds; var db = node.dragBounds;
if(ds === "none" || ds === "horizontal") { if(ds === 'none' || ds === 'horizontal') {
var newX = pos.x - go.drag.offset.x; var newX = pos.x - go.drag.offset.x;
if((db.left === undefined || db.left < newX) && (db.right === undefined || db.right > newX)) { if((db.left === undefined || db.left < newX) && (db.right === undefined || db.right > newX)) {
node.x = newX; node.x = newX;
} }
} }
if(ds === "none" || ds === "vertical") { if(ds === 'none' || ds === 'vertical') {
var newY = pos.y - go.drag.offset.y; var newY = pos.y - go.drag.offset.y;
if((db.top === undefined || db.top < newY) && (db.bottom === undefined || db.bottom > newY)) { if((db.top === undefined || db.top < newY) && (db.bottom === undefined || db.bottom > newY)) {
node.y = newY; node.y = newY;
@@ -1495,14 +1506,14 @@ Kinetic.Stage.prototype = {
if(!go.drag.moving) { if(!go.drag.moving) {
go.drag.moving = true; go.drag.moving = true;
// execute dragstart events if defined // execute dragstart events if defined
go.drag.node._handleEvents("ondragstart", evt); go.drag.node._handleEvents('ondragstart', evt);
} }
// execute user defined ondragmove if defined // execute user defined ondragmove if defined
go.drag.node._handleEvents("ondragmove", evt); go.drag.node._handleEvents('ondragmove', evt);
} }
}, false); }, false);
this.on("mouseup touchend mouseout", function(evt) { this.on('mouseup touchend mouseout', function(evt) {
that._endDrag(evt); that._endDrag(evt);
}); });
} }
@@ -1522,7 +1533,7 @@ Kinetic.GlobalObject.extend(Kinetic.Stage, Kinetic.Container);
* @param {Object} config * @param {Object} config
*/ */
Kinetic.Layer = function(config) { Kinetic.Layer = function(config) {
this.className = "Layer"; this.className = 'Layer';
this.canvas = document.createElement('canvas'); this.canvas = document.createElement('canvas');
this.context = this.canvas.getContext('2d'); this.context = this.canvas.getContext('2d');
this.canvas.style.position = 'absolute'; this.canvas.style.position = 'absolute';
@@ -1603,7 +1614,7 @@ Kinetic.GlobalObject.extend(Kinetic.Layer, Kinetic.Node);
* @param {Object} config * @param {Object} config
*/ */
Kinetic.Group = function(config) { Kinetic.Group = function(config) {
this.className = "Group"; this.className = 'Group';
// call super constructors // call super constructors
Kinetic.Container.apply(this, []); Kinetic.Container.apply(this, []);
@@ -1640,6 +1651,7 @@ Kinetic.Group.prototype = {
// Extend Container and Node // Extend Container and Node
Kinetic.GlobalObject.extend(Kinetic.Group, Kinetic.Container); Kinetic.GlobalObject.extend(Kinetic.Group, Kinetic.Container);
Kinetic.GlobalObject.extend(Kinetic.Group, Kinetic.Node); Kinetic.GlobalObject.extend(Kinetic.Group, Kinetic.Node);
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Shape // Shape
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
@@ -1651,12 +1663,12 @@ Kinetic.GlobalObject.extend(Kinetic.Group, Kinetic.Node);
* @param {Object} config * @param {Object} config
*/ */
Kinetic.Shape = function(config) { Kinetic.Shape = function(config) {
this.className = "Shape"; this.className = 'Shape';
// defaults // defaults
if(config.stroke !== undefined || config.strokeWidth !== undefined) { if(config.stroke !== undefined || config.strokeWidth !== undefined) {
if(config.stroke === undefined) { if(config.stroke === undefined) {
config.stroke = "black"; config.stroke = 'black';
} }
else else
if(config.strokeWidth === undefined) { if(config.strokeWidth === undefined) {
@@ -1760,7 +1772,7 @@ Kinetic.Shape.prototype = {
family.unshift(this); family.unshift(this);
var parent = this.parent; var parent = this.parent;
while(parent.className !== "Stage") { while(parent.className !== 'Stage') {
family.unshift(parent); family.unshift(parent);
parent = parent.parent; parent = parent.parent;
} }
@@ -2210,16 +2222,18 @@ Kinetic.Text = function(config) {
*/ */
if(config.textStroke !== undefined || config.textStrokeWidth !== undefined) { if(config.textStroke !== undefined || config.textStrokeWidth !== undefined) {
if(config.textStroke === undefined) { if(config.textStroke === undefined) {
config.textStroke = "black"; config.textStroke = 'black';
} else if(config.textStrokeWidth === undefined) { }
else
if(config.textStrokeWidth === undefined) {
config.textStrokeWidth = 2; config.textStrokeWidth = 2;
} }
} }
if(config.align === undefined) { if(config.align === undefined) {
config.align = "left"; config.align = 'left';
} }
if(config.verticalAlign === undefined) { if(config.verticalAlign === undefined) {
config.verticalAlign = "top"; config.verticalAlign = 'top';
} }
if(config.padding === undefined) { if(config.padding === undefined) {
config.padding = 0; config.padding = 0;
@@ -2227,8 +2241,8 @@ Kinetic.Text = function(config) {
config.drawFunc = function() { config.drawFunc = function() {
var context = this.getContext(); var context = this.getContext();
context.font = this.fontSize + "pt " + this.fontFamily; context.font = this.fontSize + 'pt ' + this.fontFamily;
context.textBaseline = "middle"; context.textBaseline = 'middle';
var metrics = context.measureText(this.text); var metrics = context.measureText(this.text);
var textHeight = this.fontSize; var textHeight = this.fontSize;
var textWidth = metrics.width; var textWidth = metrics.width;
@@ -2237,19 +2251,19 @@ Kinetic.Text = function(config) {
var y = 0; var y = 0;
switch (this.align) { switch (this.align) {
case "center": case 'center':
x = textWidth / -2 - p; x = textWidth / -2 - p;
break; break;
case "right": case 'right':
x = -1 * textWidth - p; x = -1 * textWidth - p;
break; break;
} }
switch (this.verticalAlign) { switch (this.verticalAlign) {
case "middle": case 'middle':
y = textHeight / -2 - p; y = textHeight / -2 - p;
break; break;
case "bottom": case 'bottom':
y = -1 * textHeight - p; y = -1 * textHeight - p;
break; break;
} }
@@ -2273,8 +2287,10 @@ Kinetic.Text = function(config) {
if(this.textStroke !== undefined || this.textStrokeWidth !== undefined) { if(this.textStroke !== undefined || this.textStrokeWidth !== undefined) {
// defaults // defaults
if(this.textStroke === undefined) { if(this.textStroke === undefined) {
this.textStroke = "black"; this.textStroke = 'black';
} else if(this.textStrokeWidth === undefined) { }
else
if(this.textStrokeWidth === undefined) {
this.textStrokeWidth = 2; this.textStrokeWidth = 2;
} }
context.lineWidth = this.textStrokeWidth; context.lineWidth = this.textStrokeWidth;
@@ -2369,7 +2385,7 @@ Kinetic.Text.prototype = {
}, },
/** /**
* set horizontal align of text * set horizontal align of text
* @param {String} align align can be "left", "center", or "right" * @param {String} align align can be 'left', 'center', or 'right'
*/ */
setAlign: function(align) { setAlign: function(align) {
this.align = align; this.align = align;

File diff suppressed because one or more lines are too long

View File

@@ -54,9 +54,10 @@ Kinetic.Container.prototype = {
var children = this.children; var children = this.children;
for(var n = 0; n < children.length; n++) { for(var n = 0; n < children.length; n++) {
var child = children[n]; var child = children[n];
if(child.className === "Shape") { if(child.className === 'Shape') {
child._draw(child.getLayer()); child._draw(child.getLayer());
} else { }
else {
child._draw(); child._draw();
} }
} }
@@ -84,22 +85,22 @@ Kinetic.Container.prototype = {
* from the container except the buffer and backstage canvases * from the container except the buffer and backstage canvases
* and then readd all the layers * and then readd all the layers
*/ */
if(this.className === "Stage") { if(this.className === 'Stage') {
var canvases = this.container.children; var canvases = this.content.children;
var bufferCanvas = canvases[0]; var bufferCanvas = canvases[0];
var backstageCanvas = canvases[1]; var backstageCanvas = canvases[1];
this.container.innerHTML = ""; this.content.innerHTML = '';
this.container.appendChild(bufferCanvas); this.content.appendChild(bufferCanvas);
this.container.appendChild(backstageCanvas); this.content.appendChild(backstageCanvas);
} }
for(var n = 0; n < this.children.length; n++) { for(var n = 0; n < this.children.length; n++) {
this.children[n].index = n; this.children[n].index = n;
if(this.className === "Stage") { if(this.className === 'Stage') {
this.container.appendChild(this.children[n].canvas); this.content.appendChild(this.children[n].canvas);
} }
} }
} }
}; };

View File

@@ -47,7 +47,7 @@ Kinetic.GlobalObject = {
for(var key in config) { for(var key in config) {
if(config.hasOwnProperty(key)) { if(config.hasOwnProperty(key)) {
if(config[key].x !== undefined || config[key].y !== undefined) { if(config[key].x !== undefined || config[key].y !== undefined) {
var propArray = ["x", "y"]; var propArray = ['x', 'y'];
for(var n = 0; n < propArray.length; n++) { for(var n = 0; n < propArray.length; n++) {
var prop = propArray[n]; var prop = propArray[n];
if(config[key][prop] !== undefined) { if(config[key][prop] !== undefined) {
@@ -66,7 +66,7 @@ Kinetic.GlobalObject = {
for(var key in config) { for(var key in config) {
if(config.hasOwnProperty(key)) { if(config.hasOwnProperty(key)) {
if(config[key].x !== undefined || config[key].y !== undefined) { if(config[key].x !== undefined || config[key].y !== undefined) {
var propArray = ["x", "y"]; var propArray = ['x', 'y'];
for(var n = 0; n < propArray.length; n++) { for(var n = 0; n < propArray.length; n++) {
var prop = propArray[n]; var prop = propArray[n];
if(config[key][prop] !== undefined) { if(config[key][prop] !== undefined) {

View File

@@ -10,7 +10,7 @@
* @param {Object} config * @param {Object} config
*/ */
Kinetic.Group = function(config) { Kinetic.Group = function(config) {
this.className = "Group"; this.className = 'Group';
// call super constructors // call super constructors
Kinetic.Container.apply(this, []); Kinetic.Container.apply(this, []);
@@ -46,4 +46,4 @@ Kinetic.Group.prototype = {
// Extend Container and Node // Extend Container and Node
Kinetic.GlobalObject.extend(Kinetic.Group, Kinetic.Container); Kinetic.GlobalObject.extend(Kinetic.Group, Kinetic.Container);
Kinetic.GlobalObject.extend(Kinetic.Group, Kinetic.Node); Kinetic.GlobalObject.extend(Kinetic.Group, Kinetic.Node);

View File

@@ -10,7 +10,7 @@
* @param {Object} config * @param {Object} config
*/ */
Kinetic.Layer = function(config) { Kinetic.Layer = function(config) {
this.className = "Layer"; this.className = 'Layer';
this.canvas = document.createElement('canvas'); this.canvas = document.createElement('canvas');
this.context = this.canvas.getContext('2d'); this.context = this.canvas.getContext('2d');
this.canvas.style.position = 'absolute'; this.canvas.style.position = 'absolute';

View File

@@ -25,7 +25,7 @@ Kinetic.Node = function(config) {
y: 0 y: 0
}; };
this.eventListeners = {}; this.eventListeners = {};
this.dragConstraint = "none"; this.dragConstraint = 'none';
this.dragBounds = {}; this.dragBounds = {};
this._draggable = false; this._draggable = false;
@@ -34,13 +34,13 @@ Kinetic.Node = function(config) {
for(var key in config) { for(var key in config) {
// handle special keys // handle special keys
switch (key) { switch (key) {
case "draggable": case 'draggable':
this.draggable(config[key]); this.draggable(config[key]);
break; break;
case "listen": case 'listen':
this.listen(config[key]); this.listen(config[key]);
break; break;
case "rotationDeg": case 'rotationDeg':
this.rotation = config[key] * Math.PI / 180; this.rotation = config[key] * Math.PI / 180;
break; break;
default: default:
@@ -67,24 +67,24 @@ Kinetic.Node.prototype = {
* mouseout, mousedown, mouseup, click, dblclick, touchstart, touchmove, * mouseout, mousedown, mouseup, click, dblclick, touchstart, touchmove,
* touchend, dbltap, dragstart, dragmove, and dragend. Pass in a string * touchend, dbltap, dragstart, dragmove, and dragend. Pass in a string
* of event types delimmited by a space to bind multiple events at once * of event types delimmited by a space to bind multiple events at once
* such as "mousedown mouseup mousemove". include a namespace to bind an * such as 'mousedown mouseup mousemove'. include a namespace to bind an
* event by name such as "click.foobar". * event by name such as 'click.foobar'.
* @param {String} typesStr * @param {String} typesStr
* @param {function} handler * @param {function} handler
*/ */
on: function(typesStr, handler) { on: function(typesStr, handler) {
var types = typesStr.split(" "); var types = typesStr.split(' ');
/* /*
* loop through types and attach event listeners to * loop through types and attach event listeners to
* each one. eg. "click mouseover.namespace mouseout" * each one. eg. 'click mouseover.namespace mouseout'
* will create three event bindings * will create three event bindings
*/ */
for(var n = 0; n < types.length; n++) { for(var n = 0; n < types.length; n++) {
var type = types[n]; var type = types[n];
var event = (type.indexOf('touch') === -1) ? 'on' + type : type; var event = (type.indexOf('touch') === -1) ? 'on' + type : type;
var parts = event.split("."); var parts = event.split('.');
var baseEvent = parts[0]; var baseEvent = parts[0];
var name = parts.length > 1 ? parts[1] : ""; var name = parts.length > 1 ? parts[1] : '';
if(!this.eventListeners[baseEvent]) { if(!this.eventListeners[baseEvent]) {
this.eventListeners[baseEvent] = []; this.eventListeners[baseEvent] = [];
@@ -99,18 +99,18 @@ Kinetic.Node.prototype = {
/** /**
* remove event bindings from the node. Pass in a string of * remove event bindings from the node. Pass in a string of
* event types delimmited by a space to remove multiple event * event types delimmited by a space to remove multiple event
* bindings at once such as "mousedown mouseup mousemove". * bindings at once such as 'mousedown mouseup mousemove'.
* include a namespace to remove an event binding by name * include a namespace to remove an event binding by name
* such as "click.foobar". * such as 'click.foobar'.
* @param {String} typesStr * @param {String} typesStr
*/ */
off: function(typesStr) { off: function(typesStr) {
var types = typesStr.split(" "); var types = typesStr.split(' ');
for(var n = 0; n < types.length; n++) { for(var n = 0; n < types.length; n++) {
var type = types[n]; var type = types[n];
var event = (type.indexOf('touch') === -1) ? 'on' + type : type; var event = (type.indexOf('touch') === -1) ? 'on' + type : type;
var parts = event.split("."); var parts = event.split('.');
var baseEvent = parts[0]; var baseEvent = parts[0];
if(this.eventListeners[baseEvent] && parts.length > 1) { if(this.eventListeners[baseEvent] && parts.length > 1) {
@@ -196,7 +196,7 @@ Kinetic.Node.prototype = {
var x = this.x; var x = this.x;
var y = this.y; var y = this.y;
var parent = this.getParent(); var parent = this.getParent();
while(parent.className !== "Stage") { while(parent.className !== 'Stage') {
x += parent.x; x += parent.x;
y += parent.y; y += parent.y;
parent = parent.parent; parent = parent.parent;
@@ -334,7 +334,7 @@ Kinetic.Node.prototype = {
var absAlpha = 1; var absAlpha = 1;
var node = this; var node = this;
// traverse upwards // traverse upwards
while(node.className !== "Stage") { while(node.className !== 'Stage') {
absAlpha *= node.alpha; absAlpha *= node.alpha;
node = node.parent; node = node.parent;
} }
@@ -449,7 +449,7 @@ Kinetic.Node.prototype = {
if(config.hasOwnProperty(key)) { if(config.hasOwnProperty(key)) {
if(config[key].x !== undefined || config[key].y !== undefined) { if(config[key].x !== undefined || config[key].y !== undefined) {
changes[key] = {}; changes[key] = {};
var propArray = ["x", "y"]; var propArray = ['x', 'y'];
for(var n = 0; n < propArray.length; n++) { for(var n = 0; n < propArray.length; n++) {
var prop = propArray[n]; var prop = propArray[n];
if(config[key][prop] !== undefined) { if(config[key][prop] !== undefined) {
@@ -507,7 +507,7 @@ Kinetic.Node.prototype = {
_initDrag: function() { _initDrag: function() {
var go = Kinetic.GlobalObject; var go = Kinetic.GlobalObject;
var that = this; var that = this;
this.on("mousedown.initdrag touchstart.initdrag", function(evt) { this.on('mousedown.initdrag touchstart.initdrag', function(evt) {
var stage = that.getStage(); var stage = that.getStage();
var pos = stage.getUserPosition(); var pos = stage.getUserPosition();
@@ -522,8 +522,8 @@ Kinetic.Node.prototype = {
* remove drag and drop event listener * remove drag and drop event listener
*/ */
_dragCleanup: function() { _dragCleanup: function() {
this.off("mousedown.initdrag"); this.off('mousedown.initdrag');
this.off("touchstart.initdrag"); this.off('touchstart.initdrag');
}, },
/** /**
* handle node events * handle node events
@@ -541,7 +541,7 @@ Kinetic.Node.prototype = {
} }
} }
if(obj.parent.className !== "Stage") { if(obj.parent.className !== 'Stage') {
handle(obj.parent); handle(obj.parent);
} }
} }

View File

@@ -9,12 +9,12 @@
* @param {Object} config * @param {Object} config
*/ */
Kinetic.Shape = function(config) { Kinetic.Shape = function(config) {
this.className = "Shape"; this.className = 'Shape';
// defaults // defaults
if(config.stroke !== undefined || config.strokeWidth !== undefined) { if(config.stroke !== undefined || config.strokeWidth !== undefined) {
if(config.stroke === undefined) { if(config.stroke === undefined) {
config.stroke = "black"; config.stroke = 'black';
} }
else else
if(config.strokeWidth === undefined) { if(config.strokeWidth === undefined) {
@@ -118,7 +118,7 @@ Kinetic.Shape.prototype = {
family.unshift(this); family.unshift(this);
var parent = this.parent; var parent = this.parent;
while(parent.className !== "Stage") { while(parent.className !== 'Stage') {
family.unshift(parent); family.unshift(parent);
parent = parent.parent; parent = parent.parent;
} }

View File

@@ -10,8 +10,10 @@
* @param {int} height * @param {int} height
*/ */
Kinetic.Stage = function(cont, width, height) { Kinetic.Stage = function(cont, width, height) {
this.className = "Stage"; this.className = 'Stage';
this.container = typeof cont === "string" ? document.getElementById(cont) : cont; this.container = typeof cont === 'string' ? document.getElementById(cont) : cont;
this.content = document.createElement('div');
this.width = width; this.width = width;
this.height = height; this.height = height;
this.scale = { this.scale = {
@@ -41,10 +43,18 @@ Kinetic.Stage = function(cont, width, height) {
this.onFrameFunc = undefined; this.onFrameFunc = undefined;
/* /*
* Layer roles * build DOM
* - buffer: canvas compositing */
* - backstage: path detection
*/ // content
this.content.style.width = width + 'px';
this.content.style.height = height + 'px';
this.content.style.position = 'relative';
this.content.style.display = 'inline-block';
this.content.className = 'kineticjs-content';
this.container.appendChild(this.content);
// default layers
this.bufferLayer = new Kinetic.Layer(); this.bufferLayer = new Kinetic.Layer();
this.backstageLayer = new Kinetic.Layer(); this.backstageLayer = new Kinetic.Layer();
@@ -55,26 +65,25 @@ Kinetic.Stage = function(cont, width, height) {
// customize back stage context // customize back stage context
var backstageLayer = this.backstageLayer; var backstageLayer = this.backstageLayer;
this._stripLayer(backstageLayer); this._stripLayer(backstageLayer);
this.bufferLayer.getCanvas().style.display = 'none'; this.bufferLayer.getCanvas().style.display = 'none';
this.backstageLayer.getCanvas().style.display = 'none'; this.backstageLayer.getCanvas().style.display = 'none';
// add buffer layer // add buffer layer
this.bufferLayer.canvas.width = this.width; this.bufferLayer.canvas.width = this.width;
this.bufferLayer.canvas.height = this.height; this.bufferLayer.canvas.height = this.height;
this.container.appendChild(this.bufferLayer.canvas); this.content.appendChild(this.bufferLayer.canvas);
// add backstage layer // add backstage layer
this.backstageLayer.canvas.width = this.width; this.backstageLayer.canvas.width = this.width;
this.backstageLayer.canvas.height = this.height; this.backstageLayer.canvas.height = this.height;
this.container.appendChild(this.backstageLayer.canvas); this.content.appendChild(this.backstageLayer.canvas);
// listen for events and prepare drag and drop
this._listen(); this._listen();
this._prepareDrag(); this._prepareDrag();
// add stage to global object // add stage to global object
var stages = Kinetic.GlobalObject.stages; Kinetic.GlobalObject.stages.push(this);
stages.push(this);
// call super constructor // call super constructor
Kinetic.Container.apply(this, []); Kinetic.Container.apply(this, []);
@@ -219,7 +228,7 @@ Kinetic.Stage.prototype = {
*/ */
remove: function(layer) { remove: function(layer) {
// remove layer canvas from dom // remove layer canvas from dom
this.container.removeChild(layer.canvas); this.content.removeChild(layer.canvas);
this._remove(layer); this._remove(layer);
}, },
@@ -230,7 +239,7 @@ Kinetic.Stage.prototype = {
* @param {function} handler * @param {function} handler
*/ */
on: function(typesStr, handler) { on: function(typesStr, handler) {
var types = typesStr.split(" "); var types = typesStr.split(' ');
for(var n = 0; n < types.length; n++) { for(var n = 0; n < types.length; n++) {
var baseEvent = types[n]; var baseEvent = types[n];
this.container.addEventListener(baseEvent, handler, false); this.container.addEventListener(baseEvent, handler, false);
@@ -250,7 +259,7 @@ Kinetic.Stage.prototype = {
// draw layer and append canvas to container // draw layer and append canvas to container
layer.draw(); layer.draw();
this.container.appendChild(layer.canvas); this.content.appendChild(layer.canvas);
}, },
/** /**
* get mouse position for desktop apps * get mouse position for desktop apps
@@ -308,14 +317,14 @@ Kinetic.Stage.prototype = {
if(!isDragging && this.mouseDown) { if(!isDragging && this.mouseDown) {
this.mouseDown = false; this.mouseDown = false;
this.clickStart = true; this.clickStart = true;
shape._handleEvents("onmousedown", evt); shape._handleEvents('onmousedown', evt);
return true; return true;
} }
// handle onmouseup & onclick // handle onmouseup & onclick
else else
if(this.mouseUp) { if(this.mouseUp) {
this.mouseUp = false; this.mouseUp = false;
shape._handleEvents("onmouseup", evt); shape._handleEvents('onmouseup', evt);
// detect if click or double click occurred // detect if click or double click occurred
if(this.clickStart) { if(this.clickStart) {
@@ -324,10 +333,10 @@ Kinetic.Stage.prototype = {
* event * event
*/ */
if((!go.drag.moving) || !go.drag.node) { if((!go.drag.moving) || !go.drag.node) {
shape._handleEvents("onclick", evt); shape._handleEvents('onclick', evt);
if(shape.inDoubleClickWindow) { if(shape.inDoubleClickWindow) {
shape._handleEvents("ondblclick", evt); shape._handleEvents('ondblclick', evt);
} }
shape.inDoubleClickWindow = true; shape.inDoubleClickWindow = true;
setTimeout(function() { setTimeout(function() {
@@ -342,7 +351,7 @@ Kinetic.Stage.prototype = {
else else
if(this.touchStart) { if(this.touchStart) {
this.touchStart = false; this.touchStart = false;
shape._handleEvents("touchstart", evt); shape._handleEvents('touchstart', evt);
if(el.ondbltap && shape.inDoubleClickWindow) { if(el.ondbltap && shape.inDoubleClickWindow) {
var events = el.ondbltap; var events = el.ondbltap;
@@ -363,14 +372,14 @@ Kinetic.Stage.prototype = {
else else
if(this.touchEnd) { if(this.touchEnd) {
this.touchEnd = false; this.touchEnd = false;
shape._handleEvents("touchend", evt); shape._handleEvents('touchend', evt);
return true; return true;
} }
// handle touchmove // handle touchmove
else else
if(!isDragging && el.touchmove) { if(!isDragging && el.touchmove) {
shape._handleEvents("touchmove", evt); shape._handleEvents('touchmove', evt);
return true; return true;
} }
@@ -383,7 +392,7 @@ Kinetic.Stage.prototype = {
if(this.targetShape) { if(this.targetShape) {
var oldEl = this.targetShape.eventListeners; var oldEl = this.targetShape.eventListeners;
if(oldEl) { if(oldEl) {
this.targetShape._handleEvents("onmouseout", evt); this.targetShape._handleEvents('onmouseout', evt);
} }
} }
@@ -392,14 +401,14 @@ Kinetic.Stage.prototype = {
this.targetFound = true; this.targetFound = true;
// handle onmouseover // handle onmouseover
shape._handleEvents("onmouseover", evt); shape._handleEvents('onmouseover', evt);
return true; return true;
} }
// handle onmousemove // handle onmousemove
else else
if(!isDragging) { if(!isDragging) {
shape._handleEvents("onmousemove", evt); shape._handleEvents('onmousemove', evt);
return true; return true;
} }
} }
@@ -407,7 +416,7 @@ Kinetic.Stage.prototype = {
else else
if(!isDragging && this.targetShape && this.targetShape.id === shape.id) { if(!isDragging && this.targetShape && this.targetShape.id === shape.id) {
this.targetShape = undefined; this.targetShape = undefined;
shape._handleEvents("onmouseout", evt); shape._handleEvents('onmouseout', evt);
return true; return true;
} }
@@ -422,7 +431,7 @@ Kinetic.Stage.prototype = {
// propapgate backwards through children // propapgate backwards through children
for(var i = children.length - 1; i >= 0; i--) { for(var i = children.length - 1; i >= 0; i--) {
var child = children[i]; var child = children[i];
if(child.className === "Shape") { if(child.className === 'Shape') {
var exit = this._detectEvent(child, evt); var exit = this._detectEvent(child, evt);
if(exit) { if(exit) {
return true; return true;
@@ -475,18 +484,18 @@ Kinetic.Stage.prototype = {
var that = this; var that = this;
// desktop events // desktop events
this.container.addEventListener("mousedown", function(evt) { this.container.addEventListener('mousedown', function(evt) {
that.mouseDown = true; that.mouseDown = true;
that._handleEvent(evt); that._handleEvent(evt);
}, false); }, false);
this.container.addEventListener("mousemove", function(evt) { this.container.addEventListener('mousemove', function(evt) {
that.mouseUp = false; that.mouseUp = false;
that.mouseDown = false; that.mouseDown = false;
that._handleEvent(evt); that._handleEvent(evt);
}, false); }, false);
this.container.addEventListener("mouseup", function(evt) { this.container.addEventListener('mouseup', function(evt) {
that.mouseUp = true; that.mouseUp = true;
that.mouseDown = false; that.mouseDown = false;
that._handleEvent(evt); that._handleEvent(evt);
@@ -494,26 +503,26 @@ Kinetic.Stage.prototype = {
that.clickStart = false; that.clickStart = false;
}, false); }, false);
this.container.addEventListener("mouseover", function(evt) { this.container.addEventListener('mouseover', function(evt) {
that._handleEvent(evt); that._handleEvent(evt);
}, false); }, false);
this.container.addEventListener("mouseout", function(evt) { this.container.addEventListener('mouseout', function(evt) {
that.mousePos = undefined; that.mousePos = undefined;
}, false); }, false);
// mobile events // mobile events
this.container.addEventListener("touchstart", function(evt) { this.container.addEventListener('touchstart', function(evt) {
evt.preventDefault(); evt.preventDefault();
that.touchStart = true; that.touchStart = true;
that._handleEvent(evt); that._handleEvent(evt);
}, false); }, false);
this.container.addEventListener("touchmove", function(evt) { this.container.addEventListener('touchmove', function(evt) {
evt.preventDefault(); evt.preventDefault();
that._handleEvent(evt); that._handleEvent(evt);
}, false); }, false);
this.container.addEventListener("touchend", function(evt) { this.container.addEventListener('touchend', function(evt) {
evt.preventDefault(); evt.preventDefault();
that.touchEnd = true; that.touchEnd = true;
that._handleEvent(evt); that._handleEvent(evt);
@@ -556,9 +565,9 @@ Kinetic.Stage.prototype = {
var obj = this.container; var obj = this.container;
var top = 0; var top = 0;
var left = 0; var left = 0;
while(obj && obj.tagName !== "BODY") { while(obj && obj.tagName !== 'BODY') {
top += obj.offsetTop; top += obj.offsetTop - obj.scrollTop;
left += obj.offsetLeft; left += obj.offsetLeft - obj.scrollLeft;
obj = obj.offsetParent; obj = obj.offsetParent;
} }
return { return {
@@ -596,7 +605,7 @@ Kinetic.Stage.prototype = {
if(go.drag.node) { if(go.drag.node) {
if(go.drag.moving) { if(go.drag.moving) {
go.drag.moving = false; go.drag.moving = false;
go.drag.node._handleEvents("ondragend", evt); go.drag.node._handleEvents('ondragend', evt);
} }
} }
go.drag.node = undefined; go.drag.node = undefined;
@@ -607,20 +616,20 @@ Kinetic.Stage.prototype = {
_prepareDrag: function() { _prepareDrag: function() {
var that = this; var that = this;
this.on("mousemove touchmove", function(evt) { this.on('mousemove touchmove', function(evt) {
var go = Kinetic.GlobalObject; var go = Kinetic.GlobalObject;
var node = go.drag.node; var node = go.drag.node;
if(node) { if(node) {
var pos = that.getUserPosition(); var pos = that.getUserPosition();
var ds = node.dragConstraint; var ds = node.dragConstraint;
var db = node.dragBounds; var db = node.dragBounds;
if(ds === "none" || ds === "horizontal") { if(ds === 'none' || ds === 'horizontal') {
var newX = pos.x - go.drag.offset.x; var newX = pos.x - go.drag.offset.x;
if((db.left === undefined || db.left < newX) && (db.right === undefined || db.right > newX)) { if((db.left === undefined || db.left < newX) && (db.right === undefined || db.right > newX)) {
node.x = newX; node.x = newX;
} }
} }
if(ds === "none" || ds === "vertical") { if(ds === 'none' || ds === 'vertical') {
var newY = pos.y - go.drag.offset.y; var newY = pos.y - go.drag.offset.y;
if((db.top === undefined || db.top < newY) && (db.bottom === undefined || db.bottom > newY)) { if((db.top === undefined || db.top < newY) && (db.bottom === undefined || db.bottom > newY)) {
node.y = newY; node.y = newY;
@@ -631,14 +640,14 @@ Kinetic.Stage.prototype = {
if(!go.drag.moving) { if(!go.drag.moving) {
go.drag.moving = true; go.drag.moving = true;
// execute dragstart events if defined // execute dragstart events if defined
go.drag.node._handleEvents("ondragstart", evt); go.drag.node._handleEvents('ondragstart', evt);
} }
// execute user defined ondragmove if defined // execute user defined ondragmove if defined
go.drag.node._handleEvents("ondragmove", evt); go.drag.node._handleEvents('ondragmove', evt);
} }
}, false); }, false);
this.on("mouseup touchend mouseout", function(evt) { this.on('mouseup touchend mouseout', function(evt) {
that._endDrag(evt); that._endDrag(evt);
}); });
} }

View File

@@ -13,16 +13,18 @@ Kinetic.Text = function(config) {
*/ */
if(config.textStroke !== undefined || config.textStrokeWidth !== undefined) { if(config.textStroke !== undefined || config.textStrokeWidth !== undefined) {
if(config.textStroke === undefined) { if(config.textStroke === undefined) {
config.textStroke = "black"; config.textStroke = 'black';
} else if(config.textStrokeWidth === undefined) { }
else
if(config.textStrokeWidth === undefined) {
config.textStrokeWidth = 2; config.textStrokeWidth = 2;
} }
} }
if(config.align === undefined) { if(config.align === undefined) {
config.align = "left"; config.align = 'left';
} }
if(config.verticalAlign === undefined) { if(config.verticalAlign === undefined) {
config.verticalAlign = "top"; config.verticalAlign = 'top';
} }
if(config.padding === undefined) { if(config.padding === undefined) {
config.padding = 0; config.padding = 0;
@@ -30,8 +32,8 @@ Kinetic.Text = function(config) {
config.drawFunc = function() { config.drawFunc = function() {
var context = this.getContext(); var context = this.getContext();
context.font = this.fontSize + "pt " + this.fontFamily; context.font = this.fontSize + 'pt ' + this.fontFamily;
context.textBaseline = "middle"; context.textBaseline = 'middle';
var metrics = context.measureText(this.text); var metrics = context.measureText(this.text);
var textHeight = this.fontSize; var textHeight = this.fontSize;
var textWidth = metrics.width; var textWidth = metrics.width;
@@ -40,19 +42,19 @@ Kinetic.Text = function(config) {
var y = 0; var y = 0;
switch (this.align) { switch (this.align) {
case "center": case 'center':
x = textWidth / -2 - p; x = textWidth / -2 - p;
break; break;
case "right": case 'right':
x = -1 * textWidth - p; x = -1 * textWidth - p;
break; break;
} }
switch (this.verticalAlign) { switch (this.verticalAlign) {
case "middle": case 'middle':
y = textHeight / -2 - p; y = textHeight / -2 - p;
break; break;
case "bottom": case 'bottom':
y = -1 * textHeight - p; y = -1 * textHeight - p;
break; break;
} }
@@ -76,8 +78,10 @@ Kinetic.Text = function(config) {
if(this.textStroke !== undefined || this.textStrokeWidth !== undefined) { if(this.textStroke !== undefined || this.textStrokeWidth !== undefined) {
// defaults // defaults
if(this.textStroke === undefined) { if(this.textStroke === undefined) {
this.textStroke = "black"; this.textStroke = 'black';
} else if(this.textStrokeWidth === undefined) { }
else
if(this.textStrokeWidth === undefined) {
this.textStrokeWidth = 2; this.textStrokeWidth = 2;
} }
context.lineWidth = this.textStrokeWidth; context.lineWidth = this.textStrokeWidth;
@@ -172,7 +176,7 @@ Kinetic.Text.prototype = {
}, },
/** /**
* set horizontal align of text * set horizontal align of text
* @param {String} align align can be "left", "center", or "right" * @param {String} align align can be 'left', 'center', or 'right'
*/ */
setAlign: function(align) { setAlign: function(align) {
this.align = align; this.align = align;

View File

@@ -4,14 +4,6 @@ body {
font-family: monospace font-family: monospace
} }
canvas {
border-right: 2px solid #9C9898;
}
div {
height: 200px;
}
p { p {
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
@@ -25,4 +17,11 @@ p {
.red { .red {
background-color: red; background-color: red;
color: white; color: white;
} }
.row > div {
display: inline-block;
background-color: #f0f0f0;
width: 578px;
height: 200px;
}

View File

@@ -1,712 +0,0 @@
function Test() {
this.testOnly = "";
this.counter = 0;
this.tests = {
"TRANSITION - transition position and rotation": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 100,
y: 100,
width: 100,
height: 50,
fill: "green",
stroke: "black",
strokeWidth: 4
});
layer.add(rect);
stage.add(layer);
rect.transitionTo({
x: 400,
y: 30,
rotation: Math.PI * 2,
duration: 1
});
},
"ANIMATION - run animation": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 200,
y: 100,
width: 100,
height: 50,
fill: "green",
stroke: "black",
strokeWidth: 4
});
layer.add(rect);
stage.add(layer);
var amplitude = 150;
var period = 1000;
// in ms
var centerX = stage.width / 2 - 100 / 2;
stage.onFrame(function(frame) {
rect.x = amplitude * Math.sin(frame.time * 2 * Math.PI / period) + centerX;
layer.draw();
});
stage.start();
},
"EVENTS - mousedown mouseup mouseover mouseout click dblclick / touchstart touchend dbltap": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true
});
circle.on('mousedown', function() {
log('mousedown');
});
circle.on('mouseup', function() {
log('mouseup');
});
circle.on('touchstart', function() {
log('touchstart');
});
circle.on('touchend', function() {
log('touchend');
});
circle.on('mouseover', function() {
log('mouseover');
});
circle.on('mouseout', function() {
log('mouseout');
});
circle.on('click', function() {
log('click');
});
circle.on('dblclick', function() {
log('dblclick');
});
circle.on('dbltap', function() {
log('dbltap');
});
layer.add(circle);
stage.add(layer);
},
"EVENTS - modify fill stroke and stroke width on hover with circle": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: 380,
y: stage.height / 2,
radius: 70,
strokeWidth: 4,
fill: "red",
stroke: "black"
});
circle.on("mouseover", function() {
this.setFill("yellow");
this.setStroke("purple");
this.setStrokeWidth(20);
layer.draw();
});
circle.on("mouseout", function() {
this.setFill("red");
this.setStroke("black");
this.setStrokeWidth(4);
layer.draw();
});
layer.add(circle);
stage.add(layer);
},
"EVENTS - modify fill stroke and stroke width on hover with circle with star": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var star = new Kinetic.Star({
x: 200,
y: 100,
points: 10,
innerRadius: 40,
outerRadius: 70,
fill: "green",
stroke: "blue",
strokeWidth: 5,
name: "foobar"
});
star.on("mouseover", function() {
this.setFill("yellow");
this.setStroke("purple");
this.setStrokeWidth(20);
layer.draw();
});
star.on("mouseout", function() {
this.setFill("green");
this.setStroke("blue");
this.setStrokeWidth(5);
layer.draw();
});
layer.add(star);
stage.add(layer);
},
"EVENTS - modify fill stroke and stroke width on hover with circle with image": function(containerId) {
var imageObj = new Image();
imageObj.onload = function() {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var darth = new Kinetic.Image({
x: 60,
y: 60,
image: imageObj
});
darth.on("mouseover", function() {
this.setFill("yellow");
this.setStroke("purple");
this.setStrokeWidth(20);
layer.draw();
});
darth.on("mouseout", function() {
this.setFill(undefined);
this.setStroke(undefined);
this.setStrokeWidth(0);
layer.draw();
});
layer.add(darth);
stage.add(layer);
};
imageObj.src = "darth-vader.jpg";
},
"EVENTS - drag events click": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: 380,
y: stage.height / 2,
radius: 70,
strokeWidth: 4,
fill: "red",
stroke: "black"
});
circle.draggable(true);
circle.on('dragstart', function() {
log('dragstart');
});
circle.on('dragmove', function() {
log('dragmove');
});
circle.on('dragend', function() {
log('dragend');
});
circle.on('click', function() {
log('click');
});
layer.add(circle);
stage.add(layer);
},
"EVENTS - isDragging": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: 380,
y: stage.height / 2,
radius: 70,
strokeWidth: 4,
fill: "red",
stroke: "black"
});
//log('not dragging yet before draggable, isDragging: ' + circle.isDragging());
test(circle.isDragging() === false, "isDragging() should be false");
circle.draggable(true);
//log('not dragging yet after draggable, isDragging: ' + circle.isDragging());
test(circle.isDragging() === false, "isDragging() should be false");
circle.on('dragstart', function() {
log('dragstart, isDragging: ' + this.isDragging());
test(circle.isDragging() === true, "isDragging() should be true");
});
circle.on('dragmove', function() {
log('dragmove, isDragging: ' + this.isDragging());
test(circle.isDragging() === true, "isDragging() should be true");
});
circle.on('dragend', function() {
log('dragend, isDragging: ' + this.isDragging());
test(circle.isDragging() === false, "isDragging() should be false");
});
layer.add(circle);
stage.add(layer);
},
"EVENTS - mousemove from shape to another shape in same layer": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var redCircle = new Kinetic.Circle({
x: 200,
y: stage.height / 2,
radius: 70,
strokeWidth: 4,
fill: "red",
stroke: "black"
});
redCircle.on("mouseover", function() {
log('mouseover red circle');
});
redCircle.on("mouseout", function() {
log('mouseout red circle');
});
var greenCircle = new Kinetic.Circle({
x: 280,
y: stage.height / 2,
radius: 70,
strokeWidth: 4,
fill: "green",
stroke: "black"
});
greenCircle.on("mouseover", function() {
log('mouseover green circle');
});
greenCircle.on("mouseout", function() {
log('mouseout green circle');
});
layer.add(redCircle);
layer.add(greenCircle);
stage.add(layer);
},
"EVENTS - mousemove from shape in one layer to shape in another layer": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var redLayer = new Kinetic.Layer();
var greenLayer = new Kinetic.Layer();
var redCircle = new Kinetic.Circle({
x: 200,
y: stage.height / 2,
radius: 70,
strokeWidth: 4,
fill: "red",
stroke: "black"
});
redCircle.on("mouseover", function() {
log('mouseover red circle');
});
redCircle.on("mouseout", function() {
log('mouseout red circle');
});
var greenCircle = new Kinetic.Circle({
x: 280,
y: stage.height / 2,
radius: 70,
strokeWidth: 4,
fill: "green",
stroke: "black"
});
greenCircle.on("mouseover", function() {
log('mouseover green circle');
});
greenCircle.on("mouseout", function() {
log('mouseout green circle');
});
redLayer.add(redCircle);
greenLayer.add(greenCircle);
stage.add(redLayer);
stage.add(greenLayer);
},
"EVENTS - event bubbling": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var group = new Kinetic.Group();
layer.on("mouseover", function() {
log('mouseover layer');
//console.log(this);
});
layer.on("mouseout", function() {
log('mouseout layer');
//console.log(this);
});
group.on("mouseover", function() {
log('mouseover group');
//console.log(this);
});
group.on("mouseout", function() {
log('mouseout group');
//console.log(this);
});
var redCircle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 80,
strokeWidth: 4,
fill: "red",
stroke: "black"
});
redCircle.on("mouseover", function() {
log('mouseover red circle');
//console.log(this);
});
redCircle.on("mouseout", function() {
log('mouseout red circle');
//console.log(this);
});
var greenCircle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 40,
strokeWidth: 4,
fill: "green",
stroke: "black"
});
greenCircle.on("mouseover", function() {
log('mouseover green circle');
//console.log(this);
});
greenCircle.on("mouseout", function() {
log('mouseout green circle');
//console.log(this);
});
group.add(redCircle);
group.add(greenCircle);
layer.add(group);
stage.add(layer);
},
"DRAG AND DROP - draggable true": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4
});
circle.draggable(true);
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - draggable true false": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4
});
circle.draggable(true);
layer.add(circle);
stage.add(layer);
circle.draggable(false);
},
"DRAG AND DROP - scale stage after add layer then drag and drop shape": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4
});
circle.draggable(true);
layer.add(circle);
stage.add(layer);
stage.setScale(0.5);
stage.draw();
},
"DRAG AND DROP - scale stage before add shape then drag and drop shape": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4
});
circle.draggable(true);
stage.setScale(0.5);
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - set stage scale to 1.5 after add layer then drag and drop shape": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4
});
circle.draggable(true);
layer.add(circle);
stage.add(layer);
stage.setScale(1.5);
stage.draw();
},
"DRAG AND DROP - set stage scale to 1.5 before add layer then drag and drop shape": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4
});
circle.draggable(true);
stage.setScale(1.5);
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - check that green events are ignored when dragging red circle": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle1 = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4
});
var circle2 = new Kinetic.Circle({
x: stage.width / 2 + 50,
y: stage.height / 2,
radius: 70,
fill: "green",
stroke: "black",
strokeWidth: 4
});
circle1.draggable(true);
circle2.on("mouseover", function() {
log("mouseover green circle");
});
layer.add(circle1);
layer.add(circle2);
stage.add(layer);
},
"DRAG AND DROP - drag and drop constrianed horiztonally": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragConstraint: "horizontal"
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop constrianed vertically": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragConstraint: "vertical"
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop with explicit no constraint": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragConstraint: "none"
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop with left bounds": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragBounds: {
left: 150
}
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop with right bounds": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragBounds: {
right: 400
}
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop with top bounds": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragBounds: {
top: 80
}
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop with bottom bounds": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragBounds: {
bottom: 120
}
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop with full rect bounds": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragBounds: {
top: 80,
bottom: 120,
left: 150,
right: 578 - 150
}
});
layer.add(circle);
stage.add(layer);
},
};
}

View File

@@ -1,10 +1,10 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<head> <head>
<link rel="stylesheet" type="text/css"href="base.css"> <link rel="stylesheet" type="text/css"href="../base.css">
<script src="../dist/kinetic-core.js"></script> <script src="../../dist/kinetic-core.js"></script>
<script src="functionalTests.js"></script> <script src="../js/Test.js"></script>
<script src="testMethods.js"></script> <script src="../js/functionalTests.js"></script>
<script> <script>
window.onload = function() { window.onload = function() {
var test = new Test(); var test = new Test();

View File

@@ -1,10 +1,10 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<head> <head>
<link rel="stylesheet" type="text/css"href="base.css"> <link rel="stylesheet" type="text/css"href="../base.css">
<script src="../dist/kinetic-core.js"></script> <script src="../../dist/kinetic-core.js"></script>
<script src="unitTests.js"></script> <script src="../js/Test.js"></script>
<script src="testMethods.js"></script> <script src="../js/unitTests.js"></script>
<script> <script>
window.onload = function() { window.onload = function() {
var test = new Test(); var test = new Test();

View File

@@ -1,34 +1,43 @@
function test(condition, message){ function test(condition, message) {
if (!condition) { if(!condition) {
throw new Error(message); throw new Error(message);
} }
} }
function log(message) {
function log(message){
console.log("LOG: " + message); console.log("LOG: " + message);
} }
/**
* Test constructor
*/
function Test() {
this.testOnly = "";
this.counter = 0;
}
/**
* Test methods
*/
Test.prototype = { Test.prototype = {
addTestContainer: function(key){ addTestContainer: function(key) {
var row = document.createElement('div'); var row = document.createElement('div');
var container = document.createElement('div'); var container = document.createElement('div');
var testMessage = document.createElement('p'); var testMessage = document.createElement('p');
container.id = key; container.id = key;
document.body.appendChild(testMessage); document.body.appendChild(testMessage);
row.appendChild(container); row.appendChild(container);
row.className = "row";
document.body.appendChild(row); document.body.appendChild(row);
return { return {
testMessage: testMessage testMessage: testMessage
}; };
}, },
run: function(){ run: function() {
var tests = this.tests; var tests = this.tests;
for (var key in tests) { for(var key in tests) {
if (!this.testOnly || (this.testOnly && this.testOnly == key)) { if(!this.testOnly || (this.testOnly && this.testOnly == key)) {
var obj = this.addTestContainer(key); var obj = this.addTestContainer(key);
this.counter++; this.counter++;
console.log(this.counter + ") " + key); console.log(this.counter + ") " + key);
@@ -38,4 +47,4 @@ Test.prototype = {
} }
} }
} }
}; };

756
tests/js/functionalTests.js Normal file
View File

@@ -0,0 +1,756 @@
Test.prototype.tests = {
"TRANSITION - transition position and rotation": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 100,
y: 100,
width: 100,
height: 50,
fill: "green",
stroke: "black",
strokeWidth: 4
});
layer.add(rect);
stage.add(layer);
rect.transitionTo({
x: 400,
y: 30,
rotation: Math.PI * 2,
duration: 1
});
},
"TRANSITION - transition position and rotation with two transitions": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 100,
y: 100,
width: 100,
height: 50,
fill: "green",
stroke: "black",
strokeWidth: 4
});
layer.add(rect);
stage.add(layer);
rect.transitionTo({
x: 400,
y: 30,
duration: 1
});
rect.transitionTo({
rotation: Math.PI * 2,
duration: 2
});
},
"ANIMATION - run animation": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 200,
y: 100,
width: 100,
height: 50,
fill: "green",
stroke: "black",
strokeWidth: 4
});
layer.add(rect);
stage.add(layer);
var amplitude = 150;
var period = 1000;
// in ms
var centerX = stage.width / 2 - 100 / 2;
stage.onFrame(function(frame) {
rect.x = amplitude * Math.sin(frame.time * 2 * Math.PI / period) + centerX;
layer.draw();
});
stage.start();
},
"EVENTS - mousedown mouseup mouseover mouseout click dblclick / touchstart touchend dbltap": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true
});
circle.on('mousedown', function() {
log('mousedown');
});
circle.on('mouseup', function() {
log('mouseup');
});
circle.on('touchstart', function() {
log('touchstart');
});
circle.on('touchend', function() {
log('touchend');
});
circle.on('mouseover', function() {
log('mouseover');
});
circle.on('mouseout', function() {
log('mouseout');
});
circle.on('click', function() {
log('click');
});
circle.on('dblclick', function() {
log('dblclick');
});
circle.on('dbltap', function() {
log('dbltap');
});
layer.add(circle);
stage.add(layer);
},
"EVENTS - modify fill stroke and stroke width on hover with circle": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: 380,
y: stage.height / 2,
radius: 70,
strokeWidth: 4,
fill: "red",
stroke: "black"
});
circle.on("mouseover", function() {
this.setFill("yellow");
this.setStroke("purple");
this.setStrokeWidth(20);
layer.draw();
});
circle.on("mouseout", function() {
this.setFill("red");
this.setStroke("black");
this.setStrokeWidth(4);
layer.draw();
});
layer.add(circle);
stage.add(layer);
},
"EVENTS - modify fill stroke and stroke width on hover with circle with star": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var star = new Kinetic.Star({
x: 200,
y: 100,
points: 10,
innerRadius: 40,
outerRadius: 70,
fill: "green",
stroke: "blue",
strokeWidth: 5,
name: "foobar"
});
star.on("mouseover", function() {
this.setFill("yellow");
this.setStroke("purple");
this.setStrokeWidth(20);
layer.draw();
});
star.on("mouseout", function() {
this.setFill("green");
this.setStroke("blue");
this.setStrokeWidth(5);
layer.draw();
});
layer.add(star);
stage.add(layer);
},
"EVENTS - modify fill stroke and stroke width on hover with circle with image": function(containerId) {
var imageObj = new Image();
imageObj.onload = function() {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var darth = new Kinetic.Image({
x: 60,
y: 60,
image: imageObj
});
darth.on("mouseover", function() {
this.setFill("yellow");
this.setStroke("purple");
this.setStrokeWidth(20);
layer.draw();
});
darth.on("mouseout", function() {
this.setFill(undefined);
this.setStroke(undefined);
this.setStrokeWidth(0);
layer.draw();
});
layer.add(darth);
stage.add(layer);
};
imageObj.src = "../darth-vader.jpg";
},
"EVENTS - drag events click": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: 380,
y: stage.height / 2,
radius: 70,
strokeWidth: 4,
fill: "red",
stroke: "black"
});
circle.draggable(true);
circle.on('dragstart', function() {
log('dragstart');
});
circle.on('dragmove', function() {
log('dragmove');
});
circle.on('dragend', function() {
log('dragend');
});
circle.on('click', function() {
log('click');
});
layer.add(circle);
stage.add(layer);
},
"EVENTS - isDragging": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: 380,
y: stage.height / 2,
radius: 70,
strokeWidth: 4,
fill: "red",
stroke: "black"
});
//log('not dragging yet before draggable, isDragging: ' + circle.isDragging());
test(circle.isDragging() === false, "isDragging() should be false");
circle.draggable(true);
//log('not dragging yet after draggable, isDragging: ' + circle.isDragging());
test(circle.isDragging() === false, "isDragging() should be false");
circle.on('dragstart', function() {
log('dragstart, isDragging: ' + this.isDragging());
test(circle.isDragging() === true, "isDragging() should be true");
});
circle.on('dragmove', function() {
log('dragmove, isDragging: ' + this.isDragging());
test(circle.isDragging() === true, "isDragging() should be true");
});
circle.on('dragend', function() {
log('dragend, isDragging: ' + this.isDragging());
test(circle.isDragging() === false, "isDragging() should be false");
});
layer.add(circle);
stage.add(layer);
},
"EVENTS - mousemove from shape to another shape in same layer": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var redCircle = new Kinetic.Circle({
x: 200,
y: stage.height / 2,
radius: 70,
strokeWidth: 4,
fill: "red",
stroke: "black"
});
redCircle.on("mouseover", function() {
log('mouseover red circle');
});
redCircle.on("mouseout", function() {
log('mouseout red circle');
});
var greenCircle = new Kinetic.Circle({
x: 280,
y: stage.height / 2,
radius: 70,
strokeWidth: 4,
fill: "green",
stroke: "black"
});
greenCircle.on("mouseover", function() {
log('mouseover green circle');
});
greenCircle.on("mouseout", function() {
log('mouseout green circle');
});
layer.add(redCircle);
layer.add(greenCircle);
stage.add(layer);
},
"EVENTS - mousemove from shape in one layer to shape in another layer": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var redLayer = new Kinetic.Layer();
var greenLayer = new Kinetic.Layer();
var redCircle = new Kinetic.Circle({
x: 200,
y: stage.height / 2,
radius: 70,
strokeWidth: 4,
fill: "red",
stroke: "black"
});
redCircle.on("mouseover", function() {
log('mouseover red circle');
});
redCircle.on("mouseout", function() {
log('mouseout red circle');
});
var greenCircle = new Kinetic.Circle({
x: 280,
y: stage.height / 2,
radius: 70,
strokeWidth: 4,
fill: "green",
stroke: "black"
});
greenCircle.on("mouseover", function() {
log('mouseover green circle');
});
greenCircle.on("mouseout", function() {
log('mouseout green circle');
});
redLayer.add(redCircle);
greenLayer.add(greenCircle);
stage.add(redLayer);
stage.add(greenLayer);
},
"EVENTS - event bubbling": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var group = new Kinetic.Group();
layer.on("mouseover", function() {
log('mouseover layer');
//console.log(this);
});
layer.on("mouseout", function() {
log('mouseout layer');
//console.log(this);
});
group.on("mouseover", function() {
log('mouseover group');
//console.log(this);
});
group.on("mouseout", function() {
log('mouseout group');
//console.log(this);
});
var redCircle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 80,
strokeWidth: 4,
fill: "red",
stroke: "black"
});
redCircle.on("mouseover", function() {
log('mouseover red circle');
//console.log(this);
});
redCircle.on("mouseout", function() {
log('mouseout red circle');
//console.log(this);
});
var greenCircle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 40,
strokeWidth: 4,
fill: "green",
stroke: "black"
});
greenCircle.on("mouseover", function() {
log('mouseover green circle');
//console.log(this);
});
greenCircle.on("mouseout", function() {
log('mouseout green circle');
//console.log(this);
});
group.add(redCircle);
group.add(greenCircle);
layer.add(group);
stage.add(layer);
},
"DRAG AND DROP - draggable true": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4
});
circle.draggable(true);
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - draggable true false": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4
});
circle.draggable(true);
layer.add(circle);
stage.add(layer);
circle.draggable(false);
},
"DRAG AND DROP - scale stage after add layer then drag and drop shape": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4
});
circle.draggable(true);
layer.add(circle);
stage.add(layer);
stage.setScale(0.5);
stage.draw();
},
"DRAG AND DROP - scale stage before add shape then drag and drop shape": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4
});
circle.draggable(true);
stage.setScale(0.5);
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - set stage scale to 1.5 after add layer then drag and drop shape": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4
});
circle.draggable(true);
layer.add(circle);
stage.add(layer);
stage.setScale(1.5);
stage.draw();
},
"DRAG AND DROP - set stage scale to 1.5 before add layer then drag and drop shape": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4
});
circle.draggable(true);
stage.setScale(1.5);
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - check that green events are ignored when dragging red circle": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle1 = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4
});
var circle2 = new Kinetic.Circle({
x: stage.width / 2 + 50,
y: stage.height / 2,
radius: 70,
fill: "green",
stroke: "black",
strokeWidth: 4
});
circle1.draggable(true);
circle2.on("mouseover", function() {
log("mouseover green circle");
});
layer.add(circle1);
layer.add(circle2);
stage.add(layer);
},
"DRAG AND DROP - drag and drop constrianed horiztonally": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragConstraint: "horizontal"
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop constrianed vertically": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragConstraint: "vertical"
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop with explicit no constraint": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragConstraint: "none"
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop with left bounds": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragBounds: {
left: 150
}
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop with right bounds": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragBounds: {
right: 400
}
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop with top bounds": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragBounds: {
top: 80
}
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop with bottom bounds": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragBounds: {
bottom: 120
}
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop with full rect bounds": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 200);
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: stage.height / 2,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true,
dragBounds: {
top: 80,
bottom: 120,
left: 150,
right: 578 - 150
}
});
layer.add(circle);
stage.add(layer);
},
"DRAG AND DROP - drag and drop shape inside scrollable div": function(containerId) {
var stage = new Kinetic.Stage(containerId, 578, 400);
// make container scrollable
var container = stage.getContainer();
container.style.overflow = "auto";
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.width / 2,
y: 100,
radius: 50,
fill: "blue",
stroke: "black",
strokeWidth: 4,
draggable: true
});
layer.add(circle);
stage.add(layer);
},
};

1227
tests/js/unitTests.js Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff