1 rizwank 1.1 /* Copyright (c) 2005 Tim Taylor Consulting (see LICENSE.txt) */
2
3 /* FIXME: assumes position styles are specified in 'px' */
4
5 ToolMan._coordinatesFactory = {
6
7 create : function(x, y) {
8 // FIXME: Safari won't parse 'throw' and aborts trying to do anything with this file
9 //if (isNaN(x) || isNaN(y)) throw "invalid x,y: " + x + "," + y
10 return new _ToolManCoordinate(this, x, y)
11 },
12
13 origin : function() {
14 return this.create(0, 0)
15 },
16
17 /*
18 * FIXME: Safari 1.2, returns (0,0) on absolutely positioned elements
19 */
20 topLeftPosition : function(element) {
21 var left = parseInt(ToolMan.css().readStyle(element, "left"))
22 rizwank 1.1 var left = isNaN(left) ? 0 : left
23 var top = parseInt(ToolMan.css().readStyle(element, "top"))
24 var top = isNaN(top) ? 0 : top
25
26 return this.create(left, top)
27 },
28
29 bottomRightPosition : function(element) {
30 return this.topLeftPosition(element).plus(this._size(element))
31 },
32
33 topLeftOffset : function(element) {
34 var offset = this._offset(element)
35
36 var parent = element.offsetParent
37 while (parent) {
38 offset = offset.plus(this._offset(parent))
39 parent = parent.offsetParent
40 }
41 return offset
42 },
43 rizwank 1.1
44 bottomRightOffset : function(element) {
45 return this.topLeftOffset(element).plus(
46 this.create(element.offsetWidth, element.offsetHeight))
47 },
48
49 scrollOffset : function() {
50 if (window.pageXOffset) {
51 return this.create(window.pageXOffset, window.pageYOffset)
52 } else if (document.documentElement) {
53 return this.create(
54 document.body.scrollLeft + document.documentElement.scrollLeft,
55 document.body.scrollTop + document.documentElement.scrollTop)
56 } else if (document.body.scrollLeft >= 0) {
57 return this.create(document.body.scrollLeft, document.body.scrollTop)
58 } else {
59 return this.create(0, 0)
60 }
61 },
62
63 clientSize : function() {
64 rizwank 1.1 if (window.innerHeight >= 0) {
65 return this.create(window.innerWidth, window.innerHeight)
66 } else if (document.documentElement) {
67 return this.create(document.documentElement.clientWidth,
68 document.documentElement.clientHeight)
69 } else if (document.body.clientHeight >= 0) {
70 return this.create(document.body.clientWidth,
71 document.body.clientHeight)
72 } else {
73 return this.create(0, 0)
74 }
75 },
76
77 /**
78 * mouse coordinate relative to the window (technically the
79 * browser client area) i.e. the part showing your page
80 *
81 * NOTE: in Safari the coordinate is relative to the document
82 */
83 mousePosition : function(event) {
84 event = ToolMan.events().fix(event)
85 rizwank 1.1 return this.create(event.clientX, event.clientY)
86 },
87
88 /**
89 * mouse coordinate relative to the document
90 */
91 mouseOffset : function(event) {
92 event = ToolMan.events().fix(event)
93 if (event.pageX >= 0 || event.pageX < 0) {
94 return this.create(event.pageX, event.pageY)
95 } else if (event.clientX >= 0 || event.clientX < 0) {
96 return this.mousePosition(event).plus(this.scrollOffset())
97 }
98 },
99
100 _size : function(element) {
101 /* TODO: move to a Dimension class */
102 return this.create(element.offsetWidth, element.offsetHeight)
103 },
104
105 _offset : function(element) {
106 rizwank 1.1 return this.create(element.offsetLeft, element.offsetTop)
107 }
108 }
109
110 function _ToolManCoordinate(factory, x, y) {
111 this.factory = factory
112 this.x = isNaN(x) ? 0 : x
113 this.y = isNaN(y) ? 0 : y
114 }
115
116 _ToolManCoordinate.prototype = {
117 toString : function() {
118 return "(" + this.x + "," + this.y + ")"
119 },
120
121 plus : function(that) {
122 return this.factory.create(this.x + that.x, this.y + that.y)
123 },
124
125 minus : function(that) {
126 return this.factory.create(this.x - that.x, this.y - that.y)
127 rizwank 1.1 },
128
129 min : function(that) {
130 return this.factory.create(
131 Math.min(this.x , that.x), Math.min(this.y , that.y))
132 },
133
134 max : function(that) {
135 return this.factory.create(
136 Math.max(this.x , that.x), Math.max(this.y , that.y))
137 },
138
139 constrainTo : function (one, two) {
140 var min = one.min(two)
141 var max = one.max(two)
142
143 return this.max(min).min(max)
144 },
145
146 distance : function (that) {
147 return Math.sqrt(Math.pow(this.x - that.x, 2) + Math.pow(this.y - that.y, 2))
148 rizwank 1.1 },
149
150 reposition : function(element) {
151 element.style["top"] = this.y + "px"
152 element.style["left"] = this.x + "px"
153 }
154 }
|