Button.html 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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-layout-component-Button'>/**
  19. </span> * Component layout for buttons
  20. * @private
  21. */
  22. Ext.define('Ext.layout.component.Button', {
  23. /* Begin Definitions */
  24. alias: ['layout.button'],
  25. extend: 'Ext.layout.component.Auto',
  26. /* End Definitions */
  27. type: 'button',
  28. cellClsRE: /-btn-(tl|br)\b/,
  29. htmlRE: /&lt;.*&gt;/,
  30. constructor: function () {
  31. this.callParent(arguments);
  32. this.hackWidth = Ext.isIE &amp;&amp; (!Ext.isStrict || Ext.isIE6 || Ext.isIE7 || Ext.isIE8);
  33. this.heightIncludesPadding = Ext.isIE6 &amp;&amp; Ext.isStrict;
  34. },
  35. // TODO - use last run results if text has not changed?
  36. beginLayout: function (ownerContext) {
  37. this.callParent(arguments);
  38. this.cacheTargetInfo(ownerContext);
  39. },
  40. beginLayoutCycle: function(ownerContext) {
  41. var me = this,
  42. empty = '',
  43. owner = me.owner,
  44. btnEl = owner.btnEl,
  45. btnInnerEl = owner.btnInnerEl,
  46. text = owner.text,
  47. htmlAutoHeight;
  48. me.callParent(arguments);
  49. btnInnerEl.setStyle('overflow', empty);
  50. // Clear all element widths
  51. if (!ownerContext.widthModel.natural) {
  52. owner.el.setStyle('width', empty);
  53. }
  54. // If the text is HTML we need to let the browser automatically size things to cope with the case where the text
  55. // is multi-line. This incurs a cost as we then have to measure those elements to derive other sizes
  56. htmlAutoHeight = ownerContext.heightModel.shrinkWrap &amp;&amp; text &amp;&amp; me.htmlRE.test(text);
  57. btnEl.setStyle('width', empty);
  58. btnEl.setStyle('height', htmlAutoHeight ? 'auto' : empty);
  59. btnInnerEl.setStyle('width', empty);
  60. btnInnerEl.setStyle('height', htmlAutoHeight ? 'auto' : empty);
  61. btnInnerEl.setStyle('line-height', htmlAutoHeight ? 'normal' : empty);
  62. btnInnerEl.setStyle('padding-top', empty);
  63. owner.btnIconEl.setStyle('width', empty);
  64. },
  65. calculateOwnerHeightFromContentHeight: function (ownerContext, contentHeight) {
  66. return contentHeight;
  67. },
  68. calculateOwnerWidthFromContentWidth: function (ownerContext, contentWidth) {
  69. return contentWidth;
  70. },
  71. measureContentWidth: function (ownerContext) {
  72. var me = this,
  73. owner = me.owner,
  74. btnEl = owner.btnEl,
  75. btnInnerEl = owner.btnInnerEl,
  76. text = owner.text,
  77. btnFrameWidth, metrics, sizeIconEl, width, btnElContext, btnInnerElContext;
  78. // IE suffers from various sizing problems, usually caused by relying on it to size elements automatically. Even
  79. // if an element is sized correctly it can prove necessary to set that size explicitly on the element to get it
  80. // to size and position its children correctly. While the exact nature of the problems varies depending on the
  81. // browser version, doctype and button configuration there is a common solution: set the sizes manually.
  82. if (owner.text &amp;&amp; me.hackWidth &amp;&amp; btnEl) {
  83. btnFrameWidth = me.btnFrameWidth;
  84. // If the button text is something like '&lt;' or '&lt;&lt;' then we need to escape it or it won't be measured
  85. // correctly. The button text is supposed to be HTML and strictly speaking '&lt;' and '&lt;&lt;' aren't valid HTML.
  86. // However in practice they are commonly used and have worked 'correctly' in previous versions.
  87. if (text.indexOf('&gt;') === -1) {
  88. text = text.replace(/&lt;/g, '&amp;lt;');
  89. }
  90. metrics = Ext.util.TextMetrics.measure(btnInnerEl, text);
  91. width = metrics.width + btnFrameWidth + me.adjWidth;
  92. btnElContext = ownerContext.getEl('btnEl');
  93. btnInnerElContext = ownerContext.getEl('btnInnerEl');
  94. sizeIconEl = (owner.icon || owner.iconCls) &amp;&amp;
  95. (owner.iconAlign == &quot;top&quot; || owner.iconAlign == &quot;bottom&quot;);
  96. // This cheat works (barely) with publishOwnerWidth which calls setProp also
  97. // to publish the width. Since it is the same value we set here, the dirty bit
  98. // we set true will not be cleared by publishOwnerWidth.
  99. ownerContext.setWidth(width); // not setWidth (no framing)
  100. btnElContext.setWidth(metrics.width + btnFrameWidth);
  101. btnInnerElContext.setWidth(metrics.width + btnFrameWidth);
  102. if (sizeIconEl) {
  103. owner.btnIconEl.setWidth(metrics.width + btnFrameWidth);
  104. }
  105. } else {
  106. width = ownerContext.el.getWidth();
  107. }
  108. return width;
  109. },
  110. measureContentHeight: function (ownerContext) {
  111. var me = this,
  112. owner = me.owner,
  113. btnInnerEl = owner.btnInnerEl,
  114. btnItem = ownerContext.getEl('btnEl'),
  115. btnInnerItem = ownerContext.getEl('btnInnerEl'),
  116. minTextHeight = me.minTextHeight,
  117. adjHeight = me.adjHeight,
  118. text = owner.getText(),
  119. height,
  120. textHeight,
  121. topPadding;
  122. if (owner.vertical) {
  123. height = Ext.util.TextMetrics.measure(btnInnerEl, owner.text).width;
  124. height += me.btnFrameHeight + adjHeight;
  125. // Vertical buttons need height explicitly set
  126. ownerContext.setHeight(height, /*dirty=*/true, /*force=*/true);
  127. }
  128. else {
  129. // If the button text is HTML we have to handle it specially as it could contain multiple lines
  130. if (text &amp;&amp; me.htmlRE.test(text)) {
  131. textHeight = btnInnerEl.getHeight();
  132. // HTML content doesn't guarantee multiple lines: in the single line case it could now be too short for the icon
  133. if (textHeight &lt; minTextHeight) {
  134. topPadding = Math.floor((minTextHeight - textHeight) / 2);
  135. // Resize the span and use padding to center the text vertically. The hack to remove the padding
  136. // from the height on IE6 is especially needed for link buttons
  137. btnInnerItem.setHeight(minTextHeight - (me.heightIncludesPadding ? topPadding : 0));
  138. btnInnerItem.setProp('padding-top', topPadding);
  139. textHeight = minTextHeight;
  140. }
  141. // Calculate the height relative to the text span, auto can't be trusted in IE quirks
  142. height = textHeight + adjHeight;
  143. }
  144. else {
  145. height = ownerContext.el.getHeight();
  146. }
  147. }
  148. // IE quirks needs the button height setting using style or it won't position the icon correctly (even if the height was already correct)
  149. btnItem.setHeight(height - adjHeight);
  150. return height;
  151. },
  152. publishInnerHeight: function(ownerContext, height) {
  153. var me = this,
  154. owner = me.owner,
  155. isNum = Ext.isNumber,
  156. btnItem = ownerContext.getEl('btnEl'),
  157. btnInnerEl = owner.btnInnerEl,
  158. btnInnerItem = ownerContext.getEl('btnInnerEl'),
  159. btnHeight = isNum(height) ? height - me.adjHeight : height,
  160. btnFrameHeight = me.btnFrameHeight,
  161. text = owner.getText(),
  162. textHeight,
  163. paddingTop;
  164. btnItem.setHeight(btnHeight);
  165. btnInnerItem.setHeight(btnHeight);
  166. // Only need the line-height setting for regular, horizontal Buttons
  167. if (!owner.vertical &amp;&amp; btnHeight &gt;= 0) {
  168. btnInnerItem.setProp('line-height', btnHeight - btnFrameHeight + 'px');
  169. }
  170. // Button text may contain markup that would force it to wrap to more than one line (e.g. 'Button&lt;br&gt;Label').
  171. // When this happens, we cannot use the line-height set above for vertical centering; we instead reset the
  172. // line-height to normal, measure the rendered text height, and add padding-top to center the text block
  173. // vertically within the button's height. This is more expensive than the basic line-height approach so
  174. // we only do it if the text contains markup.
  175. if (text &amp;&amp; me.htmlRE.test(text)) {
  176. btnInnerItem.setProp('line-height', 'normal');
  177. btnInnerEl.setStyle('line-height', 'normal');
  178. textHeight = Ext.util.TextMetrics.measure(btnInnerEl, text).height;
  179. paddingTop = Math.floor(Math.max(btnHeight - btnFrameHeight - textHeight, 0) / 2);
  180. btnInnerItem.setProp('padding-top', me.btnFrameTop + paddingTop);
  181. btnInnerItem.setHeight(btnHeight - (me.heightIncludesPadding ? paddingTop : 0));
  182. }
  183. },
  184. publishInnerWidth: function(ownerContext, width) {
  185. var me = this,
  186. isNum = Ext.isNumber,
  187. btnItem = ownerContext.getEl('btnEl'),
  188. btnInnerItem = ownerContext.getEl('btnInnerEl'),
  189. btnWidth = isNum(width) ? width - me.adjWidth : width;
  190. btnItem.setWidth(btnWidth);
  191. btnInnerItem.setWidth(btnWidth);
  192. },
  193. clearTargetCache: function(){
  194. delete this.adjWidth;
  195. },
  196. cacheTargetInfo: function(ownerContext) {
  197. var me = this,
  198. owner = me.owner,
  199. scale = owner.scale,
  200. padding, frameSize, btnWrapPadding, btnInnerEl, innerFrameSize;
  201. // The cache is only valid for a particular scale
  202. if (!('adjWidth' in me) || me.lastScale !== scale) {
  203. // If there has been a previous layout run it could have sullied the line-height
  204. if (me.lastScale) {
  205. owner.btnInnerEl.setStyle('line-height', '');
  206. }
  207. me.lastScale = scale;
  208. padding = ownerContext.getPaddingInfo();
  209. frameSize = ownerContext.getFrameInfo();
  210. btnWrapPadding = ownerContext.getEl('btnWrap').getPaddingInfo();
  211. btnInnerEl = ownerContext.getEl('btnInnerEl');
  212. innerFrameSize = btnInnerEl.getPaddingInfo();
  213. Ext.apply(me, {
  214. // Width adjustment must take into account the arrow area. The btnWrap is the &lt;em&gt; which has padding to accommodate the arrow.
  215. adjWidth : btnWrapPadding.width + frameSize.width + padding.width,
  216. adjHeight : btnWrapPadding.height + frameSize.height + padding.height,
  217. btnFrameWidth : innerFrameSize.width,
  218. btnFrameHeight : innerFrameSize.height,
  219. btnFrameTop : innerFrameSize.top,
  220. // Use the line-height rather than height because if the text is multi-line then the height will be 'wrong'
  221. minTextHeight : parseInt(btnInnerEl.getStyle('line-height'), 10)
  222. });
  223. }
  224. me.callParent(arguments);
  225. },
  226. finishedLayout: function(){
  227. var owner = this.owner;
  228. this.callParent(arguments);
  229. // Fixes issue EXTJSIV-5989. Looks like a browser repaint bug
  230. // This hack can be removed once it is resolved.
  231. if (Ext.isWebKit) {
  232. owner.el.dom.offsetWidth;
  233. }
  234. }
  235. });
  236. </pre>
  237. </body>
  238. </html>