ZIndexManager.html 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  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-ZIndexManager'>/**
  19. </span> * A class that manages a group of {@link Ext.Component#floating} Components and provides z-order management,
  20. * and Component activation behavior, including masking below the active (topmost) Component.
  21. *
  22. * {@link Ext.Component#floating Floating} Components which are rendered directly into the document (such as
  23. * {@link Ext.window.Window Window}s) which are {@link Ext.Component#method-show show}n are managed by a
  24. * {@link Ext.WindowManager global instance}.
  25. *
  26. * {@link Ext.Component#floating Floating} Components which are descendants of {@link Ext.Component#floating floating}
  27. * *Containers* (for example a {@link Ext.view.BoundList BoundList} within an {@link Ext.window.Window Window},
  28. * or a {@link Ext.menu.Menu Menu}), are managed by a ZIndexManager owned by that floating Container. Therefore
  29. * ComboBox dropdowns within Windows will have managed z-indices guaranteed to be correct, relative to the Window.
  30. */
  31. Ext.define('Ext.ZIndexManager', {
  32. alternateClassName: 'Ext.WindowGroup',
  33. statics: {
  34. zBase : 9000
  35. },
  36. constructor: function(container) {
  37. var me = this;
  38. me.list = {};
  39. me.zIndexStack = [];
  40. me.front = null;
  41. if (container) {
  42. // This is the ZIndexManager for an Ext.container.Container, base its zseed on the zIndex of the Container's element
  43. if (container.isContainer) {
  44. container.on('resize', me._onContainerResize, me);
  45. me.zseed = Ext.Number.from(me.rendered ? container.getEl().getStyle('zIndex') : undefined, me.getNextZSeed());
  46. // The containing element we will be dealing with (eg masking) is the content target
  47. me.targetEl = container.getTargetEl();
  48. me.container = container;
  49. }
  50. // This is the ZIndexManager for a DOM element
  51. else {
  52. Ext.EventManager.onWindowResize(me._onContainerResize, me);
  53. me.zseed = me.getNextZSeed();
  54. me.targetEl = Ext.get(container);
  55. }
  56. }
  57. // No container passed means we are the global WindowManager. Our target is the doc body.
  58. // DOM must be ready to collect that ref.
  59. else {
  60. Ext.EventManager.onWindowResize(me._onContainerResize, me);
  61. me.zseed = me.getNextZSeed();
  62. Ext.onDocumentReady(function() {
  63. me.targetEl = Ext.getBody();
  64. });
  65. }
  66. },
  67. getNextZSeed: function() {
  68. return (Ext.ZIndexManager.zBase += 10000);
  69. },
  70. setBase: function(baseZIndex) {
  71. this.zseed = baseZIndex;
  72. var result = this.assignZIndices();
  73. this._activateLast();
  74. return result;
  75. },
  76. // private
  77. assignZIndices: function() {
  78. var a = this.zIndexStack,
  79. len = a.length,
  80. i = 0,
  81. zIndex = this.zseed,
  82. comp;
  83. for (; i &lt; len; i++) {
  84. comp = a[i];
  85. if (comp &amp;&amp; !comp.hidden) {
  86. // Setting the zIndex of a Component returns the topmost zIndex consumed by
  87. // that Component.
  88. // If it's just a plain floating Component such as a BoundList, then the
  89. // return value is the passed value plus 10, ready for the next item.
  90. // If a floating *Container* has its zIndex set, it re-orders its managed
  91. // floating children, starting from that new base, and returns a value 10000 above
  92. // the highest zIndex which it allocates.
  93. zIndex = comp.setZIndex(zIndex);
  94. }
  95. }
  96. // Activate new topmost
  97. this._activateLast();
  98. return zIndex;
  99. },
  100. // private
  101. _setActiveChild: function(comp, oldFront) {
  102. var front = this.front;
  103. if (comp !== front) {
  104. if (front &amp;&amp; !front.destroying) {
  105. front.setActive(false, comp);
  106. }
  107. this.front = comp;
  108. if (comp &amp;&amp; comp != oldFront) {
  109. comp.setActive(true);
  110. if (comp.modal) {
  111. this._showModalMask(comp);
  112. }
  113. }
  114. }
  115. },
  116. onComponentHide: function(comp){
  117. comp.setActive(false);
  118. this._activateLast();
  119. },
  120. // private
  121. _activateLast: function() {
  122. var me = this,
  123. stack = me.zIndexStack,
  124. i = stack.length - 1,
  125. oldFront = me.front,
  126. comp;
  127. // There may be no visible floater to activate
  128. me.front = undefined;
  129. // Go down through the z-index stack.
  130. // Activate the next visible one down.
  131. // If that was modal, then we're done
  132. for (; i &gt;= 0 &amp;&amp; stack[i].hidden; --i);
  133. if ((comp = stack[i])) {
  134. me._setActiveChild(comp, oldFront);
  135. if (comp.modal) {
  136. return;
  137. }
  138. }
  139. // If the new top one was not modal, keep going down to find the next visible
  140. // modal one to shift the modal mask down under
  141. for (; i &gt;= 0; --i) {
  142. comp = stack[i];
  143. // If we find a visible modal further down the zIndex stack, move the mask to just under it.
  144. if (comp.isVisible() &amp;&amp; comp.modal) {
  145. me._showModalMask(comp);
  146. return;
  147. }
  148. }
  149. // No visible modal Component was found in the run down the stack.
  150. // So hide the modal mask
  151. me._hideModalMask();
  152. },
  153. _showModalMask: function(comp) {
  154. var me = this,
  155. zIndex = comp.el.getStyle('zIndex') - 4,
  156. maskTarget = comp.floatParent ? comp.floatParent.getTargetEl() : comp.container,
  157. viewSize = maskTarget.getBox();
  158. if (maskTarget.dom === document.body) {
  159. viewSize.height = Math.max(document.body.scrollHeight, Ext.dom.Element.getDocumentHeight());
  160. viewSize.width = Math.max(document.body.scrollWidth, viewSize.width);
  161. }
  162. if (!me.mask) {
  163. me.mask = Ext.getBody().createChild({
  164. cls: Ext.baseCSSPrefix + 'mask'
  165. });
  166. me.mask.setVisibilityMode(Ext.Element.DISPLAY);
  167. me.mask.on('click', me._onMaskClick, me);
  168. }
  169. me.mask.maskTarget = maskTarget;
  170. maskTarget.addCls(Ext.baseCSSPrefix + 'body-masked');
  171. me.mask.setStyle('zIndex', zIndex);
  172. // setting mask box before showing it in an IE7 strict iframe within a quirks page
  173. // can cause body scrolling [EXTJSIV-6219]
  174. me.mask.show();
  175. me.mask.setBox(viewSize);
  176. },
  177. _hideModalMask: function() {
  178. var mask = this.mask;
  179. if (mask &amp;&amp; mask.isVisible()) {
  180. mask.maskTarget.removeCls(Ext.baseCSSPrefix + 'body-masked');
  181. mask.maskTarget = undefined;
  182. mask.hide();
  183. }
  184. },
  185. _onMaskClick: function() {
  186. if (this.front) {
  187. this.front.focus();
  188. }
  189. },
  190. _onContainerResize: function() {
  191. var mask = this.mask,
  192. maskTarget,
  193. viewSize;
  194. if (mask &amp;&amp; mask.isVisible()) {
  195. // At the new container size, the mask might be *causing* the scrollbar, so to find the valid
  196. // client size to mask, we must temporarily unmask the parent node.
  197. mask.hide();
  198. maskTarget = mask.maskTarget;
  199. if (maskTarget.dom === document.body) {
  200. viewSize = {
  201. height: Math.max(document.body.scrollHeight, Ext.dom.Element.getDocumentHeight()),
  202. width: Math.max(document.body.scrollWidth, document.documentElement.clientWidth)
  203. };
  204. } else {
  205. viewSize = maskTarget.getViewSize(true);
  206. }
  207. mask.setSize(viewSize);
  208. mask.show();
  209. }
  210. },
  211. <span id='Ext-ZIndexManager-method-register'> /**
  212. </span> * Registers a floating {@link Ext.Component} with this ZIndexManager. This should not
  213. * need to be called under normal circumstances. Floating Components (such as Windows,
  214. * BoundLists and Menus) are automatically registered with a
  215. * {@link Ext.Component#zIndexManager zIndexManager} at render time.
  216. *
  217. * Where this may be useful is moving Windows between two ZIndexManagers. For example,
  218. * to bring the Ext.MessageBox dialog under the same manager as the Desktop's
  219. * ZIndexManager in the desktop sample app:
  220. *
  221. * MyDesktop.getDesktop().getManager().register(Ext.MessageBox);
  222. *
  223. * @param {Ext.Component} comp The Component to register.
  224. */
  225. register : function(comp) {
  226. var me = this;
  227. if (comp.zIndexManager) {
  228. comp.zIndexManager.unregister(comp);
  229. }
  230. comp.zIndexManager = me;
  231. me.list[comp.id] = comp;
  232. me.zIndexStack.push(comp);
  233. comp.on('hide', me.onComponentHide, me);
  234. },
  235. <span id='Ext-ZIndexManager-method-unregister'> /**
  236. </span> * Unregisters a {@link Ext.Component} from this ZIndexManager. This should not
  237. * need to be called. Components are automatically unregistered upon destruction.
  238. * See {@link #register}.
  239. * @param {Ext.Component} comp The Component to unregister.
  240. */
  241. unregister : function(comp) {
  242. var me = this,
  243. list = me.list;
  244. delete comp.zIndexManager;
  245. if (list &amp;&amp; list[comp.id]) {
  246. delete list[comp.id];
  247. comp.un('hide', me.onComponentHide);
  248. Ext.Array.remove(me.zIndexStack, comp);
  249. // Destruction requires that the topmost visible floater be activated. Same as hiding.
  250. me._activateLast();
  251. }
  252. },
  253. <span id='Ext-ZIndexManager-method-get'> /**
  254. </span> * Gets a registered Component by id.
  255. * @param {String/Object} id The id of the Component or a {@link Ext.Component} instance
  256. * @return {Ext.Component}
  257. */
  258. get : function(id) {
  259. return id.isComponent ? id : this.list[id];
  260. },
  261. <span id='Ext-ZIndexManager-method-bringToFront'> /**
  262. </span> * Brings the specified Component to the front of any other active Components in this ZIndexManager.
  263. * @param {String/Object} comp The id of the Component or a {@link Ext.Component} instance
  264. * @return {Boolean} True if the dialog was brought to the front, else false
  265. * if it was already in front
  266. */
  267. bringToFront : function(comp) {
  268. var me = this,
  269. result = false,
  270. zIndexStack = me.zIndexStack;
  271. comp = me.get(comp);
  272. if (comp !== me.front) {
  273. Ext.Array.remove(zIndexStack, comp);
  274. if (comp.preventBringToFront) {
  275. // this takes care of cases where a load mask should be displayed under a floated component
  276. zIndexStack.unshift(comp);
  277. } else {
  278. // the default behavior is to push onto the stack
  279. zIndexStack.push(comp);
  280. }
  281. me.assignZIndices();
  282. result = true;
  283. this.front = comp;
  284. }
  285. if (result &amp;&amp; comp.modal) {
  286. me._showModalMask(comp);
  287. }
  288. return result;
  289. },
  290. <span id='Ext-ZIndexManager-method-sendToBack'> /**
  291. </span> * Sends the specified Component to the back of other active Components in this ZIndexManager.
  292. * @param {String/Object} comp The id of the Component or a {@link Ext.Component} instance
  293. * @return {Ext.Component} The Component
  294. */
  295. sendToBack : function(comp) {
  296. var me = this;
  297. comp = me.get(comp);
  298. Ext.Array.remove(me.zIndexStack, comp);
  299. me.zIndexStack.unshift(comp);
  300. me.assignZIndices();
  301. this._activateLast();
  302. return comp;
  303. },
  304. <span id='Ext-ZIndexManager-method-hideAll'> /**
  305. </span> * Hides all Components managed by this ZIndexManager.
  306. */
  307. hideAll : function() {
  308. var list = this.list,
  309. item,
  310. id;
  311. for (id in list) {
  312. if (list.hasOwnProperty(id)) {
  313. item = list[id];
  314. if (item.isComponent &amp;&amp; item.isVisible()) {
  315. item.hide();
  316. }
  317. }
  318. }
  319. },
  320. <span id='Ext-ZIndexManager-method-hide'> /**
  321. </span> * @private
  322. * Temporarily hides all currently visible managed Components. This is for when
  323. * dragging a Window which may manage a set of floating descendants in its ZIndexManager;
  324. * they should all be hidden just for the duration of the drag.
  325. */
  326. hide: function() {
  327. var me = this,
  328. mask = me.mask,
  329. i = 0,
  330. stack = me.zIndexStack,
  331. len = stack.length,
  332. comp;
  333. me.tempHidden = me.tempHidden||[];
  334. for (; i &lt; len; i++) {
  335. comp = stack[i];
  336. if (comp.isVisible()) {
  337. me.tempHidden.push(comp);
  338. comp.el.hide();
  339. }
  340. }
  341. // Also hide modal mask during hidden state
  342. if (mask) {
  343. mask.hide();
  344. }
  345. },
  346. <span id='Ext-ZIndexManager-method-show'> /**
  347. </span> * @private
  348. * Restores temporarily hidden managed Components to visibility.
  349. */
  350. show: function() {
  351. var me = this,
  352. mask = me.mask,
  353. i = 0,
  354. tempHidden = me.tempHidden,
  355. len = tempHidden ? tempHidden.length : 0,
  356. comp;
  357. for (; i &lt; len; i++) {
  358. comp = tempHidden[i];
  359. comp.el.show();
  360. comp.setPosition(comp.x, comp.y);
  361. }
  362. me.tempHidden.length = 0;
  363. // Also restore mask to visibility and ensure it is aligned with its target element
  364. if (mask) {
  365. mask.show();
  366. mask.alignTo(mask.maskTarget, 'tl-tl');
  367. }
  368. },
  369. <span id='Ext-ZIndexManager-method-getActive'> /**
  370. </span> * Gets the currently-active Component in this ZIndexManager.
  371. * @return {Ext.Component} The active Component
  372. */
  373. getActive : function() {
  374. return this.front;
  375. },
  376. <span id='Ext-ZIndexManager-method-getBy'> /**
  377. </span> * Returns zero or more Components in this ZIndexManager using the custom search function passed to this method.
  378. * The function should accept a single {@link Ext.Component} reference as its only argument and should
  379. * return true if the Component matches the search criteria, otherwise it should return false.
  380. * @param {Function} fn The search function
  381. * @param {Object} [scope] The scope (this reference) in which the function is executed.
  382. * Defaults to the Component being tested. That gets passed to the function if not specified.
  383. * @return {Array} An array of zero or more matching windows
  384. */
  385. getBy : function(fn, scope) {
  386. var r = [],
  387. i = 0,
  388. stack = this.zIndexStack,
  389. len = stack.length,
  390. comp;
  391. for (; i &lt; len; i++) {
  392. comp = stack[i];
  393. if (fn.call(scope||comp, comp) !== false) {
  394. r.push(comp);
  395. }
  396. }
  397. return r;
  398. },
  399. <span id='Ext-ZIndexManager-method-each'> /**
  400. </span> * Executes the specified function once for every Component in this ZIndexManager, passing each
  401. * Component as the only parameter. Returning false from the function will stop the iteration.
  402. * @param {Function} fn The function to execute for each item
  403. * @param {Object} [scope] The scope (this reference) in which the function
  404. * is executed. Defaults to the current Component in the iteration.
  405. */
  406. each : function(fn, scope) {
  407. var list = this.list,
  408. id,
  409. comp;
  410. for (id in list) {
  411. if (list.hasOwnProperty(id)) {
  412. comp = list[id];
  413. if (comp.isComponent &amp;&amp; fn.call(scope || comp, comp) === false) {
  414. return;
  415. }
  416. }
  417. }
  418. },
  419. <span id='Ext-ZIndexManager-method-eachBottomUp'> /**
  420. </span> * Executes the specified function once for every Component in this ZIndexManager, passing each
  421. * Component as the only parameter. Returning false from the function will stop the iteration.
  422. * The components are passed to the function starting at the bottom and proceeding to the top.
  423. * @param {Function} fn The function to execute for each item
  424. * @param {Object} scope (optional) The scope (this reference) in which the function
  425. * is executed. Defaults to the current Component in the iteration.
  426. */
  427. eachBottomUp: function (fn, scope) {
  428. var stack = this.zIndexStack,
  429. i = 0,
  430. len = stack.length,
  431. comp;
  432. for (; i &lt; len; i++) {
  433. comp = stack[i];
  434. if (comp.isComponent &amp;&amp; fn.call(scope || comp, comp) === false) {
  435. return;
  436. }
  437. }
  438. },
  439. <span id='Ext-ZIndexManager-method-eachTopDown'> /**
  440. </span> * Executes the specified function once for every Component in this ZIndexManager, passing each
  441. * Component as the only parameter. Returning false from the function will stop the iteration.
  442. * The components are passed to the function starting at the top and proceeding to the bottom.
  443. * @param {Function} fn The function to execute for each item
  444. * @param {Object} [scope] The scope (this reference) in which the function
  445. * is executed. Defaults to the current Component in the iteration.
  446. */
  447. eachTopDown: function (fn, scope) {
  448. var stack = this.zIndexStack,
  449. i = stack.length,
  450. comp;
  451. for (; i-- &gt; 0; ) {
  452. comp = stack[i];
  453. if (comp.isComponent &amp;&amp; fn.call(scope || comp, comp) === false) {
  454. return;
  455. }
  456. }
  457. },
  458. destroy: function() {
  459. var me = this,
  460. list = me.list,
  461. comp,
  462. id;
  463. for (id in list) {
  464. if (list.hasOwnProperty(id)) {
  465. comp = list[id];
  466. if (comp.isComponent) {
  467. comp.destroy();
  468. }
  469. }
  470. }
  471. delete me.zIndexStack;
  472. delete me.list;
  473. delete me.container;
  474. delete me.targetEl;
  475. }
  476. }, function() {
  477. <span id='Ext-WindowManager'> /**
  478. </span> * @class Ext.WindowManager
  479. * @extends Ext.ZIndexManager
  480. *
  481. * The default global floating Component group that is available automatically.
  482. *
  483. * This manages instances of floating Components which were rendered programatically without
  484. * being added to a {@link Ext.container.Container Container}, and for floating Components
  485. * which were added into non-floating Containers.
  486. *
  487. * *Floating* Containers create their own instance of ZIndexManager, and floating Components
  488. * added at any depth below there are managed by that ZIndexManager.
  489. *
  490. * @singleton
  491. */
  492. Ext.WindowManager = Ext.WindowMgr = new this();
  493. });
  494. </pre>
  495. </body>
  496. </html>