aboutsummaryrefslogtreecommitdiff
path: root/node_modules/montage-user/ui/nearest-neighbor-component-search.js
diff options
context:
space:
mode:
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.js226
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 @@
1var Montage = require("montage").Montage;
2
3var 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;