michael@0: michael@0: MochiKit.Base.update(MochiKit.DOM, { michael@0: /** @id MochiKit.DOM.makeClipping */ michael@0: makeClipping: function (element) { michael@0: element = MochiKit.DOM.getElement(element); michael@0: var oldOverflow = element.style.overflow; michael@0: if ((MochiKit.Style.getStyle(element, 'overflow') || 'visible') != 'hidden') { michael@0: element.style.overflow = 'hidden'; michael@0: } michael@0: return oldOverflow; michael@0: }, michael@0: michael@0: /** @id MochiKit.DOM.undoClipping */ michael@0: undoClipping: function (element, overflow) { michael@0: element = MochiKit.DOM.getElement(element); michael@0: if (!overflow) { michael@0: return; michael@0: } michael@0: element.style.overflow = overflow; michael@0: }, michael@0: michael@0: /** @id MochiKit.DOM.makePositioned */ michael@0: makePositioned: function (element) { michael@0: element = MochiKit.DOM.getElement(element); michael@0: var pos = MochiKit.Style.getStyle(element, 'position'); michael@0: if (pos == 'static' || !pos) { michael@0: element.style.position = 'relative'; michael@0: // Opera returns the offset relative to the positioning context, michael@0: // when an element is position relative but top and left have michael@0: // not been defined michael@0: if (/Opera/.test(navigator.userAgent)) { michael@0: element.style.top = 0; michael@0: element.style.left = 0; michael@0: } michael@0: } michael@0: }, michael@0: michael@0: /** @id MochiKit.DOM.undoPositioned */ michael@0: undoPositioned: function (element) { michael@0: element = MochiKit.DOM.getElement(element); michael@0: if (element.style.position == 'relative') { michael@0: element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = ''; michael@0: } michael@0: }, michael@0: michael@0: /** @id MochiKit.DOM.getFirstElementByTagAndClassName */ michael@0: getFirstElementByTagAndClassName: function (tagName, className, michael@0: /* optional */parent) { michael@0: var self = MochiKit.DOM; michael@0: if (typeof(tagName) == 'undefined' || tagName === null) { michael@0: tagName = '*'; michael@0: } michael@0: if (typeof(parent) == 'undefined' || parent === null) { michael@0: parent = self._document; michael@0: } michael@0: parent = self.getElement(parent); michael@0: var children = (parent.getElementsByTagName(tagName) michael@0: || self._document.all); michael@0: if (typeof(className) == 'undefined' || className === null) { michael@0: return children[0]; michael@0: } michael@0: michael@0: for (var i = 0; i < children.length; i++) { michael@0: var child = children[i]; michael@0: var classNames = child.className.split(' '); michael@0: for (var j = 0; j < classNames.length; j++) { michael@0: if (classNames[j] == className) { michael@0: return child; michael@0: } michael@0: } michael@0: } michael@0: }, michael@0: michael@0: /** @id MochiKit.DOM.isParent */ michael@0: isParent: function (child, element) { michael@0: if (!child.parentNode || child == element) { michael@0: return false; michael@0: } michael@0: michael@0: if (child.parentNode == element) { michael@0: return true; michael@0: } michael@0: michael@0: return MochiKit.DOM.isParent(child.parentNode, element); michael@0: } michael@0: }); michael@0: michael@0: 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: