1 | define(["dojo", "dojox"], function(dojo, dojox) { |
---|
2 | |
---|
3 | return dojo.declare('dojox.dnd.BoundingBoxController', null, { |
---|
4 | |
---|
5 | // summary: Allows the user draw bounding boxes around nodes on the page. |
---|
6 | // Publishes to the "/dojox/dnd/bounding" topic to tell the selector to check |
---|
7 | // to see whether any dnd items fall within the coordinates of the bounding box |
---|
8 | |
---|
9 | // x,y start and end coordinates for the bounding box |
---|
10 | _startX: null, |
---|
11 | _startY: null, |
---|
12 | _endX: null, |
---|
13 | _endY: null, |
---|
14 | |
---|
15 | constructor: function(sources, domNode) { |
---|
16 | // summary: |
---|
17 | // Sets mouse handlers for the document to capture when a user |
---|
18 | // is trying to draw a bounding box. |
---|
19 | // sources: Array: |
---|
20 | // an array of dojox.dnd.Selectors which need to be aware of |
---|
21 | // the positioning of the bounding box. |
---|
22 | // domNode: String|DomNode: |
---|
23 | // the DOM node or id which represents the bounding box on the page. |
---|
24 | this.events = [ |
---|
25 | dojo.connect(dojo.doc, 'onmousedown', this, '_onMouseDown'), |
---|
26 | dojo.connect(dojo.doc, 'onmouseup', this, '_onMouseUp'), |
---|
27 | // cancel text selection and text dragging |
---|
28 | //dojo.connect(dojo.doc, "ondragstart", dojo.stopEvent), |
---|
29 | //dojo.connect(dojo.doc, "onselectstart", dojo.stopEvent), |
---|
30 | // when a user is scrolling using a scrollbar, don't draw the bounding box. |
---|
31 | dojo.connect(dojo.doc, 'onscroll', this, '_finishSelecting') |
---|
32 | ]; |
---|
33 | // set up a subscription so the client can easily cancel a user drawing a bounding box. |
---|
34 | this.subscriptions = [ |
---|
35 | dojo.subscribe('/dojox/bounding/cancel', this, '_finishSelecting') |
---|
36 | ]; |
---|
37 | dojo.forEach(sources, function(item) { |
---|
38 | // listen for "/dojox/dnd/bounding" events eminating from the bounding box. |
---|
39 | // for each of the dojox.dnd.selectors passed in args. |
---|
40 | if (item.selectByBBox) { |
---|
41 | this.subscriptions.push(dojo.subscribe('/dojox/dnd/bounding', item, 'selectByBBox')); |
---|
42 | } |
---|
43 | }, this); |
---|
44 | this.domNode = dojo.byId(domNode); |
---|
45 | dojo.style(this.domNode, { |
---|
46 | position: 'absolute', |
---|
47 | display: 'none' |
---|
48 | }); |
---|
49 | }, |
---|
50 | |
---|
51 | destroy: function() { |
---|
52 | // summary: |
---|
53 | // prepares this object to be garbage-collected |
---|
54 | dojo.forEach(this.events, dojo.disconnect); |
---|
55 | dojo.forEach(this.subscriptions, dojo.unsubscribe); |
---|
56 | this.domNode = null; |
---|
57 | }, |
---|
58 | |
---|
59 | shouldStartDrawingBox: function(evt) { |
---|
60 | // summary: Override-able by the client as an extra check to ensure that a bounding |
---|
61 | // box should begin to be drawn. If the client has any preconditions to when a |
---|
62 | // bounding box should be drawn, they should be included in this method. |
---|
63 | // evt: Object: the mouse event which caused this callback to fire. |
---|
64 | return true; |
---|
65 | }, |
---|
66 | |
---|
67 | boundingBoxIsViable: function(evt) { |
---|
68 | // summary: Override-able by the client as an extra check to ensure that a bounding |
---|
69 | // box is viable. In some instances, it might not make sense that |
---|
70 | // a mouse down -> mouse move -> mouse up interaction represents a bounding box. |
---|
71 | // For example, if a dialog is open the client might want to suppress a bounding |
---|
72 | // box. This function could be used by the client to ensure that a bounding box is only |
---|
73 | // drawn on the document when certain conditions are met. |
---|
74 | // evt: Object: the mouse event which caused this callback to fire. |
---|
75 | return true; |
---|
76 | }, |
---|
77 | |
---|
78 | _onMouseDown: function(evt) { |
---|
79 | // summary: Executed when the user mouses down on the document. Resets the |
---|
80 | // this._startX and this._startY member variables. |
---|
81 | // evt: Object: the mouse event which caused this callback to fire. |
---|
82 | if (this.shouldStartDrawingBox(evt) && dojo.mouseButtons.isLeft(evt)) { |
---|
83 | if (this._startX == null) { |
---|
84 | this._startX = evt.clientX; |
---|
85 | this._startY = evt.clientY; |
---|
86 | } |
---|
87 | this.events.push( |
---|
88 | dojo.connect(dojo.doc, 'onmousemove', this, '_onMouseMove') |
---|
89 | ); |
---|
90 | } |
---|
91 | }, |
---|
92 | |
---|
93 | _onMouseMove: function(evt) { |
---|
94 | // summary: Executed when the user moves the mouse over the document. Delegates to |
---|
95 | // this._drawBoundingBox if the user is trying to draw a bounding box. |
---|
96 | // whether the user was drawing a bounding box and publishes to the |
---|
97 | // "/dojox/dnd/bounding" topic if the user is finished drawing their bounding box. |
---|
98 | // evt: Object: the mouse event which caused this callback to fire. |
---|
99 | this._endX = evt.clientX; |
---|
100 | this._endY = evt.clientY; |
---|
101 | this._drawBoundingBox(); |
---|
102 | }, |
---|
103 | |
---|
104 | _onMouseUp: function(evt) { |
---|
105 | // summary: Executed when the users mouses up on the document. Checks to see |
---|
106 | // whether the user was drawing a bounding box and publishes to the |
---|
107 | // "/dojox/dnd/bounding" topic if the user is finished drawing their bounding box. |
---|
108 | // evt: Object: the mouse event which caused this callback to fire. |
---|
109 | if (this._endX !== null && this.boundingBoxIsViable(evt)) { |
---|
110 | // the user has moused up ... tell the selector to check to see whether |
---|
111 | // any nodes within the bounding box need to be selected. |
---|
112 | dojo.publish('/dojox/dnd/bounding', [this._startX, this._startY, this._endX, this._endY]); |
---|
113 | } |
---|
114 | this._finishSelecting(); |
---|
115 | }, |
---|
116 | |
---|
117 | _finishSelecting: function() { |
---|
118 | // summary: hide the bounding box and reset for the next time around |
---|
119 | if (this._startX !== null) { |
---|
120 | dojo.disconnect(this.events.pop()); |
---|
121 | dojo.style(this.domNode, 'display', 'none'); |
---|
122 | this._startX = null; |
---|
123 | this._endX = null; |
---|
124 | } |
---|
125 | }, |
---|
126 | |
---|
127 | _drawBoundingBox: function() { |
---|
128 | // summary: draws the bounding box over the document. |
---|
129 | dojo.style(this.domNode, { |
---|
130 | left: Math.min(this._startX, this._endX) + 'px', |
---|
131 | top: Math.min(this._startY, this._endY) + 'px', |
---|
132 | width: Math.abs(this._startX - this._endX) + 'px', |
---|
133 | height: Math.abs(this._startY - this._endY) + 'px', |
---|
134 | display: '' |
---|
135 | }); |
---|
136 | } |
---|
137 | } |
---|
138 | ); |
---|
139 | }); |
---|