8d5456e8ddfb628195e58ff1068b576f88ee02d0.svn-base 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. /*
  2. * Ext JS Library 2.0 Copyright(c) 2006-2007, Ext JS, LLC. licensing@extjs.com
  3. *
  4. * http://extjs.com/license
  5. */
  6. /**
  7. * @class Ext.Layer
  8. * @extends Ext.Element An extended {@link Ext.Element} object that supports a
  9. * shadow and shim, constrain to viewport and automatic maintaining of
  10. * shadow/shim positions.
  11. * @cfg {Boolean} shim False to disable the iframe shim in browsers which need
  12. * one (defaults to true)
  13. * @cfg {String/Boolean} shadow True to create a shadow element with default
  14. * class "x-layer-shadow", or you can pass a string with a CSS class name.
  15. * False turns off the shadow.
  16. * @cfg {Object} dh DomHelper object config to create element with (defaults to
  17. * {tag: "div", cls: "x-layer"}).
  18. * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to
  19. * true)
  20. * @cfg {String} cls CSS class to add to the element
  21. * @cfg {Number} zindex Starting z-index (defaults to 11000)
  22. * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to
  23. * 3)
  24. * @constructor
  25. * @param {Object}
  26. * config An object with config options.
  27. * @param {String/HTMLElement}
  28. * existingEl (optional) Uses an existing DOM element. If the element
  29. * is not found it creates it.
  30. */
  31. (function() {
  32. Ext.Layer = function(config, existingEl) {
  33. config = config || {};
  34. var dh = Ext.DomHelper;
  35. var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
  36. if (existingEl) {
  37. this.dom = Ext.getDom(existingEl);
  38. }
  39. if (!this.dom) {
  40. var o = config.dh || {
  41. tag : "div",
  42. cls : "x-layer"
  43. };
  44. this.dom = dh.append(pel, o);
  45. }
  46. if (config.cls) {
  47. this.addClass(config.cls);
  48. }
  49. this.constrain = config.constrain !== false;
  50. this.visibilityMode = Ext.Element.VISIBILITY;
  51. if (config.id) {
  52. this.id = this.dom.id = config.id;
  53. } else {
  54. this.id = Ext.id(this.dom);
  55. }
  56. this.zindex = config.zindex || this.getZIndex();
  57. this.position("absolute", this.zindex);
  58. if (config.shadow) {
  59. this.shadowOffset = config.shadowOffset || 4;
  60. this.shadow = new Ext.Shadow({
  61. offset : this.shadowOffset,
  62. mode : config.shadow
  63. });
  64. } else {
  65. this.shadowOffset = 0;
  66. }
  67. this.useShim = config.shim !== false && Ext.useShims;
  68. this.useDisplay = config.useDisplay;
  69. this.hide();
  70. };
  71. var supr = Ext.Element.prototype;
  72. // shims are shared among layer to keep from having 100 iframes
  73. var shims = [];
  74. Ext.extend(Ext.Layer, Ext.Element, {
  75. getZIndex : function() {
  76. return this.zindex || parseInt(this.getStyle("z-index"), 10)
  77. || 11000;
  78. },
  79. getShim : function() {
  80. if (!this.useShim) {
  81. return null;
  82. }
  83. if (this.shim) {
  84. return this.shim;
  85. }
  86. var shim = shims.shift();
  87. if (!shim) {
  88. shim = this.createShim();
  89. shim.enableDisplayMode('block');
  90. shim.dom.style.display = 'none';
  91. shim.dom.style.visibility = 'visible';
  92. }
  93. var pn = this.dom.parentNode;
  94. if (shim.dom.parentNode != pn) {
  95. pn.insertBefore(shim.dom, this.dom);
  96. }
  97. shim.setStyle('z-index', this.getZIndex() - 2);
  98. this.shim = shim;
  99. return shim;
  100. },
  101. hideShim : function() {
  102. if (this.shim) {
  103. this.shim.setDisplayed(false);
  104. shims.push(this.shim);
  105. delete this.shim;
  106. }
  107. },
  108. disableShadow : function() {
  109. if (this.shadow) {
  110. this.shadowDisabled = true;
  111. this.shadow.hide();
  112. this.lastShadowOffset = this.shadowOffset;
  113. this.shadowOffset = 0;
  114. }
  115. },
  116. enableShadow : function(show) {
  117. if (this.shadow) {
  118. this.shadowDisabled = false;
  119. this.shadowOffset = this.lastShadowOffset;
  120. delete this.lastShadowOffset;
  121. if (show) {
  122. this.sync(true);
  123. }
  124. }
  125. },
  126. // private
  127. // this code can execute repeatedly in milliseconds (i.e. during a drag)
  128. // so
  129. // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY
  130. // calls)
  131. sync : function(doShow) {
  132. var sw = this.shadow;
  133. if (!this.updating && this.isVisible() && (sw || this.useShim)) {
  134. var sh = this.getShim();
  135. var w = this.getWidth(), h = this.getHeight();
  136. var l = this.getLeft(true), t = this.getTop(true);
  137. if (sw && !this.shadowDisabled) {
  138. if (doShow && !sw.isVisible()) {
  139. sw.show(this);
  140. } else {
  141. sw.realign(l, t, w, h);
  142. }
  143. if (sh) {
  144. if (doShow) {
  145. sh.show();
  146. }
  147. // fit the shim behind the shadow, so it is shimmed too
  148. var a = sw.adjusts, s = sh.dom.style;
  149. s.left = (Math.min(l, l + a.l)) + "px";
  150. s.top = (Math.min(t, t + a.t)) + "px";
  151. s.width = (w + a.w) + "px";
  152. s.height = (h + a.h) + "px";
  153. }
  154. } else if (sh) {
  155. if (doShow) {
  156. sh.show();
  157. }
  158. sh.setSize(w, h);
  159. sh.setLeftTop(l, t);
  160. }
  161. }
  162. },
  163. // private
  164. destroy : function() {
  165. this.hideShim();
  166. if (this.shadow) {
  167. this.shadow.hide();
  168. }
  169. this.removeAllListeners();
  170. Ext.removeNode(this.dom);
  171. Ext.Element.uncache(this.id);
  172. },
  173. remove : function() {
  174. this.destroy();
  175. },
  176. // private
  177. beginUpdate : function() {
  178. this.updating = true;
  179. },
  180. // private
  181. endUpdate : function() {
  182. this.updating = false;
  183. this.sync(true);
  184. },
  185. // private
  186. hideUnders : function(negOffset) {
  187. if (this.shadow) {
  188. this.shadow.hide();
  189. }
  190. this.hideShim();
  191. },
  192. // private
  193. constrainXY : function() {
  194. if (this.constrain) {
  195. var vw = Ext.lib.Dom.getViewWidth(), vh = Ext.lib.Dom
  196. .getViewHeight();
  197. var s = Ext.getDoc().getScroll();
  198. var xy = this.getXY();
  199. var x = xy[0], y = xy[1];
  200. var w = this.dom.offsetWidth + this.shadowOffset, h = this.dom.offsetHeight
  201. + this.shadowOffset;
  202. // only move it if it needs it
  203. var moved = false;
  204. // first validate right/bottom
  205. if ((x + w) > vw + s.left) {
  206. x = vw - w - this.shadowOffset;
  207. moved = true;
  208. }
  209. if ((y + h) > vh + s.top) {
  210. y = vh - h - this.shadowOffset;
  211. moved = true;
  212. }
  213. // then make sure top/left isn't negative
  214. if (x < s.left) {
  215. x = s.left;
  216. moved = true;
  217. }
  218. if (y < s.top) {
  219. y = s.top;
  220. moved = true;
  221. }
  222. if (moved) {
  223. if (this.avoidY) {
  224. var ay = this.avoidY;
  225. if (y <= ay && (y + h) >= ay) {
  226. y = ay - h - 5;
  227. }
  228. }
  229. xy = [x, y];
  230. this.storeXY(xy);
  231. supr.setXY.call(this, xy);
  232. this.sync();
  233. }
  234. }
  235. },
  236. isVisible : function() {
  237. return this.visible;
  238. },
  239. // private
  240. showAction : function() {
  241. this.visible = true; // track visibility to prevent getStyle
  242. // calls
  243. if (this.useDisplay === true) {
  244. this.setDisplayed("");
  245. } else if (this.lastXY) {
  246. supr.setXY.call(this, this.lastXY);
  247. } else if (this.lastLT) {
  248. supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
  249. }
  250. },
  251. // private
  252. hideAction : function() {
  253. this.visible = false;
  254. if (this.useDisplay === true) {
  255. this.setDisplayed(false);
  256. } else {
  257. this.setLeftTop(-10000, -10000);
  258. }
  259. },
  260. // overridden Element method
  261. setVisible : function(v, a, d, c, e) {
  262. if (v) {
  263. this.showAction();
  264. }
  265. if (a && v) {
  266. var cb = function() {
  267. this.sync(true);
  268. if (c) {
  269. c();
  270. }
  271. }.createDelegate(this);
  272. supr.setVisible.call(this, true, true, d, cb, e);
  273. } else {
  274. if (!v) {
  275. this.hideUnders(true);
  276. }
  277. var cb = c;
  278. if (a) {
  279. cb = function() {
  280. this.hideAction();
  281. if (c) {
  282. c();
  283. }
  284. }.createDelegate(this);
  285. }
  286. supr.setVisible.call(this, v, a, d, cb, e);
  287. if (v) {
  288. this.sync(true);
  289. } else if (!a) {
  290. this.hideAction();
  291. }
  292. }
  293. },
  294. storeXY : function(xy) {
  295. delete this.lastLT;
  296. this.lastXY = xy;
  297. },
  298. storeLeftTop : function(left, top) {
  299. delete this.lastXY;
  300. this.lastLT = [left, top];
  301. },
  302. // private
  303. beforeFx : function() {
  304. this.beforeAction();
  305. return Ext.Layer.superclass.beforeFx.apply(this, arguments);
  306. },
  307. // private
  308. afterFx : function() {
  309. Ext.Layer.superclass.afterFx.apply(this, arguments);
  310. this.sync(this.isVisible());
  311. },
  312. // private
  313. beforeAction : function() {
  314. if (!this.updating && this.shadow) {
  315. this.shadow.hide();
  316. }
  317. },
  318. // overridden Element method
  319. setLeft : function(left) {
  320. this.storeLeftTop(left, this.getTop(true));
  321. supr.setLeft.apply(this, arguments);
  322. this.sync();
  323. },
  324. setTop : function(top) {
  325. this.storeLeftTop(this.getLeft(true), top);
  326. supr.setTop.apply(this, arguments);
  327. this.sync();
  328. },
  329. setLeftTop : function(left, top) {
  330. this.storeLeftTop(left, top);
  331. supr.setLeftTop.apply(this, arguments);
  332. this.sync();
  333. },
  334. setXY : function(xy, a, d, c, e) {
  335. this.fixDisplay();
  336. this.beforeAction();
  337. this.storeXY(xy);
  338. var cb = this.createCB(c);
  339. supr.setXY.call(this, xy, a, d, cb, e);
  340. if (!a) {
  341. cb();
  342. }
  343. },
  344. // private
  345. createCB : function(c) {
  346. var el = this;
  347. return function() {
  348. el.constrainXY();
  349. el.sync(true);
  350. if (c) {
  351. c();
  352. }
  353. };
  354. },
  355. // overridden Element method
  356. setX : function(x, a, d, c, e) {
  357. this.setXY([x, this.getY()], a, d, c, e);
  358. },
  359. // overridden Element method
  360. setY : function(y, a, d, c, e) {
  361. this.setXY([this.getX(), y], a, d, c, e);
  362. },
  363. // overridden Element method
  364. setSize : function(w, h, a, d, c, e) {
  365. this.beforeAction();
  366. var cb = this.createCB(c);
  367. supr.setSize.call(this, w, h, a, d, cb, e);
  368. if (!a) {
  369. cb();
  370. }
  371. },
  372. // overridden Element method
  373. setWidth : function(w, a, d, c, e) {
  374. this.beforeAction();
  375. var cb = this.createCB(c);
  376. supr.setWidth.call(this, w, a, d, cb, e);
  377. if (!a) {
  378. cb();
  379. }
  380. },
  381. // overridden Element method
  382. setHeight : function(h, a, d, c, e) {
  383. this.beforeAction();
  384. var cb = this.createCB(c);
  385. supr.setHeight.call(this, h, a, d, cb, e);
  386. if (!a) {
  387. cb();
  388. }
  389. },
  390. // overridden Element method
  391. setBounds : function(x, y, w, h, a, d, c, e) {
  392. this.beforeAction();
  393. var cb = this.createCB(c);
  394. if (!a) {
  395. this.storeXY([x, y]);
  396. supr.setXY.call(this, [x, y]);
  397. supr.setSize.call(this, w, h, a, d, cb, e);
  398. cb();
  399. } else {
  400. supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
  401. }
  402. return this;
  403. },
  404. /**
  405. * Sets the z-index of this layer and adjusts any shadow and shim
  406. * z-indexes. The layer z-index is automatically incremented by two more
  407. * than the value passed in so that it always shows above any shadow or
  408. * shim (the shadow element, if any, will be assigned z-index + 1, and
  409. * the shim element, if any, will be assigned the unmodified z-index).
  410. *
  411. * @param {Number}
  412. * zindex The new z-index to set
  413. * @return {this} The Layer
  414. */
  415. setZIndex : function(zindex) {
  416. this.zindex = zindex;
  417. this.setStyle("z-index", zindex + 2);
  418. if (this.shadow) {
  419. this.shadow.setZIndex(zindex + 1);
  420. }
  421. if (this.shim) {
  422. this.shim.setStyle("z-index", zindex);
  423. }
  424. }
  425. });
  426. })();