TextMetrics.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /**
  2. * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
  3. * wide, in pixels, a given block of text will be. Note that when measuring text, it should be plain text and
  4. * should not contain any HTML, otherwise it may not be measured correctly.
  5. *
  6. * The measurement works by copying the relevant CSS styles that can affect the font related display,
  7. * then checking the size of an element that is auto-sized. Note that if the text is multi-lined, you must
  8. * provide a **fixed width** when doing the measurement.
  9. *
  10. * If multiple measurements are being done on the same element, you create a new instance to initialize
  11. * to avoid the overhead of copying the styles to the element repeatedly.
  12. */
  13. Ext.define('Ext.util.TextMetrics', {
  14. statics: {
  15. shared: null,
  16. /**
  17. * Measures the size of the specified text
  18. * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
  19. * that can affect the size of the rendered text
  20. * @param {String} text The text to measure
  21. * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
  22. * in order to accurately measure the text height
  23. * @return {Object} An object containing the text's size `{width: (width), height: (height)}`
  24. * @static
  25. */
  26. measure: function(el, text, fixedWidth){
  27. var me = this,
  28. shared = me.shared;
  29. if(!shared){
  30. shared = me.shared = new me(el, fixedWidth);
  31. }
  32. shared.bind(el);
  33. shared.setFixedWidth(fixedWidth || 'auto');
  34. return shared.getSize(text);
  35. },
  36. /**
  37. * Destroy the TextMetrics instance created by {@link #measure}.
  38. * @static
  39. */
  40. destroy: function(){
  41. var me = this;
  42. Ext.destroy(me.shared);
  43. me.shared = null;
  44. }
  45. },
  46. /**
  47. * Creates new TextMetrics.
  48. * @param {String/HTMLElement/Ext.Element} bindTo The element or its ID to bind to.
  49. * @param {Number} [fixedWidth] A fixed width to apply to the measuring element.
  50. */
  51. constructor: function(bindTo, fixedWidth){
  52. var measure = this.measure = Ext.getBody().createChild({
  53. cls: Ext.baseCSSPrefix + 'textmetrics'
  54. });
  55. this.el = Ext.get(bindTo);
  56. measure.position('absolute');
  57. measure.setLeftTop(-1000, -1000);
  58. measure.hide();
  59. if (fixedWidth) {
  60. measure.setWidth(fixedWidth);
  61. }
  62. },
  63. /**
  64. * Returns the size of the specified text based on the internal element's style and width properties
  65. * @param {String} text The text to measure
  66. * @return {Object} An object containing the text's size `{width: (width), height: (height)}`
  67. */
  68. getSize: function(text){
  69. var measure = this.measure,
  70. size;
  71. measure.update(text);
  72. size = measure.getSize();
  73. measure.update('');
  74. return size;
  75. },
  76. /**
  77. * Binds this TextMetrics instance to a new element
  78. * @param {String/HTMLElement/Ext.Element} el The element or its ID.
  79. */
  80. bind: function(el){
  81. var me = this;
  82. me.el = Ext.get(el);
  83. me.measure.setStyle(
  84. me.el.getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
  85. );
  86. },
  87. /**
  88. * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
  89. * to set a fixed width in order to accurately measure the text height.
  90. * @param {Number} width The width to set on the element
  91. */
  92. setFixedWidth : function(width){
  93. this.measure.setWidth(width);
  94. },
  95. /**
  96. * Returns the measured width of the specified text
  97. * @param {String} text The text to measure
  98. * @return {Number} width The width in pixels
  99. */
  100. getWidth : function(text){
  101. this.measure.dom.style.width = 'auto';
  102. return this.getSize(text).width;
  103. },
  104. /**
  105. * Returns the measured height of the specified text
  106. * @param {String} text The text to measure
  107. * @return {Number} height The height in pixels
  108. */
  109. getHeight : function(text){
  110. return this.getSize(text).height;
  111. },
  112. /**
  113. * Destroy this instance
  114. */
  115. destroy: function(){
  116. var me = this;
  117. me.measure.remove();
  118. delete me.el;
  119. delete me.measure;
  120. }
  121. }, function(){
  122. Ext.Element.addMethods({
  123. /**
  124. * Returns the width in pixels of the passed text, or the width of the text in this Element.
  125. * @param {String} text The text to measure. Defaults to the innerHTML of the element.
  126. * @param {Number} [min] The minumum value to return.
  127. * @param {Number} [max] The maximum value to return.
  128. * @return {Number} The text width in pixels.
  129. * @member Ext.dom.Element
  130. */
  131. getTextWidth : function(text, min, max){
  132. return Ext.Number.constrain(Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width, min || 0, max || 1000000);
  133. }
  134. });
  135. });