1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 /**
 27  * the DOM object
 28  * @class
 29  * @type {Object}
 30  */
 31 cc.DOM = {};
 32 /**
 33  * Set to true to enalbe DOM debugging/editing, which allows you to move, rotate, scale, skew an element.
 34  * Set to false to turn off debugging/editing
 35  * @type Boolean
 36  */
 37 cc.DOMEditMode = true;
 38 /**
 39  * @function
 40  * @private
 41  * @param x
 42  */
 43 cc.DOM.addMethods = function (x) {
 44     for (funcs in cc.DOM.methods) {
 45         x[funcs] = cc.DOM.methods[funcs];
 46     }
 47 };
 48 cc.DOM.methods = /** @lends cc.DOM# */{
 49     /**
 50      * Replace the set position of ccNode
 51      * @param {object|Number} x
 52      * @param {Number} y
 53      */
 54     setPosition:function (x, y) {
 55         if (arguments.length == 2) {
 56             this._position.x = x;
 57             this._position.y = y;
 58             //this._position = cc.p(newPosOrxValue,yValue);
 59         } else {
 60             this._position = x;
 61         }
 62         this.dom.translates(this._position.x, -this._position.y);
 63     },
 64     /**
 65      * replace set Position Y of ccNode
 66      * @param {Number} y
 67      */
 68     setPositionY:function (y) {
 69         this._position.y = y;
 70         this.dom.translates(this._position.x, -this._position.y);
 71     },
 72 
 73     /**
 74      * replace set Position X of ccNode
 75      * @param {Number} x
 76      */
 77     setPositionX:function (x) {
 78         this._position.x = x;
 79         this.dom.translates(this._position.x, -this._position.y);
 80     },
 81 
 82     /**
 83      * replace set Scale of ccNode
 84      * @param {object|Number} scale
 85      * @param {Number} scaleY
 86      */
 87     setScale:function (scale, scaleY) {
 88         //save dirty region when before change
 89         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
 90 
 91         this._scaleX = scale;
 92         this._scaleY = scaleY || scale;
 93 
 94         //save dirty region when after changed
 95         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
 96         this.dom.resize(this._scaleX, this._scaleY);
 97     },
 98 
 99     /**
100      * replace set Scale X of ccNode
101      * @param {Number} x
102      */
103     setScaleX:function (x) {
104         this._scaleX = x;
105         this.dom.resize(this._scaleX, this._scaleY);
106     },
107 
108     /**
109      * replace set Scale Y of ccNode
110      * @param {Number} y
111      */
112     setScaleY:function (y) {
113         this._scaleY = y;
114         this.dom.resize(this._scaleX, this._scaleY);
115     },
116 
117     /**
118      * replace set anchorpoint of ccNode
119      * @param {object} point
120      */
121     setAnchorPoint:function (point) {
122         this._anchorPoint = point;
123         this._anchorPointInPoints = cc.p(this._contentSize.width * this._anchorPoint.x,
124             this._contentSize.height * this._anchorPoint.y);
125         this.dom.style[cc.$.pfx + 'TransformOrigin'] = '' + this._anchorPointInPoints.x + 'px ' + this._anchorPointInPoints.y + 'px';
126         if (this.isIgnoreAnchorPointForPosition()) {
127             this.dom.style.marginLeft = 0;
128             this.dom.style.marginBottom = 0;
129         }
130         else {
131             this.dom.style.marginLeft = (this.isToggler) ? 0 : -this._anchorPointInPoints.x + 'px';
132             this.dom.style.marginBottom = -this._anchorPointInPoints.y + 'px';
133         }
134     },
135 
136     /**
137      * replace set ContentSize of ccNode
138      * @param {cc.Size} size
139      */
140     setContentSize:function (size) {
141         if (!cc.Size.CCSizeEqualToSize(size, this._contentSize)) {
142             this._contentSize = size;
143             this._anchorPointInPoints = cc.p(this._contentSize.width * this._anchorPoint.x,
144                 this._contentSize.height * this._anchorPoint.y);
145             this.dom.width = size.width;
146             this.dom.height = size.height;
147             this.setAnchorPoint(this.getAnchorPoint());
148         }
149         if (this.canvas) {
150             this.canvas.width = this._contentSize.width;
151             this.canvas.height = this._contentSize.height;
152         }
153         if (cc.DOMEditMode && !this.placeholder) {
154             this.dom.style.width = this._contentSize.width + 'px';
155             this.dom.style.height = this._contentSize.height + 'px';
156             this.dom.addClass('CCDOMEdit');
157         }
158         this.redraw();
159     },
160 
161     /**
162      * replace set Rotation of ccNode
163      * @param {Number} newRotation
164      */
165     setRotation:function (newRotation) {
166         if (this._rotation == newRotation)
167             return;
168         //save dirty region when before change
169         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
170 
171         this._rotation = newRotation;
172         this._rotationRadians = this._rotation * (Math.PI / 180);
173         this.dom.rotate(newRotation);
174     },
175 
176     /**
177      * replace set SkewX of ccNode
178      * @param {Number} x
179      */
180     setSkewX:function (x) {
181         this._skewX = x;
182         this.dom.setSkew(this._skewX, this._skewY);
183     },
184 
185     /**
186      * replace set SkewY of ccNode
187      * @param {Number} y
188      */
189     setSkewY:function (y) {
190         this._skewY = y;
191         this.dom.setSkew(this._skewX, this._skewY);
192     },
193 
194     /**
195      * replace set Visible of ccNode
196      * @param {Boolean} x
197      */
198     setVisible:function (x) {
199         this._visible = x;
200         if (this.dom)
201             this.dom.style.visibility = (x) ? 'visible' : 'hidden';
202     },
203     _setZOrder:function (z) {
204         this._zOrder = z;
205         if (this.dom)
206             this.dom.zIndex = z;
207     },
208 
209     /**
210      * replace set Parent of ccNode
211      * @param {cc.Node} p
212      */
213     setParent:function (p) {
214         this._parent = p;
215         cc.DOM.parentDOM(this);
216     },
217 
218     /**
219      * replace resume Schedule and actions of ccNode
220      */
221     resumeSchedulerAndActions:function () {
222         this.getScheduler().resumeTarget(this);
223         this.getActionManager().resumeTarget(this);
224         //if dom does not have parent, but node has no parent and its running
225         if (this.dom && !this.dom.parentNode) {
226             if (!this.getParent()) {
227                 this.dom.appendTo(cc.container);
228             }
229             else {
230                 cc.DOM.parentDOM(this);
231             }
232         }
233         if (this.dom)
234             this.dom.style.visibility = "visible";
235     },
236 
237     /**
238      * replace pause Schedule and Actions of ccNode
239      */
240     pauseSchedulerAndActions:function () {
241         this.getScheduler().pauseTarget(this);
242         this.getActionManager().pauseTarget(this);
243         if (this.dom) {
244             this.dom.style.visibility = 'hidden';
245         }
246     },
247 
248     /**
249      * replace clean up of ccNode
250      */
251     cleanup:function () {
252         // actions
253         this.stopAllActions();
254         this.unscheduleAllCallbacks();
255 
256         // timers
257         this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.cleanup);
258         if (this.dom) {
259             this.dom.remove();
260         }
261     },
262     /**
263      * replace remove from parent and clean up of ccNode
264      */
265     removeFromParentAndCleanup:function () {
266         this.dom.remove();
267     },
268     setOpacity:function (o) {
269         this._opacity = o;
270         this.dom.style.opacity = o / 255;
271     },
272     /**
273      * refresh/updates the DOM element
274      */
275     redraw:function () {
276         if (this.isSprite) {
277             var tmp = this._children;
278             this._children = null;
279             cc.Sprite.prototype.visit.call(this, this.ctx);
280             this._children = tmp;
281         }
282         else {
283             cc.Sprite.prototype.visit.call(this, this.ctx);
284         }
285     }
286 };
287 /**
288  * @function
289  * @private
290  * @param x
291  * @return {Boolean}
292  */
293 cc.DOM.parentDOM = function (x) {
294     var p = x.getParent();
295     //if has parent, parent need to have dom too
296     if (!p || !x.dom)
297         return false;
298     if (!p.dom) {
299         cc.DOM.placeHolder(p);
300         p.setParent = cc.DOM.methods.setParent;
301     }
302     //if parent have dom, attach self to parent
303     x.dom.appendTo(p.dom);
304     var pp;
305     if (pp = p.getParent()) {
306         cc.DOM.parentDOM(p);
307     }
308     else {
309         //parent has no more parent, if its running, then add it to the container
310         if (p.isRunning()) {
311             p.dom.appendTo(cc.container);
312         }
313     }
314     return true;
315 };
316 
317 /**
318  * @function
319  * @private
320  * @param x
321  */
322 cc.DOM.setTransform = function (x) {
323     if (x.ctx) {
324         /*        x.ctx.save();
325          x.ctx.setTransform(1,0,0,1,0,0);
326          x.ctx.clearRect(0,0,x.canvas.width, x.canvas.height);
327          x.ctx.restore();*/
328         x.ctx.translate(x.getAnchorPointInPoints().x, x.getAnchorPointInPoints().y);
329         if (x.isSprite) {
330             var tmp = x._children;
331             x._children = null;
332             cc.Sprite.prototype.visit.call(x, x.ctx);
333             x._children = tmp;
334         }
335         else {
336             cc.Sprite.prototype.visit.call(x, x.ctx);
337         }
338     }
339     if (x.dom) {
340         x.dom.position.x = x.getPosition().x;
341         x.dom.position.y = -x.getPosition().y;
342         x.dom.rotation = x.getRotation();
343         x.dom.scale = {x:x.getScaleX(), y:x.getScaleY()};
344         x.dom.skew = {x:x.getSkewX(), y:x.getSkewY()};
345         if (x.setAnchorPoint)
346             x.setAnchorPoint(x.getAnchorPoint());
347         x.dom.transforms();
348         x.dom.position.y = -x.getPosition().y;
349         x.dom.rotation = x.getRotation();
350         x.dom.scale = {x:x.getScaleX(), y:x.getScaleY()};
351         x.dom.skew = {x:x.getSkewX(), y:x.getSkewY()};
352         if (x.setAnchorPoint)
353             x.setAnchorPoint(x.getAnchorPoint());
354         x.dom.transforms();
355     }
356 
357 };
358 
359 /**
360  * @function
361  * @private
362  * @param x
363  */
364 cc.DOM.forSprite = function (x) {
365     x.dom = cc.$new('div');
366     x.canvas = cc.$new('canvas');
367     x.canvas.width = x.getContentSize().width;
368     x.canvas.height = x.getContentSize().height;
369     if (cc.DOMEditMode) {
370         x.dom.style.width = x.getContentSize().width + 'px';
371         x.dom.style.height = x.getContentSize().height + 'px';
372         x.dom.addClass('CCDOMEdit');
373     }
374     x.dom.style.position = 'absolute';
375     x.dom.style.bottom = 0;
376     x.ctx = x.canvas.getContext('2d');
377     x.dom.appendChild(x.canvas);
378     if (x.getParent()) {
379         cc.DOM.parentDOM(x);
380     }
381     x.isSprite = true;
382 };
383 
384 /**
385  * @function
386  * @private
387  * @param x
388  */
389 cc.DOM.forMenuToggler = function (x) {
390     x.dom = cc.$new('div');
391     x.dom2 = cc.$new('div');
392     x.dom.appendChild(x.dom2);
393     for (var i = 0; i < x._subItems.length; i++) {
394         cc.DOM.convert(x._subItems[i]);
395         x.dom2.appendChild(x._subItems[i].dom);
396         x._subItems[i].setPosition(cc.p(0, 0));
397     }
398     x.dom.style.marginLeft = 0;
399     x.setSelectedIndex = function (SelectedIndex) {
400         this._selectedIndex = SelectedIndex;
401         for (var i = 0; i < this._subItems.length; i++) {
402             this._subItems[i].setVisible(false);
403         }
404         this._subItems[SelectedIndex].setVisible(true);
405     };
406 
407 
408     x.setSelectedIndex(x.getSelectedIndex());
409     x.dom2.addEventListener('click', function () {
410         x.activate();
411     });
412     x.dom2.addEventListener('mousedown', function () {
413         for (var i = 0; i < x._subItems.length; i++) {
414             x._subItems[i]._isEnabled = true;
415             x._subItems[i]._running = true;
416             x._subItems[i].selected();
417             x._subItems[i]._isEnabled = false;
418             x._subItems[i]._running = false;
419         }
420         x._subItems[x.getSelectedIndex()]._isEnabled = true;
421         x._subItems[x.getSelectedIndex()]._running = true;
422 
423     });
424     x.dom2.addEventListener('mouseup', function () {
425         for (var i = 0; i < x._subItems.length; i++) {
426             x._subItems[i]._isEnabled = true;
427             x._subItems[i].unselected();
428             x._subItems[i]._isEnabled = false;
429         }
430         x._subItems[x.getSelectedIndex()]._isEnabled = true;
431     });
432     x.dom2.addEventListener('mouseout', function () {
433         if (x.mouseDown) {
434             for (var i = 0; i < x._subItems.length; i++) {
435                 x._subItems[i]._isEnabled = true;
436                 x._subItems[i].unselected();
437                 x._subItems[i]._isEnabled = false;
438             }
439             x._subItems[x.getSelectedIndex()]._isEnabled = true;
440             x.mouseDown = false;
441         }
442     });
443     x.dom.style.position = "absolute";
444     x.isToggler = true;
445 };
446 
447 /**
448  * @function
449  * @private
450  * @param x
451  */
452 cc.DOM.forMenuItem = function (x) {
453     x.dom = cc.$new('div');
454     x.canvas = cc.$new('canvas');
455     x.canvas.width = x.getContentSize().width;
456     x.canvas.height = x.getContentSize().height;
457     if (cc.DOMEditMode) {
458         x.dom.style.width = x.getContentSize().width + 'px';
459         x.dom.style.height = x.getContentSize().height + 'px';
460         x.dom.addClass('CCDOMEdit');
461     }
462     x.dom.style.position = 'absolute';
463     x.dom.style.bottom = 0;
464     x.ctx = x.canvas.getContext('2d');
465     x.dom.appendChild(x.canvas);
466     if (x.getParent()) {
467         cc.DOM.parentDOM(x);
468     }
469     if (x._selector) {
470         //if menu item have callback
471         x.canvas.addEventListener('click', function () {
472             x.activate();
473         });
474         x.canvas.addEventListener('mousedown', function () {
475             x.selected();
476             x.ctx.save();
477             x.ctx.setTransform(1, 0, 0, 1, 0, 0);
478             x.ctx.clearRect(0, 0, x.canvas.width, x.canvas.height);
479             x.ctx.restore();
480             x.mouseDown = true;
481             cc.Sprite.prototype.visit.call(x, x.ctx);
482         });
483         x.canvas.addEventListener('mouseup', function () {
484             x.unselected();
485             x.ctx.save();
486             x.ctx.setTransform(1, 0, 0, 1, 0, 0);
487             x.ctx.clearRect(0, 0, x.canvas.width, x.canvas.height);
488             x.ctx.restore();
489             cc.Sprite.prototype.visit.call(x, x.ctx);
490         });
491         x.canvas.addEventListener('mouseout', function () {
492             if (x.mouseDown) {
493                 x.unselected();
494                 x.ctx.save();
495                 x.ctx.setTransform(1, 0, 0, 1, 0, 0);
496                 x.ctx.clearRect(0, 0, x.canvas.width, x.canvas.height);
497                 x.ctx.restore();
498                 cc.Sprite.prototype.visit.call(x, x.ctx);
499                 x.mouseDown = false;
500             }
501         })
502     }
503 };
504 
505 /**
506  * This creates divs for parent Nodes that are related to the current node
507  * @function
508  * @private
509  * @param x
510  */
511 cc.DOM.placeHolder = function (x) {
512     //creating a placeholder dom to simulate other ccNode in the hierachy
513     x.dom = cc.$new('div');
514     x.placeholder = true;
515     x.dom.style.position = 'absolute';
516     x.dom.style.bottom = 0;
517     //x.dom.style.display='block';
518     x.dom.style.width = (x.getContentSize().width || cc.Director.getInstance().getWinSize().width) + "px";
519     x.dom.style.maxHeight = (x.getContentSize().height || cc.Director.getInstance().getWinSize().height) + "px";
520     x.dom.style.margin = 0;
521     cc.DOM.setTransform(x);
522     x.dom.transforms();
523     cc.DOM.addMethods(x);
524     //x.dom.style.border = 'red 1px dotted';
525 };
526 
527 /**
528  * Converts cc.Sprite or cc.MenuItem to DOM elements <br/>
529  * It currently only supports cc.Sprite and cc.MenuItem
530  * @function
531  * @param {cc.Sprite|cc.MenuItem|Array}
532     * * @example
533  * // example
534  * cc.DOM.convert(Sprite1, Sprite2, Menuitem);
535  *
536  * var myDOMElements = [Sprite1, Sprite2, MenuItem];
537  * cc.DOM.convert(myDOMElements);
538  */
539 cc.DOM.convert = function () {
540     //if passing by list, make it an array
541     if (arguments.length > 1) {
542         return cc.DOM.convert(arguments);
543     }
544     else if (arguments.length == 1 && !arguments[0].length) {
545         return cc.DOM.convert([arguments[0]]);
546     }
547     var args = arguments[0];
548     for (var i = 0; i < args.length; i++) {
549         //first check if its sprite or menuitem
550         if (args[i] instanceof cc.Sprite) {
551             // create a canvas
552             if (!args[i].dom)
553                 cc.DOM.forSprite(args[i]);
554         }
555         else if (args[i] instanceof cc.MenuItemToggle) {
556             if (!args[i].dom)
557                 cc.DOM.forMenuToggler(args[i]);
558         }
559 
560         else if (args[i] instanceof cc.MenuItem) {
561             if (!args[i].dom)
562                 cc.DOM.forMenuItem(args[i]);
563         }
564         else {
565             cc.log('DOM converter only supports sprite and menuitems yet');
566         }
567         cc.DOM.addMethods(args[i]);
568         args[i].visit = function () {
569         };
570         args[i].transform = function () {
571         };
572         cc.DOM.setTransform(args[i]);
573         args[i].setVisible(args[i].isVisible());
574         if (cc.DOMEditMode) {
575             //add hover event to popup inspector
576             if (!cc.DOM.tooltip) {
577                 var style = cc.$new('style');
578                 style.textContent = ".CCDOMEdit:hover{border: rgba(255,0,0,0.5) 2px dashed;left: -2px;} .CCDOMEdit "
579                     + " #CCCloseButton{width:80px;height:15px;background: rgba(0,0,0,0.4);border:1px solid #aaaaaa;font-size: 9px;line-height:9px;color:#bbbbbb;} "
580                     + " .CCTipWindow .CCTipMove{cursor:move;} .CCTipWindow .CCTipRotate{cursor:w-resize;} .CCTipWindow .CCTipScale{cursor:ne-resize;} "
581                     + ".CCTipWindow .CCTipSkew{cursor:se-resize;} .CCTipWindow input{width:40px;background: rgba(0,0,0,0.5);color:white;border:none;border-bottom: 1px solid #fff;} "
582                     + "div.CCTipWindow:hover{color:rgb(50,50,255);}";
583                 document.body.appendChild(style);
584                 cc.container.style.overflow = "visible";
585                 var tip = cc.DOM.tooltip = cc.$new('div');
586                 tip.mouseDown = false;
587                 document.body.appendChild(tip);
588                 tip.addClass('CCTipWindow');
589                 tip.style.width = '140px';
590                 tip.style.height = '134px';
591                 tip.style.background = 'rgba(50,50,50,0.5)';
592                 tip.style.border = '1px rgba(255,255,255,0.5) solid';
593                 tip.style.borderRadius = '5px';
594                 tip.style.color = 'rgb(255,255,255)';
595                 tip.style.boxShadow = '0 0 10px 1px rgba(0,0,0,0.5)';
596                 tip.style.position = 'absolute';
597                 tip.style.display = 'none';
598                 tip.style.top = 0;
599                 tip.style.left = '-150px';
600                 tip.style[cc.$.pfx + "Transform"] = 'translate3d(0,0,100px)';
601                 tip.style[cc.$.pfx + 'UserSelect'] = 'none';
602                 tip.innerHTML = '<table><tr>' +
603                     '<td><label class="CCTipMove">Move</label></td><td><input type="text" value="12" id="posx"/></td><td><input type="text" value="12" id="posy"/></td></tr>' +
604                     '<tr><td><label class="CCTipRotate">Rotate</label></td><td><input type="text" value="12" id="rot"/></td></tr>' +
605                     '<tr><td><label class="CCTipScale">Scale</label></td><td><input type="text" value="12" id="scalex"/></td><td><input type="text" value="12" id="scaley"/></td></tr>' +
606                     '<tr><td><label class="CCTipSkew">Skew</label></td><td><input type="text" value="12" id="skewx"/></td><td><input type="text" value="12" id="skewy"/></td></tr>' +
607                     '</table><button id="CCCloseButton">Close</button>';
608                 tip.updateNumbers = function () {
609                     var t = cc.DOM.tooltip;
610                     if (t.target) {
611                         t.find("#posx").value = t.target._position.x;
612                         t.find("#posy").value = t.target._position.y;
613                         t.find("#rot").value = t.target._rotation;
614                         t.find("#scalex").value = t.target._scaleX;
615                         t.find("#scaley").value = t.target._scaleY;
616                         t.find("#skewx").value = t.target._skewX;
617                         t.find("#skewy").value = t.target._skewY;
618                     }
619                 };
620                 tip.find('.CCTipMove').addEventListener('mousedown', function (e) {
621                     tip.mode = 'move';
622                     tip.initialpos = {x:e.clientX, y:e.clientY};
623                     tip.mouseDown = true;
624                 });
625                 tip.find('.CCTipRotate').addEventListener('mousedown', function (e) {
626                     //find out the position of cc.canvas
627                     var canvaspos = cc.$.findpos(cc.canvas);
628                     //find out the bottom left position of cc.canvas, adding canvas height to canvaspos
629                     var canvaspos = {x:canvaspos.x, y:canvaspos.y + cc.canvas.height};
630                     //add the position of the element from canvas bottom left
631                     tip.nodepos = tip.target.getPosition();
632                     tip.nodepos = {x:canvaspos.x + tip.nodepos.x, y:canvaspos.y - tip.nodepos.y};
633                     tip.startPos = {x:e.x, y:e.y};
634                     tip.mode = 'rot';
635                     tip.initialpos = {x:e.clientX, y:e.clientY};
636                     tip.mouseDown = true;
637                     //also need to find out the starting angle
638                     var C = {x:tip.startPos.x, y:tip.nodepos.y};
639                     var A = tip.startPos;
640                     var B = tip.nodepos;
641                     var a = Math.sqrt(Math.pow((B.x - C.x), 2) + Math.pow((B.y - C.y), 2));
642                     var b = Math.sqrt(Math.pow((A.x - C.x), 2) + Math.pow((A.y - C.y), 2));
643                     var c = Math.sqrt(Math.pow((A.x - B.x), 2) + Math.pow((A.y - B.y), 2));
644                     var theta = ((a * a) + (c * c) - (b * b)) / (2 * a * c);
645                     var theta = Math.acos(theta) * (180 / cc.PI);
646                     tip.startAngle = theta;
647                     tip.startRot = tip.target.getRotation();
648                 });
649                 tip.find('.CCTipScale').addEventListener('mousedown', function (e) {
650                     tip.mode = 'scale';
651                     tip.initialpos = {x:e.clientX, y:e.clientY};
652                     tip.mouseDown = true;
653                 });
654                 tip.find('.CCTipSkew').addEventListener('mousedown', function (e) {
655                     tip.mode = 'skew';
656                     tip.initialpos = {x:e.clientX, y:e.clientY};
657                     tip.mouseDown = true;
658                 });
659                 document.body.addEventListener('mousemove', function (e) {
660                     if (tip.mode == 'move') {
661                         var movex = e.clientX - tip.initialpos.x;
662                         var movey = e.clientY - tip.initialpos.y;
663                         var nodepos = tip.target.getPosition();
664                         tip.target.setPosition(movex + nodepos.x, -movey + nodepos.y);
665                         tip.initialpos = {x:e.clientX, y:e.clientY};
666                         tip.updateNumbers();
667                     }
668                     else if (tip.mode == 'rot') {
669                         //get the third point position
670                         var C = {x:e.x, y:e.y};
671                         var A = tip.startPos;
672                         var B = tip.nodepos;
673                         var a = Math.sqrt(Math.pow((B.x - C.x), 2) + Math.pow((B.y - C.y), 2));
674                         var b = Math.sqrt(Math.pow((A.x - C.x), 2) + Math.pow((A.y - C.y), 2));
675                         var c = Math.sqrt(Math.pow((A.x - B.x), 2) + Math.pow((A.y - B.y), 2));
676                         var theta = ((a * a) + (c * c) - (b * b)) / (2 * a * c);
677                         var theta = Math.acos(theta) * (180 / cc.PI);
678                         //console.log({a:a,b:b,c:c,A:A,B:B,C:C});
679 
680 
681                         //get current mouse
682                         var movey = e.clientY - tip.initialpos.y;
683                         var movex = e.clientX - tip.initialpos.x;
684                         if (e.y > tip.startPos.y) {
685                             tip.target.setRotation(-theta + tip.startRot);
686                         }
687                         else {
688                             tip.target.setRotation(theta + tip.startRot);
689                         }
690                         tip.updateNumbers();
691                     }
692                     else if (tip.mode == 'scale') {
693                         //find out the position of cc.canvas
694                         //find out the bottom left position of cc.canvas
695                         //add the position of the element from canvas bottom left
696                         var movey = e.clientY - tip.initialpos.y;
697                         var movex = e.clientX - tip.initialpos.x;
698                         var nodescalex = tip.target.getScaleX();
699                         var nodescaley = tip.target.getScaleY();
700                         tip.target.setScale(nodescalex - (movex / 150), nodescaley + (movey / 150));
701                         tip.initialpos = {x:e.clientX, y:e.clientY};
702                         tip.updateNumbers();
703                     }
704                     else if (tip.mode == 'skew') {
705                         var movey = e.clientY - tip.initialpos.y;
706                         var movex = e.clientX - tip.initialpos.x;
707                         var nodeskewx = tip.target.getSkewX();
708                         var nodeskewy = tip.target.getSkewY();
709                         tip.target.setSkewX(nodeskewx - (movex / 4));
710                         tip.target.setSkewY(nodeskewy + (movey / 4));
711                         tip.initialpos = {x:e.clientX, y:e.clientY};
712                         tip.updateNumbers();
713                     }
714                 });
715                 tip.find('#CCCloseButton').addEventListener('click', function () {
716                     tip.mode = null;
717                     tip.style.display = 'none';
718                     tip.mouseDown = false;
719                 });
720                 document.addEventListener('mouseup', function () {
721                     tip.mode = null;
722                     tip.mouseDown = false;
723                 });
724             }
725             args[i].dom.ccnode = args[i];
726             var that = args[i];
727             args[i].dom.addEventListener('mouseover', function () {
728                 this.style.zIndex = 999999;
729 
730                 if(this.showTooltipDiv !== undefined && this.showTooltipDiv === false)
731                     return;
732 
733                 if (!cc.DOM.tooltip.mouseDown) {
734                     var pos = cc.$.findpos(this);
735                     cc.DOM.tooltip.style.display = 'block';
736                     cc.DOM.tooltip.prependTo(this);
737                     cc.DOM.tooltip.target = that;
738                     this.style.zIndex = 999999;
739                     cc.DOM.tooltip.updateNumbers();
740                 }
741             });
742             args[i].dom.addEventListener('mouseout', function () {
743                 this.style.zIndex = this.ccnode._zOrder;
744             });
745         }
746     }
747 };