Update configs. IGNORE BROKEN CHANGESETS CLOSED TREE NO BUG a=release ba=release
[gecko.git] / testing / mochitest / MochiKit / Style.js
blob6abf6d7172d6ca1056d3795f91f282f6ef4a17b3
1 /***
3 MochiKit.Style 1.4
5 See <http://mochikit.com/> for documentation, downloads, license, etc.
7 (c) 2005-2006 Bob Ippolito, Beau Hartshorne.  All rights Reserved.
9 ***/
11 if (typeof(dojo) != 'undefined') {
12     dojo.provide('MochiKit.Style');
13     dojo.require('MochiKit.Base');
14     dojo.require('MochiKit.DOM');
16 if (typeof(JSAN) != 'undefined') {
17     JSAN.use('MochiKit.Base', []);
20 try {
21     if (typeof(MochiKit.Base) == 'undefined') {
22         throw '';
23     }
24 } catch (e) {
25     throw 'MochiKit.Style depends on MochiKit.Base!';
28 try {
29     if (typeof(MochiKit.DOM) == 'undefined') {
30         throw '';
31     }
32 } catch (e) {
33     throw 'MochiKit.Style depends on MochiKit.DOM!';
37 if (typeof(MochiKit.Style) == 'undefined') {
38     MochiKit.Style = {};
41 MochiKit.Style.NAME = 'MochiKit.Style';
42 MochiKit.Style.VERSION = '1.4';
43 MochiKit.Style.__repr__ = function () {
44     return '[' + this.NAME + ' ' + this.VERSION + ']';
46 MochiKit.Style.toString = function () {
47     return this.__repr__();
50 MochiKit.Style.EXPORT_OK = [];
52 MochiKit.Style.EXPORT = [
53     'setOpacity',
54     'getOpacity',
55     'setStyle',
56     'getStyle', // temporary
57     'computedStyle',
58     'getElementDimensions',
59     'elementDimensions', // deprecated
60     'setElementDimensions',
61     'getElementPosition',
62     'elementPosition', // deprecated
63     'setElementPosition',
64     'setDisplayForElement',
65     'hideElement',
66     'showElement',
67     'getViewportDimensions',
68     'getViewportPosition',
69     'Dimensions',
70     'Coordinates'
76     Dimensions
77     
79 /** @id MochiKit.Style.Dimensions */
80 MochiKit.Style.Dimensions = function (w, h) {
81     this.w = w;
82     this.h = h;
85 MochiKit.Style.Dimensions.prototype.__repr__ = function () {
86     var repr = MochiKit.Base.repr;
87     return '{w: '  + repr(this.w) + ', h: ' + repr(this.h) + '}';
90 MochiKit.Style.Dimensions.prototype.toString = function () {
91     return this.__repr__();
97     Coordinates
100 /** @id MochiKit.Style.Coordinates */
101 MochiKit.Style.Coordinates = function (x, y) {
102     this.x = x;
103     this.y = y;
106 MochiKit.Style.Coordinates.prototype.__repr__ = function () {
107     var repr = MochiKit.Base.repr;
108     return '{x: '  + repr(this.x) + ', y: ' + repr(this.y) + '}';
111 MochiKit.Style.Coordinates.prototype.toString = function () {
112     return this.__repr__();
116 MochiKit.Base.update(MochiKit.Style, {
118     /** @id MochiKit.Style.computedStyle */
119     computedStyle: function (elem, cssProperty) {
120         var dom = MochiKit.DOM;
121         var d = dom._document;
122         
123         elem = dom.getElement(elem);
124         cssProperty = MochiKit.Base.camelize(cssProperty);
125         
126         if (!elem || elem == d) {
127             return undefined;
128         }
130         /* from YUI 0.10.0 */
131         if (cssProperty == 'opacity' && elem.filters) { // IE opacity
132             try {
133                 return elem.filters.item('DXImageTransform.Microsoft.Alpha'
134                     ).opacity / 100;
135             } catch(e) {
136                 try {
137                     return elem.filters.item('alpha').opacity / 100;
138                 } catch(e) {}
139             }
140         }
141         
142         if (elem.currentStyle) {
143             return elem.currentStyle[cssProperty];
144         }
145         if (typeof(d.defaultView) == 'undefined') {
146             return undefined;
147         }
148         if (d.defaultView === null) {
149             return undefined;
150         }
151         var style = d.defaultView.getComputedStyle(elem, null);
152         if (typeof(style) == 'undefined' || style === null) {
153             return undefined;
154         }
155         
156         var selectorCase = cssProperty.replace(/([A-Z])/g, '-$1'
157             ).toLowerCase(); // from dojo.style.toSelectorCase
158             
159         return style.getPropertyValue(selectorCase);
160     },
161     
162     /** @id MochiKit.Style.getStyle */
163     getStyle: function (elem, style) {
164         elem = MochiKit.DOM.getElement(elem);
165         var value = elem.style[MochiKit.Base.camelize(style)];
166         if (!value) {
167             if (document.defaultView && document.defaultView.getComputedStyle) {
168                 var css = document.defaultView.getComputedStyle(elem, null);
169                 value = css ? css.getPropertyValue(style) : null;
170             } else if (elem.currentStyle) {
171                 value = elem.currentStyle[MochiKit.Base.camelize(style)];
172             }
173         }
175         if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.find(['left', 'top', 'right', 'bottom'], style) != -1)) {
176             if (MochiKit.Style.getStyle(elem, 'position') == 'static') {
177                 value = 'auto';
178             }
179         }
181         return value == 'auto' ? null : value;
182     },
184     /** @id MochiKit.Style.setStyle */
185     setStyle: function (elem, style) {
186         elem = MochiKit.DOM.getElement(elem);
187         for (name in style) {
188             elem.style[MochiKit.Base.camelize(name)] = style[name];
189         }
190     },
192     /** @id MochiKit.Style.getOpacity */
193     getOpacity: function (elem) {
194         var opacity;
195         if (opacity = MochiKit.Style.getStyle(elem, 'opacity')) {
196             return parseFloat(opacity);
197         }
198         if (opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/)) {
199             if (opacity[1]) {
200                 return parseFloat(opacity[1]) / 100;
201             }
202         }
203         return 1.0;
204     },
205     /** @id MochiKit.Style.setOpacity */
206     setOpacity: function(elem, o) {
207         elem = MochiKit.DOM.getElement(elem);
208         var self = MochiKit.Style;
209         if (o == 1) {
210             var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|Safari|KHTML/.test(navigator.userAgent));
211             self.setStyle(elem, {opacity: toSet ? 0.999999 : 1.0});
212             if (/MSIE/.test(navigator.userAgent)) {
213                 self.setStyle(elem, {filter:
214                     self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '')});
215             }
216         } else {
217             if (o < 0.00001) {
218                 o = 0;
219             }
220             self.setStyle(elem, {opacity: o});
221             if (/MSIE/.test(navigator.userAgent)) {
222                 self.setStyle(elem,
223                     {filter: self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')' });
224             }
225         }
226     },
228     /* 
230         getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0.
231         Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved.
232         License: BSD, http://developer.yahoo.net/yui/license.txt
234     */
235     
236     /** @id MochiKit.Style.getElementPosition */    
237     getElementPosition: function (elem, /* optional */relativeTo) {
238         var self = MochiKit.Style;
239         var dom = MochiKit.DOM;        
240         elem = dom.getElement(elem);
241         
242         if (!elem || 
243             (!(elem.x && elem.y) && 
244             (!elem.parentNode == null || 
245             self.computedStyle(elem, 'display') == 'none'))) {
246             return undefined;
247         }
249         var c = new self.Coordinates(0, 0);        
250         var box = null;
251         var parent = null;
252         
253         var d = MochiKit.DOM._document;
254         var de = d.documentElement;
255         var b = d.body;            
256     
257         if (!elem.parentNode && elem.x && elem.y) {
258             /* it's just a MochiKit.Style.Coordinates object */
259             c.x += elem.x || 0;
260             c.y += elem.y || 0;
261         } else if (elem.getBoundingClientRect) { // IE shortcut
262             /*
263             
264                 The IE shortcut can be off by two. We fix it. See:
265                 http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
266                 
267                 This is similar to the method used in 
268                 MochiKit.Signal.Event.mouse().
269                 
270             */
271             box = elem.getBoundingClientRect();
272                         
273             c.x += box.left + 
274                 (de.scrollLeft || b.scrollLeft) - 
275                 (de.clientLeft || 0);
276             
277             c.y += box.top + 
278                 (de.scrollTop || b.scrollTop) - 
279                 (de.clientTop || 0);
280             
281         } else if (elem.offsetParent) {
282             c.x += elem.offsetLeft;
283             c.y += elem.offsetTop;
284             parent = elem.offsetParent;
285             
286             if (parent != elem) {
287                 while (parent) {
288                     c.x += parent.offsetLeft;
289                     c.y += parent.offsetTop;
290                     parent = parent.offsetParent;
291                 }
292             }
294             /*
295                 
296                 Opera < 9 and old Safari (absolute) incorrectly account for 
297                 body offsetTop and offsetLeft.
298                 
299             */
300             var ua = navigator.userAgent.toLowerCase();
301             if ((typeof(opera) != 'undefined' && 
302                 parseFloat(opera.version()) < 9) || 
303                 (ua.indexOf('safari') != -1 && 
304                 self.computedStyle(elem, 'position') == 'absolute')) {
305                                 
306                 c.x -= b.offsetLeft;
307                 c.y -= b.offsetTop;
308                 
309             }
310         }
311         
312         if (typeof(relativeTo) != 'undefined') {
313             relativeTo = arguments.callee(relativeTo);
314             if (relativeTo) {
315                 c.x -= (relativeTo.x || 0);
316                 c.y -= (relativeTo.y || 0);
317             }
318         }
319         
320         if (elem.parentNode) {
321             parent = elem.parentNode;
322         } else {
323             parent = null;
324         }
325         
326         while (parent) {
327             var tagName = parent.tagName.toUpperCase();
328             if (tagName === 'BODY' || tagName === 'HTML') {
329                 break;
330             }
331             c.x -= parent.scrollLeft;
332             c.y -= parent.scrollTop;        
333             if (parent.parentNode) {
334                 parent = parent.parentNode;
335             } else {
336                 parent = null;
337             }
338         }
339         
340         return c;
341     },
342         
343     /** @id MochiKit.Style.setElementPosition */    
344     setElementPosition: function (elem, newPos/* optional */, units) {
345         elem = MochiKit.DOM.getElement(elem);
346         if (typeof(units) == 'undefined') {
347             units = 'px';
348         }
349         var newStyle = {};
350         var isUndefNull = MochiKit.Base.isUndefinedOrNull;
351         if (!isUndefNull(newPos.x)) {
352             newStyle['left'] = newPos.x + units;
353         }
354         if (!isUndefNull(newPos.y)) {
355             newStyle['top'] = newPos.y + units;
356         }
357         MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
358     },
360     /** @id MochiKit.Style.getElementDimensions */
361     getElementDimensions: function (elem) {
362         var self = MochiKit.Style;
363         var dom = MochiKit.DOM;
364         if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') {
365             return new self.Dimensions(elem.w || 0, elem.h || 0);
366         }
367         elem = dom.getElement(elem);
368         if (!elem) {
369             return undefined;
370         }
371         var disp = self.computedStyle(elem, 'display'); 
372         // display can be empty/undefined on WebKit/KHTML
373         if (disp != 'none' && disp != '' && typeof(disp) != 'undefined') { 
374             return new self.Dimensions(elem.offsetWidth || 0, 
375                 elem.offsetHeight || 0);
376         }
377         var s = elem.style;
378         var originalVisibility = s.visibility;
379         var originalPosition = s.position;
380         s.visibility = 'hidden';
381         s.position = 'absolute';
382         s.display = '';
383         var originalWidth = elem.offsetWidth;
384         var originalHeight = elem.offsetHeight;
385         s.display = 'none';
386         s.position = originalPosition; 
387         s.visibility = originalVisibility;
388         return new self.Dimensions(originalWidth, originalHeight);
389     },
391     /** @id MochiKit.Style.setElementDimensions */    
392     setElementDimensions: function (elem, newSize/* optional */, units) {
393         elem = MochiKit.DOM.getElement(elem);
394         if (typeof(units) == 'undefined') {
395             units = 'px';
396         }
397         var newStyle = {};
398         var isUndefNull = MochiKit.Base.isUndefinedOrNull;
399         if (!isUndefNull(newSize.w)) {
400             newStyle['width'] = newSize.w + units;
401         }
402         if (!isUndefNull(newSize.h)) {
403             newStyle['height'] = newSize.h + units;
404         }
405         MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
406     },
408     /** @id MochiKit.Style.setDisplayForElement */
409     setDisplayForElement: function (display, element/*, ...*/) {
410         var elements = MochiKit.Base.extend(null, arguments, 1);
411         var getElement = MochiKit.DOM.getElement;
412         for (var i = 0; i < elements.length; i++) {
413             var element = getElement(elements[i]);
414             if (element) {
415                 element.style.display = display;
416             }
417         }
418     },
420     /** @id MochiKit.Style.getViewportDimensions */
421     getViewportDimensions: function () {
422         var d = new MochiKit.Style.Dimensions();
423         
424         var w = MochiKit.DOM._window;
425         var b = MochiKit.DOM._document.body;
426         
427         if (w.innerWidth) {
428             d.w = w.innerWidth;
429             d.h = w.innerHeight;
430         } else if (b.parentElement.clientWidth) {
431             d.w = b.parentElement.clientWidth;
432             d.h = b.parentElement.clientHeight;
433         } else if (b && b.clientWidth) {
434             d.w = b.clientWidth;
435             d.h = b.clientHeight;
436         }
437         return d;
438     },
440     /** @id MochiKit.Style.getViewportPosition */
441     getViewportPosition: function () {
442         var c = new MochiKit.Style.Coordinates(0, 0);
443         var d = MochiKit.DOM._document;
444         var de = d.documentElement;
445         var db = d.body;
446         if (de && (de.scrollTop || de.scrollLeft)) {
447             c.x = de.scrollLeft;
448             c.y = de.scrollTop;
449         } else if (db) {
450             c.x = db.scrollLeft;
451             c.y = db.scrollTop;
452         }
453         return c;
454     },
456     __new__: function () {
457         var m = MochiKit.Base;
458         
459         this.elementPosition = this.getElementPosition;
460         this.elementDimensions = this.getElementDimensions;
461         
462         this.hideElement = m.partial(this.setDisplayForElement, 'none');
463         this.showElement = m.partial(this.setDisplayForElement, 'block');
464         
465         this.EXPORT_TAGS = {
466             ':common': this.EXPORT,
467             ':all': m.concat(this.EXPORT, this.EXPORT_OK)
468         };
470         m.nameFunctions(this);
471     }
474 MochiKit.Style.__new__();
475 MochiKit.Base._exportSymbols(this, MochiKit.Style);