michael@0: /*** michael@0: michael@0: MochiKit.Style 1.4 michael@0: michael@0: See for documentation, downloads, license, etc. michael@0: michael@0: (c) 2005-2006 Bob Ippolito, Beau Hartshorne. All rights Reserved. michael@0: michael@0: ***/ michael@0: michael@0: if (typeof(dojo) != 'undefined') { michael@0: dojo.provide('MochiKit.Style'); michael@0: dojo.require('MochiKit.Base'); michael@0: dojo.require('MochiKit.DOM'); michael@0: } michael@0: if (typeof(JSAN) != 'undefined') { michael@0: JSAN.use('MochiKit.Base', []); michael@0: JSAN.use('MochiKit.DOM', []); michael@0: } michael@0: michael@0: try { michael@0: if (typeof(MochiKit.Base) == 'undefined') { michael@0: throw ''; michael@0: } michael@0: } catch (e) { michael@0: throw 'MochiKit.Style depends on MochiKit.Base!'; michael@0: } michael@0: michael@0: try { michael@0: if (typeof(MochiKit.DOM) == 'undefined') { michael@0: throw ''; michael@0: } michael@0: } catch (e) { michael@0: throw 'MochiKit.Style depends on MochiKit.DOM!'; michael@0: } michael@0: michael@0: michael@0: if (typeof(MochiKit.Style) == 'undefined') { michael@0: MochiKit.Style = {}; michael@0: } michael@0: michael@0: MochiKit.Style.NAME = 'MochiKit.Style'; michael@0: MochiKit.Style.VERSION = '1.4'; michael@0: MochiKit.Style.__repr__ = function () { michael@0: return '[' + this.NAME + ' ' + this.VERSION + ']'; michael@0: }; michael@0: MochiKit.Style.toString = function () { michael@0: return this.__repr__(); michael@0: }; michael@0: michael@0: MochiKit.Style.EXPORT_OK = []; michael@0: michael@0: MochiKit.Style.EXPORT = [ michael@0: 'setStyle', michael@0: 'setOpacity', michael@0: 'getStyle', michael@0: 'getElementDimensions', michael@0: 'elementDimensions', // deprecated michael@0: 'setElementDimensions', michael@0: 'getElementPosition', michael@0: 'elementPosition', // deprecated michael@0: 'setElementPosition', michael@0: 'setDisplayForElement', michael@0: 'hideElement', michael@0: 'showElement', michael@0: 'getViewportDimensions', michael@0: 'getViewportPosition', michael@0: 'Dimensions', michael@0: 'Coordinates' michael@0: ]; michael@0: michael@0: michael@0: /* michael@0: michael@0: Dimensions michael@0: michael@0: */ michael@0: /** @id MochiKit.Style.Dimensions */ michael@0: MochiKit.Style.Dimensions = function (w, h) { michael@0: this.w = w; michael@0: this.h = h; michael@0: }; michael@0: michael@0: MochiKit.Style.Dimensions.prototype.__repr__ = function () { michael@0: var repr = MochiKit.Base.repr; michael@0: return '{w: ' + repr(this.w) + ', h: ' + repr(this.h) + '}'; michael@0: }; michael@0: michael@0: MochiKit.Style.Dimensions.prototype.toString = function () { michael@0: return this.__repr__(); michael@0: }; michael@0: michael@0: michael@0: /* michael@0: michael@0: Coordinates michael@0: michael@0: */ michael@0: /** @id MochiKit.Style.Coordinates */ michael@0: MochiKit.Style.Coordinates = function (x, y) { michael@0: this.x = x; michael@0: this.y = y; michael@0: }; michael@0: michael@0: MochiKit.Style.Coordinates.prototype.__repr__ = function () { michael@0: var repr = MochiKit.Base.repr; michael@0: return '{x: ' + repr(this.x) + ', y: ' + repr(this.y) + '}'; michael@0: }; michael@0: michael@0: MochiKit.Style.Coordinates.prototype.toString = function () { michael@0: return this.__repr__(); michael@0: }; michael@0: michael@0: michael@0: MochiKit.Base.update(MochiKit.Style, { michael@0: michael@0: /** @id MochiKit.Style.getStyle */ michael@0: getStyle: function (elem, cssProperty) { michael@0: var dom = MochiKit.DOM; michael@0: var d = dom._document; michael@0: michael@0: elem = dom.getElement(elem); michael@0: cssProperty = MochiKit.Base.camelize(cssProperty); michael@0: michael@0: if (!elem || elem == d) { michael@0: return undefined; michael@0: } michael@0: if (cssProperty == 'opacity' && elem.filters) { michael@0: var opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/); michael@0: if (opacity && opacity[1]) { michael@0: return parseFloat(opacity[1]) / 100; michael@0: } michael@0: return 1.0; michael@0: } michael@0: var value = elem.style ? elem.style[cssProperty] : null; michael@0: if (!value) { michael@0: if (d.defaultView && d.defaultView.getComputedStyle) { michael@0: var css = d.defaultView.getComputedStyle(elem, null); michael@0: cssProperty = cssProperty.replace(/([A-Z])/g, '-$1' michael@0: ).toLowerCase(); // from dojo.style.toSelectorCase michael@0: value = css ? css.getPropertyValue(cssProperty) : null; michael@0: } else if (elem.currentStyle) { michael@0: value = elem.currentStyle[cssProperty]; michael@0: } michael@0: } michael@0: if (cssProperty == 'opacity') { michael@0: value = parseFloat(value); michael@0: } michael@0: michael@0: if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.find(['left', 'top', 'right', 'bottom'], cssProperty) != -1)) { michael@0: if (MochiKit.Style.getStyle(elem, 'position') == 'static') { michael@0: value = 'auto'; michael@0: } michael@0: } michael@0: michael@0: return value == 'auto' ? null : value; michael@0: }, michael@0: michael@0: /** @id MochiKit.Style.setStyle */ michael@0: setStyle: function (elem, style) { michael@0: elem = MochiKit.DOM.getElement(elem); michael@0: for (var name in style) { michael@0: if (name == 'opacity') { michael@0: MochiKit.Style.setOpacity(elem, style[name]); michael@0: } else { michael@0: elem.style[MochiKit.Base.camelize(name)] = style[name]; michael@0: } michael@0: } michael@0: }, michael@0: michael@0: /** @id MochiKit.Style.setOpacity */ michael@0: setOpacity: function (elem, o) { michael@0: elem = MochiKit.DOM.getElement(elem); michael@0: var self = MochiKit.Style; michael@0: if (o == 1) { michael@0: var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent)); michael@0: elem.style["opacity"] = toSet ? 0.999999 : 1.0; michael@0: if (/MSIE/.test(navigator.userAgent)) { michael@0: elem.style['filter'] = michael@0: self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, ''); michael@0: } michael@0: } else { michael@0: if (o < 0.00001) { michael@0: o = 0; michael@0: } michael@0: elem.style["opacity"] = o; michael@0: if (/MSIE/.test(navigator.userAgent)) { michael@0: elem.style['filter'] = michael@0: self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')'; michael@0: } michael@0: } michael@0: }, michael@0: michael@0: /* michael@0: michael@0: getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0. michael@0: Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved. michael@0: License: BSD, http://developer.yahoo.net/yui/license.txt michael@0: michael@0: */ michael@0: michael@0: /** @id MochiKit.Style.getElementPosition */ michael@0: getElementPosition: function (elem, /* optional */relativeTo) { michael@0: var self = MochiKit.Style; michael@0: var dom = MochiKit.DOM; michael@0: elem = dom.getElement(elem); michael@0: michael@0: if (!elem || michael@0: (!(elem.x && elem.y) && michael@0: (!elem.parentNode === null || michael@0: self.getStyle(elem, 'display') == 'none'))) { michael@0: return undefined; michael@0: } michael@0: michael@0: var c = new self.Coordinates(0, 0); michael@0: var box = null; michael@0: var parent = null; michael@0: michael@0: var d = MochiKit.DOM._document; michael@0: var de = d.documentElement; michael@0: var b = d.body; michael@0: michael@0: if (!elem.parentNode && elem.x && elem.y) { michael@0: /* it's just a MochiKit.Style.Coordinates object */ michael@0: c.x += elem.x || 0; michael@0: c.y += elem.y || 0; michael@0: } else if (elem.getBoundingClientRect) { // IE shortcut michael@0: /* michael@0: michael@0: The IE shortcut can be off by two. We fix it. See: michael@0: http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp michael@0: michael@0: This is similar to the method used in michael@0: MochiKit.Signal.Event.mouse(). michael@0: michael@0: */ michael@0: box = elem.getBoundingClientRect(); michael@0: michael@0: c.x += box.left + michael@0: (de.scrollLeft || b.scrollLeft) - michael@0: (de.clientLeft || 0); michael@0: michael@0: c.y += box.top + michael@0: (de.scrollTop || b.scrollTop) - michael@0: (de.clientTop || 0); michael@0: michael@0: } else if (elem.offsetParent) { michael@0: c.x += elem.offsetLeft; michael@0: c.y += elem.offsetTop; michael@0: parent = elem.offsetParent; michael@0: michael@0: if (parent != elem) { michael@0: while (parent) { michael@0: c.x += parent.offsetLeft; michael@0: c.y += parent.offsetTop; michael@0: parent = parent.offsetParent; michael@0: } michael@0: } michael@0: michael@0: /* michael@0: michael@0: Opera < 9 and old Safari (absolute) incorrectly account for michael@0: body offsetTop and offsetLeft. michael@0: michael@0: */ michael@0: var ua = navigator.userAgent.toLowerCase(); michael@0: if ((typeof(opera) != 'undefined' && michael@0: parseFloat(opera.version()) < 9) || michael@0: (ua.indexOf('AppleWebKit') != -1 && michael@0: self.getStyle(elem, 'position') == 'absolute')) { michael@0: michael@0: c.x -= b.offsetLeft; michael@0: c.y -= b.offsetTop; michael@0: michael@0: } michael@0: } michael@0: michael@0: if (typeof(relativeTo) != 'undefined') { michael@0: relativeTo = arguments.callee(relativeTo); michael@0: if (relativeTo) { michael@0: c.x -= (relativeTo.x || 0); michael@0: c.y -= (relativeTo.y || 0); michael@0: } michael@0: } michael@0: michael@0: if (elem.parentNode) { michael@0: parent = elem.parentNode; michael@0: } else { michael@0: parent = null; michael@0: } michael@0: michael@0: while (parent) { michael@0: var tagName = parent.tagName.toUpperCase(); michael@0: if (tagName === 'BODY' || tagName === 'HTML') { michael@0: break; michael@0: } michael@0: var disp = self.getStyle(parent, 'display'); michael@0: // Handle strange Opera bug for some display michael@0: if (disp != 'inline' && disp != 'table-row') { michael@0: c.x -= parent.scrollLeft; michael@0: c.y -= parent.scrollTop; michael@0: } michael@0: if (parent.parentNode) { michael@0: parent = parent.parentNode; michael@0: } else { michael@0: parent = null; michael@0: } michael@0: } michael@0: michael@0: return c; michael@0: }, michael@0: michael@0: /** @id MochiKit.Style.setElementPosition */ michael@0: setElementPosition: function (elem, newPos/* optional */, units) { michael@0: elem = MochiKit.DOM.getElement(elem); michael@0: if (typeof(units) == 'undefined') { michael@0: units = 'px'; michael@0: } michael@0: var newStyle = {}; michael@0: var isUndefNull = MochiKit.Base.isUndefinedOrNull; michael@0: if (!isUndefNull(newPos.x)) { michael@0: newStyle['left'] = newPos.x + units; michael@0: } michael@0: if (!isUndefNull(newPos.y)) { michael@0: newStyle['top'] = newPos.y + units; michael@0: } michael@0: MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle}); michael@0: }, michael@0: michael@0: /** @id MochiKit.Style.getElementDimensions */ michael@0: getElementDimensions: function (elem) { michael@0: var self = MochiKit.Style; michael@0: var dom = MochiKit.DOM; michael@0: if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') { michael@0: return new self.Dimensions(elem.w || 0, elem.h || 0); michael@0: } michael@0: elem = dom.getElement(elem); michael@0: if (!elem) { michael@0: return undefined; michael@0: } michael@0: var disp = self.getStyle(elem, 'display'); michael@0: // display can be empty/undefined on WebKit/KHTML michael@0: if (disp != 'none' && disp !== '' && typeof(disp) != 'undefined') { michael@0: return new self.Dimensions(elem.offsetWidth || 0, michael@0: elem.offsetHeight || 0); michael@0: } michael@0: var s = elem.style; michael@0: var originalVisibility = s.visibility; michael@0: var originalPosition = s.position; michael@0: s.visibility = 'hidden'; michael@0: s.position = 'absolute'; michael@0: s.display = ''; michael@0: var originalWidth = elem.offsetWidth; michael@0: var originalHeight = elem.offsetHeight; michael@0: s.display = 'none'; michael@0: s.position = originalPosition; michael@0: s.visibility = originalVisibility; michael@0: return new self.Dimensions(originalWidth, originalHeight); michael@0: }, michael@0: michael@0: /** @id MochiKit.Style.setElementDimensions */ michael@0: setElementDimensions: function (elem, newSize/* optional */, units) { michael@0: elem = MochiKit.DOM.getElement(elem); michael@0: if (typeof(units) == 'undefined') { michael@0: units = 'px'; michael@0: } michael@0: var newStyle = {}; michael@0: var isUndefNull = MochiKit.Base.isUndefinedOrNull; michael@0: if (!isUndefNull(newSize.w)) { michael@0: newStyle['width'] = newSize.w + units; michael@0: } michael@0: if (!isUndefNull(newSize.h)) { michael@0: newStyle['height'] = newSize.h + units; michael@0: } michael@0: MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle}); michael@0: }, michael@0: michael@0: /** @id MochiKit.Style.setDisplayForElement */ michael@0: setDisplayForElement: function (display, element/*, ...*/) { michael@0: var elements = MochiKit.Base.extend(null, arguments, 1); michael@0: var getElement = MochiKit.DOM.getElement; michael@0: for (var i = 0; i < elements.length; i++) { michael@0: element = getElement(elements[i]); michael@0: if (element) { michael@0: element.style.display = display; michael@0: } michael@0: } michael@0: }, michael@0: michael@0: /** @id MochiKit.Style.getViewportDimensions */ michael@0: getViewportDimensions: function () { michael@0: var d = new MochiKit.Style.Dimensions(); michael@0: michael@0: var w = MochiKit.DOM._window; michael@0: var b = MochiKit.DOM._document.body; michael@0: michael@0: if (w.innerWidth) { michael@0: d.w = w.innerWidth; michael@0: d.h = w.innerHeight; michael@0: } else if (b.parentElement.clientWidth) { michael@0: d.w = b.parentElement.clientWidth; michael@0: d.h = b.parentElement.clientHeight; michael@0: } else if (b && b.clientWidth) { michael@0: d.w = b.clientWidth; michael@0: d.h = b.clientHeight; michael@0: } michael@0: return d; michael@0: }, michael@0: michael@0: /** @id MochiKit.Style.getViewportPosition */ michael@0: getViewportPosition: function () { michael@0: var c = new MochiKit.Style.Coordinates(0, 0); michael@0: var d = MochiKit.DOM._document; michael@0: var de = d.documentElement; michael@0: var db = d.body; michael@0: if (de && (de.scrollTop || de.scrollLeft)) { michael@0: c.x = de.scrollLeft; michael@0: c.y = de.scrollTop; michael@0: } else if (db) { michael@0: c.x = db.scrollLeft; michael@0: c.y = db.scrollTop; michael@0: } michael@0: return c; michael@0: }, michael@0: michael@0: __new__: function () { michael@0: var m = MochiKit.Base; michael@0: michael@0: this.elementPosition = this.getElementPosition; michael@0: this.elementDimensions = this.getElementDimensions; michael@0: michael@0: this.hideElement = m.partial(this.setDisplayForElement, 'none'); michael@0: this.showElement = m.partial(this.setDisplayForElement, 'block'); michael@0: michael@0: this.EXPORT_TAGS = { michael@0: ':common': this.EXPORT, michael@0: ':all': m.concat(this.EXPORT, this.EXPORT_OK) michael@0: }; michael@0: michael@0: m.nameFunctions(this); michael@0: } michael@0: }); michael@0: michael@0: MochiKit.Style.__new__(); michael@0: MochiKit.Base._exportSymbols(this, MochiKit.Style);