diff options
Diffstat (limited to 'node_modules/montage-user/ui/nearest-neighbor-component-search.js')
-rw-r--r-- | node_modules/montage-user/ui/nearest-neighbor-component-search.js | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/node_modules/montage-user/ui/nearest-neighbor-component-search.js b/node_modules/montage-user/ui/nearest-neighbor-component-search.js new file mode 100644 index 00000000..209d25f8 --- /dev/null +++ b/node_modules/montage-user/ui/nearest-neighbor-component-search.js | |||
@@ -0,0 +1,226 @@ | |||
1 | var Montage = require("montage").Montage; | ||
2 | |||
3 | var NearestNeighborComponentSearch = exports.NearestNeighborComponentSearch = Montage.create(Montage, { | ||
4 | |||
5 | _componentList: { | ||
6 | enumerable: false, | ||
7 | value: null | ||
8 | }, | ||
9 | |||
10 | componentList: { | ||
11 | get: function () { | ||
12 | return this._componentList; | ||
13 | }, | ||
14 | set: function (value) { | ||
15 | var i; | ||
16 | |||
17 | this._componentList=value; | ||
18 | } | ||
19 | }, | ||
20 | |||
21 | _pointerPosition: { | ||
22 | enumerable: false, | ||
23 | value: null | ||
24 | }, | ||
25 | |||
26 | pointerPosition: { | ||
27 | get: function () { | ||
28 | return this._pointerPosition; | ||
29 | }, | ||
30 | set: function (value) { | ||
31 | var nearest = null; | ||
32 | |||
33 | this._pointerPosition=value; | ||
34 | if ((this._componentList)&&(this._componentList.length)) { | ||
35 | var target = value.target, | ||
36 | nearest; | ||
37 | |||
38 | for (i=0; i<this._componentList.length; i++) { | ||
39 | this._componentList[i]._element.setAttribute("data-nn-index", i); | ||
40 | } | ||
41 | while ((target.tagName !== "BODY")&&!(nearest = target.getAttribute("data-nn-index"))) { | ||
42 | target = target.parentNode; | ||
43 | } | ||
44 | for (i=0; i<this._componentList.length; i++) { | ||
45 | this._componentList[i]._element.removeAttribute("data-nn-index", i); | ||
46 | } | ||
47 | } | ||
48 | if (nearest) { | ||
49 | this.nearestNeighborComponent = Number(nearest); | ||
50 | } else { | ||
51 | if (value && this._hasNearestNeighborComponentSearch && this._componentList) { | ||
52 | if (this._nearestNeighborComponentSearchMethod==="precise") { | ||
53 | this.nearestNeighborComponent=this._searchPreciseNearestNeighborComponent(); | ||
54 | } else { | ||
55 | this.nearestNeighborComponent=this._searchMidpointNearestNeighborComponent(); | ||
56 | } | ||
57 | } else { | ||
58 | this.nearestNeighborComponent=null; | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | }, | ||
63 | |||
64 | _hasNearestNeighborComponentSearch: { | ||
65 | enumerable: false, | ||
66 | value: true | ||
67 | }, | ||
68 | |||
69 | hasNearestNeighborComponentSearch: { | ||
70 | get: function () { | ||
71 | return this._hasNearestNeighborComponentSearch; | ||
72 | }, | ||
73 | set: function (value) { | ||
74 | if (value===true) { | ||
75 | this._hasNearestNeighborComponentSearch=true; | ||
76 | } else { | ||
77 | this._hasNearestNeighborComponentSearch=false; | ||
78 | } | ||
79 | } | ||
80 | }, | ||
81 | |||
82 | _nearestNeighborComponentSearchMethod: { | ||
83 | enumerable: false, | ||
84 | value: "precise" | ||
85 | }, | ||
86 | |||
87 | nearestNeighborComponentSearchMethod: { | ||
88 | get: function () { | ||
89 | return this._nearestNeighborComponentSearchMethod; | ||
90 | }, | ||
91 | set: function (vale) { | ||
92 | if (value==="midpoint") { | ||
93 | this._nearestNeighborComponentSearchMethod=value; | ||
94 | } else { | ||
95 | this._nearestNeighborComponentSearchMethod="precise"; | ||
96 | } | ||
97 | } | ||
98 | }, | ||
99 | |||
100 | _pointToQuadSquaredDistance: { | ||
101 | enumerable: false, | ||
102 | value: function (pX, pY, q) { | ||
103 | var dist, iDist, | ||
104 | i, j, u, x, y, div, | ||
105 | dist=1e20, a, b; | ||
106 | |||
107 | q[0]-=pX; q[1]-=pY; q[2]-=pX; q[3]-=pY; | ||
108 | q[4]-=pX; q[5]-=pY; q[6]-=pX; q[7]-=pY; | ||
109 | for (i=0; i<8; i+=2) { | ||
110 | j=(i+2)%8; | ||
111 | a=q[i+1]-q[j+1]; | ||
112 | b=q[j]-q[i]; | ||
113 | div=a*a+b*b; | ||
114 | if (div>1e-10) { | ||
115 | u=q[i+1]*a-q[i]*b; | ||
116 | if (u<0) { | ||
117 | x=q[i]; | ||
118 | y=q[i+1]; | ||
119 | } else if (u>div) { | ||
120 | x=q[i]+b; | ||
121 | y=q[i+1]-a; | ||
122 | } else { | ||
123 | u/=div; | ||
124 | x=q[i]+u*b; | ||
125 | y=q[i+1]-u*a; | ||
126 | } | ||
127 | iDist=x*x+y*y; | ||
128 | if (iDist<dist) { | ||
129 | dist=iDist; | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | return dist; | ||
134 | } | ||
135 | }, | ||
136 | |||
137 | _searchPreciseNearestNeighborComponent: { | ||
138 | enumerable: false, | ||
139 | value: function () { | ||
140 | var length=this._componentList.length, | ||
141 | point=new WebKitPoint(0, 0), | ||
142 | v0, v1, v2, v3, i, | ||
143 | quad=Array(8), | ||
144 | element, | ||
145 | iDistance, | ||
146 | distance=1e20, | ||
147 | pageX=this._pointerPosition.pageX, | ||
148 | pageY=this._pointerPosition.pageY, | ||
149 | convert=window.webkitConvertPointFromNodeToPage, | ||
150 | nearest=null, | ||
151 | index; | ||
152 | |||
153 | for (i=0; i<length; i++) { | ||
154 | element=this._componentList[i].element; | ||
155 | point.y=0; | ||
156 | v0=convert(element, point); | ||
157 | point.x=element.offsetWidth; | ||
158 | v1=convert(element, point); | ||
159 | point.y=element.offsetHeight; | ||
160 | v2=convert(element, point); | ||
161 | point.x=0; | ||
162 | v3=convert(element, point); | ||
163 | quad[0]=v0.x; | ||
164 | quad[1]=v0.y; | ||
165 | quad[2]=v1.x; | ||
166 | quad[3]=v1.y; | ||
167 | quad[4]=v2.x; | ||
168 | quad[5]=v2.y; | ||
169 | quad[6]=v3.x; | ||
170 | quad[7]=v3.y; | ||
171 | iDistance=this._pointToQuadSquaredDistance(pageX, pageY, quad); | ||
172 | if (iDistance < distance) { | ||
173 | distance=iDistance; | ||
174 | //nearest=this._componentList[i]; | ||
175 | nearest=i; | ||
176 | } | ||
177 | } | ||
178 | return nearest; | ||
179 | } | ||
180 | }, | ||
181 | |||
182 | _searchMidpointNearestNeighborComponent: { | ||
183 | enumerable: false, | ||
184 | value: function () { | ||
185 | var length=this._componentList.length, | ||
186 | point=new WebKitPoint(0, 0), | ||
187 | element, | ||
188 | iDistance, | ||
189 | distance=1e20, | ||
190 | v, i, | ||
191 | pageX=this._pointerPosition.pageX, | ||
192 | pageY=this._pointerPosition.pageY, | ||
193 | convert=window.webkitConvertPointFromNodeToPage, | ||
194 | nearest=null, | ||
195 | index; | ||
196 | |||
197 | for (i=0; i<length; i++) { | ||
198 | element=this._componentList[i].element; | ||
199 | point.x=element.offsetWidth>>1; | ||
200 | point.y=element.offsetHeight>>1; | ||
201 | v=convert(element, point); | ||
202 | iDistance=(pageX-v.x)*(pageX-v.x)+(pageY-v.y)*(pageY-v.y); | ||
203 | if (iDistance < distance) { | ||
204 | distance=iDistance; | ||
205 | //nearest=this._componentList[i]; | ||
206 | nearest=i; | ||
207 | } | ||
208 | } | ||
209 | return nearest; | ||