dragndrop.js 5.6 KB

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