/** * 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. * * The measurement works by copying the relevant CSS styles that can affect the font related display, * then checking the size of an element that is auto-sized. Note that if the text is multi-lined, you must * provide a **fixed width** when doing the measurement. * * If multiple measurements are being done on the same element, you create a new instance to initialize * to avoid the overhead of copying the styles to the element repeatedly. */ Ext.define('Ext.util.TextMetrics', { statics: { shared: null, /** * 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){ var me = this, shared = me.shared; if(!shared){ shared = me.shared = new me(el, fixedWidth); } shared.bind(el); shared.setFixedWidth(fixedWidth || 'auto'); return shared.getSize(text); }, /** * Destroy the TextMetrics instance created by {@link #measure}. */ destroy: function(){ var me = this; Ext.destroy(me.shared); me.shared = null; } }, /** * Creates new TextMetrics. * @param {String/HTMLElement/Ext.Element} bindTo The element or its ID to bind to. * @param {Number} fixedWidth (optional) A fixed width to apply to the measuring element. */ constructor: function(bindTo, fixedWidth){ var measure = this.measure = Ext.getBody().createChild({ cls: 'x-textmetrics' }); this.el = Ext.get(bindTo); measure.position('absolute'); measure.setLeftTop(-1000, -1000); measure.hide(); if (fixedWidth) { measure.setWidth(fixedWidth); } }, /** * 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){ var measure = this.measure, size; measure.update(text); size = measure.getSize(); measure.update(''); return size; }, /** * Binds this TextMetrics instance to a new element * @param {String/HTMLElement/Ext.Element} el The element or its ID. */ bind: function(el){ var me = this; me.el = Ext.get(el); me.measure.setStyle( me.el.getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing') ); }, /** * 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){ this.measure.setWidth(width); }, /** * 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){ this.measure.dom.style.width = 'auto'; return this.getSize(text).width; }, /** * Returns the measured height of the specified text * @param {String} text The text to measure * @return {Number} height The height in pixels */ getHeight : function(text){ return this.getSize(text).height; }, /** * Destroy this instance */ destroy: function(){ var me = this; me.measure.remove(); delete me.el; delete me.measure; } }, function(){ 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 : function(text, min, max){ return Ext.Number.constrain(Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width, min || 0, max || 1000000); } }); });