HTML5技术

html5 Sortable.js 拖拽排序源码分析 - qq281113270(11)

字号+ 作者:H5之家 来源:H5之家 2016-11-04 15:00 我要评论( )

1 /* *! 2 * Sortable 3 * @author RubaXa trash@rubaxa.org 4 * @license MIT (function (factory) { ; ( define.amd) { define(factory); 14 } ( ) { module.exports = factory(); 17 } ( ) { } 21 else { window

1 /**! 2 * Sortable 3 * @author RubaXa <trash@rubaxa.org> 4 * @license MIT (function (factory) { ; (&& define.amd) { define(factory); 14 } (&& ) { module.exports = factory(); 17 } () { } 21 else { window[] = factory(); } 27 })(function () { ; (|| ) { function () { Error(); }; 34 } 35 var i=0; parentEl, cloneEl, rootEl, nextEl, scrollEl,scrollParentEl, lastEl, lastCSS, 48 lastParentCSS, newIndex, activeGroup, tapEvt 触摸对象包括x与y轴与拖拽当前节点 58 tapEvt = { 59 target: dragEl, 60 clientX: touch.clientX, 61 clientY: touch.clientY 62 }; tapEvt, 65 touchEvt, 66 67 moved, RSPACE = /\s+/g, expando = + (win = window, document = win.document, 76 parseInt = win.parseInt; supportDraggable = !!(document.createElement()), supportCssPointerEvents = (function (el) { ); ; ; 86 })(), abs = Math.abs, 91 slice = [].slice, 92 93 touchDragOverListeners = [], //新建一个数组 鼠标触摸拖拽数组 _autoScroll = function(callback,ms){ 97 var args, 98 _this; 99 if (args === void 0) { 100 args = arguments; 101 _this = this; 102 103 setTimeout(function () { 104 if (args.length === 1) { 105 callback.call(_this, args[0]); 106 } else { 107 callback.apply(_this, args); 108 } 109 110 args = void 0; 111 }, ms); 112 } 113 其实就是_autoScroll=function(参数){ 114 放到 _throttle 的回调函数中 function (/参数/) 115 } ********************************************************************************************** 122 *函数名 :_autoScroll 123 *函数功能描述 : 拖拽智能滚动 124 *函数参数 : 125 evt: 126 类型:boj, 事件对象 127 options:类型:obj, 参数类 128 rootEl:类型:obj dom节点,拖拽的目标节点 129 *函数返回值 : viod 130 *作者 : 131 *函数创建日期 : 132 *函数修改日期 : 133 *修改人 : 134 *修改原因 : 135 *版本 : 136 *历史版本 : _autoScroll = _throttle( function (evt, options, rootEl) { 141 //每次拖拽只会调用一次该函数 evt 是事件对象 event 145 //options.scroll如果为真 并且rootEl 为真的时候 (rootEl && options.scroll) { 148 var el, 149 rect, speed = options.scrollSpeed, x = evt.clientX, y = evt.clientY, winWidth = window.innerWidth, winHeight = window.innerHeight, 157 158 vx, 159 vy 160 ; (scrollParentEl !== rootEl) { scrollParentEl = rootEl; (scrollEl === true) { 168 scrollEl = rootEl; 169 do { ((scrollEl.offsetWidth < scrollEl.scrollWidth) || 172 (scrollEl.offsetHeight < scrollEl.scrollHeight) 173 ) { 174 break; 175 } } while (scrollEl = scrollEl.parentNode); 178 } 179 } (scrollEl) { 183 el = scrollEl; 184 rect = scrollEl.getBoundingClientRect(); var box=document.getElementById('box'); // 获取元素 187 alert(box.getBoundingClientRect().top); // 元素上边距离页面上边的距离 188 alert(box.getBoundingClientRect().right); // 元素右边距离页面左边的距离 189 alert(box.getBoundingClientRect().bottom); // 元素下边距离页面上边的距离 190 alert(box.getBoundingClientRect().left); // 元素左边距离页面左边的距离 191 y:y = evt.clientY, //获取鼠标在可视窗口的y值 192 sens: sens = options.scrollSensitivity, //滚动灵敏度 默认是30 true-true=0 199 true-false=1 200 false-false=0 201 false-true=-1 vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens); if(rect.top+sens-y>=0){ 207 vy=-1; 208 } else if(rect.bottom+sens-y<=0){ 209 vy=1; 210 }else{ 211 vy=0; 212 } } (!(vx || vy)) { vx = (winWidth - x <= sens) - (x <= sens); 220 vy = (winHeight - y <= sens) - (y <= sens); (vx || vy) && (el = win); 224 } (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) { 228 autoScroll.el = el; 229 autoScroll.vx = vx; 230 autoScroll.vy = vy; clearInterval(autoScroll.pid); (el) { 235 autoScroll.pid = setInterval(function () { 236 if (el === win) { 237 win.scrollTo(win.pageXOffset + vx * speed, win.pageYOffset + vy * speed); 238 } else { vx && (el.scrollLeft += vx * speed); } 242 }, 243 24); 244 } 245 } 246 } }, 30), 249 /*********************************************************************************************** 250 *函数名 :_prepareGroup 251 *函数功能描述 : //options.group 属性变成对象 。如果group不是对象则变成对象,并且group对象的name就等于改group的值 并且添加多['pull', 'put'] 属性默认值是true 252 如果设置group{ 253 pull:true, 则可以拖拽到其他列表 否则反之 254 put:true, 则可以从其他列表中放数据到改列表,false则反之 255 } 256 pull: 'clone', 还有一个作用是克隆,就是当这个列表拖拽到其他列表的时候不会删除改列表的节点。 257 *函数参数 : 258 options: 259 类型:boj, options 拖拽参数 260 261 *函数返回值 : viod 262 *作者 : 263 *函数创建日期 : 264 *函数修改日期 : 265 *修改人 : 266 *修改原因 : 267 *版本 : 268 *历史版本 : _prepareGroup = function (options) { group = options.group; //把options.group 付值给group (!group || ) { group = options.group = {name: group}; 279 } [, ].forEach(function (key) { 282 if (!(key in group)) { // } 285 }); 286 //options.group 变成对象之后join方法将匹配不到任何东西 287 //如果他直接是数组的话这里就是把数组的值拆分成字符串连接起来 options.groups = + group.put.join(; 290 } 291 ; * 296 * @class Sortable 297 * @param {HTMLElement} el 298 * @param {Object} [options] el html dom节点 ********************************************************************************************** 304 *函数名 :Sortable 305 *函数功能描述 : 主类,里面包含很多方法 306 *函数参数 : dom节点rootEl 307 *函数返回值 : 308 *作者 : 309 *函数创建日期 : 310 *函数修改日期 : 311 *修改人 : 312 *修改原因 : 313 *版本 : 314 *历史版本 : function Sortable(el, options) { (!(el && el.nodeType && el.nodeType === 1)) { + {}.toString.call(el); 320 } .el = el; .options = options = _extend({}, options); //把options初始化的数据存到this中 好操作 Export instance el[expando] = this; Default options defaults = { sort: disabled: store: handle: scroll: scrollSensitivity: scrollSpeed: draggable: /[uo]l/i.test(el.nodeName) ? : ,ghostClass: , chosenClass: , ignore: , filter: animation: setData: function (dataTransfer, dragEl) { dataTransfer.setData(, dragEl.textContent); 351 }, dragoverBubble: dataIdAttr: , delay: forceFallback: fallbackClass: , fallbackOnBody: }; Set default options (var name in defaults) { 365 !(name in options) && (options[name] = defaults[name]); 366 } _prepareGroup(options); (var fn in this) { ) { [fn] = this[fn].bind(this); 377 } 378 } Setup drag mode .nativeDraggable = options.forceFallback ? false : supportDraggable; Bind events _on(el, , this._onTapStart); , this._onTapStart); (this.nativeDraggable) { _on(el, , _on(el, , } touchDragOverListeners.push(this._onDragOver); Restore sorting 403 //sort 排序函数 options.store && this.sort(options.store.get(this)); 406 } 407 /*********************************************************************************************** 408 *函数名 :Sortable.prototype 409 *函数功能描述 : 主类,的原型 410 *函数参数 : 411 *函数返回值 : 412 *作者 : 413 *函数创建日期 : 414 *函数修改日期 : 415 *修改人 : 416 *修改原因 : 417 *版本 : 418 *历史版本 : Sortable.prototype = { ********************************************************************************************** 424 *函数名 :_onTapStart 425 *函数功能描述 : 鼠标按下去函数,oldIndex统计目标节点与同级同胞的上节点总和 426 *函数参数 : viod 427 *函数返回值 : 无 428 *作者 : 429 *函数创建日期 : 430 *函数修改日期 : 431 *修改人 : 432 *修改原因 : 433 *版本 : 434 *历史版本 : _onTapStart: function (evt) { _this = this, options = type = evt.type, touch = evt.touches && evt.touches[target = (touch || evt).target, originalTarget = target, 446 filter = options.filter; // null (type === && evt.button !== 0 || options.disabled) { } 452 //draggable=/[uo]l/i.test(el.nodeName) ? 'li' : '>*', 453 // target=el true (!target) { 457 return; 458 } get the index of the dragged element within its parent oldIndex = _index(target, options.draggable); Check filter+ () { 467 if (filter.call(this, evt, target, this)) { //并且有返回值是true 的话 _dispatchEvent(_this, originalTarget, , target, el, oldIndex); evt.preventDefault(); ; } 474 } (filter) { 例子 479 if (!Array.prototype.some) 480 { 481 Array.prototype.some = function(fun ) 482 { 483 var len = this.length; 484 if (typeof fun != "function") 485 throw new TypeError(); 486 487 var thisp = arguments[1]; 488 for (var i = 0; i < len; i++) 489 { 490 if (i in this && 491 fun.call(thisp, this[i], i, this)) 492 return true; 493 } 494 495 return false; 496 }; 497 } 498 499 function isBigEnough(element, index, array) { 500 return (element >= 10); 501 } 502 503 var retval = [2, 5, 8, 1, 4].some(isBigEnough); 504 document.write("Returned value is : " + retval ); 505 506 var retval = [12, 5, 8, 1, 4].some(isBigEnough); 507 document.write("<br />Returned value is : " + retval ); filter = filter.split().some(function (criteria) { criteria = _closest(originalTarget, criteria.trim(), el); (criteria) { , target, el, oldIndex); ; 517 } 518 }); (filter) { 521 evt.preventDefault(); } 524 } handle 存在 527 //originalTarget (options.handle && !_closest(originalTarget, options.handle, el)) { 531 return; 532 } Prepare `dragstart` ._prepareDragStart(evt, touch, target); 538 }, ********************************************************************************************** 544 *函数名 :_onTapStart 545 *函数功能描述 : 开始准备拖 546 *函数参数 : evt: 547 类型:obj,事件对象 548 touch: 549 类型:obj,触摸事件对象,判断是否是触摸事件还是鼠标事件 550 target: 类型:dom-obj,目标节点 551 *函数返回值 : 无 552 *作者 : 553 *函数创建日期 : 554 *函数修改日期 : 555 *修改人 : 556 *修改原因 : 557 *版本 : 558 *历史版本 : _prepareDragStart: function (evt, touch, target) { 561 //evt pc 的事件对象 562 //touch 移动的的事件对象 _this = this, options = _this.options, ownerDocument = el.ownerDocument, dragStartFn; //声明开始拖拽函数 (target && !dragEl && (target.parentNode === el)) { rootEl = el; dragEl = target; parentEl = dragEl.parentNode; nextEl = dragEl.nextSibling; activeGroup = options.group; //Object {name: "words", pull: true, put: true} dragStartFn = function () { 581 // Delayed drag has been triggered 延迟拖动已被触发 582 // we can re-enable the events: touchmove/mousemove 我们可以重新启用touchmove / MouseMove事件: _this._disableDelayedDrag(); Make the element draggable 使元件拖动 dragEl.draggable = true; Chosen item dragEl 目标节点 类 _this.options.chosenClass='sortable-chosen' _toggleClass(dragEl, _this.options.chosenClass, true); _this._triggerDragStart(touch); 596 }; options.ignore.split().forEach(function (criteria) { 600 // criteria 遍历数组的当前target el.draggable //html5拖拽属性 605 function _disableDraggable(el) { 606 el.draggable = false; 607 } _find(dragEl, criteria.trim(), _disableDraggable); 612 }); , _this._onDrop); _on(ownerDocument, , _this._onDrop);_on(ownerDocument, , _this._onDrop);//在ownerDocument 文档上面当发生触摸划过抬起的时候,解绑_onDrop函数 (options.delay) { 这里里面的程序块添加了事件只有调用_disableDelayedDrag,添加了一个定时器执行一次dragStartFn函数,这个函数又马上解绑_disableDelayedDrag事件,关闭定时器,整个思路是只让程序发生一次,并且马上解绑事件,销毁该事件。这样思维有些特别 If the user moves the pointer or let go the click or touch 如果用户移动指针或单击“单击”或“触摸” 之前的延迟已达到 _on(ownerDocument, , _this._disableDelayedDrag); _on(ownerDocument, , _this._disableDelayedDrag); _on(ownerDocument, , _this._disableDelayedDrag); _on(ownerDocument, , _this._disableDelayedDrag); _on(ownerDocument, , _this._disableDelayedDrag); _this._dragStartTimer = setTimeout(dragStartFn, options.delay); } else { dragStartFn(); 636 } 637 } 638 }, ********************************************************************************************** 641 *函数名 :_disableDelayedDrag 642 *函数功能描述 : 禁用延迟拖拽 当拖拽延时的时候,把所有事件解绑,并且关闭定时器。 643 *函数参数 : 644 *函数返回值 : 645 *作者 : 646 *函数创建日期 : 647 *函数修改日期 : 648 *修改人 : 649 *修改原因 : 650 *版本 : 651 *历史版本 : _disableDelayedDrag: function () { 654 var ownerDocument = this.el.ownerDocument; _off(ownerDocument, , _off(ownerDocument, , _off(ownerDocument, , _off(ownerDocument, , _off(ownerDocument, , }, 664 /*********************************************************************************************** 665 *函数名 :_triggerDragStart 666 *函数功能描述 : 为拖拽前做好准本,包括判断是否是触摸设备,或者pc,或者没有dragend 667 *函数参数 : 668 *函数返回值 : 669 *作者 : 670 *函数创建日期 : 671 *函数修改日期 : 672 *修改人 : 673 *修改原因 : 674 *版本 : 675 *历史版本 : _triggerDragStart: function (touch) { (touch) { tapEvt = { 683 target: dragEl, 684 clientX: touch.clientX, 685 clientY: touch.clientY 686 }; ._onDragStart(tapEvt, ); } (!this.nativeDraggable) { ._onDragStart(tapEvt, } 694 else { _on(dragEl, , this); , this._onDragStart); 698 699 } { 702 if (document.selection) { setTimeout(function () { }); 707 } else { } 710 } catch (err) { 711 712 } 713 }, _dragStarted: function () { 718 if (rootEl && dragEl) { //如果鼠标按下去的拖拽节点存在和拖拽的根节点存在 719 // Apply effect _toggleClass(dragEl, this.options.ghostClass, true); Sortable.active = this; Drag start event _dispatchEvent(, dragEl, rootEl, oldIndex); 729 } 730 }, 731 732 _emulateDragOver: function () { (touchEvt) { 735 if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) { 736 return; 737 } ._lastX = touchEvt.clientX; 740 this._lastY = touchEvt.clientY; (!supportCssPointerEvents) { , ); 744 } target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY), 747 parent = target, 748 groupName = ' ' + this.options.group.name + '', 749 i = touchDragOverListeners.length; (parent) { 752 do { 753 if (parent[expando] && parent[expando].options.groups.indexOf(groupName) > -1) { 754 while (i--) { 755 touchDragOverListeners[i]({ 756 clientX: touchEvt.clientX, 757 clientY: touchEvt.clientY, 758 target: target, 759 rootEl: parent 760 }); 761 } ; 764 } } (parent = parent.parentNode); 770 } (!supportCssPointerEvents) { , ''); 774 } 775 } 776 }, tapEvt = { 780 target: dragEl, 781 clientX: touch.clientX, 782 clientY: touch.clientY 783 }; ********************************************************************************************** 786 *函数名 :_onTouchMove 787 *函数功能描述 : 触摸移动拖拽动画事件ghostEl,把拖拽移动的xy值给ghostEl节点 788 *函数参数 : viod 789 *函数返回值 : 无 790 *作者 : 791 *函数创建日期 : 792 *函数修改日期 : 793 *修改人 : 794 *修改原因 : 795 *版本 : 796 *历史版本 : _onTouchMove: function (evt) { (tapEvt) { (!Sortable.active) { ._dragStarted(); 804 } as well as creating the ghost element on the document body ._appendGhost(); touch = evt.touches ? evt.touches[dx = touch.clientX - tapEvt.clientX, dy = touch.clientY - tapEvt.clientY,//鼠标移动的y位置减去鼠标按下去的位置。 translate3d = evt.touches ? + dx + + dy + : + dx + + dy + ; 815 816 moved = true; _css(ghostEl, , translate3d); _css(ghostEl, , translate3d); _css(ghostEl, , translate3d) ; _css(ghostEl, , translate3d); evt.preventDefault(); } 827 }, 828 /*********************************************************************************************** 829 *函数名 :_appendGhost 830 *函数功能描述 : 创建一个ghostEl dom节点,并且是克隆拖拽节点的rootEl下面就是id那个dom节点,添加在,并且设置了一些属性,高,宽,top,left,透明度,鼠标样式, 831 *函数参数 : viod 832 *函数返回值 : 无 833 *作者 : 834 *函数创建日期 : 835 *函数修改日期 : 836 *修改人 : 837 *修改原因 : 838 *版本 : 839 *历史版本 : _appendGhost: function () { (!ghostEl) { getBoundingClientRect() 845 其实跟 o_dom.getBoundingClientRect().left= o_dom.offsetLeft; 他们值相等 846 这个方法返回一个矩形对象,包含四个属性:left、top、right和bottom。分别表示元素各边与页面上边和左边的距离。 rect = dragEl.getBoundingClientRect(), options = ghostRect; ghostEl = dragEl.cloneNode(true); //克隆dragEl 当前拖拽的节点 _toggleClass(ghostEl, options.ghostClass, false); _toggleClass(ghostEl, options.fallbackClass, true); _css(ghostEl, , rect.top - parseInt(css.marginTop, 10)); , rect.left - parseInt(css.marginLeft, 10)); , rect.width); _css(ghostEl, , rect.height); , ); _css(ghostEl, , ); _css(ghostEl, , ); _css(ghostEl, , ); //pointer-events:none顾名思意,就是鼠标事件拜拜的意思。元素应用了该CSS属性,链接啊,点击啊什么的都变成了“浮云牌酱油”。 options.fallbackOnBody && document.body.appendChild(ghostEl) || rootEl.appendChild(ghostEl); ghostRect = ghostEl.getBoundingClientRect(); , rect.width * 2 - ghostRect.width); , rect.height * 2 - ghostRect.height); 876 877 } 878 }, 879 /*********************************************************************************************** 880 *函数名 :_onDragStart 881 *函数功能描述 : 拖拽开始 为document添加触摸事件与鼠标事件 882 *函数参数 : 883 evt: 884 类型:obj, 事件对象 885 useFallback:类型:string, Boolean 值 886 *函数返回值 : 887 *作者 : 888 *函数创建日期 : 889 *函数修改日期 : 890 *修改人 : 891 *修改原因 : 892 *版本 : 893 *历史版本 : _onDragStart: function (evt, useFallback) { dataTransfer = evt.dataTransfer, 899 options = this.options; ._offUpEvents(); 903 //Object {name: "words", pull: true, put: true} (activeGroup.pull == ) { cloneEl = dragEl.cloneNode(true); //cloneNode(false) 克隆复制节点,参数如果是false则不复制里面的html,true则会复制整个dom包括里面的html _css(cloneEl, , ); rootEl.insertBefore(cloneEl, dragEl); 911 } (useFallback) { (useFallback === ) { 916 // Bind touch events _on(document, , this._onTouchMove); _on(document, , this._onDrop); _on(document, , this._onDrop); 923 } else { 924 // Old brwoser _on(document, , this._onTouchMove); _on(document, , this._onDrop); 929 } ._loopId = setInterval(this._emulateDragOver, 50); 932 } 933 else { (dataTransfer) { ; setData: function (dataTransfer, dragEl) { dataTransfer.setData('Text', dragEl.textContent);} 939 设置拖拽时候拖拽信息 options.setData && options.setData.call(this, dataTransfer, dragEl); 942 } , setTimeout( } 948 }, 949 /*********************************************************************************************** 950 *函数名 :_onDragOver 951 *函数功能描述 : 拖拽元素进进入拖拽区域, 判断拖拽节点与拖拽碰撞的节点,交换他们的dom节点位置,并执行动画。 952 *函数参数 :evt 953 *函数返回值 : 954 *作者 : 955 *函数创建日期 : 956 *函数修改日期 : 957 *修改人 : 958 *修改原因 : 959 *版本 : 960 *历史版本 : _onDragOver: function (evt) { el = this.el, 965 target, 966 dragRect, 967 revert, 968 options = this.options, 969 group = options.group, 970 groupPut = group.put, 971 isOwner = (activeGroup === group), 972 canSort = options.sort; ) { !options.dragoverBubble && evt.stopPropagation(); } 977 978 moved = true; 979 //activeGroup={name: "words", pull: true, put: true} activeGroup=true 983 //options.disabled=false 984 //isOwner=true 因为isOwner=true 则执行canSort || (revert = !rootEl.contains(dragEl)) 985 //如果父节点包含子节点则返回true ,contains,所以当canSort 是假时候(revert = !rootEl.contains(dragEl) 986 //revert = !rootEl.contains(dragEl) 取反赋值 987 //这里的if需要一个假才能拖拽 988 //(activeGroup.name === group.name) ==true; 989 //(evt.rootEl === void 0 || evt.rootEl === this.el) ==true ( 992 activeGroup && 993 !options.disabled && 994 ( : activeGroup.pull && groupPut && ( (groupPut.indexOf && ~groupPut.indexOf(activeGroup.name)) ) 1000 ) && ) 1003 { _autoScroll(evt, options, this.el); (_silent) { 1008 return; 1009 } dragRect = dragEl.getBoundingClientRect(); (revert) { _cloneHide((cloneEl || nextEl) { rootEl.insertBefore(dragEl, cloneEl || nextEl); } (!canSort) { rootEl.appendChild(dragEl); } 1029 return; 1030 } el.children.length 如果拖拽根节点没有子节点的时候该为true 1033 //el.children[0] === ghostEl如果根节点的字节点等于镜像节点的时候为真 ((el.children.length === 0) || (el.children[0] === ghostEl) || 1036 (el === evt.target) && (target = _ghostIsLast(el, evt)) 1037 ) { (target) { (target.animated) { ; 1042 } 1043 1044 targetRect = target.getBoundingClientRect(); 1045 } _cloneHide(isOwner); rootEl:拖拽根节点 1052 el:拖拽根节点 1053 dragEl:拖拽节点 1054 dragRect:拖拽几点的Rect 1055 target:目标节点或者是根节点的最后一个子节点,释放鼠标的节点 1056 targetRect:target的Rect (_onMove(rootEl, el, dragEl, dragRect, target, targetRect) !== false) { el.appendChild(dragEl); parentEl = el; } ._animate(dragRect, dragEl); 1067 target && this._animate(targetRect, target); 1068 } 1069 } 1070 //target 拖拽的目标节点存在 1071 //target.animated动画没有在执行 1072 //target !== dragEl 拖拽的节点不等于目标节点 就是发生了dragenter事件 (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0)) { 1075 1076 i++; lastEl = target; lastCSS = _css(target); lastParentCSS = _css(target.parentNode); } floating 其实就是判断这里的拖拽节点是否已经有浮动,或者是inline也跟浮动差不多,或者是css3的flex-direction横向对其成一排的那个属性 1087 //isWide:如果目标节点的宽大于拖拽节点的宽 targetRect = target.getBoundingClientRect(), width = targetRect.right - targetRect.left, height = targetRect.bottom - targetRect.top, floating = /left|right|inline|inlineBlock/.test(lastCSS.cssFloat + lastCSS.display) && lastParentCSS[].indexOf() === 0), isLong = (target.offsetHeight > dragEl.offsetHeight),//目标节点高大于拖拽节点 1096 //halfway 如果floating 浮动,inline,横向对齐 了就判断此时鼠标是在target中间的左边还是右边,右边则为true,否则false halfway = (floating ? 1099 (evt.clientX - targetRect.left) / width : 1100 (evt.clientY - targetRect.top) / height 1101 ) 1102 > 0.5, nextSibling = target.nextElementSibling, rootEl:拖拽根节点 1107 el:拖拽根节点 1108 dragEl:拖拽节点 1109 dragRect:拖拽几点的Rect 1110 target:拖拽节点或者是根节点的最后一个子节点 1111 targetRect:target的Rect moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect), after ; (moveVector !== false) { 1119 _silent = true; _cloneHide(isOwner); (moveVector === after = (moveVector === 1); 1126 } (floating) { elTop = dragEl.offsetTop, tgTop = target.offsetTop; (elTop === tgTop) { // //拖拽几点的top===目标节点top 说明他们是在同一列中 target.previousElementSibling 如果目标节点的上一个节点是拖拽节点,这里就是他们上下节点互换位置,!isWide 目标节点宽小于拖拽节点 1135 //或者 halfway 为真并且 isWide 目标节点宽大于拖拽节点 1136 // } else { after = tgTop > elTop; } 1145 } else { 1146 //没有浮动的时候 1147 // 目标节点的下一个节点。 往下拖拽 1149 //dom节点是按照拖拽完之后排序做判断 1150 //(nextSibling !== dragEl) 不是往上拖拽的时候 则为真的时候 如果目标节点的高大于拖拽节点的高 after = (nextSibling !== dragEl) && !isLong || halfway && isLong; 1153 } (!dragEl.contains(el)) { (after && !nextSibling) { // } else { 1161 //判断拖拽节点添加到哪个位置after真时候是往下拖拽则把拖拽节点添加到target下面。 target.parentNode.insertBefore(dragEl, after ? nextSibling : target); 1164 } 1165 } 1166 1167 parentEl = dragEl.parentNode; // actualization 1168 //交换位置前的drgRect, 交换后位置的拖拽节点dragEl 1169 //交换位置前的目标节点targetRect, 交换后位置的目标节点dragEl ._animate(dragRect, dragEl); //执行css3动画其实只是一种掩饰而已,真正的核心是他们交换dom节点的位置 ._animate(targetRect, target); 1175 } 1176 } 1177 } 1178 }, ********************************************************************************************** 1181 *函数名 :_animate 1182 *函数功能描述 : 动画效果,执行css3动画 1183 *函数参数 : 1184 prevRect:obj,初始动画的坐标, 1185 target:obj,target 其实最重要是获取交换dom节点后的坐标 1186 *函数返回值 : 1187 *作者 : 1188 *函数创建日期 : 1189 *函数修改日期 : 1190 *修改人 : 1191 *修改原因 : 1192 *版本 : 1193 *历史版本 : _animate: function (prevRect, target) { 1196 //每次当目标节点与拖拽节点交替的时候就调用次改函数 1197 //i++; prevRect: obj.getBoundingClientRect ms = (ms) { 1205 var currentRect = target.getBoundingClientRect(); _css(target, , ); , + (prevRect.left - currentRect.left) + + (prevRect.top - currentRect.top) + ); _css(target, , + ms + ); , ); 1218 1219 clearTimeout(target.animated); 1220 target.animated = setTimeout(function () { , ''); , ''); 1223 target.animated = false; 1224 }, ms); 1225 } 1226 }, 1227 /*********************************************************************************************** 1228 *函数名 :_offUpEvents 1229 *函数功能描述 : 解绑文档上的拖拽函数 1230 *函数参数 : viod 1231 *函数返回值 :viod 1232 *作者 : 1233 *函数创建日期 : 1234 *函数修改日期 : 1235 *修改人 : 1236 *修改原因 : 1237 *版本 : 1238 *历史版本 : _offUpEvents: function () { 1242 var ownerDocument = this.el.ownerDocument; , _off(ownerDocument, , _off(ownerDocument, , this._onDrop); //当文档上面document 发生触摸结束事件的时候解绑 _onTouchMove事件 _off(ownerDocument, , }, ********************************************************************************************** 1255 *函数名 :init 1256 *函数功能描述 : 初始化作用 1257 *函数参数 : 1258 *函数返回值 : 1259 *作者 : 1260 *函数创建日期 : 1261 *函数修改日期 : 1262 *修改人 : 1263 *修改原因 : 1264 *版本 : 1265 *历史版本 : _onDrop: function (evt) { el = options = clearInterval(clearInterval(autoScroll.pid);clearTimeout(this._dragStartTimer);//清除_dragStartTimer 定时器 _off(document, , DataTransfer 对象:退拽对象用来传递的媒介,使用一般为Event.dataTransfer。 1282 draggable 属性:就是标签元素要设置draggable=true,否则不会有效果,例如: 1283 1284 <div title="拖拽我" draggable="true">列表1</div> 1285 1286 ondragstart 事件:当拖拽元素开始被拖拽的时候触发的事件,此事件作用在被拖曳元素上 1287 ondragenter 事件:当拖曳元素进入目标元素的时候触发的事件,此事件作用在目标元素上 1288 ondragover 事件:拖拽元素在目标元素上移动的时候触发的事件,此事件作用在目标元素上 1289 ondrop 事件:被拖拽的元素在目标元素上同时鼠标放开触发的事件,此事件作用在目标元素上 1290 ondragend 事件:当拖拽完成后触发的事件,此事件作用在被拖曳元素上 1291 Event.preventDefault() 方法:阻止默认的些事件方法等执行。在ondragover中一定要执行preventDefault(),否则ondrop事件不会被触发。另外,如果是从其他应用软件或是文件中拖东西进来,尤其是图片的时候,默认的动作是显示这个图片或是相关信息,并不是真的执行drop。此时需要用用document的ondragover事件把它直接干掉。 1292 Event.effectAllowed 属性:就是拖拽的效果。 1293 如果nativeDraggable是true 那么 (this.nativeDraggable) { , _off(el, , } ._offUpEvents(); (evt) { 1303 if (moved) { !options.dropBubble && evt.stopPropagation(); } 1307 //ghostEl 在736行时候才会创建该节点,所以在736行调用_onDrop函数的时候都是为空 ghostEl && ghostEl.parentNode.removeChild(ghostEl); (dragEl) { 1313 if (this.nativeDraggable) { _off(dragEl, , this); 1316 } _disableDraggable(dragEl); _toggleClass(dragEl, this.options.ghostClass, false); 1322 _toggleClass(dragEl, this.options.chosenClass, false); (rootEl !== parentEl) { //如果从一个列表拖拽到另一个列表的时候 newIndex = _index(dragEl, options.draggable); (newIndex >= 0) { //如果当前的索引大于0 从类表中拖拽到另一个列表 _dispatchEvent(, dragEl, rootEl, oldIndex, newIndex); _dispatchEvent(, dragEl, rootEl, oldIndex, newIndex);//开始拖拽函数创建与触发 _dispatchEvent(, dragEl, rootEl, oldIndex, newIndex);//添加节点拖拽函数创建与触发 _dispatchEvent(, dragEl, rootEl, oldIndex, newIndex); 1340 } 1341 1342 } 1343 else { //同一个列表中 cloneEl && cloneEl.parentNode.removeChild(cloneEl); (dragEl.nextSibling !== nextEl) { newIndex = _index(dragEl, options.draggable); (newIndex >= 0) { _dispatchEvent(, dragEl, rootEl, oldIndex, newIndex); , dragEl, rootEl, oldIndex, newIndex); 1357 } 1358 } 1359 } (Sortable.active) { (newIndex == newIndex = oldIndex; 1365 } _dispatchEvent(, dragEl, rootEl, oldIndex, newIndex); .save(); 1371 } 1372 } 1373 1374 } ._nulling(); 1377 }, 1378 /*********************************************************************************************** 1379 *函数名 :_nulling 1380 *函数功能描述 : 初始化拖拽的数据 1381 *函数参数 : 1382 *函数返回值 : 1383 *作者 : 1384 *函数创建日期 : 1385 *函数修改日期 : 1386 *修改人 : 1387 *修改原因 : 1388 *版本 : 1389 *历史版本 : _nulling: function () { 1392 if (Sortable.active === this) { dragEl = parentEl = ghostEl = nextEl = cloneEl = scrollEl = scrollParentEl = tapEvt = touchEvt = moved = newIndex = lastEl = lastCSS = activeGroup = Sortable.active = null; 1414 1415 } 1416 }, 1417 /*********************************************************************************************** 1418 *函数名 :handleEvent 1419 *函数功能描述 : 为事件绑定this的时候提供该事件,判断是否在拖拽还是拖拽结束,调用对应的函数 1420 *函数参数 : 1421 evt: 1422 类型:object,事件类型 拖拽的事件类型 1423 *函数返回值 : 1424 *作者 : 1425 *函数创建日期 : 1426 *函数修改日期 : 1427 *修改人 : 1428 *修改原因 : 1429 *版本 : 1430 *历史版本 : handleEvent: function (evt) {type = evt.type; 1434 //dragover 在拖拽区域移动拖拽时候发生事件相当于move (type === || type === ) { (dragEl) { ._onDragOver(evt); 1441 _globalDragOver(evt); 1442 } 1443 } (type === || type === ) { ._onDrop(evt); 1446 } 1447 }, * 1451 * Serializes the item into an array of string. 1452 * @returns {String[]} ********************************************************************************************** 1455 *函数名 :toArray 1456 1457 *函数功能描述 : 获取dom节点的 data-id 的属性 如果没有则 会调用_generateId函数生成唯一表示符 1458 *函数参数 : viod 1459 *函数返回值 : 类型:array 生成唯一标识符的id数组 1460 *作者 : 1461 *函数创建日期 : 1462 *函数修改日期 : 1463 *修改人 : 1464 *修改原因 : 1465 *版本 : 1466 *历史版本 : toArray: function () { 1469 var order = [], 1470 el, i = 0, options = this.options; (; i < n; i++) { 1478 el = children[i]; 1479 if (_closest(el, options.draggable, this.el)) { 1480 //getAttribute获取 data-id 的属性 order.push(el.getAttribute(options.dataIdAttr) || _generateId(el)); 1483 } 1484 } order; 1487 }, * 1491 * Sorts the elements according to the array. 1492 * @param {String[]} order order of the items ********************************************************************************************** 1496 *函数名 :sort 1497 1498 *函数功能描述 : 删除含有这个id的子节点 删除他 让他重新排序, 从栈底部插入数据 1499 *函数参数 : order: 1500 类型:array, 数组id 1501 1502 *函数返回值 : void 1503 *作者 : 1504 *函数创建日期 : 1505 *函数修改日期 : 1506 *修改人 : 1507 *修改原因 : 1508 *版本 : 1509 *历史版本 : sort: function (order) { 1512 debugger; items = {}, .toArray().forEach(function (id, i) { el = rootEl.children[i]; (_closest(el, this.options.draggable, rootEl)) { } 1524 }, this); 1525 1526 order.forEach(function (id) { 1527 if (items[id]) { rootEl.appendChild(items[id]); } 1531 }); 1532 }, * 1536 * Save the current sorting 1537 保存排序 save: function () { 1540 var store = this.options.store; 1541 store && store.set(this); 1542 }, * 1546 * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. 1547 * @param {HTMLElement} el 1548 * @param {String} [selector] default: `options.draggable` 1549 * @returns {HTMLElement|null} ********************************************************************************************** 1552 *函数名 :_closest 1553 *函数功能描述 : 用来调节节点,匹配节点。匹配calss。 匹配触发dom该函数的dom节点中的tag或者class,selector参数可以是tag或者class或者>*, 1554 如果是>* 并且当前的父节点和ctx 参数相同 则不需要匹配直接返回el,如果是tag或者class则匹配。 1555 *函数参数 : 1556 el: 1557 类型:obj,拖拽节点dom 1558 selector: 1559 类型:字符串,如果selector是'li' : '>*'则返回是改节点dom,还有如果selector是和当前拖拽节点的name相同则也返回改节点dom,还有匹配触发该函数的el中的class是否是和参数中selector相同,相同则返回true,否则返回null 1560 1561 *函数返回值 :dom和null 1562 *作者 : 1563 *函数创建日期 : 1564 *函数修改日期 : 1565 *修改人 : 1566 *修改原因 : 1567 *版本 : 1568 *历史版本 : closest: function (el, selector) { _closest(el, selector || this.options.draggable, this.el); 1573 }, * 1577 * Set/get option 1578 * @param {string} name 1579 * @param {*} [value] 1580 * @returns {*} ********************************************************************************************** 1583 *函数名 :option 1584 *函数功能描述 : 获取option对象中的某个参数,或者设置option对象中的某个参数 1585 1586 *函数参数 :name: 1587 类型:string, option的key, 1588 1589 value:类型:string, 设置option的值 1590 1591 *函数返回值 : viod 1592 *作者 : 1593 *函数创建日期 : 1594 *函数修改日期 : 1595 *修改人 : 1596 *修改原因 : 1597 *版本 : 1598 *历史版本 : option: function (name, value) { 1602 var options = this.options; (value === options[name]; 1606 } else { (name === ) { _prepareGroup(options); 1611 } 1612 } 1613 }, * 1617 * Destroy 破坏 ********************************************************************************************** 1620 *函数名 :destroy 1621 *函数功能描述 : 清空拖拽事件,和情况拖拽列表dom节点,销毁拖拽 。 1622 1623 *函数参数 viod 1624 *函数返回值 : viod 1625 *作者 : 1626 *函数创建日期 : 1627 *函数修改日期 : 1628 *修改人 : 1629 *修改原因 : 1630 *版本 : 1631 *历史版本 : destroy: function () { 1634 var el = this.el; _off(el, , _off(el, , (this.nativeDraggable) { , _off(el, , } Remove draggable attributes Array.prototype.forEach.call(el.querySelectorAll(), function (el) { ); 1650 }); touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1); ._onDrop(); .el = el = } 1658 }; ********************************************************************************************** 1661 *函数名 :_cloneHide 1662 *函数功能描述 : 设置克隆的节点隐藏显示,是否添加到页面 1663 *函数参数 : 1664 state: 1665 类型:Boolean 真,假 1666 *函数返回值 : viod 1667 *作者 : 1668 *函数创建日期 : 1669 *函数修改日期 : 1670 *修改人 : 1671 *修改原因 : 1672 *版本 : 1673 *历史版本 : function _cloneHide(state) { 1676 //state布尔值 1677 //cloneEl 克隆的节点 (cloneEl && (cloneEl.state !== state)) {_css(cloneEl, , state ? : !state && cloneEl.state && rootEl.insertBefore(cloneEl, dragEl);cloneEl.state = state; // 1683 } 1684 } ********************************************************************************************** 1687 *函数名 :_closest 1688 *函数功能描述 : 匹配触发dom该函数的dom节点中的tag或者class,selector参数可以是tag或者class或者>*, 1689 如果是>* 并且当前的父节点和ctx 参数相同 则不需要匹配直接返回el,如果是tag或者class则匹配 1690 *函数参数 : 1691 el: 1692 类型:obj,拖拽节点dom 1693 selector: 1694 类型:字符串,如果selector是'li' : '>*'则返回是改节点dom,还有如果selector是和当前拖拽节点的name相同则也返回改节点dom,还有匹配触发该函数的el中的class是否是和参数中selector相同,相同则返回true,否则返回null 1695 ctx:ctx用来匹配当前selector的父节点是否等于ctx节点 1696 *函数返回值 :dom和null 1697 *作者 : 1698 *函数创建日期 : 1699 *函数修改日期 : 1700 *修改人 : 1701 *修改原因 : 1702 *版本 : 1703 *历史版本 : function _closest(el, selector, ctx) { 1706 /* el 目标节点 1707 selector /[uo]l/i.test(el.nodeName) ? 'li' : '>*', (el) { ctx = ctx || document; { ( 1716 //如果不是li而是其他节点 并且已经搜索完了直到是父亲节点的时候就返回true 1717 //或者走_matches _matches 需要true (selector === && el.parentNode === ctx) 1720 || _matches(el, selector) 1721 ) { el; 1724 } 1725 } (el !== ctx && (el = el.parentNode)); } ; 1731 } *函数名 :_globalDragOver 1735 *函数功能描述 :设置拖动的元素移动到放置目标。 1736 *参数说明: 1737 evt:类型obj事件对象 1738 返回值:void function _globalDragOver(evt) { 1.effectAllowed属性表示允许拖放元素的哪种dropEffect。什么是dropEffect?也是dataTransfer 的一种属性。 1743 dropEffect属性可以知道被拖动的元素能够执行哪种放置行为(当拖到目的地时)。这个属性有下列4个可能的值。 1744 “none”:不能把拖动的元素放在这里。这是除文本框之外所有元素的默认值。 1745 “move”:应该把拖动的元素移动到放置目标。 1746 “copy”:应该把拖动的元素复制到放置目标。 1747 “link”:表示放置目标会打开拖动的元素(但拖动的元素必须是一个链接,有URL)。 1748 2. dt.effectAllowed = 'all':即说被拖动元素在放置到目的地时,可以上面的任意一种效果来处理。 1749 3. 必须在ondraggstart事件处理程序中设置effectAllowed属性。 (evt.dataTransfer) { ; } 1755 evt.preventDefault(); 1756 } *函数名 :_on 1760 *函数功能描述 : 事件绑定 1761 *参数说明: 1762 el:类型DOM节点, 1763 name:类型string,事件类型 1764 fn:类型:function,需要绑定的函数 function _on(el, event, fn) { 1767 el.addEventListener(event, fn, false); 1768 } *函数名 :_toggleClass 1772 *函数功能描述 : 添加删除calss 1773 *参数说明: 1774 el:类型DOM节点, 需要添加和删除的dom节点, 1775 name:类型string,需要添加删除class字符串的 1776 fn:类型:布尔值,如果是真则删除name的class名称否则添加 function _off(el, event, fn) { 1779 el.removeEventListener(event, fn, false); 1780 } *函数名 :_toggleClass 1784 *函数功能描述 : 添加删除calss 1785 *参数说明: 1786 el:类型DOM节点, 需要添加和删除的dom节点, 1787 name:类型string,需要添加删除class字符串的 1788 state:类型:布尔值,如果是真则删除name的class名称否则添加 function _toggleClass(el, name, state) { 获取dom节点clss的个数并且以数组形式存储起来 (el) { 1794 if (el.classList) { el.classList[state ? : ](name); 1797 } 1798 else { 1799 //replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。 1800 // RSPACE = /\s+/g, 匹配1-n个空格 全局匹配 1801 // (' ' + el.className + ' ').replace(RSPACE, ' ') 去除class 中的所有空格 并且只保留一个空格 每一个class中 className = ().replace(RSPACE, , ' '); el.className = (className + (state ? ); 1807 } 1808 } } *函数名 :设置 样式 与 获取dom节点的style属性 1814 *函数功能描述 : 添加删除calss,获取dom节点全部css属性,如果是一个参数的时候将返回该dom节点的全部css属性,如果是两个参数的时候该返回该css的第二个参数的值,如果是三个参数的话将设置css样式 1815 *参数说明: 1816 el:类型DOM节点, 需要添加和删除的dom节点, 1817 prop:类型string,需要添加删除class字符串的那么 1818 val:类型:布尔值,如果是真则删除name的class名称否则添加 function _css(el, prop, val) { (style) { ) { //如果val===undefined 1826 //var win = document.defaultView; 返回当前文档上面的所有对象 1827 //document.defaultView.getComputedStyle 返回当前文档上的对象的样式方法 1828 // 1829 if (document.defaultView && document.defaultView.getComputedStyle) { } (el.currentStyle) { } prop === } 1838 else { prop = + prop; } ? ); } 1845 } 1846 } ********************************************************************************************** 1852 *函数名 :_find 1853 *函数功能描述 : 获取拖拽节点下面的所有a和img标签,并且设置他们禁止拖拽行为 1854 *函数参数 : 1855 ctx: 1856 类型:dom-obj 拖拽的节点 1857 tagName: 1858 类型:string,ctx.getElementsByTagName(tagName) 1859 获取拖拽节点下面的所有a和img 1860 *函数返回值 : a和img的dom集合 1861 *作者 : 1862 *函数创建日期 : 1863 *函数修改日期 : 1864 *修改人 : 1865 *修改原因 : 1866 *版本 : 1867 *历史版本 : function _find(ctx, tagName, iterator) { ctx 拖拽的节点 1872 ctx.getElementsByTagName(tagName) 获取拖拽节点下面的所有a和img 1873 _disableDraggable 是一个函数 1874 iterator=_disableDraggable 1875 _find(ctx, tagName, iterator) 该函数功能是把当前拖拽对象的a和img节点的html5 拖拽属性改为false (ctx) { 1879 var list = ctx.getElementsByTagName(tagName), i = 0, n = list.length; (iterator) { 1882 for (; i < n; i++) { 1883 iterator(list[i], i); 1884 } 1885 } list; 1888 } []; 1891 } ********************************************************************************************** 1894 *函数名 :_dispatchEvent 1895 *函数功能描述 : 创建一个事件,事件参数主要由name 提供,并且触发该事件,其实就是模拟事件并且触发该事件 1896 *函数参数 : 1897 sortable: 1898 类型: obj sortable 1899 rootEl: 1900 类型: dom-obj 鼠标按下去拖拽节点的根节点 1901 1902 name: 类型: string 需要创建的事件 1903 1904 targetEl:dom-obj 鼠标按下去拖拽节点,触屏到发生事件ondragover的节点的根节点,就是目标节点的根节点。但是如果是start事件的时候传进来的改参数就是鼠标按下去拖拽节点的根节点 1905 1906 fromEl: 1907 类型: dom-obj 鼠标按下去拖拽节点的根节点 参数和第二个一样,为什么重写参数进来呢,可能是为了兼容这样的的吧 1908 1909 startIndex: 1910 类型: number 鼠标按下去拖拽节点的索引 1911 newIndex: 1912 类型: number 1913 1914 * *函数返回值 : 1915 *作者 : 1916 *函数创建日期 : 1917 *函数修改日期 : 1918 *修改人 : 1919 *修改原因 : 1920 *版本 : 1921 *历史版本 : function _dispatchEvent(sortable, rootEl, name, targetEl, fromEl, startIndex, newIndex) { evt = document.createEvent(), options = (sortable || rootEl[expando]).options, //获取options 参数 1927 //name.charAt(0) 获取name的第一个字符串 1928 //toUpperCase() 变成大写 1929 //name.substr(1) 提取从索引为1下标到字符串的结束位置的字符串 onName = + name.charAt(0).toUpperCase() + name.substr(1); evt.to = rootEl; evt.evt.item = targetEl || rootEl; evt.clone = cloneEl; evt.oldIndex = startIndex; evt.newIndex = newIndex; //现在节点 rootEl.dispatchEvent(evt); (options[onName]) { 1947 options[onName].call(sortable, evt); 1948 } 1949 } ********************************************************************************************** 1952 *函数名 :_onMove 1953 *函数功能描述 : 表格分页数据 1954 *函数参数 : 1955 fromEl: 1956 类型:obj,拖拽的根节点 1957 toEl: 1958 类型:obj,拖拽的根节点 1959 dragEl: 1960 类型:obj,拖拽的节点 1961 dragRect: 1962 类型:obj,拖拽的节点rect 1963 targetEl: 1964 类型:obj,目标节点 ondragover 发生事件的节点 1965 targetRect: 1966 类型:obj,目标节点rect 1967 *函数返回值 : retVal 1968 *作者 : 1969 *函数创建日期 : 1970 *函数修改日期 : 1971 *修改人 : 1972 *修改原因 : 1973 *版本 : 1974 *历史版本 : function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect) { evt, sortable = fromEl[expando], onMoveFn = sortable.options.onMove, retVal; evt = document.createEvent(); evt.initEvent(, evt.to = toEl; evt.evt.dragged = dragEl; evt.draggedRect = dragRect; evt.related = targetEl || toEl; evt.relatedRect = targetRect || toEl.getBoundingClientRect(); fromEl.dispatchEvent(evt); (onMoveFn) { } retVal; } 2004 /*********************************************************************************************** 2005 *函数名 :_disableDraggable 2006 *函数功能描述 : 禁用拖动 把heml5的拖拽属性设置为假 2007 *函数参数 :viod 2008 *函数返回值 :无 2009 *作者 : 2010 *函数创建日期 : 2011 *函数修改日期 : 2012 *修改人 : 2013 *修改原因 : 2014 *版本 : 2015 *历史版本 : function _disableDraggable(el) { 2019 el.draggable = false; 2020 } ********************************************************************************************** 2023 *函数名 :_unsilent 2024 *函数功能描述 : 将 _silent 设置为假 2025 *函数参数 :viod 2026 *函数返回值 :无 2027 *作者 : 2028 *函数创建日期 : 2029 *函数修改日期 : 2030 *修改人 : 2031 *修改原因 : 2032 *版本 : 2033 *历史版本 : function _unsilent() { 2036 _silent = false; 2037 } ********************************************************************************************** 2042 *函数名 :_ghostIsLast 2043 *函数功能描述 : 表格分页数据 2044 *函数参数 : 2045 el :类型:dom,拖拽的根节点 2046 evt:类型:obj,事件对象 2047 *函数返回值 : 2048 *作者 : 2049 *函数创建日期 : 2050 *函数修改日期 : 2051 *修改人 : 2052 *修改原因 : 2053 *版本 : 2054 *历史版本 : function _ghostIsLast(el, evt) { rect = lastEl.getBoundingClientRect(); ( (evt.clientX - (rect.right + rect.width) > ) && lastEl; } * 2067 * Generate id 2068 * @param {HTMLElement} el 2069 * @returns {String} 2070 * @private ********************************************************************************************** 2073 *函数名 :_generateId 2074 *函数功能描述 : 根据tag的name和class,src,href,文本内容,来匹配生成唯一的标识符 2075 *函数参数 : 2076 el:dom节点 2077 *函数返回值 :string 2078 *作者 : 2079 *函数创建日期 : 2080 *函数修改日期 : 2081 *修改人 : 2082 *修改原因 : 2083 *版本 : 2084 *历史版本 : function _generateId(el) { 2089 var str = el.tagName + el.className + el.src + el.href + el.textContent, 2090 i = str.length, 2091 sum = 0; (i--) { 2094 sum += str.charCodeAt(i); 2095 } sum.toString( } * 2101 * Returns the index of an element within its parent for a selected set of 2102 * elements 2103 * @param {HTMLElement} el 2104 * @param {selector} selector 2105 * @return {number} ********************************************************************************************** 2108 *函数名 :_index 2109 *函数功能描述 : 返回在其父范围内的元素的元素的索引 2110 *函数参数 : 2111 el 2112 *函数返回值 :number 2113 *作者 : 2114 *函数创建日期 : 2115 *函数修改日期 : 2116 *修改人 : 2117 *修改原因 : 2118 *版本 : 2119 *历史版本 : function _index(el, selector) { 2123 var index = 0; (!el || !el.parentNode) { 2127 return -1; 2128 } TEMPLATE 标签 html5 模板标签 例子 2133 // 模板文本 2134 <template> 2135 <img src="dummy.png" title="{{title}}"/> 2136 </template> 2137 2138 // 获取模板 2139 <script type="text/javascript"> 2140 var tplEl = document.getElementById('tpl') 2141 // 通过tplEl.innerText获取也可以 2142 var tpl = tplEl.innerHTML 2143 tpl = tpl.replace(/^[\s\u3000]*|[\s\u3000]*$/, '') 2144 Handlebars.compile(tpl)({title: 'test'}) 2145 </script> 2146 2147 意思是当节点是TEMPLATE标签的时候则表示该搜索标签已经到达了最顶端 (el && (el = el.previousElementSibling)) { && _matches(el, selector)) { 2152 index++; 2153 } 2154 } index; 2157 } 2158 /*********************************************************************************************** 2159 *函数名 :_matches 2160 *函数功能描述 : 匹配tag和tag,匹配clsss和tag, 2161 *函数参数 : 2162 el: 2163 类型:obj,当前拖拽节点dom 2164 selector: 2165 类型:string, tag或者clasname 2166 2167 *函数返回值 : 2168 类型:Boolean,真假,selector如果传递的是tag,则当前的el的tag和selector的tag要同样,或当前的el的class含有selector 中的calss则返回真,否则返回假 2169 *作者 : 2170 *函数创建日期 : 2171 *函数修改日期 : 2172 *修改人 : 2173 *修改原因 : 2174 *版本 : 2175 *历史版本 : function _matches(el, selector) { el 目标节点 2180 selector = /[uo]l/i.test(el.nodeName) ? 'li' : '>*', 2181 selector=>* (el) { 没有.则返回为空 但是selector 的值还是原来的 li 但是selector 类型变成了数组 2185 //shift 删除数组第一个字符串并返回该字符串 2186 //toUpperCase 把字符串变成大写 selector = selector.split(); tag = selector.shift().toUpperCase(), // class join 把数组["a","b","c"]变成a|b|c 2193 // (?=)会作为匹配校验,但不会出现在匹配结果字符串里面 就是前后必须要匹配有空格 但是不会匹配上空格 \\s 与 (?=\\s) 前后必须要有空格,但是不会匹配上空格 re = + selector.join() + , ); ( 2203 //tag === '' el.nodeName.toUpperCase() == tag 2204 //selector.length=2 tag === '' true (tag === '' || el.nodeName.toUpperCase() == tag) && (!selector.length || (().match(re) || []).length == selector.length) 2209 ); 2210 } ; 2213 } ********************************************************************************************** 2217 *函数名 :_throttle 2218 *函数功能描述 : 回调初始化一个函数 并且调用该回调函数 2219 *函数参数 : 2220 callback: 2221 类型:function,回调函数 2222 ms: 2223 类型:number, 毫秒 2224 2225 *函数返回值 : 2226 类型:function,函数,可以用来声明一个函数作用 2227 *作者 : 2228 *函数创建日期 : 2229 *函数修改日期 : 2230 *修改人 : 2231 *修改原因 : 2232 *版本 : 2233 *历史版本 : function _throttle(callback, ms) { 2236 var args, 2237 _this; function () { (args === void 0) { _this = this; setTimeout(function () { callback.call(_this, args[0]); 2248 } else { } 2251 args = void 0; 2252 }, ms); 2253 } 2254 }; 2255 } 2256 /*********************************************************************************************** 2257 *函数名 :_extend 2258 *函数功能描述 :类合并 2259 *函数参数 : 2260 dst:类型:obj,子类 2261 src:类型:obj,父类 2262 *函数返回值 : dst 子类 2263 *作者 : 2264 *函数创建日期 : 2265 *函数修改日期 : 2266 *修改人 : 2267 *修改原因 : 2268 *版本 : 2269 *历史版本 : function _extend(dst, src) { 2272 if (dst && src) { (src.hasOwnProperty(key)) { dst[key] = src[key]; 2276 } 2277 } 2278 } dst; 2281 } 声明一个类utils Sortable.utils = { 2287 on: _on, 2288 off: _off, 2289 css: _css, 2290 find: _find, 2291 is: function (el, selector) { !!_closest(el, selector, el); 2294 }, 2295 extend: _extend, 2296 throttle: _throttle, 2297 closest: _closest, 2298 toggleClass: _toggleClass, 2299 index: _index 2300 }; * 2304 * Create sortable instance 2305 * @param {HTMLElement} el 2306 * @param {Object} [options] ********************************************************************************************** 2309 *函数名 :Sortable.create 2310 *函数功能描述 :在类Sortable中添加多个一个方法,而调用Sortable构造函数实例化给Sortable.create 属性,创建了拖拽功能 2311 *函数参数 : 2312 el:类型:obj,拖拽列表的dom节点 2313 options:类型:obj,拖拽的参数 2314 *函数返回值 : dst 子类 2315 *作者 : 2316 *函数创建日期 : 2317 *函数修改日期 : 2318 *修改人 : 2319 *修改原因 : 2320 *版本 : 2321 *历史版本 : Sortable.create = function (el, options) { Sortable(el, options); 2326 }; Sortable.version = ; Sortable; 2333 });

 

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • HTML5大数据可视化效果(二)可交互地铁线路图 - twaver

    HTML5大数据可视化效果(二)可交互地铁线路图 - twaver

    2016-11-04 14:00

  • 让IE9以下版本的浏览支持html5,CSS3的插件 - 叫我小龙哥

    让IE9以下版本的浏览支持html5,CSS3的插件 - 叫我小龙哥

    2016-11-04 12:00

  • HTML5 标签 details 展开 搜索 - 心韵

    HTML5 标签 details 展开 搜索 - 心韵

    2016-11-03 15:00

  • 自己写的HTML5 Canvas + Javascript五子棋 - 氢氦

    自己写的HTML5 Canvas + Javascript五子棋 - 氢氦

    2016-10-31 13:00

网友点评