/hippo/src/main/webapp/ext/src/widgets/Layer.js

http://hdbc.googlecode.com/ · JavaScript · 466 lines · 365 code · 41 blank · 60 comment · 68 complexity · d8d90d3fda075f2f5f71772f869c53b5 MD5 · raw file

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