/* * jquery ui draggable 1.7.2 * * copyright (c) 2009 authors.txt (http://jqueryui.com/about) * dual licensed under the mit (mit-license.txt) * and gpl (gpl-license.txt) licenses. * * http://docs.jquery.com/ui/draggables * * depends: * ui.core.js */ (function($){ $.widget("ui.draggable", $.extend({}, $.ui.mouse, { _init: function(){ if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position"))) this.element[0].style.position = 'relative'; (this.options.addclasses && this.element.addclass("ui-draggable")); (this.options.disabled && this.element.addclass("ui-draggable-disabled")); this._mouseinit(); }, destroy: function(){ if (!this.element.data('draggable')) return; this.element.removedata("draggable").unbind(".draggable").removeclass("ui-draggable" + " ui-draggable-dragging" + " ui-draggable-disabled"); this._mousedestroy(); }, _mousecapture: function(event){ var o = this.options; if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle')) return false; //quit if we're not on a valid handle this.handle = this._gethandle(event); if (!this.handle) return false; return true; }, _mousestart: function(event){ var o = this.options; //create and append the visible helper this.helper = this._createhelper(event); //cache the helper size this._cachehelperproportions(); //if ddmanager is used for droppables, set the global draggable if ($.ui.ddmanager) $.ui.ddmanager.current = this; /* * - position generation - * this block generates everything position related - it's the core of draggables. */ //cache the margins of the original element this._cachemargins(); //store the helper's css position this.cssposition = this.helper.css("position"); this.scrollparent = this.helper.scrollparent(); //the element's absolute position on the page minus margins this.offset = this.element.offset(); this.offset = { top: this.offset.top - this.margins.top, left: this.offset.left - this.margins.left }; $.extend(this.offset, { click: { //where the click happened, relative to the element left: event.pagex - this.offset.left, top: event.pagey - this.offset.top }, parent: this._getparentoffset(), relative: this._getrelativeoffset() //this is a relative to absolute position minus the actual position calculation - only used for relative positioned helper }); //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 if (o.cursorat) this._adjustoffsetfromhelper(o.cursorat); //set a containment if given in the options if (o.containment) this._setcontainment(); //call plugins and callbacks this._trigger("start", event); //recache the helper size this._cachehelperproportions(); //prepare the droppable offsets if ($.ui.ddmanager && !o.dropbehaviour) $.ui.ddmanager.prepareoffsets(this, event); this.helper.addclass("ui-draggable-dragging"); this._mousedrag(event, true); //execute the drag once - this causes the helper not to be visible before getting its correct position return true; }, _mousedrag: function(event, nopropagation){ //compute the helpers position this.position = this._generateposition(event); this.positionabs = this._convertpositionto("absolute"); //call plugins and callbacks and use the resulting position if something is returned if (!nopropagation) { var ui = this._uihash(); this._trigger('drag', event, ui); this.position = ui.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'; if ($.ui.ddmanager) $.ui.ddmanager.drag(this, event); return false; }, _mousestop: function(event){ //if we are using droppables, inform the manager about the drop var dropped = false; if ($.ui.ddmanager && !this.options.dropbehaviour) dropped = $.ui.ddmanager.drop(this, event); //if a drop comes from outside (a sortable) if (this.dropped) { dropped = this.dropped; this.dropped = false; } if ((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isfunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { var self = this; $(this.helper).animate(this.originalposition, parseint(this.options.revertduration, 10), function(){ self._trigger("stop", event); self._clear(); }); } else { this._trigger("stop", event); this._clear(); } return false; }, _gethandle: function(event){ var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false; $(this.options.handle, this.element).find("*").andself().each(function(){ if (this == event.target) handle = true; }); return handle; }, _createhelper: function(event){ var o = this.options; var helper = $.isfunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element); if (!helper.parents('body').length) helper.appendto((o.appendto == 'parent' ? this.element[0].parentnode : o.appendto)); if (helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) helper.css("position", "absolute"); return helper; }, _adjustoffsetfromhelper: function(obj){ if (obj.left != undefined) this.offset.click.left = obj.left + this.margins.left; if (obj.right != undefined) this.offset.click.left = this.helperproportions.width - obj.right + this.margins.left; if (obj.top != undefined) this.offset.click.top = obj.top + this.margins.top; if (obj.bottom != undefined) 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 && $.ui.contains(this.scrollparent[0], this.offsetparent[0])) { po.left += this.scrollparent.scrollleft(); po.top += this.scrollparent.scrolltop(); } if ((this.offsetparent[0] == document.body) //this needs to be actually done for all browsers, since pagex/pagey includes this information || (this.offsetparent[0].tagname && this.offsetparent[0].tagname.tolowercase() == 'html' && $.browser.msie)) //ugly ie fix po = { top: 0, left: 0 }; return { top: po.top + (parseint(this.offsetparent.css("bordertopwidth"), 10) || 0), left: po.left + (parseint(this.offsetparent.css("borderleftwidth"), 10) || 0) }; }, _getrelativeoffset: function(){ if (this.cssposition == "relative") { var p = this.element.position(); return { top: p.top - (parseint(this.helper.css("top"), 10) || 0) + this.scrollparent.scrolltop(), left: p.left - (parseint(this.helper.css("left"), 10) || 0) + this.scrollparent.scrollleft() }; } else { return { top: 0, left: 0 }; } }, _cachemargins: function(){ this.margins = { left: (parseint(this.element.css("marginleft"), 10) || 0), top: (parseint(this.element.css("margintop"), 10) || 0) }; }, _cachehelperproportions: function(){ this.helperproportions = { width: this.helper.outerwidth(), height: this.helper.outerheight() }; }, _setcontainment: function(){ var o = this.options; if (o.containment == 'parent') o.containment = this.helper[0].parentnode; if (o.containment == 'document' || o.containment == 'window') this.containment = [0 - this.offset.relative.left - this.offset.parent.left, 0 - 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) && o.containment.constructor != array) { var ce = $(o.containment)[0]; if (!ce) return; var co = $(o.containment).offset(); var 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]; } else if (o.containment.constructor == array) { this.containment = o.containment; } }, _convertpositionto: function(d, pos){ if (!pos) pos = this.position; var mod = d == "absolute" ? 1 : -1; var o = this.options, scroll = this.cssposition == 'absolute' && !(this.scrollparent[0] != document && $.ui.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) - ($.browser.safari && this.cssposition == 'fixed' ? 0 : (this.cssposition == 'fixed' ? -this.scrollparent.scrolltop() : (scrollisrootnode ? 0 : 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) - ($.browser.safari && this.cssposition == 'fixed' ? 0 : (this.cssposition == 'fixed' ? -this.scrollparent.scrollleft() : scrollisrootnode ? 0 : scroll.scrollleft()) * mod)) }; }, _generateposition: function(event){ var o = this.options, scroll = this.cssposition == 'absolute' && !(this.scrollparent[0] != document && $.ui.contains(this.scrollparent[0], this.offsetparent[0])) ? this.offsetparent : this.scrollparent, scrollisrootnode = (/(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(); } var pagex = event.pagex; var pagey = event.pagey; /* * - 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) { var 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; var 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) + ($.browser.safari && this.cssposition == 'fixed' ? 0 : (this.cssposition == 'fixed' ? -this.scrollparent.scrolltop() : (scrollisrootnode ? 0 : 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) + ($.browser.safari && this.cssposition == 'fixed' ? 0 : (this.cssposition == 'fixed' ? -this.scrollparent.scrollleft() : scrollisrootnode ? 0 : scroll.scrollleft()))) }; }, _clear: function(){ this.helper.removeclass("ui-draggable-dragging"); if (this.helper[0] != this.element[0] && !this.cancelhelperremoval) this.helper.remove(); //if($.ui.ddmanager) $.ui.ddmanager.current = null; this.helper = null; this.cancelhelperremoval = false; }, // from now on bulk stuff - mainly helpers _trigger: function(type, event, ui){ ui = ui || this._uihash(); $.ui.plugin.call(this, type, [event, ui]); if (type == "drag") this.positionabs = this._convertpositionto("absolute"); //the absolute position has to be recalculated after plugins return $.widget.prototype._trigger.call(this, type, event, ui); }, plugins: {}, _uihash: function(event){ return { helper: this.helper, position: this.position, absoluteposition: this.positionabs, //deprecated offset: this.positionabs }; } })); $.extend($.ui.draggable, { version: "1.7.2", eventprefix: "drag", defaults: { addclasses: true, appendto: "parent", axis: false, cancel: ":input,option", connecttosortable: false, containment: false, cursor: "auto", cursorat: false, delay: 0, distance: 1, grid: false, handle: false, helper: "original", iframefix: false, opacity: false, refreshpositions: false, revert: false, revertduration: 500, scope: "default", scroll: true, scrollsensitivity: 20, scrollspeed: 20, snap: false, snapmode: "both", snaptolerance: 20, stack: false, zindex: false, dragitem: false } }); $.ui.plugin.add("draggable", "connecttosortable", { start: function(event, ui){ var inst = $(this).data("draggable"), o = inst.options, uisortable = $.extend({}, ui, { item: inst.element }); inst.sortables = []; $(o.connecttosortable).each(function(){ var sortable = $.data(this, 'sortable'); if (sortable && !sortable.options.disabled) { inst.sortables.push({ instance: sortable, shouldrevert: sortable.options.revert }); sortable._refreshitems(); //do a one-time refresh at start to refresh the containercache sortable._trigger("activate", event, uisortable); } }); }, stop: function(event, ui){ //if we are still over the sortable, we fake the stop event of the sortable, but also remove helper var inst = $(this).data("draggable"), uisortable = $.extend({}, ui, { item: inst.element }), self = $(this); $.each(inst.sortables, function(){ if (this.instance.isover) { var index = 0; var parentid = this.instance.element.parent().attr('id'); var namespace = $(self).attr('namespace'); //判断父级是否是diy框架,如果等于 body-bg表示框架 //具体判断按照 diy_content 的父级而定 if (parentid !== "" && parentid != "body-bg") { var classs = this.instance.element.attr('class'), classes = classs.split(' '), needclass = classes.shift(),gid=$(self).attr('rel'); if (typeof(framearray[parentid][needclass]) == "object") { index = framearray[parentid][needclass].push("0"); } else { framearray[parentid][needclass] = new array; index = framearray[parentid][needclass].push("0"); } $.tbox.popup(site_url + "/index.php?app=page&mod=diy&act=getpopup&gid="+gid+"&tagname=" + namespace + "&index=" + (index - 1) + "&parentid=" + parentid + "&needclass=" + needclass + "&id=" + parentid + "-" + needclass + "-" + index, "添加模块", false, false, { "closed": function(){ $('#placeholder').remove(); } }); var button = '

'; $('#tbox .tb_button_list').show().html(button); $('#preview_button').click(function(){ preview(); }); $('#savemodel').click(function(){ savemodel(); $.tbox.close(); }); } this.instance.isover = 0; inst.cancelhelperremoval = true; //don't remove the helper in the draggable instance this.instance.cancelhelperremoval = false; //remove it in the sortable instance (so sortable plugins like revert still work) //the sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid' if (this.shouldrevert) this.instance.options.revert = true; //trigger the stop of the sortable this.instance._mousestop(event); this.instance.options.helper = this.instance.options._helper; //if the helper has been the original item, restore properties in the sortable if (inst.options.helper == 'original') this.instance.currentitem.css({ top: 'auto', left: 'auto' }); } else { this.instance.cancelhelperremoval = false; //remove the helper in the sortable instance this.instance._trigger("deactivate", event, uisortable); } }); }, drag: function(event, ui){ var inst = $(this).data("draggable"), self = this; var checkpos = function(o){ var dyclick = this.offset.click.top, dxclick = this.offset.click.left; var helpertop = this.positionabs.top, helperleft = this.positionabs.left; var itemheight = o.height, itemwidth = o.width; var itemtop = o.top, itemleft = o.left; return $.ui.isover(helpertop + dyclick, helperleft + dxclick, itemtop, itemleft, itemheight, itemwidth); }; $.each(inst.sortables, function(i){ var myinstance; var newid; //copy over some variables to allow calling the sortable's native _intersectswith this.instance.positionabs = inst.positionabs; this.instance.helperproportions = inst.helperproportions; this.instance.offset.click = inst.offset.click; if (this.instance._intersectswith(this.instance.containercache)) { //if it intersects, we use a little isover variable and set it once, so our move-in stuff gets fired only once if (!this.instance.isover) { //for (var test in inst.options.dragitem) { var needclass = $(self).attr('class'); needclass = needclass.split(' '); switch (needclass.shift()) { case "addframe": framecount++; newid = $(self).attr('rel') + "f" + framecount; var tempframetemplate = inst.options.dragitem[$(self).attr('rel')].clone(); framearray[newid] = new array(); framearray[newid]['html'] = tempframetemplate.html().replace(/(\s+)line_d_r/g, ''); myinstance = inst.options.dragitem[$(self).attr('rel')]; myinstance.children('.bg_diy_tit').find('a').attr('href', 'javascript:void(0)').attr('rel', newid) myinstance.attr('id', newid); break; case "addmodel": myinstance = inst.options.dragitem['placeholder']; //alert( this.instance.element.width()); myinstance.width(80); myinstance.height(25); myinstance.html('loading...'); break; } // } this.instance.isover = 1; //now we fake the start of dragging for the sortable instance, //by cloning the list group item, appending it to the sortable and using it as inst.currentitem //we can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) //this.instance.options.dragitem[$(self).attr('rel')].clone() this.instance.currentitem = myinstance.clone().appendto(this.instance.element).data("sortable-item", true); this.instance.options._helper = this.instance.options.helper; //store helper option to later restore it this.instance.options.helper = function(){ return ui.helper[0]; }; event.target = this.instance.currentitem[0]; this.instance._mousecapture(event, true); this.instance._mousestart(event, true, true); //because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes this.instance.offset.click.top = inst.offset.click.top; this.instance.offset.click.left = inst.offset.click.left; this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; inst._trigger("tosortable", event); inst.dropped = this.instance.element; //draggable revert needs that //hack so receive/update callbacks work (mostly) inst.currentitem = inst.element; this.instance.fromoutside = inst; } //provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable if (this.instance.currentitem) this.instance._mousedrag(event); } else { //if it doesn't intersect with the sortable, and it intersected before, //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelhelperremoval if (this.instance.isover) { this.instance.isover = 0; this.instance.cancelhelperremoval = true; //prevent reverting on this forced stop this.instance.options.revert = false; // the out event needs to be triggered independently this.instance._trigger('out', event, this.instance._uihash(this.instance)); this.instance._mousestop(event, true); this.instance.options.helper = this.instance.options._helper; //now we remove our currentitem, the list group clone again, and the placeholder, and animate the helper back to it's original size this.instance.currentitem.remove(); if (this.instance.placeholder) this.instance.placeholder.remove(); inst._trigger("fromsortable", event); inst.dropped = false; //draggable revert needs that } }; }); } }); $.ui.plugin.add("draggable", "cursor", { start: function(event, ui){ var t = $('body'), o = $(this).data('draggable').options; if (t.css("cursor")) o._cursor = t.css("cursor"); t.css("cursor", o.cursor); }, stop: function(event, ui){ var o = $(this).data('draggable').options; if (o._cursor) $('body').css("cursor", o._cursor); } }); $.ui.plugin.add("draggable", "iframefix", { start: function(event, ui){ var o = $(this).data('draggable').options; $(o.iframefix === true ? "iframe" : o.iframefix).each(function(){ $('
').css({ width: this.offsetwidth + "px", height: this.offsetheight + "px", position: "absolute", opacity: "0.001", zindex: 1000 }).css($(this).offset()).appendto("body"); }); }, stop: function(event, ui){ $("div.ui-draggable-iframefix").each(function(){ this.parentnode.removechild(this); }); //remove frame helpers } }); $.ui.plugin.add("draggable", "opacity", { start: function(event, ui){ var t = $(ui.helper), o = $(this).data('draggable').options; if (t.css("opacity")) o._opacity = t.css("opacity"); t.css('opacity', o.opacity); }, stop: function(event, ui){ var o = $(this).data('draggable').options; if (o._opacity) $(ui.helper).css('opacity', o._opacity); } }); $.ui.plugin.add("draggable", "scroll", { start: function(event, ui){ var i = $(this).data("draggable"); if (i.scrollparent[0] != document && i.scrollparent[0].tagname != 'html') i.overflowoffset = i.scrollparent.offset(); }, drag: function(event, ui){ var i = $(this).data("draggable"), o = i.options, scrolled = false; if (i.scrollparent[0] != document && i.scrollparent[0].tagname != 'html') { if (!o.axis || o.axis != 'x') { if ((i.overflowoffset.top + i.scrollparent[0].offsetheight) - event.pagey < o.scrollsensitivity) i.scrollparent[0].scrolltop = scrolled = i.scrollparent[0].scrolltop + o.scrollspeed; else if (event.pagey - i.overflowoffset.top < o.scrollsensitivity) i.scrollparent[0].scrolltop = scrolled = i.scrollparent[0].scrolltop - o.scrollspeed; } if (!o.axis || o.axis != 'y') { if ((i.overflowoffset.left + i.scrollparent[0].offsetwidth) - event.pagex < o.scrollsensitivity) i.scrollparent[0].scrollleft = scrolled = i.scrollparent[0].scrollleft + o.scrollspeed; else if (event.pagex - i.overflowoffset.left < o.scrollsensitivity) i.scrollparent[0].scrollleft = scrolled = i.scrollparent[0].scrollleft - o.scrollspeed; } } else { if (!o.axis || o.axis != 'x') { 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 (!o.axis || o.axis != 'y') { 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(i, event); } }); $.ui.plugin.add("draggable", "snap", { start: function(event, ui){ var i = $(this).data("draggable"), o = i.options; i.snapelements = []; $(o.snap.constructor != string ? (o.snap.items || ':data(draggable)') : o.snap).each(function(){ var $t = $(this); var $o = $t.offset(); if (this != i.element[0]) i.snapelements.push({ item: this, width: $t.outerwidth(), height: $t.outerheight(), top: $o.top, left: $o.left }); }); }, drag: function(event, ui){ var inst = $(this).data("draggable"), o = inst.options; var d = o.snaptolerance; var x1 = ui.offset.left, x2 = x1 + inst.helperproportions.width, y1 = ui.offset.top, y2 = y1 + inst.helperproportions.height; for (var i = inst.snapelements.length - 1; i >= 0; i--) { var l = inst.snapelements[i].left, r = l + inst.snapelements[i].width, t = inst.snapelements[i].top, b = t + inst.snapelements[i].height; //yes, i know, this is insane ;) if (!((l - d < x1 && x1 < r + d && t - d < y1 && y1 < b + d) || (l - d < x1 && x1 < r + d && t - d < y2 && y2 < b + d) || (l - d < x2 && x2 < r + d && t - d < y1 && y1 < b + d) || (l - d < x2 && x2 < r + d && t - d < y2 && y2 < b + d))) { if (inst.snapelements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uihash(), { snapitem: inst.snapelements[i].item }))); inst.snapelements[i].snapping = false; continue; } if (o.snapmode != 'inner') { var ts = math.abs(t - y2) <= d; var bs = math.abs(b - y1) <= d; var ls = math.abs(l - x2) <= d; var rs = math.abs(r - x1) <= d; if (ts) ui.position.top = inst._convertpositionto("relative", { top: t - inst.helperproportions.height, left: 0 }).top - inst.margins.top; if (bs) ui.position.top = inst._convertpositionto("relative", { top: b, left: 0 }).top - inst.margins.top; if (ls) ui.position.left = inst._convertpositionto("relative", { top: 0, left: l - inst.helperproportions.width }).left - inst.margins.left; if (rs) ui.position.left = inst._convertpositionto("relative", { top: 0, left: r }).left - inst.margins.left; } var first = (ts || bs || ls || rs); if (o.snapmode != 'outer') { var ts = math.abs(t - y1) <= d; var bs = math.abs(b - y2) <= d; var ls = math.abs(l - x1) <= d; var rs = math.abs(r - x2) <= d; if (ts) ui.position.top = inst._convertpositionto("relative", { top: t, left: 0 }).top - inst.margins.top; if (bs) ui.position.top = inst._convertpositionto("relative", { top: b - inst.helperproportions.height, left: 0 }).top - inst.margins.top; if (ls) ui.position.left = inst._convertpositionto("relative", { top: 0, left: l }).left - inst.margins.left; if (rs) ui.position.left = inst._convertpositionto("relative", { top: 0, left: r - inst.helperproportions.width }).left - inst.margins.left; } if (!inst.snapelements[i].snapping && (ts || bs || ls || rs || first)) (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uihash(), { snapitem: inst.snapelements[i].item }))); inst.snapelements[i].snapping = (ts || bs || ls || rs || first); }; } }); $.ui.plugin.add("draggable", "stack", { start: function(event, ui){ var o = $(this).data("draggable").options; var group = $.makearray($(o.stack.group)).sort(function(a, b){ return (parseint($(a).css("zindex"), 10) || o.stack.min) - (parseint($(b).css("zindex"), 10) || o.stack.min); }); $(group).each(function(i){ this.style.zindex = o.stack.min + i; }); this[0].style.zindex = o.stack.min + group.length; } }); $.ui.plugin.add("draggable", "zindex", { start: function(event, ui){ var t = $(ui.helper), o = $(this).data("draggable").options; if (t.css("zindex")) o._zindex = t.css("zindex"); t.css('zindex', o.zindex); }, stop: function(event, ui){ var o = $(this).data("draggable").options; if (o._zindex) $(ui.helper).css('zindex', o._zindex); } }); })(jquery);