Resizer.html 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-resizer-Resizer'>/**
  19. </span> * Applies drag handles to an element or component to make it resizable. The drag handles are inserted into the element
  20. * (or component's element) and positioned absolute.
  21. *
  22. * Textarea and img elements will be wrapped with an additional div because these elements do not support child nodes.
  23. * The original element can be accessed through the originalTarget property.
  24. *
  25. * Here is the list of valid resize handles:
  26. *
  27. * Value Description
  28. * ------ -------------------
  29. * 'n' north
  30. * 's' south
  31. * 'e' east
  32. * 'w' west
  33. * 'nw' northwest
  34. * 'sw' southwest
  35. * 'se' southeast
  36. * 'ne' northeast
  37. * 'all' all
  38. *
  39. * {@img Ext.resizer.Resizer/Ext.resizer.Resizer.png Ext.resizer.Resizer component}
  40. *
  41. * Here's an example showing the creation of a typical Resizer:
  42. *
  43. * Ext.create('Ext.resizer.Resizer', {
  44. * el: 'elToResize',
  45. * handles: 'all',
  46. * minWidth: 200,
  47. * minHeight: 100,
  48. * maxWidth: 500,
  49. * maxHeight: 400,
  50. * pinned: true
  51. * });
  52. */
  53. Ext.define('Ext.resizer.Resizer', {
  54. mixins: {
  55. observable: 'Ext.util.Observable'
  56. },
  57. uses: ['Ext.resizer.ResizeTracker', 'Ext.Component'],
  58. alternateClassName: 'Ext.Resizable',
  59. handleCls: Ext.baseCSSPrefix + 'resizable-handle',
  60. pinnedCls: Ext.baseCSSPrefix + 'resizable-pinned',
  61. overCls: Ext.baseCSSPrefix + 'resizable-over',
  62. wrapCls: Ext.baseCSSPrefix + 'resizable-wrap',
  63. <span id='Ext-resizer-Resizer-cfg-dynamic'> /**
  64. </span> * @cfg {Boolean} dynamic
  65. * Specify as true to update the {@link #target} (Element or {@link Ext.Component Component}) dynamically during
  66. * dragging. This is `true` by default, but the {@link Ext.Component Component} class passes `false` when it is
  67. * configured as {@link Ext.Component#resizable}.
  68. *
  69. * If specified as `false`, a proxy element is displayed during the resize operation, and the {@link #target} is
  70. * updated on mouseup.
  71. */
  72. dynamic: true,
  73. <span id='Ext-resizer-Resizer-cfg-handles'> /**
  74. </span> * @cfg {String} handles
  75. * String consisting of the resize handles to display. Defaults to 's e se' for Elements and fixed position
  76. * Components. Defaults to 8 point resizing for floating Components (such as Windows). Specify either `'all'` or any
  77. * of `'n s e w ne nw se sw'`.
  78. */
  79. handles: 's e se',
  80. <span id='Ext-resizer-Resizer-cfg-height'> /**
  81. </span> * @cfg {Number} height
  82. * Optional. The height to set target to in pixels
  83. */
  84. height : null,
  85. <span id='Ext-resizer-Resizer-cfg-width'> /**
  86. </span> * @cfg {Number} width
  87. * Optional. The width to set the target to in pixels
  88. */
  89. width : null,
  90. <span id='Ext-resizer-Resizer-cfg-heightIncrement'> /**
  91. </span> * @cfg {Number} heightIncrement
  92. * The increment to snap the height resize in pixels.
  93. */
  94. heightIncrement : 0,
  95. <span id='Ext-resizer-Resizer-cfg-widthIncrement'> /**
  96. </span> * @cfg {Number} widthIncrement
  97. * The increment to snap the width resize in pixels.
  98. */
  99. widthIncrement : 0,
  100. <span id='Ext-resizer-Resizer-cfg-minHeight'> /**
  101. </span> * @cfg {Number} minHeight
  102. * The minimum height for the element
  103. */
  104. minHeight : 20,
  105. <span id='Ext-resizer-Resizer-cfg-minWidth'> /**
  106. </span> * @cfg {Number} minWidth
  107. * The minimum width for the element
  108. */
  109. minWidth : 20,
  110. <span id='Ext-resizer-Resizer-cfg-maxHeight'> /**
  111. </span> * @cfg {Number} maxHeight
  112. * The maximum height for the element
  113. */
  114. maxHeight : 10000,
  115. <span id='Ext-resizer-Resizer-cfg-maxWidth'> /**
  116. </span> * @cfg {Number} maxWidth
  117. * The maximum width for the element
  118. */
  119. maxWidth : 10000,
  120. <span id='Ext-resizer-Resizer-cfg-pinned'> /**
  121. </span> * @cfg {Boolean} pinned
  122. * True to ensure that the resize handles are always visible, false indicates resizing by cursor changes only
  123. */
  124. pinned: false,
  125. <span id='Ext-resizer-Resizer-cfg-preserveRatio'> /**
  126. </span> * @cfg {Boolean} preserveRatio
  127. * True to preserve the original ratio between height and width during resize
  128. */
  129. preserveRatio: false,
  130. <span id='Ext-resizer-Resizer-cfg-transparent'> /**
  131. </span> * @cfg {Boolean} transparent
  132. * True for transparent handles. This is only applied at config time.
  133. */
  134. transparent: false,
  135. <span id='Ext-resizer-Resizer-cfg-constrainTo'> /**
  136. </span> * @cfg {Ext.Element/Ext.util.Region} constrainTo
  137. * An element, or a {@link Ext.util.Region Region} into which the resize operation must be constrained.
  138. */
  139. possiblePositions: {
  140. n: 'north',
  141. s: 'south',
  142. e: 'east',
  143. w: 'west',
  144. se: 'southeast',
  145. sw: 'southwest',
  146. nw: 'northwest',
  147. ne: 'northeast'
  148. },
  149. <span id='Ext-resizer-Resizer-cfg-target'> /**
  150. </span> * @cfg {Ext.Element/Ext.Component} target
  151. * The Element or Component to resize.
  152. */
  153. <span id='Ext-resizer-Resizer-property-el'> /**
  154. </span> * @property {Ext.Element} el
  155. * Outer element for resizing behavior.
  156. */
  157. constructor: function(config) {
  158. var me = this,
  159. target,
  160. targetEl,
  161. tag,
  162. handles = me.handles,
  163. handleCls,
  164. possibles,
  165. len,
  166. i = 0,
  167. pos,
  168. handleEls = [],
  169. eastWestStyle, style,
  170. box;
  171. me.addEvents(
  172. <span id='Ext-resizer-Resizer-event-beforeresize'> /**
  173. </span> * @event beforeresize
  174. * Fired before resize is allowed. Return false to cancel resize.
  175. * @param {Ext.resizer.Resizer} this
  176. * @param {Number} width The start width
  177. * @param {Number} height The start height
  178. * @param {Ext.EventObject} e The mousedown event
  179. */
  180. 'beforeresize',
  181. <span id='Ext-resizer-Resizer-event-resizedrag'> /**
  182. </span> * @event resizedrag
  183. * Fires during resizing. Return false to cancel resize.
  184. * @param {Ext.resizer.Resizer} this
  185. * @param {Number} width The new width
  186. * @param {Number} height The new height
  187. * @param {Ext.EventObject} e The mousedown event
  188. */
  189. 'resizedrag',
  190. <span id='Ext-resizer-Resizer-event-resize'> /**
  191. </span> * @event resize
  192. * Fired after a resize.
  193. * @param {Ext.resizer.Resizer} this
  194. * @param {Number} width The new width
  195. * @param {Number} height The new height
  196. * @param {Ext.EventObject} e The mouseup event
  197. */
  198. 'resize'
  199. );
  200. if (Ext.isString(config) || Ext.isElement(config) || config.dom) {
  201. target = config;
  202. config = arguments[1] || {};
  203. config.target = target;
  204. }
  205. // will apply config to this
  206. me.mixins.observable.constructor.call(me, config);
  207. // If target is a Component, ensure that we pull the element out.
  208. // Resizer must examine the underlying Element.
  209. target = me.target;
  210. if (target) {
  211. if (target.isComponent) {
  212. me.el = target.getEl();
  213. if (target.minWidth) {
  214. me.minWidth = target.minWidth;
  215. }
  216. if (target.minHeight) {
  217. me.minHeight = target.minHeight;
  218. }
  219. if (target.maxWidth) {
  220. me.maxWidth = target.maxWidth;
  221. }
  222. if (target.maxHeight) {
  223. me.maxHeight = target.maxHeight;
  224. }
  225. if (target.floating) {
  226. if (!me.hasOwnProperty('handles')) {
  227. me.handles = 'n ne e se s sw w nw';
  228. }
  229. }
  230. } else {
  231. me.el = me.target = Ext.get(target);
  232. }
  233. }
  234. // Backwards compatibility with Ext3.x's Resizable which used el as a config.
  235. else {
  236. me.target = me.el = Ext.get(me.el);
  237. }
  238. // Tags like textarea and img cannot
  239. // have children and therefore must
  240. // be wrapped
  241. tag = me.el.dom.tagName.toUpperCase();
  242. if (tag == 'TEXTAREA' || tag == 'IMG' || tag == 'TABLE') {
  243. <span id='Ext-resizer-Resizer-property-originalTarget'> /**
  244. </span> * @property {Ext.Element/Ext.Component} originalTarget
  245. * Reference to the original resize target if the element of the original resize target was a
  246. * {@link Ext.form.field.Field Field}, or an IMG or a TEXTAREA which must be wrapped in a DIV.
  247. */
  248. me.originalTarget = me.target;
  249. targetEl = me.el;
  250. box = targetEl.getBox();
  251. me.target = me.el = me.el.wrap({
  252. cls: me.wrapCls,
  253. id: me.el.id + '-rzwrap',
  254. style: targetEl.getStyles('margin-top', 'margin-bottom')
  255. });
  256. // Transfer originalTarget's positioning+sizing+margins
  257. me.el.setPositioning(targetEl.getPositioning());
  258. targetEl.clearPositioning();
  259. me.el.setBox(box);
  260. // Position the wrapped element absolute so that it does not stretch the wrapper
  261. targetEl.setStyle('position', 'absolute');
  262. }
  263. // Position the element, this enables us to absolute position
  264. // the handles within this.el
  265. me.el.position();
  266. if (me.pinned) {
  267. me.el.addCls(me.pinnedCls);
  268. }
  269. <span id='Ext-resizer-Resizer-property-resizeTracker'> /**
  270. </span> * @property {Ext.resizer.ResizeTracker} resizeTracker
  271. */
  272. me.resizeTracker = new Ext.resizer.ResizeTracker({
  273. disabled: me.disabled,
  274. target: me.target,
  275. constrainTo: me.constrainTo,
  276. overCls: me.overCls,
  277. throttle: me.throttle,
  278. originalTarget: me.originalTarget,
  279. delegate: '.' + me.handleCls,
  280. dynamic: me.dynamic,
  281. preserveRatio: me.preserveRatio,
  282. heightIncrement: me.heightIncrement,
  283. widthIncrement: me.widthIncrement,
  284. minHeight: me.minHeight,
  285. maxHeight: me.maxHeight,
  286. minWidth: me.minWidth,
  287. maxWidth: me.maxWidth
  288. });
  289. // Relay the ResizeTracker's superclass events as our own resize events
  290. me.resizeTracker.on({
  291. mousedown: me.onBeforeResize,
  292. drag: me.onResize,
  293. dragend: me.onResizeEnd,
  294. scope: me
  295. });
  296. if (me.handles == 'all') {
  297. me.handles = 'n s e w ne nw se sw';
  298. }
  299. handles = me.handles = me.handles.split(/ |\s*?[,;]\s*?/);
  300. possibles = me.possiblePositions;
  301. len = handles.length;
  302. handleCls = me.handleCls + ' ' + (me.target.isComponent ? (me.target.baseCls + '-handle ') : '') + me.handleCls + '-';
  303. // Needs heighting on IE6!
  304. eastWestStyle = Ext.isIE6 ? ' style=&quot;height:' + me.el.getHeight() + 'px&quot;' : '';
  305. for (; i &lt; len; i++){
  306. // if specified and possible, create
  307. if (handles[i] &amp;&amp; possibles[handles[i]]) {
  308. pos = possibles[handles[i]];
  309. if (pos === 'east' || pos === 'west') {
  310. style = eastWestStyle;
  311. } else {
  312. style = '';
  313. }
  314. handleEls.push('&lt;div id=&quot;' + me.el.id + '-' + pos + '-handle&quot; class=&quot;' + handleCls + pos + ' ' + Ext.baseCSSPrefix + 'unselectable&quot;' + style + '&gt;&lt;/div&gt;');
  315. }
  316. }
  317. Ext.DomHelper.append(me.el, handleEls.join(''));
  318. // store a reference to each handle elelemtn in this.east, this.west, etc
  319. for (i = 0; i &lt; len; i++){
  320. // if specified and possible, create
  321. if (handles[i] &amp;&amp; possibles[handles[i]]) {
  322. pos = possibles[handles[i]];
  323. me[pos] = me.el.getById(me.el.id + '-' + pos + '-handle');
  324. me[pos].region = pos;
  325. me[pos].unselectable();
  326. if (me.transparent) {
  327. me[pos].setOpacity(0);
  328. }
  329. }
  330. }
  331. // Constrain within configured maxima
  332. if (Ext.isNumber(me.width)) {
  333. me.width = Ext.Number.constrain(me.width, me.minWidth, me.maxWidth);
  334. }
  335. if (Ext.isNumber(me.height)) {
  336. me.height = Ext.Number.constrain(me.height, me.minHeight, me.maxHeight);
  337. }
  338. // Size the target (and originalTarget)
  339. if (me.width !== null || me.height !== null) {
  340. if (me.originalTarget) {
  341. me.originalTarget.setWidth(me.width);
  342. me.originalTarget.setHeight(me.height);
  343. }
  344. me.resizeTo(me.width, me.height);
  345. }
  346. me.forceHandlesHeight();
  347. },
  348. disable: function() {
  349. this.resizeTracker.disable();
  350. },
  351. enable: function() {
  352. this.resizeTracker.enable();
  353. },
  354. <span id='Ext-resizer-Resizer-method-onBeforeResize'> /**
  355. </span> * @private Relay the Tracker's mousedown event as beforeresize
  356. * @param tracker The Resizer
  357. * @param e The Event
  358. */
  359. onBeforeResize: function(tracker, e) {
  360. var box = this.el.getBox();
  361. return this.fireEvent('beforeresize', this, box.width, box.height, e);
  362. },
  363. <span id='Ext-resizer-Resizer-method-onResize'> /**
  364. </span> * @private Relay the Tracker's drag event as resizedrag
  365. * @param tracker The Resizer
  366. * @param e The Event
  367. */
  368. onResize: function(tracker, e) {
  369. var me = this,
  370. box = me.el.getBox();
  371. me.forceHandlesHeight();
  372. return me.fireEvent('resizedrag', me, box.width, box.height, e);
  373. },
  374. <span id='Ext-resizer-Resizer-method-onResizeEnd'> /**
  375. </span> * @private Relay the Tracker's dragend event as resize
  376. * @param tracker The Resizer
  377. * @param e The Event
  378. */
  379. onResizeEnd: function(tracker, e) {
  380. var me = this,
  381. box = me.el.getBox();
  382. me.forceHandlesHeight();
  383. return me.fireEvent('resize', me, box.width, box.height, e);
  384. },
  385. <span id='Ext-resizer-Resizer-method-resizeTo'> /**
  386. </span> * Perform a manual resize and fires the 'resize' event.
  387. * @param {Number} width
  388. * @param {Number} height
  389. */
  390. resizeTo : function(width, height) {
  391. var me = this;
  392. me.target.setSize(width, height);
  393. me.fireEvent('resize', me, width, height, null);
  394. },
  395. <span id='Ext-resizer-Resizer-method-getEl'> /**
  396. </span> * Returns the element that was configured with the el or target config property. If a component was configured with
  397. * the target property then this will return the element of this component.
  398. *
  399. * Textarea and img elements will be wrapped with an additional div because these elements do not support child
  400. * nodes. The original element can be accessed through the originalTarget property.
  401. * @return {Ext.Element} element
  402. */
  403. getEl : function() {
  404. return this.el;
  405. },
  406. <span id='Ext-resizer-Resizer-method-getTarget'> /**
  407. </span> * Returns the element or component that was configured with the target config property.
  408. *
  409. * Textarea and img elements will be wrapped with an additional div because these elements do not support child
  410. * nodes. The original element can be accessed through the originalTarget property.
  411. * @return {Ext.Element/Ext.Component}
  412. */
  413. getTarget: function() {
  414. return this.target;
  415. },
  416. destroy: function() {
  417. var i = 0,
  418. handles = this.handles,
  419. len = handles.length,
  420. positions = this.possiblePositions;
  421. for (; i &lt; len; i++) {
  422. this[positions[handles[i]]].remove();
  423. }
  424. },
  425. <span id='Ext-resizer-Resizer-method-forceHandlesHeight'> /**
  426. </span> * @private
  427. * Fix IE6 handle height issue.
  428. */
  429. forceHandlesHeight : function() {
  430. var me = this,
  431. handle;
  432. if (Ext.isIE6) {
  433. handle = me.east;
  434. if (handle) {
  435. handle.setHeight(me.el.getHeight());
  436. }
  437. handle = me.west;
  438. if (handle) {
  439. handle.setHeight(me.el.getHeight());
  440. }
  441. me.el.repaint();
  442. }
  443. }
  444. });
  445. </pre>
  446. </body>
  447. </html>