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