Selaa lähdekoodia

为任务泳增加拖动

guohh 4 vuotta sitten
vanhempi
commit
ba8a853135

+ 13 - 0
2020/x-3/biz/css/base-ghh.css

@ -3905,6 +3905,7 @@ body.date-picked .list-item-pickered {
3905 3905
.pages-project-phase-task .ipu-hammer-carousel .ipu-carousel-wrapper > li {
3906 3906
  height: 100%;
3907 3907
  overflow: auto;
3908
  overflow-x: visible;
3908 3909
}
3909 3910
3910 3911
.project-phase-item {
@ -3986,6 +3987,7 @@ body.date-picked .list-item-pickered {
3986 3987
  line-height: .22rem;
3987 3988
  color: #1A202C;
3988 3989
  padding: .2rem 0 .06rem;
3990
  position: static;
3989 3991
}
3990 3992
3991 3993
.project-phase-item .item-state .num {
@ -4450,4 +4452,15 @@ body.date-picked .list-item-pickered {
4450 4452
.ipu-carousel-animate {
4451 4453
  -webkit-transition: all 200ms ease-out 0ms;
4452 4454
  transition: all 200ms ease-out 0ms;
4455
}
4456
4457
.project-task-item.drag-slt {
4458
  box-shadow: .02rem .02rem .05rem .03rem rgba(0, 0, 0, .2);
4459
  position: absolute;
4460
  width: 2.95rem;
4461
  z-index: 1111;
4462
}
4463
4464
.project-task-item-placehoder {
4465
  visibility: hidden;
4453 4466
}

+ 9 - 7
2020/x-3/biz/js/common/PanCarousel.js

@ -255,7 +255,6 @@ define(["jquery"], function ($) {
255 255
     */
256 256
    refresh: function () {
257 257
      if (this.wrapperWidth != this.wrapper.outerWidth(true)) {
258
        console.log('refresh');
259 258
        this._sizeCount();
260 259
        this._show(this.realIndex, false); //新的位置
261 260
      }
@ -277,10 +276,8 @@ define(["jquery"], function ($) {
277 276
        move = this.moveLen - moveLen;
278 277
        if (move < 0) {
279 278
          move = move / 2;
280
          //move = 0;
281 279
        } else if (move > this.endSize) {
282 280
          move = this.endSize + (move - this.endSize) / 2;
283
          //move = this.endSzie;
284 281
        }
285 282
      }
286 283
@ -315,7 +312,7 @@ define(["jquery"], function ($) {
315 312
      }
316 313
317 314
      var oldIndex = this.currentIndex;
318
      var newIndex = index % this.itemSize;
315
      var newIndex = this.itemSize && index % this.itemSize || 0;
319 316
      var cloneItem = index >= this.itemSize;
320 317
321 318
      if (animate && this.option.callBack) {
@ -331,7 +328,12 @@ define(["jquery"], function ($) {
331 328
      this.currentIndex = newIndex;
332 329
      this.moveLen = this.carouselItemWides[index];
333 330
334
      $(this.wrapper).css("transform", "translate3d(-" + this.moveLen + "px, 0, 0)");
331
      var _this = this;
332
      $(this.wrapper).css("transform", "translate3d(-" + this.moveLen + "px, 0, 0)").transitionEnd(function () {
333
        if (_this.option.trasnCallBack) {
334
          _this.option.trasnCallBack.call(_this, _this.currentIndex);
335
        }
336
      });
335 337
336 338
      if (this.indicator) {
337 339
        this.indicatorIndexs.eq(this.currentIndex).addClass("ipu-current").siblings().removeClass("ipu-current");
@ -343,8 +345,8 @@ define(["jquery"], function ($) {
343 345
344 346
      this._play();//处理自动播放
345 347
    },
346
    update: function () {  // 组件更新,因为内容更新了
347
      var index = this.currentIndex;
348
    update: function (index) {  // 组件更新,因为内容更新了
349
      index = index || this.currentIndex || 0;
348 350
      $(".ipu-carousel-indicator", this.el).remove();
349 351
      this._init();
350 352
      this.show(index);

+ 175 - 27
2020/x-3/biz/js/page/project-phase-task.js

@ -1,41 +1,185 @@
1
require(["ipuUI", "jquery", "tool", "PanCarousel"], function (ipuUI, $, tool, PanCarousel) {
1
require(["ipuUI", "jquery", "tool", "PanCarousel", 'Hammer'], function (ipuUI, $, tool, PanCarousel, Hammer) {
2 2
  $(function () {
3 3
4
    function confirm(option) {
5
      setTimeout(function () {
6
        option = $.extend({}, defaultConfirmOption, option);
4
    // 上下拖动,还未支持滚动(任务数太多时,往下移动,没有滚动处理)
5
    (function () {    // 业务较复杂,使匿名方法处理
6
      var holdTime = 360;      // 按住后,1s内没有移动,假设为需要拖动
7
      var touchState = 0;        // 0待进入状态,1待确认(需要按住多少秒),2已确认
8
      var listenEl = $(".ipu-hammer-carousel")[0];
9
      var dragSlt = ".project-task-item";
10
      var dragItem = null;      // 选中元素
11
      var touchId;            // 触点id
12
      var touchFirst;         //  触点坐标
13
      var placeholderHtml = "<div class='project-task-item project-task-item-placehoder'></div>";
14
      var placeHolderEl;        // 占位元素
15
      var dragPosition;             // 元素初始位置
16
      var itemWidth = $(".project-task-list:first").width();
17
      var disabledMove = 0;   // 暂时不处理移动,计数器
18
      var outid;
19
      var dragLiIndex;        // 拖拽的对象的初始泳道
7 20
8
        var modalEl = $(confirmTpl).appendTo("body")[0];
21
      listenEl.addEventListener("touchstart", touchStartLister, {passive: true});  // 添加触屏监听
9 22
10
        $(".confirm-modal-title", modalEl).text(option.title);
11
        $(option.texts).each(function (index, text) {
12
          $(".confirm-modal-button:eq(" + index + ")", modalEl).text(text);
13
        });
23
      // 监听触点开始
24
      function touchStartLister(e) {
25
        // 不在限制范围内的平移
26
        var isDragSlt = $(e.target).is(dragSlt);    // 获取任务item元素
27
        dragItem = $(e.target).parents(dragSlt);
28
29
        if ((!isDragSlt && dragItem.size() == 0) || e.touches.length != 1) {  // 触点数量不为1,或点中的非任务元素el
30
          if (touchState != 2) {  // 不是确认状态,重置为初始化状态,状态确认后忽略
31
            clearTime();
32
          }
33
        } else {
34
          // console.log('start');
35
          if (isDragSlt) {  // 当前即为dragItem
36
            dragItem = $(e.target);
37
          }
14 38
15
        ipuUI.openModal(modalEl);
39
          touchState = 1;
40
          var touch = e.touches[0];
41
          touchId = touch.identifier;       //
42
          touchFirst = {x: touch.pageX, y: touch.pageY};    // 记录当前位置
43
          addTouchLister();
44
          disabledMove = 0;
16 45
17
        function removeActionDialog() {       // 关闭弹窗并移除遮掩绑定事件
18
          ipuUI.closeModal(modalEl);
19
          $(".ipu-modal-overlay").off("click", removeActionDialog);
46
          outid = setTimeout(function () {            // 先开始监听move
47
            if (touchState == 1) {  // 1秒后,还没有移动
48
              touchState = 2;        // 满足条件可拖动
49
              dragPosition = dragItem.position();  // 相当页面的偏移
50
              placeholderEl = $(placeholderHtml).insertBefore(dragItem);
51
              placeholderEl.height(dragItem.height());
52
              dragLiIndex = carousel.currentIndex;
53
              console.log(dragLiIndex);
54
              dragItem.addClass("drag-slt").css(dragPosition).appendTo(listenEl);
55
              outid = 0;
56
            }
57
          }, holdTime);
20 58
        }
59
      }
21 60
22
        $(".ipu-modal-overlay").on("click", function () {  // 点击透明区域
23
          option.cancelClick && option.cancelClick();
24
          removeActionDialog();
25
        });     // 点击遮掩,移除弹框
61
      // 移除按住时间监听
62
      function clearTime() {
63
        if (outid) {
64
          window.clearTimeout(outid);
65
          outid = 0;
66
        }
67
        removeTouchLister();
68
        touchState = 0;
69
      }
26 70
27
        $(".confirm-modal-button-ok", modalEl).click(function () {  // 点击确认按钮
28
          option.okClick && option.okClick();
29
          removeActionDialog();
30
        });
31
        $(".confirm-modal-button-cancel", modalEl).click(function () { // 点击取消按钮
32
          option.cancelClick && option.cancelClick();
33
          removeActionDialog();
71
      // 监听触点移动
72
      function touchMoveLister(e) {
73
        if (e.changedTouches[0].identifier == touchId) {    // 只监听当前触点
74
          if (touchState != 2) {
75
            clearTime();
76
          } else {    // 监听在window对象上面,阻止默认行为太晚了....
77
            e.stopImmediatePropagation();
78
            // e.preventDefault(); // 在滚动时阻止行为,浏览器报错,先不处理
79
80
            var touch = e.touches[0];
81
            var moveX = touch.pageX - touchFirst.x;
82
            var moveY = touch.pageY - touchFirst.y;
83
84
            var newPosition = {left: dragPosition.left + moveX, top: dragPosition.top + moveY};
85
            dragItem.css(newPosition);
86
            var index = carousel.currentIndex;
87
            // console.log('move', moveX);
88
89
            if (disabledMove) {  // 为0的时候,才可以处理,否则暂停处理,防止抖动
90
91
            } else {
92
              if (Math.abs(moveX) >= itemWidth * 0.3) {  // 纵向移动1/3,则切换泳道
93
                if ((index == 0 && moveX < 0) || (index == carousel.itemSize - 1 && moveX > 0)) {
94
                  // 边界条件,没有上一项或下一项,不处理
95
                } else {
96
                  disabledMove++;
97
                  index = index + (moveX > 0 ? 1 : -1);           // 判断是向左还是往右
98
                  carousel.show(index);
99
                  setTimeout(function () {
100
                    disabledMove--;
101
                    // placeholderEl = placeholderEl.appendTo($(".ipu-carousel-wrapper li:eq(" + index + ") .project-task-list"));  // 默认拖动后放在对应泳道的最后位置
102
                    // adjustPhd(newPosition);
103
                  }, 640);
104
                }
105
              } else {                        // 还要处理往下的滚动
106
                // adjustPhd(newPosition);
107
              }
108
            }
109
          }
110
        }
111
      }
112
113
      // 调整上下位置
114
      function adjustPhd(newPosition) {  // 调整占位位置
115
        var offsetTop = null;
116
        var toIndex = 0;
117
        var index = carousel.currentIndex;
118
119
        $(".ipu-carousel-wrapper li:eq(" + index + ") .project-task-item").each(function (index, el) {
120
          // 在一个子项的上半部或下半部,位置好像不大准确
121
          var tempOffsetTop = newPosition.top - $(el).position().top;
122
          if (tempOffsetTop > 0 && (index == 0 || tempOffsetTop < offsetTop)) {
123
            offsetTop = tempOffsetTop;
124
            toIndex = index;
125
          }
34 126
        });
35
      }, 310);  // 如果是action方法的回调,会导致遮掩不显示,延迟避免此问题
36 127
37
    }
128
        var phdIndex = placeholderEl.index();     // 取占位的index
129
        var toEl = $(".ipu-carousel-wrapper li:eq(" + index + ") .project-task-item:eq(" + toIndex + ")");
38 130
131
        //
132
        if (phdIndex != toIndex) {
133
          if (phdIndex > toIndex) {
134
            placeholderEl.insertBefore(toEl);
135
          } else {
136
            placeholderEl.insertAfter(toEl);
137
          }
138
139
          disabledMove++;
140
          setTimeout(function () {
141
            disabledMove--;
142
            // 处理 placeHolder
143
          }, 600); // 防止抖动,或者移动多少以后再更新
144
        }
145
      }
146
147
      // 触点结束监听
148
      function touchEndLister(e) {
149
        if (e.changedTouches[0].identifier == touchId) {
150
          if (touchState == 2) {
151
            var currentIndex = carousel.currentIndex;
152
            console.log('end', currentIndex);
153
            if (dragLiIndex == currentIndex) {
154
              dragItem.insertBefore(placeholderEl);
155
            } else {
156
              dragItem.appendTo($(".ipu-carousel-wrapper li:eq(" + currentIndex + ") .project-task-list"));  // 默认放最后面
157
            }
158
            dragItem.removeClass("drag-slt").css({"top": "auto", left: "auto"});
159
            placeholderEl.remove();    // 回调方法,更新泳道切换
160
            removeTouchLister();
161
            touchState = 0;
162
          } else {
163
            clearTime();
164
          }
165
        }
166
      }
167
168
      // 开始监听
169
      function addTouchLister() {
170
        listenEl.addEventListener("touchmove", touchMoveLister, {passive: false});   // 会调用阻止默认行为
171
        listenEl.addEventListener("touchcancel", touchEndLister);
172
        listenEl.addEventListener("touchend", touchEndLister);
173
      }
174
175
      // 结束监听
176
      function removeTouchLister() {   // 结束触点事件监听
177
        listenEl.removeEventListener("touchmove", touchMoveLister, {passive: false});   // 会调用阻止默认行为
178
        listenEl.removeEventListener("touchcancel", touchEndLister);
179
        listenEl.removeEventListener("touchend", touchEndLister);
180
      }
181
182
    })();
39 183
40 184
    function initIndicator() {
41 185
      $(".ipu-carousel-indicator").empty();
@ -54,9 +198,13 @@ require(["ipuUI", "jquery", "tool", "PanCarousel"], function (ipuUI, $, tool, Pa
54 198
      indicator: false, // 是否生成指示器(右下角的小圆点)
55 199
      loop: false,       // 是否循环
56 200
      callBack: function (index, oldIndex) {
201
        // console.log("callBack", index, Date.now());
57 202
        if (index != oldIndex) {
58 203
          sltIndicator(index);
59 204
        }
205
      },
206
      trasnCallBack: function (index) {
207
        // console.log("trasnCallBack", index, Date.now());
60 208
      }
61 209
    });
62 210
    sltIndicator(carousel.currentIndex);
@ -138,6 +286,6 @@ require(["ipuUI", "jquery", "tool", "PanCarousel"], function (ipuUI, $, tool, Pa
138 286
      }
139 287
    });
140 288
141
    //
289
142 290
  });
143 291
});

+ 0 - 438
2020/x-3/biz/lib/dragsort/jquery.dragsort-0.5.2.js

@ -1,438 +0,0 @@
1
// jQuery List DragSort v0.5.2
2
// Website: http://dragsort.codeplex.com/
3
// License: http://dragsort.codeplex.com/license
4
// 源码上修改,增加支持手机事件,增加amd支持
5
define(["jquery"], function ($) {
6
7
  $.fn.dragsort = function (options) {
8
    if (options == "destroy") {
9
      $(this.selector).trigger("dragsort-uninit");
10
      return;
11
    }
12
13
    var opts = $.extend({}, $.fn.dragsort.defaults, options);
14
    var lists = [];
15
    var list = null, lastPos = null;
16
    var events = {
17
      press: "touchstart",
18
      move: "touchmove",
19
      up: "touchend"
20
    };
21
22
    this.each(function (i, cont) {
23
24
      //if list container is table, the browser automatically wraps rows in tbody if not specified so change list container to tbody so that children returns rows as user expected
25
      if ($(cont).is("table") && $(cont).children().size() == 1 && $(cont).children().is("tbody"))
26
        cont = $(cont).children().get(0);
27
28
      var newList = {
29
				el: $(cont),
30
        draggedItem: null,
31
        placeHolderItem: null,
32
        pos: null,
33
        offset: null,
34
        offsetLimit: null,
35
        scroll: null,
36
        container: cont,
37
38
        init: function () {
39
          //set options to default values if not set
40
          opts.tagName = $(this.container).children().size() == 0 ? "li" : $(this.container).children().get(0).tagName.toLowerCase();
41
          if (opts.itemSelector == "")
42
            opts.itemSelector = opts.tagName;
43
          if (opts.dragSelector == "")
44
            opts.dragSelector = opts.tagName;
45
          if (opts.placeHolderTemplate == "")
46
            opts.placeHolderTemplate = "<" + opts.tagName + ">&nbsp;</" + opts.tagName + ">";
47
48
          //listidx allows reference back to correct list variable instance
49
          $(this.container).attr("data-listidx", i).on("touchstart", this.grabItem).bind("dragsort-uninit", this.uninit);
50
          this.styleDragHandlers(true);
51
        },
52
53
        uninit: function () {
54
          var list = lists[$(this).attr("data-listidx")];
55
          $(list.container).unbind("touchstart", list.grabItem).unbind("dragsort-uninit");
56
          list.styleDragHandlers(false);
57
        },
58
59
        getItems: function () {
60
          return $(this.container).children(opts.itemSelector);
61
        },
62
63
        styleDragHandlers: function (cursor) {
64
          this.getItems().map(function () {
65
            return $(this).is(opts.dragSelector) ? this : $(this).find(opts.dragSelector).get();
66
          }).css("cursor", cursor ? "pointer" : "");
67
        },
68
69
        grabItem: function (e) {
70
          var list = lists[$(this).attr("data-listidx")];
71
          var item = $(e.target).closest("[data-listidx] > " + opts.tagName).get(0);
72
          var insideMoveableItem = list.getItems().filter(function () {
73
              return this == item;
74
            }).size() > 0;
75
76
          //if not left click or if clicked on excluded element (e.g. text box) or not a moveable list item return
77
          // e.which = 0 其它,e.which:1 鼠标左键,2鼠标中键,3鼠标右键
78
          if (e.which > 1 || $(e.target).is(opts.dragSelectorExclude) || $(e.target).closest(opts.dragSelectorExclude).size() > 0 || !insideMoveableItem)
79
            return;
80
81
          //prevents selection, stops issue on Fx where dragging hyperlink doesn't work and on IE where it triggers mousemove even though mouse hasn't moved,
82
          //does also stop being able to click text boxes hence dragging on text boxes by default is disabled in dragSelectorExclude
83
          e.preventDefault();
84
85
          //change cursor to move while dragging
86
          var dragHandle = e.target;
87
          while (!$(dragHandle).is(opts.dragSelector)) {
88
            if (dragHandle == this) return;
89
            dragHandle = dragHandle.parentNode;
90
          }
91
          $(dragHandle).attr("data-cursor", $(dragHandle).css("cursor"));
92
          $(dragHandle).css("cursor", "move");
93
94
          //on mousedown wait for movement of mouse before triggering dragsort script (dragStart) to allow clicking of hyperlinks to work
95
          var listElem = this;
96
          var trigger = function () {
97
            list.dragStart.call(listElem, e);
98
            $(list.container).unbind("touchmove", trigger);
99
          };
100
          $(list.container).on("touchmove", trigger).on("touchend", function () {
101
            $(list.container).unbind("touchmove", trigger);
102
            $(dragHandle).css("cursor", $(dragHandle).attr("data-cursor"));
103
          });
104
        },
105
106
        dragStart: function (e) {
107
          var touches = e.originalEvent.touches;
108
109
          var lastTouch = touches[touches.length - 1]
110
          e.pageX = lastTouch.pageX;
111
          e.pageY = lastTouch.pageY;
112
113
          if (list != null && list.draggedItem != null)
114
            list.dropItem();
115
116
          list = lists[$(this).attr("data-listidx")];
117
          list.draggedItem = $(e.target).closest("[data-listidx] > " + opts.tagName)
118
119
          //record current position so on dragend we know if the dragged item changed position or not, not using getItems to allow dragsort to restore dragged item to original location in relation to fixed items
120
          list.draggedItem.attr("data-origpos", $(this).attr("data-listidx") + "-" + $(list.container).children().index(list.draggedItem));
121
122
          //calculate mouse offset relative to draggedItem
123
          var mt = parseInt(list.draggedItem.css("marginTop"));
124
          var ml = parseInt(list.draggedItem.css("marginLeft"));
125
          list.offset = list.draggedItem.offset();
126
          list.offset.top = e.pageY - list.offset.top + (isNaN(mt) ? 0 : mt) - 1;
127
          list.offset.left = e.pageX - list.offset.left + (isNaN(ml) ? 0 : ml) - 1;
128
129
          //calculate box the dragged item can't be dragged outside of
130
          if (!opts.dragBetween) {
131
            var containerHeight = $(list.container).outerHeight() == 0 ? Math.max(1, Math.round(0.5 + list.getItems().size() * list.draggedItem.outerWidth() / $(list.container).outerWidth())) * list.draggedItem.outerHeight() : $(list.container).outerHeight();
132
            list.offsetLimit = $(list.container).offset();
133
            list.offsetLimit.right = list.offsetLimit.left + $(list.container).outerWidth() - list.draggedItem.outerWidth();
134
            list.offsetLimit.bottom = list.offsetLimit.top + containerHeight - list.draggedItem.outerHeight();
135
          }
136
137
          //create placeholder item
138
          var h = list.draggedItem.height();
139
          var w = list.draggedItem.width();
140
          if (opts.tagName == "tr") {
141
            list.draggedItem.children().each(function () {
142
              $(this).width($(this).width());
143
            });
144
            list.placeHolderItem = list.draggedItem.clone().attr("data-placeholder", true);
145
            list.draggedItem.after(list.placeHolderItem);
146
            list.placeHolderItem.children().each(function () {
147
              $(this).css({borderWidth: 0, width: $(this).width() + 1, height: $(this).height() + 1}).html("&nbsp;");
148
            });
149
          } else {
150
            list.draggedItem.after(opts.placeHolderTemplate);
151
            // list.placeHolderItem = list.draggedItem.next().css({ height: h, width: w }).attr("data-placeholder", true);
152
            list.placeHolderItem = list.draggedItem.next().attr("data-placeholder", true);
153
          }
154
155
          if (opts.tagName == "td") {
156
            var listTable = list.draggedItem.closest("table").get(0);
157
            $("<table id='" + listTable.id + "' style='border-width: 0px;' class='dragSortItem " + listTable.className + "'><tr></tr></table>").appendTo("body").children().append(list.draggedItem);
158
          }
159
160
          //style draggedItem while dragging
161
          var orig = list.draggedItem.attr("style");
162
          list.draggedItem.attr("data-origstyle", orig ? orig : "");
163
          list.draggedItem.css({position: "absolute", opacity: 0.8, "z-index": 999, height: h, width: w});
164
165
          //auto-scroll setup
166
          list.scroll = {
167
            moveX: 0,
168
            moveY: 0,
169
            maxX: $(document).width() - $(window).width(),
170
            maxY: $(document).height() - $(window).height()
171
          };
172
          list.scroll.scrollY = window.setInterval(function () {
173
            if (opts.scrollContainer != window) {
174
              $(opts.scrollContainer).scrollTop($(opts.scrollContainer).scrollTop() + list.scroll.moveY);
175
              return;
176
            }
177
            var t = $(opts.scrollContainer).scrollTop();
178
            if (list.scroll.moveY > 0 && t < list.scroll.maxY || list.scroll.moveY < 0 && t > 0) {
179
              $(opts.scrollContainer).scrollTop(t + list.scroll.moveY);
180
              list.draggedItem.css("top", list.draggedItem.offset().top + list.scroll.moveY + 1);
181
            }
182
          }, 10);
183
          list.scroll.scrollX = window.setInterval(function () {
184
            if (opts.scrollContainer != window) {
185
              $(opts.scrollContainer).scrollLeft($(opts.scrollContainer).scrollLeft() + list.scroll.moveX);
186
              return;
187
            }
188
            var l = $(opts.scrollContainer).scrollLeft();
189
            if (list.scroll.moveX > 0 && l < list.scroll.maxX || list.scroll.moveX < 0 && l > 0) {
190
              $(opts.scrollContainer).scrollLeft(l + list.scroll.moveX);
191
              list.draggedItem.css("left", list.draggedItem.offset().left + list.scroll.moveX + 1);
192
            }
193
          }, 10);
194
195
          //misc
196
          $(lists).each(function (i, l) {
197
            l.createDropTargets();
198
            l.buildPositionTable();
199
          });
200
          list.setPos(e.pageX, e.pageY);
201
          $(document).bind("touchmove", list.swapItems);
202
          $(document).bind("touchend", list.dropItem);
203
          if (opts.scrollContainer != window)
204
            $(window).bind("wheel", list.wheel);
205
        },
206
207
        //set position of draggedItem
208
        setPos: function (x, y) {
209
          //remove mouse offset so mouse cursor remains in same place on draggedItem instead of top left corner
210
          var top = y - this.offset.top;
211
          var left = x - this.offset.left;
212
213
          //limit top, left to within box draggedItem can't be dragged outside of
214
          if (!opts.dragBetween) {
215
            top = Math.min(this.offsetLimit.bottom, Math.max(top, this.offsetLimit.top));
216
            left = Math.min(this.offsetLimit.right, Math.max(left, this.offsetLimit.left));
217
          }
218
219
          //adjust top & left calculations to parent offset
220
          var parent = this.draggedItem.offsetParent().not("body").offset(); //offsetParent returns body even when it's static, if not static offset is only factoring margin
221
          if (parent != null) {
222
            top -= parent.top;
223
            left -= parent.left;
224
          }
225
226
          //set x or y auto-scroll amount
227
          if (opts.scrollContainer == window) {
228
            y -= $(window).scrollTop();
229
            x -= $(window).scrollLeft();
230
            y = Math.max(0, y - $(window).height() + 5) + Math.min(0, y - 5);
231
            x = Math.max(0, x - $(window).width() + 5) + Math.min(0, x - 5);
232
          } else {
233
            var cont = $(opts.scrollContainer);
234
            var offset = cont.offset();
235
            y = Math.max(0, y - cont.height() - offset.top) + Math.min(0, y - offset.top);
236
            x = Math.max(0, x - cont.width() - offset.left) + Math.min(0, x - offset.left);
237
          }
238
239
          list.scroll.moveX = x == 0 ? 0 : x * opts.scrollSpeed / Math.abs(x);
240
          list.scroll.moveY = y == 0 ? 0 : y * opts.scrollSpeed / Math.abs(y);
241
242
          //move draggedItem to new mouse cursor location
243
          this.draggedItem.css({top: top, left: left});
244
        },
245
246
        //if scroll container is a div allow mouse wheel to scroll div instead of window when mouse is hovering over
247
        wheel: function (e) {
248
          if (list && opts.scrollContainer != window) {
249
            var cont = $(opts.scrollContainer);
250
            var offset = cont.offset();
251
            e = e.originalEvent;
252
            if (e.clientX > offset.left && e.clientX < offset.left + cont.width() && e.clientY > offset.top && e.clientY < offset.top + cont.height()) {
253
              var deltaY = (e.deltaMode == 0 ? 1 : 10) * e.deltaY;
254
              cont.scrollTop(cont.scrollTop() + deltaY);
255
              e.preventDefault();
256
            }
257
          }
258
        },
259
260
        //build a table recording all the positions of the moveable list items
261
        buildPositionTable: function () {
262
          var pos = [];
263
          this.getItems().not([list.draggedItem[0], list.placeHolderItem[0]]).each(function (i) {
264
            var loc = $(this).offset();
265
            loc.right = loc.left + $(this).outerWidth();
266
            loc.bottom = loc.top + $(this).outerHeight();
267
            loc.elm = this;
268
            pos[i] = loc;
269
          });
270
          this.pos = pos;
271
        },
272
273
        dropItem: function () {
274
          if (list.draggedItem == null)
275
            return;
276
277
278
					list.el.trigger("dragend");	// 增加拖动时触发事件
279
280
          //list.draggedItem.attr("style", "") doesn't work on IE8 and jQuery 1.5 or lower
281
          //list.draggedItem.removeAttr("style") doesn't work on chrome and jQuery 1.6 (works jQuery 1.5 or lower)
282
          var orig = list.draggedItem.attr("data-origstyle");
283
          list.draggedItem.attr("style", orig);
284
          if (orig == "")
285
            list.draggedItem.removeAttr("style");
286
          list.draggedItem.removeAttr("data-origstyle");
287
288
          list.styleDragHandlers(true);
289
290
          var oldIndex = parseInt(list.draggedItem.attr("data-origpos").split('-')[1]);
291
          var newIndex = list.placeHolderItem.index();
292
          if (newIndex > oldIndex) {
293
            newIndex = newIndex - 1; // 因为新的位置大于老的位置,则要减1,因为增加多了个临时点位的点
294
          }
295
296
          list.placeHolderItem.before(list.draggedItem);
297
          list.placeHolderItem.remove();
298
299
          $("[data-droptarget], .dragSortItem").remove();
300
301
          window.clearInterval(list.scroll.scrollY);
302
          window.clearInterval(list.scroll.scrollX);
303
304
          //if position changed call dragEnd
305
          if (list.draggedItem.attr("data-origpos") != $(lists).index(list) + "-" + $(list.container).children().index(list.draggedItem))
306
            if (opts.dragEnd.apply(list.draggedItem, [newIndex, oldIndex]) == false) { //if dragEnd returns false revert order
307
              var pos = list.draggedItem.attr("data-origpos").split('-');
308
              var nextItem = $(lists[pos[0]].container).children().not(list.draggedItem).eq(pos[1]);
309
              if (nextItem.size() > 0)
310
                nextItem.before(list.draggedItem);
311
              else if (pos[1] == 0) //was the only item in list
312
                $(lists[pos[0]].container).prepend(list.draggedItem);
313
              else //was the last item in list
314
                $(lists[pos[0]].container).append(list.draggedItem);
315
            }
316
          list.draggedItem.removeAttr("data-origpos");
317
318
          list.draggedItem = null;
319
          $(document).unbind("touchmove", list.swapItems);
320
          $(document).unbind("touchend", list.dropItem);
321
          if (opts.scrollContainer != window)
322
            $(window).unbind("wheel", list.wheel);
323
          return false;
324
        },
325
326
        //swap the draggedItem (represented visually by placeholder) with the list item the it has been dragged on top of
327
        swapItems: function (e) {
328
          if (list.draggedItem == null)
329
            return false;
330
331
          var touches = e.originalEvent.touches;
332
333
          var lastTouch = touches[touches.length - 1]
334
          e.pageX = lastTouch.pageX;
335
          e.pageY = lastTouch.pageY;
336
337
          //move draggedItem to mouse location
338
          list.setPos(e.pageX, e.pageY);
339
340
					list.el.trigger("dragmove", [list.draggedItem, e.pageX, e.pageY]);	// 增加拖动时触发事件
341
342
          //retrieve list and item position mouse cursor is over
343
          var ei = list.findPos(e.pageX, e.pageY);
344
          var nlist = list;
345
          for (var i = 0; ei == -1 && opts.dragBetween && i < lists.length; i++) {
346
            ei = lists[i].findPos(e.pageX, e.pageY);
347
            nlist = lists[i];
348
          }
349
350
          //if not over another moveable list item return
351
          if (ei == -1)
352
            return false;
353
354
          //save fixed items locations
355
          var children = function () {
356
            return $(nlist.container).children().not(nlist.draggedItem);
357
          };
358
          var fixed = children().not(opts.itemSelector).each(function (i) {
359
            this.idx = children().index(this);
360
          });
361
362
          //if moving draggedItem up or left place placeHolder before list item the dragged item is hovering over otherwise place it after
363
          if (lastPos == null || lastPos.top > list.draggedItem.offset().top || lastPos.left > list.draggedItem.offset().left)
364
            $(nlist.pos[ei].elm).before(list.placeHolderItem);
365
          else
366
            $(nlist.pos[ei].elm).after(list.placeHolderItem);
367
368
          //restore fixed items location
369
          fixed.each(function () {
370
            var elm = children().eq(this.idx).get(0);
371
            if (this != elm && children().index(this) < this.idx)
372
              $(this).insertAfter(elm);
373
            else if (this != elm)
374
              $(this).insertBefore(elm);
375
          });
376
377
          //misc
378
          $(lists).each(function (i, l) {
379
            l.createDropTargets();
380
            l.buildPositionTable();
381
          });
382
          lastPos = list.draggedItem.offset();
383
          return false;
384
        },
385
386
        //returns the index of the list item the mouse is over
387
        findPos: function (x, y) {
388
          for (var i = 0; i < this.pos.length; i++) {
389
            if (this.pos[i].left < x && this.pos[i].right > x && this.pos[i].top < y && this.pos[i].bottom > y)
390
              return i;
391
          }
392
          return -1;
393
        },
394
395
        //create drop targets which are placeholders at the end of other lists to allow dragging straight to the last position
396
        createDropTargets: function () {
397
          if (!opts.dragBetween)
398
            return;
399
400
          $(lists).each(function () {
401
            var ph = $(this.container).find("[data-placeholder]");
402
            var dt = $(this.container).find("[data-droptarget]");
403
            if (ph.size() > 0 && dt.size() > 0)
404
              dt.remove();
405
            else if (ph.size() == 0 && dt.size() == 0) {
406
              if (opts.tagName == "td")
407
                $(opts.placeHolderTemplate).attr("data-droptarget", true).appendTo(this.container);
408
              else
409
              //list.placeHolderItem.clone().removeAttr("data-placeholder") crashes in IE7 and jquery 1.5.1 (doesn't in jquery 1.4.2 or IE8)
410
                $(this.container).append(list.placeHolderItem.removeAttr("data-placeholder").clone().attr("data-droptarget", true));
411
412
              list.placeHolderItem.attr("data-placeholder", true);
413
            }
414
          });
415
        }
416
      };
417
418
      newList.init();
419
      lists.push(newList);
420
    });
421
422
    return this;
423
  };
424
425
  $.fn.dragsort.defaults = {
426
    itemSelector: "",
427
    dragSelector: "",
428
    dragSelectorExclude: "input, textarea",
429
    dragEnd: function () {
430
    },
431
    dragBetween: false,
432
    placeHolderTemplate: "",
433
    scrollContainer: window,
434
    scrollSpeed: 5
435
  };
436
437
438
});