dragndrop.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. function DragScope(scope) {
  2. function calcShift()
  3. {
  4. var svgWidth = $svg[0].viewBox.baseVal.width;
  5. var svgHeight = $svg[0].viewBox.baseVal.height;
  6. sizeX = svgWidth / innerWidth;
  7. sizeY = svgHeight / innerHeight;
  8. size = Math.max(sizeX, sizeY) || 1;
  9. }
  10. var currentDragTarget = null
  11. function Draggable(root, options)
  12. {
  13. options = options || {},
  14. this.$el = $(root),
  15. this.revert = options.revert,
  16. this.elements = {},
  17. this.proxies = [ "onDown", "onMove", "onUp" ], this.__super__.constructor.call(this),
  18. this.enable();
  19. }
  20. Draggable.revert = function(){
  21. if(currentDragTarget){
  22. currentDragTarget.drop()
  23. }
  24. }
  25. var sizeX,
  26. sizeY,
  27. size,
  28. moved;
  29. $svg = $("svg");
  30. calcShift();
  31. $(window).on("resize", calcShift);
  32. $(window).on("orientationchange", calcShift);
  33. $.inherit(Draggable, scope.Controller);
  34. $.extend(Draggable.prototype, {
  35. storeTrf: function() {
  36. var trf = this.$el.attr("transform");
  37. this.initTrf = trf ? trf.slice(10, -1).split(/\s+/) : [ 0, 0 ];
  38. },
  39. disable: function() {
  40. this.$el.off(document.createTouch ? "touchstart" : "mousedown", this.onDown),
  41. this.$el.css({cursor: "default"});
  42. },
  43. enable: function() {
  44. this.$el.on(document.createTouch ? "touchstart" : "mousedown", this.onDown),
  45. this.$el.attr("style", "cursor: -moz-grab; cursor: -webkit-grab; cursor: grab;");
  46. },
  47. onDown: function(e, silent) {
  48. e.preventDefault(), moved || (moved = !1, this.$el.attr("style", "cursor: -moz-grabbing; cursor: -webkit-grabbing; cursor: grabbing;"),
  49. this.$el[0].parentNode.appendChild(this.$el[0]), this.x = this.clientX(e), this.y = this.clientY(e),
  50. this.trf = this.$el.attr("transform"), this.trf && (this.trf = this.trf.slice(10, -1).split(/\s+/)),
  51. this.storeTrf(), silent || (document.createTouch ? (this.$el.on("touchmove", this.onMove),
  52. this.$el.on("touchend", this.onUp)) : ($("body").on("mousemove", this.onMove), $("body").on("mouseup", this.onUp)),
  53. this.$el.trigger("dragstart")));
  54. },
  55. onMove: function(e, silent) {
  56. e.preventDefault(), moved = !0, currentDragTarget = this, this.dx = ((this.curX = this.clientX(e)) - this.x) * size,
  57. this.dy = ((this.curY = this.clientY(e)) - this.y) * size, this.trf && (this.dx += 0 | this.trf[0],
  58. this.dy += 0 | this.trf[1]), this.$el.attr("transform", "translate(" + this.dx + " " + this.dy + ")"),
  59. silent || this.$el.trigger("dragmove", {
  60. detail: {
  61. x: this.curX,
  62. y: this.curY,
  63. event: e
  64. }
  65. });
  66. },
  67. onUp: function(e, silent) {
  68. e.preventDefault()
  69. this.drop(e, silent)
  70. },
  71. drop: function(e, silent){
  72. currentDragTarget = null
  73. this.$el.attr('style', 'cursor: -moz-grab; cursor: -webkit-grab; cursor: grab;')
  74. // detect drop
  75. if(moved){
  76. var dropList = scope.Droppable.list,
  77. droped
  78. for(var i = 0, l = dropList.length, item; i < l; i++){
  79. item = dropList[i]
  80. if(item.intersect(this.curX, this.curY)){
  81. droped = item.drop(this, this.curX, this.curY)
  82. break
  83. }
  84. }
  85. // revert
  86. if(!droped){
  87. this.$el.transform({
  88. from: [this.dx, this.dy].join(' '),
  89. to: this.initTrf.join(' ')
  90. })
  91. if(!silent){
  92. this.$el.trigger('revert')
  93. }
  94. }
  95. if(!silent){
  96. this.$el.trigger('dragstop', {detail: {x: this.curX, y: this.curY, event: e}})
  97. }
  98. moved = false
  99. }
  100. if(document.createTouch){
  101. this.$el.off('touchmove', this.onMove)
  102. this.$el.off('touchend', this.onUp)
  103. }
  104. else {
  105. $('body').off('mousemove', this.onMove)
  106. $('body').off('mouseup', this.onUp)
  107. }
  108. }
  109. });
  110. scope.Draggable = Draggable;
  111. $.mixin({ draggable: function() { return this.each(function(el) { new Draggable(el); }); } });
  112. }
  113. function DropScope(scope) {
  114. function Droppable(root, options)
  115. {
  116. options = options || {},
  117. this.$el = $(root),
  118. this.accept = options.accept || function() { return !0; },
  119. this.onDrop = options.drop || function() {};
  120. this.elements = {};
  121. this.proxies = [];
  122. this.__super__.constructor.call(this);
  123. this.activate();
  124. }
  125. Droppable.list = [];
  126. $.inherit(Droppable, scope.Controller), $.extend(Droppable.prototype, {
  127. drop: function(target, x, y) { return this.accept(target, x, y) ? (this.onDrop(target, x, y), !0) : !1; },
  128. activate: function() { Droppable.list.push(this); },
  129. release: function() { var i; ~(i = Droppable.list.indexOf(this)) && Droppable.list.splice(i, 1); }
  130. });
  131. scope.Droppable = Droppable,
  132. $.mixin({
  133. droppable: function(options) { return this.each(function(el) { new Droppable(el, options); }); }
  134. });
  135. }