source: Dev/branches/rest-dojo-ui/client/dojo/dom-style.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 10.7 KB
RevLine 
[256]1define(["./_base/sniff", "./dom"], function(has, dom){
2        // module:
3        //              dojo/dom-style
4        // summary:
5        //              This module defines the core dojo DOM style API.
6
7        // =============================
8        // Style Functions
9        // =============================
10
11        // getComputedStyle drives most of the style code.
12        // Wherever possible, reuse the returned object.
13        //
14        // API functions below that need to access computed styles accept an
15        // optional computedStyle parameter.
16        // If this parameter is omitted, the functions will call getComputedStyle themselves.
17        // This way, calling code can access computedStyle once, and then pass the reference to
18        // multiple API functions.
19
20        /*=====
21        dojo.getComputedStyle = function(node){
22                // summary:
23                //              Returns a "computed style" object.
24                //
25                // description:
26                //              Gets a "computed style" object which can be used to gather
27                //              information about the current state of the rendered node.
28                //
29                //              Note that this may behave differently on different browsers.
30                //              Values may have different formats and value encodings across
31                //              browsers.
32                //
33                //              Note also that this method is expensive.  Wherever possible,
34                //              reuse the returned object.
35                //
36                //              Use the dojo.style() method for more consistent (pixelized)
37                //              return values.
38                //
39                // node: DOMNode
40                //              A reference to a DOM node. Does NOT support taking an
41                //              ID string for speed reasons.
42                // example:
43                //      |       dojo.getComputedStyle(dojo.byId('foo')).borderWidth;
44                //
45                // example:
46                //              Reusing the returned object, avoiding multiple lookups:
47                //      |       var cs = dojo.getComputedStyle(dojo.byId("someNode"));
48                //      |       var w = cs.width, h = cs.height;
49                return; // CSS2Properties
50        }
51        =====*/
52
53        /*=====
54        dojo.toPixelValue = function(node, value){
55                // summary:
56                //      converts style value to pixels on IE or return a numeric value.
57                // node: DOMNode
58                // value: String
59                // returns: Number
60        };
61        =====*/
62
63        /*=====
64        dojo._toPixelValue = function(node, value){
65                // summary:
66                //              Existing alias for `dojo._toPixelValue`. Deprecated, will be removed in 2.0.
67        };
68        =====*/
69
70        /*=====
71        dojo.getStyle = function(node, name){
72                // summary:
73                //              Accesses styles on a node.
74                // description:
75                //              Getting the style value uses the computed style for the node, so the value
76                //              will be a calculated value, not just the immediate node.style value.
77                //              Also when getting values, use specific style names,
78                //              like "borderBottomWidth" instead of "border" since compound values like
79                //              "border" are not necessarily reflected as expected.
80                //              If you want to get node dimensions, use `dojo.marginBox()`,
81                //              `dojo.contentBox()` or `dojo.position()`.
82                // node: DOMNode|String
83                //              id or reference to node to get style for
84                // name: String?
85                //              the style property to get
86                // example:
87                //              Passing only an ID or node returns the computed style object of
88                //              the node:
89                //      |       dojo.getStyle("thinger");
90                // example:
91                //              Passing a node and a style property returns the current
92                //              normalized, computed value for that property:
93                //      |       dojo.getStyle("thinger", "opacity"); // 1 by default
94        };
95        =====*/
96
97        /*=====
98        dojo.setStyle = function(node, name, value){
99                // summary:
100                //              Sets styles on a node.
101                // node: DOMNode|String
102                //              id or reference to node to set style for
103                // name: String|Object
104                //              the style property to set in DOM-accessor format
105                //              ("borderWidth", not "border-width") or an object with key/value
106                //              pairs suitable for setting each property.
107                // value: String?
108                //              If passed, sets value on the node for style, handling
109                //              cross-browser concerns.  When setting a pixel value,
110                //              be sure to include "px" in the value. For instance, top: "200px".
111                //              Otherwise, in some cases, some browsers will not apply the style.
112                //
113                // example:
114                //              Passing a node, a style property, and a value changes the
115                //              current display of the node and returns the new computed value
116                //      |       dojo.setStyle("thinger", "opacity", 0.5); // == 0.5
117                //
118                // example:
119                //              Passing a node, an object-style style property sets each of the values in turn and returns the computed style object of the node:
120                //      |       dojo.setStyle("thinger", {
121                //      |               "opacity": 0.5,
122                //      |               "border": "3px solid black",
123                //      |               "height": "300px"
124                //      |       });
125                //
126                // example:
127                //              When the CSS style property is hyphenated, the JavaScript property is camelCased.
128                //              font-size becomes fontSize, and so on.
129                //      |       dojo.setStyle("thinger",{
130                //      |               fontSize:"14pt",
131                //      |               letterSpacing:"1.2em"
132                //      |       });
133                //
134                // example:
135                //              dojo.NodeList implements .style() using the same syntax, omitting the "node" parameter, calling
136                //              dojo.style() on every element of the list. See: `dojo.query()` and `dojo.NodeList()`
137                //      |       dojo.query(".someClassName").style("visibility","hidden");
138                //      |       // or
139                //      |       dojo.query("#baz > div").style({
140                //      |               opacity:0.75,
141                //      |               fontSize:"13pt"
142                //      |       });
143        };
144        =====*/
145
146        // Although we normally eschew argument validation at this
147        // level, here we test argument 'node' for (duck)type,
148        // by testing nodeType, ecause 'document' is the 'parentNode' of 'body'
149        // it is frequently sent to this function even
150        // though it is not Element.
151        var getComputedStyle, style = {};
152        //>>excludeStart("webkitMobile", kwArgs.webkitMobile);
153        if(has("webkit")){
154        //>>excludeEnd("webkitMobile");
155                getComputedStyle = function(/*DomNode*/node){
156                        var s;
157                        if(node.nodeType == 1){
158                                var dv = node.ownerDocument.defaultView;
159                                s = dv.getComputedStyle(node, null);
160                                if(!s && node.style){
161                                        node.style.display = "";
162                                        s = dv.getComputedStyle(node, null);
163                                }
164                        }
165                        return s || {};
166                };
167        //>>excludeStart("webkitMobile", kwArgs.webkitMobile);
168        }else if(has("ie") && (has("ie") < 9 || has("quirks"))){
169                getComputedStyle = function(node){
170                        // IE (as of 7) doesn't expose Element like sane browsers
171                        return node.nodeType == 1 /* ELEMENT_NODE*/ ? node.currentStyle : {};
172                };
173        }else{
174                getComputedStyle = function(node){
175                        return node.nodeType == 1 ?
176                                node.ownerDocument.defaultView.getComputedStyle(node, null) : {};
177                };
178        }
179        //>>excludeEnd("webkitMobile");
180        style.getComputedStyle = getComputedStyle;
181
182        var toPixel;
183        //>>excludeStart("webkitMobile", kwArgs.webkitMobile);
184        if(!has("ie")){
185        //>>excludeEnd("webkitMobile");
186                toPixel = function(element, value){
187                        // style values can be floats, client code may want
188                        // to round for integer pixels.
189                        return parseFloat(value) || 0;
190                };
191        //>>excludeStart("webkitMobile", kwArgs.webkitMobile);
192        }else{
193                toPixel = function(element, avalue){
194                        if(!avalue){ return 0; }
195                        // on IE7, medium is usually 4 pixels
196                        if(avalue == "medium"){ return 4; }
197                        // style values can be floats, client code may
198                        // want to round this value for integer pixels.
199                        if(avalue.slice && avalue.slice(-2) == 'px'){ return parseFloat(avalue); }
200                        var s = element.style, rs = element.runtimeStyle, cs = element.currentStyle,
201                                sLeft = s.left, rsLeft = rs.left;
202                        rs.left = cs.left;
203                        try{
204                                // 'avalue' may be incompatible with style.left, which can cause IE to throw
205                                // this has been observed for border widths using "thin", "medium", "thick" constants
206                                // those particular constants could be trapped by a lookup
207                                // but perhaps there are more
208                                s.left = avalue;
209                                avalue = s.pixelLeft;
210                        }catch(e){
211                                avalue = 0;
212                        }
213                        s.left = sLeft;
214                        rs.left = rsLeft;
215                        return avalue;
216                }
217        }
218        //>>excludeEnd("webkitMobile");
219        style.toPixelValue = toPixel;
220
221        // FIXME: there opacity quirks on FF that we haven't ported over. Hrm.
222
223        //>>excludeStart("webkitMobile", kwArgs.webkitMobile);
224        var astr = "DXImageTransform.Microsoft.Alpha";
225        var af = function(n, f){
226                try{
227                        return n.filters.item(astr);
228                }catch(e){
229                        return f ? {} : null;
230                }
231        };
232
233        //>>excludeEnd("webkitMobile");
234        var _getOpacity =
235        //>>excludeStart("webkitMobile", kwArgs.webkitMobile);
236                has("ie") < 9 || (has("ie") && has("quirks")) ? function(node){
237                        try{
238                                return af(node).Opacity / 100; // Number
239                        }catch(e){
240                                return 1; // Number
241                        }
242                } :
243        //>>excludeEnd("webkitMobile");
244                function(node){
245                        return getComputedStyle(node).opacity;
246                };
247
248        var _setOpacity =
249                //>>excludeStart("webkitMobile", kwArgs.webkitMobile);
250                has("ie") < 9 || (has("ie") && has("quirks")) ? function(/*DomNode*/node, /*Number*/opacity){
251                        var ov = opacity * 100, opaque = opacity == 1;
252                        node.style.zoom = opaque ? "" : 1;
253
254                        if(!af(node)){
255                                if(opaque){
256                                        return opacity;
257                                }
258                                node.style.filter += " progid:" + astr + "(Opacity=" + ov + ")";
259                        }else{
260                                af(node, 1).Opacity = ov;
261                        }
262
263                        // on IE7 Alpha(Filter opacity=100) makes text look fuzzy so disable it altogether (bug #2661),
264                        //but still update the opacity value so we can get a correct reading if it is read later.
265                        af(node, 1).Enabled = !opaque;
266
267                        if(node.tagName.toLowerCase() == "tr"){
268                                for(var td = node.firstChild; td; td = td.nextSibling){
269                                        if(td.tagName.toLowerCase() == "td"){
270                                                _setOpacity(td, opacity);
271                                        }
272                                }
273                        }
274                        return opacity;
275                } :
276                //>>excludeEnd("webkitMobile");
277                function(node, opacity){
278                        return node.style.opacity = opacity;
279                };
280
281        var _pixelNamesCache = {
282                left: true, top: true
283        };
284        var _pixelRegExp = /margin|padding|width|height|max|min|offset/; // |border
285        function _toStyleValue(node, type, value){
286                //TODO: should we really be doing string case conversion here? Should we cache it? Need to profile!
287                type = type.toLowerCase();
288                //>>excludeStart("webkitMobile", kwArgs.webkitMobile);
289                if(has("ie")){
290                        if(value == "auto"){
291                                if(type == "height"){ return node.offsetHeight; }
292                                if(type == "width"){ return node.offsetWidth; }
293                        }
294                        if(type == "fontweight"){
295                                switch(value){
296                                        case 700: return "bold";
297                                        case 400:
298                                        default: return "normal";
299                                }
300                        }
301                }
302                //>>excludeEnd("webkitMobile");
303                if(!(type in _pixelNamesCache)){
304                        _pixelNamesCache[type] = _pixelRegExp.test(type);
305                }
306                return _pixelNamesCache[type] ? toPixel(node, value) : value;
307        }
308
309        var _floatStyle = has("ie") ? "styleFloat" : "cssFloat",
310                _floatAliases = {"cssFloat": _floatStyle, "styleFloat": _floatStyle, "float": _floatStyle};
311
312        // public API
313
314        style.get = function getStyle(/*DOMNode|String*/ node, /*String?*/ name){
315                var n = dom.byId(node), l = arguments.length, op = (name == "opacity");
316                if(l == 2 && op){
317                        return _getOpacity(n);
318                }
319                name = _floatAliases[name] || name;
320                var s = style.getComputedStyle(n);
321                return (l == 1) ? s : _toStyleValue(n, name, s[name] || n.style[name]); /* CSS2Properties||String||Number */
322        };
323
324        style.set = function setStyle(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){
325                var n = dom.byId(node), l = arguments.length, op = (name == "opacity");
326                name = _floatAliases[name] || name;
327                if(l == 3){
328                        return op ? _setOpacity(n, value) : n.style[name] = value; // Number
329                }
330                for(var x in name){
331                        style.set(node, x, name[x]);
332                }
333                return style.getComputedStyle(n);
334        };
335
336        return style;
337});
Note: See TracBrowser for help on using the repository browser.