X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/2e847cf21b8ab9d15fa167b315ca5b2fa92638fc..7a654f8d43fdb43d78b63d90528bed6e86b608cc:/src/util/TextMetrics.js diff --git a/src/util/TextMetrics.js b/src/util/TextMetrics.js index 4e2f397c..e0c5967d 100644 --- a/src/util/TextMetrics.js +++ b/src/util/TextMetrics.js @@ -1,19 +1,21 @@ -/*! - * Ext JS Library 3.1.1 - * Copyright(c) 2006-2010 Ext JS, LLC - * licensing@extjs.com - * http://www.extjs.com/license - */ /** * @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 + * 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.util.TextMetrics = function(){ - var shared; - return { +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 @@ -23,114 +25,126 @@ Ext.util.TextMetrics = function(){ * 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){ + measure: function(el, text, fixedWidth){ + var me = this, + shared = me.shared; + if(!shared){ - shared = Ext.util.TextMetrics.Instance(el, fixedWidth); + shared = me.shared = new me(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 = { - /** - *

Only available on the instance returned from {@link #createInstance}, not on the singleton.

- * 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; - }, - + /** - *

Only available on the instance returned from {@link #createInstance}, not on the singleton.

- * 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') - ); - }, - - /** - *

Only available on the instance returned from {@link #createInstance}, not on the singleton.

- * 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); - }, - - /** - *

Only available on the instance returned from {@link #createInstance}, not on the singleton.

- * 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; - }, + * Destroy the TextMetrics instance created by {@link #measure}. + */ + destroy: function(){ + var me = this; + Ext.destroy(me.shared); + me.shared = null; + } + }, + + /** + * @constructor + * @param {Mixed} bindTo The element to bind to. + * @param {Number} fixedWidth 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(); - /** - *

Only available on the instance returned from {@link #createInstance}, not on the singleton.

- * 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; + if (fixedWidth) { + measure.setWidth(fixedWidth); } - }; - - instance.bind(bindTo); - - return instance; -}; - -Ext.Element.addMethods({ + }, + + /** + *

Only available on the instance returned from {@link #createInstance}, not on the singleton.

+ * 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; + }, + /** - * 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 + * Binds this TextMetrics instance to a new element + * @param {Mixed} el The element */ - 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); - } + 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.core.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.core.Element getTextWidth + */ + 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); + } + }); });