1 | define(["dojo/_base/declare", "dojo/_base/sniff", "dojo/_base/lang", "dojo/aspect", "dojo/dom", "dojo/dom-attr", "dojo/dom-class", "dojo/dom-geometry", "dojo/dom-style", "dojo/dom-construct", "dojo/on", "dojo/_base/window", "dojo/mouse", "dijit/_WidgetBase", "dijit/_TemplatedMixin", "dijit/_Container", "./FisheyeListItem"], |
---|
2 | function(declare, has, lang, aspect, dom, attr, domClass, geometry, style, construct, on, winUtil, mouse, _WidgetBase, _TemplatedMixin, _Container, FisheyeListItem){ |
---|
3 | |
---|
4 | return declare("dojox.widget.FisheyeList", |
---|
5 | [_WidgetBase, _TemplatedMixin, _Container], { |
---|
6 | // summary: |
---|
7 | // Menu similar to the fish eye menu on the Mac OS |
---|
8 | // example: |
---|
9 | // | <div dojoType="dojo.widget.FisheyeList" |
---|
10 | // | itemWidth="40" itemHeight="40" |
---|
11 | // | itemMaxWidth="150" itemMaxHeight="150" |
---|
12 | // | orientation="horizontal" |
---|
13 | // | effectUnits="2" |
---|
14 | // | itemPadding="10" |
---|
15 | // | attachEdge="center" |
---|
16 | // | labelEdge="bottom"> |
---|
17 | // | |
---|
18 | // | <div dojoType="dojox.widget.FisheyeListItem" |
---|
19 | // | id="item1" |
---|
20 | // | onclick="alert('click on' + this.label + '(from widget id ' + this.widgetId + ')!');" |
---|
21 | // | label="Item 1" |
---|
22 | // | iconSrc="images/fisheye_1.png"> |
---|
23 | // | </div> |
---|
24 | // | ... |
---|
25 | // | </div> |
---|
26 | |
---|
27 | constructor: function(){ |
---|
28 | // |
---|
29 | // TODO |
---|
30 | // fix really long labels in vertical mode |
---|
31 | // |
---|
32 | |
---|
33 | this.pos = {'x': -1, 'y': -1}; // current cursor position, relative to the grid |
---|
34 | |
---|
35 | // for conservative trigger mode, when triggered, timerScale is gradually increased from 0 to 1 |
---|
36 | this.timerScale = 1.0; |
---|
37 | }, |
---|
38 | |
---|
39 | EDGE: { |
---|
40 | CENTER: 0, |
---|
41 | LEFT: 1, |
---|
42 | RIGHT: 2, |
---|
43 | TOP: 3, |
---|
44 | BOTTOM: 4 |
---|
45 | }, |
---|
46 | |
---|
47 | templateString: '<div class="dojoxFisheyeListBar" data-dojo-attach-point="containerNode"></div>', |
---|
48 | |
---|
49 | snarfChildDomOutput: true, |
---|
50 | |
---|
51 | // itemWidth: Integer |
---|
52 | // width of menu item (in pixels) in it's dormant state (when the mouse is far away) |
---|
53 | itemWidth: 40, |
---|
54 | |
---|
55 | // itemHeight: Integer |
---|
56 | // height of menu item (in pixels) in it's dormant state (when the mouse is far away) |
---|
57 | itemHeight: 40, |
---|
58 | |
---|
59 | // itemMaxWidth: Integer |
---|
60 | // width of menu item (in pixels) in it's fully enlarged state (when the mouse is directly over it) |
---|
61 | itemMaxWidth: 150, |
---|
62 | |
---|
63 | // itemMaxHeight: Integer |
---|
64 | // height of menu item (in pixels) in it's fully enlarged state (when the mouse is directly over it) |
---|
65 | itemMaxHeight: 150, |
---|
66 | |
---|
67 | imgNode: null, |
---|
68 | |
---|
69 | // orientation: String |
---|
70 | // orientation of the menu, either "horizontal" or "vertical" |
---|
71 | orientation: 'horizontal', |
---|
72 | |
---|
73 | // isFixed: Boolean |
---|
74 | // toggle to enable additional listener (window scroll) if FisheyeList is in a fixed postion |
---|
75 | isFixed: false, |
---|
76 | |
---|
77 | // conservativeTrigger: Boolean |
---|
78 | // if true, don't start enlarging menu items until mouse is over an image; |
---|
79 | // if false, start enlarging menu items as the mouse moves near them. |
---|
80 | conservativeTrigger: false, |
---|
81 | |
---|
82 | // effectUnits: Number |
---|
83 | // controls how much reaction the menu makes, relative to the distance of the mouse from the menu |
---|
84 | effectUnits: 2, |
---|
85 | |
---|
86 | // itemPadding: Integer |
---|
87 | // padding (in pixels) between each menu item |
---|
88 | itemPadding: 10, |
---|
89 | |
---|
90 | // attachEdge: String |
---|
91 | // Controls the border that the menu items don't expand past; |
---|
92 | // for example, if set to "top", then the menu items will drop downwards as they expand. |
---|
93 | // Values: "center", "left", "right", "top", "bottom". |
---|
94 | attachEdge: 'center', |
---|
95 | |
---|
96 | // labelEdge: String |
---|
97 | // Controls were the labels show up in relation to the menu item icons. |
---|
98 | // Values: "center", "left", "right", "top", "bottom". |
---|
99 | labelEdge: 'bottom', |
---|
100 | |
---|
101 | postCreate: function(){ |
---|
102 | var e = this.EDGE, |
---|
103 | isHorizontal = this.isHorizontal = (this.orientation == 'horizontal'); |
---|
104 | |
---|
105 | dom.setSelectable(this.domNode, false); |
---|
106 | |
---|
107 | this.selectedNode = -1; |
---|
108 | |
---|
109 | this.isOver = false; |
---|
110 | this.hitX1 = -1; |
---|
111 | this.hitY1 = -1; |
---|
112 | this.hitX2 = -1; |
---|
113 | this.hitY2 = -1; |
---|
114 | |
---|
115 | // |
---|
116 | // only some edges make sense... |
---|
117 | // |
---|
118 | this.anchorEdge = this._toEdge(this.attachEdge, e.CENTER); |
---|
119 | this.labelEdge = this._toEdge(this.labelEdge, e.TOP); |
---|
120 | |
---|
121 | if(this.labelEdge == e.CENTER){ this.labelEdge = e.TOP; } |
---|
122 | |
---|
123 | if(isHorizontal){ |
---|
124 | if(this.anchorEdge == e.LEFT){ this.anchorEdge = e.CENTER; } |
---|
125 | if(this.anchorEdge == e.RIGHT){ this.anchorEdge = e.CENTER; } |
---|
126 | if(this.labelEdge == e.LEFT){ this.labelEdge = e.TOP; } |
---|
127 | if(this.labelEdge == e.RIGHT){ this.labelEdge = e.TOP; } |
---|
128 | }else{ |
---|
129 | if(this.anchorEdge == e.TOP){ this.anchorEdge = e.CENTER; } |
---|
130 | if(this.anchorEdge == e.BOTTOM){ this.anchorEdge = e.CENTER; } |
---|
131 | if(this.labelEdge == e.TOP){ this.labelEdge = e.LEFT; } |
---|
132 | if(this.labelEdge == e.BOTTOM){ this.labelEdge = e.LEFT; } |
---|
133 | } |
---|
134 | |
---|
135 | // |
---|
136 | // figure out the proximity size |
---|
137 | // |
---|
138 | var effectUnits = this.effectUnits; |
---|
139 | this.proximityLeft = this.itemWidth * (effectUnits - 0.5); |
---|
140 | this.proximityRight = this.itemWidth * (effectUnits - 0.5); |
---|
141 | this.proximityTop = this.itemHeight * (effectUnits - 0.5); |
---|
142 | this.proximityBottom = this.itemHeight * (effectUnits - 0.5); |
---|
143 | |
---|
144 | if(this.anchorEdge == e.LEFT){ |
---|
145 | this.proximityLeft = 0; |
---|
146 | } |
---|
147 | if(this.anchorEdge == e.RIGHT){ |
---|
148 | this.proximityRight = 0; |
---|
149 | } |
---|
150 | if(this.anchorEdge == e.TOP){ |
---|
151 | this.proximityTop = 0; |
---|
152 | } |
---|
153 | if(this.anchorEdge == e.BOTTOM){ |
---|
154 | this.proximityBottom = 0; |
---|
155 | } |
---|
156 | if(this.anchorEdge == e.CENTER){ |
---|
157 | this.proximityLeft /= 2; |
---|
158 | this.proximityRight /= 2; |
---|
159 | this.proximityTop /= 2; |
---|
160 | this.proximityBottom /= 2; |
---|
161 | } |
---|
162 | }, |
---|
163 | |
---|
164 | startup: function(){ |
---|
165 | // summary: |
---|
166 | // create our connections and setup our FisheyeList |
---|
167 | this.children = this.getChildren(); |
---|
168 | //original postCreate() --tk |
---|
169 | this._initializePositioning(); |
---|
170 | |
---|
171 | // |
---|
172 | // in liberal trigger mode, activate menu whenever mouse is close, in conservative mode, pause until needed |
---|
173 | // |
---|
174 | this._onMouseMoveHandle = on.pausable(winUtil.doc.documentElement, "mousemove", lang.hitch(this, "_onMouseMove")); |
---|
175 | if(this.conservativeTrigger){ |
---|
176 | this._onMouseMoveHandle.pause(); |
---|
177 | } |
---|
178 | if(this.isFixed){ |
---|
179 | this.own(on(winUtil.doc,"scroll", lang.hitch(this, this._onScroll))); |
---|
180 | } |
---|
181 | |
---|
182 | // Deactivate the menu if mouse is moved off screen (doesn't work for FF?) |
---|
183 | this.own( |
---|
184 | on(winUtil.doc.documentElement, mouse.leave, lang.hitch(this, "_onBodyOut")), |
---|
185 | aspect.after(this, "addChild", lang.hitch(this, "_initializePositioning"), true), |
---|
186 | aspect.after(winUtil.global, "onresize", lang.hitch(this, "_initializePositioning"), true) |
---|
187 | ); |
---|
188 | }, |
---|
189 | |
---|
190 | _initializePositioning: function(){ |
---|
191 | this.itemCount = this.children.length; |
---|
192 | |
---|
193 | this.barWidth = (this.isHorizontal ? this.itemCount : 1) * this.itemWidth; |
---|
194 | this.barHeight = (this.isHorizontal ? 1 : this.itemCount) * this.itemHeight; |
---|
195 | |
---|
196 | this.totalWidth = this.proximityLeft + this.proximityRight + this.barWidth; |
---|
197 | this.totalHeight = this.proximityTop + this.proximityBottom + this.barHeight; |
---|
198 | |
---|
199 | // |
---|
200 | // calculate effect ranges for each item |
---|
201 | // |
---|
202 | |
---|
203 | for(var i=0; i<this.children.length; i++){ |
---|
204 | |
---|
205 | this.children[i].posX = this.itemWidth * (this.isHorizontal ? i : 0); |
---|
206 | this.children[i].posY = this.itemHeight * (this.isHorizontal ? 0 : i); |
---|
207 | |
---|
208 | this.children[i].cenX = this.children[i].posX + (this.itemWidth / 2); |
---|
209 | this.children[i].cenY = this.children[i].posY + (this.itemHeight / 2); |
---|
210 | |
---|
211 | var isz = this.isHorizontal ? this.itemWidth : this.itemHeight, |
---|
212 | r = this.effectUnits * isz, |
---|
213 | c = this.isHorizontal ? this.children[i].cenX : this.children[i].cenY, |
---|
214 | lhs = this.isHorizontal ? this.proximityLeft : this.proximityTop, |
---|
215 | rhs = this.isHorizontal ? this.proximityRight : this.proximityBottom, |
---|
216 | siz = this.isHorizontal ? this.barWidth : this.barHeight, |
---|
217 | |
---|
218 | range_lhs = r, |
---|
219 | range_rhs = r; |
---|
220 | |
---|
221 | if(range_lhs > c+lhs){ range_lhs = c+lhs; } |
---|
222 | if(range_rhs > (siz-c+rhs)){ range_rhs = siz-c+rhs; } |
---|
223 | |
---|
224 | this.children[i].effectRangeLeft = range_lhs / isz; |
---|
225 | this.children[i].effectRangeRght = range_rhs / isz; |
---|
226 | |
---|
227 | //dojo.debug('effect range for '+i+' is '+range_lhs+'/'+range_rhs); |
---|
228 | } |
---|
229 | |
---|
230 | // |
---|
231 | // create the bar |
---|
232 | // |
---|
233 | style.set(this.domNode, {width: this.barWidth + 'px', height: this.barHeight + 'px'}); |
---|
234 | |
---|
235 | // |
---|
236 | // position the items |
---|
237 | // |
---|
238 | for(i=0; i<this.children.length; i++){ |
---|
239 | var itm = this.children[i]; |
---|
240 | var elm = itm.domNode; |
---|
241 | style.set(elm, {left: itm.posX + 'px', top: itm.posY + 'px', width: this.itemWidth + 'px', height: this.itemHeight + 'px'}); |
---|
242 | |
---|
243 | style.set(itm.imgNode, {left: this.itemPadding+'%', top: this.itemPadding+'%', width: (100 - 2 * this.itemPadding) + '%', height: (100 - 2 * this.itemPadding) + '%'}); |
---|
244 | } |
---|
245 | // |
---|
246 | // calc the grid |
---|
247 | // |
---|
248 | this._calcHitGrid(); |
---|
249 | }, |
---|
250 | |
---|
251 | _overElement: function(/* DomNode|String */ node, /* Event */ e){ |
---|
252 | // summary: |
---|
253 | // Returns whether the mouse is over the passed element. |
---|
254 | // node: |
---|
255 | // Must must be display:block (ie, not a `<span>`) |
---|
256 | node = dom.byId(node); |
---|
257 | var mouse = {x: e.pageX, y: e.pageY}, |
---|
258 | absolute = geometry.position(node, true), |
---|
259 | top = absolute.y, |
---|
260 | bottom = top + absolute.h, |
---|
261 | left = absolute.x, |
---|
262 | right = left + absolute.w; |
---|
263 | |
---|
264 | return (mouse.x >= left |
---|
265 | && mouse.x <= right |
---|
266 | && mouse.y >= top |
---|
267 | && mouse.y <= bottom |
---|
268 | ); // Boolean |
---|
269 | }, |
---|
270 | |
---|
271 | _onBodyOut: function(/*Event*/ e){ |
---|
272 | // clicking over an object inside of body causes this event to fire; ignore that case |
---|
273 | if( this._overElement(winUtil.body(), e) ){ |
---|
274 | return; |
---|
275 | } |
---|
276 | this._setDormant(e); |
---|
277 | }, |
---|
278 | |
---|
279 | _setDormant: function(/*Event*/ e){ |
---|
280 | // summary: |
---|
281 | // called when mouse moves out of menu's range |
---|
282 | |
---|
283 | if(!this.isOver){ return; } // already dormant? |
---|
284 | this.isOver = false; |
---|
285 | |
---|
286 | if(this.conservativeTrigger){ |
---|
287 | // user can't re-trigger the menu expansion |
---|
288 | // until he mouses over a icon again |
---|
289 | this._onMouseMoveHandle.pause(); |
---|
290 | } |
---|
291 | this._onGridMouseMove(-1, -1); |
---|
292 | }, |
---|
293 | |
---|
294 | _setActive: function(/*Event*/ e){ |
---|
295 | // summary: |
---|
296 | // called when mouse is moved into menu's range |
---|
297 | |
---|
298 | if(this.isOver){ return; } // already activated? |
---|
299 | this.isOver = true; |
---|
300 | |
---|
301 | if(this.conservativeTrigger){ |
---|
302 | // switch event handlers so that we handle mouse events from anywhere near |
---|
303 | // the menu |
---|
304 | this._onMouseMoveHandle.resume(); |
---|
305 | |
---|
306 | this.timerScale=0.0; |
---|
307 | |
---|
308 | // call mouse handler to do some initial necessary calculations/positioning |
---|
309 | this._onMouseMove(e); |
---|
310 | |
---|
311 | // slowly expand the icon size so it isn't jumpy |
---|
312 | this._expandSlowly(); |
---|
313 | } |
---|
314 | }, |
---|
315 | |
---|
316 | _onMouseMove: function(/*Event*/ e){ |
---|
317 | // summary: |
---|
318 | // called when mouse is moved |
---|
319 | if( (e.pageX >= this.hitX1) && (e.pageX <= this.hitX2) && |
---|
320 | (e.pageY >= this.hitY1) && (e.pageY <= this.hitY2) ){ |
---|
321 | if(!this.isOver){ |
---|
322 | this._setActive(e); |
---|
323 | } |
---|
324 | this._onGridMouseMove(e.pageX-this.hitX1, e.pageY-this.hitY1); |
---|
325 | }else{ |
---|
326 | if(this.isOver){ |
---|
327 | this._setDormant(e); |
---|
328 | } |
---|
329 | } |
---|
330 | }, |
---|
331 | |
---|
332 | _onScroll: function(){ |
---|
333 | this._calcHitGrid(); |
---|
334 | }, |
---|
335 | |
---|
336 | onResized: function(){ |
---|
337 | this._calcHitGrid(); |
---|
338 | }, |
---|
339 | |
---|
340 | _onGridMouseMove: function(x, y){ |
---|
341 | // summary: |
---|
342 | // called when mouse is moved in the vicinity of the menu |
---|
343 | this.pos = {x:x, y:y}; |
---|
344 | this._paint(); |
---|
345 | }, |
---|
346 | |
---|
347 | _paint: function(){ |
---|
348 | var x=this.pos.x; |
---|
349 | var y=this.pos.y; |
---|
350 | |
---|
351 | if(this.itemCount <= 0){ return; } |
---|
352 | |
---|
353 | // |
---|
354 | // figure out our main index |
---|
355 | // |
---|
356 | var pos = this.isHorizontal ? x : y, |
---|
357 | prx = this.isHorizontal ? this.proximityLeft : this.proximityTop, |
---|
358 | siz = this.isHorizontal ? this.itemWidth : this.itemHeight, |
---|
359 | sim = this.isHorizontal ? |
---|
360 | (1.0-this.timerScale)*this.itemWidth + this.timerScale*this.itemMaxWidth : |
---|
361 | (1.0-this.timerScale)*this.itemHeight + this.timerScale*this.itemMaxHeight, |
---|
362 | |
---|
363 | cen = ((pos - prx) / siz) - 0.5, |
---|
364 | max_off_cen = (sim / siz) - 0.5; |
---|
365 | |
---|
366 | if(max_off_cen > this.effectUnits){ max_off_cen = this.effectUnits; } |
---|
367 | |
---|
368 | // |
---|
369 | // figure out our off-axis weighting |
---|
370 | // |
---|
371 | var off_weight = 0, cen2; |
---|
372 | |
---|
373 | if(this.anchorEdge == this.EDGE.BOTTOM){ |
---|
374 | cen2 = (y - this.proximityTop) / this.itemHeight; |
---|
375 | off_weight = (cen2 > 0.5) ? 1 : y / (this.proximityTop + (this.itemHeight / 2)); |
---|
376 | } |
---|
377 | if(this.anchorEdge == this.EDGE.TOP){ |
---|
378 | cen2 = (y - this.proximityTop) / this.itemHeight; |
---|
379 | off_weight = (cen2 < 0.5) ? 1 : (this.totalHeight - y) / (this.proximityBottom + (this.itemHeight / 2)); |
---|
380 | } |
---|
381 | if(this.anchorEdge == this.EDGE.RIGHT){ |
---|
382 | cen2 = (x - this.proximityLeft) / this.itemWidth; |
---|
383 | off_weight = (cen2 > 0.5) ? 1 : x / (this.proximityLeft + (this.itemWidth / 2)); |
---|
384 | } |
---|
385 | if(this.anchorEdge == this.EDGE.LEFT){ |
---|
386 | cen2 = (x - this.proximityLeft) / this.itemWidth; |
---|
387 | off_weight = (cen2 < 0.5) ? 1 : (this.totalWidth - x) / (this.proximityRight + (this.itemWidth / 2)); |
---|
388 | } |
---|
389 | if(this.anchorEdge == this.EDGE.CENTER){ |
---|
390 | if(this.isHorizontal){ |
---|
391 | off_weight = y / (this.totalHeight); |
---|
392 | }else{ |
---|
393 | off_weight = x / (this.totalWidth); |
---|
394 | } |
---|
395 | |
---|
396 | if(off_weight > 0.5){ |
---|
397 | off_weight = 1 - off_weight; |
---|
398 | } |
---|
399 | |
---|
400 | off_weight *= 2; |
---|
401 | } |
---|
402 | |
---|
403 | // |
---|
404 | // set the sizes |
---|
405 | // |
---|
406 | for(var i=0; i<this.itemCount; i++){ |
---|
407 | var weight = this._weighAt(cen, i); |
---|
408 | if(weight < 0){weight = 0;} |
---|
409 | this._setItemSize(i, weight * off_weight); |
---|
410 | } |
---|
411 | |
---|
412 | // |
---|
413 | // set the positions |
---|
414 | // |
---|
415 | |
---|
416 | var main_p = Math.round(cen), |
---|
417 | offset = 0; |
---|
418 | |
---|
419 | if(cen < 0){ |
---|
420 | |
---|
421 | main_p = 0; |
---|
422 | |
---|
423 | }else if(cen > this.itemCount - 1){ |
---|
424 | |
---|
425 | main_p = this.itemCount -1; |
---|
426 | |
---|
427 | }else{ |
---|
428 | |
---|
429 | offset = (cen - main_p) * ((this.isHorizontal ? this.itemWidth : this.itemHeight) - this.children[main_p].sizeMain); |
---|
430 | } |
---|
431 | |
---|
432 | this._positionElementsFrom(main_p, offset); |
---|
433 | }, |
---|
434 | |
---|
435 | _weighAt: function(/*Integer*/ cen, /*Integer*/ i){ |
---|
436 | var dist = Math.abs(cen - i), |
---|
437 | limit = ((cen - i) > 0) ? this.children[i].effectRangeRght : this.children[i].effectRangeLeft; |
---|
438 | |
---|
439 | return (dist > limit) ? 0 : (1 - dist / limit); // Integer |
---|
440 | }, |
---|
441 | |
---|
442 | _setItemSize: function(p, scale){ |
---|
443 | if(this.children[p].scale == scale){ return; } |
---|
444 | this.children[p].scale = scale; |
---|
445 | |
---|
446 | scale *= this.timerScale; |
---|
447 | var w = Math.round(this.itemWidth + ((this.itemMaxWidth - this.itemWidth ) * scale)), |
---|
448 | h = Math.round(this.itemHeight + ((this.itemMaxHeight - this.itemHeight) * scale)); |
---|
449 | |
---|
450 | if(this.isHorizontal){ |
---|
451 | |
---|
452 | this.children[p].sizeW = w; |
---|
453 | this.children[p].sizeH = h; |
---|
454 | |
---|
455 | this.children[p].sizeMain = w; |
---|
456 | this.children[p].sizeOff = h; |
---|
457 | |
---|
458 | var y = 0; |
---|
459 | if(this.anchorEdge == this.EDGE.TOP){ |
---|
460 | y = (this.children[p].cenY - (this.itemHeight / 2)); |
---|
461 | }else if(this.anchorEdge == this.EDGE.BOTTOM){ |
---|
462 | y = (this.children[p].cenY - (h - (this.itemHeight / 2))); |
---|
463 | }else{ |
---|
464 | y = (this.children[p].cenY - (h / 2)); |
---|
465 | } |
---|
466 | |
---|
467 | this.children[p].usualX = Math.round(this.children[p].cenX - (w / 2)); |
---|
468 | style.set(this.children[p].domNode, {top: y + 'px', left: this.children[p].usualX + 'px'}); |
---|
469 | |
---|
470 | }else{ |
---|
471 | |
---|
472 | this.children[p].sizeW = w; |
---|
473 | this.children[p].sizeH = h; |
---|
474 | |
---|
475 | this.children[p].sizeOff = w; |
---|
476 | this.children[p].sizeMain = h; |
---|
477 | |
---|
478 | var x = 0; |
---|
479 | if(this.anchorEdge == this.EDGE.LEFT){ |
---|
480 | x = this.children[p].cenX - (this.itemWidth / 2); |
---|
481 | }else if(this.anchorEdge == this.EDGE.RIGHT){ |
---|
482 | x = this.children[p].cenX - (w - (this.itemWidth / 2)); |
---|
483 | }else{ |
---|
484 | x = this.children[p].cenX - (w / 2); |
---|
485 | } |
---|
486 | |
---|
487 | this.children[p].usualY = Math.round(this.children[p].cenY - (h / 2)); |
---|
488 | style.set(this.children[p].domNode, {left: x + 'px', top: this.children[p].usualY + 'px'}); |
---|
489 | } |
---|
490 | |
---|
491 | style.set(this.children[p].domNode, {width: w + 'px', height: h + 'px'}); |
---|
492 | |
---|
493 | if(this.children[p].svgNode){ |
---|
494 | this.children[p].svgNode.setSize(w, h); |
---|
495 | } |
---|
496 | }, |
---|
497 | |
---|
498 | _positionElementsFrom: function(p, offset){ |
---|
499 | var pos = 0; |
---|
500 | |
---|
501 | var usual, start; |
---|
502 | if(this.isHorizontal){ |
---|
503 | usual = "usualX"; |
---|
504 | start = "left"; |
---|
505 | }else{ |
---|
506 | usual = "usualY"; |
---|
507 | start = "top"; |
---|
508 | } |
---|
509 | pos = Math.round(this.children[p][usual] + offset); |
---|
510 | if(style.get(this.children[p].domNode, start) != (pos + 'px')){ |
---|
511 | style.set(this.children[p].domNode, start, pos + 'px'); |
---|
512 | this._positionLabel(this.children[p]); |
---|
513 | } |
---|
514 | |
---|
515 | // position before |
---|
516 | var bpos = pos; |
---|
517 | for(var i=p-1; i>=0; i--){ |
---|
518 | bpos -= this.children[i].sizeMain; |
---|
519 | |
---|
520 | if(style.get(this.children[p].domNode, start) != (bpos + 'px')){ |
---|
521 | style.set(this.children[i].domNode, start, bpos + 'px'); |
---|
522 | this._positionLabel(this.children[i]); |
---|
523 | } |
---|
524 | } |
---|
525 | |
---|
526 | // position after |
---|
527 | var apos = pos; |
---|
528 | for(i=p+1; i<this.itemCount; i++){ |
---|
529 | apos += this.children[i-1].sizeMain; |
---|
530 | if(style.get(this.children[p].domNode, start) != (apos + 'px')){ |
---|
531 | style.set(this.children[i].domNode, start, apos + 'px'); |
---|
532 | this._positionLabel(this.children[i]); |
---|
533 | } |
---|
534 | } |
---|
535 | |
---|
536 | }, |
---|
537 | |
---|
538 | _positionLabel: function(itm){ |
---|
539 | var x = 0; |
---|
540 | var y = 0; |
---|
541 | |
---|
542 | var mb = geometry.getMarginBox(itm.lblNode); |
---|
543 | |
---|
544 | if(this.labelEdge == this.EDGE.TOP){ |
---|
545 | x = Math.round((itm.sizeW / 2) - (mb.w / 2)); |
---|
546 | y = -mb.h; |
---|
547 | } |
---|
548 | |
---|
549 | if(this.labelEdge == this.EDGE.BOTTOM){ |
---|
550 | x = Math.round((itm.sizeW / 2) - (mb.w / 2)); |
---|
551 | y = itm.sizeH; |
---|
552 | } |
---|
553 | |
---|
554 | if(this.labelEdge == this.EDGE.LEFT){ |
---|
555 | x = -mb.w; |
---|
556 | y = Math.round((itm.sizeH / 2) - (mb.h / 2)); |
---|
557 | } |
---|
558 | |
---|
559 | if(this.labelEdge == this.EDGE.RIGHT){ |
---|
560 | x = itm.sizeW; |
---|
561 | y = Math.round((itm.sizeH / 2) - (mb.h / 2)); |
---|
562 | } |
---|
563 | |
---|
564 | style.set(itm.lblNode, {left: x + 'px', top: y + 'px'}); |
---|
565 | }, |
---|
566 | |
---|
567 | _calcHitGrid: function(){ |
---|
568 | |
---|
569 | var pos = geometry.position(this.domNode, true); |
---|
570 | |
---|
571 | this.hitX1 = pos.x - this.proximityLeft; |
---|
572 | this.hitY1 = pos.y - this.proximityTop; |
---|
573 | this.hitX2 = this.hitX1 + this.totalWidth; |
---|
574 | this.hitY2 = this.hitY1 + this.totalHeight; |
---|
575 | |
---|
576 | }, |
---|
577 | |
---|
578 | _toEdge: function(inp, def){ |
---|
579 | return this.EDGE[inp.toUpperCase()] || def; |
---|
580 | }, |
---|
581 | |
---|
582 | _expandSlowly: function(){ |
---|
583 | // summary: |
---|
584 | // slowly expand the image to user specified max size |
---|
585 | if(!this.isOver){ return; } |
---|
586 | this.timerScale += 0.2; |
---|
587 | this._paint(); |
---|
588 | if(this.timerScale<1.0){ |
---|
589 | setTimeout(lang.hitch(this, "_expandSlowly"), 10); |
---|
590 | } |
---|
591 | } |
---|
592 | }); |
---|
593 | |
---|
594 | }); |
---|