/**! 
 | 
 * KvSortable 
 | 
 * @author    RubaXa   <trash@rubaxa.org> 
 | 
 * @license MIT 
 | 
 * 
 | 
 * Changed kvsortable plugin naming to prevent conflict with JQuery UI KvSortable 
 | 
 * @author Kartik Visweswaran 
 | 
 */ 
 | 
(function (factory) { 
 | 
    "use strict"; 
 | 
  
 | 
    if (typeof define === "function" && define.amd) { 
 | 
        define(factory); 
 | 
    } 
 | 
    else if (typeof module != "undefined" && typeof module.exports != "undefined") { 
 | 
        module.exports = factory(); 
 | 
    } 
 | 
    else if (typeof Package !== "undefined") { 
 | 
        KvSortable = factory();  // export for Meteor.js 
 | 
    } 
 | 
    else { 
 | 
        /* jshint sub:true */ 
 | 
        window["KvSortable"] = factory(); 
 | 
    } 
 | 
})(function () { 
 | 
    "use strict"; 
 | 
     
 | 
    if (typeof window === "undefined" || typeof window.document == "undefined") { 
 | 
        return function() { 
 | 
            throw new Error( "sortable.js requires a window with a document" ); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    var dragEl, 
 | 
        parentEl, 
 | 
        ghostEl, 
 | 
        cloneEl, 
 | 
        rootEl, 
 | 
        nextEl, 
 | 
  
 | 
        scrollEl, 
 | 
        scrollParentEl, 
 | 
  
 | 
        lastEl, 
 | 
        lastCSS, 
 | 
        lastParentCSS, 
 | 
  
 | 
        oldIndex, 
 | 
        newIndex, 
 | 
  
 | 
        activeGroup, 
 | 
        autoScroll = {}, 
 | 
  
 | 
        tapEvt, 
 | 
        touchEvt, 
 | 
  
 | 
        moved, 
 | 
  
 | 
        /** @const */ 
 | 
        RSPACE = /\s+/g, 
 | 
  
 | 
        expando = 'KvSortable' + (new Date).getTime(), 
 | 
  
 | 
        win = window, 
 | 
        document = win.document, 
 | 
        parseInt = win.parseInt, 
 | 
  
 | 
        supportDraggable = !!('draggable' in document.createElement('div')), 
 | 
        supportCssPointerEvents = (function (el) { 
 | 
            el = document.createElement('x'); 
 | 
            el.style.cssText = 'pointer-events:auto'; 
 | 
            return el.style.pointerEvents === 'auto'; 
 | 
        })(), 
 | 
  
 | 
        _silent = false, 
 | 
  
 | 
        abs = Math.abs, 
 | 
        slice = [].slice, 
 | 
  
 | 
        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 el, 
 | 
                    rect, 
 | 
                    sens = options.scrollSensitivity, 
 | 
                    speed = options.scrollSpeed, 
 | 
  
 | 
                    x = evt.clientX, 
 | 
                    y = evt.clientY, 
 | 
  
 | 
                    winWidth = window.innerWidth, 
 | 
                    winHeight = window.innerHeight, 
 | 
  
 | 
                    vx, 
 | 
                    vy 
 | 
                ; 
 | 
  
 | 
                // Delect scrollEl 
 | 
                if (scrollParentEl !== rootEl) { 
 | 
                    scrollEl = options.scroll; 
 | 
                    scrollParentEl = rootEl; 
 | 
  
 | 
                    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 () { 
 | 
                            if (el === win) { 
 | 
                                win.scrollTo(win.pageXOffset + vx * speed, win.pageYOffset + vy * speed); 
 | 
                            } else { 
 | 
                                vy && (el.scrollTop += vy * speed); 
 | 
                                vx && (el.scrollLeft += vx * speed); 
 | 
                            } 
 | 
                        }, 24); 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
        }, 30), 
 | 
  
 | 
        _prepareGroup = function (options) { 
 | 
            var group = options.group; 
 | 
  
 | 
            if (!group || typeof group != 'object') { 
 | 
                group = options.group = {name: group}; 
 | 
            } 
 | 
  
 | 
            ['pull', 'put'].forEach(function (key) { 
 | 
                if (!(key in group)) { 
 | 
                    group[key] = true; 
 | 
                } 
 | 
            }); 
 | 
  
 | 
            options.groups = ' ' + group.name + (group.put.join ? ' ' + group.put.join(' ') : '') + ' '; 
 | 
        } 
 | 
    ; 
 | 
  
 | 
  
 | 
  
 | 
    /** 
 | 
     * @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', 
 | 
            ignore: 'a, img', 
 | 
            filter: null, 
 | 
            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 
 | 
        }; 
 | 
  
 | 
  
 | 
        // 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) === '_') { 
 | 
                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); 
 | 
  
 | 
        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, 
 | 
                type = evt.type, 
 | 
                touch = evt.touches && evt.touches[0], 
 | 
                target = (touch || evt).target, 
 | 
                originalTarget = target, 
 | 
                filter = options.filter; 
 | 
  
 | 
  
 | 
            if (type === 'mousedown' && evt.button !== 0 || options.disabled) { 
 | 
                return; // only left button or enabled 
 | 
            } 
 | 
  
 | 
            target = _closest(target, options.draggable, el); 
 | 
  
 | 
            if (!target) { 
 | 
                return; 
 | 
            } 
 | 
  
 | 
            // get the index of the dragged element within its parent 
 | 
            oldIndex = _index(target, options.draggable); 
 | 
  
 | 
            // Check filter 
 | 
            if (typeof filter === 'function') { 
 | 
                if (filter.call(this, evt, target, this)) { 
 | 
                    _dispatchEvent(_this, originalTarget, 'filter', target, el, oldIndex); 
 | 
                    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, oldIndex); 
 | 
                        return true; 
 | 
                    } 
 | 
                }); 
 | 
  
 | 
                if (filter) { 
 | 
                    evt.preventDefault(); 
 | 
                    return; // cancel dnd 
 | 
                } 
 | 
            } 
 | 
  
 | 
  
 | 
            if (options.handle && !_closest(originalTarget, options.handle, el)) { 
 | 
                return; 
 | 
            } 
 | 
  
 | 
  
 | 
            // Prepare `dragstart` 
 | 
            this._prepareDragStart(evt, touch, target); 
 | 
        }, 
 | 
  
 | 
        _prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target) { 
 | 
            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; 
 | 
                activeGroup = options.group; 
 | 
  
 | 
                dragStartFn = function () { 
 | 
                    // Delayed drag has been triggered 
 | 
                    // we can re-enable the events: touchmove/mousemove 
 | 
                    _this._disableDelayedDrag(); 
 | 
  
 | 
                    // Make the element draggable 
 | 
                    dragEl.draggable = true; 
 | 
  
 | 
                    // Chosen item 
 | 
                    _toggleClass(dragEl, _this.options.chosenClass, true); 
 | 
  
 | 
                    // Bind the events: dragstart/dragend 
 | 
                    _this._triggerDragStart(touch); 
 | 
                }; 
 | 
  
 | 
                // 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); 
 | 
  
 | 
                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); 
 | 
  
 | 
                    _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); 
 | 
        }, 
 | 
  
 | 
        _triggerDragStart: function (/** Touch */touch) { 
 | 
            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) { 
 | 
                    document.selection.empty(); 
 | 
                } else { 
 | 
                    window.getSelection().removeAllRanges(); 
 | 
                } 
 | 
            } catch (err) { 
 | 
            } 
 | 
        }, 
 | 
  
 | 
        _dragStarted: function () { 
 | 
            if (rootEl && dragEl) { 
 | 
                // Apply effect 
 | 
                _toggleClass(dragEl, this.options.ghostClass, true); 
 | 
  
 | 
                KvSortable.active = this; 
 | 
  
 | 
                // Drag start event 
 | 
                _dispatchEvent(this, rootEl, 'start', dragEl, rootEl, oldIndex); 
 | 
            } 
 | 
        }, 
 | 
  
 | 
        _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), 
 | 
                    parent = target, 
 | 
                    groupName = ' ' + this.options.group.name + '', 
 | 
                    i = touchDragOverListeners.length; 
 | 
  
 | 
                if (parent) { 
 | 
                    do { 
 | 
                        if (parent[expando] && parent[expando].options.groups.indexOf(groupName) > -1) { 
 | 
                            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) { 
 | 
                // only set the status to dragging, when we are actually dragging 
 | 
                if (!KvSortable.active) { 
 | 
                    this._dragStarted(); 
 | 
                } 
 | 
  
 | 
                // as well as creating the ghost element on the document body 
 | 
                this._appendGhost(); 
 | 
  
 | 
                var touch = evt.touches ? evt.touches[0] : evt, 
 | 
                    dx = touch.clientX - tapEvt.clientX, 
 | 
                    dy = touch.clientY - tapEvt.clientY, 
 | 
                    translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)'; 
 | 
  
 | 
                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); 
 | 
  
 | 
                _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 dataTransfer = evt.dataTransfer, 
 | 
                options = this.options; 
 | 
  
 | 
            this._offUpEvents(); 
 | 
  
 | 
            if (activeGroup.pull == 'clone') { 
 | 
                cloneEl = dragEl.cloneNode(true); 
 | 
                _css(cloneEl, 'display', 'none'); 
 | 
                rootEl.insertBefore(cloneEl, dragEl); 
 | 
            } 
 | 
  
 | 
            if (useFallback) { 
 | 
  
 | 
                if (useFallback === 'touch') { 
 | 
                    // Bind touch events 
 | 
                    _on(document, 'touchmove', this._onTouchMove); 
 | 
                    _on(document, 'touchend', this._onDrop); 
 | 
                    _on(document, 'touchcancel', 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); 
 | 
                setTimeout(this._dragStarted, 0); 
 | 
            } 
 | 
        }, 
 | 
  
 | 
        _onDragOver: function (/**Event*/evt) { 
 | 
            var el = this.el, 
 | 
                target, 
 | 
                dragRect, 
 | 
                revert, 
 | 
                options = this.options, 
 | 
                group = options.group, 
 | 
                groupPut = group.put, 
 | 
                isOwner = (activeGroup === group), 
 | 
                canSort = options.sort; 
 | 
  
 | 
            if (evt.preventDefault !== void 0) { 
 | 
                evt.preventDefault(); 
 | 
                !options.dragoverBubble && evt.stopPropagation(); 
 | 
            } 
 | 
  
 | 
            moved = true; 
 | 
  
 | 
            if (activeGroup && !options.disabled && 
 | 
                (isOwner 
 | 
                    ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list 
 | 
                    : activeGroup.pull && groupPut && ( 
 | 
                        (activeGroup.name === group.name) || // by Name 
 | 
                        (groupPut.indexOf && ~groupPut.indexOf(activeGroup.name)) // by Array 
 | 
                    ) 
 | 
                ) && 
 | 
                (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 (revert) { 
 | 
                    _cloneHide(true); 
 | 
  
 | 
                    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) && (target = _ghostIsLast(el, evt)) 
 | 
                ) { 
 | 
  
 | 
                    if (target) { 
 | 
                        if (target.animated) { 
 | 
                            return; 
 | 
                        } 
 | 
  
 | 
                        targetRect = target.getBoundingClientRect(); 
 | 
                    } 
 | 
  
 | 
                    _cloneHide(isOwner); 
 | 
  
 | 
                    if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect) !== 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); 
 | 
                    } 
 | 
  
 | 
  
 | 
                    var targetRect = target.getBoundingClientRect(), 
 | 
                        width = targetRect.right - targetRect.left, 
 | 
                        height = targetRect.bottom - targetRect.top, 
 | 
                        floating = /left|right|inline/.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, 
 | 
                        moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect), 
 | 
                        after 
 | 
                    ; 
 | 
  
 | 
                    if (moveVector !== false) { 
 | 
                        _silent = true; 
 | 
                        setTimeout(_unsilent, 30); 
 | 
  
 | 
                        _cloneHide(isOwner); 
 | 
  
 | 
                        if (moveVector === 1 || moveVector === -1) { 
 | 
                            after = (moveVector === 1); 
 | 
                        } 
 | 
                        else if (floating) { 
 | 
                            var elTop = dragEl.offsetTop, 
 | 
                                tgTop = target.offsetTop; 
 | 
  
 | 
                            if (elTop === tgTop) { 
 | 
                                after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide; 
 | 
                            } else { 
 | 
                                after = tgTop > elTop; 
 | 
                            } 
 | 
                        } else { 
 | 
                            after = (nextSibling !== dragEl) && !isLong || halfway && isLong; 
 | 
                        } 
 | 
  
 | 
                        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(); 
 | 
  
 | 
                _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(ownerDocument, 'mouseup', this._onDrop); 
 | 
            _off(ownerDocument, 'touchend', this._onDrop); 
 | 
            _off(ownerDocument, 'touchcancel', this._onDrop); 
 | 
        }, 
 | 
  
 | 
        _onDrop: function (/**Event*/evt) { 
 | 
            var el = this.el, 
 | 
                options = this.options; 
 | 
  
 | 
            clearInterval(this._loopId); 
 | 
            clearInterval(autoScroll.pid); 
 | 
            clearTimeout(this._dragStartTimer); 
 | 
  
 | 
            // Unbind events 
 | 
            _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.removeChild(ghostEl); 
 | 
  
 | 
                if (dragEl) { 
 | 
                    if (this.nativeDraggable) { 
 | 
                        _off(dragEl, 'dragend', this); 
 | 
                    } 
 | 
  
 | 
                    _disableDraggable(dragEl); 
 | 
  
 | 
                    // Remove class's 
 | 
                    _toggleClass(dragEl, this.options.ghostClass, false); 
 | 
                    _toggleClass(dragEl, this.options.chosenClass, false); 
 | 
  
 | 
                    if (rootEl !== parentEl) { 
 | 
                        newIndex = _index(dragEl, options.draggable); 
 | 
  
 | 
                        if (newIndex >= 0) { 
 | 
                            // drag from one list and drop into another 
 | 
                            _dispatchEvent(null, parentEl, 'sort', dragEl, rootEl, oldIndex, newIndex); 
 | 
                            _dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex); 
 | 
  
 | 
                            // Add event 
 | 
                            _dispatchEvent(null, parentEl, 'add', dragEl, rootEl, oldIndex, newIndex); 
 | 
  
 | 
                            // Remove event 
 | 
                            _dispatchEvent(this, rootEl, 'remove', dragEl, rootEl, oldIndex, newIndex); 
 | 
                        } 
 | 
                    } 
 | 
                    else { 
 | 
                        // Remove clone 
 | 
                        cloneEl && cloneEl.parentNode.removeChild(cloneEl); 
 | 
  
 | 
                        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, rootEl, oldIndex, newIndex); 
 | 
                                _dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex); 
 | 
                            } 
 | 
                        } 
 | 
                    } 
 | 
  
 | 
                    if (KvSortable.active) { 
 | 
                        if (newIndex === null || newIndex === -1) { 
 | 
                            newIndex = oldIndex; 
 | 
                        } 
 | 
  
 | 
                        _dispatchEvent(this, rootEl, 'end', dragEl, rootEl, oldIndex, newIndex); 
 | 
  
 | 
                        // Save sorting 
 | 
                        this.save(); 
 | 
                    } 
 | 
                } 
 | 
  
 | 
            } 
 | 
            this._nulling(); 
 | 
        }, 
 | 
  
 | 
        _nulling: function() { 
 | 
            // Nulling 
 | 
            rootEl = 
 | 
            dragEl = 
 | 
            parentEl = 
 | 
            ghostEl = 
 | 
            nextEl = 
 | 
            cloneEl = 
 | 
  
 | 
            scrollEl = 
 | 
            scrollParentEl = 
 | 
  
 | 
            tapEvt = 
 | 
            touchEvt = 
 | 
  
 | 
            moved = 
 | 
            newIndex = 
 | 
  
 | 
            lastEl = 
 | 
            lastCSS = 
 | 
  
 | 
            activeGroup = 
 | 
            KvSortable.active = null; 
 | 
        }, 
 | 
  
 | 
        handleEvent: function (/**Event*/evt) { 
 | 
            var type = evt.type; 
 | 
  
 | 
            if (type === 'dragover' || type === 'dragenter') { 
 | 
                if (dragEl) { 
 | 
                    this._onDragOver(evt); 
 | 
                    _globalDragOver(evt); 
 | 
                } 
 | 
            } 
 | 
            else if (type === 'drop' || type === 'dragend') { 
 | 
                this._onDrop(evt); 
 | 
            } 
 | 
        }, 
 | 
  
 | 
  
 | 
        /** 
 | 
         * 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); 
 | 
  
 | 
            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(state) { 
 | 
        if (cloneEl && (cloneEl.state !== state)) { 
 | 
            _css(cloneEl, 'display', state ? 'none' : ''); 
 | 
            !state && cloneEl.state && 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; 
 | 
                } 
 | 
            } 
 | 
            while (el !== ctx && (el = el.parentNode)); 
 | 
        } 
 | 
  
 | 
        return null; 
 | 
    } 
 | 
  
 | 
  
 | 
    function _globalDragOver(/**Event*/evt) { 
 | 
        if (evt.dataTransfer) { 
 | 
            evt.dataTransfer.dropEffect = 'move'; 
 | 
        } 
 | 
        evt.preventDefault(); 
 | 
    } 
 | 
  
 | 
  
 | 
    function _on(el, event, fn) { 
 | 
        el.addEventListener(event, fn, false); 
 | 
    } 
 | 
  
 | 
  
 | 
    function _off(el, event, fn) { 
 | 
        el.removeEventListener(event, fn, false); 
 | 
    } 
 | 
  
 | 
  
 | 
    function _toggleClass(el, name, state) { 
 | 
        if (el) { 
 | 
            if (el.classList) { 
 | 
                el.classList[state ? 'add' : 'remove'](name); 
 | 
            } 
 | 
            else { 
 | 
                var className = (' ' + el.className + ' ').replace(RSPACE, ' ').replace(' ' + name + ' ', ' '); 
 | 
                el.className = (className + (state ? ' ' + name : '')).replace(RSPACE, ' '); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
  
 | 
    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, fromEl, startIndex, newIndex) { 
 | 
        var evt = document.createEvent('Event'), 
 | 
            options = (kvsortable || rootEl[expando]).options, 
 | 
            onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1); 
 | 
  
 | 
        evt.initEvent(name, true, true); 
 | 
  
 | 
        evt.to = 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) { 
 | 
        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(); 
 | 
  
 | 
        fromEl.dispatchEvent(evt); 
 | 
  
 | 
        if (onMoveFn) { 
 | 
            retVal = onMoveFn.call(kvsortable, evt); 
 | 
        } 
 | 
  
 | 
        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(); 
 | 
  
 | 
        return ((evt.clientY - (rect.top + rect.height) > 5) || (evt.clientX - (rect.right + rect.width) > 5)) && lastEl; // min delta 
 | 
    } 
 | 
  
 | 
  
 | 
    /** 
 | 
     * 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' 
 | 
                    && _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; 
 | 
    } 
 | 
  
 | 
  
 | 
    // 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, 
 | 
        index: _index 
 | 
    }; 
 | 
  
 | 
  
 | 
    /** 
 | 
     * Create kvsortable instance 
 | 
     * @param {HTMLElement}  el 
 | 
     * @param {Object}      [options] 
 | 
     */ 
 | 
    KvSortable.create = function (el, options) { 
 | 
        return new KvSortable(el, options); 
 | 
    }; 
 | 
  
 | 
  
 | 
    // Export 
 | 
    KvSortable.version = '1.4.2'; 
 | 
    return KvSortable; 
 | 
}); 
 | 
/** 
 | 
 * jQuery plugin for KvSortable 
 | 
 * @author    RubaXa   <trash@rubaxa.org> 
 | 
 * @license MIT 
 | 
 */ 
 | 
(function (factory) { 
 | 
    "use strict"; 
 | 
  
 | 
    if (typeof define === "function" && define.amd) { 
 | 
        define(["jquery"], factory); 
 | 
    } 
 | 
    else { 
 | 
        /* jshint sub:true */ 
 | 
        factory(jQuery); 
 | 
    } 
 | 
})(function ($) { 
 | 
    "use strict"; 
 | 
  
 | 
  
 | 
    /* CODE */ 
 | 
  
 | 
  
 | 
    /** 
 | 
     * jQuery plugin for KvSortable 
 | 
     * @param   {Object|String} options 
 | 
     * @param   {..*}           [args] 
 | 
     * @returns {jQuery|*} 
 | 
     */ 
 | 
    $.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') { 
 | 
                    return 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; 
 | 
    }; 
 | 
}); 
 |