| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590 | /**! * KvSortable * @author	RubaXa   <[email protected]> * @license MIT * * Changed kvsortable plugin naming to prevent conflict with JQuery UI Sortable * @author Kartik Visweswaran */(function kvsortableModule(factory) {	"use strict";	if (typeof define === "function" && define.amd) {		define(factory);	}	else if (typeof module != "undefined" && typeof module.exports != "undefined") {		module.exports = factory();	}	else {		/* jshint sub:true */		window["KvSortable"] = factory();	}})(function kvsortableFactory() {	"use strict";	if (typeof window === "undefined" || !window.document) {		return function kvsortableError() {			throw new Error("KvSortable.js requires a window with a document");		};	}	var dragEl,		parentEl,		ghostEl,		cloneEl,		rootEl,		nextEl,		lastDownEl,		scrollEl,		scrollParentEl,		scrollCustomFn,		lastEl,		lastCSS,		lastParentCSS,		oldIndex,		newIndex,		activeGroup,		putKvSortable,		autoScroll = {},		tapEvt,		touchEvt,		moved,		/** @const */		R_SPACE = /\s+/g,		R_FLOAT = /left|right|inline/,		expando = 'KvSortable' + (new Date).getTime(),		win = window,		document = win.document,		parseInt = win.parseInt,		setTimeout = win.setTimeout,		$ = win.jQuery || win.Zepto,		Polymer = win.Polymer,		captureMode = false,		passiveMode = false,		supportDraggable = ('draggable' in document.createElement('div')),		supportCssPointerEvents = (function (el) {			// false when IE11			if (!!navigator.userAgent.match(/(?:Trident.*rv[ :]?11\.|msie)/i)) {				return false;			}			el = document.createElement('x');			el.style.cssText = 'pointer-events:auto';			return el.style.pointerEvents === 'auto';		})(),		_silent = false,		abs = Math.abs,		min = Math.min,		savedInputChecked = [],		touchDragOverListeners = [],		_autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl) {			// Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521			if (rootEl && options.scroll) {				var _this = rootEl[expando],					el,					rect,					sens = options.scrollSensitivity,					speed = options.scrollSpeed,					x = evt.clientX,					y = evt.clientY,					winWidth = window.innerWidth,					winHeight = window.innerHeight,					vx,					vy,					scrollOffsetX,					scrollOffsetY				;				// Delect scrollEl				if (scrollParentEl !== rootEl) {					scrollEl = options.scroll;					scrollParentEl = rootEl;					scrollCustomFn = options.scrollFn;					if (scrollEl === true) {						scrollEl = rootEl;						do {							if ((scrollEl.offsetWidth < scrollEl.scrollWidth) ||								(scrollEl.offsetHeight < scrollEl.scrollHeight)							) {								break;							}							/* jshint boss:true */						} while (scrollEl = scrollEl.parentNode);					}				}				if (scrollEl) {					el = scrollEl;					rect = scrollEl.getBoundingClientRect();					vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens);					vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens);				}				if (!(vx || vy)) {					vx = (winWidth - x <= sens) - (x <= sens);					vy = (winHeight - y <= sens) - (y <= sens);					/* jshint expr:true */					(vx || vy) && (el = win);				}				if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) {					autoScroll.el = el;					autoScroll.vx = vx;					autoScroll.vy = vy;					clearInterval(autoScroll.pid);					if (el) {						autoScroll.pid = setInterval(function () {							scrollOffsetY = vy ? vy * speed : 0;							scrollOffsetX = vx ? vx * speed : 0;							if ('function' === typeof(scrollCustomFn)) {								return scrollCustomFn.call(_this, scrollOffsetX, scrollOffsetY, evt);							}							if (el === win) {								win.scrollTo(win.pageXOffset + scrollOffsetX, win.pageYOffset + scrollOffsetY);							} else {								el.scrollTop += scrollOffsetY;								el.scrollLeft += scrollOffsetX;							}						}, 24);					}				}			}		}, 30),		_prepareGroup = function (options) {			function toFn(value, pull) {				if (value === void 0 || value === true) {					value = group.name;				}				if (typeof value === 'function') {					return value;				} else {					return function (to, from) {						var fromGroup = from.options.group.name;						return pull							? value							: value && (value.join								? value.indexOf(fromGroup) > -1								: (fromGroup == value)							);					};				}			}			var group = {};			var originalGroup = options.group;			if (!originalGroup || typeof originalGroup != 'object') {				originalGroup = {name: originalGroup};			}			group.name = originalGroup.name;			group.checkPull = toFn(originalGroup.pull, true);			group.checkPut = toFn(originalGroup.put);			group.revertClone = originalGroup.revertClone;			options.group = group;		}	;	// Detect support a passive mode	try {		window.addEventListener('test', null, Object.defineProperty({}, 'passive', {			get: function () {				// `false`, because everything starts to work incorrectly and instead of d'n'd,				// begins the page has scrolled.				passiveMode = false;				captureMode = {					capture: false,					passive: passiveMode				};			}		}));	} catch (err) {}	/**	 * @class  KvSortable	 * @param  {HTMLElement}  el	 * @param  {Object}       [options]	 */	function KvSortable(el, options) {		if (!(el && el.nodeType && el.nodeType === 1)) {			throw 'KvSortable: `el` must be HTMLElement, and not ' + {}.toString.call(el);		}		this.el = el; // root element		this.options = options = _extend({}, options);		// Export instance		el[expando] = this;		// Default options		var defaults = {			group: Math.random(),			sort: true,			disabled: false,			store: null,			handle: null,			scroll: true,			scrollSensitivity: 30,			scrollSpeed: 10,			draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*',			ghostClass: 'kvsortable-ghost',			chosenClass: 'kvsortable-chosen',			dragClass: 'kvsortable-drag',			ignore: 'a, img',			filter: null,			preventOnFilter: true,			animation: 0,			setData: function (dataTransfer, dragEl) {				dataTransfer.setData('Text', dragEl.textContent);			},			dropBubble: false,			dragoverBubble: false,			dataIdAttr: 'data-id',			delay: 0,			forceFallback: false,			fallbackClass: 'kvsortable-fallback',			fallbackOnBody: false,			fallbackTolerance: 0,			fallbackOffset: {x: 0, y: 0},			supportPointer: KvSortable.supportPointer !== false		};		// Set default options		for (var name in defaults) {			!(name in options) && (options[name] = defaults[name]);		}		_prepareGroup(options);		// Bind all private methods		for (var fn in this) {			if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {				this[fn] = this[fn].bind(this);			}		}		// Setup drag mode		this.nativeDraggable = options.forceFallback ? false : supportDraggable;		// Bind events		_on(el, 'mousedown', this._onTapStart);		_on(el, 'touchstart', this._onTapStart);		options.supportPointer && _on(el, 'pointerdown', this._onTapStart);		if (this.nativeDraggable) {			_on(el, 'dragover', this);			_on(el, 'dragenter', this);		}		touchDragOverListeners.push(this._onDragOver);		// Restore sorting		options.store && this.sort(options.store.get(this));	}	KvSortable.prototype = /** @lends KvSortable.prototype */ {		constructor: KvSortable,		_onTapStart: function (/** Event|TouchEvent */evt) {			var _this = this,				el = this.el,				options = this.options,				preventOnFilter = options.preventOnFilter,				type = evt.type,				touch = evt.touches && evt.touches[0],				target = (touch || evt).target,				originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0]) || target,				filter = options.filter,				startIndex;			_saveInputCheckedState(el);			// Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.			if (dragEl) {				return;			}			if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) {				return; // only left button or enabled			}			// cancel dnd if original target is content editable			if (originalTarget.isContentEditable) {				return;			}			target = _closest(target, options.draggable, el);			if (!target) {				return;			}			if (lastDownEl === target) {				// Ignoring duplicate `down`				return;			}			// Get the index of the dragged element within its parent			startIndex = _index(target, options.draggable);			// Check filter			if (typeof filter === 'function') {				if (filter.call(this, evt, target, this)) {					_dispatchEvent(_this, originalTarget, 'filter', target, el, el, startIndex);					preventOnFilter && evt.preventDefault();					return; // cancel dnd				}			}			else if (filter) {				filter = filter.split(',').some(function (criteria) {					criteria = _closest(originalTarget, criteria.trim(), el);					if (criteria) {						_dispatchEvent(_this, criteria, 'filter', target, el, el, startIndex);						return true;					}				});				if (filter) {					preventOnFilter && evt.preventDefault();					return; // cancel dnd				}			}			if (options.handle && !_closest(originalTarget, options.handle, el)) {				return;			}			// Prepare `dragstart`			this._prepareDragStart(evt, touch, target, startIndex);		},		_prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target, /** Number */startIndex) {			var _this = this,				el = _this.el,				options = _this.options,				ownerDocument = el.ownerDocument,				dragStartFn;			if (target && !dragEl && (target.parentNode === el)) {				tapEvt = evt;				rootEl = el;				dragEl = target;				parentEl = dragEl.parentNode;				nextEl = dragEl.nextSibling;				lastDownEl = target;				activeGroup = options.group;				oldIndex = startIndex;				this._lastX = (touch || evt).clientX;				this._lastY = (touch || evt).clientY;				dragEl.style['will-change'] = 'all';				dragStartFn = function () {					// Delayed drag has been triggered					// we can re-enable the events: touchmove/mousemove					_this._disableDelayedDrag();					// Make the element draggable					dragEl.draggable = _this.nativeDraggable;					// Chosen item					_toggleClass(dragEl, options.chosenClass, true);					// Bind the events: dragstart/dragend					_this._triggerDragStart(evt, touch);					// Drag start event					_dispatchEvent(_this, rootEl, 'choose', dragEl, rootEl, rootEl, oldIndex);				};				// Disable "draggable"				options.ignore.split(',').forEach(function (criteria) {					_find(dragEl, criteria.trim(), _disableDraggable);				});				_on(ownerDocument, 'mouseup', _this._onDrop);				_on(ownerDocument, 'touchend', _this._onDrop);				_on(ownerDocument, 'touchcancel', _this._onDrop);				_on(ownerDocument, 'selectstart', _this);				options.supportPointer && _on(ownerDocument, 'pointercancel', _this._onDrop);				if (options.delay) {					// If the user moves the pointer or let go the click or touch					// before the delay has been reached:					// disable the delayed drag					_on(ownerDocument, 'mouseup', _this._disableDelayedDrag);					_on(ownerDocument, 'touchend', _this._disableDelayedDrag);					_on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);					_on(ownerDocument, 'mousemove', _this._disableDelayedDrag);					_on(ownerDocument, 'touchmove', _this._disableDelayedDrag);					options.supportPointer && _on(ownerDocument, 'pointermove', _this._disableDelayedDrag);					_this._dragStartTimer = setTimeout(dragStartFn, options.delay);				} else {					dragStartFn();				}			}		},		_disableDelayedDrag: function () {			var ownerDocument = this.el.ownerDocument;			clearTimeout(this._dragStartTimer);			_off(ownerDocument, 'mouseup', this._disableDelayedDrag);			_off(ownerDocument, 'touchend', this._disableDelayedDrag);			_off(ownerDocument, 'touchcancel', this._disableDelayedDrag);			_off(ownerDocument, 'mousemove', this._disableDelayedDrag);			_off(ownerDocument, 'touchmove', this._disableDelayedDrag);			_off(ownerDocument, 'pointermove', this._disableDelayedDrag);		},		_triggerDragStart: function (/** Event */evt, /** Touch */touch) {			touch = touch || (evt.pointerType == 'touch' ? evt : null);			if (touch) {				// Touch device support				tapEvt = {					target: dragEl,					clientX: touch.clientX,					clientY: touch.clientY				};				this._onDragStart(tapEvt, 'touch');			}			else if (!this.nativeDraggable) {				this._onDragStart(tapEvt, true);			}			else {				_on(dragEl, 'dragend', this);				_on(rootEl, 'dragstart', this._onDragStart);			}			try {				if (document.selection) {					// Timeout neccessary for IE9					_nextTick(function () {						document.selection.empty();					});				} else {					window.getSelection().removeAllRanges();				}			} catch (err) {			}		},		_dragStarted: function () {			if (rootEl && dragEl) {				var options = this.options;				// Apply effect				_toggleClass(dragEl, options.ghostClass, true);				_toggleClass(dragEl, options.dragClass, false);				KvSortable.active = this;				// Drag start event				_dispatchEvent(this, rootEl, 'start', dragEl, rootEl, rootEl, oldIndex);			} else {				this._nulling();			}		},		_emulateDragOver: function () {			if (touchEvt) {				if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) {					return;				}				this._lastX = touchEvt.clientX;				this._lastY = touchEvt.clientY;				if (!supportCssPointerEvents) {					_css(ghostEl, 'display', 'none');				}				var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY);				var parent = target;				var i = touchDragOverListeners.length;				if (target && target.shadowRoot) {					target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY);					parent = target;				}				if (parent) {					do {						if (parent[expando]) {							while (i--) {								touchDragOverListeners[i]({									clientX: touchEvt.clientX,									clientY: touchEvt.clientY,									target: target,									rootEl: parent								});							}							break;						}						target = parent; // store last element					}					/* jshint boss:true */					while (parent = parent.parentNode);				}				if (!supportCssPointerEvents) {					_css(ghostEl, 'display', '');				}			}		},		_onTouchMove: function (/**TouchEvent*/evt) {			if (tapEvt) {				var	options = this.options,					fallbackTolerance = options.fallbackTolerance,					fallbackOffset = options.fallbackOffset,					touch = evt.touches ? evt.touches[0] : evt,					dx = (touch.clientX - tapEvt.clientX) + fallbackOffset.x,					dy = (touch.clientY - tapEvt.clientY) + fallbackOffset.y,					translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)';				// only set the status to dragging, when we are actually dragging				if (!KvSortable.active) {					if (fallbackTolerance &&						min(abs(touch.clientX - this._lastX), abs(touch.clientY - this._lastY)) < fallbackTolerance					) {						return;					}					this._dragStarted();				}				// as well as creating the ghost element on the document body				this._appendGhost();				moved = true;				touchEvt = touch;				_css(ghostEl, 'webkitTransform', translate3d);				_css(ghostEl, 'mozTransform', translate3d);				_css(ghostEl, 'msTransform', translate3d);				_css(ghostEl, 'transform', translate3d);				evt.preventDefault();			}		},		_appendGhost: function () {			if (!ghostEl) {				var rect = dragEl.getBoundingClientRect(),					css = _css(dragEl),					options = this.options,					ghostRect;				ghostEl = dragEl.cloneNode(true);				_toggleClass(ghostEl, options.ghostClass, false);				_toggleClass(ghostEl, options.fallbackClass, true);				_toggleClass(ghostEl, options.dragClass, true);				_css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10));				_css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10));				_css(ghostEl, 'width', rect.width);				_css(ghostEl, 'height', rect.height);				_css(ghostEl, 'opacity', '0.8');				_css(ghostEl, 'position', 'fixed');				_css(ghostEl, 'zIndex', '100000');				_css(ghostEl, 'pointerEvents', 'none');				options.fallbackOnBody && document.body.appendChild(ghostEl) || rootEl.appendChild(ghostEl);				// Fixing dimensions.				ghostRect = ghostEl.getBoundingClientRect();				_css(ghostEl, 'width', rect.width * 2 - ghostRect.width);				_css(ghostEl, 'height', rect.height * 2 - ghostRect.height);			}		},		_onDragStart: function (/**Event*/evt, /**boolean*/useFallback) {			var _this = this;			var dataTransfer = evt.dataTransfer;			var options = _this.options;			_this._offUpEvents();			if (activeGroup.checkPull(_this, _this, dragEl, evt)) {				cloneEl = _clone(dragEl);				cloneEl.draggable = false;				cloneEl.style['will-change'] = '';				_css(cloneEl, 'display', 'none');				_toggleClass(cloneEl, _this.options.chosenClass, false);				// #1143: IFrame support workaround				_this._cloneId = _nextTick(function () {					rootEl.insertBefore(cloneEl, dragEl);					_dispatchEvent(_this, rootEl, 'clone', dragEl);				});			}			_toggleClass(dragEl, options.dragClass, true);			if (useFallback) {				if (useFallback === 'touch') {					// Bind touch events					_on(document, 'touchmove', _this._onTouchMove);					_on(document, 'touchend', _this._onDrop);					_on(document, 'touchcancel', _this._onDrop);					if (options.supportPointer) {						_on(document, 'pointermove', _this._onTouchMove);						_on(document, 'pointerup', _this._onDrop);					}				} else {					// Old brwoser					_on(document, 'mousemove', _this._onTouchMove);					_on(document, 'mouseup', _this._onDrop);				}				_this._loopId = setInterval(_this._emulateDragOver, 50);			}			else {				if (dataTransfer) {					dataTransfer.effectAllowed = 'move';					options.setData && options.setData.call(_this, dataTransfer, dragEl);				}				_on(document, 'drop', _this);				// #1143: Бывает элемент с IFrame внутри блокирует `drop`,				// поэтому если вызвался `mouseover`, значит надо отменять весь d'n'd.				// Breaking Chrome 62+				// _on(document, 'mouseover', _this);				_this._dragStartId = _nextTick(_this._dragStarted);			}		},		_onDragOver: function (/**Event*/evt) {			var el = this.el,				target,				dragRect,				targetRect,				revert,				options = this.options,				group = options.group,				activeKvSortable = KvSortable.active,				isOwner = (activeGroup === group),				isMovingBetweenKvSortable = false,				canSort = options.sort;			if (evt.preventDefault !== void 0) {				evt.preventDefault();				!options.dragoverBubble && evt.stopPropagation();			}			if (dragEl.animated) {				return;			}			moved = true;			if (activeKvSortable && !options.disabled &&				(isOwner					? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list					: (						putKvSortable === this ||						(							(activeKvSortable.lastPullMode = activeGroup.checkPull(this, activeKvSortable, dragEl, evt)) &&							group.checkPut(this, activeKvSortable, dragEl, evt)						)					)				) &&				(evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback			) {				// Smart auto-scrolling				_autoScroll(evt, options, this.el);				if (_silent) {					return;				}				target = _closest(evt.target, options.draggable, el);				dragRect = dragEl.getBoundingClientRect();				if (putKvSortable !== this) {					putKvSortable = this;					isMovingBetweenKvSortable = true;				}				if (revert) {					_cloneHide(activeKvSortable, true);					parentEl = rootEl; // actualization					if (cloneEl || nextEl) {						rootEl.insertBefore(dragEl, cloneEl || nextEl);					}					else if (!canSort) {						rootEl.appendChild(dragEl);					}					return;				}				if ((el.children.length === 0) || (el.children[0] === ghostEl) ||					(el === evt.target) && (_ghostIsLast(el, evt))				) {					//assign target only if condition is true					if (el.children.length !== 0 && el.children[0] !== ghostEl && el === evt.target) {						target = el.lastElementChild;					}					if (target) {						if (target.animated) {							return;						}						targetRect = target.getBoundingClientRect();					}					_cloneHide(activeKvSortable, isOwner);					if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt) !== false) {						if (!dragEl.contains(el)) {							el.appendChild(dragEl);							parentEl = el; // actualization						}						this._animate(dragRect, dragEl);						target && this._animate(targetRect, target);					}				}				else if (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0)) {					if (lastEl !== target) {						lastEl = target;						lastCSS = _css(target);						lastParentCSS = _css(target.parentNode);					}					targetRect = target.getBoundingClientRect();					var width = targetRect.right - targetRect.left,						height = targetRect.bottom - targetRect.top,						floating = R_FLOAT.test(lastCSS.cssFloat + lastCSS.display)							|| (lastParentCSS.display == 'flex' && lastParentCSS['flex-direction'].indexOf('row') === 0),						isWide = (target.offsetWidth > dragEl.offsetWidth),						isLong = (target.offsetHeight > dragEl.offsetHeight),						halfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5,						nextSibling = target.nextElementSibling,						after = false					;					if (floating) {						var elTop = dragEl.offsetTop,							tgTop = target.offsetTop;						if (elTop === tgTop) {							after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide;						}						else if (target.previousElementSibling === dragEl || dragEl.previousElementSibling === target) {							after = (evt.clientY - targetRect.top) / height > 0.5;						} else {							after = tgTop > elTop;						}						} else if (!isMovingBetweenKvSortable) {						after = (nextSibling !== dragEl) && !isLong || halfway && isLong;					}					var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after);					if (moveVector !== false) {						if (moveVector === 1 || moveVector === -1) {							after = (moveVector === 1);						}						_silent = true;						setTimeout(_unsilent, 30);						_cloneHide(activeKvSortable, isOwner);						if (!dragEl.contains(el)) {							if (after && !nextSibling) {								el.appendChild(dragEl);							} else {								target.parentNode.insertBefore(dragEl, after ? nextSibling : target);							}						}						parentEl = dragEl.parentNode; // actualization						this._animate(dragRect, dragEl);						this._animate(targetRect, target);					}				}			}		},		_animate: function (prevRect, target) {			var ms = this.options.animation;			if (ms) {				var currentRect = target.getBoundingClientRect();				if (prevRect.nodeType === 1) {					prevRect = prevRect.getBoundingClientRect();				}				_css(target, 'transition', 'none');				_css(target, 'transform', 'translate3d('					+ (prevRect.left - currentRect.left) + 'px,'					+ (prevRect.top - currentRect.top) + 'px,0)'				);				target.offsetWidth; // repaint				_css(target, 'transition', 'all ' + ms + 'ms');				_css(target, 'transform', 'translate3d(0,0,0)');				clearTimeout(target.animated);				target.animated = setTimeout(function () {					_css(target, 'transition', '');					_css(target, 'transform', '');					target.animated = false;				}, ms);			}		},		_offUpEvents: function () {			var ownerDocument = this.el.ownerDocument;			_off(document, 'touchmove', this._onTouchMove);			_off(document, 'pointermove', this._onTouchMove);			_off(ownerDocument, 'mouseup', this._onDrop);			_off(ownerDocument, 'touchend', this._onDrop);			_off(ownerDocument, 'pointerup', this._onDrop);			_off(ownerDocument, 'touchcancel', this._onDrop);			_off(ownerDocument, 'pointercancel', this._onDrop);			_off(ownerDocument, 'selectstart', this);		},		_onDrop: function (/**Event*/evt) {			var el = this.el,				options = this.options;			clearInterval(this._loopId);			clearInterval(autoScroll.pid);			clearTimeout(this._dragStartTimer);			_cancelNextTick(this._cloneId);			_cancelNextTick(this._dragStartId);			// Unbind events			_off(document, 'mouseover', this);			_off(document, 'mousemove', this._onTouchMove);			if (this.nativeDraggable) {				_off(document, 'drop', this);				_off(el, 'dragstart', this._onDragStart);			}			this._offUpEvents();			if (evt) {				if (moved) {					evt.preventDefault();					!options.dropBubble && evt.stopPropagation();				}				ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl);				if (rootEl === parentEl || KvSortable.active.lastPullMode !== 'clone') {					// Remove clone					cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl);				}				if (dragEl) {					if (this.nativeDraggable) {						_off(dragEl, 'dragend', this);					}					_disableDraggable(dragEl);					dragEl.style['will-change'] = '';					// Remove class's					_toggleClass(dragEl, this.options.ghostClass, false);					_toggleClass(dragEl, this.options.chosenClass, false);					// Drag stop event					_dispatchEvent(this, rootEl, 'unchoose', dragEl, parentEl, rootEl, oldIndex);					if (rootEl !== parentEl) {						newIndex = _index(dragEl, options.draggable);						if (newIndex >= 0) {							// Add event							_dispatchEvent(null, parentEl, 'add', dragEl, parentEl, rootEl, oldIndex, newIndex);							// Remove event							_dispatchEvent(this, rootEl, 'remove', dragEl, parentEl, rootEl, oldIndex, newIndex);							// drag from one list and drop into another							_dispatchEvent(null, parentEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);							_dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);						}					}					else {						if (dragEl.nextSibling !== nextEl) {							// Get the index of the dragged element within its parent							newIndex = _index(dragEl, options.draggable);							if (newIndex >= 0) {								// drag & drop within the same list								_dispatchEvent(this, rootEl, 'update', dragEl, parentEl, rootEl, oldIndex, newIndex);								_dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);							}						}					}					if (KvSortable.active) {						/* jshint eqnull:true */						if (newIndex == null || newIndex === -1) {							newIndex = oldIndex;						}						_dispatchEvent(this, rootEl, 'end', dragEl, parentEl, rootEl, oldIndex, newIndex);						// Save sorting						this.save();					}				}			}			this._nulling();		},		_nulling: function() {			rootEl =			dragEl =			parentEl =			ghostEl =			nextEl =			cloneEl =			lastDownEl =			scrollEl =			scrollParentEl =			tapEvt =			touchEvt =			moved =			newIndex =			lastEl =			lastCSS =			putKvSortable =			activeGroup =			KvSortable.active = null;			savedInputChecked.forEach(function (el) {				el.checked = true;			});			savedInputChecked.length = 0;		},		handleEvent: function (/**Event*/evt) {			switch (evt.type) {				case 'drop':				case 'dragend':					this._onDrop(evt);					break;				case 'dragover':				case 'dragenter':					if (dragEl) {						this._onDragOver(evt);						_globalDragOver(evt);					}					break;				case 'mouseover':					this._onDrop(evt);					break;				case 'selectstart':					evt.preventDefault();					break;			}		},		/**		 * Serializes the item into an array of string.		 * @returns {String[]}		 */		toArray: function () {			var order = [],				el,				children = this.el.children,				i = 0,				n = children.length,				options = this.options;			for (; i < n; i++) {				el = children[i];				if (_closest(el, options.draggable, this.el)) {					order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));				}			}			return order;		},		/**		 * Sorts the elements according to the array.		 * @param  {String[]}  order  order of the items		 */		sort: function (order) {			var items = {}, rootEl = this.el;			this.toArray().forEach(function (id, i) {				var el = rootEl.children[i];				if (_closest(el, this.options.draggable, rootEl)) {					items[id] = el;				}			}, this);			order.forEach(function (id) {				if (items[id]) {					rootEl.removeChild(items[id]);					rootEl.appendChild(items[id]);				}			});		},		/**		 * Save the current sorting		 */		save: function () {			var store = this.options.store;			store && store.set(this);		},		/**		 * 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.		 * @param   {HTMLElement}  el		 * @param   {String}       [selector]  default: `options.draggable`		 * @returns {HTMLElement|null}		 */		closest: function (el, selector) {			return _closest(el, selector || this.options.draggable, this.el);		},		/**		 * Set/get option		 * @param   {string} name		 * @param   {*}      [value]		 * @returns {*}		 */		option: function (name, value) {			var options = this.options;			if (value === void 0) {				return options[name];			} else {				options[name] = value;				if (name === 'group') {					_prepareGroup(options);				}			}		},		/**		 * Destroy		 */		destroy: function () {			var el = this.el;			el[expando] = null;			_off(el, 'mousedown', this._onTapStart);			_off(el, 'touchstart', this._onTapStart);			_off(el, 'pointerdown', this._onTapStart);			if (this.nativeDraggable) {				_off(el, 'dragover', this);				_off(el, 'dragenter', this);			}			// Remove draggable attributes			Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {				el.removeAttribute('draggable');			});			touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1);			this._onDrop();			this.el = el = null;		}	};	function _cloneHide(kvsortable, state) {		if (kvsortable.lastPullMode !== 'clone') {			state = true;		}		if (cloneEl && (cloneEl.state !== state)) {			_css(cloneEl, 'display', state ? 'none' : '');			if (!state) {				if (cloneEl.state) {					if (kvsortable.options.group.revertClone) {						rootEl.insertBefore(cloneEl, nextEl);						kvsortable._animate(dragEl, cloneEl);					} else {						rootEl.insertBefore(cloneEl, dragEl);					}				}			}			cloneEl.state = state;		}	}	function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) {		if (el) {			ctx = ctx || document;			do {				if ((selector === '>*' && el.parentNode === ctx) || _matches(el, selector)) {					return el;				}				/* jshint boss:true */			} while (el = _getParentOrHost(el));		}		return null;	}	function _getParentOrHost(el) {		var parent = el.host;		return (parent && parent.nodeType) ? parent : el.parentNode;	}	function _globalDragOver(/**Event*/evt) {		if (evt.dataTransfer) {			evt.dataTransfer.dropEffect = 'move';		}		evt.preventDefault();	}	function _on(el, event, fn) {		el.addEventListener(event, fn, captureMode);	}	function _off(el, event, fn) {		el.removeEventListener(event, fn, captureMode);	}	function _toggleClass(el, name, state) {		if (el) {			if (el.classList) {				el.classList[state ? 'add' : 'remove'](name);			}			else {				var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');				el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');			}		}	}	function _css(el, prop, val) {		var style = el && el.style;		if (style) {			if (val === void 0) {				if (document.defaultView && document.defaultView.getComputedStyle) {					val = document.defaultView.getComputedStyle(el, '');				}				else if (el.currentStyle) {					val = el.currentStyle;				}				return prop === void 0 ? val : val[prop];			}			else {				if (!(prop in style)) {					prop = '-webkit-' + prop;				}				style[prop] = val + (typeof val === 'string' ? '' : 'px');			}		}	}	function _find(ctx, tagName, iterator) {		if (ctx) {			var list = ctx.getElementsByTagName(tagName), i = 0, n = list.length;			if (iterator) {				for (; i < n; i++) {					iterator(list[i], i);				}			}			return list;		}		return [];	}	function _dispatchEvent(kvsortable, rootEl, name, targetEl, toEl, fromEl, startIndex, newIndex) {		kvsortable = (kvsortable || rootEl[expando]);		var evt = document.createEvent('Event'),			options = kvsortable.options,			onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1);		evt.initEvent(name, true, true);		evt.to = toEl || rootEl;		evt.from = fromEl || rootEl;		evt.item = targetEl || rootEl;		evt.clone = cloneEl;		evt.oldIndex = startIndex;		evt.newIndex = newIndex;		rootEl.dispatchEvent(evt);		if (options[onName]) {			options[onName].call(kvsortable, evt);		}	}	function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvt, willInsertAfter) {		var evt,			kvsortable = fromEl[expando],			onMoveFn = kvsortable.options.onMove,			retVal;		evt = document.createEvent('Event');		evt.initEvent('move', true, true);		evt.to = toEl;		evt.from = fromEl;		evt.dragged = dragEl;		evt.draggedRect = dragRect;		evt.related = targetEl || toEl;		evt.relatedRect = targetRect || toEl.getBoundingClientRect();		evt.willInsertAfter = willInsertAfter;		fromEl.dispatchEvent(evt);		if (onMoveFn) {			retVal = onMoveFn.call(kvsortable, evt, originalEvt);		}		return retVal;	}	function _disableDraggable(el) {		el.draggable = false;	}	function _unsilent() {		_silent = false;	}	/** @returns {HTMLElement|false} */	function _ghostIsLast(el, evt) {		var lastEl = el.lastElementChild,			rect = lastEl.getBoundingClientRect();		// 5 — min delta		// abs — нельзя добавлять, а то глюки при наведении сверху		return (evt.clientY - (rect.top + rect.height) > 5) ||			(evt.clientX - (rect.left + rect.width) > 5);	}	/**	 * Generate id	 * @param   {HTMLElement} el	 * @returns {String}	 * @private	 */	function _generateId(el) {		var str = el.tagName + el.className + el.src + el.href + el.textContent,			i = str.length,			sum = 0;		while (i--) {			sum += str.charCodeAt(i);		}		return sum.toString(36);	}	/**	 * Returns the index of an element within its parent for a selected set of	 * elements	 * @param  {HTMLElement} el	 * @param  {selector} selector	 * @return {number}	 */	function _index(el, selector) {		var index = 0;		if (!el || !el.parentNode) {			return -1;		}		while (el && (el = el.previousElementSibling)) {			if ((el.nodeName.toUpperCase() !== 'TEMPLATE') && (selector === '>*' || _matches(el, selector))) {				index++;			}		}		return index;	}	function _matches(/**HTMLElement*/el, /**String*/selector) {		if (el) {			selector = selector.split('.');			var tag = selector.shift().toUpperCase(),				re = new RegExp('\\s(' + selector.join('|') + ')(?=\\s)', 'g');			return (				(tag === '' || el.nodeName.toUpperCase() == tag) &&				(!selector.length || ((' ' + el.className + ' ').match(re) || []).length == selector.length)			);		}		return false;	}	function _throttle(callback, ms) {		var args, _this;		return function () {			if (args === void 0) {				args = arguments;				_this = this;				setTimeout(function () {					if (args.length === 1) {						callback.call(_this, args[0]);					} else {						callback.apply(_this, args);					}					args = void 0;				}, ms);			}		};	}	function _extend(dst, src) {		if (dst && src) {			for (var key in src) {				if (src.hasOwnProperty(key)) {					dst[key] = src[key];				}			}		}		return dst;	}	function _clone(el) {		if (Polymer && Polymer.dom) {			return Polymer.dom(el).cloneNode(true);		}		else if ($) {			return $(el).clone(true)[0];		}		else {			return el.cloneNode(true);		}	}	function _saveInputCheckedState(root) {		var inputs = root.getElementsByTagName('input');		var idx = inputs.length;		while (idx--) {			var el = inputs[idx];			el.checked && savedInputChecked.push(el);		}	}	function _nextTick(fn) {		return setTimeout(fn, 0);	}	function _cancelNextTick(id) {		return clearTimeout(id);	}	// Fixed #973:	_on(document, 'touchmove', function (evt) {		if (KvSortable.active) {			evt.preventDefault();		}	});	// Export utils	KvSortable.utils = {		on: _on,		off: _off,		css: _css,		find: _find,		is: function (el, selector) {			return !!_closest(el, selector, el);		},		extend: _extend,		throttle: _throttle,		closest: _closest,		toggleClass: _toggleClass,		clone: _clone,		index: _index,		nextTick: _nextTick,		cancelNextTick: _cancelNextTick	};	/**	 * Create kvsortable instance	 * @param {HTMLElement}  el	 * @param {Object}      [options]	 */	KvSortable.create = function (el, options) {		return new KvSortable(el, options);	};	// Export	KvSortable.version = '1.7.0';	return KvSortable;});/** * jQuery plugin for KvSortable */(function (factory) {    "use strict";    if (typeof define === "function" && define.amd) {        define(["jquery"], factory);    }    else {        /* jshint sub:true */        factory(jQuery);    }})(function ($) {    "use strict";    $.fn.kvsortable = function (options) {        var retVal,            args = arguments;        this.each(function () {            var $el = $(this), kvsortable = $el.data('kvsortable');            if (!kvsortable && (options instanceof Object || !options)) {                kvsortable = new KvSortable(this, options);                $el.data('kvsortable', kvsortable);            }            if (kvsortable) {                if (options === 'widget') {                    retVal = kvsortable;                }                else if (options === 'destroy') {                    kvsortable.destroy();                    $el.removeData('kvsortable');                }                else if (typeof kvsortable[options] === 'function') {                    retVal = kvsortable[options].apply(kvsortable, [].slice.call(args, 1));                }                else if (options in kvsortable.options) {                    retVal = kvsortable.option.apply(kvsortable, args);                }            }        });        return (retVal === void 0) ? this : retVal;    };});
 |