Вход Регистрация
Файл: ui/development-bundle/ui/jquery.ui.sortable.js
Строк: 1796
<?php
/*!
 * jQuery UI Sortable 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/sortable/
 *
 * Depends:
 *    jquery.ui.core.js
 *    jquery.ui.mouse.js
 *    jquery.ui.widget.js
 */
(function( $, undefined ) {

/*jshint loopfunc: true */

function isOverAxisxreferencesize ) {
    return ( 
reference ) && ( < ( reference size ) );
}

$.
widget("ui.sortable", $.ui.mouse, {
    
version"1.10.0",
    
widgetEventPrefix"sort",
    
readyfalse,
    
options: {
        
appendTo"parent",
        
axisfalse,
        
connectWithfalse,
        
containmentfalse,
        
cursor"auto",
        
cursorAtfalse,
        
dropOnEmptytrue,
        
forcePlaceholderSizefalse,
        
forceHelperSizefalse,
        
gridfalse,
        
handlefalse,
        
helper"original",
        
items"> *",
        
opacityfalse,
        
placeholderfalse,
        
revertfalse,
        
scrolltrue,
        
scrollSensitivity20,
        
scrollSpeed20,
        
scope"default",
        
tolerance"intersect",
        
zIndex1000,

        
// callbacks
        
activatenull,
        
beforeStopnull,
        
changenull,
        
deactivatenull,
        
outnull,
        
overnull,
        
receivenull,
        
removenull,
        
sortnull,
        
startnull,
        
stopnull,
        
updatenull
    
},
    
_create: function() {

        var 
this.options;
        
this.containerCache = {};
        
this.element.addClass("ui-sortable");

        
//Get the items
        
this.refresh();

        
//Let's determine if the items are being displayed horizontally
        
this.floating this.items.length o.axis === "x" || (/left|right/).test(this.items[0].item.css("float")) || (/inline|table-cell/).test(this.items[0].item.css("display")) : false;

        
//Let's determine the parent's offset
        
this.offset this.element.offset();

        
//Initialize mouse events for interaction
        
this._mouseInit();

        
//We're ready to go
        
this.ready true;

    },

    
_destroy: function() {
        
this.element
            
.removeClass("ui-sortable ui-sortable-disabled");
        
this._mouseDestroy();

        for ( var 
this.items.length 1>= 0i-- ) {
            
this.items[i].item.removeData(this.widgetName "-item");
        }

        return 
this;
    },

    
_setOption: function(keyvalue){
        if ( 
key === "disabled" ) {
            
this.optionskey ] = value;

            
this.widget().toggleClass"ui-sortable-disabled", !!value );
        } else {
            
// Don't call widget base _setOption for disable as it adds ui-state-disabled class
            
$.Widget.prototype._setOption.apply(thisarguments);
        }
    },

    
_mouseCapture: function(eventoverrideHandle) {
        var 
currentItem null,
            
validHandle false,
            
that this;

        if (
this.reverting) {
            return 
false;
        }

        if(
this.options.disabled || this.options.type === "static") {
            return 
false;
        }

        
//We have to refresh the items data once first
        
this._refreshItems(event);

        
//Find out if the clicked node (or one of its parents) is a actual item in this.items
        
$(event.target).parents().each(function() {
            if($.
data(thisthat.widgetName "-item") === that) {
                
currentItem = $(this);
                return 
false;
            }
        });
        if($.
data(event.targetthat.widgetName "-item") === that) {
            
currentItem = $(event.target);
        }

        if(!
currentItem) {
            return 
false;
        }
        if(
this.options.handle && !overrideHandle) {
            $(
this.options.handlecurrentItem).find("*").addBack().each(function() {
                if(
this === event.target) {
                    
validHandle true;
                }
            });
            if(!
validHandle) {
                return 
false;
            }
        }

        
this.currentItem currentItem;
        
this._removeCurrentsFromItems();
        return 
true;

    },

    
_mouseStart: function(eventoverrideHandlenoActivation) {

        var 
i,
            
this.options;

        
this.currentContainer this;

        
//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
        
this.refreshPositions();

        
//Create and append the visible helper
        
this.helper this._createHelper(event);

        
//Cache the helper size
        
this._cacheHelperProportions();

        
/*
         * - Position generation -
         * This block generates everything position related - it's the core of draggables.
         */

        //Cache the margins of the original element
        
this._cacheMargins();

        
//Get the next scrolling parent
        
this.scrollParent this.helper.scrollParent();

        
//The element's absolute position on the page minus margins
        
this.offset this.currentItem.offset();
        
this.offset = {
            
topthis.offset.top this.margins.top,
            
leftthis.offset.left this.margins.left
        
};

        $.
extend(this.offset, {
            
click: { //Where the click happened, relative to the element
                
leftevent.pageX this.offset.left,
                
topevent.pageY this.offset.top
            
},
            
parentthis._getParentOffset(),
            
relativethis._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
        
});

        
// Only after we got the offset, we can change the helper's position to absolute
        // TODO: Still need to figure out a way to make relative sorting possible
        
this.helper.css("position""absolute");
        
this.cssPosition this.helper.css("position");

        
//Generate the original position
        
this.originalPosition this._generatePosition(event);
        
this.originalPageX event.pageX;
        
this.originalPageY event.pageY;

        
//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
        
(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));

        
//Cache the former DOM position
        
this.domPosition = { prevthis.currentItem.prev()[0], parentthis.currentItem.parent()[0] };

        
//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
        
if(this.helper[0] !== this.currentItem[0]) {
            
this.currentItem.hide();
        }

        
//Create the placeholder
        
this._createPlaceholder();

        
//Set a containment if given in the options
        
if(o.containment) {
            
this._setContainment();
        }

        if(
o.cursor) { // cursor option
            
if ($("body").css("cursor")) {
                
this._storedCursor = $("body").css("cursor");
            }
            $(
"body").css("cursor"o.cursor);
        }

        if(
o.opacity) { // opacity option
            
if (this.helper.css("opacity")) {
                
this._storedOpacity this.helper.css("opacity");
            }
            
this.helper.css("opacity"o.opacity);
        }

        if(
o.zIndex) { // zIndex option
            
if (this.helper.css("zIndex")) {
                
this._storedZIndex this.helper.css("zIndex");
            }
            
this.helper.css("zIndex"o.zIndex);
        }

        
//Prepare scrolling
        
if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
            
this.overflowOffset this.scrollParent.offset();
        }

        
//Call callbacks
        
this._trigger("start"eventthis._uiHash());

        
//Recache the helper size
        
if(!this._preserveHelperProportions) {
            
this._cacheHelperProportions();
        }


        
//Post "activate" events to possible containers
        
if( !noActivation ) {
            for ( 
this.containers.length 1>= 0i-- ) {
                
this.containers]._trigger"activate"eventthis._uiHashthis ) );
            }
        }

        
//Prepare possible droppables
        
if($.ui.ddmanager) {
            $.
ui.ddmanager.current this;
        }

        if ($.
ui.ddmanager && !o.dropBehaviour) {
            $.
ui.ddmanager.prepareOffsets(thisevent);
        }

        
this.dragging true;

        
this.helper.addClass("ui-sortable-helper");
        
this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
        
return true;

    },

    
_mouseDrag: function(event) {
        var 
iitemitemElementintersection,
            
this.options,
            
scrolled false;

        
//Compute the helpers position
        
this.position this._generatePosition(event);
        
this.positionAbs this._convertPositionTo("absolute");

        if (!
this.lastPositionAbs) {
            
this.lastPositionAbs this.positionAbs;
        }

        
//Do scrolling
        
if(this.options.scroll) {
            if(
this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {

                if((
this.overflowOffset.top this.scrollParent[0].offsetHeight) - event.pageY o.scrollSensitivity) {
                    
this.scrollParent[0].scrollTop scrolled this.scrollParent[0].scrollTop o.scrollSpeed;
                } else if(
event.pageY this.overflowOffset.top o.scrollSensitivity) {
                    
this.scrollParent[0].scrollTop scrolled this.scrollParent[0].scrollTop o.scrollSpeed;
                }

                if((
this.overflowOffset.left this.scrollParent[0].offsetWidth) - event.pageX o.scrollSensitivity) {
                    
this.scrollParent[0].scrollLeft scrolled this.scrollParent[0].scrollLeft o.scrollSpeed;
                } else if(
event.pageX this.overflowOffset.left o.scrollSensitivity) {
                    
this.scrollParent[0].scrollLeft scrolled this.scrollParent[0].scrollLeft o.scrollSpeed;
                }

            } else {

                if(
event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
                    
scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
                } else if($(
window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
                    
scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
                }

                if(
event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
                    
scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
                } else if($(
window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
                    
scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
                }

            }

            if(
scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
                $.
ui.ddmanager.prepareOffsets(thisevent);
            }
        }

        
//Regenerate the absolute position used for position checks
        
this.positionAbs this._convertPositionTo("absolute");

        
//Set the helper position
        
if(!this.options.axis || this.options.axis !== "y") {
            
this.helper[0].style.left this.position.left+"px";
        }
        if(!
this.options.axis || this.options.axis !== "x") {
            
this.helper[0].style.top this.position.top+"px";
        }

        
//Rearrange
        
for (this.items.length 1>= 0i--) {

            
//Cache variables and intersection, continue if no intersection
            
item this.items[i];
            
itemElement item.item[0];
            
intersection this._intersectsWithPointer(item);
            if (!
intersection) {
                continue;
            }

            
// Only put the placeholder inside the current Container, skip all
            // items form other containers. This works because when moving
            // an item from one container to another the
            // currentContainer is switched before the placeholder is moved.
            //
            // Without this moving items in "sub-sortables" can cause the placeholder to jitter
            // beetween the outer and inner container.
            
if (item.instance !== this.currentContainer) {
                continue;
            }

            
// cannot intersect with itself
            // no useless actions that have been done before
            // no action if the item moved is the parent of the item checked
            
if (itemElement !== this.currentItem[0] &&
                
this.placeholder[intersection === "next" "prev"]()[0] !== itemElement &&
                !$.
contains(this.placeholder[0], itemElement) &&
                (
this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
            ) {

                
this.direction intersection === "down" "up";

                if (
this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
                    
this._rearrange(eventitem);
                } else {
                    break;
                }

                
this._trigger("change"eventthis._uiHash());
                break;
            }
        }

        
//Post events to containers
        
this._contactContainers(event);

        
//Interconnect with droppables
        
if($.ui.ddmanager) {
            $.
ui.ddmanager.drag(thisevent);
        }

        
//Call callbacks
        
this._trigger("sort"eventthis._uiHash());

        
this.lastPositionAbs this.positionAbs;
        return 
false;

    },

    
_mouseStop: function(eventnoPropagation) {

        if(!
event) {
            return;
        }

        
//If we are using droppables, inform the manager about the drop
        
if ($.ui.ddmanager && !this.options.dropBehaviour) {
            $.
ui.ddmanager.drop(thisevent);
        }

        if(
this.options.revert) {
            var 
that this,
                
cur this.placeholder.offset();

            
this.reverting true;

            $(
this.helper).animate({
                
leftcur.left this.offset.parent.left this.margins.left + (this.offsetParent[0] === document.body this.offsetParent[0].scrollLeft),
                
topcur.top this.offset.parent.top this.margins.top + (this.offsetParent[0] === document.body this.offsetParent[0].scrollTop)
            }, 
parseInt(this.options.revert10) || 500, function() {
                
that._clear(event);
            });
        } else {
            
this._clear(eventnoPropagation);
        }

        return 
false;

    },

    
cancel: function() {

        if(
this.dragging) {

            
this._mouseUp({ targetnull });

            if(
this.options.helper === "original") {
                
this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
            } else {
                
this.currentItem.show();
            }

            
//Post deactivating events to containers
            
for (var this.containers.length 1>= 0i--){
                
this.containers[i]._trigger("deactivate"nullthis._uiHash(this));
                if(
this.containers[i].containerCache.over) {
                    
this.containers[i]._trigger("out"nullthis._uiHash(this));
                    
this.containers[i].containerCache.over 0;
                }
            }

        }

        if (
this.placeholder) {
            
//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
            
if(this.placeholder[0].parentNode) {
                
this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
            }
            if(
this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
                
this.helper.remove();
            }

            $.
extend(this, {
                
helpernull,
                
draggingfalse,
                
revertingfalse,
                
_noFinalSortnull
            
});

            if(
this.domPosition.prev) {
                $(
this.domPosition.prev).after(this.currentItem);
            } else {
                $(
this.domPosition.parent).prepend(this.currentItem);
            }
        }

        return 
this;

    },

    
serialize: function(o) {

        var 
items this._getItemsAsjQuery(&& o.connected),
            
str = [];
        
|| {};

        $(
items).each(function() {
            var 
res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[-=_](.+)/));
            if (
res) {
                
str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression res[1] : res[2]));
            }
        });

        if(!
str.length && o.key) {
            
str.push(o.key "=");
        }

        return 
str.join("&");

    },

    
toArray: function(o) {

        var 
items this._getItemsAsjQuery(&& o.connected),
            
ret = [];

        
|| {};

        
items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
        return 
ret;

    },

    
/* Be careful with the following core functions */
    
_intersectsWith: function(item) {

        var 
x1 this.positionAbs.left,
            
x2 x1 this.helperProportions.width,
            
y1 this.positionAbs.top,
            
y2 y1 this.helperProportions.height,
            
item.left,
            
item.width,
            
item.top,
            
item.height,
            
dyClick this.offset.click.top,
            
dxClick this.offset.click.left,
            
isOverElement = (y1 dyClick) > && (y1 dyClick) < && (x1 dxClick) > && (x1 dxClick) < r;

        if ( 
this.options.tolerance === "pointer" ||
            
this.options.forcePointerForContainers ||
            (
this.options.tolerance !== "pointer" && this.helperProportions[this.floating "width" "height"] > item[this.floating "width" "height"])
        ) {
            return 
isOverElement;
        } else {

            return (
x1 + (this.helperProportions.width 2) && // Right Half
                
x2 - (this.helperProportions.width 2) < && // Left Half
                
y1 + (this.helperProportions.height 2) && // Bottom Half
                
y2 - (this.helperProportions.height 2) < ); // Top Half

        
}
    },

    
_intersectsWithPointer: function(item) {

        var 
isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top this.offset.click.topitem.topitem.height),
            
isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left this.offset.click.leftitem.leftitem.width),
            
isOverElement isOverElementHeight && isOverElementWidth,
            
verticalDirection this._getDragVerticalDirection(),
            
horizontalDirection this._getDragHorizontalDirection();

        if (!
isOverElement) {
            return 
false;
        }

        return 
this.floating ?
            ( ((
horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? )
            : ( 
verticalDirection && (verticalDirection === "down" 1) );

    },

    
_intersectsWithSides: function(item) {

        var 
isOverBottomHalf isOverAxis(this.positionAbs.top this.offset.click.topitem.top + (item.height/2), item.height),
            
isOverRightHalf isOverAxis(this.positionAbs.left this.offset.click.leftitem.left + (item.width/2), item.width),
            
verticalDirection this._getDragVerticalDirection(),
            
horizontalDirection this._getDragHorizontalDirection();

        if (
this.floating && horizontalDirection) {
            return ((
horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
        } else {
            return 
verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
        }

    },

    
_getDragVerticalDirection: function() {
        var 
delta this.positionAbs.top this.lastPositionAbs.top;
        return 
delta !== && (delta "down" "up");
    },

    
_getDragHorizontalDirection: function() {
        var 
delta this.positionAbs.left this.lastPositionAbs.left;
        return 
delta !== && (delta "right" "left");
    },

    
refresh: function(event) {
        
this._refreshItems(event);
        
this.refreshPositions();
        return 
this;
    },

    
_connectWith: function() {
        var 
options this.options;
        return 
options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
    },

    
_getItemsAsjQuery: function(connected) {

        var 
ijcurinst,
            
items = [],
            
queries = [],
            
connectWith this._connectWith();

        if(
connectWith && connected) {
            for (
connectWith.length 1>= 0i--){
                
cur = $(connectWith[i]);
                for ( 
cur.length 1>= 0j--){
                    
inst = $.data(cur[j], this.widgetFullName);
                    if(
inst && inst !== this && !inst.options.disabled) {
                        
queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.itemsinst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]);
                    }
                }
            }
        }

        
queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.elementnull, { optionsthis.optionsitemthis.currentItem }) : $(this.options.itemsthis.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]);

        for (
queries.length 1>= 0i--){
            
queries[i][0].each(function() {
                
items.push(this);
            });
        }

        return $(
items);

    },

    
_removeCurrentsFromItems: function() {

        var list = 
this.currentItem.find(":data(" this.widgetName "-item)");

        
this.items = $.grep(this.items, function (item) {
            for (var 
j=0< list.lengthj++) {
                if(list[
j] === item.item[0]) {
                    return 
false;
                }
            }
            return 
true;
        });

    },

    
_refreshItems: function(event) {

        
this.items = [];
        
this.containers = [this];

        var 
ijcurinsttargetData_queriesitemqueriesLength,
            
items this.items,
            
queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { itemthis.currentItem }) : $(this.options.itemsthis.element), this]],
            
connectWith this._connectWith();

        if(
connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
            
for (connectWith.length 1>= 0i--){
                
cur = $(connectWith[i]);
                for (
cur.length 1>= 0j--){
                    
inst = $.data(cur[j], this.widgetFullName);
                    if(
inst && inst !== this && !inst.options.disabled) {
                        
queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { itemthis.currentItem }) : $(inst.options.itemsinst.element), inst]);
                        
this.containers.push(inst);
                    }
                }
            }
        }

        for (
queries.length 1>= 0i--) {
            
targetData queries[i][1];
            
_queries queries[i][0];

            for (
j=0queriesLength _queries.lengthqueriesLengthj++) {
                
item = $(_queries[j]);

                
item.data(this.widgetName "-item"targetData); // Data for target checking (mouse manager)

                
items.push({
                    
itemitem,
                    
instancetargetData,
                    
width0height0,
                    
left0top0
                
});
            }
        }

    },

    
refreshPositions: function(fast) {

        
//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
        
if(this.offsetParent && this.helper) {
            
this.offset.parent this._getParentOffset();
        }

        var 
iitemtp;

        for (
this.items.length 1>= 0i--){
            
item this.items[i];

            
//We ignore calculating positions of all connected containers when we're not over them
            
if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
                continue;
            }

            
this.options.toleranceElement ? $(this.options.toleranceElementitem.item) : item.item;

            if (!
fast) {
                
item.width t.outerWidth();
                
item.height t.outerHeight();
            }

            
t.offset();
            
item.left p.left;
            
item.top p.top;
        }

        if(
this.options.custom && this.options.custom.refreshContainers) {
            
this.options.custom.refreshContainers.call(this);
        } else {
            for (
this.containers.length 1>= 0i--){
                
this.containers[i].element.offset();
                
this.containers[i].containerCache.left p.left;
                
this.containers[i].containerCache.top p.top;
                
this.containers[i].containerCache.width    this.containers[i].element.outerWidth();
                
this.containers[i].containerCache.height this.containers[i].element.outerHeight();
            }
        }

        return 
this;
    },

    
_createPlaceholder: function(that) {
        
that that || this;
        var 
className,
            
that.options;

        if(!
o.placeholder || o.placeholder.constructor === String) {
            
className o.placeholder;
            
o.placeholder = {
                
element: function() {

                    var 
el = $(document.createElement(that.currentItem[0].nodeName))
                        .
addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
                        .
removeClass("ui-sortable-helper")[0];

                    if(!
className) {
                        
el.style.visibility "hidden";
                    }

                    return 
el;
                },
                
update: function(containerp) {

                    
// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
                    // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
                    
if(className && !o.forcePlaceholderSize) {
                        return;
                    }

                    
//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
                    
if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||010) - parseInt(that.currentItem.css("paddingBottom")||010)); }
                    if(!
p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||010) - parseInt(that.currentItem.css("paddingRight")||010)); }
                }
            };
        }

        
//Create the placeholder
        
that.placeholder = $(o.placeholder.element.call(that.elementthat.currentItem));

        
//Append it after the actual current item
        
that.currentItem.after(that.placeholder);

        
//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
        
o.placeholder.update(thatthat.placeholder);

    },

    
_contactContainers: function(event) {
        var 
ijdistitemWithLeastDistanceposPropertysizePropertybasecurnearBottom,
            
innermostContainer null,
            
innermostIndex null;

        
// get innermost container that intersects with item
        
for (this.containers.length 1>= 0i--) {

            
// never consider a container that's located within the item itself
            
if($.contains(this.currentItem[0], this.containers[i].element[0])) {
                continue;
            }

            if(
this._intersectsWith(this.containers[i].containerCache)) {

                
// if we've already found a container and it's more "inner" than this, then continue
                
if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
                    continue;
                }

                
innermostContainer this.containers[i];
                
innermostIndex i;

            } else {
                
// container doesn't intersect. trigger "out" event if necessary
                
if(this.containers[i].containerCache.over) {
                    
this.containers[i]._trigger("out"eventthis._uiHash(this));
                    
this.containers[i].containerCache.over 0;
                }
            }

        }

        
// if no intersecting containers found, return
        
if(!innermostContainer) {
            return;
        }

        
// move the item into the container if it's not there already
        
if(this.containers.length === 1) {
            
this.containers[innermostIndex]._trigger("over"eventthis._uiHash(this));
            
this.containers[innermostIndex].containerCache.over 1;
        } else {

            
//When entering a new container, we will find the item with the least distance and append our item near it
            
dist 10000;
            
itemWithLeastDistance null;
            
posProperty this.containers[innermostIndex].floating "left" "top";
            
sizeProperty this.containers[innermostIndex].floating "width" "height";
            
base this.positionAbs[posProperty] + this.offset.click[posProperty];
            for (
this.items.length 1>= 0j--) {
                if(!$.
contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
                    continue;
                }
                if(
this.items[j].item[0] === this.currentItem[0]) {
                    continue;
                }
                
cur this.items[j].item.offset()[posProperty];
                
nearBottom false;
                if(
Math.abs(cur base) > Math.abs(cur this.items[j][sizeProperty] - base)){
                    
nearBottom true;
                    
cur += this.items[j][sizeProperty];
                }

                if(
Math.abs(cur base) < dist) {
                    
dist Math.abs(cur base); itemWithLeastDistance this.items[j];
                    
this.direction nearBottom "up""down";
                }
            }

            
//Check if dropOnEmpty is enabled
            
if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
                return;
            }

            
this.currentContainer this.containers[innermostIndex];
            
itemWithLeastDistance this._rearrange(eventitemWithLeastDistancenulltrue) : this._rearrange(eventnullthis.containers[innermostIndex].elementtrue);
            
this._trigger("change"eventthis._uiHash());
            
this.containers[innermostIndex]._trigger("change"eventthis._uiHash(this));

            
//Update the placeholder
            
this.options.placeholder.update(this.currentContainerthis.placeholder);

            
this.containers[innermostIndex]._trigger("over"eventthis._uiHash(this));
            
this.containers[innermostIndex].containerCache.over 1;
        }


    },

    
_createHelper: function(event) {

        var 
this.options,
            
helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [eventthis.currentItem])) : (o.helper === "clone" this.currentItem.clone() : this.currentItem);

        
//Add the helper to the DOM if that didn't happen already
        
if(!helper.parents("body").length) {
            $(
o.appendTo !== "parent" o.appendTo this.currentItem[0].parentNode)[0].appendChild(helper[0]);
        }

        if(
helper[0] === this.currentItem[0]) {
            
this._storedCSS = { widththis.currentItem[0].style.widthheightthis.currentItem[0].style.heightpositionthis.currentItem.css("position"), topthis.currentItem.css("top"), leftthis.currentItem.css("left") };
        }

        if(!
helper[0].style.width || o.forceHelperSize) {
            
helper.width(this.currentItem.width());
        }
        if(!
helper[0].style.height || o.forceHelperSize) {
            
helper.height(this.currentItem.height());
        }

        return 
helper;

    },

    
_adjustOffsetFromHelper: function(obj) {
        if (
typeof obj === "string") {
            
obj obj.split(" ");
        }
        if ($.
isArray(obj)) {
            
obj = {left: +obj[0], top: +obj[1] || 0};
        }
        if (
"left" in obj) {
            
this.offset.click.left obj.left this.margins.left;
        }
        if (
"right" in obj) {
            
this.offset.click.left this.helperProportions.width obj.right this.margins.left;
        }
        if (
"top" in obj) {
            
this.offset.click.top obj.top this.margins.top;
        }
        if (
"bottom" in obj) {
            
this.offset.click.top this.helperProportions.height obj.bottom this.margins.top;
        }
    },

    
_getParentOffset: function() {


        
//Get the offsetParent and cache its position
        
this.offsetParent this.helper.offsetParent();
        var 
po this.offsetParent.offset();

        
// This is a special case where we need to modify a offset calculated on start, since the following happened:
        // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
        // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
        //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
        
if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
            
po.left += this.scrollParent.scrollLeft();
            
po.top += this.scrollParent.scrollTop();
        }

        
// This needs to be actually done for all browsers, since pageX/pageY includes this information
        // with an ugly IE fix
        
if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
            
po = { top0left};
        }

        return {
            
toppo.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
            
leftpo.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
        };

    },

    
_getRelativeOffset: function() {

        if(
this.cssPosition === "relative") {
            var 
this.currentItem.position();
            return {
                
topp.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
                
leftp.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
            };
        } else {
            return { 
top0left};
        }

    },

    
_cacheMargins: function() {
        
this.margins = {
            
left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
            
top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
        };
    },

    
_cacheHelperProportions: function() {
        
this.helperProportions = {
            
widththis.helper.outerWidth(),
            
heightthis.helper.outerHeight()
        };
    },

    
_setContainment: function() {

        var 
cecoover,
            
this.options;
        if(
o.containment === "parent") {
            
o.containment this.helper[0].parentNode;
        }
        if(
o.containment === "document" || o.containment === "window") {
            
this.containment = [
                
this.offset.relative.left this.offset.parent.left,
                
this.offset.relative.top this.offset.parent.top,
                $(
o.containment === "document" document window).width() - this.helperProportions.width this.margins.left,
                ($(
o.containment === "document" document window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height this.margins.top
            
];
        }

        if(!(/^(
document|window|parent)$/).test(o.containment)) {
            
ce = $(o.containment)[0];
            
co = $(o.containment).offset();
            
over = ($(ce).css("overflow") !== "hidden");

            
this.containment = [
                
co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
                
co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
                
co.left+(over Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width this.margins.left,
                
co.top+(over Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height this.margins.top
            
];
        }

    },

    
_convertPositionTo: function(dpos) {

        if(!
pos) {
            
pos this.position;
        }
        var 
mod === "absolute" : -1,
            
scroll this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent this.scrollParent,
            
scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);

        return {
            
top: (
                
pos.top    +                                                                // The absolute mouse position
                
this.offset.relative.top mod +                                        // Only for relative positioned nodes: Relative offset from element to offset parent
                
this.offset.parent.top mod -                                            // The offsetParent's offset without borders (offset + border)
                
( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode scroll.scrollTop() ) ) * mod)
            ),
            
left: (
                
pos.left +                                                                // The absolute mouse position
                
this.offset.relative.left mod +                                        // Only for relative positioned nodes: Relative offset from element to offset parent
                
this.offset.parent.left mod    -                                        // The offsetParent's offset without borders (offset + border)
                
( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode scroll.scrollLeft() ) * mod)
            )
        };

    },

    
_generatePosition: function(event) {

        var 
topleft,
            
this.options,
            
pageX event.pageX,
            
pageY event.pageY,
            
scroll this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent this.scrollParentscrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);

        
// This is another very weird special case that only happens for relative elements:
        // 1. If the css position is relative
        // 2. and the scroll parent is the document or similar to the offset parent
        // we have to refresh the relative offset during the scroll so there are no jumps
        
if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {
            
this.offset.relative this._getRelativeOffset();
        }

        
/*
         * - Position constraining -
         * Constrain the position to a mix of grid, containment.
         */

        
if(this.originalPosition) { //If we are not dragging yet, we won't check for options

            
if(this.containment) {
                if(
event.pageX this.offset.click.left this.containment[0]) {
                    
pageX this.containment[0] + this.offset.click.left;
                }
                if(
event.pageY this.offset.click.top this.containment[1]) {
                    
pageY this.containment[1] + this.offset.click.top;
                }
                if(
event.pageX this.offset.click.left this.containment[2]) {
                    
pageX this.containment[2] + this.offset.click.left;
                }
                if(
event.pageY this.offset.click.top this.containment[3]) {
                    
pageY this.containment[3] + this.offset.click.top;
                }
            }

            if(
o.grid) {
                
top this.originalPageY Math.round((pageY this.originalPageY) / o.grid[1]) * o.grid[1];
                
pageY this.containment ? ( (top this.offset.click.top >= this.containment[1] && top this.offset.click.top <= this.containment[3]) ? top : ((top this.offset.click.top >= this.containment[1]) ? top o.grid[1] : top o.grid[1])) : top;

                
left this.originalPageX Math.round((pageX this.originalPageX) / o.grid[0]) * o.grid[0];
                
pageX this.containment ? ( (left this.offset.click.left >= this.containment[0] && left this.offset.click.left <= this.containment[2]) ? left : ((left this.offset.click.left >= this.containment[0]) ? left o.grid[0] : left o.grid[0])) : left;
            }

        }

        return {
            
top: (
                
pageY -                                                                // The absolute mouse position
                
this.offset.click.top -                                                    // Click offset (relative to the element)
                
this.offset.relative.top    -                                            // Only for relative positioned nodes: Relative offset from element to offset parent
                
this.offset.parent.top +                                                // The offsetParent's offset without borders (offset + border)
                
( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode scroll.scrollTop() ) ))
            ),
            
left: (
                
pageX -                                                                // The absolute mouse position
                
this.offset.click.left -                                                // Click offset (relative to the element)
                
this.offset.relative.left    -                                            // Only for relative positioned nodes: Relative offset from element to offset parent
                
this.offset.parent.left +                                                // The offsetParent's offset without borders (offset + border)
                
( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode scroll.scrollLeft() ))
            )
        };

    },

    
_rearrange: function(eventiahardRefresh) {

        
a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" i.item[0] : i.item[0].nextSibling));

        
//Various things done here to improve the performance:
        // 1. we create a setTimeout, that calls refreshPositions
        // 2. on the instance, we have a counter variable, that get's higher after every append
        // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
        // 4. this lets only the last addition to the timeout stack through
        
this.counter this.counter ? ++this.counter 1;
        var 
counter this.counter;

        
this._delay(function() {
            if(
counter === this.counter) {
                
this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
            
}
        });

    },

    
_clear: function(eventnoPropagation) {

        
this.reverting false;
        
// We delay all events that have to be triggered to after the point where the placeholder has been removed and
        // everything else normalized again
        
var i,
            
delayedTriggers = [];

        
// We first have to update the dom position of the actual currentItem
        // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
        
if(!this._noFinalSort && this.currentItem.parent().length) {
            
this.placeholder.before(this.currentItem);
        }
        
this._noFinalSort null;

        if(
this.helper[0] === this.currentItem[0]) {
            for(
i in this._storedCSS) {
                if(
this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
                    
this._storedCSS[i] = "";
                }
            }
            
this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
        } else {
            
this.currentItem.show();
        }

        if(
this.fromOutside && !noPropagation) {
            
delayedTriggers.push(function(event) { this._trigger("receive"eventthis._uiHash(this.fromOutside)); });
        }
        if((
this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
            
delayedTriggers.push(function(event) { this._trigger("update"eventthis._uiHash()); }); //Trigger update callback if the DOM position has changed
        
}

        
// Check if the items Container has Changed and trigger appropriate
        // events.
        
if (this !== this.currentContainer) {
            if(!
noPropagation) {
                
delayedTriggers.push(function(event) { this._trigger("remove"eventthis._uiHash()); });
                
delayedTriggers.push((function(c) { return function(event) { c._trigger("receive"eventthis._uiHash(this)); };  }).call(thisthis.currentContainer));
                
delayedTriggers.push((function(c) { return function(event) { c._trigger("update"eventthis._uiHash(this));  }; }).call(thisthis.currentContainer));
            }
        }


        
//Post events to containers
        
for (this.containers.length 1>= 0i--){
            if(!
noPropagation) {
                
delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate"eventthis._uiHash(this)); };  }).call(thisthis.containers[i]));
            }
            if(
this.containers[i].containerCache.over) {
                
delayedTriggers.push((function(c) { return function(event) { c._trigger("out"eventthis._uiHash(this)); };  }).call(thisthis.containers[i]));
                
this.containers[i].containerCache.over 0;
            }
        }

        
//Do what was originally in plugins
        
if(this._storedCursor) {
            $(
"body").css("cursor"this._storedCursor);
        }
        if(
this._storedOpacity) {
            
this.helper.css("opacity"this._storedOpacity);
        }
        if(
this._storedZIndex) {
            
this.helper.css("zIndex"this._storedZIndex === "auto" "" this._storedZIndex);
        }

        
this.dragging false;
        if(
this.cancelHelperRemoval) {
            if(!
noPropagation) {
                
this._trigger("beforeStop"eventthis._uiHash());
                for (
i=0delayedTriggers.lengthi++) {
                    
delayedTriggers[i].call(thisevent);
                } 
//Trigger all delayed events
                
this._trigger("stop"eventthis._uiHash());
            }

            
this.fromOutside false;
            return 
false;
        }

        if(!
noPropagation) {
            
this._trigger("beforeStop"eventthis._uiHash());
        }

        
//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
        
this.placeholder[0].parentNode.removeChild(this.placeholder[0]);

        if(
this.helper[0] !== this.currentItem[0]) {
            
this.helper.remove();
        }
        
this.helper null;

        if(!
noPropagation) {
            for (
i=0delayedTriggers.lengthi++) {
                
delayedTriggers[i].call(thisevent);
            } 
//Trigger all delayed events
            
this._trigger("stop"eventthis._uiHash());
        }

        
this.fromOutside false;
        return 
true;

    },

    
_trigger: function() {
        if ($.
Widget.prototype._trigger.apply(thisarguments) === false) {
            
this.cancel();
        }
    },

    
_uiHash: function(_inst) {
        var 
inst _inst || this;
        return {
            
helperinst.helper,
            
placeholderinst.placeholder || $([]),
            
positioninst.position,
            
originalPositioninst.originalPosition,
            
offsetinst.positionAbs,
            
iteminst.currentItem,
            
sender_inst _inst.element null
        
};
    }

});

})(
jQuery);
?>
Онлайн: 1
Реклама