PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/qooxdoo/framework/source/class/qx/ui/root/Inline.js

https://github.com/Wkasel/qooxdoo
JavaScript | 325 lines | 155 code | 59 blank | 111 comment | 40 complexity | b12048c108694ba30b41548c5c2dabf3 MD5 | raw file
  1. /* ************************************************************************
  2. qooxdoo - the new era of web development
  3. http://qooxdoo.org
  4. Copyright:
  5. 2004-2008 1&1 Internet AG, Germany, http://www.1und1.de
  6. License:
  7. LGPL: http://www.gnu.org/licenses/lgpl.html
  8. EPL: http://www.eclipse.org/org/documents/epl-v10.php
  9. See the LICENSE file in the project's top-level directory for details.
  10. Authors:
  11. * Sebastian Werner (wpbasti)
  12. * Fabian Jakobs (fjakobs)
  13. * Alexander Steitz (aback)
  14. ************************************************************************ */
  15. /* ************************************************************************
  16. #use(qx.event.handler.ElementResize)
  17. #ignore(qx.ui)
  18. #ignore(qx.ui.popup.Manager)
  19. #ignore(qx.ui.menu.Manager)
  20. ************************************************************************ */
  21. /**
  22. * This classes could be used to insert qooxdoo islands into existing
  23. * web pages. You can use the isles to place any qooxdoo powered widgets
  24. * inside a layout made using traditional HTML markup and CSS.
  25. *
  26. * The size of the widget in each dimension can either be determined by the
  27. * size hint of the inline's children or by the size of the root DOM element. If
  28. * <code>dynamicX</code>/<code>dynamicY</code> is true the width/height of the DOM
  29. * element is used.
  30. *
  31. * This class uses {@link qx.ui.layout.Basic} as default layout. The layout
  32. * can be changed using the {@link #setLayout} method.
  33. *
  34. * To position popups and tooltips please have a look at {@link qx.ui.root.Page}.
  35. */
  36. qx.Class.define("qx.ui.root.Inline",
  37. {
  38. extend : qx.ui.root.Abstract,
  39. include : [qx.ui.core.MLayoutHandling],
  40. /*
  41. *****************************************************************************
  42. CONSTRUCTOR
  43. *****************************************************************************
  44. */
  45. /**
  46. * @param el {Element} DOM element to use as isle for qooxdoo content. Please
  47. * note that existing content gets removed on the first layout flush.
  48. * @param dynamicX {Boolean} If <code>true</code> the widget's width is
  49. * determined by the DOM element's width. Otherwise the children's size hint
  50. * is used.
  51. * @param dynamicY {Boolean} If <code>true</code> the widget's height is
  52. * determined by the DOM element's height. Otherwise the children's size hint
  53. * is used.
  54. */
  55. construct : function(el, dynamicX, dynamicY)
  56. {
  57. // check the parameter
  58. if (qx.core.Environment.get("qx.debug")) {
  59. this.assertElement(el, "Please use a DOM element to create an inline root.");
  60. }
  61. // Temporary storage of element to use
  62. this.__elem = el;
  63. // Avoid any problems with dynamic resizing
  64. el.style.overflow = "hidden";
  65. // Avoid any problems with broken layout
  66. el.style.textAlign = "left";
  67. this.__dynX = dynamicX || false;
  68. this.__dynY = dynamicY || false;
  69. this.__initDynamicMode();
  70. this.base(arguments);
  71. // Use static layout
  72. this._setLayout(new qx.ui.layout.Basic());
  73. // Directly schedule layout for root element
  74. qx.ui.core.queue.Layout.add(this);
  75. // Register as root
  76. qx.ui.core.FocusHandler.getInstance().connectTo(this);
  77. // Input type file does only work, when the root element is selectable.
  78. // See http://bugzilla.qooxdoo.org/show_bug.cgi?id=3408 for details.
  79. if ((qx.core.Environment.get("engine.name") == "opera")) {
  80. this.setSelectable(true);
  81. }
  82. // Avoid the automatically scroll in to view.
  83. // See http://bugzilla.qooxdoo.org/show_bug.cgi?id=3236 for details.
  84. if ((qx.core.Environment.get("engine.name") == "mshtml")) {
  85. this.setKeepFocus(true);
  86. }
  87. // Resize handling for the window
  88. var window = qx.dom.Node.getWindow(el);
  89. qx.event.Registration.addListener(window, "resize", this._onWindowResize, this);
  90. },
  91. /*
  92. *****************************************************************************
  93. MEMBERS
  94. *****************************************************************************
  95. */
  96. members :
  97. {
  98. __dynX : false,
  99. __dynY : false,
  100. __elem : null,
  101. /**
  102. * Performs several checks for dynamic mode and adds the "resize" listener
  103. */
  104. __initDynamicMode : function()
  105. {
  106. if (this.__dynX || this.__dynY)
  107. {
  108. // Check the DOM element for an usable width and height
  109. var elementDimensions = qx.bom.element.Dimension.getSize(this.__elem);
  110. if (this.__dynX && elementDimensions.width < 1) {
  111. throw new Error("The root element " + this.__elem + " of " + this +
  112. " needs a width when its width size should be used!");
  113. }
  114. if (this.__dynY)
  115. {
  116. if (elementDimensions.height < 1) {
  117. throw new Error("The root element " + this.__elem + " of " + this +
  118. " needs a height when its height size should be used!");
  119. }
  120. // check for implicit height. Set the height explicit to prevent that
  121. // the element grows indefinetely
  122. if (elementDimensions.height >= 1 &&
  123. qx.bom.element.Style.get(this.__elem, "height", 3) == "") {
  124. qx.bom.element.Style.set(this.__elem, "height", elementDimensions.height + "px");
  125. }
  126. }
  127. qx.event.Registration.addListener(this.__elem, "resize", this._onResize, this);
  128. }
  129. },
  130. // overridden
  131. _createContainerElement : function()
  132. {
  133. var el = this.__elem;
  134. if (this.__dynX || this.__dynY)
  135. {
  136. var rootEl = document.createElement("div");
  137. el.appendChild(rootEl);
  138. // If any of the ancestor elements has a position "relative" it is
  139. // necessary for IE6 to apply this style also to the root element to
  140. // avoid any problems when resizing the browser window (see Bug #2035)
  141. if ((qx.core.Environment.get("engine.name") == "mshtml") &&
  142. qx.core.Environment.get("engine.version") == 6)
  143. {
  144. var bodyElement = qx.dom.Node.getBodyElement(el);
  145. var ancestorElement;
  146. var position;
  147. var isPositionRelative = false;
  148. var ancestors = qx.dom.Hierarchy.getAncestors(el);
  149. for (var i=0, j=ancestors.length; i<j; i++)
  150. {
  151. ancestorElement = ancestors[i];
  152. if (ancestorElement != bodyElement)
  153. {
  154. position = qx.bom.element.Style.get(ancestorElement, "position");
  155. if (position == "relative")
  156. {
  157. isPositionRelative = true;
  158. break;
  159. }
  160. } else {
  161. break;
  162. }
  163. }
  164. if (isPositionRelative) {
  165. el.style.position = "relative";
  166. }
  167. }
  168. } else {
  169. rootEl = el;
  170. }
  171. var root = new qx.html.Root(rootEl);
  172. // Make relative
  173. rootEl.style.position = "relative";
  174. // Store "weak" reference to the widget in the DOM element.
  175. root.setAttribute("$$widget", this.toHashCode());
  176. // fire event asynchronously, otherwise the browser will fire the event
  177. // too early and no listener will be informed since they're not added
  178. // at this time
  179. qx.event.Timer.once(function(e) {
  180. this.fireEvent("appear");
  181. }, this, 0);
  182. return root;
  183. },
  184. /**
  185. * Listener for the element's resize event
  186. *
  187. * @param e {qx.event.type.Event} Event object
  188. */
  189. _onResize : function(e)
  190. {
  191. var data = e.getData();
  192. if (
  193. (data.oldWidth !== data.width) && this.__dynX ||
  194. (data.oldHeight !== data.height) && this.__dynY
  195. ) {
  196. qx.ui.core.queue.Layout.add(this);
  197. }
  198. },
  199. /**
  200. * Listener for the window's resize event.
  201. */
  202. _onWindowResize : function() {
  203. // close all popups
  204. if (qx.ui.popup && qx.ui.popup.Manager) {
  205. qx.ui.popup.Manager.getInstance().hideAll();
  206. }
  207. // close all menus
  208. if (qx.ui.menu && qx.ui.menu.Manager) {
  209. qx.ui.menu.Manager.getInstance().hideAll();
  210. }
  211. },
  212. // overridden
  213. _computeSizeHint : function()
  214. {
  215. var dynX = this.__dynX;
  216. var dynY = this.__dynY;
  217. if (!dynX || !dynY) {
  218. var hint = this.base(arguments);
  219. } else {
  220. hint = {};
  221. }
  222. var Dimension = qx.bom.element.Dimension;
  223. if (dynX)
  224. {
  225. var width = Dimension.getContentWidth(this.__elem);
  226. hint.width = width;
  227. hint.minWidth = width;
  228. hint.maxWidth = width;
  229. }
  230. if (dynY)
  231. {
  232. var height = Dimension.getContentHeight(this.__elem);
  233. hint.height = height;
  234. hint.minHeight = height;
  235. hint.maxHeight = height;
  236. }
  237. return hint;
  238. }
  239. },
  240. /*
  241. *****************************************************************************
  242. DEFER
  243. *****************************************************************************
  244. */
  245. defer : function(statics, members) {
  246. qx.ui.core.MLayoutHandling.remap(members);
  247. },
  248. /*
  249. *****************************************************************************
  250. DESTRUCT
  251. *****************************************************************************
  252. */
  253. destruct : function()
  254. {
  255. qx.event.Registration.removeListener(this.__elem, "resize", this._onResize, this);
  256. this.__elem = null;
  257. }
  258. });