commit extjs-2.2.1
[extjs.git] / source / util / TextMetrics.js
1 /*\r
2  * Ext JS Library 2.2.1\r
3  * Copyright(c) 2006-2009, Ext JS, LLC.\r
4  * licensing@extjs.com\r
5  * \r
6  * http://extjs.com/license\r
7  */\r
8 \r
9 /**\r
10  * @class Ext.util.TextMetrics\r
11  * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and\r
12  * wide, in pixels, a given block of text will be.\r
13  * @singleton\r
14  */\r
15 Ext.util.TextMetrics = function(){\r
16     var shared;\r
17     return {\r
18         /**\r
19          * Measures the size of the specified text\r
20          * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles\r
21          * that can affect the size of the rendered text\r
22          * @param {String} text The text to measure\r
23          * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width\r
24          * in order to accurately measure the text height\r
25          * @return {Object} An object containing the text's size {width: (width), height: (height)}\r
26          */\r
27         measure : function(el, text, fixedWidth){\r
28             if(!shared){\r
29                 shared = Ext.util.TextMetrics.Instance(el, fixedWidth);\r
30             }\r
31             shared.bind(el);\r
32             shared.setFixedWidth(fixedWidth || 'auto');\r
33             return shared.getSize(text);\r
34         },\r
35 \r
36         /**\r
37          * Return a unique TextMetrics instance that can be bound directly to an element and reused.  This reduces\r
38          * the overhead of multiple calls to initialize the style properties on each measurement.\r
39          * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to\r
40          * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width\r
41          * in order to accurately measure the text height\r
42          * @return {Ext.util.TextMetrics.Instance} instance The new instance\r
43          */\r
44         createInstance : function(el, fixedWidth){\r
45             return Ext.util.TextMetrics.Instance(el, fixedWidth);\r
46         }\r
47     };\r
48 }();\r
49 \r
50 Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){\r
51     var ml = new Ext.Element(document.createElement('div'));\r
52     document.body.appendChild(ml.dom);\r
53     ml.position('absolute');\r
54     ml.setLeftTop(-1000, -1000);\r
55     ml.hide();\r
56 \r
57     if(fixedWidth){\r
58         ml.setWidth(fixedWidth);\r
59     }\r
60 \r
61     var instance = {\r
62         /**\r
63          * Returns the size of the specified text based on the internal element's style and width properties\r
64          * @param {String} text The text to measure\r
65          * @return {Object} An object containing the text's size {width: (width), height: (height)}\r
66          */\r
67         getSize : function(text){\r
68             ml.update(text);\r
69             var s = ml.getSize();\r
70             ml.update('');\r
71             return s;\r
72         },\r
73 \r
74         /**\r
75          * Binds this TextMetrics instance to an element from which to copy existing CSS styles\r
76          * that can affect the size of the rendered text\r
77          * @param {String/HTMLElement} el The element, dom node or id\r
78          */\r
79         bind : function(el){\r
80             ml.setStyle(\r
81                 Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')\r
82             );\r
83         },\r
84 \r
85         /**\r
86          * Sets a fixed width on the internal measurement element.  If the text will be multiline, you have\r
87          * to set a fixed width in order to accurately measure the text height.\r
88          * @param {Number} width The width to set on the element\r
89          */\r
90         setFixedWidth : function(width){\r
91             ml.setWidth(width);\r
92         },\r
93 \r
94         /**\r
95          * Returns the measured width of the specified text\r
96          * @param {String} text The text to measure\r
97          * @return {Number} width The width in pixels\r
98          */\r
99         getWidth : function(text){\r
100             ml.dom.style.width = 'auto';\r
101             return this.getSize(text).width;\r
102         },\r
103 \r
104         /**\r
105          * Returns the measured height of the specified text.  For multiline text, be sure to call\r
106          * {@link #setFixedWidth} if necessary.\r
107          * @param {String} text The text to measure\r
108          * @return {Number} height The height in pixels\r
109          */\r
110         getHeight : function(text){\r
111             return this.getSize(text).height;\r
112         }\r
113     };\r
114 \r
115     instance.bind(bindTo);\r
116 \r
117     return instance;\r
118 };\r
119 \r
120 // backwards compat\r
121 Ext.Element.measureText = Ext.util.TextMetrics.measure;