]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/dom/dom-style.js
Release 6.2.0beta4
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / dom / dom-style.js
1 /*
2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 3.0.0
6 build: 1549
7 */
8 YUI.add('dom-style', function(Y) {
9
10 (function(Y) {
11 /** 
12  * Add style management functionality to DOM.
13  * @module dom
14  * @submodule dom-style
15  * @for DOM
16  */
17
18 var DOCUMENT_ELEMENT = 'documentElement',
19     DEFAULT_VIEW = 'defaultView',
20     OWNER_DOCUMENT = 'ownerDocument',
21     STYLE = 'style',
22     FLOAT = 'float',
23     CSS_FLOAT = 'cssFloat',
24     STYLE_FLOAT = 'styleFloat',
25     TRANSPARENT = 'transparent',
26     GET_COMPUTED_STYLE = 'getComputedStyle',
27
28     DOCUMENT = Y.config.doc,
29     UNDEFINED = undefined,
30
31     re_color = /color$/i;
32
33
34 Y.mix(Y.DOM, {
35     CUSTOM_STYLES: {
36     },
37
38
39     /**
40      * Sets a style property for a given element.
41      * @method setStyle
42      * @param {HTMLElement} An HTMLElement to apply the style to.
43      * @param {String} att The style property to set. 
44      * @param {String|Number} val The value. 
45      */
46     setStyle: function(node, att, val, style) {
47         style = style || node.style;
48         var CUSTOM_STYLES = Y.DOM.CUSTOM_STYLES;
49
50         if (style) {
51             if (val === null) {
52                 val = ''; // normalize for unsetting
53             }
54             if (att in CUSTOM_STYLES) {
55                 if (CUSTOM_STYLES[att].set) {
56                     CUSTOM_STYLES[att].set(node, val, style);
57                     return; // NOTE: return
58                 } else if (typeof CUSTOM_STYLES[att] === 'string') {
59                     att = CUSTOM_STYLES[att];
60                 }
61             }
62             style[att] = val; 
63         }
64     },
65
66     /**
67      * Returns the current style value for the given property.
68      * @method getStyle
69      * @param {HTMLElement} An HTMLElement to get the style from.
70      * @param {String} att The style property to get. 
71      */
72     getStyle: function(node, att) {
73         var style = node[STYLE],
74             CUSTOM_STYLES = Y.DOM.CUSTOM_STYLES,
75             val = '';
76
77         if (style) {
78             if (att in CUSTOM_STYLES) {
79                 if (CUSTOM_STYLES[att].get) {
80                     return CUSTOM_STYLES[att].get(node, att, style); // NOTE: return
81                 } else if (typeof CUSTOM_STYLES[att] === 'string') {
82                     att = CUSTOM_STYLES[att];
83                 }
84             }
85             val = style[att];
86             if (val === '') { // TODO: is empty string sufficient?
87                 val = Y.DOM[GET_COMPUTED_STYLE](node, att);
88             }
89         }
90
91         return val;
92     },
93
94     /**
95      * Sets multiple style properties.
96      * @method setStyles
97      * @param {HTMLElement} node An HTMLElement to apply the styles to. 
98      * @param {Object} hash An object literal of property:value pairs. 
99      */
100     setStyles: function(node, hash) {
101         var style = node.style;
102         Y.each(hash, function(v, n) {
103             Y.DOM.setStyle(node, n, v, style);
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, null)[att];
120         }
121         return val;
122     }
123 });
124
125 // normalize reserved word float alternatives ("cssFloat" or "styleFloat")
126 if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][CSS_FLOAT] !== UNDEFINED) {
127     Y.DOM.CUSTOM_STYLES[FLOAT] = CSS_FLOAT;
128 } else if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][STYLE_FLOAT] !== UNDEFINED) {
129     Y.DOM.CUSTOM_STYLES[FLOAT] = STYLE_FLOAT;
130 }
131
132 // fix opera computedStyle default color unit (convert to rgb)
133 if (Y.UA.opera) {
134     Y.DOM[GET_COMPUTED_STYLE] = function(node, att) {
135         var view = node[OWNER_DOCUMENT][DEFAULT_VIEW],
136             val = view[GET_COMPUTED_STYLE](node, '')[att];
137
138         if (re_color.test(att)) {
139             val = Y.Color.toRGB(val);
140         }
141
142         return val;
143     };
144
145 }
146
147 // safari converts transparent to rgba(), others use "transparent"
148 if (Y.UA.webkit) {
149     Y.DOM[GET_COMPUTED_STYLE] = function(node, att) {
150         var view = node[OWNER_DOCUMENT][DEFAULT_VIEW],
151             val = view[GET_COMPUTED_STYLE](node, '')[att];
152
153         if (val === 'rgba(0, 0, 0, 0)') {
154             val = TRANSPARENT; 
155         }
156
157         return val;
158     };
159
160 }
161 })(Y);
162 (function(Y) {
163 var PARSE_INT = parseInt,
164     RE = RegExp;
165
166 Y.Color = {
167     KEYWORDS: {
168         black: '000',
169         silver: 'c0c0c0',
170         gray: '808080',
171         white: 'fff',
172         maroon: '800000',
173         red: 'f00',
174         purple: '800080',
175         fuchsia: 'f0f',
176         green: '008000',
177         lime: '0f0',
178         olive: '808000',
179         yellow: 'ff0',
180         navy: '000080',
181         blue: '00f',
182         teal: '008080',
183         aqua: '0ff'
184     },
185
186     re_RGB: /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,
187     re_hex: /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,
188     re_hex3: /([0-9A-F])/gi,
189
190     toRGB: function(val) {
191         if (!Y.Color.re_RGB.test(val)) {
192             val = Y.Color.toHex(val);
193         }
194
195         if(Y.Color.re_hex.exec(val)) {
196             val = 'rgb(' + [
197                 PARSE_INT(RE.$1, 16),
198                 PARSE_INT(RE.$2, 16),
199                 PARSE_INT(RE.$3, 16)
200             ].join(', ') + ')';
201         }
202         return val;
203     },
204
205     toHex: function(val) {
206         val = Y.Color.KEYWORDS[val] || val;
207         if (Y.Color.re_RGB.exec(val)) {
208             val = [
209                 Number(RE.$1).toString(16),
210                 Number(RE.$2).toString(16),
211                 Number(RE.$3).toString(16)
212             ];
213
214             for (var i = 0; i < val.length; i++) {
215                 if (val[i].length < 2) {
216                     val[i] = val[i].replace(Y.Color.re_hex3, '$1$1');
217                 }
218             }
219
220             val = '#' + val.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 })(Y);
235
236 (function(Y) {
237 var HAS_LAYOUT = 'hasLayout',
238     PX = 'px',
239     FILTER = 'filter',
240     FILTERS = 'filters',
241     OPACITY = 'opacity',
242     AUTO = 'auto',
243
244     BORDER_WIDTH = 'borderWidth',
245     BORDER_TOP_WIDTH = 'borderTopWidth',
246     BORDER_RIGHT_WIDTH = 'borderRightWidth',
247     BORDER_BOTTOM_WIDTH = 'borderBottomWidth',
248     BORDER_LEFT_WIDTH = 'borderLeftWidth',
249     WIDTH = 'width',
250     HEIGHT = 'height',
251     TRANSPARENT = 'transparent',
252     VISIBLE = 'visible',
253     GET_COMPUTED_STYLE = 'getComputedStyle',
254     UNDEFINED = undefined,
255     documentElement = document.documentElement,
256
257     // TODO: unit-less lineHeight (e.g. 1.22)
258     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,
259
260     _getStyleObj = function(node) {
261         return node.currentStyle || node.style;
262     },
263
264     ComputedStyle = {
265         CUSTOM_STYLES: {},
266
267         get: function(el, property) {
268             var value = '',
269                 current;
270
271             if (el) {
272                     current = _getStyleObj(el)[property];
273
274                 if (property === OPACITY && Y.DOM.CUSTOM_STYLES[OPACITY]) {
275                     value = Y.DOM.CUSTOM_STYLES[OPACITY].get(el);        
276                 } else if (!current || (current.indexOf && current.indexOf(PX) > -1)) { // no need to convert
277                     value = current;
278                 } else if (Y.DOM.IE.COMPUTED[property]) { // use compute function
279                     value = Y.DOM.IE.COMPUTED[property](el, property);
280                 } else if (re_unit.test(current)) { // convert to pixel
281                     value = ComputedStyle.getPixel(el, property) + PX;
282                 } else {
283                     value = current;
284                 }
285             }
286
287             return value;
288         },
289
290         sizeOffsets: {
291             width: ['Left', 'Right'],
292             height: ['Top', 'Bottom'],
293             top: ['Top'],
294             bottom: ['Bottom']
295         },
296
297         getOffset: function(el, prop) {
298             var current = _getStyleObj(el)[prop],                     // value of "width", "top", etc.
299                 capped = prop.charAt(0).toUpperCase() + prop.substr(1), // "Width", "Top", etc.
300                 offset = 'offset' + capped,                             // "offsetWidth", "offsetTop", etc.
301                 pixel = 'pixel' + capped,                               // "pixelWidth", "pixelTop", etc.
302                 sizeOffsets = ComputedStyle.sizeOffsets[prop], 
303                 value = '';
304
305             // IE pixelWidth incorrect for percent
306             // manually compute by subtracting padding and border from offset size
307             // NOTE: clientWidth/Height (size minus border) is 0 when current === AUTO so offsetHeight is used
308             // reverting to auto from auto causes position stacking issues (old impl)
309             if (current === AUTO || current.indexOf('%') > -1) {
310                 value = el['offset' + capped];
311
312                 if (sizeOffsets[0]) {
313                     value -= ComputedStyle.getPixel(el, 'padding' + sizeOffsets[0]);
314                     value -= ComputedStyle.getBorderWidth(el, 'border' + sizeOffsets[0] + 'Width', 1);
315                 }
316
317                 if (sizeOffsets[1]) {
318                     value -= ComputedStyle.getPixel(el, 'padding' + sizeOffsets[1]);
319                     value -= ComputedStyle.getBorderWidth(el, 'border' + sizeOffsets[1] + 'Width', 1);
320                 }
321
322             } else { // use style.pixelWidth, etc. to convert to pixels
323                 // need to map style.width to currentStyle (no currentStyle.pixelWidth)
324                 if (!el.style[pixel] && !el.style[prop]) {
325                     el.style[prop] = current;
326                 }
327                 value = el.style[pixel];
328                 
329             }
330             return value + PX;
331         },
332
333         borderMap: {
334             thin: '2px', 
335             medium: '4px', 
336             thick: '6px'
337         },
338
339         getBorderWidth: function(el, property, omitUnit) {
340             var unit = omitUnit ? '' : PX,
341                 current = el.currentStyle[property];
342
343             if (current.indexOf(PX) < 0) { // look up keywords
344                 if (ComputedStyle.borderMap[current]) {
345                     current = ComputedStyle.borderMap[current];
346                 } else {
347                 }
348             }
349             return (omitUnit) ? parseFloat(current) : current;
350         },
351
352         getPixel: function(node, att) {
353             // use pixelRight to convert to px
354             var val = null,
355                 style = _getStyleObj(node),
356                 styleRight = style.right,
357                 current = style[att];
358
359             node.style.right = current;
360             val = node.style.pixelRight;
361             node.style.right = styleRight; // revert
362
363             return val;
364         },
365
366         getMargin: function(node, att) {
367             var val,
368                 style = _getStyleObj(node);
369
370             if (style[att] == AUTO) {
371                 val = 0;
372             } else {
373                 val = ComputedStyle.getPixel(node, att);
374             }
375             return val + PX;
376         },
377
378         getVisibility: function(node, att) {
379             var current;
380             while ( (current = node.currentStyle) && current[att] == 'inherit') { // NOTE: assignment in test
381                 node = node.parentNode;
382             }
383             return (current) ? current[att] : VISIBLE;
384         },
385
386         getColor: function(node, att) {
387             var current = _getStyleObj(node)[att];
388
389             if (!current || current === TRANSPARENT) {
390                 Y.DOM.elementByAxis(node, 'parentNode', null, function(parent) {
391                     current = _getStyleObj(parent)[att];
392                     if (current && current !== TRANSPARENT) {
393                         node = parent;
394                         return true;
395                     }
396                 });
397             }
398
399             return Y.Color.toRGB(current);
400         },
401
402         getBorderColor: function(node, att) {
403             var current = _getStyleObj(node),
404                 val = current[att] || current.color;
405             return Y.Color.toRGB(Y.Color.toHex(val));
406         }
407     },
408
409     //fontSize: getPixelFont,
410     IEComputed = {};
411
412 // use alpha filter for IE opacity
413 try {
414     if (documentElement.style[OPACITY] === UNDEFINED &&
415             documentElement[FILTERS]) {
416         Y.DOM.CUSTOM_STYLES[OPACITY] = {
417             get: function(node) {
418                 var val = 100;
419                 try { // will error if no DXImageTransform
420                     val = node[FILTERS]['DXImageTransform.Microsoft.Alpha'][OPACITY];
421
422                 } catch(e) {
423                     try { // make sure its in the document
424                         val = node[FILTERS]('alpha')[OPACITY];
425                     } catch(err) {
426                     }
427                 }
428                 return val / 100;
429             },
430
431             set: function(node, val, style) {
432                 var current,
433                     styleObj;
434
435                 if (val === '') { // normalize inline style behavior
436                     styleObj = _getStyleObj(node);
437                     current = (OPACITY in styleObj) ? styleObj[OPACITY] : 1; // revert to original opacity
438                     val = current;
439                 }
440
441                 if (typeof style[FILTER] == 'string') { // in case not appended
442                     style[FILTER] = 'alpha(' + OPACITY + '=' + val * 100 + ')';
443                     
444                     if (!node.currentStyle || !node.currentStyle[HAS_LAYOUT]) {
445                         style.zoom = 1; // needs layout 
446                     }
447                 }
448             }
449         };
450     }
451 } catch(e) {
452 }
453
454 try {
455     document.createElement('div').style.height = '-1px';
456 } catch(e) { // IE throws error on invalid style set; trap common cases
457     Y.DOM.CUSTOM_STYLES.height = {
458         set: function(node, val, style) {
459             var floatVal = parseFloat(val);
460             if (isNaN(floatVal) || floatVal >= 0) {
461                 style.height = val;
462             } else {
463             }
464         }
465     };
466
467     Y.DOM.CUSTOM_STYLES.width = {
468         set: function(node, val, style) {
469             var floatVal = parseFloat(val);
470             if (isNaN(floatVal) || floatVal >= 0) {
471                 style.width = val;
472             } else {
473             }
474         }
475     };
476 }
477
478 // TODO: top, right, bottom, left
479 IEComputed[WIDTH] = IEComputed[HEIGHT] = ComputedStyle.getOffset;
480
481 IEComputed.color = IEComputed.backgroundColor = ComputedStyle.getColor;
482
483 IEComputed[BORDER_WIDTH] = IEComputed[BORDER_TOP_WIDTH] = IEComputed[BORDER_RIGHT_WIDTH] =
484         IEComputed[BORDER_BOTTOM_WIDTH] = IEComputed[BORDER_LEFT_WIDTH] =
485         ComputedStyle.getBorderWidth;
486
487 IEComputed.marginTop = IEComputed.marginRight = IEComputed.marginBottom =
488         IEComputed.marginLeft = ComputedStyle.getMargin;
489
490 IEComputed.visibility = ComputedStyle.getVisibility;
491 IEComputed.borderColor = IEComputed.borderTopColor =
492         IEComputed.borderRightColor = IEComputed.borderBottomColor =
493         IEComputed.borderLeftColor = ComputedStyle.getBorderColor;
494
495 if (!Y.config.win[GET_COMPUTED_STYLE]) {
496     Y.DOM[GET_COMPUTED_STYLE] = ComputedStyle.get; 
497 }
498
499 Y.namespace('DOM.IE');
500 Y.DOM.IE.COMPUTED = IEComputed;
501 Y.DOM.IE.ComputedStyle = ComputedStyle;
502
503 })(Y);
504
505
506 }, '3.0.0' ,{requires:['dom-base']});