5 See <http://mochikit.com/> for documentation, downloads, license, etc.
7 (c) 2005-2006 Bob Ippolito and others. All rights Reserved.
11 if (typeof(dojo) != 'undefined') {
12 dojo.provide('MochiKit.Position');
13 dojo.require('MochiKit.Base');
14 dojo.require('MochiKit.DOM');
15 dojo.require('MochiKit.Style');
17 if (typeof(JSAN) != 'undefined') {
18 JSAN.use('MochiKit.Base', []);
19 JSAN.use('MochiKit.DOM', []);
20 JSAN.use('MochiKit.Style', []);
24 if (typeof(MochiKit.Base) == 'undefined' ||
25 typeof(MochiKit.Style) == 'undefined' ||
26 typeof(MochiKit.DOM) == 'undefined') {
30 throw 'MochiKit.Style depends on MochiKit.Base, MochiKit.DOM, and MochiKit.Style!';
33 if (typeof(MochiKit.Position) == 'undefined') {
34 MochiKit.Position = {};
37 MochiKit.Position.NAME = 'MochiKit.Position';
38 MochiKit.Position.VERSION = '1.4';
39 MochiKit.Position.__repr__ = function () {
40 return '[' + this.NAME + ' ' + this.VERSION + ']';
42 MochiKit.Position.toString = function () {
43 return this.__repr__();
46 MochiKit.Position.EXPORT_OK = [];
48 MochiKit.Position.EXPORT = [
52 MochiKit.Base.update(MochiKit.Position, {
53 // set to true if needed, warning: firefox performance problems
54 // NOT neeeded for page scrolling, only if draggable contained in
55 // scrollable elements
56 includeScrollOffsets: false,
58 /** @id MochiKit.Position.prepare */
59 prepare: function () {
60 var deltaX = window.pageXOffset
61 || document.documentElement.scrollLeft
62 || document.body.scrollLeft
64 var deltaY = window.pageYOffset
65 || document.documentElement.scrollTop
66 || document.body.scrollTop
68 this.windowOffset = new MochiKit.Style.Coordinates(deltaX, deltaY);
71 /** @id MochiKit.Position.cumulativeOffset */
72 cumulativeOffset: function (element) {
76 valueT += element.offsetTop || 0;
77 valueL += element.offsetLeft || 0;
78 element = element.offsetParent;
80 return new MochiKit.Style.Coordinates(valueL, valueT);
83 /** @id MochiKit.Position.realOffset */
84 realOffset: function (element) {
88 valueT += element.scrollTop || 0;
89 valueL += element.scrollLeft || 0;
90 element = element.parentNode;
92 return new MochiKit.Style.Coordinates(valueL, valueT);
95 /** @id MochiKit.Position.within */
96 within: function (element, x, y) {
97 if (this.includeScrollOffsets) {
98 return this.withinIncludingScrolloffsets(element, x, y);
102 this.offset = this.cumulativeOffset(element);
103 if (element.style.position == "fixed") {
104 this.offset.x += this.windowOffset.x;
105 this.offset.y += this.windowOffset.y;
108 return (y >= this.offset.y &&
109 y < this.offset.y + element.offsetHeight &&
110 x >= this.offset.x &&
111 x < this.offset.x + element.offsetWidth);
114 /** @id MochiKit.Position.withinIncludingScrolloffsets */
115 withinIncludingScrolloffsets: function (element, x, y) {
116 var offsetcache = this.realOffset(element);
118 this.xcomp = x + offsetcache.x - this.windowOffset.x;
119 this.ycomp = y + offsetcache.y - this.windowOffset.y;
120 this.offset = this.cumulativeOffset(element);
122 return (this.ycomp >= this.offset.y &&
123 this.ycomp < this.offset.y + element.offsetHeight &&
124 this.xcomp >= this.offset.x &&
125 this.xcomp < this.offset.x + element.offsetWidth);
128 // within must be called directly before
129 /** @id MochiKit.Position.overlap */
130 overlap: function (mode, element) {
134 if (mode == 'vertical') {
135 return ((this.offset.y + element.offsetHeight) - this.ycomp) /
136 element.offsetHeight;
138 if (mode == 'horizontal') {
139 return ((this.offset.x + element.offsetWidth) - this.xcomp) /
144 /** @id MochiKit.Position.absolutize */
145 absolutize: function (element) {
146 element = MochiKit.DOM.getElement(element);
147 if (element.style.position == 'absolute') {
150 MochiKit.Position.prepare();
152 var offsets = MochiKit.Position.positionedOffset(element);
153 var width = element.clientWidth;
154 var height = element.clientHeight;
157 'position': element.style.position,
158 'left': offsets.x - parseFloat(element.style.left || 0),
159 'top': offsets.y - parseFloat(element.style.top || 0),
160 'width': element.style.width,
161 'height': element.style.height
164 element.style.position = 'absolute';
165 element.style.top = offsets.y + 'px';
166 element.style.left = offsets.x + 'px';
167 element.style.width = width + 'px';
168 element.style.height = height + 'px';
173 /** @id MochiKit.Position.positionedOffset */
174 positionedOffset: function (element) {
175 var valueT = 0, valueL = 0;
177 valueT += element.offsetTop || 0;
178 valueL += element.offsetLeft || 0;
179 element = element.offsetParent;
181 p = MochiKit.Style.getStyle(element, 'position');
182 if (p == 'relative' || p == 'absolute') {
187 return new MochiKit.Style.Coordinates(valueL, valueT);
190 /** @id MochiKit.Position.relativize */
191 relativize: function (element, oldPos) {
192 element = MochiKit.DOM.getElement(element);
193 if (element.style.position == 'relative') {
196 MochiKit.Position.prepare();
198 var top = parseFloat(element.style.top || 0) -
199 (oldPos['top'] || 0);
200 var left = parseFloat(element.style.left || 0) -
201 (oldPos['left'] || 0);
203 element.style.position = oldPos['position'];
204 element.style.top = top + 'px';
205 element.style.left = left + 'px';
206 element.style.width = oldPos['width'];
207 element.style.height = oldPos['height'];
210 /** @id MochiKit.Position.clone */
211 clone: function (source, target) {
212 source = MochiKit.DOM.getElement(source);
213 target = MochiKit.DOM.getElement(target);
214 target.style.position = 'absolute';
215 var offsets = this.cumulativeOffset(source);
216 target.style.top = offsets.y + 'px';
217 target.style.left = offsets.x + 'px';
218 target.style.width = source.offsetWidth + 'px';
219 target.style.height = source.offsetHeight + 'px';
222 /** @id MochiKit.Position.page */
223 page: function (forElement) {
227 var element = forElement;
229 valueT += element.offsetTop || 0;
230 valueL += element.offsetLeft || 0;
233 if (element.offsetParent == document.body && MochiKit.Style.getStyle(element, 'position') == 'absolute') {
236 } while (element = element.offsetParent);
238 element = forElement;
240 valueT -= element.scrollTop || 0;
241 valueL -= element.scrollLeft || 0;
242 } while (element = element.parentNode);
244 return new MochiKit.Style.Coordinates(valueL, valueT);
248 MochiKit.Position.__new__ = function (win) {
249 var m = MochiKit.Base;
251 ':common': this.EXPORT,
252 ':all': m.concat(this.EXPORT, this.EXPORT_OK)
255 m.nameFunctions(this);
258 MochiKit.Position.__new__(this);