michael@0: /*** michael@0: michael@0: MochiKit.Position 1.4 michael@0: michael@0: See for documentation, downloads, license, etc. michael@0: michael@0: (c) 2005-2006 Bob Ippolito and others. All rights Reserved. michael@0: michael@0: ***/ michael@0: michael@0: if (typeof(dojo) != 'undefined') { michael@0: dojo.provide('MochiKit.Position'); michael@0: dojo.require('MochiKit.Base'); michael@0: dojo.require('MochiKit.DOM'); michael@0: dojo.require('MochiKit.Style'); michael@0: } michael@0: if (typeof(JSAN) != 'undefined') { michael@0: JSAN.use('MochiKit.Base', []); michael@0: JSAN.use('MochiKit.DOM', []); michael@0: JSAN.use('MochiKit.Style', []); michael@0: } michael@0: michael@0: try { michael@0: if (typeof(MochiKit.Base) == 'undefined' || michael@0: typeof(MochiKit.Style) == 'undefined' || michael@0: typeof(MochiKit.DOM) == 'undefined') { michael@0: throw ''; michael@0: } michael@0: } catch (e) { michael@0: throw 'MochiKit.Style depends on MochiKit.Base, MochiKit.DOM, and MochiKit.Style!'; michael@0: } michael@0: michael@0: if (typeof(MochiKit.Position) == 'undefined') { michael@0: MochiKit.Position = {}; michael@0: } michael@0: michael@0: MochiKit.Position.NAME = 'MochiKit.Position'; michael@0: MochiKit.Position.VERSION = '1.4'; michael@0: MochiKit.Position.__repr__ = function () { michael@0: return '[' + this.NAME + ' ' + this.VERSION + ']'; michael@0: }; michael@0: MochiKit.Position.toString = function () { michael@0: return this.__repr__(); michael@0: }; michael@0: michael@0: MochiKit.Position.EXPORT_OK = []; michael@0: michael@0: MochiKit.Position.EXPORT = [ michael@0: ]; michael@0: michael@0: michael@0: MochiKit.Base.update(MochiKit.Position, { michael@0: // set to true if needed, warning: firefox performance problems michael@0: // NOT neeeded for page scrolling, only if draggable contained in michael@0: // scrollable elements michael@0: includeScrollOffsets: false, michael@0: michael@0: /** @id MochiKit.Position.prepare */ michael@0: prepare: function () { michael@0: var deltaX = window.pageXOffset michael@0: || document.documentElement.scrollLeft michael@0: || document.body.scrollLeft michael@0: || 0; michael@0: var deltaY = window.pageYOffset michael@0: || document.documentElement.scrollTop michael@0: || document.body.scrollTop michael@0: || 0; michael@0: this.windowOffset = new MochiKit.Style.Coordinates(deltaX, deltaY); michael@0: }, michael@0: michael@0: /** @id MochiKit.Position.cumulativeOffset */ michael@0: cumulativeOffset: function (element) { michael@0: var valueT = 0; michael@0: var valueL = 0; michael@0: do { michael@0: valueT += element.offsetTop || 0; michael@0: valueL += element.offsetLeft || 0; michael@0: element = element.offsetParent; michael@0: } while (element); michael@0: return new MochiKit.Style.Coordinates(valueL, valueT); michael@0: }, michael@0: michael@0: /** @id MochiKit.Position.realOffset */ michael@0: realOffset: function (element) { michael@0: var valueT = 0; michael@0: var valueL = 0; michael@0: do { michael@0: valueT += element.scrollTop || 0; michael@0: valueL += element.scrollLeft || 0; michael@0: element = element.parentNode; michael@0: } while (element); michael@0: return new MochiKit.Style.Coordinates(valueL, valueT); michael@0: }, michael@0: michael@0: /** @id MochiKit.Position.within */ michael@0: within: function (element, x, y) { michael@0: if (this.includeScrollOffsets) { michael@0: return this.withinIncludingScrolloffsets(element, x, y); michael@0: } michael@0: this.xcomp = x; michael@0: this.ycomp = y; michael@0: this.offset = this.cumulativeOffset(element); michael@0: if (element.style.position == "fixed") { michael@0: this.offset.x += this.windowOffset.x; michael@0: this.offset.y += this.windowOffset.y; michael@0: } michael@0: michael@0: return (y >= this.offset.y && michael@0: y < this.offset.y + element.offsetHeight && michael@0: x >= this.offset.x && michael@0: x < this.offset.x + element.offsetWidth); michael@0: }, michael@0: michael@0: /** @id MochiKit.Position.withinIncludingScrolloffsets */ michael@0: withinIncludingScrolloffsets: function (element, x, y) { michael@0: var offsetcache = this.realOffset(element); michael@0: michael@0: this.xcomp = x + offsetcache.x - this.windowOffset.x; michael@0: this.ycomp = y + offsetcache.y - this.windowOffset.y; michael@0: this.offset = this.cumulativeOffset(element); michael@0: michael@0: return (this.ycomp >= this.offset.y && michael@0: this.ycomp < this.offset.y + element.offsetHeight && michael@0: this.xcomp >= this.offset.x && michael@0: this.xcomp < this.offset.x + element.offsetWidth); michael@0: }, michael@0: michael@0: // within must be called directly before michael@0: /** @id MochiKit.Position.overlap */ michael@0: overlap: function (mode, element) { michael@0: if (!mode) { michael@0: return 0; michael@0: } michael@0: if (mode == 'vertical') { michael@0: return ((this.offset.y + element.offsetHeight) - this.ycomp) / michael@0: element.offsetHeight; michael@0: } michael@0: if (mode == 'horizontal') { michael@0: return ((this.offset.x + element.offsetWidth) - this.xcomp) / michael@0: element.offsetWidth; michael@0: } michael@0: }, michael@0: michael@0: /** @id MochiKit.Position.absolutize */ michael@0: absolutize: function (element) { michael@0: element = MochiKit.DOM.getElement(element); michael@0: if (element.style.position == 'absolute') { michael@0: return; michael@0: } michael@0: MochiKit.Position.prepare(); michael@0: michael@0: var offsets = MochiKit.Position.positionedOffset(element); michael@0: var width = element.clientWidth; michael@0: var height = element.clientHeight; michael@0: michael@0: var oldStyle = { michael@0: 'position': element.style.position, michael@0: 'left': offsets.x - parseFloat(element.style.left || 0), michael@0: 'top': offsets.y - parseFloat(element.style.top || 0), michael@0: 'width': element.style.width, michael@0: 'height': element.style.height michael@0: }; michael@0: michael@0: element.style.position = 'absolute'; michael@0: element.style.top = offsets.y + 'px'; michael@0: element.style.left = offsets.x + 'px'; michael@0: element.style.width = width + 'px'; michael@0: element.style.height = height + 'px'; michael@0: michael@0: return oldStyle; michael@0: }, michael@0: michael@0: /** @id MochiKit.Position.positionedOffset */ michael@0: positionedOffset: function (element) { michael@0: var valueT = 0, valueL = 0; michael@0: do { michael@0: valueT += element.offsetTop || 0; michael@0: valueL += element.offsetLeft || 0; michael@0: element = element.offsetParent; michael@0: if (element) { michael@0: p = MochiKit.Style.getStyle(element, 'position'); michael@0: if (p == 'relative' || p == 'absolute') { michael@0: break; michael@0: } michael@0: } michael@0: } while (element); michael@0: return new MochiKit.Style.Coordinates(valueL, valueT); michael@0: }, michael@0: michael@0: /** @id MochiKit.Position.relativize */ michael@0: relativize: function (element, oldPos) { michael@0: element = MochiKit.DOM.getElement(element); michael@0: if (element.style.position == 'relative') { michael@0: return; michael@0: } michael@0: MochiKit.Position.prepare(); michael@0: michael@0: var top = parseFloat(element.style.top || 0) - michael@0: (oldPos['top'] || 0); michael@0: var left = parseFloat(element.style.left || 0) - michael@0: (oldPos['left'] || 0); michael@0: michael@0: element.style.position = oldPos['position']; michael@0: element.style.top = top + 'px'; michael@0: element.style.left = left + 'px'; michael@0: element.style.width = oldPos['width']; michael@0: element.style.height = oldPos['height']; michael@0: }, michael@0: michael@0: /** @id MochiKit.Position.clone */ michael@0: clone: function (source, target) { michael@0: source = MochiKit.DOM.getElement(source); michael@0: target = MochiKit.DOM.getElement(target); michael@0: target.style.position = 'absolute'; michael@0: var offsets = this.cumulativeOffset(source); michael@0: target.style.top = offsets.y + 'px'; michael@0: target.style.left = offsets.x + 'px'; michael@0: target.style.width = source.offsetWidth + 'px'; michael@0: target.style.height = source.offsetHeight + 'px'; michael@0: }, michael@0: michael@0: /** @id MochiKit.Position.page */ michael@0: page: function (forElement) { michael@0: var valueT = 0; michael@0: var valueL = 0; michael@0: michael@0: var element = forElement; michael@0: do { michael@0: valueT += element.offsetTop || 0; michael@0: valueL += element.offsetLeft || 0; michael@0: michael@0: // Safari fix michael@0: if (element.offsetParent == document.body && MochiKit.Style.getStyle(element, 'position') == 'absolute') { michael@0: break; michael@0: } michael@0: } while (element = element.offsetParent); michael@0: michael@0: element = forElement; michael@0: do { michael@0: valueT -= element.scrollTop || 0; michael@0: valueL -= element.scrollLeft || 0; michael@0: } while (element = element.parentNode); michael@0: michael@0: return new MochiKit.Style.Coordinates(valueL, valueT); michael@0: } michael@0: }); michael@0: michael@0: MochiKit.Position.__new__ = function (win) { michael@0: var m = MochiKit.Base; 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: MochiKit.Position.__new__(this);