~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/static/javascript/yui/build/dom/dom-style.js

[rs=mwhudson] Merged the latest and greatest from trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
 
3
Code licensed under the BSD License:
 
4
http://developer.yahoo.net/yui/license.txt
 
5
version: 3.0.0pr1
 
6
*/
 
7
YUI.add('dom-style', function(Y) {
 
8
 
 
9
/** 
 
10
 * Add style management functionality to DOM.
 
11
 * @module dom
 
12
 * @submodule dom-style
 
13
 * @for DOM
 
14
 */
 
15
 
 
16
var DOCUMENT_ELEMENT = 'documentElement',
 
17
    DEFAULT_VIEW = 'defaultView',
 
18
    OWNER_DOCUMENT = 'ownerDocument',
 
19
    STYLE = 'style',
 
20
    FLOAT = 'float',
 
21
    CSS_FLOAT = 'cssFloat',
 
22
    STYLE_FLOAT = 'styleFloat',
 
23
    TRANSPARENT = 'transparent',
 
24
    VISIBLE = 'visible',
 
25
    WIDTH = 'width',
 
26
    HEIGHT = 'height',
 
27
    BORDER_TOP_WIDTH = 'borderTopWidth',
 
28
    BORDER_RIGHT_WIDTH = 'borderRightWidth',
 
29
    BORDER_BOTTOM_WIDTH = 'borderBottomWidth',
 
30
    BORDER_LEFT_WIDTH = 'borderLeftWidth',
 
31
    GET_COMPUTED_STYLE = 'getComputedStyle',
 
32
 
 
33
    DOCUMENT = Y.config.doc,
 
34
    UNDEFINED = undefined,
 
35
 
 
36
    re_color = /color$/i;
 
37
 
 
38
 
 
39
Y.mix(Y.DOM, {
 
40
    CUSTOM_STYLES: {},
 
41
 
 
42
 
 
43
    /**
 
44
     * Sets a style property for a given element.
 
45
     * @method setStyle
 
46
     * @param {HTMLElement} An HTMLElement to apply the style to.
 
47
     * @param {String} att The style property to set. 
 
48
     * @param {String|Number} val The value. 
 
49
     */
 
50
    setStyle: function(node, att, val) {
 
51
        var style = node[STYLE],
 
52
            CUSTOM_STYLES = Y.DOM.CUSTOM_STYLES;
 
53
 
 
54
        if (style) {
 
55
            if (att in CUSTOM_STYLES) {
 
56
                if (CUSTOM_STYLES[att].set) {
 
57
                    CUSTOM_STYLES[att].set(node, val, style);
 
58
                    return; // NOTE: return
 
59
                } else if (typeof CUSTOM_STYLES[att] === 'string') {
 
60
                    att = CUSTOM_STYLES[att];
 
61
                }
 
62
            }
 
63
            style[att] = val; 
 
64
        }
 
65
    },
 
66
 
 
67
    /**
 
68
     * Returns the current style value for the given property.
 
69
     * @method getStyle
 
70
     * @param {HTMLElement} An HTMLElement to get the style from.
 
71
     * @param {String} att The style property to get. 
 
72
     */
 
73
    getStyle: function(node, att) {
 
74
        var style = node[STYLE],
 
75
            CUSTOM_STYLES = Y.DOM.CUSTOM_STYLES,
 
76
            val = '';
 
77
 
 
78
        if (style) {
 
79
            if (att in CUSTOM_STYLES) {
 
80
                if (CUSTOM_STYLES[att].get) {
 
81
                    return CUSTOM_STYLES[att].get(node, att, style); // NOTE: return
 
82
                } else if (typeof CUSTOM_STYLES[att] === 'string') {
 
83
                    att = CUSTOM_STYLES[att];
 
84
                }
 
85
            }
 
86
            val = style[att];
 
87
            if (val === '') { // TODO: is empty string sufficient?
 
88
                val = Y.DOM[GET_COMPUTED_STYLE](node, att);
 
89
            }
 
90
        }
 
91
 
 
92
        return val;
 
93
    },
 
94
 
 
95
    /**
 
96
     * Sets multiple style properties.
 
97
     * @method setStyles
 
98
     * @param {HTMLElement} node An HTMLElement to apply the styles to. 
 
99
     * @param {Object} hash An object literal of property:value pairs. 
 
100
     */
 
101
    'setStyles': function(node, hash) {
 
102
        Y.each(hash, function(v, n) {
 
103
            Y.DOM.setStyle(node, n, v);
 
104
        }, Y.DOM);
 
105
    },
 
106
 
 
107
    /**
 
108
     * Returns the computed style for the given node.
 
109
     * @method getComputedStyle
 
110
     * @param {HTMLElement} An HTMLElement to get the style from.
 
111
     * @param {String} att The style property to get. 
 
112
     * @return {String} The computed value of the style property. 
 
113
     */
 
114
    getComputedStyle: function(node, att) {
 
115
        var val = '',
 
116
            doc = node[OWNER_DOCUMENT];
 
117
 
 
118
        if (node[STYLE]) {
 
119
            val = doc[DEFAULT_VIEW][GET_COMPUTED_STYLE](node, '')[att];
 
120
        }
 
121
        return val;
 
122
    }
 
123
});
 
124
 
 
125
if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][CSS_FLOAT] !== UNDEFINED) {
 
126
    Y.DOM.CUSTOM_STYLES[FLOAT] = CSS_FLOAT;
 
127
} else if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][STYLE_FLOAT] !== UNDEFINED) {
 
128
    Y.DOM.CUSTOM_STYLES[FLOAT] = STYLE_FLOAT;
 
129
}
 
130
 
 
131
if (Y.UA.opera) { // opera defaults to hex instead of RGB
 
132
    Y.DOM[GET_COMPUTED_STYLE] = function(node, att) {
 
133
        var view = node[OWNER_DOCUMENT][DEFAULT_VIEW],
 
134
            val = view[GET_COMPUTED_STYLE](node, '')[att];
 
135
 
 
136
        if (re_color.test(att)) {
 
137
            val = Y.Color.toRGB(val);
 
138
        }
 
139
 
 
140
        return val;
 
141
    };
 
142
 
 
143
}
 
144
 
 
145
if (Y.UA.webkit) { // safari converts transparent to rgba()
 
146
    Y.DOM[GET_COMPUTED_STYLE] = function(node, att) {
 
147
        var view = node[OWNER_DOCUMENT][DEFAULT_VIEW],
 
148
            val = view[GET_COMPUTED_STYLE](node, '')[att];
 
149
 
 
150
        if (val === 'rgba(0, 0, 0, 0)') {
 
151
            val = TRANSPARENT; 
 
152
        }
 
153
 
 
154
        return val;
 
155
    };
 
156
 
 
157
}
 
158
 
 
159
/**
 
160
 * Add style management functionality to DOM.
 
161
 * @module dom
 
162
 * @submodule dom-style
 
163
 * @for DOM
 
164
 */
 
165
 
 
166
var TO_STRING = 'toString',
 
167
    PARSE_INT = parseInt,
 
168
    RE = RegExp;
 
169
 
 
170
Y.Color = {
 
171
    KEYWORDS: {
 
172
        black: '000',
 
173
        silver: 'c0c0c0',
 
174
        gray: '808080',
 
175
        white: 'fff',
 
176
        maroon: '800000',
 
177
        red: 'f00',
 
178
        purple: '800080',
 
179
        fuchsia: 'f0f',
 
180
        green: '008000',
 
181
        lime: '0f0',
 
182
        olive: '808000',
 
183
        yellow: 'ff0',
 
184
        navy: '000080',
 
185
        blue: '00f',
 
186
        teal: '008080',
 
187
        aqua: '0ff'
 
188
    },
 
189
 
 
190
    re_RGB: /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,
 
191
    re_hex: /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,
 
192
    re_hex3: /([0-9A-F])/gi,
 
193
 
 
194
    toRGB: function(val) {
 
195
        if (!Y.Color.re_RGB.test(val)) {
 
196
            val = Y.Color.toHex(val);
 
197
        }
 
198
 
 
199
        if(Y.Color.re_hex.exec(val)) {
 
200
            val = 'rgb(' + [
 
201
                PARSE_INT(RE.$1, 16),
 
202
                PARSE_INT(RE.$2, 16),
 
203
                PARSE_INT(RE.$3, 16)
 
204
            ].join(', ') + ')';
 
205
        }
 
206
        return val;
 
207
    },
 
208
 
 
209
    toHex: function(val) {
 
210
        val = Y.Color.KEYWORDS[val] || val;
 
211
        if (Y.Color.re_RGB.exec(val)) {
 
212
            var r = (RE.$1.length === 1) ? '0' + RE.$1 : Number(RE.$1),
 
213
                g = (RE.$2.length === 1) ? '0' + RE.$2 : Number(RE.$2),
 
214
                b = (RE.$3.length === 1) ? '0' + RE.$3 : Number(RE.$3);
 
215
 
 
216
            val = [
 
217
                r[TO_STRING](16),
 
218
                g[TO_STRING](16),
 
219
                b[TO_STRING](16)
 
220
            ].join('');
 
221
        }
 
222
 
 
223
        if (val.length < 6) {
 
224
            val = val.replace(Y.Color.re_hex3, '$1$1');
 
225
        }
 
226
 
 
227
        if (val !== 'transparent' && val.indexOf('#') < 0) {
 
228
            val = '#' + val;
 
229
        }
 
230
 
 
231
        return val.toLowerCase();
 
232
    }
 
233
};
 
234
 
 
235
/**
 
236
 * Add style management functionality to DOM.
 
237
 * @module dom
 
238
 * @submodule dom-style
 
239
 * @for DOM
 
240
 */
 
241
 
 
242
var CLIENT_TOP = 'clientTop',
 
243
    CLIENT_LEFT = 'clientLeft',
 
244
    PARENT_NODE = 'parentNode',
 
245
    RIGHT = 'right',
 
246
    HAS_LAYOUT = 'hasLayout',
 
247
    PX = 'px',
 
248
    FILTER = 'filter',
 
249
    FILTERS = 'filters',
 
250
    OPACITY = 'opacity',
 
251
    AUTO = 'auto',
 
252
    CURRENT_STYLE = 'currentStyle';
 
253
 
 
254
// use alpha filter for IE opacity
 
255
if (document[DOCUMENT_ELEMENT][STYLE][OPACITY] === UNDEFINED &&
 
256
        document[DOCUMENT_ELEMENT][FILTERS]) {
 
257
    Y.DOM.CUSTOM_STYLES[OPACITY] = {
 
258
        get: function(node) {
 
259
            var val = 100;
 
260
            try { // will error if no DXImageTransform
 
261
                val = node[FILTERS]['DXImageTransform.Microsoft.Alpha'][OPACITY];
 
262
 
 
263
            } catch(e) {
 
264
                try { // make sure its in the document
 
265
                    val = node[FILTERS]('alpha')[OPACITY];
 
266
                } catch(err) {
 
267
                }
 
268
            }
 
269
            return val / 100;
 
270
        },
 
271
 
 
272
        set: function(node, val, style) {
 
273
            if (typeof style[FILTER] == 'string') { // in case not appended
 
274
                style[FILTER] = 'alpha(' + OPACITY + '=' + val * 100 + ')';
 
275
                
 
276
                if (!node[CURRENT_STYLE] || !node[CURRENT_STYLE][HAS_LAYOUT]) {
 
277
                    style.zoom = 1; // needs layout 
 
278
                }
 
279
            }
 
280
        }
 
281
    };
 
282
}
 
283
 
 
284
// IE getComputedStyle
 
285
// TODO: unit-less lineHeight (e.g. 1.22)
 
286
var re_size = /^width|height$/,
 
287
    re_unit = /^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i;
 
288
 
 
289
var ComputedStyle = {
 
290
    CUSTOM_STYLES: {},
 
291
 
 
292
    get: function(el, property) {
 
293
        var value = '',
 
294
            current = el[CURRENT_STYLE][property];
 
295
 
 
296
        if (property === OPACITY) {
 
297
            value = Y.DOM.CUSTOM_STYLES[OPACITY].get(el);        
 
298
        } else if (!current || current.indexOf(PX) > -1) { // no need to convert
 
299
            value = current;
 
300
        } else if (Y.DOM.IE.COMPUTED[property]) { // use compute function
 
301
            value = Y.DOM.IE.COMPUTED[property](el, property);
 
302
        } else if (re_unit.test(current)) { // convert to pixel
 
303
            value = Y.DOM.IE.ComputedStyle.getPixel(el, property);
 
304
        } else {
 
305
            value = current;
 
306
        }
 
307
 
 
308
        return value;
 
309
    },
 
310
 
 
311
    getOffset: function(el, prop) {
 
312
        var current = el[CURRENT_STYLE][prop],                        // value of "width", "top", etc.
 
313
            capped = prop.charAt(0).toUpperCase() + prop.substr(1), // "Width", "Top", etc.
 
314
            offset = 'offset' + capped,                             // "offsetWidth", "offsetTop", etc.
 
315
            pixel = 'pixel' + capped,                               // "pixelWidth", "pixelTop", etc.
 
316
            value = '';
 
317
 
 
318
        if (current == AUTO) {
 
319
            var actual = el[offset]; // offsetHeight/Top etc.
 
320
            if (actual === UNDEFINED) { // likely "right" or "bottom"
 
321
                value = 0;
 
322
            }
 
323
 
 
324
            value = actual;
 
325
            if (re_size.test(prop)) { // account for box model diff 
 
326
                el[STYLE][prop] = actual; 
 
327
                if (el[offset] > actual) {
 
328
                    // the difference is padding + border (works in Standards & Quirks modes)
 
329
                    value = actual - (el[offset] - actual);
 
330
                }
 
331
                el[STYLE][prop] = AUTO; // revert to auto
 
332
            }
 
333
        } else { // convert units to px
 
334
            if (!el[STYLE][pixel] && !el[STYLE][prop]) { // need to map style.width to currentStyle (no currentStyle.pixelWidth)
 
335
                el[STYLE][prop] = current;              // no style.pixelWidth if no style.width
 
336
            }
 
337
            value = el[STYLE][pixel];
 
338
        }
 
339
        return value + PX;
 
340
    },
 
341
 
 
342
    getBorderWidth: function(el, property) {
 
343
        // clientHeight/Width = paddingBox (e.g. offsetWidth - borderWidth)
 
344
        // clientTop/Left = borderWidth
 
345
        var value = null;
 
346
        if (!el[CURRENT_STYLE][HAS_LAYOUT]) { // TODO: unset layout?
 
347
            el[STYLE].zoom = 1; // need layout to measure client
 
348
        }
 
349
 
 
350
        switch(property) {
 
351
            case BORDER_TOP_WIDTH:
 
352
                value = el[CLIENT_TOP];
 
353
                break;
 
354
            case BORDER_BOTTOM_WIDTH:
 
355
                value = el.offsetHeight - el.clientHeight - el[CLIENT_TOP];
 
356
                break;
 
357
            case BORDER_LEFT_WIDTH:
 
358
                value = el[CLIENT_LEFT];
 
359
                break;
 
360
            case BORDER_RIGHT_WIDTH:
 
361
                value = el.offsetWidth - el.clientWidth - el[CLIENT_LEFT];
 
362
                break;
 
363
        }
 
364
        return value + PX;
 
365
    },
 
366
 
 
367
    getPixel: function(node, att) {
 
368
        // use pixelRight to convert to px
 
369
        var val = null,
 
370
            styleRight = node[CURRENT_STYLE][RIGHT],
 
371
            current = node[CURRENT_STYLE][att];
 
372
 
 
373
        node[STYLE][RIGHT] = current;
 
374
        val = node[STYLE].pixelRight;
 
375
        node[STYLE][RIGHT] = styleRight; // revert
 
376
 
 
377
        return val + PX;
 
378
    },
 
379
 
 
380
    getMargin: function(node, att) {
 
381
        var val;
 
382
        if (node[CURRENT_STYLE][att] == AUTO) {
 
383
            val = 0 + PX;
 
384
        } else {
 
385
            val = Y.DOM.IE.ComputedStyle.getPixel(node, att);
 
386
        }
 
387
        return val;
 
388
    },
 
389
 
 
390
    getVisibility: function(node, att) {
 
391
        var current;
 
392
        while ( (current = node[CURRENT_STYLE]) && current[att] == 'inherit') { // NOTE: assignment in test
 
393
            node = node[PARENT_NODE];
 
394
        }
 
395
        return (current) ? current[att] : VISIBLE;
 
396
    },
 
397
 
 
398
    getColor: function(node, att) {
 
399
        var current = node[CURRENT_STYLE][att];
 
400
 
 
401
        if (!current || current === TRANSPARENT) {
 
402
            Y.DOM.elementByAxis(node, PARENT_NODE, null, function(parent) {
 
403
                current = parent[CURRENT_STYLE][att];
 
404
                if (current && current !== TRANSPARENT) {
 
405
                    node = parent;
 
406
                    return true;
 
407
                }
 
408
            });
 
409
        }
 
410
 
 
411
        return Y.Color.toRGB(current);
 
412
    },
 
413
 
 
414
    getBorderColor: function(node, att) {
 
415
        var current = node[CURRENT_STYLE];
 
416
        var val = current[att] || current.color;
 
417
        return Y.Color.toRGB(Y.Color.toHex(val));
 
418
    }
 
419
 
 
420
};
 
421
 
 
422
//fontSize: getPixelFont,
 
423
var IEComputed = {};
 
424
 
 
425
IEComputed[WIDTH] = IEComputed[HEIGHT] = ComputedStyle.getOffset;
 
426
 
 
427
IEComputed.color = IEComputed.backgroundColor = ComputedStyle.getColor;
 
428
 
 
429
IEComputed[BORDER_TOP_WIDTH] = IEComputed[BORDER_RIGHT_WIDTH] =
 
430
        IEComputed[BORDER_BOTTOM_WIDTH] = IEComputed[BORDER_LEFT_WIDTH] =
 
431
        ComputedStyle.getBorderWidth;
 
432
 
 
433
IEComputed.marginTop = IEComputed.marginRight = IEComputed.marginBottom =
 
434
        IEComputed.marginLeft = ComputedStyle.getMargin;
 
435
 
 
436
IEComputed.visibility = ComputedStyle.getVisibility;
 
437
IEComputed.borderColor = IEComputed.borderTopColor =
 
438
        IEComputed.borderRightColor = IEComputed.borderBottomColor =
 
439
        IEComputed.borderLeftColor = ComputedStyle.getBorderColor;
 
440
 
 
441
if (!Y.config.win[GET_COMPUTED_STYLE]) {
 
442
    Y.DOM[GET_COMPUTED_STYLE] = ComputedStyle.get; 
 
443
}
 
444
 
 
445
Y.namespace('DOM.IE');
 
446
Y.DOM.IE.COMPUTED = IEComputed;
 
447
Y.DOM.IE.ComputedStyle = ComputedStyle;
 
448
 
 
449
 
 
450
 
 
451
}, '3.0.0pr1' ,{skinnable:false, requires:['dom-base']});