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