5 See <http://mochikit.com/> for documentation, downloads, license, etc.
7 (c) 2005-2006 Bob Ippolito, Beau Hartshorne. All rights Reserved.
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', []);
18 JSAN.use('MochiKit.DOM', []);
22 if (typeof(MochiKit.Base) == 'undefined') {
26 throw 'MochiKit.Style depends on MochiKit.Base!';
30 if (typeof(MochiKit.DOM) == 'undefined') {
34 throw 'MochiKit.Style depends on MochiKit.DOM!';
38 if (typeof(MochiKit.Style) == 'undefined') {
42 MochiKit.Style.NAME = 'MochiKit.Style';
43 MochiKit.Style.VERSION = '1.4';
44 MochiKit.Style.__repr__ = function () {
45 return '[' + this.NAME + ' ' + this.VERSION + ']';
47 MochiKit.Style.toString = function () {
48 return this.__repr__();
51 MochiKit.Style.EXPORT_OK = [];
53 MochiKit.Style.EXPORT = [
57 'getElementDimensions',
58 'elementDimensions', // deprecated
59 'setElementDimensions',
61 'elementPosition', // deprecated
63 'setDisplayForElement',
66 'getViewportDimensions',
67 'getViewportPosition',
78 /** @id MochiKit.Style.Dimensions */
79 MochiKit.Style.Dimensions = function (w, h) {
84 MochiKit.Style.Dimensions.prototype.__repr__ = function () {
85 var repr = MochiKit.Base.repr;
86 return '{w: ' + repr(this.w) + ', h: ' + repr(this.h) + '}';
89 MochiKit.Style.Dimensions.prototype.toString = function () {
90 return this.__repr__();
99 /** @id MochiKit.Style.Coordinates */
100 MochiKit.Style.Coordinates = function (x, y) {
105 MochiKit.Style.Coordinates.prototype.__repr__ = function () {
106 var repr = MochiKit.Base.repr;
107 return '{x: ' + repr(this.x) + ', y: ' + repr(this.y) + '}';
110 MochiKit.Style.Coordinates.prototype.toString = function () {
111 return this.__repr__();
115 MochiKit.Base.update(MochiKit.Style, {
117 /** @id MochiKit.Style.getStyle */
118 getStyle: function (elem, cssProperty) {
119 var dom = MochiKit.DOM;
120 var d = dom._document;
122 elem = dom.getElement(elem);
123 cssProperty = MochiKit.Base.camelize(cssProperty);
125 if (!elem || elem == d) {
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;
135 var value = elem.style ? elem.style[cssProperty] : null;
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];
146 if (cssProperty == 'opacity') {
147 value = parseFloat(value);
150 if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.find(['left', 'top', 'right', 'bottom'], cssProperty) != -1)) {
151 if (MochiKit.Style.getStyle(elem, 'position') == 'static') {
156 return value == 'auto' ? null : value;
159 /** @id MochiKit.Style.setStyle */
160 setStyle: function (elem, style) {
161 elem = MochiKit.DOM.getElement(elem);
162 for (name in style) {
163 if (name == 'opacity') {
164 MochiKit.Style.setOpacity(elem, style[name]);
166 elem.style[MochiKit.Base.camelize(name)] = style[name];
171 /** @id MochiKit.Style.setOpacity */
172 setOpacity: function (elem, o) {
173 elem = MochiKit.DOM.getElement(elem);
174 var self = MochiKit.Style;
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, '');
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 + ')';
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
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);
209 (!(elem.x && elem.y) &&
210 (!elem.parentNode === null ||
211 self.getStyle(elem, 'display') == 'none'))) {
215 var c = new self.Coordinates(0, 0);
219 var d = MochiKit.DOM._document;
220 var de = d.documentElement;
223 if (!elem.parentNode && elem.x && elem.y) {
224 /* it's just a MochiKit.Style.Coordinates object */
227 } else if (elem.getBoundingClientRect) { // IE shortcut
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
233 This is similar to the method used in
234 MochiKit.Signal.Event.mouse().
237 box = elem.getBoundingClientRect();
240 (de.scrollLeft || b.scrollLeft) -
241 (de.clientLeft || 0);
244 (de.scrollTop || b.scrollTop) -
247 } else if (elem.offsetParent) {
248 c.x += elem.offsetLeft;
249 c.y += elem.offsetTop;
250 parent = elem.offsetParent;
252 if (parent != elem) {
254 c.x += parent.offsetLeft;
255 c.y += parent.offsetTop;
256 parent = parent.offsetParent;
262 Opera < 9 and old Safari (absolute) incorrectly account for
263 body offsetTop and offsetLeft.
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')) {
278 if (typeof(relativeTo) != 'undefined') {
279 relativeTo = arguments.callee(relativeTo);
281 c.x -= (relativeTo.x || 0);
282 c.y -= (relativeTo.y || 0);
286 if (elem.parentNode) {
287 parent = elem.parentNode;
293 var tagName = parent.tagName.toUpperCase();
294 if (tagName === 'BODY' || tagName === 'HTML') {
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;
303 if (parent.parentNode) {
304 parent = parent.parentNode;
313 /** @id MochiKit.Style.setElementPosition */
314 setElementPosition: function (elem, newPos/* optional */, units) {
315 elem = MochiKit.DOM.getElement(elem);
316 if (typeof(units) == 'undefined') {
320 var isUndefNull = MochiKit.Base.isUndefinedOrNull;
321 if (!isUndefNull(newPos.x)) {
322 newStyle['left'] = newPos.x + units;
324 if (!isUndefNull(newPos.y)) {
325 newStyle['top'] = newPos.y + units;
327 MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
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);
337 elem = dom.getElement(elem);
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);
348 var originalVisibility = s.visibility;
349 var originalPosition = s.position;
350 s.visibility = 'hidden';
351 s.position = 'absolute';
353 var originalWidth = elem.offsetWidth;
354 var originalHeight = elem.offsetHeight;
356 s.position = originalPosition;
357 s.visibility = originalVisibility;
358 return new self.Dimensions(originalWidth, originalHeight);
361 /** @id MochiKit.Style.setElementDimensions */
362 setElementDimensions: function (elem, newSize/* optional */, units) {
363 elem = MochiKit.DOM.getElement(elem);
364 if (typeof(units) == 'undefined') {
368 var isUndefNull = MochiKit.Base.isUndefinedOrNull;
369 if (!isUndefNull(newSize.w)) {
370 newStyle['width'] = newSize.w + units;
372 if (!isUndefNull(newSize.h)) {
373 newStyle['height'] = newSize.h + units;
375 MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
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]);
385 element.style.display = display;
390 /** @id MochiKit.Style.getViewportDimensions */
391 getViewportDimensions: function () {
392 var d = new MochiKit.Style.Dimensions();
394 var w = MochiKit.DOM._window;
395 var b = MochiKit.DOM._document.body;
400 } else if (b.parentElement.clientWidth) {
401 d.w = b.parentElement.clientWidth;
402 d.h = b.parentElement.clientHeight;
403 } else if (b && b.clientWidth) {
405 d.h = b.clientHeight;
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;
416 if (de && (de.scrollTop || de.scrollLeft)) {
426 __new__: function () {
427 var m = MochiKit.Base;
429 this.elementPosition = this.getElementPosition;
430 this.elementDimensions = this.getElementDimensions;
432 this.hideElement = m.partial(this.setDisplayForElement, 'none');
433 this.showElement = m.partial(this.setDisplayForElement, 'block');
436 ':common': this.EXPORT,
437 ':all': m.concat(this.EXPORT, this.EXPORT_OK)
440 m.nameFunctions(this);
444 MochiKit.Style.__new__();
445 MochiKit.Base._exportSymbols(this, MochiKit.Style);