BoundingBoxController.js 5.6 KB

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