social_cheesecake 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. data/app/assets/javascripts/kinetic.js +812 -432
  2. data/app/assets/javascripts/socialcheesecake/_header.js +1 -1
  3. data/app/assets/javascripts/socialcheesecake/actor.js +57 -32
  4. data/app/assets/javascripts/socialcheesecake/cheesecake.js +257 -280
  5. data/app/assets/javascripts/socialcheesecake/grid.js +168 -56
  6. data/app/assets/javascripts/socialcheesecake/sector.js +124 -70
  7. data/app/assets/javascripts/socialcheesecake/text.js +9 -4
  8. data/lib/social_cheesecake/version.rb +1 -1
  9. data/test/dummy/app/assets/images/images/ui-bg_diagonals-medium_20_d34d17_40x40.png +0 -0
  10. data/test/dummy/app/assets/images/images/ui-bg_flat_30_cccccc_40x100.png +0 -0
  11. data/test/dummy/app/assets/images/images/ui-bg_flat_50_5c5c5c_40x100.png +0 -0
  12. data/test/dummy/app/assets/images/images/ui-bg_gloss-wave_45_817865_500x100.png +0 -0
  13. data/test/dummy/app/assets/images/images/ui-bg_gloss-wave_60_fece2f_500x100.png +0 -0
  14. data/test/dummy/app/assets/images/images/ui-bg_gloss-wave_70_ffdd57_500x100.png +0 -0
  15. data/test/dummy/app/assets/images/images/ui-bg_gloss-wave_90_fff9e5_500x100.png +0 -0
  16. data/test/dummy/app/assets/images/images/ui-bg_highlight-soft_100_feeebd_1x100.png +0 -0
  17. data/test/dummy/app/assets/images/images/ui-bg_inset-soft_30_ffffff_1x100.png +0 -0
  18. data/test/dummy/app/assets/images/images/ui-icons_3d3d3d_256x240.png +0 -0
  19. data/test/dummy/app/assets/images/images/ui-icons_bd7b00_256x240.png +0 -0
  20. data/test/dummy/app/assets/images/images/ui-icons_d19405_256x240.png +0 -0
  21. data/test/dummy/app/assets/images/images/ui-icons_eb990f_256x240.png +0 -0
  22. data/test/dummy/app/assets/images/images/ui-icons_ed9f26_256x240.png +0 -0
  23. data/test/dummy/app/assets/images/images/ui-icons_fadc7a_256x240.png +0 -0
  24. data/test/dummy/app/assets/images/images/ui-icons_ffe180_256x240.png +0 -0
  25. data/test/dummy/app/assets/images/socialcheesecake_background.png +0 -0
  26. data/test/dummy/app/assets/images/soialcheesecake_icon.png +0 -0
  27. data/test/dummy/app/assets/images/soialcheesecake_icon_back.png +0 -0
  28. data/test/dummy/app/assets/images/under-construction.png +0 -0
  29. data/test/dummy/app/assets/javascripts/application.js +1 -0
  30. data/test/dummy/app/assets/javascripts/main.js +352 -0
  31. data/test/dummy/app/assets/stylesheets/jquery-ui-1.8.17.custom.css +565 -0
  32. data/test/dummy/app/assets/stylesheets/style.css +251 -0
  33. data/test/dummy/public/index.html +149 -119
  34. data/test/dummy/vendor/assets/javascripts/jquery-ui.js +356 -0
  35. metadata +29 -4
@@ -1,11 +1,11 @@
1
1
  /**
2
- * KineticJS JavaScript Library v3.4.0
2
+ * KineticJS JavaScript Library v3.6.2
3
3
  * http://www.kineticjs.com/
4
- * Copyright 2011, Eric Rowell
4
+ * Copyright 2012, Eric Rowell
5
5
  * Licensed under the MIT or GPL Version 2 licenses.
6
- * Date: Dec 31 2011
6
+ * Date: Jan 21 2012
7
7
  *
8
- * Copyright (C) 2011 by Eric Rowell
8
+ * Copyright (C) 2012 by Eric Rowell
9
9
  *
10
10
  * Permission is hereby granted, free of charge, to any person obtaining a copy
11
11
  * of this software and associated documentation files (the "Software"), to deal
@@ -27,39 +27,58 @@
27
27
  */
28
28
  var Kinetic = {};
29
29
 
30
- /****************************************
31
- * Layer
30
+ /*
31
+ * I know, globals suck. But since Shape objects
32
+ * and Layer objects can exist before adding them to
33
+ * the stage, a global shape id counter is necessary
32
34
  */
33
- Kinetic.Layer = function(stage, isInvisible){
35
+ Kinetic.GLOBALS = {
36
+ shapeIdCounter: 0
37
+ };
38
+
39
+ ///////////////////////////////////////////////////////////////////////
40
+ //// Link
41
+ ///////////////////////////////////////////////////////////////////////
42
+ ///////////////////////////////////////////////////////////////////////
43
+
44
+ Kinetic.Link = function(shape){
45
+ this.shape = shape;
46
+ shape.link = this;
47
+ this.id = shape.id;
48
+ this.index = undefined;
49
+
50
+ // thes params are string ids
51
+ this.nextId = undefined;
52
+ this.prevId = undefined;
53
+ };
54
+
55
+ ///////////////////////////////////////////////////////////////////////
56
+ //// Layer
57
+ ///////////////////////////////////////////////////////////////////////
58
+ ///////////////////////////////////////////////////////////////////////
59
+
60
+ Kinetic.Layer = function(name){
61
+ this.name = name;
62
+ this.shapeIndexCounter = 0;
63
+ this.isListening = true;
64
+ this.shapeNames = {};
34
65
  this.canvas = document.createElement('canvas');
35
66
  this.context = this.canvas.getContext('2d');
36
- this.canvas.width = stage.width;
37
- this.canvas.height = stage.height;
38
67
  this.canvas.style.position = 'absolute';
39
- this.shapes = [];
40
68
 
41
- if (isInvisible) {
42
- var that = this;
43
- this.context.stroke = function(){
44
- };
45
- this.context.fill = function(){
46
- };
47
- this.context.fillRect = function(x, y, width, height){
48
- that.context.rect(x, y, width, height);
49
- };
50
- this.context.strokeRect = function(x, y, width, height){
51
- that.context.rect(x, y, width, height);
52
- };
53
- this.context.drawImage = function(){
54
- };
55
- this.context.fillText = function(){
56
- };
57
- this.context.strokeText = function(){
58
- };
59
- }
69
+ //links is an array of links which point to event links
70
+ this.links = [];
71
+ this.linkHash = {};
60
72
 
61
- stage.container.appendChild(this.canvas);
62
- }
73
+ this.headId = undefined;
74
+ this.tailId = undefined;
75
+ };
76
+ /*
77
+ * listen or don't listen to events
78
+ */
79
+ Kinetic.Layer.prototype.listen = function(isListening){
80
+ this.isListening = isListening;
81
+ };
63
82
  /*
64
83
  * clear layer
65
84
  */
@@ -67,7 +86,7 @@ Kinetic.Layer.prototype.clear = function(){
67
86
  var context = this.getContext();
68
87
  var canvas = this.getCanvas();
69
88
  context.clearRect(0, 0, canvas.width, canvas.height);
70
- }
89
+ };
71
90
  /*
72
91
  * get layer canvas
73
92
  */
@@ -81,32 +100,142 @@ Kinetic.Layer.prototype.getContext = function(){
81
100
  return this.context;
82
101
  }
83
102
  /*
84
- * get layer shapes
103
+ * get shapes as an array
85
104
  */
86
105
  Kinetic.Layer.prototype.getShapes = function(){
87
- return this.shapes;
88
- }
106
+ var shapes = [];
107
+ for (var n = 0; n < this.links.length; n++) {
108
+ shapes.push(this.links[n].shape);
109
+ }
110
+ return shapes;
111
+ };
89
112
  /*
90
113
  * draw all shapes in layer
91
114
  */
92
115
  Kinetic.Layer.prototype.draw = function(){
93
116
  this.clear();
94
- var context = this.getContext();
117
+ var links = this.links;
118
+ for (var n = 0; n < links.length; n++) {
119
+ var shape = links[n].shape;
120
+ shape.draw(shape.layer);
121
+ }
122
+ };
123
+ /*
124
+ * add link to data structure
125
+ */
126
+ Kinetic.Layer.prototype.addLink = function(link){
127
+ var shape = link.shape;
128
+ shape.layer = this;
129
+ // add link to array
130
+ this.links.push(link);
131
+ // add link to hash
132
+ this.linkHash[link.id] = link;
133
+ link.index = this.links.length - 1;
95
134
 
96
- for (var n = 0; n < this.getShapes().length; n++) {
97
- this.getShapes()[n].draw(this);
135
+ if (shape.isListening) {
136
+ // if tail doesnt exist, add tail and head
137
+ if (this.tailId === undefined) {
138
+ this.tailId = link.id;
139
+ this.headId = link.id;
140
+ }
141
+ // if tail does exist, this means there's at least one link
142
+ else {
143
+ var tail = this.linkHash[this.tailId];
144
+ tail.nextId = link.id;
145
+ link.prevId = tail.id;
146
+ this.tailId = link.id;
147
+ }
148
+ }
149
+ };
150
+ /*
151
+ * add shape
152
+ */
153
+ Kinetic.Layer.prototype.add = function(shape){
154
+ if (shape.name) {
155
+ this.shapeNames[shape.name] = shape;
156
+ }
157
+ shape.id = Kinetic.GLOBALS.shapeIdCounter++;
158
+ var link = new Kinetic.Link(shape);
159
+ this.addLink(link);
160
+ };
161
+ /*
162
+ * get shape by name
163
+ */
164
+ Kinetic.Layer.prototype.getShape = function(name){
165
+ return this.shapeNames[name];
166
+ };
167
+ /*
168
+ * remove a shape from layer (link + shape deconstructor)
169
+ */
170
+ Kinetic.Layer.prototype.remove = function(shape){
171
+ var link = shape.link;
172
+ this.removeLink(link);
173
+ this.shape = null;
174
+ this.link = null;
175
+ };
176
+ /*
177
+ * remove link from layer. this does not deconstruct
178
+ * the link or the shape
179
+ */
180
+ Kinetic.Layer.prototype.removeLink = function(link){
181
+ link.shape.layer = undefined;
182
+ this.unlink(link);
183
+ this.links.splice(link.index, 1);
184
+ this.linkHash[link.id] = undefined;
185
+ this.setLinkIndices();
186
+ };
187
+
188
+ /*
189
+ * unlink link. This is different from removeLink because it
190
+ * keeps the link in the layer data structure
191
+ */
192
+ Kinetic.Layer.prototype.unlink = function(link){
193
+ // set head if needed
194
+ if (link.id === this.headId) {
195
+ this.headId = link.nextId;
196
+ }
197
+ // set tail if needed
198
+ if (link.id === this.tailId) {
199
+ this.tailId = link.prevId;
98
200
  }
201
+ // link prev to next
202
+ if (link.prevId !== undefined) {
203
+ this.linkHash[link.prevId].nextId = link.nextId;
204
+ }
205
+ if (link.nextId !== undefined) {
206
+ this.linkHash[link.nextId].prevId = link.prevId;
207
+ }
208
+ // clear pointers
209
+ link.prevId = undefined;
210
+ link.nextId = undefined;
99
211
  };
100
- /****************************************
101
- * Stage
212
+ /*
213
+ * set link indices
102
214
  */
215
+ Kinetic.Layer.prototype.setLinkIndices = function(){
216
+ for (var n = 0; n < this.links.length; n++) {
217
+ this.links[n].index = n;
218
+ }
219
+ };
220
+ ///////////////////////////////////////////////////////////////////////
221
+ //// Stage
222
+ ///////////////////////////////////////////////////////////////////////
223
+ ///////////////////////////////////////////////////////////////////////
224
+
103
225
  Kinetic.Stage = function(containerId, width, height){
104
226
  this.container = document.getElementById(containerId);
105
227
  this.width = width;
106
228
  this.height = height;
107
- this.zIndexCounter = 9999;
108
- this.idCounter = 0;
229
+ this.scale = {
230
+ x: 1,
231
+ y: 1
232
+ };
233
+ this.layerIdCounter = 0;
109
234
  this.dblClickWindow = 400;
235
+ this.targetShape = {};
236
+ this.clickStart = false;
237
+ this.layerNames = {};
238
+
110
239
  // desktop flags
111
240
  this.mousePos = null;
112
241
  this.mouseDown = false;
@@ -117,39 +246,119 @@ Kinetic.Stage = function(containerId, width, height){
117
246
  this.touchStart = false;
118
247
  this.touchEnd = false;
119
248
 
120
- // create layers
121
- this.bufferLayer = new Kinetic.Layer(this);
122
- this.backstageLayer = new Kinetic.Layer(this, true);
123
- this.stageLayer = new Kinetic.Layer(this);
124
- this.propsLayer = new Kinetic.Layer(this);
125
- this.actorsLayer = new Kinetic.Layer(this);
249
+ // user defined layers
250
+ this.layers = [];
251
+
252
+ /*
253
+ * Layer roles
254
+ *
255
+ * buffer - canvas compositing
256
+ * backstage - path detection
257
+ */
258
+ var that = this;
259
+ this.bufferLayer = new Kinetic.Layer();
260
+ this.backstageLayer = new Kinetic.Layer();
261
+
262
+ // customize back stage context
263
+ var backstageLayer = this.backstageLayer;
264
+ backstageLayer.context.stroke = function(){
265
+ };
266
+ backstageLayer.context.fill = function(){
267
+ };
268
+ backstageLayer.context.fillRect = function(x, y, width, height){
269
+ backstageLayer.context.rect(x, y, width, height);
270
+ };
271
+ backstageLayer.context.strokeRect = function(x, y, width, height){
272
+ that.context.rect(x, y, width, height);
273
+ };
274
+ backstageLayer.context.drawImage = function(){
275
+ };
276
+ backstageLayer.context.fillText = function(){
277
+ };
278
+ backstageLayer.context.strokeText = function(){
279
+ };
126
280
 
127
281
  this.bufferLayer.getCanvas().style.display = 'none';
128
282
  this.backstageLayer.getCanvas().style.display = 'none';
283
+
284
+ // add buffer layer
285
+ this.bufferLayer.stage = this;
286
+ this.bufferLayer.canvas.width = this.width;
287
+ this.bufferLayer.canvas.height = this.height;
288
+ this.container.appendChild(this.bufferLayer.canvas);
289
+
290
+ // add backstage layer
291
+ this.backstageLayer.stage = this;
292
+ this.backstageLayer.canvas.width = this.width;
293
+ this.backstageLayer.canvas.height = this.height;
294
+ this.container.appendChild(this.backstageLayer.canvas);
295
+
129
296
  this.listen();
130
297
 
131
298
  this.addEventListener("mouseout", function(evt){
132
299
  that.shapeDragging = undefined;
133
300
  }, false);
134
301
 
135
- // prepare stage for drag and drop
136
- var that = this;
137
- this.addEventListener("mousemove", function(evt){
138
- if (that.shapeDragging) {
139
- var mousePos = that.getMousePos();
140
- that.shapeDragging.x = mousePos.x - that.shapeDragging.offset.x;
141
- that.shapeDragging.y = mousePos.y - that.shapeDragging.offset.y;
142
- that.drawActors();
143
- }
144
- }, false);
145
- this.addEventListener("mouseup", function(evt){
302
+ /*
303
+ * prepare drag and drop
304
+ */
305
+ var types = [{
306
+ end: "mouseup",
307
+ move: "mousemove"
308
+ }, {
309
+ end: "touchend",
310
+ move: "touchmove"
311
+ }];
312
+
313
+ for (var n = 0; n < types.length; n++) {
314
+ var pubType = types[n];
315
+ (function(){
316
+ var type = pubType;
317
+ that.on(type.move, function(evt){
318
+ if (that.shapeDragging) {
319
+ var pos = type.move == "mousemove" ? that.getMousePosition() : that.getTouchPosition();
320
+ if (that.shapeDragging.drag.x) {
321
+ that.shapeDragging.x = pos.x - that.shapeDragging.offset.x;
322
+ }
323
+ if (that.shapeDragging.drag.y) {
324
+ that.shapeDragging.y = pos.y - that.shapeDragging.offset.y;
325
+ }
326
+ that.shapeDragging.layer.draw();
327
+
328
+ // execute user defined ondragend if defined
329
+ var dragmove = that.shapeDragging.eventListeners.ondragmove;
330
+ if (dragmove) {
331
+ var events = dragmove;
332
+ for (var i = 0; i < events.length; i++) {
333
+ events[i].handler.apply(that.shapeDragging, [evt]);
334
+ }
335
+ }
336
+ }
337
+ }, false);
338
+ that.on(type.end, function(evt){
339
+ // execute user defined ondragend if defined
340
+ if (that.shapeDragging) {
341
+ var dragend = that.shapeDragging.eventListeners.ondragend;
342
+ if (dragend) {
343
+ var events = dragend;
344
+ for (var i = 0; i < events.length; i++) {
345
+ events[i].handler.apply(that.shapeDragging, [evt]);
346
+ }
347
+ }
348
+ }
349
+ that.shapeDragging = undefined;
350
+ });
351
+ })();
352
+ }
353
+
354
+ this.on("touchend", function(evt){
146
355
  // execute user defined ondragend if defined
147
-
148
356
  if (that.shapeDragging) {
149
357
  var dragend = that.shapeDragging.eventListeners.ondragend;
150
358
  if (dragend) {
151
- for (var i = 0; i < dragend.length; i++) {
152
- dragend[i].func(evt);
359
+ var events = dragend;
360
+ for (var i = 0; i < events.length; i++) {
361
+ events[i].handler.apply(that.shapeDragging, [evt]);
153
362
  }
154
363
  }
155
364
  }
@@ -157,60 +366,41 @@ Kinetic.Stage = function(containerId, width, height){
157
366
  });
158
367
  };
159
368
  /*
160
- * get buffer layer
161
- */
162
- Kinetic.Stage.prototype.getBufferLayer = function(){
163
- return this.bufferLayer;
164
- };
165
- /*
166
- * get backstage layer
369
+ * set stage size
167
370
  */
168
- Kinetic.Stage.prototype.getBackstageLayer = function(){
169
- return this.backstageLayer;
170
- };
171
- /*
172
- * get stage layer
173
- */
174
- Kinetic.Stage.prototype.getStageLayer = function(){
175
- return this.stageLayer;
176
- };
177
- /*
178
- * get props layer
179
- */
180
- Kinetic.Stage.prototype.getPropsLayer = function(){
181
- return this.propsLayer;
182
- };
183
- /*
184
- * get actors layer
185
- */
186
- Kinetic.Stage.prototype.getActorsLayer = function(){
187
- return this.actorsLayer;
188
- };
189
- /*
190
- * clear stage
191
- */
192
- Kinetic.Stage.prototype.clear = function(){
193
- this.stageLayer.clear();
371
+ Kinetic.Stage.prototype.setSize = function(width, height){
372
+ var layers = this.layers;
373
+ for (n = 0; n < layers.length; n++) {
374
+ var layer = layers[n];
375
+ layer.getCanvas().width = width;
376
+ layer.getCanvas().height = height;
377
+ layer.draw();
378
+ }
379
+
380
+ // set stage dimensions
381
+ this.width = width;
382
+ this.height = height;
194
383
  };
195
384
  /*
196
- * clear all canvases
385
+ * scale stage
197
386
  */
198
- Kinetic.Stage.prototype.clearAll = function(){
199
- this.backstageLayer.clear();
200
- this.stageLayer.clear();
201
- this.propsLayer.clear();
202
- this.actorsLayer.clear();
387
+ Kinetic.Stage.prototype.setScale = function(scaleX, scaleY){
388
+ if (scaleY) {
389
+ this.scale.x = scaleX;
390
+ this.scale.y = scaleY;
391
+ }
392
+ else {
393
+ this.scale.x = scaleX;
394
+ this.scale.y = scaleX;
395
+ }
203
396
  };
204
397
  /*
205
398
  * Composite toDataURL
206
399
  */
207
400
  Kinetic.Stage.prototype.toDataURL = function(callback){
208
- var bufferLayer = this.getBufferLayer();
401
+ var bufferLayer = this.bufferLayer;
209
402
  var bufferContext = bufferLayer.getContext();
210
- var stageLayer = this.getStageLayer();
211
- var propsLayer = this.getPropsLayer();
212
- var actorsLayer = this.getActorsLayer();
213
- var layers = [stageLayer, propsLayer, actorsLayer];
403
+ var layers = this.layers;
214
404
 
215
405
  function addLayer(n){
216
406
  var dataURL = layers[n].getCanvas().toDataURL();
@@ -228,92 +418,59 @@ Kinetic.Stage.prototype.toDataURL = function(callback){
228
418
  imageObj.src = dataURL;
229
419
  }
230
420
 
421
+
231
422
  bufferLayer.clear();
232
423
  addLayer(0);
233
424
  };
425
+
234
426
  /*
235
- * draw actors layer
236
- */
237
- Kinetic.Stage.prototype.drawActors = function(){
238
- this.getActorsLayer().draw();
239
- };
240
- /*
241
- * draw props layer
242
- */
243
- Kinetic.Stage.prototype.drawProps = function(){
244
- this.getPropsLayer().draw();
245
- };
246
- /*
247
- * draw actors and props layer. This method should be used
248
- * in combination with makeActor() or makeProp()
427
+ * draw shapes
249
428
  */
250
429
  Kinetic.Stage.prototype.draw = function(){
251
- this.drawProps();
252
- this.drawActors();
253
- };
254
- /*
255
- * remove a shape from the stage
256
- */
257
- Kinetic.Stage.prototype.remove = function(shape){
258
- // remove from shapes array
259
- var shapes = this.getShapes();
260
- for (var n = 0; n < shapes.length; n++) {
261
- var id = shapes[n].id;
262
- if (id == shape.id) {
263
- shape.getLayer().getShapes().splice(n, 1);
264
- }
430
+ var layers = this.layers;
431
+ for (var n = 0; n < layers.length; n++) {
432
+ layers[n].draw();
265
433
  }
266
434
  };
267
435
  /*
268
- * remove all shapes from the stage
269
- */
270
- Kinetic.Stage.prototype.removeAll = function(){
271
- // remove all shapes
272
- this.getPropsLayer().shapes = [];
273
- this.getActorsLayer().shapes = [];
274
- };
275
- /*
276
- * get stage canvas
277
- */
278
- Kinetic.Stage.prototype.getCanvas = function(){
279
- return this.stageLayer.getCanvas();
280
- };
281
- /*
282
- * get stage context
436
+ * remove a layer from the stage
283
437
  */
284
- Kinetic.Stage.prototype.getContext = function(){
285
- return this.stageLayer.getContext();
438
+ Kinetic.Stage.prototype.remove = function(shape){
439
+ // TODO
286
440
  };
287
441
  /*
288
442
  * short-hand add event listener to stage (which is essentially
289
443
  * the container DOM)
290
444
  */
291
- Kinetic.Stage.prototype.on = function(type, func){
292
- this.container.addEventListener(type, func);
445
+ Kinetic.Stage.prototype.on = function(type, handler){
446
+ this.container.addEventListener(type, handler);
293
447
  };
294
448
  /*
295
449
  * long-hand add event listener to stage (which is essentially
296
450
  * the container DOM)
297
451
  */
298
- Kinetic.Stage.prototype.addEventListener = function(type, func){
299
- this.on(type, func);
452
+ Kinetic.Stage.prototype.addEventListener = function(type, handler){
453
+ this.on(type, handler);
300
454
  };
301
- /*
302
- * add shape to stage
455
+ /*
456
+ * add layer to stage
303
457
  */
304
- Kinetic.Stage.prototype.add = function(shape){
305
- shape.stage = this;
306
- if (shape.isProp) {
307
- shape.layer = this.propsLayer;
458
+ Kinetic.Stage.prototype.add = function(layer){
459
+ if (layer.name) {
460
+ this.layerNames[layer.name] = layer;
308
461
  }
309
- else {
310
- shape.layer = this.actorsLayer;
311
- }
312
-
313
- shape.getLayer().shapes.push(shape);
314
-
315
- shape.id = this.idCounter++;
316
- shape.draw(shape.layer);
462
+ layer.canvas.width = this.width;
463
+ layer.canvas.height = this.height;
464
+ layer.stage = this;
465
+ this.layers.push(layer);
466
+ layer.draw();
467
+ this.container.appendChild(layer.canvas);
468
+ };
469
+ /*
470
+ * get layer by name
471
+ */
472
+ Kinetic.Stage.prototype.getLayer = function(name){
473
+ return this.layerNames[name];
317
474
  };
318
475
  /*
319
476
  * handle incoming event
@@ -332,120 +489,180 @@ Kinetic.Stage.prototype.handleEvent = function(evt){
332
489
 
333
490
  backstageLayer.clear();
334
491
 
335
- for (var n = this.getShapes().length - 1; n >= 0; n--) {
336
- var pubShape = this.getShapes()[n];
337
- (function(){
338
- var shape = pubShape;
339
- shape.draw(backstageLayer);
340
- var pos = that.touchPos || that.mousePos;
341
- var el = shape.eventListeners;
492
+ /*
493
+ * loop through layers. If at any point an event
494
+ * is triggered, n is set to -1 which will break out of the
495
+ * three nested loops
496
+ */
497
+ for (var n = this.layers.length - 1; n >= 0; n--) {
498
+ var layer = this.layers[n];
499
+ if (n >= 0 && layer.isListening) {
500
+ var linkId = layer.tailId;
342
501
 
343
- if (shape.visible && pos !== null && backstageLayerContext.isPointInPath(pos.x, pos.y)) {
344
- // handle onmousedown
345
- if (that.mouseDown) {
346
- that.mouseDown = false;
347
- shape.clickStart = true;
502
+ // propapgate backwards through event links
503
+ while (n >= 0 && linkId !== undefined) {
504
+ //for (var n = this.getEventShapes().length - 1; n >= 0; n--) {
505
+ //var pubShape = this.getEventShapes()[n];
506
+ var link = layer.linkHash[linkId];
507
+ var pubShape = link.shape;
508
+ (function(){
509
+ var shape = pubShape;
510
+ shape.draw(backstageLayer);
511
+ var pos = that.getUserPosition();
512
+ var el = shape.eventListeners;
348
513
 
349
- if (el.onmousedown) {
350
- for (var i = 0; i < el.onmousedown.length; i++) {
351
- el.onmousedown[i].func(evt);
514
+ if (shape.visible && pos !== null && backstageLayerContext.isPointInPath(pos.x, pos.y)) {
515
+ // handle onmousedown
516
+ if (that.mouseDown) {
517
+ that.mouseDown = false;
518
+ that.clickStart = true;
519
+
520
+ if (el.onmousedown) {
521
+ var events = el.onmousedown;
522
+ for (var i = 0; i < events.length; i++) {
523
+ events[i].handler.apply(shape, [evt]);
524
+ }
525
+ }
526
+ n = -1;
352
527
  }
353
- }
354
- n = -1;
355
- }
356
- // handle onmouseup & onclick
357
- else if (that.mouseUp) {
358
- that.mouseUp = false;
359
- if (el.onmouseup) {
360
- for (var i = 0; i < el.onmouseup.length; i++) {
361
- el.onmouseup[i].func(evt);
528
+ // handle onmouseup & onclick
529
+ else if (that.mouseUp) {
530
+ that.mouseUp = false;
531
+ if (el.onmouseup) {
532
+ var events = el.onmouseup;
533
+ for (var i = 0; i < events.length; i++) {
534
+ events[i].handler.apply(shape, [evt]);
535
+ }
536
+ }
537
+
538
+ // detect if click or double click occurred
539
+ if (that.clickStart) {
540
+ if (el.onclick) {
541
+ var events = el.onclick;
542
+ for (var i = 0; i < events.length; i++) {
543
+ events[i].handler.apply(shape, [evt]);
544
+ }
545
+ }
546
+
547
+ if (el.ondblclick && shape.inDoubleClickWindow) {
548
+ var events = el.ondblclick;
549
+ for (var i = 0; i < events.length; i++) {
550
+ events[i].handler.apply(shape, [evt]);
551
+ }
552
+ }
553
+
554
+ shape.inDoubleClickWindow = true;
555
+
556
+ setTimeout(function(){
557
+ shape.inDoubleClickWindow = false;
558
+ }, that.dblClickWindow);
559
+ }
560
+ n = -1;
362
561
  }
363
- }
364
-
365
- // detect if click or double click occurred
366
- if (shape.clickStart) {
367
- if (el.onclick) {
368
- for (var i = 0; i < el.onclick.length; i++) {
369
- el.onclick[i].func(evt);
562
+
563
+ // handle touchstart
564
+ else if (that.touchStart) {
565
+ that.touchStart = false;
566
+ if (el.touchstart) {
567
+ var events = el.touchstart;
568
+ for (var i = 0; i < events.length; i++) {
569
+ events[i].handler.apply(shape, [evt]);
570
+ }
571
+ }
572
+
573
+ if (el.ondbltap && shape.inDoubleClickWindow) {
574
+ var events = el.ondbltap;
575
+ for (var i = 0; i < events.length; i++) {
576
+ events[i].handler.apply(shape, [evt]);
577
+ }
370
578
  }
579
+
580
+ shape.inDoubleClickWindow = true;
581
+
582
+ setTimeout(function(){
583
+ shape.inDoubleClickWindow = false;
584
+ }, that.dblClickWindow);
585
+ n = -1;
371
586
  }
372
587
 
373
- if (el.ondblclick && shape.inDoubleClickWindow) {
374
- for (var i = 0; i < el.ondblclick.length; i++) {
375
- el.ondblclick[i].func(evt);
588
+ // handle touchend
589
+ else if (that.touchEnd) {
590
+ that.touchEnd = false;
591
+ if (el.touchend) {
592
+ var events = el.touchend;
593
+ for (var i = 0; i < events.length; i++) {
594
+ events[i].handler.apply(shape, [evt]);
595
+ }
376
596
  }
597
+ n = -1;
377
598
  }
378
599
 
379
- shape.inDoubleClickWindow = true;
600
+ // handle touchmove
601
+ else if (el.touchmove) {
602
+ var events = el.touchmove;
603
+ for (var i = 0; i < events.length; i++) {
604
+ events[i].handler.apply(shape, [evt]);
605
+ }
606
+ n = -1;
607
+ }
380
608
 
381
- setTimeout(function(){
382
- shape.inDoubleClickWindow = false;
383
- }, that.dblClickWindow);
384
- }
385
- n = -1;
386
- }
387
-
388
- // handle touchstart
389
- else if (that.touchStart) {
390
- that.touchStart = false;
391
- if (el.touchstart) {
392
- for (var i = 0; i < el.touchstart.length; i++) {
393
- el.touchstart[i].func(evt);
609
+ /*
610
+ * this condition is used to identify a new target shape.
611
+ * A new target shape occurs if a target shape is not defined or
612
+ * if the current shape is different from the current target shape and
613
+ * the current shape is beneath the target
614
+ */
615
+ else if (that.targetShape.id === undefined || (that.targetShape.id != shape.id && that.targetShape.getZIndex() < shape.getZIndex())) {
616
+ /*
617
+ * check if old target has an onmouseout event listener
618
+ */
619
+ var oldEl = that.targetShape.eventListeners;
620
+ if (oldEl && oldEl.onmouseout) {
621
+ var events = oldEl.onmouseout;
622
+ for (var i = 0; i < events.length; i++) {
623
+ events[i].handler.apply(that.targetShape, [evt]);
624
+ }
625
+ }
626
+
627
+ // set new target shape
628
+ that.targetShape = shape;
629
+
630
+ // handle onmouseover
631
+ if (el.onmouseover) {
632
+ var events = el.onmouseover;
633
+ for (var i = 0; i < events.length; i++) {
634
+ events[i].handler.apply(shape, [evt]);
635
+ }
636
+ }
637
+ n = -1;
394
638
  }
395
- }
396
- n = -1;
397
- }
398
-
399
- // handle touchend
400
- else if (that.touchEnd) {
401
- that.touchEnd = false;
402
- if (el.touchend) {
403
- for (var i = 0; i < el.touchend.length; i++) {
404
- el.touchend[i].func(evt);
639
+
640
+ // handle onmousemove
641
+ else if (el.onmousemove) {
642
+ var events = el.onmousemove;
643
+ for (var i = 0; i < events.length; i++) {
644
+ events[i].handler.apply(shape, [evt]);
645
+ }
646
+ n = -1;
405
647
  }
406
648
  }
407
- n = -1;
408
- }
409
-
410
- // handle touchmove
411
- else if (el.touchmove) {
412
- for (var i = 0; i < el.touchmove.length; i++) {
413
- el.touchmove[i].func(evt);
414
- }
415
- n = -1;
416
- }
417
-
418
- // handle onmouseover
419
- else if (!shape.mouseOver) {
420
- shape.mouseOver = true;
421
- if (el.onmouseover) {
422
- for (var i = 0; i < el.onmouseover.length; i++) {
423
- el.onmouseover[i].func(evt);
649
+ // handle mouseout condition
650
+ else if (that.targetShape.id == shape.id) {
651
+ that.targetShape = {};
652
+ if (el.onmouseout) {
653
+ var events = el.onmouseout;
654
+ for (var i = 0; i < events.length; i++) {
655
+ events[i].handler.apply(shape, [evt]);
656
+ }
424
657
  }
658
+ n = -1;
425
659
  }
426
- n = -1;
427
- }
660
+ }());
428
661
 
429
- // handle onmousemove
430
- else if (el.onmousemove) {
431
- for (var i = 0; i < el.onmousemove.length; i++) {
432
- el.onmousemove[i].func(evt);
433
- }
434
- n = -1;
435
- }
436
- }
437
- // handle mouseout condition
438
- else if (shape.mouseOver) {
439
- shape.mouseOver = false;
440
- if (el.onmouseout) {
441
- for (var i = 0; i < el.onmouseout.length; i++) {
442
- el.onmouseout[i].func(evt);
443
- }
444
- }
445
- n = -1;
446
- }
447
- }());
448
- }
662
+ linkId = link.prevId;
663
+ } // end links loop
664
+ }
665
+ } // end layer loop
449
666
  };
450
667
  /*
451
668
  * begin listening for events by adding event handlers
@@ -471,10 +688,7 @@ Kinetic.Stage.prototype.listen = function(){
471
688
  that.mouseDown = false;
472
689
  that.handleEvent(evt);
473
690
 
474
- // clear all click starts
475
- for (var i = 0; i < that.getShapes().length; i++) {
476
- that.getShapes()[i].clickStart = false;
477
- }
691
+ that.clickStart = false;
478
692
  }, false);
479
693
 
480
694
  this.container.addEventListener("mouseover", function(evt){
@@ -505,21 +719,28 @@ Kinetic.Stage.prototype.listen = function(){
505
719
  /*
506
720
  * get mouse position for desktop apps
507
721
  */
508
- Kinetic.Stage.prototype.getMousePos = function(evt){
722
+ Kinetic.Stage.prototype.getMousePosition = function(evt){
509
723
  return this.mousePos;
510
724
  };
511
725
  /*
512
726
  * get touch position for mobile apps
513
727
  */
514
- Kinetic.Stage.prototype.getTouchPos = function(evt){
728
+ Kinetic.Stage.prototype.getTouchPosition = function(evt){
515
729
  return this.touchPos;
516
730
  };
731
+ /*
732
+ * get user position (mouse position or touch position)
733
+ *
734
+ */
735
+ Kinetic.Stage.prototype.getUserPosition = function(evt){
736
+ return this.getTouchPosition() || this.getMousePosition();
737
+ };
517
738
  /*
518
739
  * set mouse positon for desktop apps
519
740
  */
520
741
  Kinetic.Stage.prototype.setMousePosition = function(evt){
521
- var mouseX = evt.clientX - this.getContainerPos().left + window.pageXOffset;
522
- var mouseY = evt.clientY - this.getContainerPos().top + window.pageYOffset;
742
+ var mouseX = evt.clientX - this.getContainerPosition().left + window.pageXOffset;
743
+ var mouseY = evt.clientY - this.getContainerPosition().top + window.pageYOffset;
523
744
  this.mousePos = {
524
745
  x: mouseX,
525
746
  y: mouseY
@@ -533,8 +754,8 @@ Kinetic.Stage.prototype.setTouchPosition = function(evt){
533
754
  // one finger
534
755
  var touch = evt.touches[0];
535
756
  // Get the information for finger #1
536
- var touchX = touch.clientX - this.getContainerPos().left + window.pageXOffset;
537
- var touchY = touch.clientY - this.getContainerPos().top + window.pageYOffset;
757
+ var touchX = touch.clientX - this.getContainerPosition().left + window.pageXOffset;
758
+ var touchY = touch.clientY - this.getContainerPosition().top + window.pageYOffset;
538
759
 
539
760
  this.touchPos = {
540
761
  x: touchX,
@@ -545,11 +766,11 @@ Kinetic.Stage.prototype.setTouchPosition = function(evt){
545
766
  /*
546
767
  * get container position
547
768
  */
548
- Kinetic.Stage.prototype.getContainerPos = function(){
769
+ Kinetic.Stage.prototype.getContainerPosition = function(){
549
770
  var obj = this.container;
550
771
  var top = 0;
551
772
  var left = 0;
552
- while (obj.tagName != "BODY") {
773
+ while (obj && obj.tagName != "BODY") {
553
774
  top += obj.offsetTop;
554
775
  left += obj.offsetLeft;
555
776
  obj = obj.offsetParent;
@@ -565,18 +786,16 @@ Kinetic.Stage.prototype.getContainerPos = function(){
565
786
  Kinetic.Stage.prototype.getContainer = function(){
566
787
  return this.container;
567
788
  };
568
- /*
569
- * get all shapes
570
- */
571
- Kinetic.Stage.prototype.getShapes = function(){
572
- return (this.getPropsLayer().getShapes()).concat(this.getActorsLayer().getShapes());
573
- };
574
- /****************************************
575
- * Shape
576
- */
577
- Kinetic.Shape = function(drawFunc, isProp){
789
+
790
+ ///////////////////////////////////////////////////////////////////////
791
+ //// Shape
792
+ ///////////////////////////////////////////////////////////////////////
793
+ ///////////////////////////////////////////////////////////////////////
794
+
795
+ Kinetic.Shape = function(drawFunc, name){
796
+ this.isListening = true;
578
797
  this.drawFunc = drawFunc;
579
- this.isProp = isProp === undefined ? false : isProp;
798
+ this.name = name;
580
799
  this.x = 0;
581
800
  this.y = 0;
582
801
  this.scale = {
@@ -596,28 +815,68 @@ Kinetic.Shape = function(drawFunc, isProp){
596
815
  };
597
816
 
598
817
  this.eventListeners = {};
599
- this.mouseOver = false;
600
- this.clickStart = false;
601
- this.inDblClickWindow = false;
602
-
603
818
  this.visible = true;
819
+ this.drag = {
820
+ x: false,
821
+ y: false
822
+ };
823
+ };
824
+ /*
825
+ * listen or don't listen to events
826
+ */
827
+ Kinetic.Shape.prototype.listen = function(isListening){
828
+ // if shape is in layer
829
+ if (this.link) {
830
+ // if changing isListening
831
+ if (isListening != this.isListening) {
832
+ // is now listening
833
+ if (isListening) {
834
+ //TODO
835
+ }
836
+ // if now not listening
837
+ else {
838
+ //TODO
839
+ }
840
+ }
841
+ }
842
+
843
+ this.isListening = isListening;
844
+ };
845
+ /*
846
+ * get shape temp layer context
847
+ */
848
+ Kinetic.Shape.prototype.getContext = function(){
849
+ return this.tempLayer.getContext();
850
+ };
851
+ /*
852
+ * get shape temp layer canvas
853
+ */
854
+ Kinetic.Shape.prototype.getCanvas = function(){
855
+ return this.tempLayer.getCanvas();
604
856
  };
605
857
  /*
606
858
  * get stage
607
859
  */
608
860
  Kinetic.Shape.prototype.getStage = function(){
609
- return this.stage;
861
+ return this.layer.stage;
610
862
  };
611
863
  /*
612
864
  * draw shape
613
865
  */
614
866
  Kinetic.Shape.prototype.draw = function(layer){
615
867
  if (this.visible) {
616
- var stage = this.getStage();
868
+ //var layer = this.layer;
869
+ var stage = layer.stage;
617
870
  var context = layer.getContext();
618
871
 
872
+ // layer transform
619
873
  context.save();
874
+ if (stage.scale.x != 1 || stage.scale.y != 1) {
875
+ context.scale(stage.scale.x, stage.scale.y);
876
+ }
620
877
 
878
+ // shape transform
879
+ context.save();
621
880
  if (this.x !== 0 || this.y !== 0) {
622
881
  context.translate(this.x, this.y);
623
882
  }
@@ -628,51 +887,128 @@ Kinetic.Shape.prototype.draw = function(layer){
628
887
  context.scale(this.scale.x, this.scale.y);
629
888
  }
630
889
 
631
- this.drawFunc.call(layer);
890
+ this.tempLayer = layer;
891
+ this.drawFunc.call(this);
892
+
893
+ context.restore();
632
894
  context.restore();
633
895
  }
634
896
  };
635
897
  /*
636
- * enable/disable drag and drop
898
+ * initialize drag and drop
899
+ */
900
+ Kinetic.Shape.prototype.initDrag = function(){
901
+ var that = this;
902
+ var types = ["mousedown", "touchstart"];
903
+
904
+ for (var n = 0; n < types.length; n++) {
905
+ var pubType = types[n];
906
+ (function(){
907
+ var type = pubType;
908
+ that.on(type + ".initdrag", function(evt){
909
+ var stage = that.layer.stage;
910
+ var pos = stage.getUserPosition();
911
+
912
+ if (pos) {
913
+ stage.shapeDragging = that;
914
+ stage.shapeDragging.offset = {};
915
+ stage.shapeDragging.offset.x = pos.x - that.x;
916
+ stage.shapeDragging.offset.y = pos.y - that.y;
917
+
918
+ // execute dragstart events if defined
919
+ var dragstart = that.eventListeners.ondragstart;
920
+ if (dragstart) {
921
+ var events = dragstart;
922
+ for (var i = 0; i < events.length; i++) {
923
+ events[i].handler.apply(that, [evt]);
924
+ }
925
+ }
926
+ }
927
+ });
928
+ })();
929
+ }
930
+ };
931
+ /*
932
+ * remove drag and drop event listener
933
+ */
934
+ Kinetic.Shape.prototype.dragCleanup = function(){
935
+ if (!this.drag.x && !this.drag.y) {
936
+ this.off("mousedown.initdrag");
937
+ this.off("touchstart.initdrag");
938
+ }
939
+ };
940
+ /*
941
+ * enable/disable drag and drop for box x and y direction
637
942
  */
638
943
  Kinetic.Shape.prototype.draggable = function(setDraggable){
639
944
  if (setDraggable) {
640
- var that = this;
641
- this.addEventListener("mousedown.initdrag", function(evt){
642
- var stage = that.getStage();
643
- stage.shapeDragging = that;
644
- var mousePos = stage.getMousePos();
645
-
646
- stage.shapeDragging.offset = {};
647
- stage.shapeDragging.offset.x = mousePos.x - that.x;
648
- stage.shapeDragging.offset.y = mousePos.y - that.y;
649
-
650
- // execute dragstart events if defined
651
- var dragstart = that.eventListeners.ondragstart;
652
- if (dragstart) {
653
- for (var i = 0; i < dragstart.length; i++) {
654
- dragstart[i].func(evt);
655
- }
656
- }
657
- });
945
+ var needInit = !this.drag.x && !this.drag.y;
946
+ this.drag = {
947
+ x: true,
948
+ y: true
949
+ };
950
+ if (needInit) {
951
+ this.initDrag();
952
+ }
658
953
  }
659
954
  else {
660
- this.removeEventListener("mousedown.initdrag");
955
+ this.drag = {
956
+ x: false,
957
+ y: false
958
+ };
959
+ this.dragCleanup();
661
960
  }
662
961
  };
663
962
  /*
664
- * set shape scale
963
+ * enable/disable drag and drop for x only
665
964
  */
666
- Kinetic.Shape.prototype.setScale = function(scale){
667
- this.scale.x = scale;
668
- this.scale.y = scale;
965
+ Kinetic.Shape.prototype.draggableX = function(setDraggable){
966
+ if (setDraggable) {
967
+ var needInit = !this.drag.x && !this.drag.y;
968
+ this.drag.x = true;
969
+ if (needInit) {
970
+ this.initDrag();
971
+ }
972
+ }
973
+ else {
974
+ this.drag.x = false;
975
+ this.dragCleanup();
976
+ }
669
977
  };
670
978
  /*
671
- * scale shape
979
+ * enable/disable drag and drop for y only
672
980
  */
673
- Kinetic.Shape.prototype.scale = function(scale){
674
- this.scale.x *= scale;
675
- this.scale.y *= scale;
981
+ Kinetic.Shape.prototype.draggableY = function(setDraggable){
982
+ if (setDraggable) {
983
+ var needInit = !this.drag.x && !this.drag.y;
984
+ this.drag.y = true;
985
+ if (needInit) {
986
+ this.initDrag();
987
+ }
988
+ }
989
+ else {
990
+ this.drag.y = false;
991
+ this.dragCleanup();
992
+ }
993
+ };
994
+ /*
995
+ * get zIndex
996
+ */
997
+ Kinetic.Shape.prototype.getZIndex = function(){
998
+ return this.link.index;
999
+ };
1000
+ /*
1001
+ * set shape scale
1002
+ */
1003
+ Kinetic.Shape.prototype.setScale = function(scaleX, scaleY){
1004
+ if (scaleY) {
1005
+ this.scale.x = scaleX;
1006
+ this.scale.y = scaleY;
1007
+ }
1008
+ else {
1009
+ this.scale.x = scaleX;
1010
+ this.scale.y = scaleX;
1011
+ }
676
1012
  };
677
1013
  /*
678
1014
  * move shape to position
@@ -681,6 +1017,15 @@ Kinetic.Shape.prototype.setPosition = function(x, y){
681
1017
  this.x = x;
682
1018
  this.y = y;
683
1019
  };
1020
+ /*
1021
+ * get shape position
1022
+ */
1023
+ Kinetic.Shape.prototype.getPosition = function(){
1024
+ return {
1025
+ x: this.x,
1026
+ y: this.y
1027
+ };
1028
+ };
684
1029
  /*
685
1030
  * move shape by amount
686
1031
  */
@@ -703,26 +1048,35 @@ Kinetic.Shape.prototype.rotate = function(theta){
703
1048
  /*
704
1049
  * short-hand add event listener to shape
705
1050
  */
706
- Kinetic.Shape.prototype.on = function(type, func){
707
- var event = (type.indexOf('touch') == -1) ? 'on' + type : type;
708
- var parts = event.split(".");
709
- var baseEvent = parts[0];
710
- var name = parts.length > 1 ? parts[1] : "";
711
-
712
- if (!this.eventListeners[baseEvent]) {
713
- this.eventListeners[baseEvent] = [];
1051
+ Kinetic.Shape.prototype.on = function(typesStr, handler){
1052
+ var types = typesStr.split(" ");
1053
+ /*
1054
+ * loop through types and attach event listeners to
1055
+ * each one. eg. "click mouseover.namespace mouseout"
1056
+ * will create three event bindings
1057
+ */
1058
+ for (var n = 0; n < types.length; n++) {
1059
+ var type = types[n];
1060
+ var event = (type.indexOf('touch') == -1) ? 'on' + type : type;
1061
+ var parts = event.split(".");
1062
+ var baseEvent = parts[0];
1063
+ var name = parts.length > 1 ? parts[1] : "";
1064
+
1065
+ if (!this.eventListeners[baseEvent]) {
1066
+ this.eventListeners[baseEvent] = [];
1067
+ }
1068
+
1069
+ this.eventListeners[baseEvent].push({
1070
+ name: name,
1071
+ handler: handler
1072
+ });
714
1073
  }
715
-
716
- this.eventListeners[baseEvent].push({
717
- name: name,
718
- func: func
719
- });
720
1074
  };
721
1075
  /*
722
1076
  * long-hand add event listener to shape
723
1077
  */
724
- Kinetic.Shape.prototype.addEventListener = function(type, func){
725
- this.on(type, func);
1078
+ Kinetic.Shape.prototype.addEventListener = function(type, handler){
1079
+ this.on(type, handler);
726
1080
  };
727
1081
  /*
728
1082
  * short-hand remove event listener(s)
@@ -732,13 +1086,13 @@ Kinetic.Shape.prototype.off = function(type){
732
1086
  var parts = event.split(".");
733
1087
  var baseEvent = parts[0];
734
1088
 
735
- if (parts.length > 1) {
1089
+ if (this.eventListeners[baseEvent] && parts.length > 1) {
736
1090
  var name = parts[1];
737
1091
 
738
1092
  for (var i = 0; i < this.eventListeners[baseEvent].length; i++) {
739
1093
  if (this.eventListeners[baseEvent][i].name == name) {
740
1094
  this.eventListeners[baseEvent].splice(i, 1);
741
- if (this.eventListeners[baseEvent].length == 0) {
1095
+ if (this.eventListeners[baseEvent].length === 0) {
742
1096
  this.eventListeners[baseEvent] = undefined;
743
1097
  }
744
1098
  break;
@@ -771,115 +1125,141 @@ Kinetic.Shape.prototype.hide = function(){
771
1125
  * move shape to top
772
1126
  */
773
1127
  Kinetic.Shape.prototype.moveToTop = function(){
774
- var stage = this.stage;
775
- var layer = this.getLayer();
776
- var shapes = layer.getShapes();
777
-
778
- for (var n = 0; n < shapes.length; n++) {
779
- var shape = shapes[n];
780
- if (shape.id == this.id) {
781
- layer.shapes.splice(n, 1);
782
- layer.shapes.push(this);
783
- break;
1128
+ var link = this.link;
1129
+ var index = link.index;
1130
+ var layer = this.layer;
1131
+ this.layer.links.splice(index, 1);
1132
+ this.layer.links.push(link);
1133
+
1134
+ layer.setLinkIndices();
1135
+
1136
+ if (this.isListening) {
1137
+ // alter link structure if more than one link in the layer
1138
+ if (link.nextId !== undefined || link.prevId !== undefined) {
1139
+ layer.unlink(link);
1140
+ var tail = layer.linkHash[layer.tailId];
1141
+ tail.nextId = link.id;
1142
+ link.prevId = tail.id;
1143
+ layer.tailId = link.id;
784
1144
  }
785
1145
  }
786
1146
  };
787
1147
  /*
788
- * get shape layer
1148
+ * move shape up
789
1149
  */
790
- Kinetic.Shape.prototype.getLayer = function(){
791
- return this.layer;
792
- };
793
- /*
794
- * get shape layer
795
- */
796
- Kinetic.Shape.prototype.makeActor = function(){
797
- var stage = this.stage;
798
- var layer = this.getLayer();
799
- var propsLayer = stage.getPropsLayer();
800
- var actorsLayer = stage.getActorsLayer();
801
- var shapes = layer.getShapes();
802
-
803
- for (var n = 0; n < shapes.length; n++) {
804
- var shape = shapes[n];
805
- if (shape.id == this.id) {
806
- layer.shapes.splice(n, 1);
807
- actorsLayer.getShapes().push(this);
808
- break;
1150
+ Kinetic.Shape.prototype.moveUp = function(){
1151
+ var link = this.link;
1152
+ var index = link.index;
1153
+ var layer = this.layer;
1154
+ var nextLink = layer.linkHash[link.nextId];
1155
+
1156
+ // only do something if there's a link above
1157
+ if (nextLink) {
1158
+ // swap links
1159
+ this.layer.links.splice(index, 1);
1160
+ this.layer.links.splice(index + 1, 0, link);
1161
+
1162
+ layer.setLinkIndices();
1163
+
1164
+ nextLink.prevId = link.prevId;
1165
+ link.nextId = nextLink.nextId;
1166
+
1167
+ if (link.prevId !== undefined) {
1168
+ layer.linkHash[link.prevId].nextId = nextLink.id;
1169
+ }
1170
+ if (nextLink.nextId !== undefined) {
1171
+ layer.linkHash[nextLink.nextId].prevId = link.id;
1172
+ }
1173
+
1174
+ // link to eachother
1175
+ link.prevId = nextLink.id;
1176
+ nextLink.nextId = link.id;
1177
+
1178
+ // handle tail and head reassignment
1179
+ if (link.id == layer.headId) {
1180
+ layer.headId = nextLink.id;
1181
+ }
1182
+ if (nextLink.id == layer.tailId) {
1183
+ layer.tailId = link.id;
809
1184
  }
810
1185
  }
811
1186
  };
812
1187
  /*
813
- * make shape into an actor
1188
+ * move shape down
814
1189
  */
815
- Kinetic.Shape.prototype.makeActor = function(){
816
- var stage = this.stage;
817
- var layer = this.getLayer();
818
- var propsLayer = stage.getPropsLayer();
819
- var actorsLayer = stage.getActorsLayer();
820
- var shapes = layer.getShapes();
1190
+ Kinetic.Shape.prototype.moveDown = function(){
1191
+ var link = this.link;
1192
+ var index = link.index;
1193
+ var layer = this.layer;
1194
+ var prevLink = layer.linkHash[link.prevId];
821
1195
 
822
- for (var n = 0; n < shapes.length; n++) {
823
- var shape = shapes[n];
824
- if (shape.id == this.id) {
825
- layer.shapes.splice(n, 1);
826
- actorsLayer.getShapes().push(this);
827
- this.layer = stage.actorsLayer;
828
- break;
1196
+ // only do something if there's a link above
1197
+ if (prevLink) {
1198
+ // swap links
1199
+ this.layer.links.splice(index, 1);
1200
+ this.layer.links.splice(index - 1, 0, link);
1201
+
1202
+ layer.setLinkIndices();
1203
+
1204
+ link.prevId = prevLink.prevId;
1205
+ prevLink.nextId = link.nextId;
1206
+
1207
+ if (link.nextId !== undefined) {
1208
+ layer.linkHash[link.nextId].prevId = prevLink.id;
1209
+ }
1210
+ if (prevLink.prevId !== undefined) {
1211
+ layer.linkHash[prevLink.prevId].nextId = link.id;
1212
+ }
1213
+
1214
+ // link to eachother
1215
+ link.nextId = prevLink.id;
1216
+ prevLink.prevId = link.id;
1217
+
1218
+ // handle tail and head reassignment
1219
+ if (prevLink.id == layer.headId) {
1220
+ layer.headId = link.id;
1221
+ }
1222
+ if (link.id == layer.tailId) {
1223
+ layer.tailId = prevLink.id;
829
1224
  }
830
1225
  }
831
1226
  };
832
1227
  /*
833
- * make shape into a prop
1228
+ * move shape to bottom
834
1229
  */
835
- Kinetic.Shape.prototype.makeProp = function(){
836
- var stage = this.stage;
837
- var layer = this.getLayer();
838
- var propsLayer = stage.getPropsLayer();
839
- var actorsLayer = stage.getActorsLayer();
840
- var shapes = layer.getShapes();
841
- for (var n = 0; n < shapes.length; n++) {
842
- var shape = shapes[n];
843
- if (shape.id == this.id) {
844
- layer.shapes.splice(n, 1);
845
- propsLayer.getShapes().push(this);
846
- this.layer = stage.propsLayer;
847
- break;
1230
+ Kinetic.Shape.prototype.moveToBottom = function(){
1231
+ var link = this.link;
1232
+ var index = link.index;
1233
+ var layer = this.layer;
1234
+ this.layer.links.splice(index, 1);
1235
+ this.layer.links.unshift(link);
1236
+
1237
+ layer.setLinkIndices();
1238
+
1239
+ if (this.isListening) {
1240
+ // alter link structure if more than one link in the layer
1241
+ if (link.nextId !== undefined || link.prevId !== undefined) {
1242
+ layer.unlink(link);
1243
+ var head = layer.linkHash[layer.headId];
1244
+ head.prevId = link.id;
1245
+ link.nextId = head.id;
1246
+ layer.headId = link.id;
848
1247
  }
849
1248
  }
850
1249
  };
851
- /****************************************
852
- * Image constructor
1250
+ /*
1251
+ * get shape layer
853
1252
  */
854
- Kinetic.Image = function(config){
855
- var imageObj = config.imageObj;
856
- var x = config.x;
857
- var y = config.y;
858
- var width = config.width;
859
- var height = config.height;
860
- var isProp = config.isProp;
861
-
862
- if (!width) {
863
- width = imageObj.width;
864
- }
865
- if (!height) {
866
- height = imageObj.height;
867
- }
868
- var drawImage = function(){
869
- var context = this.getContext();
870
- context.drawImage(imageObj, x, y, width, height);
871
- context.beginPath();
872
- context.rect(x, y, width, height);
873
- context.closePath();
874
- };
875
-
876
- var shape = new Kinetic.Shape(drawImage, isProp);
877
-
878
- /*
879
- * copy shape methods and properties to
880
- * Image object
881
- */
882
- for (var key in shape) {
883
- this[key] = shape[key];
884
- }
1253
+ Kinetic.Shape.prototype.getLayer = function(){
1254
+ return this.layer;
885
1255
  };
1256
+ /*
1257
+ * move shape to another layer
1258
+ */
1259
+ Kinetic.Shape.prototype.moveToLayer = function(newLayer){
1260
+ var layer = this.layer;
1261
+ var link = this.link;
1262
+ layer.unlink(link);
1263
+ layer.removeLink(link);
1264
+ newLayer.addLink(link);
1265
+ };