/** * @class Ext.util.TextMetrics * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and * wide, in pixels, a given block of text will be. Note that when measuring text, it should be plain text and * should not contain any HTML, otherwise it may not be measured correctly. * @singleton */ Ext.util.TextMetrics = function(){ var shared; return { /** * Measures the size of the specified text * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles * that can affect the size of the rendered text * @param {String} text The text to measure * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width * in order to accurately measure the text height * @return {Object} An object containing the text's size {width: (width), height: (height)} */ measure : function(el, text, fixedWidth){ if(!shared){ shared = Ext.util.TextMetrics.Instance(el, fixedWidth); } shared.bind(el); shared.setFixedWidth(fixedWidth || 'auto'); return shared.getSize(text); }, /** * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces * the overhead of multiple calls to initialize the style properties on each measurement. * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width * in order to accurately measure the text height * @return {Ext.util.TextMetrics.Instance} instance The new instance */ createInstance : function(el, fixedWidth){ return Ext.util.TextMetrics.Instance(el, fixedWidth); } }; }(); Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){ var ml = new Ext.Element(document.createElement('div')); document.body.appendChild(ml.dom); ml.position('absolute'); ml.setLeftTop(-1000, -1000); ml.hide(); if(fixedWidth){ ml.setWidth(fixedWidth); } var instance = { /** * <p><b>Only available on the instance returned from {@link #createInstance}, <u>not</u> on the singleton.</b></p> * Returns the size of the specified text based on the internal element's style and width properties * @param {String} text The text to measure * @return {Object} An object containing the text's size {width: (width), height: (height)} */ getSize : function(text){ ml.update(text); var s = ml.getSize(); ml.update(''); return s; }, /** * <p><b>Only available on the instance returned from {@link #createInstance}, <u>not</u> on the singleton.</b></p> * Binds this TextMetrics instance to an element from which to copy existing CSS styles * that can affect the size of the rendered text * @param {String/HTMLElement} el The element, dom node or id */ bind : function(el){ ml.setStyle( Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing') ); }, /** * <p><b>Only available on the instance returned from {@link #createInstance}, <u>not</u> on the singleton.</b></p> * Sets a fixed width on the internal measurement element. If the text will be multiline, you have * to set a fixed width in order to accurately measure the text height. * @param {Number} width The width to set on the element */ setFixedWidth : function(width){ ml.setWidth(width); }, /** * <p><b>Only available on the instance returned from {@link #createInstance}, <u>not</u> on the singleton.</b></p> * Returns the measured width of the specified text * @param {String} text The text to measure * @return {Number} width The width in pixels */ getWidth : function(text){ ml.dom.style.width = 'auto'; return this.getSize(text).width; }, /** * <p><b>Only available on the instance returned from {@link #createInstance}, <u>not</u> on the singleton.</b></p> * Returns the measured height of the specified text. For multiline text, be sure to call * {@link #setFixedWidth} if necessary. * @param {String} text The text to measure * @return {Number} height The height in pixels */ getHeight : function(text){ return this.getSize(text).height; } }; instance.bind(bindTo); return instance; }; Ext.Element.addMethods({ /** * Returns the width in pixels of the passed text, or the width of the text in this Element. * @param {String} text The text to measure. Defaults to the innerHTML of the element. * @param {Number} min (Optional) The minumum value to return. * @param {Number} max (Optional) The maximum value to return. * @return {Number} The text width in pixels. * @member Ext.Element getTextWidth */ getTextWidth : function(text, min, max){ return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000); } });