Region.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /**
  2. * This class represents a rectangular region in X,Y space, and performs geometric
  3. * transformations or tests upon the region.
  4. *
  5. * This class may be used to compare the document regions occupied by elements.
  6. */
  7. Ext.define('Ext.util.Region', {
  8. /* Begin Definitions */
  9. requires: ['Ext.util.Offset'],
  10. statics: {
  11. /**
  12. * @static
  13. * Retrieves an Ext.util.Region for a particular element.
  14. * @param {String/HTMLElement/Ext.Element} el An element ID, htmlElement or Ext.Element representing an element in the document.
  15. * @returns {Ext.util.Region} region
  16. */
  17. getRegion: function(el) {
  18. return Ext.fly(el).getPageBox(true);
  19. },
  20. /**
  21. * @static
  22. * Creates a Region from a "box" Object which contains four numeric properties `top`, `right`, `bottom` and `left`.
  23. * @param {Object} o An object with `top`, `right`, `bottom` and `left` properties.
  24. * @return {Ext.util.Region} region The Region constructed based on the passed object
  25. */
  26. from: function(o) {
  27. return new this(o.top, o.right, o.bottom, o.left);
  28. }
  29. },
  30. /* End Definitions */
  31. /**
  32. * Creates a region from the bounding sides.
  33. * @param {Number} top Top The topmost pixel of the Region.
  34. * @param {Number} right Right The rightmost pixel of the Region.
  35. * @param {Number} bottom Bottom The bottom pixel of the Region.
  36. * @param {Number} left Left The leftmost pixel of the Region.
  37. */
  38. constructor : function(t, r, b, l) {
  39. var me = this;
  40. me.y = me.top = me[1] = t;
  41. me.right = r;
  42. me.bottom = b;
  43. me.x = me.left = me[0] = l;
  44. },
  45. /**
  46. * Checks if this region completely contains the region that is passed in.
  47. * @param {Ext.util.Region} region
  48. * @return {Boolean}
  49. */
  50. contains : function(region) {
  51. var me = this;
  52. return (region.x >= me.x &&
  53. region.right <= me.right &&
  54. region.y >= me.y &&
  55. region.bottom <= me.bottom);
  56. },
  57. /**
  58. * Checks if this region intersects the region passed in.
  59. * @param {Ext.util.Region} region
  60. * @return {Ext.util.Region/Boolean} Returns the intersected region or false if there is no intersection.
  61. */
  62. intersect : function(region) {
  63. var me = this,
  64. t = Math.max(me.y, region.y),
  65. r = Math.min(me.right, region.right),
  66. b = Math.min(me.bottom, region.bottom),
  67. l = Math.max(me.x, region.x);
  68. if (b > t && r > l) {
  69. return new this.self(t, r, b, l);
  70. }
  71. else {
  72. return false;
  73. }
  74. },
  75. /**
  76. * Returns the smallest region that contains the current AND targetRegion.
  77. * @param {Ext.util.Region} region
  78. * @return {Ext.util.Region} a new region
  79. */
  80. union : function(region) {
  81. var me = this,
  82. t = Math.min(me.y, region.y),
  83. r = Math.max(me.right, region.right),
  84. b = Math.max(me.bottom, region.bottom),
  85. l = Math.min(me.x, region.x);
  86. return new this.self(t, r, b, l);
  87. },
  88. /**
  89. * Modifies the current region to be constrained to the targetRegion.
  90. * @param {Ext.util.Region} targetRegion
  91. * @return {Ext.util.Region} this
  92. */
  93. constrainTo : function(r) {
  94. var me = this,
  95. constrain = Ext.Number.constrain;
  96. me.top = me.y = constrain(me.top, r.y, r.bottom);
  97. me.bottom = constrain(me.bottom, r.y, r.bottom);
  98. me.left = me.x = constrain(me.left, r.x, r.right);
  99. me.right = constrain(me.right, r.x, r.right);
  100. return me;
  101. },
  102. /**
  103. * Modifies the current region to be adjusted by offsets.
  104. * @param {Number} top top offset
  105. * @param {Number} right right offset
  106. * @param {Number} bottom bottom offset
  107. * @param {Number} left left offset
  108. * @return {Ext.util.Region} this
  109. */
  110. adjust : function(t, r, b, l) {
  111. var me = this;
  112. me.top = me.y += t;
  113. me.left = me.x += l;
  114. me.right += r;
  115. me.bottom += b;
  116. return me;
  117. },
  118. /**
  119. * Get the offset amount of a point outside the region
  120. * @param {String} [axis]
  121. * @param {Ext.util.Point} [p] the point
  122. * @return {Ext.util.Offset}
  123. */
  124. getOutOfBoundOffset: function(axis, p) {
  125. if (!Ext.isObject(axis)) {
  126. if (axis == 'x') {
  127. return this.getOutOfBoundOffsetX(p);
  128. } else {
  129. return this.getOutOfBoundOffsetY(p);
  130. }
  131. } else {
  132. p = axis;
  133. var d = new Ext.util.Offset();
  134. d.x = this.getOutOfBoundOffsetX(p.x);
  135. d.y = this.getOutOfBoundOffsetY(p.y);
  136. return d;
  137. }
  138. },
  139. /**
  140. * Get the offset amount on the x-axis
  141. * @param {Number} p the offset
  142. * @return {Number}
  143. */
  144. getOutOfBoundOffsetX: function(p) {
  145. if (p <= this.x) {
  146. return this.x - p;
  147. } else if (p >= this.right) {
  148. return this.right - p;
  149. }
  150. return 0;
  151. },
  152. /**
  153. * Get the offset amount on the y-axis
  154. * @param {Number} p the offset
  155. * @return {Number}
  156. */
  157. getOutOfBoundOffsetY: function(p) {
  158. if (p <= this.y) {
  159. return this.y - p;
  160. } else if (p >= this.bottom) {
  161. return this.bottom - p;
  162. }
  163. return 0;
  164. },
  165. /**
  166. * Check whether the point / offset is out of bound
  167. * @param {String} [axis]
  168. * @param {Ext.util.Point/Number} [p] the point / offset
  169. * @return {Boolean}
  170. */
  171. isOutOfBound: function(axis, p) {
  172. if (!Ext.isObject(axis)) {
  173. if (axis == 'x') {
  174. return this.isOutOfBoundX(p);
  175. } else {
  176. return this.isOutOfBoundY(p);
  177. }
  178. } else {
  179. p = axis;
  180. return (this.isOutOfBoundX(p.x) || this.isOutOfBoundY(p.y));
  181. }
  182. },
  183. /**
  184. * Check whether the offset is out of bound in the x-axis
  185. * @param {Number} p the offset
  186. * @return {Boolean}
  187. */
  188. isOutOfBoundX: function(p) {
  189. return (p < this.x || p > this.right);
  190. },
  191. /**
  192. * Check whether the offset is out of bound in the y-axis
  193. * @param {Number} p the offset
  194. * @return {Boolean}
  195. */
  196. isOutOfBoundY: function(p) {
  197. return (p < this.y || p > this.bottom);
  198. },
  199. /**
  200. * Restrict a point within the region by a certain factor.
  201. * @param {String} [axis]
  202. * @param {Ext.util.Point/Ext.util.Offset/Object} [p]
  203. * @param {Number} [factor]
  204. * @return {Ext.util.Point/Ext.util.Offset/Object/Number}
  205. * @private
  206. */
  207. restrict: function(axis, p, factor) {
  208. if (Ext.isObject(axis)) {
  209. var newP;
  210. factor = p;
  211. p = axis;
  212. if (p.copy) {
  213. newP = p.copy();
  214. }
  215. else {
  216. newP = {
  217. x: p.x,
  218. y: p.y
  219. };
  220. }
  221. newP.x = this.restrictX(p.x, factor);
  222. newP.y = this.restrictY(p.y, factor);
  223. return newP;
  224. } else {
  225. if (axis == 'x') {
  226. return this.restrictX(p, factor);
  227. } else {
  228. return this.restrictY(p, factor);
  229. }
  230. }
  231. },
  232. /**
  233. * Restrict an offset within the region by a certain factor, on the x-axis
  234. * @param {Number} p
  235. * @param {Number} [factor=1] The factor.
  236. * @return {Number}
  237. * @private
  238. */
  239. restrictX : function(p, factor) {
  240. if (!factor) {
  241. factor = 1;
  242. }
  243. if (p <= this.x) {
  244. p -= (p - this.x) * factor;
  245. }
  246. else if (p >= this.right) {
  247. p -= (p - this.right) * factor;
  248. }
  249. return p;
  250. },
  251. /**
  252. * Restrict an offset within the region by a certain factor, on the y-axis
  253. * @param {Number} p
  254. * @param {Number} [factor] The factor, defaults to 1
  255. * @return {Number}
  256. * @private
  257. */
  258. restrictY : function(p, factor) {
  259. if (!factor) {
  260. factor = 1;
  261. }
  262. if (p <= this.y) {
  263. p -= (p - this.y) * factor;
  264. }
  265. else if (p >= this.bottom) {
  266. p -= (p - this.bottom) * factor;
  267. }
  268. return p;
  269. },
  270. /**
  271. * Get the width / height of this region
  272. * @return {Object} an object with width and height properties
  273. * @private
  274. */
  275. getSize: function() {
  276. return {
  277. width: this.right - this.x,
  278. height: this.bottom - this.y
  279. };
  280. },
  281. /**
  282. * Create a copy of this Region.
  283. * @return {Ext.util.Region}
  284. */
  285. copy: function() {
  286. return new this.self(this.y, this.right, this.bottom, this.x);
  287. },
  288. /**
  289. * Copy the values of another Region to this Region
  290. * @param {Ext.util.Region} p The region to copy from.
  291. * @return {Ext.util.Region} This Region
  292. */
  293. copyFrom: function(p) {
  294. var me = this;
  295. me.top = me.y = me[1] = p.y;
  296. me.right = p.right;
  297. me.bottom = p.bottom;
  298. me.left = me.x = me[0] = p.x;
  299. return this;
  300. },
  301. /*
  302. * Dump this to an eye-friendly string, great for debugging
  303. * @return {String}
  304. */
  305. toString: function() {
  306. return "Region[" + this.top + "," + this.right + "," + this.bottom + "," + this.left + "]";
  307. },
  308. /**
  309. * Translate this region by the given offset amount
  310. * @param {Ext.util.Offset/Object} x Object containing the `x` and `y` properties.
  311. * Or the x value is using the two argument form.
  312. * @param {Number} y The y value unless using an Offset object.
  313. * @return {Ext.util.Region} this This Region
  314. */
  315. translateBy: function(x, y) {
  316. if (arguments.length == 1) {
  317. y = x.y;
  318. x = x.x;
  319. }
  320. var me = this;
  321. me.top = me.y += y;
  322. me.right += x;
  323. me.bottom += y;
  324. me.left = me.x += x;
  325. return me;
  326. },
  327. /**
  328. * Round all the properties of this region
  329. * @return {Ext.util.Region} this This Region
  330. */
  331. round: function() {
  332. var me = this;
  333. me.top = me.y = Math.round(me.y);
  334. me.right = Math.round(me.right);
  335. me.bottom = Math.round(me.bottom);
  336. me.left = me.x = Math.round(me.x);
  337. return me;
  338. },
  339. /**
  340. * Check whether this region is equivalent to the given region
  341. * @param {Ext.util.Region} region The region to compare with
  342. * @return {Boolean}
  343. */
  344. equals: function(region) {
  345. return (this.top == region.top && this.right == region.right && this.bottom == region.bottom && this.left == region.left);
  346. }
  347. });