Movable.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /**
  2. * Movable.js
  3. *
  4. * Copyright, Moxiecode Systems AB
  5. * Released under LGPL License.
  6. *
  7. * License: http://www.tinymce.com/license
  8. * Contributing: http://www.tinymce.com/contributing
  9. */
  10. /**
  11. * Movable mixin. Makes controls movable absolute and relative to other elements.
  12. *
  13. * @mixin tinymce.ui.Movable
  14. */
  15. define("tinymce/ui/Movable", [
  16. "tinymce/ui/DomUtils"
  17. ], function(DomUtils) {
  18. "use strict";
  19. function calculateRelativePosition(ctrl, targetElm, rel) {
  20. var ctrlElm, pos, x, y, selfW, selfH, targetW, targetH, viewport, size;
  21. viewport = DomUtils.getViewPort();
  22. // Get pos of target
  23. pos = DomUtils.getPos(targetElm);
  24. x = pos.x;
  25. y = pos.y;
  26. if (ctrl._fixed) {
  27. x -= viewport.x;
  28. y -= viewport.y;
  29. }
  30. // Get size of self
  31. ctrlElm = ctrl.getEl();
  32. size = DomUtils.getSize(ctrlElm);
  33. selfW = size.width;
  34. selfH = size.height;
  35. // Get size of target
  36. size = DomUtils.getSize(targetElm);
  37. targetW = size.width;
  38. targetH = size.height;
  39. // Parse align string
  40. rel = (rel || '').split('');
  41. // Target corners
  42. if (rel[0] === 'b') {
  43. y += targetH;
  44. }
  45. if (rel[1] === 'r') {
  46. x += targetW;
  47. }
  48. if (rel[0] === 'c') {
  49. y += Math.round(targetH / 2);
  50. }
  51. if (rel[1] === 'c') {
  52. x += Math.round(targetW / 2);
  53. }
  54. // Self corners
  55. if (rel[3] === 'b') {
  56. y -= selfH;
  57. }
  58. if (rel[4] === 'r') {
  59. x -= selfW;
  60. }
  61. if (rel[3] === 'c') {
  62. y -= Math.round(selfH / 2);
  63. }
  64. if (rel[4] === 'c') {
  65. x -= Math.round(selfW / 2);
  66. }
  67. return {
  68. x: x,
  69. y: y,
  70. w: selfW,
  71. h: selfH
  72. };
  73. }
  74. return {
  75. /**
  76. * Tests various positions to get the most suitable one.
  77. *
  78. * @method testMoveRel
  79. * @param {DOMElement} elm Element to position against.
  80. * @param {Array} rels Array with relative positions.
  81. * @return {String} Best suitable relative position.
  82. */
  83. testMoveRel: function(elm, rels) {
  84. var viewPortRect = DomUtils.getViewPort();
  85. for (var i = 0; i < rels.length; i++) {
  86. var pos = calculateRelativePosition(this, elm, rels[i]);
  87. if (this._fixed) {
  88. if (pos.x > 0 && pos.x + pos.w < viewPortRect.w && pos.y > 0 && pos.y + pos.h < viewPortRect.h) {
  89. return rels[i];
  90. }
  91. } else {
  92. if (pos.x > viewPortRect.x && pos.x + pos.w < viewPortRect.w + viewPortRect.x &&
  93. pos.y > viewPortRect.y && pos.y + pos.h < viewPortRect.h + viewPortRect.y) {
  94. return rels[i];
  95. }
  96. }
  97. }
  98. return rels[0];
  99. },
  100. /**
  101. * Move relative to the specified element.
  102. *
  103. * @method moveRel
  104. * @param {Element} elm Element to move relative to.
  105. * @param {String} rel Relative mode. For example: br-tl.
  106. * @return {tinymce.ui.Control} Current control instance.
  107. */
  108. moveRel: function(elm, rel) {
  109. if (typeof(rel) != 'string') {
  110. rel = this.testMoveRel(elm, rel);
  111. }
  112. var pos = calculateRelativePosition(this, elm, rel);
  113. return this.moveTo(pos.x, pos.y);
  114. },
  115. /**
  116. * Move by a relative x, y values.
  117. *
  118. * @method moveBy
  119. * @param {Number} dx Relative x position.
  120. * @param {Number} dy Relative y position.
  121. * @return {tinymce.ui.Control} Current control instance.
  122. */
  123. moveBy: function(dx, dy) {
  124. var self = this, rect = self.layoutRect();
  125. self.moveTo(rect.x + dx, rect.y + dy);
  126. return self;
  127. },
  128. /**
  129. * Move to absolute position.
  130. *
  131. * @method moveTo
  132. * @param {Number} x Absolute x position.
  133. * @param {Number} y Absolute y position.
  134. * @return {tinymce.ui.Control} Current control instance.
  135. */
  136. moveTo: function(x, y) {
  137. var self = this;
  138. // TODO: Move this to some global class
  139. function contrain(value, max, size) {
  140. if (value < 0) {
  141. return 0;
  142. }
  143. if (value + size > max) {
  144. value = max - size;
  145. return value < 0 ? 0 : value;
  146. }
  147. return value;
  148. }
  149. if (self.settings.constrainToViewport) {
  150. var viewPortRect = DomUtils.getViewPort(window);
  151. var layoutRect = self.layoutRect();
  152. x = contrain(x, viewPortRect.w + viewPortRect.x, layoutRect.w);
  153. y = contrain(y, viewPortRect.h + viewPortRect.y, layoutRect.h);
  154. }
  155. if (self._rendered) {
  156. self.layoutRect({x: x, y: y}).repaint();
  157. } else {
  158. self.settings.x = x;
  159. self.settings.y = y;
  160. }
  161. self.fire('move', {x: x, y: y});
  162. return self;
  163. }
  164. };
  165. });