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', []);
21 if (typeof(MochiKit.Base) == 'undefined') {
25 throw 'MochiKit.Style depends on MochiKit.Base!';
29 if (typeof(MochiKit.DOM) == 'undefined') {
33 throw 'MochiKit.Style depends on MochiKit.DOM!';
37 if (typeof(MochiKit.Style) == 'undefined') {
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 = [
56 'getStyle', // temporary
58 'getElementDimensions',
59 'elementDimensions', // deprecated
60 'setElementDimensions',
62 'elementPosition', // deprecated
64 'setDisplayForElement',
67 'getViewportDimensions',
68 'getViewportPosition',
79 /** @id MochiKit.Style.Dimensions */
80 MochiKit.Style.Dimensions = function (w, 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__();
100 /** @id MochiKit.Style.Coordinates */
101 MochiKit.Style.Coordinates = function (x, 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;
123 elem = dom.getElement(elem);
124 cssProperty = MochiKit.Base.camelize(cssProperty);
126 if (!elem || elem == d) {
130 /* from YUI 0.10.0 */
131 if (cssProperty == 'opacity' && elem.filters) { // IE opacity
133 return elem.filters.item('DXImageTransform.Microsoft.Alpha'
137 return elem.filters.item('alpha').opacity / 100;
142 if (elem.currentStyle) {
143 return elem.currentStyle[cssProperty];
145 if (typeof(d.defaultView) == 'undefined') {
148 if (d.defaultView === null) {
151 var style = d.defaultView.getComputedStyle(elem, null);
152 if (typeof(style) == 'undefined' || style === null) {
156 var selectorCase = cssProperty.replace(/([A-Z])/g, '-$1'
157 ).toLowerCase(); // from dojo.style.toSelectorCase
159 return style.getPropertyValue(selectorCase);
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)];
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)];
175 if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.find(['left', 'top', 'right', 'bottom'], style) != -1)) {
176 if (MochiKit.Style.getStyle(elem, 'position') == 'static') {
181 return value == 'auto' ? null : value;
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];
192 /** @id MochiKit.Style.getOpacity */
193 getOpacity: function (elem) {
195 if (opacity = MochiKit.Style.getStyle(elem, 'opacity')) {
196 return parseFloat(opacity);
198 if (opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/)) {
200 return parseFloat(opacity[1]) / 100;
205 /** @id MochiKit.Style.setOpacity */
206 setOpacity: function(elem, o) {
207 elem = MochiKit.DOM.getElement(elem);
208 var self = MochiKit.Style;
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, '')});
220 self.setStyle(elem, {opacity: o});
221 if (/MSIE/.test(navigator.userAgent)) {
223 {filter: self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')' });
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
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);
243 (!(elem.x && elem.y) &&
244 (!elem.parentNode == null ||
245 self.computedStyle(elem, 'display') == 'none'))) {
249 var c = new self.Coordinates(0, 0);
253 var d = MochiKit.DOM._document;
254 var de = d.documentElement;
257 if (!elem.parentNode && elem.x && elem.y) {
258 /* it's just a MochiKit.Style.Coordinates object */
261 } else if (elem.getBoundingClientRect) { // IE shortcut
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
267 This is similar to the method used in
268 MochiKit.Signal.Event.mouse().
271 box = elem.getBoundingClientRect();
274 (de.scrollLeft || b.scrollLeft) -
275 (de.clientLeft || 0);
278 (de.scrollTop || b.scrollTop) -
281 } else if (elem.offsetParent) {
282 c.x += elem.offsetLeft;
283 c.y += elem.offsetTop;
284 parent = elem.offsetParent;
286 if (parent != elem) {
288 c.x += parent.offsetLeft;
289 c.y += parent.offsetTop;
290 parent = parent.offsetParent;
296 Opera < 9 and old Safari (absolute) incorrectly account for
297 body offsetTop and offsetLeft.
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')) {
312 if (typeof(relativeTo) != 'undefined') {
313 relativeTo = arguments.callee(relativeTo);
315 c.x -= (relativeTo.x || 0);
316 c.y -= (relativeTo.y || 0);
320 if (elem.parentNode) {
321 parent = elem.parentNode;
327 var tagName = parent.tagName.toUpperCase();
328 if (tagName === 'BODY' || tagName === 'HTML') {
331 c.x -= parent.scrollLeft;
332 c.y -= parent.scrollTop;
333 if (parent.parentNode) {
334 parent = parent.parentNode;
343 /** @id MochiKit.Style.setElementPosition */
344 setElementPosition: function (elem, newPos/* optional */, units) {
345 elem = MochiKit.DOM.getElement(elem);
346 if (typeof(units) == 'undefined') {
350 var isUndefNull = MochiKit.Base.isUndefinedOrNull;
351 if (!isUndefNull(newPos.x)) {
352 newStyle['left'] = newPos.x + units;
354 if (!isUndefNull(newPos.y)) {
355 newStyle['top'] = newPos.y + units;
357 MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
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);
367 elem = dom.getElement(elem);
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);
378 var originalVisibility = s.visibility;
379 var originalPosition = s.position;
380 s.visibility = 'hidden';
381 s.position = 'absolute';
383 var originalWidth = elem.offsetWidth;
384 var originalHeight = elem.offsetHeight;
386 s.position = originalPosition;
387 s.visibility = originalVisibility;
388 return new self.Dimensions(originalWidth, originalHeight);
391 /** @id MochiKit.Style.setElementDimensions */
392 setElementDimensions: function (elem, newSize/* optional */, units) {
393 elem = MochiKit.DOM.getElement(elem);
394 if (typeof(units) == 'undefined') {
398 var isUndefNull = MochiKit.Base.isUndefinedOrNull;
399 if (!isUndefNull(newSize.w)) {
400 newStyle['width'] = newSize.w + units;
402 if (!isUndefNull(newSize.h)) {
403 newStyle['height'] = newSize.h + units;
405 MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
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]);
415 element.style.display = display;
420 /** @id MochiKit.Style.getViewportDimensions */
421 getViewportDimensions: function () {
422 var d = new MochiKit.Style.Dimensions();
424 var w = MochiKit.DOM._window;
425 var b = MochiKit.DOM._document.body;
430 } else if (b.parentElement.clientWidth) {
431 d.w = b.parentElement.clientWidth;
432 d.h = b.parentElement.clientHeight;
433 } else if (b && b.clientWidth) {
435 d.h = b.clientHeight;
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;
446 if (de && (de.scrollTop || de.scrollLeft)) {
456 __new__: function () {
457 var m = MochiKit.Base;
459 this.elementPosition = this.getElementPosition;
460 this.elementDimensions = this.getElementDimensions;
462 this.hideElement = m.partial(this.setDisplayForElement, 'none');
463 this.showElement = m.partial(this.setDisplayForElement, 'block');
466 ':common': this.EXPORT,
467 ':all': m.concat(this.EXPORT, this.EXPORT_OK)
470 m.nameFunctions(this);
474 MochiKit.Style.__new__();
475 MochiKit.Base._exportSymbols(this, MochiKit.Style);