drop.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #ifdef 0
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  4. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #endif
  6. // A little delay that prevents the grid from being too sensitive when dragging
  7. // sites around.
  8. const DELAY_REARRANGE_MS = 100;
  9. /**
  10. * This singleton implements site dropping functionality.
  11. */
  12. var gDrop = {
  13. /**
  14. * The last drop target.
  15. */
  16. _lastDropTarget: null,
  17. /**
  18. * Handles the 'dragenter' event.
  19. * @param aCell The drop target cell.
  20. */
  21. enter: function(aCell) {
  22. this._delayedRearrange(aCell);
  23. },
  24. /**
  25. * Handles the 'dragexit' event.
  26. * @param aCell The drop target cell.
  27. * @param aEvent The 'dragexit' event.
  28. */
  29. exit: function(aCell, aEvent) {
  30. if (aEvent.dataTransfer && !aEvent.dataTransfer.mozUserCancelled) {
  31. this._delayedRearrange();
  32. } else {
  33. // The drag operation has been cancelled.
  34. this._cancelDelayedArrange();
  35. this._rearrange();
  36. }
  37. },
  38. /**
  39. * Handles the 'drop' event.
  40. * @param aCell The drop target cell.
  41. * @param aEvent The 'dragexit' event.
  42. */
  43. drop: function(aCell, aEvent) {
  44. // The cell that is the drop target could contain a pinned site. We need
  45. // to find out where that site has gone and re-pin it there.
  46. if (aCell.containsPinnedSite())
  47. this._repinSitesAfterDrop(aCell);
  48. // Pin the dragged or insert the new site.
  49. this._pinDraggedSite(aCell, aEvent);
  50. this._cancelDelayedArrange();
  51. // Update the grid and move all sites to their new places.
  52. gUpdater.updateGrid();
  53. },
  54. /**
  55. * Re-pins all pinned sites in their (new) positions.
  56. * @param aCell The drop target cell.
  57. */
  58. _repinSitesAfterDrop: function(aCell) {
  59. let sites = gDropPreview.rearrange(aCell);
  60. // Filter out pinned sites.
  61. let pinnedSites = sites.filter(function(aSite) {
  62. return aSite && aSite.isPinned();
  63. });
  64. // Re-pin all shifted pinned cells.
  65. pinnedSites.forEach(aSite => aSite.pin(sites.indexOf(aSite)));
  66. },
  67. /**
  68. * Pins the dragged site in its new place.
  69. * @param aCell The drop target cell.
  70. * @param aEvent The 'dragexit' event.
  71. */
  72. _pinDraggedSite: function(aCell, aEvent) {
  73. let index = aCell.index;
  74. let draggedSite = gDrag.draggedSite;
  75. if (draggedSite) {
  76. // Pin the dragged site at its new place.
  77. if (aCell != draggedSite.cell)
  78. draggedSite.pin(index);
  79. } else {
  80. let link = gDragDataHelper.getLinkFromDragEvent(aEvent);
  81. if (link) {
  82. // A new link was dragged onto the grid. Create it by pinning its URL.
  83. gPinnedLinks.pin(link, index);
  84. // Make sure the newly added link is not blocked.
  85. gBlockedLinks.unblock(link);
  86. }
  87. }
  88. },
  89. /**
  90. * Time a rearrange with a little delay.
  91. * @param aCell The drop target cell.
  92. */
  93. _delayedRearrange: function(aCell) {
  94. // The last drop target didn't change so there's no need to re-arrange.
  95. if (this._lastDropTarget == aCell)
  96. return;
  97. let self = this;
  98. function callback() {
  99. self._rearrangeTimeout = null;
  100. self._rearrange(aCell);
  101. }
  102. this._cancelDelayedArrange();
  103. this._rearrangeTimeout = setTimeout(callback, DELAY_REARRANGE_MS);
  104. // Store the last drop target.
  105. this._lastDropTarget = aCell;
  106. },
  107. /**
  108. * Cancels a timed rearrange, if any.
  109. */
  110. _cancelDelayedArrange: function() {
  111. if (this._rearrangeTimeout) {
  112. clearTimeout(this._rearrangeTimeout);
  113. this._rearrangeTimeout = null;
  114. }
  115. },
  116. /**
  117. * Rearrange all sites in the grid depending on the current drop target.
  118. * @param aCell The drop target cell.
  119. */
  120. _rearrange: function(aCell) {
  121. let sites = gGrid.sites;
  122. // We need to rearrange the grid only if there's a current drop target.
  123. if (aCell)
  124. sites = gDropPreview.rearrange(aCell);
  125. gTransformation.rearrangeSites(sites, {unfreeze: !aCell});
  126. }
  127. };