Вход Регистрация
Файл: templates/backend/default/assets/plugins/jquery-nestable/jquery.nestable.js
Строк: 483
<?php
/*!
 * Nestable jQuery Plugin - Copyright (c) 2012 David Bushell - http://dbushell.com/
 * Dual-licensed under the BSD or MIT licenses
 */
;(function($, window, document, undefined)
{
    var 
hasTouch = 'ontouchstart' in window;

    
/**
     * Detect CSS pointer-events property
     * events are normally disabled on the dragging element to avoid conflicts
     * https://github.com/ausi/Feature-detection-technique-for-pointer-events/blob/master/modernizr-pointerevents.js
     */
    
var hasPointerEvents = (function()
    {
        var 
el    = document.createElement('div'),
            
docEl = document.documentElement;
        if (!(
'pointerEvents' in el.style)) {
            return 
false;
        }
        
el.style.pointerEvents = 'auto';
        
el.style.pointerEvents = 'x';
        
docEl.appendChild(el);
        var 
supports = window.getComputedStyle && window.getComputedStyle(el, '').pointerEvents === 'auto';
        
docEl.removeChild(el);
        return !!
supports;
    })();

    var 
eStart  = hasTouch ? 'touchstart'  : 'mousedown',
        
eMove   = hasTouch ? 'touchmove'   : 'mousemove',
        
eEnd    = hasTouch ? 'touchend'    : 'mouseup';
        
eCancel = hasTouch ? 'touchcancel' : 'mouseup';

    var 
defaults = {
            
listNodeName    : 'ol',
            
itemNodeName    : 'li',
            
rootClass       : 'dd',
            
listClass       : 'dd-list',
            
itemClass       : 'dd-item',
            
dragClass       : 'dd-dragel',
            
handleClass     : 'dd-handle',
            
collapsedClass  : 'dd-collapsed',
            
placeClass      : 'dd-placeholder',
            
noDragClass     : 'dd-nodrag',
            
emptyClass      : 'dd-empty',
            
expandBtnHTML   : '<button data-action="expand" type="button">Expand</button>',
            
collapseBtnHTML : '<button data-action="collapse" type="button">Collapse</button>',
            
group           : 0,
            
maxDepth        : 5,
            
threshold       : 20
        
};

    function 
Plugin(element, options)
    {
        
this.w  = $(window);
        
this.el = $(element);
        
this.options = $.extend({}, defaults, options);
        
this.init();
    }

    
Plugin.prototype = {

        
init: function()
        {
            var list = 
this;

            list.
reset();

            list.
el.data('nestable-group', this.options.group);

            list.
placeEl = $('<div class="' + list.options.placeClass + '"/>');

            $.
each(this.el.find(list.options.itemNodeName), function(k, el) {
                list.
setParent($(el));
            });

            list.
el.on('click', 'button', function(e) {
                if (list.
dragEl || (!hasTouch && e.button !== 0)) {
                    return;
                }
                var 
target = $(e.currentTarget),
                    
action = target.data('action'),
                    
item   = target.parent(list.options.itemNodeName);
                if (
action === 'collapse') {
                    list.
collapseItem(item);
                }
                if (
action === 'expand') {
                    list.
expandItem(item);
                }
            });

            var 
onStartEvent = function(e)
            {
                var 
handle = $(e.target);
                if (!
handle.hasClass(list.options.handleClass)) {
                    if (
handle.closest('.' + list.options.noDragClass).length) {
                        return;
                    }
                    
handle = handle.closest('.' + list.options.handleClass);
                }
                if (!
handle.length || list.dragEl || (!hasTouch && e.button !== 0) || (hasTouch && e.touches.length !== 1)) {
                    return;
                }
                
e.preventDefault();
                list.
dragStart(hasTouch ? e.touches[0] : e);
            };

            var 
onMoveEvent = function(e)
            {
                if (list.
dragEl) {
                    
e.preventDefault();
                    list.
dragMove(hasTouch ? e.touches[0] : e);
                }
            };

            var 
onEndEvent = function(e)
            {
                if (list.
dragEl) {
                    
e.preventDefault();
                    list.
dragStop(hasTouch ? e.touches[0] : e);
                }
            };

            if (
hasTouch) {
                list.
el[0].addEventListener(eStart, onStartEvent, false);
                
window.addEventListener(eMove, onMoveEvent, false);
                
window.addEventListener(eEnd, onEndEvent, false);
                
window.addEventListener(eCancel, onEndEvent, false);
            } else {
                list.
el.on(eStart, onStartEvent);
                list.
w.on(eMove, onMoveEvent);
                list.
w.on(eEnd, onEndEvent);
            }

        },

        
serialize: function()
        {
            var 
data,
                
depth = 0,
                list  = 
this;
                
step  = function(level, depth)
                {
                    var array = [ ],
                        
items = level.children(list.options.itemNodeName);
                    
items.each(function()
                    {
                        var 
li   = $(this),
                            
item = $.extend({}, li.data()),
                            
sub  = li.children(list.options.listNodeName);
                        if (
sub.length) {
                            
item.children = step(sub, depth + 1);
                        }
                        array.
push(item);
                    });
                    return array;
                };
            
data = step(list.el.find(list.options.listNodeName).first(), depth);
            return 
data;
        },

        
serialise: function()
        {
            return 
this.serialize();
        },

        
reset: function()
        {
            
this.mouse = {
                
offsetX   : 0,
                
offsetY   : 0,
                
startX    : 0,
                
startY    : 0,
                
lastX     : 0,
                
lastY     : 0,
                
nowX      : 0,
                
nowY      : 0,
                
distX     : 0,
                
distY     : 0,
                
dirAx     : 0,
                
dirX      : 0,
                
dirY      : 0,
                
lastDirX  : 0,
                
lastDirY  : 0,
                
distAxX   : 0,
                
distAxY   : 0
            
};
            
this.moving     = false;
            
this.dragEl     = null;
            
this.dragRootEl = null;
            
this.dragDepth  = 0;
            
this.hasNewRoot = false;
            
this.pointEl    = null;
        },

        
expandItem: function(li)
        {
            
li.removeClass(this.options.collapsedClass);
            
li.children('[data-action="expand"]').hide();
            
li.children('[data-action="collapse"]').show();
            
li.children(this.options.listNodeName).show();
        },

        
collapseItem: function(li)
        {
            var 
lists = li.children(this.options.listNodeName);
            if (
lists.length) {
                
li.addClass(this.options.collapsedClass);
                
li.children('[data-action="collapse"]').hide();
                
li.children('[data-action="expand"]').show();
                
li.children(this.options.listNodeName).hide();
            }
        },

        
expandAll: function()
        {
            var list = 
this;
            list.
el.find(list.options.itemNodeName).each(function() {
                list.
expandItem($(this));
            });
        },

        
collapseAll: function()
        {
            var list = 
this;
            list.
el.find(list.options.itemNodeName).each(function() {
                list.
collapseItem($(this));
            });
        },

        
setParent: function(li)
        {
            if (
li.children(this.options.listNodeName).length) {
                
li.prepend($(this.options.expandBtnHTML));
                
li.prepend($(this.options.collapseBtnHTML));
            }
            
li.children('[data-action="expand"]').hide();
        },

        
unsetParent: function(li)
        {
            
li.removeClass(this.options.collapsedClass);
            
li.children('[data-action]').remove();
            
li.children(this.options.listNodeName).remove();
        },

        
dragStart: function(e)
        {
            var 
mouse    = this.mouse,
                
target   = $(e.target),
                
dragItem = target.closest(this.options.itemNodeName);

            
this.placeEl.css('height', dragItem.height());

            
mouse.offsetX = e.offsetX !== undefined ? e.offsetX : e.pageX - target.offset().left;
            
mouse.offsetY = e.offsetY !== undefined ? e.offsetY : e.pageY - target.offset().top;
            
mouse.startX = mouse.lastX = e.pageX;
            
mouse.startY = mouse.lastY = e.pageY;

            
this.dragRootEl = this.el;

            
this.dragEl = $(document.createElement(this.options.listNodeName)).addClass(this.options.listClass + ' ' + this.options.dragClass);
            
this.dragEl.css('width', dragItem.width());

            
// fix for zepto.js
            //dragItem.after(this.placeEl).detach().appendTo(this.dragEl);
            
dragItem.after(this.placeEl);
            
dragItem[0].parentNode.removeChild(dragItem[0]);
            
dragItem.appendTo(this.dragEl);

            $(
document.body).append(this.dragEl);
            
this.dragEl.css({
                
'left' : e.pageX - mouse.offsetX,
                
'top'  : e.pageY - mouse.offsetY
            
});
            
// total depth of dragging item
            
var i, depth,
                
items = this.dragEl.find(this.options.itemNodeName);
            for (
i = 0; i < items.length; i++) {
                
depth = $(items[i]).parents(this.options.listNodeName).length;
                if (
depth > this.dragDepth) {
                    
this.dragDepth = depth;
                }
            }
        },

        
dragStop: function(e)
        {
            
// fix for zepto.js
            //this.placeEl.replaceWith(this.dragEl.children(this.options.itemNodeName + ':first').detach());
            
var el = this.dragEl.children(this.options.itemNodeName).first();
            
el[0].parentNode.removeChild(el[0]);
            
this.placeEl.replaceWith(el);

            
this.dragEl.remove();
            
this.el.trigger('change');
            if (
this.hasNewRoot) {
                
this.dragRootEl.trigger('change');
            }
            
this.reset();
        },

        
dragMove: function(e)
        {
            var list, 
parent, prev, next, depth,
                
opt   = this.options,
                
mouse = this.mouse;

            
this.dragEl.css({
                
'left' : e.pageX - mouse.offsetX,
                
'top'  : e.pageY - mouse.offsetY
            
});

            
// mouse position last events
            
mouse.lastX = mouse.nowX;
            
mouse.lastY = mouse.nowY;
            
// mouse position this events
            
mouse.nowX  = e.pageX;
            
mouse.nowY  = e.pageY;
            
// distance mouse moved between events
            
mouse.distX = mouse.nowX - mouse.lastX;
            
mouse.distY = mouse.nowY - mouse.lastY;
            
// direction mouse was moving
            
mouse.lastDirX = mouse.dirX;
            
mouse.lastDirY = mouse.dirY;
            
// direction mouse is now moving (on both axis)
            
mouse.dirX = mouse.distX === 0 ? 0 : mouse.distX > 0 ? 1 : -1;
            
mouse.dirY = mouse.distY === 0 ? 0 : mouse.distY > 0 ? 1 : -1;
            
// axis mouse is now moving on
            
var newAx   = Math.abs(mouse.distX) > Math.abs(mouse.distY) ? 1 : 0;

            
// do nothing on first move
            
if (!mouse.moving) {
                
mouse.dirAx  = newAx;
                
mouse.moving = true;
                return;
            }

            
// calc distance moved on this axis (and direction)
            
if (mouse.dirAx !== newAx) {
                
mouse.distAxX = 0;
                
mouse.distAxY = 0;
            } else {
                
mouse.distAxX += Math.abs(mouse.distX);
                if (
mouse.dirX !== 0 && mouse.dirX !== mouse.lastDirX) {
                    
mouse.distAxX = 0;
                }
                
mouse.distAxY += Math.abs(mouse.distY);
                if (
mouse.dirY !== 0 && mouse.dirY !== mouse.lastDirY) {
                    
mouse.distAxY = 0;
                }
            }
            
mouse.dirAx = newAx;

            
/**
             * move horizontal
             */
            
if (mouse.dirAx && mouse.distAxX >= opt.threshold) {
                
// reset move distance on x-axis for new phase
                
mouse.distAxX = 0;
                
prev = this.placeEl.prev(opt.itemNodeName);
                
// increase horizontal level if previous sibling exists and is not collapsed
                
if (mouse.distX > 0 && prev.length && !prev.hasClass(opt.collapsedClass)) {
                    
// cannot increase level when item above is collapsed
                    
list = prev.find(opt.listNodeName).last();
                    
// check if depth limit has reached
                    
depth = this.placeEl.parents(opt.listNodeName).length;
                    if (
depth + this.dragDepth <= opt.maxDepth) {
                        
// create new sub-level if one doesn't exist
                        
if (!list.length) {
                            list = $(
'<' + opt.listNodeName + '/>').addClass(opt.listClass);
                            list.
append(this.placeEl);
                            
prev.append(list);
                            
this.setParent(prev);
                        } else {
                            
// else append to next level up
                            
list = prev.children(opt.listNodeName).last();
                            list.
append(this.placeEl);
                        }
                    }
                }
                
// decrease horizontal level
                
if (mouse.distX < 0) {
                    
// we can't decrease a level if an item preceeds the current one
                    
next = this.placeEl.next(opt.itemNodeName);
                    if (!
next.length) {
                        
parent = this.placeEl.parent();
                        
this.placeEl.closest(opt.itemNodeName).after(this.placeEl);
                        if (!
parent.children().length) {
                            
this.unsetParent(parent.parent());
                        }
                    }
                }
            }

            var 
isEmpty = false;

            
// find list item under cursor
            
if (!hasPointerEvents) {
                
this.dragEl[0].style.visibility = 'hidden';
            }
            
this.pointEl = $(document.elementFromPoint(e.pageX - document.body.scrollLeft, e.pageY - (window.pageYOffset || document.documentElement.scrollTop)));
            if (!
hasPointerEvents) {
                
this.dragEl[0].style.visibility = 'visible';
            }
            if (
this.pointEl.hasClass(opt.handleClass)) {
                
this.pointEl = this.pointEl.parent(opt.itemNodeName);
            }
            if (
this.pointEl.hasClass(opt.emptyClass)) {
                
isEmpty = true;
            }
            else if (!
this.pointEl.length || !this.pointEl.hasClass(opt.itemClass)) {
                return;
            }

            
// find parent list of item under cursor
            
var pointElRoot = this.pointEl.closest('.' + opt.rootClass),
                
isNewRoot   = this.dragRootEl.data('nestable-id') !== pointElRoot.data('nestable-id');

            
/**
             * move vertical
             */
            
if (!mouse.dirAx || isNewRoot || isEmpty) {
                
// check if groups match if dragging over new root
                
if (isNewRoot && opt.group !== pointElRoot.data('nestable-group')) {
                    return;
                }
                
// check depth limit
                
depth = this.dragDepth - 1 + this.pointEl.parents(opt.listNodeName).length;
                if (
depth > opt.maxDepth) {
                    return;
                }
                var 
before = e.pageY < (this.pointEl.offset().top + this.pointEl.height() / 2);
                    
parent = this.placeEl.parent();
                
// if empty create new list to replace empty placeholder
                
if (isEmpty) {
                    list = $(
document.createElement(opt.listNodeName)).addClass(opt.listClass);
                    list.
append(this.placeEl);
                    
this.pointEl.replaceWith(list);
                }
                else if (
before) {
                    
this.pointEl.before(this.placeEl);
                }
                else {
                    
this.pointEl.after(this.placeEl);
                }
                if (!
parent.children().length) {
                    
this.unsetParent(parent.parent());
                }
                if (!
this.dragRootEl.find(opt.itemNodeName).length) {
                    
this.dragRootEl.append('<div class="' + opt.emptyClass + '"/>');
                }
                
// parent root list has changed
                
if (isNewRoot) {
                    
this.dragRootEl = pointElRoot;
                    
this.hasNewRoot = this.el[0] !== this.dragRootEl[0];
                }
            }
        }

    };

    $.
fn.nestable = function(params)
    {
        var 
lists  = this,
            
retval = this;

        
lists.each(function()
        {
            var 
plugin = $(this).data("nestable");

            if (!
plugin) {
                $(
this).data("nestable", new Plugin(this, params));
                $(
this).data("nestable-id", new Date().getTime());
            } else {
                if (
typeof params === 'string' && typeof plugin[params] === 'function') {
                    
retval = plugin[params]();
                }
            }
        });

        return 
retval || lists;
    };

})(
window.jQuery || window.Zepto, window, document);
?>
Онлайн: 2
Реклама