From 05b1d23990fac44996fb0c8c88275260d7f869fb Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 27 Sep 2011 21:10:59 -0400 Subject: [PATCH 001/190] Draggable: Initial commit for new implementation, clone is only usable option --- ui/jquery.ui.draggable.js | 860 ++++++-------------------------------- 1 file changed, 137 insertions(+), 723 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 6475ebd6116..c3d3d8e9262 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -1,5 +1,5 @@ /* - * jQuery UI Draggable @VERSION + * jQuery UI Draggable 2.0.0 * * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. @@ -9,812 +9,226 @@ * * Depends: * jquery.ui.core.js - * jquery.ui.mouse.js * jquery.ui.widget.js */ (function( $, undefined ) { -$.widget("ui.draggable", $.ui.mouse, { - version: "@VERSION", +$.widget("ui.draggable", { widgetEventPrefix: "drag", options: { - addClasses: true, - appendTo: "parent", - axis: false, - connectToSortable: false, - containment: false, - cursor: "auto", - cursorAt: false, - 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 - }, - _create: 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(); + helper : false - return this; }, - _mouseCapture: function(event) { - - var o = this.options; - - // among others, prevent a drag on a resizable-handle - 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; - - $(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"); - }); + drag_el : false, // either element or the helper - return true; + position : {}, + offset : {}, - }, - - _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.positionAbs = this.element.offset(); - this.offset = { - top: this.offset.top - this.margins.top, - left: this.offset.left - this.margins.left - }; + _start_coords : {}, // start X/Y coords of mouse before drag + _start_position : {}, // start position of element before drag + _start_offset : {}, // start offset of element before drag - $.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.position = 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)); - - //Set a containment if given in the options - if(o.containment) - this._setContainment(); - - //Trigger event + callbacks - if(this._trigger("start", event) === false) { - this._clear(); - return false; - } - - //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 - - //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) - if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event); - - return true; - }, + _create: function() { - _mouseDrag: function(event, noPropagation) { + this.scrollParent = this.element.scrollParent(); - //Compute the helpers position - this.position = this._generatePosition(event); - this.positionAbs = this._convertPositionTo("absolute"); + // Static position elements can't be moved with top/left + if ( this.element.css( "position" ) === "static" ) { + this.element.css( "position", "relative" ); + } - //Call plugins and callbacks and use the resulting position if something is returned - if (!noPropagation) { - var ui = this._uiHash(); - if(this._trigger('drag', event, ui) === false) { - this._mouseUp({}); - return false; - } - this.position = ui.position; - } + // Prevent browser from hijacking drag + this.element.disableSelection(); - 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); + // Using proxy to avoid anon functions using self to pass "this" along + this.element.bind( "mousedown." + this.widgetName, $.proxy( this._mouseDown, this ) ); - return false; - }, + }, // _create - _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 the original element is removed, don't bother to continue - if(!this.element[0] || !this.element[0].parentNode) - return 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() { - if(self._trigger("stop", event) !== false) { - self._clear(); - } - }); - } else { - if(this._trigger("stop", event) !== false) { - this._clear(); - } - } - - return false; - }, - - _mouseUp: function(event) { - if (this.options.iframeFix === true) { - $("div.ui-draggable-iframeFix").each(function() { - this.parentNode.removeChild(this); - }); //Remove frame helpers - } - - //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) - if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event); - - return $.ui.mouse.prototype._mouseUp.call(this, event); - }, - - cancel: function() { - - if(this.helper.is(".ui-draggable-dragging")) { - this._mouseUp({}); - } else { - this._clear(); - } - + destroy: function() { return this; - - }, - - _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().removeAttr('id') : 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 (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(); + }, // destroy - // 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(); - } + _setPosition : function() { - 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 }; + var left, top, position, css_position; - return { - top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), - left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) - }; + // Helper is appended to body so offset of element is all that's needed + if ( this.options.helper === true ) { + return this.element.offset(); + } - }, + css_position = this.drag_el.css( "position" );; - _getRelativeOffset: function() { + // If fixed or absolute + if ( css_position !== "relative" ) { - 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 }; - } + position = this.drag_el.position(); - }, + if ( css_position === "absolute" ) { + return position; + } - _cacheMargins: function() { - this.margins = { - left: (parseInt(this.element.css("marginLeft"),10) || 0), - top: (parseInt(this.element.css("marginTop"),10) || 0), - right: (parseInt(this.element.css("marginRight"),10) || 0), - bottom: (parseInt(this.element.css("marginBottom"),10) || 0) - }; - }, + // Take into account scrollbar for fixed position + position.top = position.top - this.scrollParent.scrollTop(); + position.left = position.left - this.scrollParent.scrollLeft(); - _cacheHelperProportions: function() { - this.helperProportions = { - width: this.helper.outerWidth(), - height: this.helper.outerHeight() - }; - }, + return position; - _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 = [ - o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, - o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, - (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, - (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(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 c = $(o.containment); - var ce = c[0]; if(!ce) return; - var co = c.offset(); - var over = ($(ce).css("overflow") != 'hidden'); - - this.containment = [ - (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0), - (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0), - (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 - this.margins.right, - (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 - this.margins.bottom - ]; - this.relative_container = c; - - } else if(o.containment.constructor == Array) { - this.containment = o.containment; - } + } // css_position !+== absolute - }, + /** When using relative, css values are checked **/ - _convertPositionTo: function(d, pos) { + left = this.drag_el.css( "left" ); + top = this.drag_el.css( "top" ); - if(!pos) pos = this.position; - var mod = d == "absolute" ? 1 : -1; - var o = this.options, 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); + // Webkit will give back auto if there is nothing inline yet + left = ( left === "auto" ) ? 0 : parseInt( left, 10 ); + top = ( top === "auto" ) ? 0 : parseInt( top, 10 ); - 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 && $.browser.version < 526 && 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 && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) - ) - }; + return { - }, + left : left, + top : top - _generatePosition: function(event) { - - var o = this.options, 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); - 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 - var containment; - if(this.containment) { - if (this.relative_container){ - var co = this.relative_container.offset(); - containment = [ this.containment[0] + co.left, - this.containment[1] + co.top, - this.containment[2] + co.left, - this.containment[3] + co.top ]; - } - else { - containment = this.containment; - } - - if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left; - if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top; - if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left; - if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top; - } - - if(o.grid) { - //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) - var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; - pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; - - var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; - pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < 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 && $.browser.version < 526 && 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 && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) - ) - }; + }, // _setPosition - }, + _mouseDown : function( event ) { - _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; - }, + var el_position; + + this.drag_el = this.element; - // From now on bulk stuff - mainly helpers + // Helper required, so clone, hide, and set reference + if ( this.options.helper === true ) { - _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); - }, + this.drag_el = this.element.clone(); - plugins: {}, + // If source element has an ID, change ID of helper to avoid overlap + if ( this.element.attr( 'id' ) ) { - _uiHash: function(event) { - return { - helper: this.helper, - position: this.position, - originalPosition: this.originalPosition, - offset: this.positionAbs - }; - } + this.drag_el + .css({ + position : 'absolute', + display : 'none' + }) + .disableSelection() + .attr( 'id', this.element.attr( 'id' ) + '-' + this.widgetName ); -}); + } // id -$.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.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page). - sortable._trigger("activate", event, uiSortable); - } - }); + $('body').append( this.drag_el ); - }, - stop: function(event, ui) { + } // if this.options.helper = true - //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 }); + // Cache starting absolute and relative positions + this._start_position = this._setPosition(); + this._start_offset = this.drag_el.offset(); - $.each(inst.sortables, function() { - if(this.instance.isOver) { + // Cache current position and offset + this.position = $.extend( {}, this._start_position ); + this.offset = $.extend( {}, this._start_offset ); - this.instance.isOver = 0; + this._start_coords = { + left : event.clientX, + top : event.clientY + }; - 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) + this._trigger( "start", event ); - //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; + $(document).bind( "mousemove." + this.widgetName, $.proxy( this._mouseMove, this ) ); + $(document).bind( "mouseup." + this.widgetName, $.proxy( this._mouseUp, this ) ); - //Trigger the stop of the sortable - this.instance._mouseStop(event); - this.instance.options.helper = this.instance.options._helper; + // Set the helper up by actual element + if ( this.options.helper === true ) { - //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' }); + // get the absolute position of element so that helper will know where to go + el_offset = this.element.offset(); - } else { - this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance - this.instance._trigger("deactivate", event, uiSortable); - } + this.drag_el.css({ + display : 'block', + top : el_offset.top + 'px', + left : el_offset.left + 'px' + }); - }); + } // this.options.height = true - }, - drag: function(event, ui) { + }, // _mouseDown - var inst = $(this).data("draggable"), self = this; + _mouseMove : function( event ) { - 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; + var left_diff = event.clientX - this._start_coords.left, + top_diff = event.clientY - this._start_coords.top, + new_left = left_diff + this._start_position.left, + new_top = top_diff + this._start_position.top; - return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth); - }; + this.position = { + left : new_left, + top : new_top + }; - $.each(inst.sortables, function(i) { - - //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) { - - 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.currentItem = $(self).clone().removeAttr('id').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 - } - - }; - - }); - - } -}); + // Refresh offset cache with new positions + this.offset.left = this._start_offset.left + new_left; + this.offset.top = this._start_offset.top + new_top; -$.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); - } -}); + this._trigger( "drag", event ); -$.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); - } -}); + // User overriding left/top so shortcut math is no longer valid + if ( new_left !== this.position.left || new_top !== this.position.top ) { -$.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) { + // refresh offset using slower functions + this.offset = this.drag_el.offset(); - var i = $(this).data("draggable"), o = i.options, scrolled = false; + } - if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') { + this.drag_el.css({ - 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; - } + left : this.position.left + 'px', + top : this.position.top + 'px' - 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 { + }, // _mouseMove - 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); - } + _mouseUp : function( event ) { - 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); - } + this._trigger( "stop", event ); - } + this._start_coords = {}; - if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) - $.ui.ddmanager.prepareOffsets(i, event); + if ( this.options.helper === true ) { + this.drag_el.remove(); + } - } -}); + $(document).unbind( "mousemove." + this.widgetName ); + $(document).unbind( "mouseup." + this.widgetName ); -$.ui.plugin.add("draggable", "snap", { - start: function(event, ui) { + }, // _mouseUp - var i = $(this).data("draggable"), o = i.options; - i.snapElements = []; + _trigger: function(type, event, ui) { - $(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 - }); - }); + ui = ui || this._uiHash(); - }, - 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); + return $.Widget.prototype._trigger.call(this, type, event, ui); + }, // _trigger + _uiHash: function(event) { + return { + position : this.position, + offset : this.offset }; + } // _uiHash - } }); -$.ui.plugin.add("draggable", "stack", { - start: function(event, ui) { - - var o = $(this).data("draggable").options; - - var group = $.makeArray($(o.stack)).sort(function(a,b) { - return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); - }); - if (!group.length) { return; } - - var min = parseInt(group[0].style.zIndex) || 0; - $(group).each(function(i) { - this.style.zIndex = min + i; - }); - - this[0].style.zIndex = min + group.length; - - } +$.extend($.ui.draggable, { + version: "2.0.0" }); -$.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); From cb828a52bd814c540cc7dece45b5066c1191c23d Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 27 Sep 2011 21:33:38 -0400 Subject: [PATCH 002/190] Draggable: Code style better matching style guideline --- ui/jquery.ui.draggable.js | 268 ++++++++++++++++++++------------------ 1 file changed, 139 insertions(+), 129 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index c3d3d8e9262..64f66741922 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -14,215 +14,225 @@ (function( $, undefined ) { $.widget("ui.draggable", { + widgetEventPrefix: "drag", + options: { - helper : false + helper : false }, - drag_el : false, // either element or the helper + // Either initialized element or the helper + dragEl : false, - position : {}, - offset : {}, + position : {}, + offset : {}, - _start_coords : {}, // start X/Y coords of mouse before drag - _start_position : {}, // start position of element before drag - _start_offset : {}, // start offset of element before drag + // Start X/Y coords of mouse before drag + startCoords : {}, - _create: function() { + // Start position of element before drag + startPosition : {}, - this.scrollParent = this.element.scrollParent(); + // Start offset of element before drag + startOffset : {}, - // Static position elements can't be moved with top/left - if ( this.element.css( "position" ) === "static" ) { - this.element.css( "position", "relative" ); - } + // TODO: actually remove data + destroy: function() { + return this; + }, - // Prevent browser from hijacking drag - this.element.disableSelection(); + _create: function() { - // Using proxy to avoid anon functions using self to pass "this" along - this.element.bind( "mousedown." + this.widgetName, $.proxy( this._mouseDown, this ) ); + this.scrollParent = this.element.scrollParent(); - }, // _create + // Static position elements can"t be moved with top/left + if ( this.element.css( "position" ) === "static" ) { + this.element.css( "position", "relative" ); + } - destroy: function() { - return this; - }, // destroy + // Prevent browser from hijacking drag + this.element.disableSelection(); + + // Using proxy to avoid anon functions using self to pass "this" along + this.element.bind( "mousedown." + this.widgetName, $.proxy( this._mouseDown, this ) ); - _setPosition : function() { + }, - var left, top, position, css_position; + _setPosition : function() { - // Helper is appended to body so offset of element is all that's needed - if ( this.options.helper === true ) { - return this.element.offset(); - } + var left, top, position, cssPosition; - css_position = this.drag_el.css( "position" );; + // Helper is appended to body so offset of element is all that"s needed + if ( this.options.helper === true ) { + return this.element.offset(); + } - // If fixed or absolute - if ( css_position !== "relative" ) { + cssPosition = this.dragEl.css( "position" );; - position = this.drag_el.position(); + // If fixed or absolute + if ( cssPosition !== "relative" ) { - if ( css_position === "absolute" ) { - return position; - } + position = this.dragEl.position(); - // Take into account scrollbar for fixed position - position.top = position.top - this.scrollParent.scrollTop(); - position.left = position.left - this.scrollParent.scrollLeft(); + if ( cssPosition === "absolute" ) { + return position; + } - return position; + // Take into account scrollbar for fixed position + position.top = position.top - this.scrollParent.scrollTop(); + position.left = position.left - this.scrollParent.scrollLeft(); - } // css_position !+== absolute + return position; - /** When using relative, css values are checked **/ + } // cssPosition !+== absolute - left = this.drag_el.css( "left" ); - top = this.drag_el.css( "top" ); + /** When using relative, css values are checked **/ - // Webkit will give back auto if there is nothing inline yet - left = ( left === "auto" ) ? 0 : parseInt( left, 10 ); - top = ( top === "auto" ) ? 0 : parseInt( top, 10 ); + left = this.dragEl.css( "left" ); + top = this.dragEl.css( "top" ); - return { + // Webkit will give back auto if there is nothing inline yet + left = ( left === "auto" ) ? 0 : parseInt( left, 10 ); + top = ( top === "auto" ) ? 0 : parseInt( top, 10 ); + + return { - left : left, - top : top + left : left, + top : top - }; + }; - }, // _setPosition + }, - _mouseDown : function( event ) { + _mouseDown : function( event ) { - var el_position; - - this.drag_el = this.element; + this.dragEl = this.element; - // Helper required, so clone, hide, and set reference - if ( this.options.helper === true ) { + // Helper required, so clone, hide, and set reference + if ( this.options.helper === true ) { - this.drag_el = this.element.clone(); + this.dragEl = this.element.clone(); - // If source element has an ID, change ID of helper to avoid overlap - if ( this.element.attr( 'id' ) ) { + // If source element has an ID, change ID of helper to avoid overlap + if ( this.element.attr( "id" ) ) { - this.drag_el - .css({ - position : 'absolute', - display : 'none' - }) - .disableSelection() - .attr( 'id', this.element.attr( 'id' ) + '-' + this.widgetName ); + this.dragEl + .css({ + position : "absolute", + display : "none" + }) + .disableSelection() + .attr( "id", this.element.attr( "id" ) + "-" + this.widgetName ); - } // id + } // id - $('body').append( this.drag_el ); + $( "body" ).append( this.dragEl ); - } // if this.options.helper = true + } // if this.options.helper = true - // Cache starting absolute and relative positions - this._start_position = this._setPosition(); - this._start_offset = this.drag_el.offset(); + // Cache starting absolute and relative positions + this.startPosition = this._setPosition(); + this.startOffset = this.dragEl.offset(); - // Cache current position and offset - this.position = $.extend( {}, this._start_position ); - this.offset = $.extend( {}, this._start_offset ); + // Cache current position and offset + this.position = $.extend( {}, this.startPosition ); + this.offset = $.extend( {}, this.startOffset ); - this._start_coords = { - left : event.clientX, - top : event.clientY - }; + this.startCoords = { + left : event.clientX, + top : event.clientY + }; - this._trigger( "start", event ); + this._trigger( "start", event ); - $(document).bind( "mousemove." + this.widgetName, $.proxy( this._mouseMove, this ) ); - $(document).bind( "mouseup." + this.widgetName, $.proxy( this._mouseUp, this ) ); + $(document).bind( "mousemove." + this.widgetName, $.proxy( this._mouseMove, this ) ); + $(document).bind( "mouseup." + this.widgetName, $.proxy( this._mouseUp, this ) ); - // Set the helper up by actual element - if ( this.options.helper === true ) { + // Set the helper up by actual element + if ( this.options.helper === true ) { - // get the absolute position of element so that helper will know where to go - el_offset = this.element.offset(); + // get the absolute position of element so that helper will know where to go + elOffset = this.element.offset(); - this.drag_el.css({ - display : 'block', - top : el_offset.top + 'px', - left : el_offset.left + 'px' - }); + this.dragEl.css({ + display : "block", + top : elOffset.top + "px", + left : elOffset.left + "px" + }); - } // this.options.height = true + } // this.options.height = true - }, // _mouseDown + }, - _mouseMove : function( event ) { + _mouseMove : function( event ) { - var left_diff = event.clientX - this._start_coords.left, - top_diff = event.clientY - this._start_coords.top, - new_left = left_diff + this._start_position.left, - new_top = top_diff + this._start_position.top; + var leftDiff = event.clientX - this.startCoords.left, + topDiff = event.clientY - this.startCoords.top, + newLeft = leftDiff + this.startPosition.left, + newTop = topDiff + this.startPosition.top; - this.position = { - left : new_left, - top : new_top - }; + this.position = { + left : newLeft, + top : newTop + }; - // Refresh offset cache with new positions - this.offset.left = this._start_offset.left + new_left; - this.offset.top = this._start_offset.top + new_top; + // Refresh offset cache with new positions + this.offset.left = this.startOffset.left + newLeft; + this.offset.top = this.startOffset.top + newTop; - this._trigger( "drag", event ); + this._trigger( "drag", event ); - // User overriding left/top so shortcut math is no longer valid - if ( new_left !== this.position.left || new_top !== this.position.top ) { + // User overriding left/top so shortcut math is no longer valid + if ( newLeft !== this.position.left || newTop !== this.position.top ) { - // refresh offset using slower functions - this.offset = this.drag_el.offset(); + // refresh offset using slower functions + this.offset = this.dragEl.offset(); - } + } - this.drag_el.css({ + this.dragEl.css({ - left : this.position.left + 'px', - top : this.position.top + 'px' + left : this.position.left + "px", + top : this.position.top + "px" - }); + }); - }, // _mouseMove + }, _mouseUp : function( event ) { - this._trigger( "stop", event ); + this._trigger( "stop", event ); - this._start_coords = {}; + this.startCoords = {}; - if ( this.options.helper === true ) { - this.drag_el.remove(); - } + if ( this.options.helper === true ) { + this.dragEl.remove(); + } - $(document).unbind( "mousemove." + this.widgetName ); - $(document).unbind( "mouseup." + this.widgetName ); + $(document).unbind( "mousemove." + this.widgetName ); + $(document).unbind( "mouseup." + this.widgetName ); - }, // _mouseUp + }, - _trigger: function(type, event, ui) { + _trigger: function( type, event, ui ) { ui = ui || this._uiHash(); - return $.Widget.prototype._trigger.call(this, type, event, ui); - }, // _trigger + return $.Widget.prototype._trigger.call( this, type, event, ui ); + + }, _uiHash: function(event) { + return { position : this.position, - offset : this.offset + offset : this.offset }; - } // _uiHash + + } }); From d85c67dd9677d75b6d7046b048173573f3379a2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 27 Sep 2011 22:02:07 -0400 Subject: [PATCH 003/190] whitespace --- ui/jquery.ui.draggable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 64f66741922..bdef17f22fd 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -13,7 +13,7 @@ */ (function( $, undefined ) { -$.widget("ui.draggable", { +$.widget( "ui.draggable", { widgetEventPrefix: "drag", From 1f23656fe28ba413e7d9a927a644b24c39b8270f Mon Sep 17 00:00:00 2001 From: = Date: Sat, 1 Oct 2011 12:05:36 -0400 Subject: [PATCH 004/190] Draggable: Fixed coding style, moved properties out of prototype --- ui/jquery.ui.draggable.js | 94 +++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index bdef17f22fd..13cd22b2ce1 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -19,31 +19,31 @@ $.widget( "ui.draggable", { options: { - helper : false + helper: false }, - // Either initialized element or the helper - dragEl : false, - - position : {}, - offset : {}, - - // Start X/Y coords of mouse before drag - startCoords : {}, - - // Start position of element before drag - startPosition : {}, - - // Start offset of element before drag - startOffset : {}, - // TODO: actually remove data destroy: function() { - return this; + return this; }, _create: function() { + + // Either initialized element or the helper + this.dragEl = false, + + this.position = {}, + this.offset = {}, + + // Start X/Y coords of mouse before drag + this.startCoords = {}, + + // Start position of element before drag + this.startPosition = {}, + + // Start offset of element before drag + this.startOffset = {}, this.scrollParent = this.element.scrollParent(); @@ -60,7 +60,7 @@ $.widget( "ui.draggable", { }, - _setPosition : function() { + _setPosition: function() { var left, top, position, cssPosition; @@ -81,7 +81,7 @@ $.widget( "ui.draggable", { } // Take into account scrollbar for fixed position - position.top = position.top - this.scrollParent.scrollTop(); + position.top = position.top - this.scrollParent.scrollTop(); position.left = position.left - this.scrollParent.scrollLeft(); return position; @@ -91,22 +91,22 @@ $.widget( "ui.draggable", { /** When using relative, css values are checked **/ left = this.dragEl.css( "left" ); - top = this.dragEl.css( "top" ); + top = this.dragEl.css( "top" ); // Webkit will give back auto if there is nothing inline yet - left = ( left === "auto" ) ? 0 : parseInt( left, 10 ); - top = ( top === "auto" ) ? 0 : parseInt( top, 10 ); + left = ( left === "auto" ) ? 0: parseInt( left, 10 ); + top = ( top === "auto" ) ? 0: parseInt( top, 10 ); return { - left : left, - top : top + left: left, + top: top }; }, - _mouseDown : function( event ) { + _mouseDown: function( event ) { this.dragEl = this.element; @@ -120,8 +120,8 @@ $.widget( "ui.draggable", { this.dragEl .css({ - position : "absolute", - display : "none" + position: "absolute", + display: "none" }) .disableSelection() .attr( "id", this.element.attr( "id" ) + "-" + this.widgetName ); @@ -134,15 +134,15 @@ $.widget( "ui.draggable", { // Cache starting absolute and relative positions this.startPosition = this._setPosition(); - this.startOffset = this.dragEl.offset(); + this.startOffset = this.dragEl.offset(); // Cache current position and offset this.position = $.extend( {}, this.startPosition ); - this.offset = $.extend( {}, this.startOffset ); + this.offset = $.extend( {}, this.startOffset ); this.startCoords = { - left : event.clientX, - top : event.clientY + left: event.clientX, + top: event.clientY }; this._trigger( "start", event ); @@ -158,30 +158,30 @@ $.widget( "ui.draggable", { elOffset = this.element.offset(); this.dragEl.css({ - display : "block", - top : elOffset.top + "px", - left : elOffset.left + "px" + display: "block", + top: elOffset.top + "px", + left: elOffset.left + "px" }); } // this.options.height = true }, - _mouseMove : function( event ) { + _mouseMove: function( event ) { var leftDiff = event.clientX - this.startCoords.left, - topDiff = event.clientY - this.startCoords.top, - newLeft = leftDiff + this.startPosition.left, - newTop = topDiff + this.startPosition.top; + topDiff = event.clientY - this.startCoords.top, + newLeft = leftDiff + this.startPosition.left, + newTop = topDiff + this.startPosition.top; this.position = { - left : newLeft, - top : newTop + left: newLeft, + top: newTop }; // Refresh offset cache with new positions this.offset.left = this.startOffset.left + newLeft; - this.offset.top = this.startOffset.top + newTop; + this.offset.top = this.startOffset.top + newTop; this._trigger( "drag", event ); @@ -189,20 +189,20 @@ $.widget( "ui.draggable", { if ( newLeft !== this.position.left || newTop !== this.position.top ) { // refresh offset using slower functions - this.offset = this.dragEl.offset(); + this.offset = this.dragEl.offset(); } this.dragEl.css({ - left : this.position.left + "px", - top : this.position.top + "px" + left: this.position.left + "px", + top: this.position.top + "px" }); }, - _mouseUp : function( event ) { + _mouseUp: function( event ) { this._trigger( "stop", event ); @@ -228,8 +228,8 @@ $.widget( "ui.draggable", { _uiHash: function(event) { return { - position : this.position, - offset : this.offset + position: this.position, + offset: this.offset }; } From 7ef6df95ebcd487e5f7284264fa59814a771ceb6 Mon Sep 17 00:00:00 2001 From: = Date: Sat, 1 Oct 2011 12:38:48 -0400 Subject: [PATCH 005/190] Draggable: Helper option can now take function that returns DOMElement --- ui/jquery.ui.draggable.js | 60 ++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 13cd22b2ce1..0ac364bc9c1 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -29,7 +29,7 @@ $.widget( "ui.draggable", { }, _create: function() { - + // Either initialized element or the helper this.dragEl = false, @@ -59,13 +59,17 @@ $.widget( "ui.draggable", { this.element.bind( "mousedown." + this.widgetName, $.proxy( this._mouseDown, this ) ); }, + + _usingHelper : function() { + return ( this.options.helper === true || typeof this.options.helper === 'function' ); + }, _setPosition: function() { var left, top, position, cssPosition; - // Helper is appended to body so offset of element is all that"s needed - if ( this.options.helper === true ) { + // Helper is appended to body so offset of element is all that's needed + if ( this._usingHelper() ) { return this.element.offset(); } @@ -86,7 +90,7 @@ $.widget( "ui.draggable", { return position; - } // cssPosition !+== absolute + } /** When using relative, css values are checked **/ @@ -108,29 +112,47 @@ $.widget( "ui.draggable", { _mouseDown: function( event ) { + // The actual dragging element, should always be a jQuery object this.dragEl = this.element; // Helper required, so clone, hide, and set reference - if ( this.options.helper === true ) { + if ( this._usingHelper() ) { + + // If getting a cloned helper + if ( this.options.helper === true ) { + + this.dragEl = this.element.clone(); - this.dragEl = this.element.clone(); + // If source element has an ID, change ID of helper to avoid overlap + if ( this.element.attr( "id" ) ) { - // If source element has an ID, change ID of helper to avoid overlap - if ( this.element.attr( "id" ) ) { + this.dragEl.attr( "id", this.element.attr( "id" ) + "-" + this.widgetName ); - this.dragEl + } + + } else { + + this.dragEl = this.options.helper(); + + // If function was passed, it should return a DOMElement + if ( typeof this.dragEl.nodeType !== 'number' ) { + throw "Helper function must return a DOMElement"; + } + + this.dragEl = $( this.dragEl ); + + } + + // Automatically make helper absolute + this.dragEl .css({ - position: "absolute", - display: "none" + position: "absolute" }) - .disableSelection() - .attr( "id", this.element.attr( "id" ) + "-" + this.widgetName ); - - } // id + .disableSelection(); $( "body" ).append( this.dragEl ); - } // if this.options.helper = true + } // Cache starting absolute and relative positions this.startPosition = this._setPosition(); @@ -152,7 +174,7 @@ $.widget( "ui.draggable", { // Set the helper up by actual element - if ( this.options.helper === true ) { + if ( this._usingHelper() ) { // get the absolute position of element so that helper will know where to go elOffset = this.element.offset(); @@ -163,7 +185,7 @@ $.widget( "ui.draggable", { left: elOffset.left + "px" }); - } // this.options.height = true + } }, @@ -208,7 +230,7 @@ $.widget( "ui.draggable", { this.startCoords = {}; - if ( this.options.helper === true ) { + if ( this._usingHelper() ) { this.dragEl.remove(); } From 7745d61a24ccaded65cabc54659825565fca2cfd Mon Sep 17 00:00:00 2001 From: = Date: Sat, 8 Oct 2011 23:30:03 -0400 Subject: [PATCH 006/190] Draggable: No longer using disableSelection in favor of preventDefault --- ui/jquery.ui.draggable.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 0ac364bc9c1..b4e166d3e1a 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -52,9 +52,6 @@ $.widget( "ui.draggable", { this.element.css( "position", "relative" ); } - // Prevent browser from hijacking drag - this.element.disableSelection(); - // Using proxy to avoid anon functions using self to pass "this" along this.element.bind( "mousedown." + this.widgetName, $.proxy( this._mouseDown, this ) ); @@ -111,6 +108,9 @@ $.widget( "ui.draggable", { }, _mouseDown: function( event ) { + + // Stop browser from highlighting, among other things + event.preventDefault(); // The actual dragging element, should always be a jQuery object this.dragEl = this.element; @@ -147,8 +147,7 @@ $.widget( "ui.draggable", { this.dragEl .css({ position: "absolute" - }) - .disableSelection(); + }); $( "body" ).append( this.dragEl ); From e43ce91212745beb0cca0fe75e18f9a89a8d6222 Mon Sep 17 00:00:00 2001 From: = Date: Sat, 8 Oct 2011 23:34:26 -0400 Subject: [PATCH 007/190] Draggable: No longer overwriting _trigger --- ui/jquery.ui.draggable.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index b4e166d3e1a..5816ca6a8b0 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -238,14 +238,6 @@ $.widget( "ui.draggable", { }, - _trigger: function( type, event, ui ) { - - ui = ui || this._uiHash(); - - return $.Widget.prototype._trigger.call( this, type, event, ui ); - - }, - _uiHash: function(event) { return { From c8e13708eb90728978a119c6adeef3010ff332e7 Mon Sep 17 00:00:00 2001 From: = Date: Sun, 9 Oct 2011 00:54:47 -0400 Subject: [PATCH 008/190] Draggable: Scrollbars being handled when scrollParent is document --- ui/jquery.ui.draggable.js | 107 +++++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 30 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 5816ca6a8b0..2fa52cc809d 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -19,6 +19,8 @@ $.widget( "ui.draggable", { options: { + scrollSpeed: 20, + scrollSensitivity:20, helper: false }, @@ -47,43 +49,48 @@ $.widget( "ui.draggable", { this.scrollParent = this.element.scrollParent(); + // Offset of scrollParent, used for auto-scrolling + this.overflowOffset = {}; + + // Height of scrollParent, used for auto-scrolling + this.overflowHeight = 0; + + // Width of scrollParent, used for auto-scrolling + this.overflowWidth = 0; + // Static position elements can"t be moved with top/left if ( this.element.css( "position" ) === "static" ) { this.element.css( "position", "relative" ); } - + // Using proxy to avoid anon functions using self to pass "this" along this.element.bind( "mousedown." + this.widgetName, $.proxy( this._mouseDown, this ) ); }, - + _usingHelper : function() { return ( this.options.helper === true || typeof this.options.helper === 'function' ); }, _setPosition: function() { - var left, top, position, cssPosition; + var left, top, position, + scrollTop = this.scrollParent.scrollTop(), + scrollLeft = this.scrollParent.scrollLeft(); // Helper is appended to body so offset of element is all that's needed if ( this._usingHelper() ) { return this.element.offset(); } - cssPosition = this.dragEl.css( "position" );; - // If fixed or absolute - if ( cssPosition !== "relative" ) { + if ( this.cssPosition !== "relative" ) { position = this.dragEl.position(); - if ( cssPosition === "absolute" ) { - return position; - } - - // Take into account scrollbar for fixed position - position.top = position.top - this.scrollParent.scrollTop(); - position.left = position.left - this.scrollParent.scrollLeft(); + // Take into account scrollbar + position.top = position.top - scrollTop; + position.left = position.left - scrollLeft return position; @@ -100,20 +107,22 @@ $.widget( "ui.draggable", { return { - left: left, - top: top + left: left - scrollLeft, + top: top - scrollTop }; }, _mouseDown: function( event ) { - + // Stop browser from highlighting, among other things event.preventDefault(); // The actual dragging element, should always be a jQuery object this.dragEl = this.element; + + this.cssPosition = this.dragEl.css( "position" ); // Helper required, so clone, hide, and set reference if ( this._usingHelper() ) { @@ -131,16 +140,16 @@ $.widget( "ui.draggable", { } } else { - + this.dragEl = this.options.helper(); - + // If function was passed, it should return a DOMElement if ( typeof this.dragEl.nodeType !== 'number' ) { throw "Helper function must return a DOMElement"; } - + this.dragEl = $( this.dragEl ); - + } // Automatically make helper absolute @@ -166,10 +175,15 @@ $.widget( "ui.draggable", { top: event.clientY }; + // Cache the offset of scrollParent + this.overflowOffset = this.scrollParent.offset(); + this.overflowHeight = ( this.scrollParent[0] === document ) ? $(window).height() : this.scrollParent.height(); + this.overflowWidth = ( this.scrollParent[0] === document ) ? $(window).width() : this.scrollParent.width(); + this._trigger( "start", event ); - $(document).bind( "mousemove." + this.widgetName, $.proxy( this._mouseMove, this ) ); - $(document).bind( "mouseup." + this.widgetName, $.proxy( this._mouseUp, this ) ); + $(document).bind( "mousemove." + this.widgetName, $.proxy( this._mouseMove, this ) ) + .bind( "mouseup." + this.widgetName, $.proxy( this._mouseUp, this ) ); // Set the helper up by actual element @@ -189,11 +203,11 @@ $.widget( "ui.draggable", { }, _mouseMove: function( event ) { - + var leftDiff = event.clientX - this.startCoords.left, - topDiff = event.clientY - this.startCoords.top, - newLeft = leftDiff + this.startPosition.left, - newTop = topDiff + this.startPosition.top; + topDiff = event.clientY - this.startCoords.top, + newLeft = leftDiff + this.startPosition.left, + newTop = topDiff + this.startPosition.top; this.position = { left: newLeft, @@ -213,18 +227,51 @@ $.widget( "ui.draggable", { this.offset = this.dragEl.offset(); } + + newLeft = this.position.left; + newTop = this.position.top; + + if ( this.cssPosition !== 'fixed' ) { + + newLeft = newLeft + this.scrollParent.scrollLeft(); + newTop = newTop + this.scrollParent.scrollTop(); + + } this.dragEl.css({ - left: this.position.left + "px", - top: this.position.top + "px" + left: newLeft + "px", + top: newTop + "px" }); + + // Scroll the scrollParent, if needed + this._handleScrolling( event ); + + }, + + _handleScrolling: function( event ) { + + var doc = $(document), + scrollTop = doc.scrollTop(), + scrollLeft = doc.scrollLeft(); + + // Handle vertical scrolling + if ( ( ( this.overflowHeight + scrollTop ) - event.pageY ) < this.options.scrollSensitivity ) { + doc.scrollTop( scrollTop + this.options.scrollSpeed ); + } + + // Handle horizontal scrolling + if ( ( ( this.overflowWidth + scrollLeft ) - event.pageX ) < this.options.scrollSensitivity ) { + doc.scrollLeft( scrollLeft + this.options.scrollSpeed ); + } }, _mouseUp: function( event ) { + var doc = $(document); + this._trigger( "stop", event ); this.startCoords = {}; @@ -233,8 +280,8 @@ $.widget( "ui.draggable", { this.dragEl.remove(); } - $(document).unbind( "mousemove." + this.widgetName ); - $(document).unbind( "mouseup." + this.widgetName ); + doc.unbind( "mousemove." + this.widgetName ); + doc.unbind( "mouseup." + this.widgetName ); }, From ee094ccf4ddc20e75cf0b6c3ed752f1302336eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 14 Oct 2011 14:19:04 -0400 Subject: [PATCH 009/190] Draggable: Cleanup. --- ui/jquery.ui.draggable.js | 239 +++++++++++++------------------------- 1 file changed, 78 insertions(+), 161 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 2fa52cc809d..1e9fb4cda3b 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -1,11 +1,11 @@ /* - * jQuery UI Draggable 2.0.0 + * jQuery UI Draggable @VERSION * * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * - * http://docs.jquery.com/UI/Draggables + * http://docs.jquery.com/UI/Draggable * * Depends: * jquery.ui.core.js @@ -14,90 +14,59 @@ (function( $, undefined ) { $.widget( "ui.draggable", { - + version: "@VERSION", widgetEventPrefix: "drag", options: { - - scrollSpeed: 20, - scrollSensitivity:20, - helper: false - + helper: false, + scrollSensitivity: 20, + scrollSpeed: 20 }, - // TODO: actually remove data - destroy: function() { - return this; - }, + // dragEl: element being dragged (original or helper) + // position: CSS position of dragEl + // offset: offset of dragEl + // startCoords: clientX/Y of the mousedown (offset of pointer) + // startPosition: CSS position prior to drag start + // startOffset: offset prior to drag start + // overflowOffset: offset of scroll parent + // overflowHeight: height of scroll parent + // overflowWidth: width of scroll parent _create: function() { - - // Either initialized element or the helper - this.dragEl = false, - - this.position = {}, - this.offset = {}, - - // Start X/Y coords of mouse before drag - this.startCoords = {}, - - // Start position of element before drag - this.startPosition = {}, - - // Start offset of element before drag - this.startOffset = {}, + // TODO: add these to the base widget + this.doc = $( this.element[0].ownerDocument ); + this.win = $( this.doc[0].defaultView ); this.scrollParent = this.element.scrollParent(); - // Offset of scrollParent, used for auto-scrolling - this.overflowOffset = {}; - - // Height of scrollParent, used for auto-scrolling - this.overflowHeight = 0; - - // Width of scrollParent, used for auto-scrolling - this.overflowWidth = 0; - - // Static position elements can"t be moved with top/left + // Static position elements can't be moved with top/left if ( this.element.css( "position" ) === "static" ) { this.element.css( "position", "relative" ); } - - // Using proxy to avoid anon functions using self to pass "this" along - this.element.bind( "mousedown." + this.widgetName, $.proxy( this._mouseDown, this ) ); - - }, - _usingHelper : function() { - return ( this.options.helper === true || typeof this.options.helper === 'function' ); + // TODO: use _bind() + this.element.bind( "mousedown." + this.widgetName, $.proxy( this, "_mouseDown" ) ); }, - _setPosition: function() { - + // TODO: why is relative handled differently than fixed/absolute? + _getPosition: function() { var left, top, position, - scrollTop = this.scrollParent.scrollTop(), - scrollLeft = this.scrollParent.scrollLeft(); - - // Helper is appended to body so offset of element is all that's needed - if ( this._usingHelper() ) { - return this.element.offset(); - } + scrollTop = this.scrollParent.scrollTop(), + scrollLeft = this.scrollParent.scrollLeft(); // If fixed or absolute if ( this.cssPosition !== "relative" ) { - position = this.dragEl.position(); // Take into account scrollbar - position.top = position.top - scrollTop; - position.left = position.left - scrollLeft + position.top -= scrollTop; + position.left -= scrollLeft return position; - } - /** When using relative, css values are checked **/ - + // When using relative, css values are checked left = this.dragEl.css( "left" ); top = this.dragEl.css( "top" ); @@ -106,64 +75,42 @@ $.widget( "ui.draggable", { top = ( top === "auto" ) ? 0: parseInt( top, 10 ); return { - left: left - scrollLeft, top: top - scrollTop - }; - }, _mouseDown: function( event ) { - - // Stop browser from highlighting, among other things - event.preventDefault(); + // Prevent text selection, among other things + event.preventDefault(); // The actual dragging element, should always be a jQuery object this.dragEl = this.element; - this.cssPosition = this.dragEl.css( "position" ); - // Helper required, so clone, hide, and set reference - if ( this._usingHelper() ) { - - // If getting a cloned helper + // Helper required + if ( this.options.helper ) { + // clone if ( this.options.helper === true ) { - - this.dragEl = this.element.clone(); - // If source element has an ID, change ID of helper to avoid overlap + this.dragEl = this.element.clone(); if ( this.element.attr( "id" ) ) { - this.dragEl.attr( "id", this.element.attr( "id" ) + "-" + this.widgetName ); - } - } else { - - this.dragEl = this.options.helper(); - - // If function was passed, it should return a DOMElement - if ( typeof this.dragEl.nodeType !== 'number' ) { - throw "Helper function must return a DOMElement"; - } - - this.dragEl = $( this.dragEl ); - + // TODO: figure out the signature for this; see #4957 + this.dragEl = $( this.options.helper() ); } - // Automatically make helper absolute this.dragEl - .css({ - position: "absolute" - }); - - $( "body" ).append( this.dragEl ); - + // TODO: should we move this to the stylesheet and use a class? + .css( "position", "absolute" ) + .appendTo( this.doc[0].body ) + .offset( this.element.offset() ); } // Cache starting absolute and relative positions - this.startPosition = this._setPosition(); + this.startPosition = this._getPosition(); this.startOffset = this.dragEl.offset(); // Cache current position and offset @@ -176,38 +123,28 @@ $.widget( "ui.draggable", { }; // Cache the offset of scrollParent + // TODO: store overflow height/width in a hash instead of separate properties this.overflowOffset = this.scrollParent.offset(); - this.overflowHeight = ( this.scrollParent[0] === document ) ? $(window).height() : this.scrollParent.height(); - this.overflowWidth = ( this.scrollParent[0] === document ) ? $(window).width() : this.scrollParent.width(); - - this._trigger( "start", event ); - - $(document).bind( "mousemove." + this.widgetName, $.proxy( this._mouseMove, this ) ) - .bind( "mouseup." + this.widgetName, $.proxy( this._mouseUp, this ) ); - - - // Set the helper up by actual element - if ( this._usingHelper() ) { - - // get the absolute position of element so that helper will know where to go - elOffset = this.element.offset(); - - this.dragEl.css({ - display: "block", - top: elOffset.top + "px", - left: elOffset.left + "px" - }); - - } - + this.overflowHeight = ( this.scrollParent[0] === this.doc[0] ) ? + this.win.height() : this.scrollParent.height(); + this.overflowWidth = ( this.scrollParent[0] === this.doc[0] ) ? + this.win.width() : this.scrollParent.width(); + + // TODO: allow modifying position, just like during drag + this._trigger( "start", event, this._uiHash() ); + + // TODO: use ._bind() + // TODO: rename _bind() to _on(); add _off() + this.doc + .bind( "mousemove." + this.widgetName, $.proxy( this, "_mouseMove" ) ) + .bind( "mouseup." + this.widgetName, $.proxy( this, "_mouseUp" ) ); }, _mouseMove: function( event ) { - var leftDiff = event.clientX - this.startCoords.left, - topDiff = event.clientY - this.startCoords.top, - newLeft = leftDiff + this.startPosition.left, - newTop = topDiff + this.startPosition.top; + topDiff = event.clientY - this.startCoords.top, + newLeft = leftDiff + this.startPosition.left, + newTop = topDiff + this.startPosition.top; this.position = { left: newLeft, @@ -218,87 +155,67 @@ $.widget( "ui.draggable", { this.offset.left = this.startOffset.left + newLeft; this.offset.top = this.startOffset.top + newTop; - this._trigger( "drag", event ); + this._trigger( "drag", event, this._uiHash() ); // User overriding left/top so shortcut math is no longer valid if ( newLeft !== this.position.left || newTop !== this.position.top ) { - + // TODO: can we just store the previous offset values + // and not go through .offset()? // refresh offset using slower functions this.offset = this.dragEl.offset(); - } - + newLeft = this.position.left; newTop = this.position.top; - - if ( this.cssPosition !== 'fixed' ) { - + + // TODO: does this work with nested scrollable parents? + if ( this.cssPosition !== "fixed" ) { newLeft = newLeft + this.scrollParent.scrollLeft(); newTop = newTop + this.scrollParent.scrollTop(); - } this.dragEl.css({ - left: newLeft + "px", top: newTop + "px" - }); - + // Scroll the scrollParent, if needed this._handleScrolling( event ); - }, _handleScrolling: function( event ) { - - var doc = $(document), - scrollTop = doc.scrollTop(), - scrollLeft = doc.scrollLeft(); + var scrollTop = this.doc.scrollTop(), + scrollLeft = this.doc.scrollLeft(); // Handle vertical scrolling if ( ( ( this.overflowHeight + scrollTop ) - event.pageY ) < this.options.scrollSensitivity ) { - doc.scrollTop( scrollTop + this.options.scrollSpeed ); + this.doc.scrollTop( scrollTop + this.options.scrollSpeed ); } - + // Handle horizontal scrolling if ( ( ( this.overflowWidth + scrollLeft ) - event.pageX ) < this.options.scrollSensitivity ) { - doc.scrollLeft( scrollLeft + this.options.scrollSpeed ); + this.doc.scrollLeft( scrollLeft + this.options.scrollSpeed ); } - }, _mouseUp: function( event ) { + this._trigger( "stop", event, this._uiHash() ); - var doc = $(document); - - this._trigger( "stop", event ); - - this.startCoords = {}; - - if ( this._usingHelper() ) { + if ( this.options.helper ) { this.dragEl.remove(); } - doc.unbind( "mousemove." + this.widgetName ); - doc.unbind( "mouseup." + this.widgetName ); - + this.doc + .unbind( "mousemove." + this.widgetName ) + .unbind( "mouseup." + this.widgetName ); }, - _uiHash: function(event) { - + _uiHash: function( event ) { return { position: this.position, offset: this.offset }; - } - -}); - -$.extend($.ui.draggable, { - version: "2.0.0" }); - -})(jQuery); +})( jQuery ); From c4df28939c8c2c0e94778333129b76e0bece35bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 14 Oct 2011 15:03:10 -0400 Subject: [PATCH 010/190] Draggable: Use ._bind(). --- ui/jquery.ui.draggable.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 1e9fb4cda3b..ef6af1086a0 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -45,8 +45,7 @@ $.widget( "ui.draggable", { this.element.css( "position", "relative" ); } - // TODO: use _bind() - this.element.bind( "mousedown." + this.widgetName, $.proxy( this, "_mouseDown" ) ); + this._bind({ mousedown: "_mouseDown" }); }, // TODO: why is relative handled differently than fixed/absolute? @@ -133,11 +132,10 @@ $.widget( "ui.draggable", { // TODO: allow modifying position, just like during drag this._trigger( "start", event, this._uiHash() ); - // TODO: use ._bind() - // TODO: rename _bind() to _on(); add _off() - this.doc - .bind( "mousemove." + this.widgetName, $.proxy( this, "_mouseMove" ) ) - .bind( "mouseup." + this.widgetName, $.proxy( this, "_mouseUp" ) ); + this._bind( this.doc, { + mousemove: "_mouseMove", + mouseup: "_mouseUp" + }); }, _mouseMove: function( event ) { @@ -205,9 +203,7 @@ $.widget( "ui.draggable", { this.dragEl.remove(); } - this.doc - .unbind( "mousemove." + this.widgetName ) - .unbind( "mouseup." + this.widgetName ); + this.doc.unbind( "." + this.widgetName ); }, _uiHash: function( event ) { From a0946d0364e9f87ea45777d2ab8d099ae0913647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Mon, 17 Oct 2011 08:26:12 -0400 Subject: [PATCH 011/190] Draggable: Remove all ids when using helper: true. --- ui/jquery.ui.draggable.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index ef6af1086a0..6abfe7a522d 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -91,11 +91,11 @@ $.widget( "ui.draggable", { if ( this.options.helper ) { // clone if ( this.options.helper === true ) { - // If source element has an ID, change ID of helper to avoid overlap - this.dragEl = this.element.clone(); - if ( this.element.attr( "id" ) ) { - this.dragEl.attr( "id", this.element.attr( "id" ) + "-" + this.widgetName ); - } + this.dragEl = this.element.clone() + .removeAttr( "id" ) + .find( "[id]" ) + .removeAttr( "id" ) + .end(); } else { // TODO: figure out the signature for this; see #4957 this.dragEl = $( this.options.helper() ); From 1337573adc9fd4411ce67a764e0dda0c59701107 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 25 Oct 2011 21:54:03 -0400 Subject: [PATCH 012/190] Squashed commit of the following: Draggable: Fixed when cssPosition is being set. Scrolling handles non-doc overflow. _handleScrolling handles scrolling up and left now Made window, doc, and window part of base widget All parts of drag may be stopped via stopPropagation User can now override position of draggable on start, drag, and stop Whitespace fix Moved overflowWidth and overflowHeight into overflow.width and overflow.height --- ui/jquery.ui.draggable.js | 174 ++++++++++++++++++++++++++++---------- ui/jquery.ui.widget.js | 3 + 2 files changed, 133 insertions(+), 44 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 6abfe7a522d..390c85a0522 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -24,20 +24,16 @@ $.widget( "ui.draggable", { }, // dragEl: element being dragged (original or helper) - // position: CSS position of dragEl + // position: final CSS position of dragEl // offset: offset of dragEl // startCoords: clientX/Y of the mousedown (offset of pointer) // startPosition: CSS position prior to drag start // startOffset: offset prior to drag start + // tempPosition: overridable CSS position of dragEl // overflowOffset: offset of scroll parent - // overflowHeight: height of scroll parent - // overflowWidth: width of scroll parent + // overflow: object containing width and height keys of scroll parent _create: function() { - // TODO: add these to the base widget - this.doc = $( this.element[0].ownerDocument ); - this.win = $( this.doc[0].defaultView ); - this.scrollParent = this.element.scrollParent(); // Static position elements can't be moved with top/left @@ -79,13 +75,62 @@ $.widget( "ui.draggable", { }; }, + _handleScrolling: function( event ) { + // TODO: what is expected behavior of absolute/fixed draggable inside a div having overflow:scroll? + var scrollTop = this.scrollParent.scrollTop(), + scrollLeft = this.scrollParent.scrollLeft(); + + // overflowOffset is only set when scrollParent is not doc/html + if ( !this.overflowOffset ) { + + // Handle vertical scrolling + if ( ( ( this.overflow.height + scrollTop ) - event.pageY ) < this.options.scrollSensitivity ) { + this.scrollParent.scrollTop( scrollTop + this.options.scrollSpeed ); + } + else if ( event.pageY < ( scrollTop + this.options.scrollSensitivity ) ) { + this.scrollParent.scrollTop( scrollTop - this.options.scrollSpeed ); + } + + // Handle horizontal scrolling + if ( ( ( this.overflow.width + scrollLeft ) - event.pageX ) < this.options.scrollSensitivity ) { + this.scrollParent.scrollLeft( scrollLeft + this.options.scrollSpeed ); + } + else if ( event.pageX < ( scrollLeft + this.options.scrollSensitivity ) ) { + this.scrollParent.scrollLeft( scrollLeft - this.options.scrollSpeed ); + } + + } else { + + + // Handle vertical scrolling + if ( ( event.pageY + this.options.scrollSensitivity ) > ( this.overflow.height + this.overflowOffset.top ) ) { + this.scrollParent.scrollTop( scrollTop + this.options.scrollSpeed ); + } + else if ( ( event.pageY - this.options.scrollSensitivity ) < this.overflowOffset.top ) { + this.scrollParent.scrollTop( scrollTop - this.options.scrollSpeed ); + } + + // Handle horizontal scrolling + if ( ( event.pageX + this.options.scrollSensitivity ) > ( this.overflow.width + this.overflowOffset.left ) ) { + this.scrollParent.scrollLeft( scrollLeft + this.options.scrollSpeed ); + } + else if ( ( event.pageX - this.options.scrollSensitivity ) < this.overflowOffset.left ) { + this.scrollParent.scrollLeft( scrollLeft - this.options.scrollSpeed ); + } + + + } + + }, + _mouseDown: function( event ) { + var newLeft, newTop; + // Prevent text selection, among other things event.preventDefault(); // The actual dragging element, should always be a jQuery object this.dragEl = this.element; - this.cssPosition = this.dragEl.css( "position" ); // Helper required if ( this.options.helper ) { @@ -107,6 +152,8 @@ $.widget( "ui.draggable", { .appendTo( this.doc[0].body ) .offset( this.element.offset() ); } + + this.cssPosition = this.dragEl.css( "position" ); // Cache starting absolute and relative positions this.startPosition = this._getPosition(); @@ -121,16 +168,31 @@ $.widget( "ui.draggable", { top: event.clientY }; - // Cache the offset of scrollParent - // TODO: store overflow height/width in a hash instead of separate properties - this.overflowOffset = this.scrollParent.offset(); - this.overflowHeight = ( this.scrollParent[0] === this.doc[0] ) ? + // Cache the offset of scrollParent, if required for _handleScrolling + if ( this.scrollParent[0] != this.doc[0] && this.scrollParent[0].tagName != 'HTML') { + this.overflowOffset = this.scrollParent.offset(); + } + + this.overflow = {}; + + this.overflow.height = ( this.scrollParent[0] === this.doc[0] ) ? this.win.height() : this.scrollParent.height(); - this.overflowWidth = ( this.scrollParent[0] === this.doc[0] ) ? + + this.overflow.width = ( this.scrollParent[0] === this.doc[0] ) ? this.win.width() : this.scrollParent.width(); - // TODO: allow modifying position, just like during drag + this._preparePosition( event ); + this._trigger( "start", event, this._uiHash() ); + + // TODO: should user be able to change position of draggable, if event stopped? + // If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes + if ( event.cancelBubble === true ) { + this.doc.unbind( "." + this.widgetName ); + return; + } + + this._setCss( event ); this._bind( this.doc, { mousemove: "_mouseMove", @@ -139,24 +201,76 @@ $.widget( "ui.draggable", { }, _mouseMove: function( event ) { + var newLeft, newTop; + + this._preparePosition( event ); + + this._trigger( "drag", event, this._uiHash() ); + + // TODO: should user be able to change position of draggable, if event stopped? + // If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes + if ( event.cancelBubble === true ) { + this.doc.unbind( "." + this.widgetName ); + return; + } + + this._setCss( event ); + + // Scroll the scrollParent, if needed + this._handleScrolling( event ); + }, + + _mouseUp: function( event ) { + + this._preparePosition( event ); + + this._trigger( "stop", event, this._uiHash() ); + + // TODO: should user be able to change position of draggable, if event stopped? + // If user stops propagation, leave helper there, disallow any CSS changes + if ( event.cancelBubble !== true ) { + + this._setCss( event ); + + if ( this.options.helper ) { + this.dragEl.remove(); + } + + } + + this.doc.unbind( "." + this.widgetName ); + }, + + // Uses event to determine new position of draggable, before any override from callbacks + _preparePosition: function( event ) { var leftDiff = event.clientX - this.startCoords.left, topDiff = event.clientY - this.startCoords.top, newLeft = leftDiff + this.startPosition.left, newTop = topDiff + this.startPosition.top; + // Save off new values for .css() in various callbacks using this function this.position = { left: newLeft, top: newTop }; + // Save off values to compare user override against automatic coordinates + this.tempPosition = { + left: newLeft, + top: newTop + } + // Refresh offset cache with new positions this.offset.left = this.startOffset.left + newLeft; this.offset.top = this.startOffset.top + newTop; + }, - this._trigger( "drag", event, this._uiHash() ); + // Places draggable where mouse or user from callback indicates + _setCss: function( event ) { + var newLeft, newTop; // User overriding left/top so shortcut math is no longer valid - if ( newLeft !== this.position.left || newTop !== this.position.top ) { + if ( this.tempPosition.left !== this.position.left || this.tempPosition.top !== this.position.top ) { // TODO: can we just store the previous offset values // and not go through .offset()? // refresh offset using slower functions @@ -176,34 +290,6 @@ $.widget( "ui.draggable", { left: newLeft + "px", top: newTop + "px" }); - - // Scroll the scrollParent, if needed - this._handleScrolling( event ); - }, - - _handleScrolling: function( event ) { - var scrollTop = this.doc.scrollTop(), - scrollLeft = this.doc.scrollLeft(); - - // Handle vertical scrolling - if ( ( ( this.overflowHeight + scrollTop ) - event.pageY ) < this.options.scrollSensitivity ) { - this.doc.scrollTop( scrollTop + this.options.scrollSpeed ); - } - - // Handle horizontal scrolling - if ( ( ( this.overflowWidth + scrollLeft ) - event.pageX ) < this.options.scrollSensitivity ) { - this.doc.scrollLeft( scrollLeft + this.options.scrollSpeed ); - } - }, - - _mouseUp: function( event ) { - this._trigger( "stop", event, this._uiHash() ); - - if ( this.options.helper ) { - this.dragEl.remove(); - } - - this.doc.unbind( "." + this.widgetName ); }, _uiHash: function( event ) { diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 31328a45564..5af56de040e 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -183,6 +183,9 @@ $.Widget.prototype = { _createWidget: function( options, element ) { element = $( element || this.defaultElement || this )[ 0 ]; this.element = $( element ); + this.doc = $( this.element[0].ownerDocument ); + this.win = $( this.doc[0].defaultView ); + this.body = this.doc.body; this.options = $.widget.extend( {}, this.options, this._getCreateOptions(), From e1e43e31091d5ea589a80c797c6e959a246f5337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Thu, 27 Oct 2011 14:20:55 -0400 Subject: [PATCH 013/190] Draggable: Add ui-draggable class. --- ui/jquery.ui.draggable.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 390c85a0522..f3842c9b553 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -41,6 +41,7 @@ $.widget( "ui.draggable", { this.element.css( "position", "relative" ); } + this.element.addClass( "ui-draggable" ); this._bind({ mousedown: "_mouseDown" }); }, @@ -56,7 +57,7 @@ $.widget( "ui.draggable", { // Take into account scrollbar position.top -= scrollTop; - position.left -= scrollLeft + position.left -= scrollLeft; return position; } @@ -258,7 +259,7 @@ $.widget( "ui.draggable", { this.tempPosition = { left: newLeft, top: newTop - } + }; // Refresh offset cache with new positions this.offset.left = this.startOffset.left + newLeft; @@ -297,6 +298,10 @@ $.widget( "ui.draggable", { position: this.position, offset: this.offset }; + }, + + _destroy: function() { + this.element.removeClass( "ui-draggable" ); } }); From 35e4ccae9129df1fc7f951ca40e2664b4b31acf4 Mon Sep 17 00:00:00 2001 From: Corey Frang Date: Thu, 27 Oct 2011 21:34:48 -0500 Subject: [PATCH 014/190] Widget: Removing code to merge clean --- ui/jquery.ui.widget.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 5af56de040e..31328a45564 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -183,9 +183,6 @@ $.Widget.prototype = { _createWidget: function( options, element ) { element = $( element || this.defaultElement || this )[ 0 ]; this.element = $( element ); - this.doc = $( this.element[0].ownerDocument ); - this.win = $( this.doc[0].defaultView ); - this.body = this.doc.body; this.options = $.widget.extend( {}, this.options, this._getCreateOptions(), From f7ec5029922af49d0637d17758271bdb3c40f731 Mon Sep 17 00:00:00 2001 From: Corey Frang Date: Thu, 27 Oct 2011 21:39:33 -0500 Subject: [PATCH 015/190] Draggable: Using this.document and this.window instead of doc/win --- ui/jquery.ui.draggable.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index f3842c9b553..f073fab5355 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -150,7 +150,7 @@ $.widget( "ui.draggable", { this.dragEl // TODO: should we move this to the stylesheet and use a class? .css( "position", "absolute" ) - .appendTo( this.doc[0].body ) + .appendTo( this.document[0].body ) .offset( this.element.offset() ); } @@ -170,17 +170,17 @@ $.widget( "ui.draggable", { }; // Cache the offset of scrollParent, if required for _handleScrolling - if ( this.scrollParent[0] != this.doc[0] && this.scrollParent[0].tagName != 'HTML') { + if ( this.scrollParent[0] != this.document[0] && this.scrollParent[0].tagName != 'HTML') { this.overflowOffset = this.scrollParent.offset(); } this.overflow = {}; - this.overflow.height = ( this.scrollParent[0] === this.doc[0] ) ? - this.win.height() : this.scrollParent.height(); + this.overflow.height = ( this.scrollParent[0] === this.document[0] ) ? + this.window.height() : this.scrollParent.height(); - this.overflow.width = ( this.scrollParent[0] === this.doc[0] ) ? - this.win.width() : this.scrollParent.width(); + this.overflow.width = ( this.scrollParent[0] === this.document[0] ) ? + this.window.width() : this.scrollParent.width(); this._preparePosition( event ); @@ -189,13 +189,13 @@ $.widget( "ui.draggable", { // TODO: should user be able to change position of draggable, if event stopped? // If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes if ( event.cancelBubble === true ) { - this.doc.unbind( "." + this.widgetName ); + this.document.unbind( "." + this.widgetName ); return; } this._setCss( event ); - this._bind( this.doc, { + this._bind( this.document, { mousemove: "_mouseMove", mouseup: "_mouseUp" }); @@ -211,7 +211,7 @@ $.widget( "ui.draggable", { // TODO: should user be able to change position of draggable, if event stopped? // If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes if ( event.cancelBubble === true ) { - this.doc.unbind( "." + this.widgetName ); + this.document.unbind( "." + this.widgetName ); return; } @@ -239,7 +239,7 @@ $.widget( "ui.draggable", { } - this.doc.unbind( "." + this.widgetName ); + this.document.unbind( "." + this.widgetName ); }, // Uses event to determine new position of draggable, before any override from callbacks From ec9c1cf6f42adbac695c1c142d28b6a8a53a8616 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sun, 6 Nov 2011 16:20:56 -0500 Subject: [PATCH 016/190] Draggable: Proper use of ._trigger for detecting preventDefault. _uiHash now returns position and helper - removed offset. --- ui/jquery.ui.draggable.js | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 390c85a0522..4677eaf30ac 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -124,7 +124,7 @@ $.widget( "ui.draggable", { }, _mouseDown: function( event ) { - var newLeft, newTop; + var newLeft, newTop, allowed; // Prevent text selection, among other things event.preventDefault(); @@ -183,11 +183,10 @@ $.widget( "ui.draggable", { this._preparePosition( event ); - this._trigger( "start", event, this._uiHash() ); + allowed = this._trigger( "start", event, this._uiHash() ); - // TODO: should user be able to change position of draggable, if event stopped? // If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes - if ( event.cancelBubble === true ) { + if ( allowed !== true ) { this.doc.unbind( "." + this.widgetName ); return; } @@ -201,15 +200,15 @@ $.widget( "ui.draggable", { }, _mouseMove: function( event ) { - var newLeft, newTop; - + var newLeft, newTop, allowed; + this._preparePosition( event ); - this._trigger( "drag", event, this._uiHash() ); - - // TODO: should user be able to change position of draggable, if event stopped? + allowed = this._trigger( "drag", event, this._uiHash() ); + + // If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes - if ( event.cancelBubble === true ) { + if ( allowed !== true ) { this.doc.unbind( "." + this.widgetName ); return; } @@ -221,14 +220,15 @@ $.widget( "ui.draggable", { }, _mouseUp: function( event ) { + + var allowed; this._preparePosition( event ); - this._trigger( "stop", event, this._uiHash() ); + allowed = this._trigger( "stop", event, this._uiHash() ); - // TODO: should user be able to change position of draggable, if event stopped? // If user stops propagation, leave helper there, disallow any CSS changes - if ( event.cancelBubble !== true ) { + if ( allowed === true ) { this._setCss( event ); @@ -293,10 +293,17 @@ $.widget( "ui.draggable", { }, _uiHash: function( event ) { - return { - position: this.position, - offset: this.offset + var ret = { + position: this.position + // offset: this.offset }; + + if ( this.options.helper ) { + ret.helper = this.dragEl; + } + + return ret; + } }); From 536a11893ad3cb6e2e480c83fc7662cd57877906 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sun, 6 Nov 2011 16:31:09 -0500 Subject: [PATCH 017/190] Draggable: Removed answered TODO --- ui/jquery.ui.draggable.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 4677eaf30ac..b3fdd6f1440 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -76,7 +76,6 @@ $.widget( "ui.draggable", { }, _handleScrolling: function( event ) { - // TODO: what is expected behavior of absolute/fixed draggable inside a div having overflow:scroll? var scrollTop = this.scrollParent.scrollTop(), scrollLeft = this.scrollParent.scrollLeft(); From 7941f7c13f884ebe1e123fffd2ee2675db0c828b Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sun, 6 Nov 2011 16:39:17 -0500 Subject: [PATCH 018/190] Draggable: Redid f7ec502992 after bad merge. --- ui/jquery.ui.draggable.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index b3fdd6f1440..3b1b9f29d1e 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -46,7 +46,7 @@ $.widget( "ui.draggable", { // TODO: why is relative handled differently than fixed/absolute? _getPosition: function() { - var left, top, position, + var left, top, position, offset, scrollTop = this.scrollParent.scrollTop(), scrollLeft = this.scrollParent.scrollLeft(); @@ -56,7 +56,7 @@ $.widget( "ui.draggable", { // Take into account scrollbar position.top -= scrollTop; - position.left -= scrollLeft + position.left -= scrollLeft; return position; } @@ -148,7 +148,7 @@ $.widget( "ui.draggable", { this.dragEl // TODO: should we move this to the stylesheet and use a class? .css( "position", "absolute" ) - .appendTo( this.doc[0].body ) + .appendTo( this.document[0].body ) .offset( this.element.offset() ); } @@ -168,17 +168,17 @@ $.widget( "ui.draggable", { }; // Cache the offset of scrollParent, if required for _handleScrolling - if ( this.scrollParent[0] != this.doc[0] && this.scrollParent[0].tagName != 'HTML') { + if ( this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== 'HTML') { this.overflowOffset = this.scrollParent.offset(); } this.overflow = {}; - this.overflow.height = ( this.scrollParent[0] === this.doc[0] ) ? - this.win.height() : this.scrollParent.height(); + this.overflow.height = ( this.scrollParent[0] === this.document[0] ) ? + this.window.height() : this.scrollParent.height(); - this.overflow.width = ( this.scrollParent[0] === this.doc[0] ) ? - this.win.width() : this.scrollParent.width(); + this.overflow.width = ( this.scrollParent[0] === this.document[0] ) ? + this.window.width() : this.scrollParent.width(); this._preparePosition( event ); @@ -186,13 +186,13 @@ $.widget( "ui.draggable", { // If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes if ( allowed !== true ) { - this.doc.unbind( "." + this.widgetName ); + this.document.unbind( "." + this.widgetName ); return; } this._setCss( event ); - this._bind( this.doc, { + this._bind( this.document, { mousemove: "_mouseMove", mouseup: "_mouseUp" }); @@ -208,7 +208,7 @@ $.widget( "ui.draggable", { // If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes if ( allowed !== true ) { - this.doc.unbind( "." + this.widgetName ); + this.document.unbind( "." + this.widgetName ); return; } @@ -237,7 +237,7 @@ $.widget( "ui.draggable", { } - this.doc.unbind( "." + this.widgetName ); + this.document.unbind( "." + this.widgetName ); }, // Uses event to determine new position of draggable, before any override from callbacks @@ -257,7 +257,7 @@ $.widget( "ui.draggable", { this.tempPosition = { left: newLeft, top: newTop - } + }; // Refresh offset cache with new positions this.offset.left = this.startOffset.left + newLeft; From 1ca93b4a6c438928268179fd98872ba270ae5e49 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sun, 6 Nov 2011 17:42:35 -0500 Subject: [PATCH 019/190] Draggable: Added in iframeFix option --- ui/jquery.ui.draggable.js | 92 +++++++++++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 19 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 3b1b9f29d1e..21412cf9805 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -20,7 +20,8 @@ $.widget( "ui.draggable", { options: { helper: false, scrollSensitivity: 20, - scrollSpeed: 20 + scrollSpeed: 20, + iframeFix: false }, // dragEl: element being dragged (original or helper) @@ -33,6 +34,36 @@ $.widget( "ui.draggable", { // overflowOffset: offset of scroll parent // overflow: object containing width and height keys of scroll parent + _blockFrames: function() { + + var iframes = $('iframe'), + widget = this; + + this.iframeBlocks = $(''); + + iframes.each( function() { + + var iframe = $(this), + width = iframe.outerWidth(), + height = iframe.outerHeight(), + iframeOffset = iframe.offset(), + block = $('
'); + + block.css({ + position: 'absolute', + width: width+'px', + height: height+'px', + top: iframeOffset.top+'px', + left: iframeOffset.left+'px' + }) + .appendTo( widget.document[0].body ); + + widget.iframeBlocks = widget.iframeBlocks.add( block ); + + }); + + }, + _create: function() { this.scrollParent = this.element.scrollParent(); @@ -78,10 +109,10 @@ $.widget( "ui.draggable", { _handleScrolling: function( event ) { var scrollTop = this.scrollParent.scrollTop(), scrollLeft = this.scrollParent.scrollLeft(); - + // overflowOffset is only set when scrollParent is not doc/html if ( !this.overflowOffset ) { - + // Handle vertical scrolling if ( ( ( this.overflow.height + scrollTop ) - event.pageY ) < this.options.scrollSensitivity ) { this.scrollParent.scrollTop( scrollTop + this.options.scrollSpeed ); @@ -89,7 +120,7 @@ $.widget( "ui.draggable", { else if ( event.pageY < ( scrollTop + this.options.scrollSensitivity ) ) { this.scrollParent.scrollTop( scrollTop - this.options.scrollSpeed ); } - + // Handle horizontal scrolling if ( ( ( this.overflow.width + scrollLeft ) - event.pageX ) < this.options.scrollSensitivity ) { this.scrollParent.scrollLeft( scrollLeft + this.options.scrollSpeed ); @@ -97,10 +128,10 @@ $.widget( "ui.draggable", { else if ( event.pageX < ( scrollLeft + this.options.scrollSensitivity ) ) { this.scrollParent.scrollLeft( scrollLeft - this.options.scrollSpeed ); } - + } else { - - + + // Handle vertical scrolling if ( ( event.pageY + this.options.scrollSensitivity ) > ( this.overflow.height + this.overflowOffset.top ) ) { this.scrollParent.scrollTop( scrollTop + this.options.scrollSpeed ); @@ -108,7 +139,7 @@ $.widget( "ui.draggable", { else if ( ( event.pageY - this.options.scrollSensitivity ) < this.overflowOffset.top ) { this.scrollParent.scrollTop( scrollTop - this.options.scrollSpeed ); } - + // Handle horizontal scrolling if ( ( event.pageX + this.options.scrollSensitivity ) > ( this.overflow.width + this.overflowOffset.left ) ) { this.scrollParent.scrollLeft( scrollLeft + this.options.scrollSpeed ); @@ -116,10 +147,10 @@ $.widget( "ui.draggable", { else if ( ( event.pageX - this.options.scrollSensitivity ) < this.overflowOffset.left ) { this.scrollParent.scrollLeft( scrollLeft - this.options.scrollSpeed ); } - - + + } - + }, _mouseDown: function( event ) { @@ -131,6 +162,10 @@ $.widget( "ui.draggable", { // The actual dragging element, should always be a jQuery object this.dragEl = this.element; + if ( this.options.iframeFix === true ) { + this._blockFrames(); + } + // Helper required if ( this.options.helper ) { // clone @@ -151,7 +186,7 @@ $.widget( "ui.draggable", { .appendTo( this.document[0].body ) .offset( this.element.offset() ); } - + this.cssPosition = this.dragEl.css( "position" ); // Cache starting absolute and relative positions @@ -183,7 +218,7 @@ $.widget( "ui.draggable", { this._preparePosition( event ); allowed = this._trigger( "start", event, this._uiHash() ); - + // If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes if ( allowed !== true ) { this.document.unbind( "." + this.widgetName ); @@ -200,12 +235,12 @@ $.widget( "ui.draggable", { _mouseMove: function( event ) { var newLeft, newTop, allowed; - + this._preparePosition( event ); allowed = this._trigger( "drag", event, this._uiHash() ); - - + + // If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes if ( allowed !== true ) { this.document.unbind( "." + this.widgetName ); @@ -219,7 +254,7 @@ $.widget( "ui.draggable", { }, _mouseUp: function( event ) { - + var allowed; this._preparePosition( event ); @@ -238,6 +273,11 @@ $.widget( "ui.draggable", { } this.document.unbind( "." + this.widgetName ); + + if ( this.options.iframeFix === true ) { + this._unblockFrames(); + } + }, // Uses event to determine new position of draggable, before any override from callbacks @@ -296,13 +336,27 @@ $.widget( "ui.draggable", { position: this.position // offset: this.offset }; - + if ( this.options.helper ) { ret.helper = this.dragEl; } - + return ret; + + }, + + _unblockFrames: function() { + + if ( !this.iframeBlocks || !this.iframeBlocks.length ) { + return; + } + this.iframeBlocks.each( function() { + + $(this).remove(); + + }); + } }); From 38c06026a125aaeacb8dd73e0deb3a276b6836e9 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sun, 13 Nov 2011 17:14:19 -0500 Subject: [PATCH 020/190] Draggable: Fixed offset calculation. Offset now passed back in uiHash. --- ui/jquery.ui.draggable.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 21412cf9805..180f3038f57 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -298,10 +298,10 @@ $.widget( "ui.draggable", { left: newLeft, top: newTop }; - + // Refresh offset cache with new positions - this.offset.left = this.startOffset.left + newLeft; - this.offset.top = this.startOffset.top + newTop; + this.offset.left = this.startOffset.left + leftDiff; + this.offset.top = this.startOffset.top + topDiff; }, // Places draggable where mouse or user from callback indicates @@ -333,8 +333,8 @@ $.widget( "ui.draggable", { _uiHash: function( event ) { var ret = { - position: this.position - // offset: this.offset + position: this.position, + offset: this.offset }; if ( this.options.helper ) { From 3c6455df0b5c405d7b1c9c2624ff2819c853313a Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sun, 13 Nov 2011 17:28:56 -0500 Subject: [PATCH 021/190] Droppable: 2.0 initial commit --- ui/jquery.ui.droppable.js | 302 +++++++------------------------------- 1 file changed, 51 insertions(+), 251 deletions(-) diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index 3942c6b8f49..5cec18b6cc9 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -10,7 +10,6 @@ * Depends: * jquery.ui.core.js * jquery.ui.widget.js - * jquery.ui.mouse.js * jquery.ui.draggable.js */ (function( $, undefined ) { @@ -18,276 +17,77 @@ $.widget("ui.droppable", { version: "@VERSION", widgetEventPrefix: "drop", + allowedTolerance: ['touch'], options: { - accept: '*', - activeClass: false, - addClasses: true, - greedy: false, - hoverClass: false, - scope: 'default', - tolerance: 'intersect' + // accept: '*', + // activeClass: false, + // addClasses: true, + // greedy: false, + // hoverClass: false, + // scope: 'default', + tolerance: 'touch' //'intersect' }, + + // draggableProportions: width and height of currently dragging draggable + // proportions: width and height of droppable + _create: function() { - var o = this.options, accept = o.accept; - this.isover = 0; this.isout = 1; - - this.accept = $.isFunction(accept) ? accept : function(d) { - return d.is(accept); - }; + // Store current location + this.offset = this.element.offset(); //Store the droppable's proportions this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; - // Add the reference and positions to the manager - $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; - $.ui.ddmanager.droppables[o.scope].push(this); - - (o.addClasses && this.element.addClass("ui-droppable")); - - }, - - destroy: function() { - var drop = $.ui.ddmanager.droppables[this.options.scope]; - for ( var i = 0; i < drop.length; i++ ) - if ( drop[i] == this ) - drop.splice(i, 1); - - this.element - .removeClass("ui-droppable ui-droppable-disabled") - .removeData("droppable") - .unbind(".droppable"); - - return this; - }, - - _setOption: function(key, value) { - - if(key == 'accept') { - this.accept = $.isFunction(value) ? value : function(d) { - return d.is(value); - }; - } - $.Widget.prototype._setOption.apply(this, arguments); - }, - - _activate: function(event) { - var draggable = $.ui.ddmanager.current; - if(this.options.activeClass) this.element.addClass(this.options.activeClass); - (draggable && this._trigger('activate', event, this.ui(draggable))); - }, - - _deactivate: function(event) { - var draggable = $.ui.ddmanager.current; - if(this.options.activeClass) this.element.removeClass(this.options.activeClass); - (draggable && this._trigger('deactivate', event, this.ui(draggable))); - }, - - _over: function(event) { - - var draggable = $.ui.ddmanager.current; - if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element - - if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { - if(this.options.hoverClass) this.element.addClass(this.options.hoverClass); - this._trigger('over', event, this.ui(draggable)); - } + // TODO: Use $.Callbacks or .on from 1.7 + $('*').live( "drag", $.proxy( this._drag, this ) ); + $('*').live( "dragstart", $.proxy( this._dragStart, this ) ); }, - _out: function(event) { - - var draggable = $.ui.ddmanager.current; - if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element - - if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { - if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); - this._trigger('out', event, this.ui(draggable)); - } + _drag: function( event, ui ) { + + var rightEdge, bottomEdge, draggableRightEdge, draggableBottomEdge, xOverlap, yOverlap; + + switch ( this.options.tolerance ) { + + case 'touch': + rightEdge = ( this.offset.left + this.proportions.width ), + bottomEdge = ( this.offset.top + this.proportions.height ), + draggableRightEdge = ( ui.offset.left + this.draggableProportions.width ), + draggableBottomEdge = ( ui.offset.top + this.draggableProportions.height ), + xOverlap = ( draggableRightEdge >= this.offset.left && ui.offset.left <= rightEdge ), + yOverlap = ( draggableBottomEdge >= this.offset.top && ui.offset.top <= bottomEdge ); + + if ( xOverlap && yOverlap ) { + // TODO: properly fill out uiHash + this._trigger( "over", event, {} ); + } + + break; + + default: + throw( "Invalid tolerance passed: " + this.options.tolerance + ". Allowed: " + this.allowedTolerance.join( ', ' ) ); + break; + } + }, - _drop: function(event,custom) { - - var draggable = custom || $.ui.ddmanager.current; - if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element - - var childrenIntersection = false; - this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() { - var inst = $.data(this, 'droppable'); - if( - inst.options.greedy - && !inst.options.disabled - && inst.options.scope == draggable.options.scope - && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) - && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) - ) { childrenIntersection = true; return false; } - }); - if(childrenIntersection) return false; + _dragStart: function( event, ui ) { + + var draggable = $( event.target ); + + this.draggableProportions = { width: draggable[0].offsetWidth, height: draggable[0].offsetHeight }; + - if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { - if(this.options.activeClass) this.element.removeClass(this.options.activeClass); - if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); - this._trigger('drop', event, this.ui(draggable)); - return this.element; - } - return false; - - }, - - ui: function(c) { - return { - draggable: (c.currentItem || c.element), - helper: c.helper, - position: c.position, - offset: c.positionAbs - }; } -}); - -$.ui.intersect = function(draggable, droppable, toleranceMode) { - - if (!droppable.offset) return false; - - var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, - y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; - var l = droppable.offset.left, r = l + droppable.proportions.width, - t = droppable.offset.top, b = t + droppable.proportions.height; - switch (toleranceMode) { - case 'fit': - return (l <= x1 && x2 <= r - && t <= y1 && y2 <= b); - break; - case 'intersect': - return (l < x1 + (draggable.helperProportions.width / 2) // Right Half - && x2 - (draggable.helperProportions.width / 2) < r // Left Half - && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half - && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half - break; - case 'pointer': - var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left), - draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top), - isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width); - return isOver; - break; - case 'touch': - return ( - (y1 >= t && y1 <= b) || // Top edge touching - (y2 >= t && y2 <= b) || // Bottom edge touching - (y1 < t && y2 > b) // Surrounded vertically - ) && ( - (x1 >= l && x1 <= r) || // Left edge touching - (x2 >= l && x2 <= r) || // Right edge touching - (x1 < l && x2 > r) // Surrounded horizontally - ); - break; - default: - return false; - break; - } -}; - -/* - This manager tracks offsets of draggables and droppables -*/ -$.ui.ddmanager = { - current: null, - droppables: { 'default': [] }, - prepareOffsets: function(t, event) { - - var m = $.ui.ddmanager.droppables[t.options.scope] || []; - var type = event ? event.type : null; // workaround for #2317 - var list = (t.currentItem || t.element).find(":data(droppable)").andSelf(); - - droppablesLoop: for (var i = 0; i < m.length; i++) { - - if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted - for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item - m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue - - if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables - - m[i].offset = m[i].element.offset(); - m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; - - } - - }, - drop: function(draggable, event) { - - var dropped = false; - $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { - - if(!this.options) return; - if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) - dropped = dropped || this._drop.call(this, event); - - if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { - this.isout = 1; this.isover = 0; - this._deactivate.call(this, event); - } - - }); - return dropped; - - }, - dragStart: function( draggable, event ) { - //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) - draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() { - if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); - }); - }, - drag: function(draggable, event) { - - //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. - if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); - - //Run through all droppables and check their positions based on specific tolerance options - $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { - - if(this.options.disabled || this.greedyChild || !this.visible) return; - var intersects = $.ui.intersect(draggable, this, this.options.tolerance); - - var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null); - if(!c) return; - - var parentInstance; - if (this.options.greedy) { - var parent = this.element.parents(':data(droppable):eq(0)'); - if (parent.length) { - parentInstance = $.data(parent[0], 'droppable'); - parentInstance.greedyChild = (c == 'isover' ? 1 : 0); - } - } - - // we just moved into a greedy child - if (parentInstance && c == 'isover') { - parentInstance['isover'] = 0; - parentInstance['isout'] = 1; - parentInstance._out.call(parentInstance, event); - } +}); - this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0; - this[c == "isover" ? "_over" : "_out"].call(this, event); +})(jQuery); - // we just moved out of a greedy child - if (parentInstance && c == 'isout') { - parentInstance['isout'] = 0; - parentInstance['isover'] = 1; - parentInstance._over.call(parentInstance, event); - } - }); - }, - dragStop: function( draggable, event ) { - draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" ); - //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) - if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); - } -}; - -})(jQuery); From e8e7847a4113b849f2dffa7f29b599d65db96094 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sun, 13 Nov 2011 17:42:05 -0500 Subject: [PATCH 022/190] Droppable: over, out, and drop callbacks working --- ui/jquery.ui.droppable.js | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index 5cec18b6cc9..5f72cdf0db3 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -29,6 +29,7 @@ $.widget("ui.droppable", { }, // draggableProportions: width and height of currently dragging draggable + // over: whether or not a draggable is currently over droppable // proportions: width and height of droppable _create: function() { @@ -42,6 +43,10 @@ $.widget("ui.droppable", { // TODO: Use $.Callbacks or .on from 1.7 $('*').live( "drag", $.proxy( this._drag, this ) ); $('*').live( "dragstart", $.proxy( this._dragStart, this ) ); + + this._bind( this.document, { + mouseup: "_mouseUp" + }); }, @@ -59,9 +64,15 @@ $.widget("ui.droppable", { xOverlap = ( draggableRightEdge >= this.offset.left && ui.offset.left <= rightEdge ), yOverlap = ( draggableBottomEdge >= this.offset.top && ui.offset.top <= bottomEdge ); + if ( xOverlap && yOverlap ) { - // TODO: properly fill out uiHash - this._trigger( "over", event, {} ); + this._trigger( "over", event, this._uiHash() ); + this.over = true; + } + else if ( this.over ) { + this.over = false; + this._trigger( "out", event, this._uiHash() ); + } break; @@ -77,11 +88,29 @@ $.widget("ui.droppable", { _dragStart: function( event, ui ) { var draggable = $( event.target ); - + + // TODO: Possibly move into draggable hash, so if there are multiple droppables, it's not recalculating all the time this.draggableProportions = { width: draggable[0].offsetWidth, height: draggable[0].offsetHeight }; + }, + + _mouseUp: function( event ) { + + if ( this.over ) { + this._trigger( "drop", event, this._uiHash() ); + } + + this.over = false; + + }, + + // TODO: fill me out + _uiHash: function() { + + return {}; + } From 9ee7c90a594924beb7dc99ad961df36b7f76c1e0 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sun, 13 Nov 2011 17:49:37 -0500 Subject: [PATCH 023/190] Droppable: Added refreshPosition public method --- ui/jquery.ui.droppable.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index 5f72cdf0db3..dbccbae2c46 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -32,13 +32,20 @@ $.widget("ui.droppable", { // over: whether or not a draggable is currently over droppable // proportions: width and height of droppable - _create: function() { - + + refreshPosition: function() { + // Store current location this.offset = this.element.offset(); //Store the droppable's proportions this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; + + }, + + _create: function() { + + this.refreshPosition(); // TODO: Use $.Callbacks or .on from 1.7 $('*').live( "drag", $.proxy( this._drag, this ) ); From 3914cebe66c71956c9067eb37ee2dabc7d7caae8 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sun, 13 Nov 2011 18:39:04 -0500 Subject: [PATCH 024/190] Droppable: Intersect tolerance added --- ui/jquery.ui.droppable.js | 134 ++++++++++++++++++++++++++------------ 1 file changed, 91 insertions(+), 43 deletions(-) diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index dbccbae2c46..e2eabd2d9c1 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -25,24 +25,24 @@ $.widget("ui.droppable", { // greedy: false, // hoverClass: false, // scope: 'default', - tolerance: 'touch' //'intersect' + tolerance: 'intersect' }, - + // draggableProportions: width and height of currently dragging draggable // over: whether or not a draggable is currently over droppable // proportions: width and height of droppable - - + + refreshPosition: function() { - + // Store current location this.offset = this.element.offset(); //Store the droppable's proportions this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; - + }, - + _create: function() { this.refreshPosition(); @@ -50,7 +50,7 @@ $.widget("ui.droppable", { // TODO: Use $.Callbacks or .on from 1.7 $('*').live( "drag", $.proxy( this._drag, this ) ); $('*').live( "dragstart", $.proxy( this._dragStart, this ) ); - + this._bind( this.document, { mouseup: "_mouseUp" }); @@ -58,66 +58,114 @@ $.widget("ui.droppable", { }, _drag: function( event, ui ) { - - var rightEdge, bottomEdge, draggableRightEdge, draggableBottomEdge, xOverlap, yOverlap; - - switch ( this.options.tolerance ) { - - case 'touch': - rightEdge = ( this.offset.left + this.proportions.width ), - bottomEdge = ( this.offset.top + this.proportions.height ), - draggableRightEdge = ( ui.offset.left + this.draggableProportions.width ), - draggableBottomEdge = ( ui.offset.top + this.draggableProportions.height ), - xOverlap = ( draggableRightEdge >= this.offset.left && ui.offset.left <= rightEdge ), - yOverlap = ( draggableBottomEdge >= this.offset.top && ui.offset.top <= bottomEdge ); - - - if ( xOverlap && yOverlap ) { - this._trigger( "over", event, this._uiHash() ); - this.over = true; - } - else if ( this.over ) { - this.over = false; - this._trigger( "out", event, this._uiHash() ); - - } + + var handleFunc, edges, + tolerance = this.options.tolerance, + over = false; + + switch ( tolerance ) { + + case "intersect": + case "touch": + + edges = { + right: ( this.offset.left + this.proportions.width ), + bottom: ( this.offset.top + this.proportions.height ), + draggableRight: ( ui.offset.left + this.draggableProportions.width ), + draggableBottom: ( ui.offset.top + this.draggableProportions.height ) + }; + + + handleFunc = "_handle" + tolerance.substr(0, 1 ).toUpperCase() + tolerance.substr( 1 ); + over = this[ handleFunc ]( edges, ui ); break; - + default: - throw( "Invalid tolerance passed: " + this.options.tolerance + ". Allowed: " + this.allowedTolerance.join( ', ' ) ); - break; + throw( "Invalid tolerance passed: " + this.options.tolerance + ". Allowed: " + this.allowedTolerance.join( ", " ) ); + } + // If there is sufficient overlap as deemed by tolerance + if ( over === true ) { + + this._trigger( "over", event, this._uiHash() ); + this.over = true; + + } + + // If there isn't enough overlap and droppable was previously flagged as over + else if ( this.over === true ) { + + this.over = false; + this._trigger( "out", event, this._uiHash() ); + + } }, _dragStart: function( event, ui ) { - + var draggable = $( event.target ); - + // TODO: Possibly move into draggable hash, so if there are multiple droppables, it's not recalculating all the time this.draggableProportions = { width: draggable[0].offsetWidth, height: draggable[0].offsetHeight }; - + + }, + + // Determines if draggable is over droppable based on intersect tolerance + _handleIntersect: function( edges, ui ) { + + var xDiff = edges.draggableRight - this.offset.left, + yDiff = edges.draggableBottom - this.offset.top, + xHalfway = Math.round( this.proportions.width / 2 ), + yHalfway = Math.round( this.proportions.height / 2 ), + xHalfOverlap = false; + yHalfOverlap = false; + + + // If Coming from left or right + xHalfOverlap = ( ui.offset.left < this.offset.left ) ? + ( xDiff >= xHalfway ) : + ( xDiff <= xHalfway + this.proportions.width ); + + // If Coming from top or bottom + yHalfOverlap = ( ui.offset.top < this.offset.top ) ? + ( yDiff >= yHalfway ) : + ( yDiff <= yHalfway + this.proportions.height ); + + return ( xHalfOverlap && yHalfOverlap ); + + }, - _mouseUp: function( event ) { + // Determines if draggable is over droppable based on touch tolerance + _handleTouch: function( edges, ui ) { + var xOverlap = ( edges.draggableRight >= this.offset.left && ui.offset.left <= edges.right ), + yOverlap = ( edges.draggableBottom >= this.offset.top && ui.offset.top <= edges.bottom ); + + return ( xOverlap && yOverlap ); + + }, + + _mouseUp: function( event ) { + if ( this.over ) { this._trigger( "drop", event, this._uiHash() ); } - + this.over = false; - + }, - + // TODO: fill me out _uiHash: function() { - + return {}; - + } From dac3dddd9e33471da95d1f125489e9931437f5da Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sun, 13 Nov 2011 18:41:29 -0500 Subject: [PATCH 025/190] Droppable: Put tolerance in allowed array --- ui/jquery.ui.droppable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index e2eabd2d9c1..a24bb14c26c 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -17,7 +17,7 @@ $.widget("ui.droppable", { version: "@VERSION", widgetEventPrefix: "drop", - allowedTolerance: ['touch'], + allowedTolerance: ["touch","intersect"], options: { // accept: '*', // activeClass: false, From 4792d5b7afe163446b4ce2ed2e49f4d78f62f9c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Thu, 17 Nov 2011 19:48:04 -0500 Subject: [PATCH 026/190] Draggable: Cleanup. --- ui/jquery.ui.draggable.js | 110 ++++++++++++-------------------------- 1 file changed, 34 insertions(+), 76 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 180f3038f57..d4e98a6173a 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -18,10 +18,10 @@ $.widget( "ui.draggable", { widgetEventPrefix: "drag", options: { - helper: false, + helper: null, + // TODO: remove scroll options scrollSensitivity: 20, - scrollSpeed: 20, - iframeFix: false + scrollSpeed: 20 }, // dragEl: element being dragged (original or helper) @@ -34,37 +34,28 @@ $.widget( "ui.draggable", { // overflowOffset: offset of scroll parent // overflow: object containing width and height keys of scroll parent + // TODO: move next to _unblockFrames() _blockFrames: function() { - - var iframes = $('iframe'), - widget = this; - - this.iframeBlocks = $(''); - - iframes.each( function() { - - var iframe = $(this), - width = iframe.outerWidth(), - height = iframe.outerHeight(), - iframeOffset = iframe.offset(), - block = $('
'); - - block.css({ - position: 'absolute', - width: width+'px', - height: height+'px', - top: iframeOffset.top+'px', - left: iframeOffset.left+'px' - }) - .appendTo( widget.document[0].body ); - - widget.iframeBlocks = widget.iframeBlocks.add( block ); - + var body = this.document[0].body; + + this.iframeBlocks = this.document.find( "iframe" ).map(function() { + var iframe = $( this ), + iframeOffset = iframe.offset(); + + return $( "
" ) + .css({ + position: "absolute", + width: iframe.outerWidth(), + height: iframe.outerHeight(), + top: iframeOffset.top, + left: iframeOffset.left + }) + .appendTo( body )[0]; }); - }, _create: function() { + // TODO: move to drag start in case DOM changes this.scrollParent = this.element.scrollParent(); // Static position elements can't be moved with top/left @@ -128,10 +119,7 @@ $.widget( "ui.draggable", { else if ( event.pageX < ( scrollLeft + this.options.scrollSensitivity ) ) { this.scrollParent.scrollLeft( scrollLeft - this.options.scrollSpeed ); } - } else { - - // Handle vertical scrolling if ( ( event.pageY + this.options.scrollSensitivity ) > ( this.overflow.height + this.overflowOffset.top ) ) { this.scrollParent.scrollTop( scrollTop + this.options.scrollSpeed ); @@ -147,14 +135,11 @@ $.widget( "ui.draggable", { else if ( ( event.pageX - this.options.scrollSensitivity ) < this.overflowOffset.left ) { this.scrollParent.scrollLeft( scrollLeft - this.options.scrollSpeed ); } - - } - }, _mouseDown: function( event ) { - var newLeft, newTop, allowed; + var newLeft, newTop; // Prevent text selection, among other things event.preventDefault(); @@ -162,10 +147,6 @@ $.widget( "ui.draggable", { // The actual dragging element, should always be a jQuery object this.dragEl = this.element; - if ( this.options.iframeFix === true ) { - this._blockFrames(); - } - // Helper required if ( this.options.helper ) { // clone @@ -217,14 +198,13 @@ $.widget( "ui.draggable", { this._preparePosition( event ); - allowed = this._trigger( "start", event, this._uiHash() ); - // If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes - if ( allowed !== true ) { + if ( this._trigger( "start", event, this._uiHash() ) === false ) { this.document.unbind( "." + this.widgetName ); return; } + this._blockFrames(); this._setCss( event ); this._bind( this.document, { @@ -234,15 +214,12 @@ $.widget( "ui.draggable", { }, _mouseMove: function( event ) { - var newLeft, newTop, allowed; + var newLeft, newTop; this._preparePosition( event ); - allowed = this._trigger( "drag", event, this._uiHash() ); - - // If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes - if ( allowed !== true ) { + if ( this._trigger( "drag", event, this._uiHash() ) === false ) { this.document.unbind( "." + this.widgetName ); return; } @@ -254,30 +231,18 @@ $.widget( "ui.draggable", { }, _mouseUp: function( event ) { - - var allowed; - this._preparePosition( event ); - allowed = this._trigger( "stop", event, this._uiHash() ); - // If user stops propagation, leave helper there, disallow any CSS changes - if ( allowed === true ) { - + if ( this._trigger( "stop", event, this._uiHash() ) === false ) { this._setCss( event ); - if ( this.options.helper ) { this.dragEl.remove(); } - } this.document.unbind( "." + this.widgetName ); - - if ( this.options.iframeFix === true ) { - this._unblockFrames(); - } - + this._unblockFrames(); }, // Uses event to determine new position of draggable, before any override from callbacks @@ -298,7 +263,7 @@ $.widget( "ui.draggable", { left: newLeft, top: newTop }; - + // Refresh offset cache with new positions this.offset.left = this.startOffset.left + leftDiff; this.offset.top = this.startOffset.top + topDiff; @@ -326,8 +291,8 @@ $.widget( "ui.draggable", { } this.dragEl.css({ - left: newLeft + "px", - top: newTop + "px" + left: newLeft, + top: newTop }); }, @@ -337,26 +302,19 @@ $.widget( "ui.draggable", { offset: this.offset }; + // TODO: should we always set the helper? if ( this.options.helper ) { ret.helper = this.dragEl; } return ret; - }, _unblockFrames: function() { - - if ( !this.iframeBlocks || !this.iframeBlocks.length ) { - return; + if ( this.iframeBlocks ) { + this.iframeBlocks.remove(); + delete this.iframeBlocks; } - - this.iframeBlocks.each( function() { - - $(this).remove(); - - }); - } }); From e9f5c1857f9d70e69f08be158b2275736c02647f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Thu, 17 Nov 2011 19:48:09 -0500 Subject: [PATCH 027/190] Droppable: Cleanup. --- ui/jquery.ui.droppable.js | 158 +++++++++++++++----------------------- 1 file changed, 60 insertions(+), 98 deletions(-) diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index a24bb14c26c..3555cb83707 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -5,7 +5,7 @@ * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * - * http://docs.jquery.com/UI/Droppables + * http://docs.jquery.com/UI/Droppable * * Depends: * jquery.ui.core.js @@ -14,164 +14,126 @@ */ (function( $, undefined ) { -$.widget("ui.droppable", { +$.widget( "ui.droppable", { version: "@VERSION", widgetEventPrefix: "drop", - allowedTolerance: ["touch","intersect"], options: { - // accept: '*', - // activeClass: false, - // addClasses: true, + // accept: null, // greedy: false, - // hoverClass: false, - // scope: 'default', - tolerance: 'intersect' + tolerance: "intersect" }, // draggableProportions: width and height of currently dragging draggable // over: whether or not a draggable is currently over droppable // proportions: width and height of droppable - + // TODO: move below _create() + // TODO: rename to refresh()? refreshPosition: function() { - // Store current location this.offset = this.element.offset(); - //Store the droppable's proportions - this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; - + // Store the droppable's proportions + // TODO: should this delegate to core? + this.proportions = { + width: this.element[0].offsetWidth, + height: this.element[0].offsetHeight + }; }, _create: function() { - this.refreshPosition(); - // TODO: Use $.Callbacks or .on from 1.7 - $('*').live( "drag", $.proxy( this._drag, this ) ); - $('*').live( "dragstart", $.proxy( this._dragStart, this ) ); + // TODO: make this much more efficient + // possibly just override draggable's methods + $( "*" ).live( "drag", $.proxy( this._drag, this ) ); + $( "*" ).live( "dragstart", $.proxy( this._dragStart, this ) ); this._bind( this.document, { mouseup: "_mouseUp" }); - }, _drag: function( event, ui ) { + var tolerance = this.options.tolerance, + handleFunc = "_handle" + tolerance.substr( 0, 1 ).toUpperCase() + tolerance.substr( 1 ), + edges = { + right: this.offset.left + this.proportions.width, + bottom: this.offset.top + this.proportions.height, + draggableRight: ui.offset.left + this.draggableProportions.width, + draggableBottom: ui.offset.top + this.draggableProportions.height + }, + over = this[ handleFunc ]( edges, ui ); - var handleFunc, edges, - tolerance = this.options.tolerance, - over = false; - - switch ( tolerance ) { - - case "intersect": - case "touch": - - edges = { - right: ( this.offset.left + this.proportions.width ), - bottom: ( this.offset.top + this.proportions.height ), - draggableRight: ( ui.offset.left + this.draggableProportions.width ), - draggableBottom: ( ui.offset.top + this.draggableProportions.height ) - }; - - - handleFunc = "_handle" + tolerance.substr(0, 1 ).toUpperCase() + tolerance.substr( 1 ); - over = this[ handleFunc ]( edges, ui ); - - break; - - default: - throw( "Invalid tolerance passed: " + this.options.tolerance + ". Allowed: " + this.allowedTolerance.join( ", " ) ); - - } - // If there is sufficient overlap as deemed by tolerance - if ( over === true ) { - + if ( over ) { this._trigger( "over", event, this._uiHash() ); this.over = true; - - } - // If there isn't enough overlap and droppable was previously flagged as over - else if ( this.over === true ) { - + } else if ( this.over ) { this.over = false; this._trigger( "out", event, this._uiHash() ); - } - }, _dragStart: function( event, ui ) { - var draggable = $( event.target ); // TODO: Possibly move into draggable hash, so if there are multiple droppables, it's not recalculating all the time - this.draggableProportions = { width: draggable[0].offsetWidth, height: draggable[0].offsetHeight }; - - - + this.draggableProportions = { + width: draggable[0].offsetWidth, + height: draggable[0].offsetHeight + }; }, // Determines if draggable is over droppable based on intersect tolerance + // TODO: move all tolerance methods into a hash + // $.ui.droppable.tolerance.intersect _handleIntersect: function( edges, ui ) { - var xDiff = edges.draggableRight - this.offset.left, yDiff = edges.draggableBottom - this.offset.top, - xHalfway = Math.round( this.proportions.width / 2 ), - yHalfway = Math.round( this.proportions.height / 2 ), - xHalfOverlap = false; - yHalfOverlap = false; - - - // If Coming from left or right - xHalfOverlap = ( ui.offset.left < this.offset.left ) ? - ( xDiff >= xHalfway ) : - ( xDiff <= xHalfway + this.proportions.width ); - - // If Coming from top or bottom - yHalfOverlap = ( ui.offset.top < this.offset.top ) ? - ( yDiff >= yHalfway ) : - ( yDiff <= yHalfway + this.proportions.height ); - - return ( xHalfOverlap && yHalfOverlap ); - - + // TODO: is there really any need to round here? + xHalfway = Math.round( this.proportions.width / 2 ), + yHalfway = Math.round( this.proportions.height / 2 ), + xOverlap = false, + yOverlap = false; + + // If Coming from left or right + xOverlap = ui.offset.left < this.offset.left ? + xDiff >= xHalfway : + xDiff <= xHalfway + this.proportions.width; + + // If Coming from top or bottom + yOverlap = ui.offset.top < this.offset.top ? + yDiff >= yHalfway : + yDiff <= yHalfway + this.proportions.height; + + return xOverlap && yOverlap; }, - + // Determines if draggable is over droppable based on touch tolerance _handleTouch: function( edges, ui ) { - - var xOverlap = ( edges.draggableRight >= this.offset.left && ui.offset.left <= edges.right ), - yOverlap = ( edges.draggableBottom >= this.offset.top && ui.offset.top <= edges.bottom ); - - return ( xOverlap && yOverlap ); - + var xOverlap = edges.draggableRight >= this.offset.left && + ui.offset.left <= edges.right, + yOverlap = edges.draggableBottom >= this.offset.top && + ui.offset.top <= edges.bottom; + + return xOverlap && yOverlap; }, - - _mouseUp: function( event ) { + // TODO: shouldn't this be dragStop? + _mouseUp: function( event ) { if ( this.over ) { this._trigger( "drop", event, this._uiHash() ); } this.over = false; - }, // TODO: fill me out _uiHash: function() { - return {}; - } - - - }); -})(jQuery); - - +})( jQuery ); From 51e1d576f61dd6e924c6120ded7446ab2903b7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Wed, 23 Nov 2011 09:03:02 -0500 Subject: [PATCH 028/190] Draggable: Cleanup. --- ui/jquery.ui.draggable.js | 47 ++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index d4e98a6173a..15b5f873b90 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -34,30 +34,7 @@ $.widget( "ui.draggable", { // overflowOffset: offset of scroll parent // overflow: object containing width and height keys of scroll parent - // TODO: move next to _unblockFrames() - _blockFrames: function() { - var body = this.document[0].body; - - this.iframeBlocks = this.document.find( "iframe" ).map(function() { - var iframe = $( this ), - iframeOffset = iframe.offset(); - - return $( "
" ) - .css({ - position: "absolute", - width: iframe.outerWidth(), - height: iframe.outerHeight(), - top: iframeOffset.top, - left: iframeOffset.left - }) - .appendTo( body )[0]; - }); - }, - _create: function() { - // TODO: move to drag start in case DOM changes - this.scrollParent = this.element.scrollParent(); - // Static position elements can't be moved with top/left if ( this.element.css( "position" ) === "static" ) { this.element.css( "position", "relative" ); @@ -66,7 +43,6 @@ $.widget( "ui.draggable", { this._bind({ mousedown: "_mouseDown" }); }, - // TODO: why is relative handled differently than fixed/absolute? _getPosition: function() { var left, top, position, offset, scrollTop = this.scrollParent.scrollTop(), @@ -84,10 +60,11 @@ $.widget( "ui.draggable", { } // When using relative, css values are checked + // Otherwise the position wouldn't account for padding on ancestors left = this.dragEl.css( "left" ); top = this.dragEl.css( "top" ); - // Webkit will give back auto if there is nothing inline yet + // Webkit will give back auto if there is no explicit value left = ( left === "auto" ) ? 0: parseInt( left, 10 ); top = ( top === "auto" ) ? 0: parseInt( top, 10 ); @@ -169,6 +146,7 @@ $.widget( "ui.draggable", { } this.cssPosition = this.dragEl.css( "position" ); + this.scrollParent = this.element.scrollParent(); // Cache starting absolute and relative positions this.startPosition = this._getPosition(); @@ -310,6 +288,25 @@ $.widget( "ui.draggable", { return ret; }, + _blockFrames: function() { + var body = this.document[0].body; + + this.iframeBlocks = this.document.find( "iframe" ).map(function() { + var iframe = $( this ), + iframeOffset = iframe.offset(); + + return $( "
" ) + .css({ + position: "absolute", + width: iframe.outerWidth(), + height: iframe.outerHeight(), + top: iframeOffset.top, + left: iframeOffset.left + }) + .appendTo( body )[0]; + }); + }, + _unblockFrames: function() { if ( this.iframeBlocks ) { this.iframeBlocks.remove(); From dbaa744f0c17f48336ca17259045b08ac11ef312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Wed, 23 Nov 2011 12:03:09 -0500 Subject: [PATCH 029/190] Interaction: Initial implementation for base interaction plugin. --- demos/draggable/default.html | 2 +- ui/jquery.ui.draggable.js | 24 ++++--------- ui/jquery.ui.interaction.js | 69 ++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 19 deletions(-) create mode 100644 ui/jquery.ui.interaction.js diff --git a/demos/draggable/default.html b/demos/draggable/default.html index 3a334d4b692..6dff38d85ee 100644 --- a/demos/draggable/default.html +++ b/demos/draggable/default.html @@ -7,7 +7,7 @@ - + - + + + + + +
+ +
+ +
+
Start:
+
0
+
Move:
+
0
+
Stop:
+
0
+
+ +
+ + +
+

This demo shows a simple interaction built using the interaction utility (jquery.ui.interaction.js).

+

Make a down-move-up motion starting on the blue box above using the mouse or a touch input device to see the interaction events

+
+ + + diff --git a/demos/interaction/index.html b/demos/interaction/index.html new file mode 100644 index 00000000000..4d9d0225d8b --- /dev/null +++ b/demos/interaction/index.html @@ -0,0 +1,18 @@ + + + + + jQuery UI Interaction Demo + + + + +
+

Examples

+ +
+ + + From c8b4be1381fa36126acad72b6327487bcf20da6d Mon Sep 17 00:00:00 2001 From: "Richard D. Worth" Date: Thu, 26 Jan 2012 11:14:57 -0500 Subject: [PATCH 073/190] Interaction: added missing file header --- ui/jquery.ui.interaction.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ui/jquery.ui.interaction.js b/ui/jquery.ui.interaction.js index c1d621ca39b..0172f9474e4 100644 --- a/ui/jquery.ui.interaction.js +++ b/ui/jquery.ui.interaction.js @@ -1,3 +1,15 @@ +/* + * jQuery UI Interaction @VERSION + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Interaction + * + * Depends: + * jquery.ui.widget.js + */ (function( $, undefined ) { var interaction; // = $.ui.interaction From f5c2e29e16be18bf9bf3c879692a94cd9577ecdc Mon Sep 17 00:00:00 2001 From: "Richard D. Worth" Date: Thu, 26 Jan 2012 14:04:01 -0500 Subject: [PATCH 074/190] Interaction demos: Added box demo --- demos/interaction/box.html | 75 ++++++++++++++++++++++++++++++++++++ demos/interaction/index.html | 1 + 2 files changed, 76 insertions(+) create mode 100644 demos/interaction/box.html diff --git a/demos/interaction/box.html b/demos/interaction/box.html new file mode 100644 index 00000000000..457552c39ee --- /dev/null +++ b/demos/interaction/box.html @@ -0,0 +1,75 @@ + + + + + jQuery UI Interaction - Box + + + + + + + + + + + +
+ +
+ +
+ + +
+

This demo shows how you can create a simple box-drawing (aka lasso) interaction built on top of the interaction utility (jquery.ui.interaction.js).

+

Draw a box by starting in the box above using the mouse or a touch input device.

+
+ + + diff --git a/demos/interaction/index.html b/demos/interaction/index.html index 4d9d0225d8b..4666b3b1d93 100644 --- a/demos/interaction/index.html +++ b/demos/interaction/index.html @@ -11,6 +11,7 @@

Examples

From 17b0324c28718467f28e40ba6300503f33c74963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 27 Jan 2012 20:57:17 -0500 Subject: [PATCH 075/190] Interaction: Pass move and stop methods to the hooks. --- ui/jquery.ui.interaction.js | 58 ++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/ui/jquery.ui.interaction.js b/ui/jquery.ui.interaction.js index 0172f9474e4..a060e95091c 100644 --- a/ui/jquery.ui.interaction.js +++ b/ui/jquery.ui.interaction.js @@ -17,11 +17,17 @@ var interaction; // = $.ui.interaction $.widget( "ui.interaction", { version: "@VERSION", _create: function() { + // force the context so we can pass these methods to the hooks + this._interactionMove = $.proxy( this, "_interactionMove" ); + this._interactionStop = $.proxy( this, "_interactionStop" ); + + // initialize all hooks for this widget for ( var hook in interaction.hooks ) { interaction.hooks[ hook ].setup( this, this._startProxy( hook ) ); } }, + // a pass through to _interactionStart() which tracks the hook that was used _startProxy: function( hook ) { var that = this; return function( event, target, pointerPosition ) { @@ -37,16 +43,20 @@ $.widget( "ui.interaction", { return false; } + // check if the event occurred on a valid target if ( false === this._isValidTarget( $( target ) ) ) { return false; } + // check if the widget wants the event to start an interaction started = ( this._start( event, pointerPosition ) !== false ); if ( started ) { interaction.started = true; - interaction.hooks[ hook ].handle( this ); + interaction.hooks[ hook ].handle( this, + this._interactionMove, this._interactionStop ); } + // let the hook know if the interaction was started return started; }, @@ -88,17 +98,17 @@ interaction.hooks.mouse = { }); }, - handle: function( widget ) { + handle: function( widget, move, stop ) { function mousemove( event ) { event.preventDefault(); - widget._interactionMove( event, { + move( event, { x: event.pageX, y: event.pageY }); } function mouseup( event ) { - widget._interactionStop( event, { + stop( event, { x: event.pageX, y: event.pageY }); @@ -153,8 +163,8 @@ var touchHook = interaction.hooks.touch = { }); }, - handle: function( widget ) { - function touchmove( event ) { + handle: function( widget, move, stop ) { + function moveHandler( event ) { // TODO: test non-Apple WebKits to see if they allow // zooming/scrolling if we don't preventDefault() var touch = getTouch( event ); @@ -163,31 +173,31 @@ var touchHook = interaction.hooks.touch = { } event.preventDefault(); - widget._interactionMove( event, { + move( event, { x: touch.pageX, y: touch.pageY }); } - function touchend( event ) { + function stopHandler( event ) { var touch = getTouch( event ); if ( !touch ) { return; } - widget._interactionStop( event, { + stop( event, { x: touch.pageX, y: touch.pageY }); touchHook.id = null; widget.document - .unbind( "touchmove", touchmove ) - .unbind( "touchend", touchend ); + .unbind( "touchmove", moveHandler ) + .unbind( "touchend", stopHandler ); } widget._bind( widget.document, { - "touchmove": touchmove, - "touchend": touchend + "touchmove": moveHandler, + "touchend": stopHandler }); } }; @@ -228,8 +238,8 @@ var pointerHook = interaction.hooks.msPointer = { }); }, - handle: function( widget ) { - function move( _event ) { + handle: function( widget, move, stop ) { + function moveHandler( _event ) { var event = _event.originalEvent, pageX = event.pageX, pageY = event.pageY; @@ -249,34 +259,34 @@ var pointerHook = interaction.hooks.msPointer = { pointerHook.x = pageX; pointerHook.y = pageY; - widget._interactionMove( event, { + move( event, { x: pageX, y: pageY }); } - function stop( _event ) { + function stopHandler( _event ) { var event = _event.originalEvent; if ( event.pointerId !== pointerHook.id ) { return; } - widget._interactionStop( event, { + stop( event, { x: event.pageX, y: event.pageY }); pointerHook.id = pointerHook.x = pointerHook.y = undefined; widget.document - .unbind( "MSPointerMove", move ) - .unbind( "MSPointerUp", stop ) - .unbind( "MSPointerCancel", stop ); + .unbind( "MSPointerMove", moveHandler ) + .unbind( "MSPointerUp", stopHandler ) + .unbind( "MSPointerCancel", stopHandler ); } widget._bind( widget.document, { - "MSPointerMove": move, - "MSPointerUp": stop, - "MSPointerCancel": stop + "MSPointerMove": moveHandler, + "MSPointerUp": stopHandler, + "MSPointerCancel": stopHandler }); } }; From 9d7b71bc299156079559fd169ce2f54c8db69735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 27 Jan 2012 21:11:22 -0500 Subject: [PATCH 076/190] Interaction demos: Cleanup. --- demos/interaction/box.html | 54 ++++++++++++++++------------------ demos/interaction/default.html | 16 +++++----- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/demos/interaction/box.html b/demos/interaction/box.html index 457552c39ee..73ce317621f 100644 --- a/demos/interaction/box.html +++ b/demos/interaction/box.html @@ -11,45 +11,43 @@ From 87c55b69e43085c869d5c0577db72dcdbbe1af1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 27 Jan 2012 22:06:37 -0500 Subject: [PATCH 077/190] Draggable: Added beforeStart event. --- demos/draggable/default.html | 12 ++++++++- ui/jquery.ui.draggable.js | 51 ++++++++++++++++++++++++++---------- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/demos/draggable/default.html b/demos/draggable/default.html index fab2b686f94..c866c5f1c36 100644 --- a/demos/draggable/default.html +++ b/demos/draggable/default.html @@ -15,7 +15,17 @@ diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 2f72b46d785..438a7c5b3e3 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -14,6 +14,16 @@ */ (function( $, undefined ) { +// create a shallow copy of an object +function copy( obj ) { + var prop, + ret = {}; + for ( prop in obj ) { + ret[ prop ] = obj[ prop ]; + } + return ret; +} + $.widget( "ui.draggable", $.ui.interaction, { version: "@VERSION", widgetEventPrefix: "drag", @@ -27,9 +37,11 @@ $.widget( "ui.draggable", $.ui.interaction, { // dragEl: element being dragged (original or helper) // position: final CSS position of dragEl // offset: offset of dragEl + // originalPosition: CSS position before drag start + // originalOffset: offset before drag start // startPointer: pageX/Y of the mousedown (offset of pointer) - // startPosition: CSS position prior to drag start - // startOffset: offset prior to drag start + // startPosition: CSS position at drag start (after beforeStart) + // startOffset: offset at drag start (after beforeStart) // tempPosition: overridable CSS position of dragEl // overflowOffset: offset of scroll parent // overflow: object containing width and height keys of scroll parent @@ -76,12 +88,12 @@ $.widget( "ui.draggable", $.ui.interaction, { // Cache starting positions this.startPointer = pointerPosition; - this.startPosition = this._getPosition(); - this.startOffset = this.dragEl.offset(); + this.originalPosition = this.startPosition = this._getPosition(); + this.originalOffset = this.startOffset = this.dragEl.offset(); // Cache current position and offset - this.position = $.extend( {}, this.startPosition ); - this.offset = $.extend( {}, this.startOffset ); + this.position = copy( this.startPosition ); + this.offset = copy( this.startOffset ); // Cache the offset of scrollParent, if required for _handleScrolling if ( this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML" ) { @@ -97,13 +109,21 @@ $.widget( "ui.draggable", $.ui.interaction, { this._preparePosition( pointerPosition ); - // If user cancels start, don't allow dragging - if ( this._trigger( "start", event, this._uiHash( pointerPosition ) ) === false ) { + // If user cancels beforeStart, don't allow dragging + if ( this._trigger( "beforeStart", event, { + position: this.position, + offset: copy( this.offset ), + pointer: copy( pointerPosition ) + }) === false ) { return false; } - this._blockFrames(); this._setCss(); + this.startPosition = this._getPosition(); + this.startOffset = this.dragEl.offset(); + + this._trigger( "start", event, this._uiHash( pointerPosition ) ); + this._blockFrames(); }, _move: function( event, pointerPosition ) { @@ -139,6 +159,7 @@ $.widget( "ui.draggable", $.ui.interaction, { parent.append( this.element ); } this.element.offset( this.offset ); + this.domPosition = null; } } @@ -301,12 +322,14 @@ $.widget( "ui.draggable", $.ui.interaction, { _uiHash: function( pointerPosition ) { var ret = { - startPosition: $.extend( {}, this.startPosition ), - startOffset: $.extend( {}, this.startOffset ), - startPointer: $.extend( {}, this.startPointer ), + originalPosition: copy( this.originalPosition ), + originalOffset: copy( this.originalOffset ), + startPosition: copy( this.startPosition ), + startOffset: copy( this.startOffset ), + startPointer: copy( this.startPointer ), position: this.position, - offset: this.offset, - pointer: pointerPosition + offset: copy( this.offset ), + pointer: copy( pointerPosition ) }; if ( this.options.helper ) { From 3c6e8a7b91d15c88aa2944822f3cc22783db1c60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 27 Jan 2012 22:17:27 -0500 Subject: [PATCH 078/190] Draggable: Only pass relevant data for each event. --- demos/draggable/default.html | 12 +----------- ui/jquery.ui.draggable.js | 35 +++++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/demos/draggable/default.html b/demos/draggable/default.html index c866c5f1c36..fab2b686f94 100644 --- a/demos/draggable/default.html +++ b/demos/draggable/default.html @@ -15,17 +15,7 @@ diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 438a7c5b3e3..14fcee9c169 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -110,11 +110,8 @@ $.widget( "ui.draggable", $.ui.interaction, { this._preparePosition( pointerPosition ); // If user cancels beforeStart, don't allow dragging - if ( this._trigger( "beforeStart", event, { - position: this.position, - offset: copy( this.offset ), - pointer: copy( pointerPosition ) - }) === false ) { + if ( this._trigger( "beforeStart", event, + this._originalHash( pointerPosition ) ) === false ) { return false; } @@ -122,7 +119,7 @@ $.widget( "ui.draggable", $.ui.interaction, { this.startPosition = this._getPosition(); this.startOffset = this.dragEl.offset(); - this._trigger( "start", event, this._uiHash( pointerPosition ) ); + this._trigger( "start", event, this._startHash( pointerPosition ) ); this._blockFrames(); }, @@ -130,7 +127,7 @@ $.widget( "ui.draggable", $.ui.interaction, { this._preparePosition( pointerPosition ); // If user cancels drag, don't move the element - if ( this._trigger( "drag", event, this._uiHash( pointerPosition ) ) === false ) { + if ( this._trigger( "drag", event, this._fullHash( pointerPosition ) ) === false ) { return; } @@ -146,7 +143,7 @@ $.widget( "ui.draggable", $.ui.interaction, { this._preparePosition( pointerPosition ); // If user cancels stop, leave helper there - if ( this._trigger( "stop", event, this._uiHash( pointerPosition ) ) !== false ) { + if ( this._trigger( "stop", event, this._fullHash( pointerPosition ) ) !== false ) { if ( this.options.helper ) { this.dragEl.remove(); } @@ -320,13 +317,8 @@ $.widget( "ui.draggable", $.ui.interaction, { }); }, - _uiHash: function( pointerPosition ) { + _originalHash: function( pointerPosition ) { var ret = { - originalPosition: copy( this.originalPosition ), - originalOffset: copy( this.originalOffset ), - startPosition: copy( this.startPosition ), - startOffset: copy( this.startOffset ), - startPointer: copy( this.startPointer ), position: this.position, offset: copy( this.offset ), pointer: copy( pointerPosition ) @@ -339,6 +331,21 @@ $.widget( "ui.draggable", $.ui.interaction, { return ret; }, + _startHash: function( pointerPosition ) { + return $.extend( this._originalHash( pointerPosition ), { + originalPosition: copy( this.originalPosition ), + originalOffset: copy( this.originalOffset ) + }); + }, + + _fullHash: function( pointerPosition ) { + return $.extend( this._startHash( pointerPosition ), { + startPosition: copy( this.startPosition ), + startOffset: copy( this.startOffset ), + startPointer: copy( this.startPointer ) + }); + }, + _blockFrames: function() { var body = this.document[0].body; From a87c1dc068f2fb91e18f2c46686a509822915c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Sat, 28 Jan 2012 10:16:36 -0500 Subject: [PATCH 079/190] Interaction: Added some comments. --- ui/jquery.ui.interaction.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/ui/jquery.ui.interaction.js b/ui/jquery.ui.interaction.js index a060e95091c..01f8984e17e 100644 --- a/ui/jquery.ui.interaction.js +++ b/ui/jquery.ui.interaction.js @@ -27,6 +27,20 @@ $.widget( "ui.interaction", { } }, + /** abstract methods **/ + + // _start: function( event, pointerPosition ) + // _move: function( event, pointerPosition ) + // _stop: function( event, pointerPosition ) + + /** protected **/ + + _isValidTarget: function( target ) { + return true; + }, + + /** internal **/ + // a pass through to _interactionStart() which tracks the hook that was used _startProxy: function( hook ) { var that = this; @@ -67,10 +81,6 @@ $.widget( "ui.interaction", { _interactionStop: function( event, pointerPosition ) { this._stop( event, pointerPosition ); interaction.started = false; - }, - - _isValidTarget: function( target ) { - return true; } }); @@ -84,6 +94,7 @@ interaction.hooks.mouse = { setup: function( widget, start ) { widget._bind({ "mousedown": function( event ) { + // only react to the primary button if ( event.which === 1 ) { var started = start( event, event.target, { x: event.pageX, @@ -91,6 +102,7 @@ interaction.hooks.mouse = { }); if ( started ) { + // prevent selection event.preventDefault(); } } From f5ceca740f51085c4c08ea9da9a4095c284d1e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Sat, 28 Jan 2012 10:45:55 -0500 Subject: [PATCH 080/190] Draggable demo: Implemented cursorAt option in cursor-style demo. --- demos/draggable/cursor-style.html | 37 ++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/demos/draggable/cursor-style.html b/demos/draggable/cursor-style.html index 2e8930eb051..daeb02704ef 100644 --- a/demos/draggable/cursor-style.html +++ b/demos/draggable/cursor-style.html @@ -7,16 +7,41 @@ - + @@ -24,9 +49,9 @@
- +
-

I will always stick to the center (relative to the mouse)

+

I will always stick to the center (relative to the pointer)

@@ -42,7 +67,7 @@
-

Position the cursor while dragging the object. By default the cursor appears in the center of the dragged object; use the cursorAt option to specify another location relative to the draggable (specify a pixel value from the top, right, bottom, and/or left). Customize the cursor's appearance by supplying the cursor option with a valid CSS cursor value: default, move, pointer, crosshair, etc.

+

Position the cursor while dragging the object. By default the cursor appears wherever the user started the drag; use the cursorAt option to specify another location relative to the draggable (specify a pixel value from the top, right, bottom, and/or left).

From 2eb9b841a31f9219a049b0f3833b24baa3137342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Sat, 28 Jan 2012 10:52:27 -0500 Subject: [PATCH 081/190] Draggable demo: Implemented cancel option in handle demo. --- demos/draggable/handle.html | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/demos/draggable/handle.html b/demos/draggable/handle.html index 672f36e7802..23efa64cfe6 100644 --- a/demos/draggable/handle.html +++ b/demos/draggable/handle.html @@ -15,6 +15,19 @@ #draggable p { cursor: move; } - +
- +

Revert the original

From a1d312b3eda227ba58eb6f728422e68dc998da36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Sat, 28 Jan 2012 11:12:54 -0500 Subject: [PATCH 083/190] Draggable: Add ui-draggable class on init. --- ui/jquery.ui.draggable.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 14fcee9c169..58efa5b380f 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -50,10 +50,13 @@ $.widget( "ui.draggable", $.ui.interaction, { _create: function() { this._super(); + // Static position elements can't be moved with top/left if ( this.element.css( "position" ) === "static" ) { this.element.css( "position", "relative" ); } + + this.element.addClass( "ui-draggable" ); }, /** interaction interface **/ @@ -370,6 +373,11 @@ $.widget( "ui.draggable", $.ui.interaction, { this.iframeBlocks.remove(); delete this.iframeBlocks; } + }, + + _destroy: function() { + this.element.removeClass( "ui-draggable" ); + this._super(); } }); From 7e7e79adb95c610b619d326646cb27c131524369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Sat, 28 Jan 2012 11:13:18 -0500 Subject: [PATCH 084/190] Draggable demo: Updated visual-feedback demo. --- demos/draggable/visual-feedback.html | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/demos/draggable/visual-feedback.html b/demos/draggable/visual-feedback.html index bced5d37a26..03cebb563a7 100644 --- a/demos/draggable/visual-feedback.html +++ b/demos/draggable/visual-feedback.html @@ -7,23 +7,21 @@ - + From 7249124d856f5b4d90401a1b03018d6ef2e44f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Sat, 28 Jan 2012 20:19:13 -0500 Subject: [PATCH 087/190] Droppable: Only calculate draggable proportions once, regardless of how many droppable instances there are. --- ui/jquery.ui.droppable.js | 80 +++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index 8cc8e5b4458..d0631dd906f 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -25,8 +25,13 @@ var guid = 0, allowed = orig.apply( this, arguments ); if ( allowed ) { - for ( droppable in droppables ) { - droppables[ droppable ][ method ]( event, ui ); + if ( $.ui.droppable[ method ] ) { + $.ui.droppable[ method ]( event, ui ); + } + if ( $.ui.droppable.prototype[ method ] ) { + for ( droppable in droppables ) { + droppables[ droppable ][ method ]( event, ui ); + } } } @@ -44,7 +49,6 @@ $.widget( "ui.droppable", { tolerance: "intersect" }, - // draggableProportions: width and height of currently dragging draggable // over: whether or not a draggable is currently over droppable // proportions: width and height of droppable @@ -71,23 +75,13 @@ $.widget( "ui.droppable", { /** draggable integration **/ - _draggableStart: function( event, ui ) { - var draggable = ui.helper ? ui.helper[0] : event.target; - - // TODO: Possibly move into draggable hash - // so if there are multiple droppables, it's not recalculating all the time - this.draggableProportions = { - width: draggable.offsetWidth, - height: draggable.offsetHeight - }; - }, - _draggableDrag: function( event, ui ) { - var edges = { + var draggableProportions = $.ui.droppable.draggableProportions, + edges = { right: this.offset.left + this.proportions.width, bottom: this.offset.top + this.proportions.height, - draggableRight: ui.offset.left + this.draggableProportions.width, - draggableBottom: ui.offset.top + this.draggableProportions.height + draggableRight: ui.offset.left + draggableProportions.width, + draggableBottom: ui.offset.top + draggableProportions.height }, over = $.ui.droppable.tolerance[ this.options.tolerance ] .call( this, event, edges, ui ); @@ -123,29 +117,43 @@ $.widget( "ui.droppable", { } }); -$.ui.droppable.tolerance = { - // Half of the draggable overlaps the droppable, horizontally and vertically - intersect: function( event, edges, ui ) { - var xHalf = ui.offset.left + this.draggableProportions.width / 2, - yHalf = ui.offset.top + this.draggableProportions.height / 2; +$.extend( $.ui.droppable, { + // draggableProportions: width and height of currently dragging draggable - return this.offset.left < xHalf && edges.right > xHalf && - this.offset.top < yHalf && edges.bottom > yHalf; + tolerance: { + // Half of the draggable overlaps the droppable, horizontally and vertically + intersect: function( event, edges, ui ) { + var draggableProportions = $.ui.droppable.draggableProportions, + xHalf = ui.offset.left + draggableProportions.width / 2, + yHalf = ui.offset.top + draggableProportions.height / 2; + + return this.offset.left < xHalf && edges.right > xHalf && + this.offset.top < yHalf && edges.bottom > yHalf; + }, + + // Draggable overlaps droppable by at least one pixel + touch: function( event, edges, ui ) { + return this.offset.left < edges.draggableRight && + edges.right > ui.offset.left && + this.offset.top < edges.draggableBottom && + edges.bottom > ui.offset.top; + }, + + // Pointer overlaps droppable + pointer: function( event, edges, ui ) { + return ui.pointer.x >= this.offset.left && ui.pointer.x <= edges.right && + ui.pointer.y >= this.offset.top && ui.pointer.y <= edges.bottom; + } }, - // Draggable overlaps droppable by at least one pixel - touch: function( event, edges, ui ) { - return this.offset.left < edges.draggableRight && - edges.right > ui.offset.left && - this.offset.top < edges.draggableBottom && - edges.bottom > ui.offset.top; - }, + _draggableStart: function( event, ui ) { + var element = ui.helper || $( event.target ); - // Pointer overlaps droppable - pointer: function( event, edges, ui ) { - return ui.pointer.x >= this.offset.left && ui.pointer.x <= edges.right && - ui.pointer.y >= this.offset.top && ui.pointer.y <= edges.bottom; + this.draggableProportions = { + width: element.outerWidth(), + height: element.outerHeight() + }; } -}; +}); })( jQuery ); From 97af9236c20f5dfbd7143ae97a0e8bbcf5ebee1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Sat, 28 Jan 2012 20:20:26 -0500 Subject: [PATCH 088/190] Droppable: Use .outerWidth() and .outerHeight() when calculating proportions. --- ui/jquery.ui.droppable.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index d0631dd906f..97242ebe40d 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -62,14 +62,10 @@ $.widget( "ui.droppable", { // TODO: rename to refresh()? refreshPosition: function() { - // Store current location this.offset = this.element.offset(); - - // Store the droppable's proportions - // TODO: should this delegate to core? this.proportions = { - width: this.element[0].offsetWidth, - height: this.element[0].offsetHeight + width: this.element.outerWidth(), + height: this.element.outerHeight() }; }, From 8ebdba73460f4fa43749b5f2c3b3d4945ac7d1d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Sun, 29 Jan 2012 12:47:35 -0500 Subject: [PATCH 089/190] Droppable: Added accept option. --- ui/jquery.ui.droppable.js | 52 +++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index 97242ebe40d..69fc0d2e2ae 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -20,19 +20,11 @@ var guid = 0, (function() { var orig = $.ui.draggable.prototype._trigger; $.ui.draggable.prototype._trigger = function( type, event, ui ) { - var droppable, - method = "_draggable" + type.substr( 0, 1 ).toUpperCase() + type.substr( 1 ), + var method = "_draggable" + type.substr( 0, 1 ).toUpperCase() + type.substr( 1 ), allowed = orig.apply( this, arguments ); - if ( allowed ) { - if ( $.ui.droppable[ method ] ) { - $.ui.droppable[ method ]( event, ui ); - } - if ( $.ui.droppable.prototype[ method ] ) { - for ( droppable in droppables ) { - droppables[ droppable ][ method ]( event, ui ); - } - } + if ( allowed && $.ui.droppable[ method ] ) { + $.ui.droppable[ method ]( event, ui ); } return allowed; @@ -44,7 +36,7 @@ $.widget( "ui.droppable", { widgetEventPrefix: "drop", options: { - // accept: null, + accept: null, // greedy: false, tolerance: "intersect" }, @@ -69,9 +61,13 @@ $.widget( "ui.droppable", { }; }, - /** draggable integration **/ + /** internal **/ - _draggableDrag: function( event, ui ) { + _accept: function( element ) { + return this.options.accept ? element.is( this.options.accept ) : true; + }, + + _drag: function( event, ui ) { var draggableProportions = $.ui.droppable.draggableProportions, edges = { right: this.offset.left + this.proportions.width, @@ -93,7 +89,7 @@ $.widget( "ui.droppable", { } }, - _draggableStop: function( event, ui ) { + _dragStop: function( event, ui ) { if ( this.over ) { this._trigger( "drop", event, this._uiHash() ); } @@ -101,8 +97,6 @@ $.widget( "ui.droppable", { this.over = false; }, - /** internal **/ - // TODO: fill me out _uiHash: function() { return {}; @@ -115,6 +109,7 @@ $.widget( "ui.droppable", { $.extend( $.ui.droppable, { // draggableProportions: width and height of currently dragging draggable + // active: array of active droppables tolerance: { // Half of the draggable overlaps the droppable, horizontally and vertically @@ -143,12 +138,33 @@ $.extend( $.ui.droppable, { }, _draggableStart: function( event, ui ) { - var element = ui.helper || $( event.target ); + var droppable, + target = $( event.target ), + element = ui.helper || target; this.draggableProportions = { width: element.outerWidth(), height: element.outerHeight() }; + + this.active = []; + for ( droppable in droppables ) { + if ( droppables[ droppable ]._accept( target ) ) { + this.active.push( droppables[ droppable ] ); + } + } + }, + + _draggableDrag: function( event, ui ) { + $.each( this.active, function() { + this._drag( event, ui ); + }); + }, + + _draggableStop: function( event, ui ) { + $.each( this.active, function() { + this._dragStop( event, ui ); + }); } }); From 74e2828ea09e36744b3992bca29ffc0b4a493b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Sun, 29 Jan 2012 13:04:40 -0500 Subject: [PATCH 090/190] Droppable: Added activate and deactivate events. --- ui/jquery.ui.droppable.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index 69fc0d2e2ae..46cae945517 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -63,8 +63,12 @@ $.widget( "ui.droppable", { /** internal **/ - _accept: function( element ) { - return this.options.accept ? element.is( this.options.accept ) : true; + _start: function( event, ui ) { + if ( this.options.accept && !$( event.target ).is( this.options.accept ) ) { + return false; + } + + this._trigger( "activate", event, this._uiHash() ); }, _drag: function( event, ui ) { @@ -89,11 +93,13 @@ $.widget( "ui.droppable", { } }, - _dragStop: function( event, ui ) { + _stop: function( event, ui ) { if ( this.over ) { this._trigger( "drop", event, this._uiHash() ); } + this._trigger( "deactivate", event, this._uiHash() ); + this.over = false; }, @@ -139,8 +145,7 @@ $.extend( $.ui.droppable, { _draggableStart: function( event, ui ) { var droppable, - target = $( event.target ), - element = ui.helper || target; + element = ui.helper || $( event.target ); this.draggableProportions = { width: element.outerWidth(), @@ -149,7 +154,7 @@ $.extend( $.ui.droppable, { this.active = []; for ( droppable in droppables ) { - if ( droppables[ droppable ]._accept( target ) ) { + if ( droppables[ droppable ]._start( event, ui ) !== false ) { this.active.push( droppables[ droppable ] ); } } @@ -163,7 +168,7 @@ $.extend( $.ui.droppable, { _draggableStop: function( event, ui ) { $.each( this.active, function() { - this._dragStop( event, ui ); + this._stop( event, ui ); }); } }); From 69b1df33f73b6f1870fc6a0fba9c468b17672781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Sun, 29 Jan 2012 13:08:38 -0500 Subject: [PATCH 091/190] Droppable: Renamed refreshPosition() to refresh(). --- ui/jquery.ui.droppable.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index 46cae945517..f6b635d2f86 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -52,8 +52,7 @@ $.widget( "ui.droppable", { /** public **/ - // TODO: rename to refresh()? - refreshPosition: function() { + refresh: function() { this.offset = this.element.offset(); this.proportions = { width: this.element.outerWidth(), From cac6901799517da217980b0a29af34ae10f62ef3 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sun, 29 Jan 2012 19:54:56 -0500 Subject: [PATCH 092/190] Droppable: Fixed reference to function name after change in 69b1df33f7 --- ui/jquery.ui.droppable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index f6b635d2f86..bc08a9630c5 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -45,7 +45,7 @@ $.widget( "ui.droppable", { // proportions: width and height of droppable _create: function() { - this.refreshPosition(); + this.refresh(); this.guid = guid++; droppables[ this.guid ] = this; }, From 62ce3e0f87a3f31aa83ea3296220a7616bfd9f90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Mon, 30 Jan 2012 20:57:52 -0500 Subject: [PATCH 093/190] Draggable: Moved containment extension into jquery.ui.draggable.js. Removed axis extension from constrain-movement demo. --- demos/draggable/constrain-movement.html | 85 ++++--------------------- ui/jquery.ui.draggable.js | 83 ++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 74 deletions(-) diff --git a/demos/draggable/constrain-movement.html b/demos/draggable/constrain-movement.html index 17278cb4c5e..28246310401 100644 --- a/demos/draggable/constrain-movement.html +++ b/demos/draggable/constrain-movement.html @@ -18,81 +18,17 @@ #containment-wrapper { width: 95%; height:150px; border:2px solid #ccc; padding: 10px; } @@ -55,11 +63,7 @@
-

My cursor is at left -5 and top -5

-
- -
-

My cursor position is only controlled for the 'bottom' value

+

My cursor position is always at the top

@@ -67,7 +71,7 @@
-

Position the cursor while dragging the object. By default the cursor appears wherever the user started the drag; use the cursorAt option to specify another location relative to the draggable (specify a pixel value from the top, right, bottom, and/or left).

+

The beforeStart callback allows you to position the draggable element in order to adjust where the draggable movements will be calculated from. In this example, we adjust the position to control where the element is relative to the pointer during the drag.

From 32260c5ec4fc57edb1ae82b39374757ec3a5fb69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Mon, 30 Jan 2012 22:39:03 -0500 Subject: [PATCH 095/190] Draggable demo: Inlined the revert logic in the revert demo. --- demos/draggable/revert.html | 38 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/demos/draggable/revert.html b/demos/draggable/revert.html index 803dfc1a7b4..756987ff832 100644 --- a/demos/draggable/revert.html +++ b/demos/draggable/revert.html @@ -11,31 +11,25 @@ @@ -56,7 +50,7 @@
-

Return the draggable (or it's helper) to its original location when dragging stops with the boolean revert option.

+

The stop callback can be used to perform an action after the user finishing dragging the element. For example, if you want to return the draggable (or it's helper) to its original location when dragging stops, you can do so in the stop callback.

From 0cc4329747ba32360a5e44ad5f36350c38cee466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=CC=88rn=20Zaefferer?= Date: Mon, 5 Mar 2012 11:50:53 +0100 Subject: [PATCH 096/190] Interactions: Add a draggable map demo. Custom containment logic still needs some improvements. --- demos/draggable/index.html | 1 + demos/draggable/map.html | 73 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 demos/draggable/map.html diff --git a/demos/draggable/index.html b/demos/draggable/index.html index 0beda8e7292..1c57161fa9b 100644 --- a/demos/draggable/index.html +++ b/demos/draggable/index.html @@ -21,6 +21,7 @@

Examples

  • Drag handle
  • Cursor style
  • Draggable + Sortable
  • +
  • Draggable Map
  • diff --git a/demos/draggable/map.html b/demos/draggable/map.html new file mode 100644 index 00000000000..ba01bbcbea9 --- /dev/null +++ b/demos/draggable/map.html @@ -0,0 +1,73 @@ + + + + + + jQuery UI Draggable - Draggable Map + + + + + + + + + + + + +
    + +
    + +
    + +
    + + + +
    +

    Drag the map around inside the viewport. Works with touch devices.

    +
    + + + From 3df4bc1b018503d0f4a22a04df41a86fd5e4a718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=CC=88rn=20Zaefferer?= Date: Mon, 5 Mar 2012 12:02:34 +0100 Subject: [PATCH 097/190] Interactions: Add pointer and closedhand cursor to map demo --- demos/draggable/closedhand.cur | Bin 0 -> 326 bytes demos/draggable/map.html | 9 ++++++++- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100755 demos/draggable/closedhand.cur diff --git a/demos/draggable/closedhand.cur b/demos/draggable/closedhand.cur new file mode 100755 index 0000000000000000000000000000000000000000..41aaa62a596f9e973f333e084e004da35bfdd9bf GIT binary patch literal 326 zcmbu(y$ypf5QgE`Mv<$CE-fxoW&}3Ks*J!W8Nosn6iAovz(opZ!dZ{+r#KrTft(|W z8?OKl;3-*p2|8QU html, body, .demo { height: 90%; } #map { width: 100%; height: 100%; max-width: 640px; overflow: hidden; position: relative; } - #map img { position: absolute; } + #map img { position: absolute; cursor: pointer; } + #map .ui-draggable-dragging { cursor: url('closedhand.cur'), move; } + diff --git a/demos/interaction/box.html b/demos/interaction/box.html index 73ce317621f..17bd03fd3dd 100644 --- a/demos/interaction/box.html +++ b/demos/interaction/box.html @@ -4,7 +4,7 @@ jQuery UI Interaction - Box - + diff --git a/demos/interaction/default.html b/demos/interaction/default.html index 80ae56d2cbd..24859575a11 100644 --- a/demos/interaction/default.html +++ b/demos/interaction/default.html @@ -4,7 +4,7 @@ jQuery UI Interaction - Default functionality - + From fb2eca65528f5d957c38184f9a1bbd977e064f88 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Thu, 8 Nov 2012 16:10:43 -0500 Subject: [PATCH 102/190] Draggable: If beforeStart is stopped by user, and appendTo is set, dragEl will be reset to proper position anyway --- ui/jquery.ui.draggable.js | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index e9b47219984..8ddbb000811 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -116,7 +116,12 @@ $.widget( "ui.draggable", $.ui.interaction, { // If user cancels beforeStart, don't allow dragging if ( this._trigger( "beforeStart", event, this._originalHash( pointerPosition ) ) === false ) { + + // domPosition needs to be undone even if beforeStart is stopped + // Otherwise this.dragEl will remain in the element appendTo is set to + this._resetDomPosition(); return false; + } this._setCss(); @@ -126,6 +131,25 @@ $.widget( "ui.draggable", $.ui.interaction, { this._trigger( "start", event, this._fullHash( pointerPosition ) ); this._blockFrames(); }, + + _resetDomPosition : function() { + + // Nothing to do in this case + if ( !this.domPosition ) { + return; + } + + parent = this.domPosition.parent; + next = parent.children().eq( this.domPosition.index ); + if ( next.length ) { + next.before( this.element ); + } else { + parent.append( this.element ); + } + this.element.offset( this.offset ); + this.domPosition = null; + + }, _move: function( event, pointerPosition ) { this._preparePosition( pointerPosition ); @@ -151,17 +175,7 @@ $.widget( "ui.draggable", $.ui.interaction, { if ( this.options.helper ) { this.dragEl.remove(); } - if ( this.domPosition ) { - parent = this.domPosition.parent; - next = parent.children().eq( this.domPosition.index ); - if ( next.length ) { - next.before( this.element ); - } else { - parent.append( this.element ); - } - this.element.offset( this.offset ); - this.domPosition = null; - } + this._resetDomPosition(); } this._unblockFrames(); From 74912d383a2191af5644391eff788fc2bc34f538 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 13 Nov 2012 16:37:09 -0500 Subject: [PATCH 103/190] Draggable: Replaced incorrect comma with semicolon after lint --- ui/jquery.ui.draggable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 8ddbb000811..fe104767432 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -415,7 +415,7 @@ $.widget( "ui.draggable", $.ui.draggable, { return; } - offset = container.offset(), + offset = container.offset(); left = offset.left + (parseFloat( $.css( container[0], "borderLeftWidth", true ) ) || 0) + (parseFloat( $.css( container[0], "paddingLeft", true ) ) || 0); From 110b3c7d2da33731880cf875fe3e24b0fb7c67ca Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 13 Nov 2012 20:12:28 -0500 Subject: [PATCH 104/190] Sortable: Initial commit with 99% code from draggable and in dire need of review and optimization --- ui/jquery.ui.sortable.js | 1451 +++++++++++--------------------------- 1 file changed, 415 insertions(+), 1036 deletions(-) diff --git a/ui/jquery.ui.sortable.js b/ui/jquery.ui.sortable.js index a95c80c68d7..e7785205fc0 100644 --- a/ui/jquery.ui.sortable.js +++ b/ui/jquery.ui.sortable.js @@ -3,1101 +3,480 @@ * http://jqueryui.com * * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license. + * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * - * http://api.jqueryui.com/sortable/ + * http://docs.jquery.com/UI/Sortable * * Depends: * jquery.ui.core.js - * jquery.ui.mouse.js + * jquery.ui.interaction.js * jquery.ui.widget.js */ (function( $, undefined ) { -/*jshint onevar: false, curly: false, eqeqeq: false, laxbreak: true, shadow: true, loopfunc: true */ -$.widget("ui.sortable", $.ui.mouse, { +// create a shallow copy of an object +function copy( obj ) { + var prop, + ret = {}; + for ( prop in obj ) { + ret[ prop ] = obj[ prop ]; + } + return ret; +} + +$.widget( "ui.sortable", $.ui.interaction, { version: "@VERSION", widgetEventPrefix: "sort", - ready: false, - options: { - appendTo: "parent", - axis: false, - connectWith: false, - containment: false, - cursor: 'auto', - cursorAt: false, - dropOnEmpty: true, - forcePlaceholderSize: false, - forceHelperSize: false, - grid: false, - handle: false, - helper: "original", - items: '> *', - opacity: false, - placeholder: false, - revert: false, - scroll: true, - scrollSensitivity: 20, - scrollSpeed: 20, - scope: "default", - tolerance: "intersect", - zIndex: 1000 - }, - _create: function() { - - var o = this.options; - this.containerCache = {}; - this.element.addClass("ui-sortable"); + items: 'li', // TODO: move to options when API is ready + + // dragEl: element being dragged (original or helper) + // position: final CSS position of dragEl + // offset: offset of dragEl + // originalPosition: CSS position before drag start + // originalOffset: offset before drag start + // originalPointer: pageX/Y at drag start (offset of pointer) + // startPosition: CSS position at drag start (after beforeStart) + // startOffset: offset at drag start (after beforeStart) + // tempPosition: overridable CSS position of dragEl + // overflowOffset: offset of scroll parent + // overflow: object containing width and height keys of scroll parent + // sortablePositions: cache of positions of all sortable items + // originalCssPosition: CSS position of element before being made absolute on start + // placeholder: reference to jquery object of cloned element that is being dragged - //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 i = this.items.length - 1; i >= 0; i-- ) - this.items[i].item.removeData(this.widgetName + "-item"); - - return this; - }, - - _setOption: function(key, value){ - if ( key === "disabled" ) { - this.options[ key ] = 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(this, arguments); - } + options: { }, - _mouseCapture: function(event, overrideHandle) { - var 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 - var currentItem = null; - - $(event.target).parents().each(function() { - if($.data(this, that.widgetName + '-item') == that) { - currentItem = $(this); - return false; - } + _create: function() { + + this._super(); + + this.element.addClass( "ui-sortable" ); + + this._setSortablePositions(); + + }, + + _setSortablePositions: function() { + + var sortablePositions = this.sortablePositions = []; + + this.element.find( this.items ).each( function() { + + var el = $(this); + + sortablePositions.push([{ + el: el, + offset: el.offset() + }]); }); - if($.data(event.target, that.widgetName + '-item') == that) currentItem = $(event.target); - - if(!currentItem) return false; - if(this.options.handle && !overrideHandle) { - var validHandle = false; - - $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; }); - if(!validHandle) return false; - } - - this.currentItem = currentItem; - this._removeCurrentsFromItems(); - return true; - - }, - - _mouseStart: function(event, overrideHandle, noActivation) { - - var o = 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 = { - 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 + + }, + + /** interaction interface **/ + + _isValidTarget: function( element ) { + + // TODO: options for what is actually valid + return element.is( this.items ); + }, + + _start: function( event, pointerPosition ) { + + var offset; + + // The actual dragging element, should always be a jQuery object + // this.dragEl = this.options.helper ? + // this._createHelper( pointerPosition ) : + // this.element; + + this.dragEl = $(event.target); + + // Save original css position if there are currently styles + // Otherwise the original css will be set back by removing attribute + if ( this.dragEl[0].style.position ) { + this.originalCssPosition = this.dragEl[0].style.position; + } + + // Create placeholder for while element is dragging + // TODO: what do we do about IDs? + // TODO: possibly use CSS for visibility portion + this.placeholder = this.dragEl.clone().removeAttr('id').css({ + visibility : 'hidden', + position : this.originalCssPosition || '' }); - // 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 = { prev: this.currentItem.prev()[0], parent: this.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.dragEl.after( this.placeholder ); + + this.dragEl.css( 'position', 'absolute' ); + + // // _createHelper() ensures that helpers are in the correct position + // // in the DOM, but we need to handle appendTo when there is no helper + // if ( this.options.appendTo && this.dragEl === this.element ) { + // this.domPosition = { + // parent: this.element.parent(), + // index: this.element.index() + // }; + // offset = this.dragEl.offset(); + // this.dragEl + // .appendTo( this.options.appendTo ) + // .offset( offset ); + // } + + this.cssPosition = this.dragEl.css( "position" ); + this.scrollParent = this.element.scrollParent(); + + // Cache starting positions + this.originalPosition = this.startPosition = this._getPosition(); + this.originalOffset = this.startOffset = this.dragEl.offset(); + this.originalPointer = pointerPosition; + + // Cache current position and offset + this.position = copy( this.startPosition ); + this.offset = copy( this.startOffset ); + + // Cache the offset of scrollParent, if required for _handleScrolling + if ( this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML" ) { this.overflowOffset = this.scrollParent.offset(); - - //Call callbacks - this._trigger("start", event, this._uiHash()); - - //Recache the helper size - if(!this._preserveHelperProportions) - this._cacheHelperProportions(); - - - //Post 'activate' events to possible containers - if(!noActivation) { - for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, this._uiHash(this)); } - } - - //Prepare possible droppables - if($.ui.ddmanager) - $.ui.ddmanager.current = this; - - if ($.ui.ddmanager && !o.dropBehaviour) - $.ui.ddmanager.prepareOffsets(this, event); - - 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) { - - //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) { - var o = this.options, scrolled = false; - 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(this, event); } - //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 (var i = this.items.length - 1; i >= 0; i--) { - - //Cache variables and intersection, continue if no intersection - var 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; - - if (itemElement != this.currentItem[0] //cannot intersect with itself - && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before - && !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked - && (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true) - //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container - ) { - - this.direction = intersection == 1 ? "down" : "up"; - - if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) { - this._rearrange(event, item); - } else { - break; - } - - this._trigger("change", event, this._uiHash()); - break; - } - } - - //Post events to containers - this._contactContainers(event); - - //Interconnect with droppables - if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); - - //Call callbacks - this._trigger('sort', event, this._uiHash()); - - this.lastPositionAbs = this.positionAbs; - return false; - - }, - - _mouseStop: function(event, noPropagation) { - - if(!event) return; - - //If we are using droppables, inform the manager about the drop - if ($.ui.ddmanager && !this.options.dropBehaviour) - $.ui.ddmanager.drop(this, event); - - if(this.options.revert) { - var that = this; - var cur = this.placeholder.offset(); - - this.reverting = true; - - $(this.helper).animate({ - left: cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft), - top: cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop) - }, parseInt(this.options.revert, 10) || 500, function() { - that._clear(event); - }); - } else { - this._clear(event, noPropagation); - } - - return false; - - }, - - cancel: function() { - - if(this.dragging) { - - this._mouseUp({ target: null }); - - 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 i = this.containers.length - 1; i >= 0; i--){ - this.containers[i]._trigger("deactivate", null, this._uiHash(this)); - if(this.containers[i].containerCache.over) { - this.containers[i]._trigger("out", null, this._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, { - helper: null, - dragging: false, - reverting: false, - _noFinalSort: null - }); - - 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 && o.connected); - var str = []; o = o || {}; - - $(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 && o.connected); - var ret = []; o = o || {}; - - 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; - - var l = item.left, - r = l + item.width, - t = item.top, - b = t + item.height; - - var dyClick = this.offset.click.top, - dxClick = this.offset.click.left; - - var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (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 (l < x1 + (this.helperProportions.width / 2) // Right Half - && x2 - (this.helperProportions.width / 2) < r // Left Half - && t < y1 + (this.helperProportions.height / 2) // Bottom Half - && y2 - (this.helperProportions.height / 2) < b ); // Top Half - - } - }, - - _intersectsWithPointer: function(item) { + this.overflow = { + height: this.scrollParent[0] === this.document[0] ? + this.window.height() : this.scrollParent.height(), + width: this.scrollParent[0] === this.document[0] ? + this.window.width() : this.scrollParent.width() + }; - var isOverElementHeight = (this.options.axis === 'x') || $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), - isOverElementWidth = (this.options.axis === 'y') || $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), - isOverElement = isOverElementHeight && isOverElementWidth, - verticalDirection = this._getDragVerticalDirection(), - horizontalDirection = this._getDragHorizontalDirection(); + this._preparePosition( pointerPosition ); - if (!isOverElement) + // If user cancels beforeStart, don't allow dragging + if ( this._trigger( "beforeStart", event, + this._originalHash( pointerPosition ) ) === false ) { return false; - - return this.floating ? - ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 ) - : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) ); - - }, - - _intersectsWithSides: function(item) { - - var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), - isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.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 !== 0 && (delta > 0 ? "down" : "up"); - }, - - _getDragHorizontalDirection: function() { - var delta = this.positionAbs.left - this.lastPositionAbs.left; - return delta !== 0 && (delta > 0 ? "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 items = []; - var queries = []; - var connectWith = this._connectWith(); - - if(connectWith && connected) { - for (var i = connectWith.length - 1; i >= 0; i--){ - var cur = $(connectWith[i]); - for (var j = cur.length - 1; j >= 0; j--){ - var inst = $.data(cur[j], this.widgetName); - if(inst && inst != this && !inst.options.disabled) { - queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]); - } - } - } - } - - queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]); - - for (var i = queries.length - 1; i >= 0; i--){ - 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; j < list.length; j++) { - if(list[j] == item.item[0]) - return false; - } - return true; - }); - - }, - - _refreshItems: function(event) { - - this.items = []; - this.containers = [this]; - var items = this.items; - var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]]; - var connectWith = this._connectWith(); - - if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down - for (var i = connectWith.length - 1; i >= 0; i--){ - var cur = $(connectWith[i]); - for (var j = cur.length - 1; j >= 0; j--){ - var inst = $.data(cur[j], this.widgetName); - if(inst && inst != this && !inst.options.disabled) { - queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); - this.containers.push(inst); - } - } - } - } - - for (var i = queries.length - 1; i >= 0; i--) { - var targetData = queries[i][1]; - var _queries = queries[i][0]; - - for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) { - var item = $(_queries[j]); - - item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager) - - items.push({ - item: item, - instance: targetData, - width: 0, height: 0, - left: 0, top: 0 - }); - } - } - - }, - - 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(); - } - - for (var i = this.items.length - 1; i >= 0; i--){ - var 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; - - var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; - - if (!fast) { - item.width = t.outerWidth(); - item.height = t.outerHeight(); - } - - var p = 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 (var i = this.containers.length - 1; i >= 0; i--){ - var p = 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 o = that.options; - - if(!o.placeholder || o.placeholder.constructor == String) { - var 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(container, p) { - - // 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')||0, 10) - parseInt(that.currentItem.css('paddingBottom')||0, 10)); } - if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css('paddingLeft')||0, 10) - parseInt(that.currentItem.css('paddingRight')||0, 10)); } - } - }; - } - - //Create the placeholder - that.placeholder = $(o.placeholder.element.call(that.element, that.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(that, that.placeholder); - - }, - - _contactContainers: function(event) { - - // get innermost container that intersects with item - var innermostContainer = null, innermostIndex = null; - - - for (var i = this.containers.length - 1; i >= 0; i--){ - - // 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])) + + } + + this._setCss(); + this.startPosition = this._getPosition(); + this.startOffset = this.dragEl.offset(); + + this._trigger( "start", event, this._fullHash( pointerPosition ) ); + this._blockFrames(); + }, + + _move: function( event, pointerPosition ) { + + var sort, sortItem, top, left, sortIndex, + len = this.sortablePositions.length; + + + this._preparePosition( pointerPosition ); + + // // If user cancels drag, don't move the element + // if ( this._trigger( "drag", event, this._fullHash( pointerPosition ) ) === false ) { + // return; + // } + + this._setCss(); + + // Scroll the scrollParent, if needed + this._handleScrolling( pointerPosition ); + + for ( sortIndex=0; sortIndex= 0; j--) { - if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; - if(this.items[j].item[0] == this.currentItem[0]) continue; - var cur = this.items[j].item.offset()[posProperty]; - var 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"; + + if ( this._over( sortItem ) ) { + + // TODO: cache height of element + if ( ( this.offset.top + this.dragEl.height() ) > ( sortItem.offset.top + sortItem.el.height()/2 ) ) { + + sortItem.el.after( this.dragEl ); + this.dragEl.after( this.placeholder ); + this._setSortablePositions(); + } + else if ( this.offset.top < ( sortItem.offset.top + sortItem.el.height()/2 ) ) { + sortItem.el.before( this.dragEl ); + this.dragEl.before( this.placeholder ); + this._setSortablePositions(); + } + } + + } - - if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled - return; - - this.currentContainer = this.containers[innermostIndex]; - itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); - this._trigger("change", event, this._uiHash()); - this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); - - //Update the placeholder - this.options.placeholder.update(this.currentContainer, this.placeholder); - - this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); - this.containers[innermostIndex].containerCache.over = 1; } - - - }, - - _createHelper: function(event) { - - var o = this.options; - var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem); - - if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already - $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); - - if(helper[0] == this.currentItem[0]) - this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.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(); - } - - 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' && $.ui.ie)) //Ugly IE fix - po = { top: 0, left: 0 }; + + }, + + // TODO: swap out for real tolerance options + _over: function( sortItem ) { + + // TODO: use same cache from _move for height and width of element + var edges = { + droppableRight: sortItem.offset.left + sortItem.el.width(), + droppableBottom: sortItem.offset.top + sortItem.el.height(), + draggableRight: this.offset.left + this.dragEl.width(), + draggableBottom: this.offset.top + this.dragEl.height() + }; + + return sortItem.offset.left < edges.draggableRight && + edges.droppableRight > this.offset.left && + sortItem.offset.top < edges.draggableBottom && + edges.droppableBottom > sortItem.offset.top; + + }, + + _stop: function( event, pointerPosition ) { + + var parent, next; + + this._preparePosition( pointerPosition ); + + // // If user cancels stop, leave helper there + // if ( this._trigger( "stop", event, this._fullHash( pointerPosition ) ) !== false ) { + // if ( this.options.helper ) { + // this.dragEl.remove(); + // } + // this._resetDomPosition(); + // } + + // If there were inline styles before drag, set them back + if ( this.originalCssPosition ) { + this.dragEl.css( 'position', this.originalCssPosition ); + } + // If there were no inline styles, let CSS take over again by removing inline absolute + else { + this.dragEl.css( 'position', '' ); + } + + // TODO: should same thing be done here as is done for position or is there better way altogether + this.dragEl.css( 'left', '' ); + this.dragEl.css( 'top', '' ); + + this.placeholder.remove(); + + // Unset properties only needed during draggin/sorting + this.dragEl = null; + this.originalCssPosition = null; + this.placeholder = null; + + this._unblockFrames(); + }, + + // /** internal **/ + + // _createHelper: function( pointerPosition ) { + // var helper, + // offset = this.element.offset(), + // xPos = (pointerPosition.x - offset.left) / this.element.outerWidth(), + // yPos = (pointerPosition.y - offset.top) / this.element.outerHeight(); + + // // clone + // if ( this.options.helper === true ) { + // helper = this.element.clone() + // .removeAttr( "id" ) + // .find( "[id]" ) + // .removeAttr( "id" ) + // .end(); + // } else { + // // TODO: figure out the signature for this; see #4957 + // helper = $( this.options.helper() ); + // } + + // // Ensure the helper is in the DOM; obey the appendTo option if it exists + // if ( this.options.appendTo || !helper.closest( "body" ).length ) { + // helper.appendTo( this.options.appendTo || this.document[0].body ); + // } + + // return helper + // // Helper must be absolute to function properly + // .css( "position", "absolute" ) + // .offset({ + // left: pointerPosition.x - helper.outerWidth() * xPos, + // top: pointerPosition.y - helper.outerHeight() * yPos + // }); + // }, + + _getPosition: function() { + var left, top, position, + scrollTop = this.scrollParent.scrollTop(), + scrollLeft = this.scrollParent.scrollLeft(); + + // If fixed or absolute + if ( this.cssPosition !== "relative" ) { + position = this.dragEl.position(); + + // Take into account scrollbar + position.top -= scrollTop; + position.left -= scrollLeft; + + return position; + } + + // When using relative, css values are checked + // Otherwise the position wouldn't account for padding on ancestors + left = this.dragEl.css( "left" ); + top = this.dragEl.css( "top" ); + + // Webkit will give back auto if there is no explicit value + left = ( left === "auto" ) ? 0: parseInt( left, 10 ); + top = ( top === "auto" ) ? 0: parseInt( top, 10 ); return { - top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), - left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) + left: left - scrollLeft, + top: top - scrollTop }; - }, - _getRelativeOffset: function() { - - if(this.cssPosition == "relative") { - var p = this.currentItem.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.currentItem.css("marginLeft"),10) || 0), - top: (parseInt(this.currentItem.css("marginTop"),10) || 0) + _handleScrolling: function( pointerPosition ) { + var scrollTop = this.scrollParent.scrollTop(), + scrollLeft = this.scrollParent.scrollLeft(), + scrollSensitivity = 20, + baseSpeed = 5, + speed = function( distance ) { + return baseSpeed + Math.round( distance / 2 ); + }, + // overflowOffset is only set when scrollParent is not doc/html + overflowLeft = this.overflowOffset ? + this.overflowOffset.left : + scrollLeft, + overflowTop = this.overflowOffset ? + this.overflowOffset.top : + scrollTop, + xRight = this.overflow.width + overflowLeft - pointerPosition.x, + xLeft = pointerPosition.x- overflowLeft, + yBottom = this.overflow.height + overflowTop - pointerPosition.y, + yTop = pointerPosition.y - overflowTop; + + // Handle vertical scrolling + if ( yBottom < scrollSensitivity ) { + this.scrollParent.scrollTop( scrollTop + + speed( scrollSensitivity - yBottom ) ); + } else if ( yTop < scrollSensitivity ) { + this.scrollParent.scrollTop( scrollTop - + speed( scrollSensitivity - yTop ) ); + } + + // Handle horizontal scrolling + if ( xRight < scrollSensitivity ) { + this.scrollParent.scrollLeft( scrollLeft + + speed( scrollSensitivity - xRight ) ); + } else if ( xLeft < scrollSensitivity ) { + this.scrollParent.scrollLeft( scrollLeft - + speed( scrollSensitivity - xLeft ) ); + } + }, + + // Uses event to determine new position of draggable, before any override from callbacks + // TODO: handle absolute element inside relative parent like a relative element + _preparePosition: function( pointerPosition ) { + var leftDiff = pointerPosition.x - this.originalPointer.x, + topDiff = pointerPosition.y - this.originalPointer.y, + newLeft = leftDiff + this.startPosition.left, + newTop = topDiff + this.startPosition.top; + + // Save off new values for .css() in various callbacks using this function + this.position = { + left: newLeft, + top: newTop }; - }, - _cacheHelperProportions: function() { - this.helperProportions = { - width: this.helper.outerWidth(), - height: this.helper.outerHeight() + // Save off values to compare user override against automatic coordinates + this.tempPosition = { + left: newLeft, + top: newTop }; - }, - _setContainment: function() { + // Refresh offset cache with new positions + this.offset.left = this.startOffset.left + leftDiff; + this.offset.top = this.startOffset.top + topDiff; + }, - 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 - ]; + // Places draggable where event, or user via event/callback, indicates + _setCss: function() { + var newLeft = this.position.left, + newTop = this.position.top; - if(!(/^(document|window|parent)$/).test(o.containment)) { - var ce = $(o.containment)[0]; - var co = $(o.containment).offset(); - var over = ($(ce).css("overflow") != 'hidden'); + // User overriding left/top so shortcut math is no longer valid + if ( this.tempPosition.left !== this.position.left || + this.tempPosition.top !== this.position.top ) { + // Reset offset based on difference of expected and overridden values + this.offset.left += newLeft - this.tempPosition.left; + this.offset.top += newTop - this.tempPosition.top; + } - 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 - ]; + // TODO: does this work with nested scrollable parents? + if ( this.cssPosition !== "fixed" ) { + newLeft += this.scrollParent.scrollLeft(); + newTop += this.scrollParent.scrollTop(); } + this.dragEl.css({ + left: newLeft, + top: newTop + }); }, - _convertPositionTo: function(d, pos) { - - if(!pos) pos = this.position; - var mod = d == "absolute" ? 1 : -1; - var 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 ? 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) - - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) - ) + _originalHash: function( pointerPosition ) { + var ret = { + position: this.position, + offset: copy( this.offset ), + pointer: copy( pointerPosition ) }; - }, - - _generatePosition: function(event) { - - var o = this.options, 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); - - // 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; - } - + if ( this.options.helper ) { + ret.helper = this.dragEl; } - 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 ? 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) - + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) - ) - }; - + return ret; }, - _rearrange: function(event, i, a, hardRefresh) { - - a ? 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 + _fullHash: function( pointerPosition ) { + return $.extend( this._originalHash( pointerPosition ), { + originalPosition: copy( this.originalPosition ), + originalOffset: copy( this.originalOffset ), + originalPointer: copy( this.originalPointer ) }); - }, - _clear: function(event, noPropagation) { - - 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 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(var 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", event, this._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", event, this._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", event, this._uiHash()); }); - delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); - delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); - } - } - - - //Post events to containers - for (var i = this.containers.length - 1; i >= 0; i--){ - if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); - if(this.containers[i].containerCache.over) { - delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); - this.containers[i].containerCache.over = 0; - } - } - - //Do what was originally in plugins - if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor - if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity - if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index - - this.dragging = false; - if(this.cancelHelperRemoval) { - if(!noPropagation) { - this._trigger("beforeStop", event, this._uiHash()); - for (var i=0; i < delayedTriggers.length; i++) { - delayedTriggers[i].call(this, event); - } //Trigger all delayed events - this._trigger("stop", event, this._uiHash()); - } - - this.fromOutside = false; - return false; - } - - if(!noPropagation) this._trigger("beforeStop", event, this._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; + _blockFrames: function() { + var body = this.document[0].body; - if(!noPropagation) { - for (var i=0; i < delayedTriggers.length; i++) { - delayedTriggers[i].call(this, event); - } //Trigger all delayed events - this._trigger("stop", event, this._uiHash()); - } - - this.fromOutside = false; - return true; + this.iframeBlocks = this.document.find( "iframe" ).map(function() { + var iframe = $( this ), + iframeOffset = iframe.offset(); + return $( "
    " ) + .css({ + position: "absolute", + width: iframe.outerWidth(), + height: iframe.outerHeight(), + top: iframeOffset.top, + left: iframeOffset.left + }) + .appendTo( body )[0]; + }); }, - _trigger: function() { - if ($.Widget.prototype._trigger.apply(this, arguments) === false) { - this.cancel(); + _unblockFrames: function() { + if ( this.iframeBlocks ) { + this.iframeBlocks.remove(); + delete this.iframeBlocks; } }, - _uiHash: function(_inst) { - var inst = _inst || this; - return { - helper: inst.helper, - placeholder: inst.placeholder || $([]), - position: inst.position, - originalPosition: inst.originalPosition, - offset: inst.positionAbs, - item: inst.currentItem, - sender: _inst ? _inst.element : null - }; + _destroy: function() { + this.element.removeClass( "ui-sortable" ); + this._super(); } - }); - -})(jQuery); +})( jQuery ); \ No newline at end of file From 4e0e4e113ab7fc1f27e52f439e3f0284f9ee20a4 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Tue, 4 Dec 2012 22:26:40 -0500 Subject: [PATCH 105/190] Get the draggable tests to run --- tests/unit/draggable/draggable.html | 2 +- tests/unit/draggable/draggable_core.js | 2 +- ui/jquery.ui.draggable.js | 20 +++++++++----------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/tests/unit/draggable/draggable.html b/tests/unit/draggable/draggable.html index dce226a9ae5..b43826f5d82 100644 --- a/tests/unit/draggable/draggable.html +++ b/tests/unit/draggable/draggable.html @@ -15,7 +15,7 @@ js: [ "ui/jquery.ui.core.js", "ui/jquery.ui.widget.js", - "ui/jquery.ui.mouse.js", + "ui/jquery.ui.interaction.js", "ui/jquery.ui.draggable.js" ] }); diff --git a/tests/unit/draggable/draggable_core.js b/tests/unit/draggable/draggable_core.js index 39151d5f7f0..9c59150c777 100644 --- a/tests/unit/draggable/draggable_core.js +++ b/tests/unit/draggable/draggable_core.js @@ -4,7 +4,7 @@ (function($) { -module("draggable"); +module("draggable: core"); test("element types", function() { var typeNames = ('p,h1,h2,h3,h4,h5,h6,blockquote,ol,ul,dl,div,form' + diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index fe104767432..27d2ac1e60e 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -32,7 +32,7 @@ $.widget( "ui.draggable", $.ui.interaction, { options: { appendTo: null, handle: null, - helper: null + helper: false }, // dragEl: element being dragged (original or helper) @@ -116,12 +116,12 @@ $.widget( "ui.draggable", $.ui.interaction, { // If user cancels beforeStart, don't allow dragging if ( this._trigger( "beforeStart", event, this._originalHash( pointerPosition ) ) === false ) { - + // domPosition needs to be undone even if beforeStart is stopped // Otherwise this.dragEl will remain in the element appendTo is set to this._resetDomPosition(); return false; - + } this._setCss(); @@ -131,16 +131,16 @@ $.widget( "ui.draggable", $.ui.interaction, { this._trigger( "start", event, this._fullHash( pointerPosition ) ); this._blockFrames(); }, - + _resetDomPosition : function() { - + // Nothing to do in this case if ( !this.domPosition ) { return; } - - parent = this.domPosition.parent; - next = parent.children().eq( this.domPosition.index ); + + var parent = this.domPosition.parent, + next = parent.children().eq( this.domPosition.index ); if ( next.length ) { next.before( this.element ); } else { @@ -148,7 +148,7 @@ $.widget( "ui.draggable", $.ui.interaction, { } this.element.offset( this.offset ); this.domPosition = null; - + }, _move: function( event, pointerPosition ) { @@ -166,8 +166,6 @@ $.widget( "ui.draggable", $.ui.interaction, { }, _stop: function( event, pointerPosition ) { - var parent, next; - this._preparePosition( pointerPosition ); // If user cancels stop, leave helper there From 0e65dec8c4ae5c3fa558603db841bf2041f040fd Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Wed, 5 Dec 2012 00:07:55 -0500 Subject: [PATCH 106/190] enforce the new draggable API in test suite --- tests/unit/draggable/draggable_common.js | 70 ++++++++++++++---------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/tests/unit/draggable/draggable_common.js b/tests/unit/draggable/draggable_common.js index 34fd20564df..0f6d94b81a7 100644 --- a/tests/unit/draggable/draggable_common.js +++ b/tests/unit/draggable/draggable_common.js @@ -1,33 +1,47 @@ TestHelpers.commonWidgetTests( "draggable", { defaults: { - addClasses: true, - appendTo: "parent", - axis: false, - cancel: "input,textarea,button,select,option", - connectToSortable: false, - containment: false, - create: null, - cursor: "auto", - cursorAt: false, - delay: 0, + // options + appendTo: null, + containment: null, disabled: false, - distance: 1, - grid: false, - handle: false, - helper: "original", - iframeFix: false, - opacity: false, - refreshPositions: false, - revert: false, - revertDuration: 500, - scroll: true, - scrollSensitivity: 20, - scrollSpeed: 20, - scope: "default", - snap: false, - snapMode: "both", - snapTolerance: 20, - stack: false, - zIndex: false + // exclude: "input,textarea,button,select,option", + handle: null, + helper: false, + + // backCompat options + // addClasses: true, + // axis: false, + // connectToSortable: false, + // cursor: "auto", + // cursorAt: false, + // grid: false, + // iframeFix: false, + // opacity: false, + // refreshPositions: false, + // revert: false, + // revertDuration: 500, + // scroll: true, + // scrollSensitivity: 20, + // scrollSpeed: 20, + // scope: "default", + // snap: false, + // snapMode: "both", + // snapTolerance: 20, + // stack: false, + // zIndex: false, + + // methods + // destroy: null, + // disable: null, + // enable: null, + // option: null, + // widget: null, + + // callbacks + // beforeStart: null, + create: null + // drag: null, + // start: null, + // stop: null } }); From 25cf569c63d66c223cc09aed36ae108487fdd084 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 10 Dec 2012 17:10:45 -0500 Subject: [PATCH 107/190] Draggable: Added exclude option without backCompat --- ui/jquery.ui.draggable.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 27d2ac1e60e..8226c0bcd96 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -32,7 +32,8 @@ $.widget( "ui.draggable", $.ui.interaction, { options: { appendTo: null, handle: null, - helper: false + helper: false, + exclude: "input,textarea,button,select,option" }, // dragEl: element being dragged (original or helper) @@ -63,7 +64,11 @@ $.widget( "ui.draggable", $.ui.interaction, { /** interaction interface **/ _isValidTarget: function( element ) { - return this.options.handle ? element.is( this.options.handle ) : true; + + var handle = this.options.handle ? element.is( this.options.handle ) : true, + exclude = this.options.exclude ? element.is( this.options.exclude ) : false; + + return ( handle && !exclude ); }, _start: function( event, pointerPosition ) { From 94e475ba2d851cb07d86a4a1058154192bdd27fa Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 10 Dec 2012 17:14:37 -0500 Subject: [PATCH 108/190] Draggable: _blockFrames now appends blocking div to iframe parent rather than body. Should fix Ticket #7650. --- ui/jquery.ui.draggable.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 8226c0bcd96..a6276c37fb1 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -361,7 +361,6 @@ $.widget( "ui.draggable", $.ui.interaction, { }, _blockFrames: function() { - var body = this.document[0].body; this.iframeBlocks = this.document.find( "iframe" ).map(function() { var iframe = $( this ), @@ -375,7 +374,7 @@ $.widget( "ui.draggable", $.ui.interaction, { top: iframeOffset.top, left: iframeOffset.left }) - .appendTo( body )[0]; + .appendTo( iframe.parent() )[0]; }); }, From 93dfd995df66eb1280d69f5017ef7e6af32c5c98 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 10 Dec 2012 17:20:11 -0500 Subject: [PATCH 109/190] Draggable: Added disabled option --- ui/jquery.ui.draggable.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index a6276c37fb1..6eaf03036b2 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -33,7 +33,8 @@ $.widget( "ui.draggable", $.ui.interaction, { appendTo: null, handle: null, helper: false, - exclude: "input,textarea,button,select,option" + exclude: "input,textarea,button,select,option", + disabled: false }, // dragEl: element being dragged (original or helper) @@ -73,6 +74,11 @@ $.widget( "ui.draggable", $.ui.interaction, { _start: function( event, pointerPosition ) { var offset; + + // Stop drag if option says disabled + if ( this.options.disabled === true ) { + return; + } // The actual dragging element, should always be a jQuery object this.dragEl = this.options.helper ? From 8a8a26f9da1e16552fc83485692a3789612bf382 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 10 Dec 2012 17:35:15 -0500 Subject: [PATCH 110/190] Draggable: Removed disabled option after realizing it is in widget. Also fixed spaces -> tabs. --- ui/jquery.ui.draggable.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 6eaf03036b2..3d5aa5d11e7 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -33,8 +33,7 @@ $.widget( "ui.draggable", $.ui.interaction, { appendTo: null, handle: null, helper: false, - exclude: "input,textarea,button,select,option", - disabled: false + exclude: "input,textarea,button,select,option" }, // dragEl: element being dragged (original or helper) @@ -49,7 +48,7 @@ $.widget( "ui.draggable", $.ui.interaction, { // overflowOffset: offset of scroll parent // overflow: object containing width and height keys of scroll parent // domPosition: object containing original parent and index when using - // appendTo option without a helper + // appendTo option without a helper _create: function() { this._super(); @@ -65,20 +64,14 @@ $.widget( "ui.draggable", $.ui.interaction, { /** interaction interface **/ _isValidTarget: function( element ) { - - var handle = this.options.handle ? element.is( this.options.handle ) : true, - exclude = this.options.exclude ? element.is( this.options.exclude ) : false; - - return ( handle && !exclude ); + var handle = this.options.handle ? element.is( this.options.handle ) : true, + exclude = this.options.exclude ? element.is( this.options.exclude ) : false; + + return ( handle && !exclude ); }, _start: function( event, pointerPosition ) { var offset; - - // Stop drag if option says disabled - if ( this.options.disabled === true ) { - return; - } // The actual dragging element, should always be a jQuery object this.dragEl = this.options.helper ? From 44330395e1dca3d41e134d74fd1f66a247d8fe6e Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 10 Dec 2012 17:50:13 -0500 Subject: [PATCH 111/190] Draggable: Added axis backCompat --- ui/jquery.ui.draggable.js | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 3d5aa5d11e7..a7757f2ab1c 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -474,3 +474,52 @@ $.widget( "ui.draggable", $.ui.draggable, { }); })( jQuery ); + +// DEPRECATED +if ( $.uiBackCompat !== false ) { + + // axis option + $.widget( "ui.draggable", $.ui.draggable, { + options: { + axis: false + }, + + _create : function() { + + var start_left, start_top; + + this._super(); + + // If movement should only move left/right + if ( this.options.axis === 'x' ) { + + // Cache starting top position to keep it from moving + this.element.on( 'dragbeforestart', function( e, ui ) { + start_top = ui.position.top; + }); + + // On drag, make sure top does not change so axis is locked + this.element.on( 'drag', function( e, ui ) { + ui.position.top = start_top; + }); + + } + // If movement should only move up/down + else if ( this.options.axis === 'y' ) { + + // Cache starting left position to keep it from moving + this.element.on( 'dragbeforestart', function( e, ui ) { + start_left = ui.position.left; + }); + + // On drag, make sure top does not change so axis is locked + this.element.on( 'drag', function( e, ui ) { + ui.position.left = start_left; + }); + + } + + } + }); + +} \ No newline at end of file From 4626c2bb34f0431fb1989fc0e92d968ab68792de Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 10 Dec 2012 18:03:58 -0500 Subject: [PATCH 112/190] Draggable: Added cursor backCompat --- ui/jquery.ui.draggable.js | 43 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index a7757f2ab1c..a3fe47ef3b1 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -522,4 +522,47 @@ if ( $.uiBackCompat !== false ) { } }); + // cursor option + $.widget( "ui.draggable", $.ui.draggable, { + options: { + cursor: 'auto' + }, + + _create : function() { + + var start_cursor, self, body; + + this._super(); + + if ( this.options.cursor ) { + + self = this; + body = $( document.body ); + + // Cache original cursor to set back + this.element.on( 'dragbeforestart', function( e, ui ) { + start_cursor = body.css( 'cursor' ); + }); + + // Set cursor to what user wants during drag + this.element.on( 'drag', function( e, ui ) { + body.css( 'cursor', self.options.cursor ); + }); + + // Set back cursor to whatever default was + this.element.on( 'dragstop', function( e, ui ) { + + // Make sure something was actually reported back before setting body + if ( start_cursor ) { + body.css( 'cursor', start_cursor ); + } + + }); + + } + + } + + }); + } \ No newline at end of file From f1f1b8d97eb3cddd9d870bce0eb2305d8dfd4ee7 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 11 Dec 2012 11:55:08 -0500 Subject: [PATCH 113/190] Draggable: Fixed variable casing + added cursorAt backCompat based on cursor-style.html demo --- ui/jquery.ui.draggable.js | 57 ++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index a3fe47ef3b1..b1873a5f77a 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -486,7 +486,7 @@ if ( $.uiBackCompat !== false ) { _create : function() { - var start_left, start_top; + var startLeft, startTop; this._super(); @@ -495,12 +495,12 @@ if ( $.uiBackCompat !== false ) { // Cache starting top position to keep it from moving this.element.on( 'dragbeforestart', function( e, ui ) { - start_top = ui.position.top; + startTop = ui.position.top; }); // On drag, make sure top does not change so axis is locked this.element.on( 'drag', function( e, ui ) { - ui.position.top = start_top; + ui.position.top = startTop; }); } @@ -509,12 +509,12 @@ if ( $.uiBackCompat !== false ) { // Cache starting left position to keep it from moving this.element.on( 'dragbeforestart', function( e, ui ) { - start_left = ui.position.left; + startLeft = ui.position.left; }); // On drag, make sure top does not change so axis is locked this.element.on( 'drag', function( e, ui ) { - ui.position.left = start_left; + ui.position.left = startLeft; }); } @@ -530,7 +530,7 @@ if ( $.uiBackCompat !== false ) { _create : function() { - var start_cursor, self, body; + var startCursor, self, body; this._super(); @@ -541,7 +541,7 @@ if ( $.uiBackCompat !== false ) { // Cache original cursor to set back this.element.on( 'dragbeforestart', function( e, ui ) { - start_cursor = body.css( 'cursor' ); + startCursor = body.css( 'cursor' ); }); // Set cursor to what user wants during drag @@ -553,8 +553,8 @@ if ( $.uiBackCompat !== false ) { this.element.on( 'dragstop', function( e, ui ) { // Make sure something was actually reported back before setting body - if ( start_cursor ) { - body.css( 'cursor', start_cursor ); + if ( startCursor ) { + body.css( 'cursor', startCursor ); } }); @@ -565,4 +565,43 @@ if ( $.uiBackCompat !== false ) { }); + // cursorAt option + $.widget( "ui.draggable", $.ui.draggable, { + options: { + cursorAt: false + }, + + _create : function() { + + var cursorAt, elem; + + this._super(); + + + if ( !this.options.cursorAt ) { + return; + } + + elem = this.dragEl; + cursorAt = this.options.cursorAt; + + this.element.on( 'dragbeforestart', function( e, ui ) { + if ( "top" in cursorAt ) { + ui.position.top += ui.pointer.y - ui.offset.top - cursorAt.top; + } + if ( "left" in cursorAt ) { + ui.position.left += ui.pointer.x - ui.offset.left - cursorAt.left; + } + if ( "bottom" in cursorAt ) { + ui.position.top += ui.pointer.y - ui.offset.top - elem.outerHeight() + cursorAt.bottom; + } + if ( "right" in cursorAt ) { + ui.position.left += ui.pointer.x - ui.offset.left - elem.outerWidth() + cursorAt.right; + } + }); + + } + + }); + } \ No newline at end of file From 9ef082821930636b1f74008b47f7f07ba35a5be6 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 11 Dec 2012 11:56:48 -0500 Subject: [PATCH 114/190] Draggable: Fixed elem reference in cursorAt --- ui/jquery.ui.draggable.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index b1873a5f77a..4dfa5afaee6 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -573,7 +573,8 @@ if ( $.uiBackCompat !== false ) { _create : function() { - var cursorAt, elem; + var self = this, + cursorAt; this._super(); @@ -582,10 +583,12 @@ if ( $.uiBackCompat !== false ) { return; } - elem = this.dragEl; cursorAt = this.options.cursorAt; this.element.on( 'dragbeforestart', function( e, ui ) { + + var elem = self.dragEl; + if ( "top" in cursorAt ) { ui.position.top += ui.pointer.y - ui.offset.top - cursorAt.top; } From 3cd5010b80084e2201acbdd74e5535c351d30c66 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 11 Dec 2012 18:20:48 -0500 Subject: [PATCH 115/190] Draggable: Added grid backCompat and fixed styles for single -> double quotes --- ui/jquery.ui.draggable.js | 85 ++++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 14 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 4dfa5afaee6..8839675980b 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -491,29 +491,29 @@ if ( $.uiBackCompat !== false ) { this._super(); // If movement should only move left/right - if ( this.options.axis === 'x' ) { + if ( this.options.axis === "x" ) { // Cache starting top position to keep it from moving - this.element.on( 'dragbeforestart', function( e, ui ) { + this.element.on( "dragbeforestart", function( e, ui ) { startTop = ui.position.top; }); // On drag, make sure top does not change so axis is locked - this.element.on( 'drag', function( e, ui ) { + this.element.on( "drag", function( e, ui ) { ui.position.top = startTop; }); } // If movement should only move up/down - else if ( this.options.axis === 'y' ) { + else if ( this.options.axis === "y" ) { // Cache starting left position to keep it from moving - this.element.on( 'dragbeforestart', function( e, ui ) { + this.element.on( "dragbeforestart", function( e, ui ) { startLeft = ui.position.left; }); // On drag, make sure top does not change so axis is locked - this.element.on( 'drag', function( e, ui ) { + this.element.on( "drag", function( e, ui ) { ui.position.left = startLeft; }); @@ -525,7 +525,7 @@ if ( $.uiBackCompat !== false ) { // cursor option $.widget( "ui.draggable", $.ui.draggable, { options: { - cursor: 'auto' + cursor: "auto" }, _create : function() { @@ -540,21 +540,21 @@ if ( $.uiBackCompat !== false ) { body = $( document.body ); // Cache original cursor to set back - this.element.on( 'dragbeforestart', function( e, ui ) { - startCursor = body.css( 'cursor' ); + this.element.on( "dragbeforestart", function( e, ui ) { + startCursor = body.css( "cursor" ); }); // Set cursor to what user wants during drag - this.element.on( 'drag', function( e, ui ) { - body.css( 'cursor', self.options.cursor ); + this.element.on( "drag", function( e, ui ) { + body.css( "cursor", self.options.cursor ); }); // Set back cursor to whatever default was - this.element.on( 'dragstop', function( e, ui ) { + this.element.on( "dragstop", function( e, ui ) { // Make sure something was actually reported back before setting body if ( startCursor ) { - body.css( 'cursor', startCursor ); + body.css( "cursor", startCursor ); } }); @@ -585,7 +585,7 @@ if ( $.uiBackCompat !== false ) { cursorAt = this.options.cursorAt; - this.element.on( 'dragbeforestart', function( e, ui ) { + this.element.on( "dragbeforestart", function( e, ui ) { var elem = self.dragEl; @@ -607,4 +607,61 @@ if ( $.uiBackCompat !== false ) { }); + // grid option + $.widget( "ui.draggable", $.ui.draggable, { + options: { + grid: false + }, + + _create : function() { + + var x, y, currentX, currentY; + + this._super(); + + if ( !this.options.grid ) { + return; + } + + x = this.options.grid[0]; + y = this.options.grid[1]; + + this.element.on( "dragbeforestart", function( e, ui ) { + + currentX = ui.position.left; + currentY = ui.position.top; + + }); + + this.element.on( "drag", function( e, ui ) { + + if ( x ) { + if ( ui.position.left - currentX > x/2 ) { + currentX = currentX + x; + } + else if ( currentX - ui.position.left > x/2 ) { + currentX = currentX - x; + } + } + + if ( y ) { + if ( ui.position.top - currentY > y/2 ) { + currentY = currentY + y; + } + else if ( currentY - ui.position.top > y/2 ) { + currentY = currentY - y; + } + } + + + ui.position.left = currentX; + ui.position.top = currentY; + + + }); + + } + + }); + } \ No newline at end of file From ee55a9df42ed657a1e60043638e5b9237067bc3b Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 11 Dec 2012 18:46:35 -0500 Subject: [PATCH 116/190] Draggable Unit: Removed any references to addClasses --- tests/unit/draggable/draggable_common.js | 11 +++++------ tests/unit/draggable/draggable_options.js | 16 ---------------- 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/tests/unit/draggable/draggable_common.js b/tests/unit/draggable/draggable_common.js index 0f6d94b81a7..61bbe2d8a60 100644 --- a/tests/unit/draggable/draggable_common.js +++ b/tests/unit/draggable/draggable_common.js @@ -4,17 +4,16 @@ TestHelpers.commonWidgetTests( "draggable", { appendTo: null, containment: null, disabled: false, - // exclude: "input,textarea,button,select,option", + exclude: "input,textarea,button,select,option", handle: null, helper: false, // backCompat options - // addClasses: true, - // axis: false, + axis: false, // connectToSortable: false, - // cursor: "auto", - // cursorAt: false, - // grid: false, + cursor: "auto", + cursorAt: false, + grid: false, // iframeFix: false, // opacity: false, // refreshPositions: false, diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index 3f4592d31fa..4f4ccd9380e 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -5,22 +5,6 @@ module("draggable: options"); -test("{ addClasses: true }, default", function() { - expect( 1 ); - var el = $("
    ").draggable({ addClasses: true }); - ok(el.is(".ui-draggable"), "'ui-draggable' class added"); - - el.draggable("destroy"); -}); - -test("{ addClasses: false }", function() { - expect( 1 ); - var el = $("
    ").draggable({ addClasses: false }); - ok(!el.is(".ui-draggable"), "'ui-draggable' class not added"); - - el.draggable("destroy"); -}); - test("{ appendTo: 'parent' }, default", function() { expect( 2 ); var el = $("#draggable2").draggable({ appendTo: 'parent' }); From b7b0fff9b206526506ce97abe29063518f4b677a Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 11 Dec 2012 18:52:56 -0500 Subject: [PATCH 117/190] Draggable Unit: Common now has all failures until more backCompat gets in --- tests/unit/draggable/draggable_common.js | 47 ++++++++++++------------ 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/tests/unit/draggable/draggable_common.js b/tests/unit/draggable/draggable_common.js index 61bbe2d8a60..ed724cf2241 100644 --- a/tests/unit/draggable/draggable_common.js +++ b/tests/unit/draggable/draggable_common.js @@ -14,33 +14,34 @@ TestHelpers.commonWidgetTests( "draggable", { cursor: "auto", cursorAt: false, grid: false, - // iframeFix: false, - // opacity: false, - // refreshPositions: false, - // revert: false, - // revertDuration: 500, - // scroll: true, - // scrollSensitivity: 20, - // scrollSpeed: 20, - // scope: "default", - // snap: false, - // snapMode: "both", - // snapTolerance: 20, - // stack: false, - // zIndex: false, + iframeFix: false, + opacity: false, + refreshPositions: false, + revert: false, + revertDuration: 500, + scroll: true, + scrollSensitivity: 20, + scrollSpeed: 20, + scope: "default", + snap: false, + snapMode: "both", + snapTolerance: 20, + stack: false, + zIndex: false, + cancel: "input,textarea,button,select,option", // methods - // destroy: null, - // disable: null, - // enable: null, - // option: null, - // widget: null, + destroy: null, + disable: null, + enable: null, + option: null, + widget: null, // callbacks - // beforeStart: null, + beforeStart: null, create: null - // drag: null, - // start: null, - // stop: null + drag: null, + start: null, + stop: null } }); From bef00728f4d75071f15ca331fcc7a563c6824542 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 11 Dec 2012 18:54:03 -0500 Subject: [PATCH 118/190] Draggable Unit: Common file syntax error fix --- tests/unit/draggable/draggable_common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/draggable/draggable_common.js b/tests/unit/draggable/draggable_common.js index ed724cf2241..9c59ef14f49 100644 --- a/tests/unit/draggable/draggable_common.js +++ b/tests/unit/draggable/draggable_common.js @@ -39,7 +39,7 @@ TestHelpers.commonWidgetTests( "draggable", { // callbacks beforeStart: null, - create: null + create: null, drag: null, start: null, stop: null From 855416ef9b16736c78d8d367a963a598cb91744e Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 11 Dec 2012 19:04:22 -0500 Subject: [PATCH 119/190] Draggable Unit: Removed distance test since that is not getting backCompat --- tests/unit/draggable/draggable_options.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index 4f4ccd9380e..172e864be98 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -391,18 +391,6 @@ test("{ cursorAt: '20, 40' }", function() { }); }); -test("{ distance: 10 }", function() { - expect( 3 ); - - var el = $("#draggable2").draggable({ distance: 10 }); - TestHelpers.draggable.testDrag(el, el, -9, -9, 0, 0, 'distance not met'); - - TestHelpers.draggable.testDrag(el, el, -10, -10, -10, -10, 'distance met'); - - TestHelpers.draggable.testDrag(el, el, 9, 9, 0, 0, 'distance not met'); - -}); - test("{ grid: [50, 50] }, relative", function() { expect( 2 ); From 421f6afdc4702ed53c7c6714bd3c22d19cba0689 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 11 Dec 2012 19:16:20 -0500 Subject: [PATCH 120/190] Draggable: Added opacity backCompat along with some more comments in other areas --- ui/jquery.ui.draggable.js | 48 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 8839675980b..05d8d80cd43 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -578,7 +578,7 @@ if ( $.uiBackCompat !== false ) { this._super(); - + // No need to continue if ( !this.options.cursorAt ) { return; } @@ -619,15 +619,18 @@ if ( $.uiBackCompat !== false ) { this._super(); + // No need to continue if ( !this.options.grid ) { return; } + // Save off the intended intervals x = this.options.grid[0]; y = this.options.grid[1]; this.element.on( "dragbeforestart", function( e, ui ) { + // Save off the start position currentX = ui.position.left; currentY = ui.position.top; @@ -635,6 +638,7 @@ if ( $.uiBackCompat !== false ) { this.element.on( "drag", function( e, ui ) { + // If x is actually something, check that user is at least half way to next point if ( x ) { if ( ui.position.left - currentX > x/2 ) { currentX = currentX + x; @@ -644,6 +648,7 @@ if ( $.uiBackCompat !== false ) { } } + // If y is actually something, check that user is at least half way to next point if ( y ) { if ( ui.position.top - currentY > y/2 ) { currentY = currentY + y; @@ -653,10 +658,49 @@ if ( $.uiBackCompat !== false ) { } } - + // If there threshold wasn't crossed these variables wouldn't be changed + // Otherwise this will now bump the draggable to the next spot on grid ui.position.left = currentX; ui.position.top = currentY; + }); + + } + + }); + + // opacity option + $.widget( "ui.draggable", $.ui.draggable, { + options: { + opacity: false + }, + + _create : function() { + + var self = this, + originalOpacity; + + this._super(); + + // No need to continue + if ( !this.options.opacity ) { + return; + } + + this.element.on( "dragbeforestart", function( e, ui ) { + + // Cache the original opacity of draggable element to reset later + originalOpacity = self.dragEl.css( 'opacity' ); + + // Set draggable element to new opacity + self.dragEl.css( 'opacity', self.options.opacity ); + + }); + + this.element.on( "dragstop", function( e, ui ) { + + // Reset opacity + self.dragEl.css( 'opacity', originalOpacity ); }); From 5a2e5a0a9a6117427038cdd9640852a72c5a05c2 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 11 Dec 2012 19:21:37 -0500 Subject: [PATCH 121/190] Draggable: Added revert backCompat with TODO for droppable strings, since that is not written yet --- ui/jquery.ui.draggable.js | 43 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 05d8d80cd43..0701f915116 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -708,4 +708,47 @@ if ( $.uiBackCompat !== false ) { }); + // TODO: handle droppables + // revert option + $.widget( "ui.draggable", $.ui.draggable, { + options: { + revert: false + }, + + _create : function() { + + var self = this, + originalLeft, originalTop, originalPosition; + + this._super(); + + // No need to continue + if ( !this.options.revert ) { + return; + } + + this.element.on( "dragbeforestart", function( e, ui ) { + + // Cache the original css of draggable element to reset later + originalLeft = self.dragEl.css( 'left' ); + originalTop = self.dragEl.css( 'top' ); + originalPosition = self.dragEl.css( 'position' ); + + }); + + this.element.on( "dragstop", function( e, ui ) { + + // Reset to before drag + self.dragEl.css({ + left: originalLeft, + top: originalTop, + position: originalPosition + }); + + }); + + } + + }); + } \ No newline at end of file From 34b4fbf08bd6bad13f17c3c814c7ed106922d89c Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 11 Dec 2012 19:28:47 -0500 Subject: [PATCH 122/190] Draggable: Added revertDuration backCompat. --- ui/jquery.ui.draggable.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 0701f915116..f2c59bc4e56 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -709,10 +709,11 @@ if ( $.uiBackCompat !== false ) { }); // TODO: handle droppables - // revert option + // revert + revertDuration options $.widget( "ui.draggable", $.ui.draggable, { options: { - revert: false + revert: false, + revertDuration: 500 }, _create : function() { @@ -739,11 +740,11 @@ if ( $.uiBackCompat !== false ) { this.element.on( "dragstop", function( e, ui ) { // Reset to before drag - self.dragEl.css({ + self.dragEl.animate({ left: originalLeft, top: originalTop, position: originalPosition - }); + }, self.options.revertDuration ); }); From d2e726d172708f6182817b4ce94504650b15a8f9 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 11 Dec 2012 19:49:41 -0500 Subject: [PATCH 123/190] Draggable: Added zIndex backCompat --- ui/jquery.ui.draggable.js | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index f2c59bc4e56..d575cf4e41e 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -752,4 +752,43 @@ if ( $.uiBackCompat !== false ) { }); + // zIndex option + $.widget( "ui.draggable", $.ui.draggable, { + options: { + zIndex: false + }, + + _create : function() { + + var self = this, + originalZIndex; + + this._super(); + + // No need to continue + if ( !this.options.zIndex ) { + return; + } + + this.element.on( "dragbeforestart", function( e, ui ) { + + // Cache the original zIndex of draggable element to reset later + originalZIndex = self.dragEl.css( 'z-index' ); + + // Set draggable element to new zIndex + self.dragEl.css( 'z-index', self.options.zIndex ); + + }); + + this.element.on( "dragstop", function( e, ui ) { + + // Reset zIndex + self.dragEl.css( 'z-index', originalZIndex ); + + }); + + } + + }); + } \ No newline at end of file From 7cd8debe730c91909c0a6d8aff06e077f6b83ecc Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 11 Dec 2012 20:20:56 -0500 Subject: [PATCH 124/190] Draggable: Modified some backCompats to use dragstart rather than dragbeforestart --- ui/jquery.ui.draggable.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index d575cf4e41e..cd2fa873c92 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -540,7 +540,7 @@ if ( $.uiBackCompat !== false ) { body = $( document.body ); // Cache original cursor to set back - this.element.on( "dragbeforestart", function( e, ui ) { + this.element.on( "dragstart", function( e, ui ) { startCursor = body.css( "cursor" ); }); @@ -687,7 +687,7 @@ if ( $.uiBackCompat !== false ) { return; } - this.element.on( "dragbeforestart", function( e, ui ) { + this.element.on( "dragstart", function( e, ui ) { // Cache the original opacity of draggable element to reset later originalOpacity = self.dragEl.css( 'opacity' ); @@ -770,7 +770,7 @@ if ( $.uiBackCompat !== false ) { return; } - this.element.on( "dragbeforestart", function( e, ui ) { + this.element.on( "dragstart", function( e, ui ) { // Cache the original zIndex of draggable element to reset later originalZIndex = self.dragEl.css( 'z-index' ); From 9f018eb30a1725bfb2706851679a5314d66c5658 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Wed, 12 Dec 2012 14:23:17 -0500 Subject: [PATCH 125/190] Draggable + Sortable: Code review changes --- ui/jquery.ui.draggable.js | 53 ++++++++++++++++++--------------------- ui/jquery.ui.sortable.js | 3 +-- 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index cd2fa873c92..0ae48a38135 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -31,9 +31,9 @@ $.widget( "ui.draggable", $.ui.interaction, { options: { appendTo: null, + exclude: "input,textarea,button,select,option", handle: null, - helper: false, - exclude: "input,textarea,button,select,option" + helper: false }, // dragEl: element being dragged (original or helper) @@ -136,7 +136,7 @@ $.widget( "ui.draggable", $.ui.interaction, { this._blockFrames(); }, - _resetDomPosition : function() { + _resetDomPosition: function() { // Nothing to do in this case if ( !this.domPosition ) { @@ -494,12 +494,12 @@ if ( $.uiBackCompat !== false ) { if ( this.options.axis === "x" ) { // Cache starting top position to keep it from moving - this.element.on( "dragbeforestart", function( e, ui ) { + this.element.on( "dragbeforestart", function( event, ui ) { startTop = ui.position.top; }); // On drag, make sure top does not change so axis is locked - this.element.on( "drag", function( e, ui ) { + this.element.on( "drag", function( event, ui ) { ui.position.top = startTop; }); @@ -508,12 +508,12 @@ if ( $.uiBackCompat !== false ) { else if ( this.options.axis === "y" ) { // Cache starting left position to keep it from moving - this.element.on( "dragbeforestart", function( e, ui ) { + this.element.on( "dragbeforestart", function( event, ui ) { startLeft = ui.position.left; }); // On drag, make sure top does not change so axis is locked - this.element.on( "drag", function( e, ui ) { + this.element.on( "drag", function( event, ui ) { ui.position.left = startLeft; }); @@ -537,25 +537,22 @@ if ( $.uiBackCompat !== false ) { if ( this.options.cursor ) { self = this; - body = $( document.body ); + body = $( this.document[0].body ); // Cache original cursor to set back - this.element.on( "dragstart", function( e, ui ) { - startCursor = body.css( "cursor" ); + this.element.on( "dragstart", function( event, ui ) { + startCursor = body.style.cursor; }); // Set cursor to what user wants during drag - this.element.on( "drag", function( e, ui ) { + this.element.on( "drag", function( event, ui ) { body.css( "cursor", self.options.cursor ); }); // Set back cursor to whatever default was - this.element.on( "dragstop", function( e, ui ) { + this.element.on( "dragstop", function( event, ui ) { - // Make sure something was actually reported back before setting body - if ( startCursor ) { - body.css( "cursor", startCursor ); - } + body.css( "cursor", startCursor ); }); @@ -585,7 +582,7 @@ if ( $.uiBackCompat !== false ) { cursorAt = this.options.cursorAt; - this.element.on( "dragbeforestart", function( e, ui ) { + this.element.on( "dragbeforestart", function( event, ui ) { var elem = self.dragEl; @@ -628,7 +625,7 @@ if ( $.uiBackCompat !== false ) { x = this.options.grid[0]; y = this.options.grid[1]; - this.element.on( "dragbeforestart", function( e, ui ) { + this.element.on( "dragbeforestart", function( event, ui ) { // Save off the start position currentX = ui.position.left; @@ -636,14 +633,13 @@ if ( $.uiBackCompat !== false ) { }); - this.element.on( "drag", function( e, ui ) { + this.element.on( "drag", function( event, ui ) { // If x is actually something, check that user is at least half way to next point if ( x ) { if ( ui.position.left - currentX > x/2 ) { currentX = currentX + x; - } - else if ( currentX - ui.position.left > x/2 ) { + } else if ( currentX - ui.position.left > x/2 ) { currentX = currentX - x; } } @@ -652,8 +648,7 @@ if ( $.uiBackCompat !== false ) { if ( y ) { if ( ui.position.top - currentY > y/2 ) { currentY = currentY + y; - } - else if ( currentY - ui.position.top > y/2 ) { + } else if ( currentY - ui.position.top > y/2 ) { currentY = currentY - y; } } @@ -687,7 +682,7 @@ if ( $.uiBackCompat !== false ) { return; } - this.element.on( "dragstart", function( e, ui ) { + this.element.on( "dragstart", function( event, ui ) { // Cache the original opacity of draggable element to reset later originalOpacity = self.dragEl.css( 'opacity' ); @@ -697,7 +692,7 @@ if ( $.uiBackCompat !== false ) { }); - this.element.on( "dragstop", function( e, ui ) { + this.element.on( "dragstop", function( event, ui ) { // Reset opacity self.dragEl.css( 'opacity', originalOpacity ); @@ -728,7 +723,7 @@ if ( $.uiBackCompat !== false ) { return; } - this.element.on( "dragbeforestart", function( e, ui ) { + this.element.on( "dragbeforestart", function( event, ui ) { // Cache the original css of draggable element to reset later originalLeft = self.dragEl.css( 'left' ); @@ -737,7 +732,7 @@ if ( $.uiBackCompat !== false ) { }); - this.element.on( "dragstop", function( e, ui ) { + this.element.on( "dragstop", function( event, ui ) { // Reset to before drag self.dragEl.animate({ @@ -770,7 +765,7 @@ if ( $.uiBackCompat !== false ) { return; } - this.element.on( "dragstart", function( e, ui ) { + this.element.on( "dragstart", function( event, ui ) { // Cache the original zIndex of draggable element to reset later originalZIndex = self.dragEl.css( 'z-index' ); @@ -780,7 +775,7 @@ if ( $.uiBackCompat !== false ) { }); - this.element.on( "dragstop", function( e, ui ) { + this.element.on( "dragstop", function( event, ui ) { // Reset zIndex self.dragEl.css( 'z-index', originalZIndex ); diff --git a/ui/jquery.ui.sortable.js b/ui/jquery.ui.sortable.js index e7785205fc0..b3888b7efd7 100644 --- a/ui/jquery.ui.sortable.js +++ b/ui/jquery.ui.sortable.js @@ -449,7 +449,6 @@ $.widget( "ui.sortable", $.ui.interaction, { }, _blockFrames: function() { - var body = this.document[0].body; this.iframeBlocks = this.document.find( "iframe" ).map(function() { var iframe = $( this ), @@ -463,7 +462,7 @@ $.widget( "ui.sortable", $.ui.interaction, { top: iframeOffset.top, left: iframeOffset.left }) - .appendTo( body )[0]; + .appendTo( iframe.parent() )[0]; }); }, From 03fc1e817580208835412d219f11583f6572c102 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Thu, 20 Dec 2012 14:10:09 -0500 Subject: [PATCH 126/190] Draggable: Removed whitespace and fixed axis backCompat based on code review --- ui/jquery.ui.draggable.js | 219 ++++++++++++++++++-------------------- 1 file changed, 102 insertions(+), 117 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 0ae48a38135..53103f7a896 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -483,109 +483,94 @@ if ( $.uiBackCompat !== false ) { options: { axis: false }, - + _create : function() { - - var startLeft, startTop; + var self = this; + this._super(); - - // If movement should only move left/right - if ( this.options.axis === "x" ) { - // Cache starting top position to keep it from moving - this.element.on( "dragbeforestart", function( event, ui ) { - startTop = ui.position.top; - }); - - // On drag, make sure top does not change so axis is locked - this.element.on( "drag", function( event, ui ) { - ui.position.top = startTop; - }); - - } - // If movement should only move up/down - else if ( this.options.axis === "y" ) { - - // Cache starting left position to keep it from moving - this.element.on( "dragbeforestart", function( event, ui ) { - startLeft = ui.position.left; - }); - - // On drag, make sure top does not change so axis is locked - this.element.on( "drag", function( event, ui ) { - ui.position.left = startLeft; - }); + // On drag, make sure top does not change so axis is locked + this.element.on( "drag", function( event, ui ) { + + if ( self.options.axis === "x" ) { + ui.position.top = ui.originalPosition.top; + } + + if ( self.options.axis === "y" ) { + ui.position.left = ui.originalPosition.left; + } + + }); - } - } + }); - + // cursor option $.widget( "ui.draggable", $.ui.draggable, { options: { cursor: "auto" }, - + _create : function() { - + var startCursor, self, body; - + this._super(); - + if ( this.options.cursor ) { - + self = this; body = $( this.document[0].body ); - + // Cache original cursor to set back this.element.on( "dragstart", function( event, ui ) { - startCursor = body.style.cursor; + startCursor = body[0].style.cursor; }); - + // Set cursor to what user wants during drag this.element.on( "drag", function( event, ui ) { body.css( "cursor", self.options.cursor ); }); - + // Set back cursor to whatever default was this.element.on( "dragstop", function( event, ui ) { - + body.css( "cursor", startCursor ); }); - + } - + } - + }); - + // cursorAt option $.widget( "ui.draggable", $.ui.draggable, { options: { cursorAt: false }, - + _create : function() { - + var self = this, cursorAt; - + this._super(); - + // No need to continue if ( !this.options.cursorAt ) { return; } - + cursorAt = this.options.cursorAt; - + this.element.on( "dragbeforestart", function( event, ui ) { - + var elem = self.dragEl; - + if ( "top" in cursorAt ) { ui.position.top += ui.pointer.y - ui.offset.top - cursorAt.top; } @@ -599,42 +584,42 @@ if ( $.uiBackCompat !== false ) { ui.position.left += ui.pointer.x - ui.offset.left - elem.outerWidth() + cursorAt.right; } }); - + } - + }); - + // grid option $.widget( "ui.draggable", $.ui.draggable, { options: { grid: false }, - + _create : function() { - + var x, y, currentX, currentY; - + this._super(); - + // No need to continue if ( !this.options.grid ) { return; } - + // Save off the intended intervals x = this.options.grid[0]; y = this.options.grid[1]; - + this.element.on( "dragbeforestart", function( event, ui ) { - + // Save off the start position currentX = ui.position.left; currentY = ui.position.top; - + }); - + this.element.on( "drag", function( event, ui ) { - + // If x is actually something, check that user is at least half way to next point if ( x ) { if ( ui.position.left - currentX > x/2 ) { @@ -643,7 +628,7 @@ if ( $.uiBackCompat !== false ) { currentX = currentX - x; } } - + // If y is actually something, check that user is at least half way to next point if ( y ) { if ( ui.position.top - currentY > y/2 ) { @@ -652,57 +637,57 @@ if ( $.uiBackCompat !== false ) { currentY = currentY - y; } } - + // If there threshold wasn't crossed these variables wouldn't be changed // Otherwise this will now bump the draggable to the next spot on grid ui.position.left = currentX; ui.position.top = currentY; - + }); - + } - + }); - + // opacity option $.widget( "ui.draggable", $.ui.draggable, { options: { opacity: false }, - + _create : function() { - + var self = this, originalOpacity; - + this._super(); - + // No need to continue if ( !this.options.opacity ) { return; } - + this.element.on( "dragstart", function( event, ui ) { - + // Cache the original opacity of draggable element to reset later originalOpacity = self.dragEl.css( 'opacity' ); - + // Set draggable element to new opacity self.dragEl.css( 'opacity', self.options.opacity ); - + }); - + this.element.on( "dragstop", function( event, ui ) { - + // Reset opacity self.dragEl.css( 'opacity', originalOpacity ); - + }); - + } - + }); - + // TODO: handle droppables // revert + revertDuration options $.widget( "ui.draggable", $.ui.draggable, { @@ -710,80 +695,80 @@ if ( $.uiBackCompat !== false ) { revert: false, revertDuration: 500 }, - + _create : function() { - + var self = this, originalLeft, originalTop, originalPosition; - + this._super(); - + // No need to continue if ( !this.options.revert ) { return; } - + this.element.on( "dragbeforestart", function( event, ui ) { - + // Cache the original css of draggable element to reset later originalLeft = self.dragEl.css( 'left' ); originalTop = self.dragEl.css( 'top' ); originalPosition = self.dragEl.css( 'position' ); - + }); - + this.element.on( "dragstop", function( event, ui ) { - + // Reset to before drag self.dragEl.animate({ - left: originalLeft, - top: originalTop, - position: originalPosition + left: originalLeft, + top: originalTop, + position: originalPosition }, self.options.revertDuration ); - + }); - + } - + }); - + // zIndex option $.widget( "ui.draggable", $.ui.draggable, { options: { zIndex: false }, - + _create : function() { - + var self = this, originalZIndex; - + this._super(); - + // No need to continue if ( !this.options.zIndex ) { return; } - + this.element.on( "dragstart", function( event, ui ) { - + // Cache the original zIndex of draggable element to reset later originalZIndex = self.dragEl.css( 'z-index' ); - + // Set draggable element to new zIndex self.dragEl.css( 'z-index', self.options.zIndex ); - + }); - + this.element.on( "dragstop", function( event, ui ) { - + // Reset zIndex self.dragEl.css( 'z-index', originalZIndex ); - + }); - + } - + }); - + } \ No newline at end of file From 876575272ede8ea53f73b358f9dff12e31c54530 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Thu, 20 Dec 2012 14:58:44 -0500 Subject: [PATCH 127/190] Draggable: Added cancel backCompat --- ui/jquery.ui.draggable.js | 43 ++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 53103f7a896..34bacb3bbe6 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -484,7 +484,7 @@ if ( $.uiBackCompat !== false ) { axis: false }, - _create : function() { + _create: function() { var self = this; @@ -506,6 +506,35 @@ if ( $.uiBackCompat !== false ) { } }); + + // cancel option + $.widget( "ui.draggable", $.ui.draggable, { + options: { + cancel: null + }, + + _create: function() { + + this._super(); + + if ( this.options.cancel !== null ) { + this.options.exclude = this.options.cancel; + } + + }, + + _setOption: function( key, value ) { + + if ( key !== 'cancel' ) { + return this._super( key, value ); + } + + this._super( key, value ); + this.options.exclude = this.options.cancel; + + } + + }); // cursor option $.widget( "ui.draggable", $.ui.draggable, { @@ -513,7 +542,7 @@ if ( $.uiBackCompat !== false ) { cursor: "auto" }, - _create : function() { + _create: function() { var startCursor, self, body; @@ -553,7 +582,7 @@ if ( $.uiBackCompat !== false ) { cursorAt: false }, - _create : function() { + _create: function() { var self = this, cursorAt; @@ -595,7 +624,7 @@ if ( $.uiBackCompat !== false ) { grid: false }, - _create : function() { + _create: function() { var x, y, currentX, currentY; @@ -655,7 +684,7 @@ if ( $.uiBackCompat !== false ) { opacity: false }, - _create : function() { + _create: function() { var self = this, originalOpacity; @@ -696,7 +725,7 @@ if ( $.uiBackCompat !== false ) { revertDuration: 500 }, - _create : function() { + _create: function() { var self = this, originalLeft, originalTop, originalPosition; @@ -738,7 +767,7 @@ if ( $.uiBackCompat !== false ) { zIndex: false }, - _create : function() { + _create: function() { var self = this, originalZIndex; From 36f7c7b0b5092b53dbd5d2077546d83b9385028c Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Thu, 20 Dec 2012 15:21:30 -0500 Subject: [PATCH 128/190] Draggable: Options are actually changeable after init now. --- ui/jquery.ui.draggable.js | 124 ++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 51 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 34bacb3bbe6..140c636e3b8 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -548,29 +548,34 @@ if ( $.uiBackCompat !== false ) { this._super(); - if ( this.options.cursor ) { + self = this; + body = $( this.document[0].body ); - self = this; - body = $( this.document[0].body ); - - // Cache original cursor to set back - this.element.on( "dragstart", function( event, ui ) { + // Cache original cursor to set back + this.element.on( "dragstart", function( event, ui ) { + + if ( self.options.cursor ) { startCursor = body[0].style.cursor; - }); + } + + }); - // Set cursor to what user wants during drag - this.element.on( "drag", function( event, ui ) { + // Set cursor to what user wants during drag + this.element.on( "drag", function( event, ui ) { + if ( self.options.cursor ) { body.css( "cursor", self.options.cursor ); - }); + } + }); - // Set back cursor to whatever default was - this.element.on( "dragstop", function( event, ui ) { + // Set back cursor to whatever default was + this.element.on( "dragstop", function( event, ui ) { + if ( self.options.cursor ) { body.css( "cursor", startCursor ); + } - }); + }); - } } @@ -584,21 +589,19 @@ if ( $.uiBackCompat !== false ) { _create: function() { - var self = this, - cursorAt; + var self = this; this._super(); - // No need to continue - if ( !this.options.cursorAt ) { - return; - } - - cursorAt = this.options.cursorAt; - this.element.on( "dragbeforestart", function( event, ui ) { - - var elem = self.dragEl; + + var elem = self.dragEl, + cursorAt = self.options.cursorAt; + + // No need to continue + if ( !cursorAt ) { + return; + } if ( "top" in cursorAt ) { ui.position.top += ui.pointer.y - ui.offset.top - cursorAt.top; @@ -626,28 +629,32 @@ if ( $.uiBackCompat !== false ) { _create: function() { - var x, y, currentX, currentY; + var self = this, + currentX, currentY; this._super(); - // No need to continue - if ( !this.options.grid ) { - return; - } - - // Save off the intended intervals - x = this.options.grid[0]; - y = this.options.grid[1]; - this.element.on( "dragbeforestart", function( event, ui ) { + + if ( !self.options.grid ) { + return; + } - // Save off the start position + // Save off the start position, which may be overwritten during drag currentX = ui.position.left; currentY = ui.position.top; }); this.element.on( "drag", function( event, ui ) { + + if ( !self.options.grid ) { + return; + } + + // Save off the intended intervals + var x = self.options.grid[0], + y = self.options.grid[1]; // If x is actually something, check that user is at least half way to next point if ( x ) { @@ -691,12 +698,12 @@ if ( $.uiBackCompat !== false ) { this._super(); - // No need to continue - if ( !this.options.opacity ) { - return; - } - this.element.on( "dragstart", function( event, ui ) { + + // No need to continue + if ( !self.options.opacity ) { + return; + } // Cache the original opacity of draggable element to reset later originalOpacity = self.dragEl.css( 'opacity' ); @@ -707,6 +714,11 @@ if ( $.uiBackCompat !== false ) { }); this.element.on( "dragstop", function( event, ui ) { + + // No need to continue + if ( !self.options.opacity ) { + return; + } // Reset opacity self.dragEl.css( 'opacity', originalOpacity ); @@ -732,12 +744,12 @@ if ( $.uiBackCompat !== false ) { this._super(); - // No need to continue - if ( !this.options.revert ) { - return; - } - this.element.on( "dragbeforestart", function( event, ui ) { + + // No need to continue + if ( !self.options.revert ) { + return; + } // Cache the original css of draggable element to reset later originalLeft = self.dragEl.css( 'left' ); @@ -747,6 +759,11 @@ if ( $.uiBackCompat !== false ) { }); this.element.on( "dragstop", function( event, ui ) { + + // No need to continue + if ( !self.options.revert ) { + return; + } // Reset to before drag self.dragEl.animate({ @@ -774,12 +791,12 @@ if ( $.uiBackCompat !== false ) { this._super(); - // No need to continue - if ( !this.options.zIndex ) { - return; - } - this.element.on( "dragstart", function( event, ui ) { + + // No need to continue + if ( !self.options.zIndex ) { + return; + } // Cache the original zIndex of draggable element to reset later originalZIndex = self.dragEl.css( 'z-index' ); @@ -790,6 +807,11 @@ if ( $.uiBackCompat !== false ) { }); this.element.on( "dragstop", function( event, ui ) { + + // No need to continue + if ( !self.options.zIndex ) { + return; + } // Reset zIndex self.dragEl.css( 'z-index', originalZIndex ); From 50e2e91e855dbcdfd684d56cdff5755c0e0caf69 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Thu, 20 Dec 2012 16:52:26 -0500 Subject: [PATCH 129/190] Draggable: Added scoll, scrollSensitivity, scrollSpeed backCompat --- ui/jquery.ui.draggable.js | 126 ++++++++++++++++++++++++++++---------- 1 file changed, 93 insertions(+), 33 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 140c636e3b8..441e87bf77b 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -53,6 +53,9 @@ $.widget( "ui.draggable", $.ui.interaction, { _create: function() { this._super(); + this.scrollSensitivity = 20; + this.scrollSpeed = 5; + // Static position elements can't be moved with top/left if ( this.element.css( "position" ) === "static" ) { this.element.css( "position", "relative" ); @@ -249,13 +252,10 @@ $.widget( "ui.draggable", $.ui.interaction, { }, _handleScrolling: function( pointerPosition ) { - var scrollTop = this.scrollParent.scrollTop(), + var self = this, + scrollTop = this.scrollParent.scrollTop(), scrollLeft = this.scrollParent.scrollLeft(), - scrollSensitivity = 20, - baseSpeed = 5, - speed = function( distance ) { - return baseSpeed + Math.round( distance / 2 ); - }, + scrollSensitivity = this.scrollSensitivity, // overflowOffset is only set when scrollParent is not doc/html overflowLeft = this.overflowOffset ? this.overflowOffset.left : @@ -271,22 +271,26 @@ $.widget( "ui.draggable", $.ui.interaction, { // Handle vertical scrolling if ( yBottom < scrollSensitivity ) { this.scrollParent.scrollTop( scrollTop + - speed( scrollSensitivity - yBottom ) ); + this._speed( scrollSensitivity - yBottom ) ); } else if ( yTop < scrollSensitivity ) { this.scrollParent.scrollTop( scrollTop - - speed( scrollSensitivity - yTop ) ); + this._speed( scrollSensitivity - yTop ) ); } // Handle horizontal scrolling if ( xRight < scrollSensitivity ) { this.scrollParent.scrollLeft( scrollLeft + - speed( scrollSensitivity - xRight ) ); + this._speed( scrollSensitivity - xRight ) ); } else if ( xLeft < scrollSensitivity ) { this.scrollParent.scrollLeft( scrollLeft - - speed( scrollSensitivity - xLeft ) ); + this._speed( scrollSensitivity - xLeft ) ); } }, + _speed: function( distance ) { + return this.scrollSpeed + Math.round( distance / 2 ); + }, + // Uses event to determine new position of draggable, before any override from callbacks // TODO: handle absolute element inside relative parent like a relative element _preparePosition: function( pointerPosition ) { @@ -485,7 +489,7 @@ if ( $.uiBackCompat !== false ) { }, _create: function() { - + var self = this; this._super(); @@ -502,11 +506,11 @@ if ( $.uiBackCompat !== false ) { } }); - + } }); - + // cancel option $.widget( "ui.draggable", $.ui.draggable, { options: { @@ -514,24 +518,24 @@ if ( $.uiBackCompat !== false ) { }, _create: function() { - + this._super(); if ( this.options.cancel !== null ) { this.options.exclude = this.options.cancel; } - + }, - + _setOption: function( key, value ) { - + if ( key !== 'cancel' ) { return this._super( key, value ); } - + this._super( key, value ); - this.options.exclude = this.options.cancel; - + this.options.exclude = this.options.cancel; + } }); @@ -553,7 +557,7 @@ if ( $.uiBackCompat !== false ) { // Cache original cursor to set back this.element.on( "dragstart", function( event, ui ) { - + if ( self.options.cursor ) { startCursor = body[0].style.cursor; } @@ -594,10 +598,10 @@ if ( $.uiBackCompat !== false ) { this._super(); this.element.on( "dragbeforestart", function( event, ui ) { - + var elem = self.dragEl, cursorAt = self.options.cursorAt; - + // No need to continue if ( !cursorAt ) { return; @@ -629,13 +633,13 @@ if ( $.uiBackCompat !== false ) { _create: function() { - var self = this, + var self = this, currentX, currentY; this._super(); this.element.on( "dragbeforestart", function( event, ui ) { - + if ( !self.options.grid ) { return; } @@ -647,11 +651,11 @@ if ( $.uiBackCompat !== false ) { }); this.element.on( "drag", function( event, ui ) { - + if ( !self.options.grid ) { return; } - + // Save off the intended intervals var x = self.options.grid[0], y = self.options.grid[1]; @@ -699,7 +703,7 @@ if ( $.uiBackCompat !== false ) { this._super(); this.element.on( "dragstart", function( event, ui ) { - + // No need to continue if ( !self.options.opacity ) { return; @@ -714,7 +718,7 @@ if ( $.uiBackCompat !== false ) { }); this.element.on( "dragstop", function( event, ui ) { - + // No need to continue if ( !self.options.opacity ) { return; @@ -745,7 +749,7 @@ if ( $.uiBackCompat !== false ) { this._super(); this.element.on( "dragbeforestart", function( event, ui ) { - + // No need to continue if ( !self.options.revert ) { return; @@ -759,7 +763,7 @@ if ( $.uiBackCompat !== false ) { }); this.element.on( "dragstop", function( event, ui ) { - + // No need to continue if ( !self.options.revert ) { return; @@ -792,7 +796,7 @@ if ( $.uiBackCompat !== false ) { this._super(); this.element.on( "dragstart", function( event, ui ) { - + // No need to continue if ( !self.options.zIndex ) { return; @@ -807,7 +811,7 @@ if ( $.uiBackCompat !== false ) { }); this.element.on( "dragstop", function( event, ui ) { - + // No need to continue if ( !self.options.zIndex ) { return; @@ -822,4 +826,60 @@ if ( $.uiBackCompat !== false ) { }); + // TODO: need droppable working + // scope option + $.widget( "ui.draggable", $.ui.draggable, { + options: { + scope: "default" + } + }); + + // scroll + scrollSensitivity + scrollSpeedType option + $.widget( "ui.draggable", $.ui.draggable, { + options: { + scroll: true, + scrollSpeed: null, + scrollSensitivity: null + }, + _create : function() { + + var self = this, + handleScroll = this._handleScrolling, + speed = this._speed; + + this._super(); + + this._speed = function( distance ) { + + if ( self.options.scrollSpeed !== null ) { + + self.scrollSpeed = self.options.scrollSpeed; + + // Undo calculation that makes things go faster as distance increases + distance = 0; + } + + return speed.call( self, distance ); + + }; + + // Wrap member function to check for ability to scroll + this._handleScrolling = function( pointerPosition ) { + + if ( !self.options.scroll ) { + return; + } + + if ( self.options.scrollSensitivity !== null ) { + self.scrollSensitivity = self.options.scrollSensitivity; + } + + handleScroll.call( self, pointerPosition ); + + }; + + } + + }); + } \ No newline at end of file From 68f45613bd32d85cc55fbf77701f393799682bf2 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Thu, 20 Dec 2012 18:02:00 -0500 Subject: [PATCH 130/190] Draggable: Added stack backCompat --- ui/jquery.ui.draggable.js | 51 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 441e87bf77b..78fa189f7be 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -252,8 +252,7 @@ $.widget( "ui.draggable", $.ui.interaction, { }, _handleScrolling: function( pointerPosition ) { - var self = this, - scrollTop = this.scrollParent.scrollTop(), + var scrollTop = this.scrollParent.scrollTop(), scrollLeft = this.scrollParent.scrollLeft(), scrollSensitivity = this.scrollSensitivity, // overflowOffset is only set when scrollParent is not doc/html @@ -882,4 +881,52 @@ if ( $.uiBackCompat !== false ) { }); + // stack option + $.widget( "ui.draggable", $.ui.draggable, { + options: { + stack: false + }, + + _create: function() { + + var self = this; + + this._super(); + + this.element.on( "dragbeforestart", function( event, ui ) { + + var stack = self.options.stack, + group, min; + + if ( !self.options.stack ) { + return; + } + + group = $.makeArray( $(stack) ).sort(function(a,b) { + + var aZIndex = parseInt( $(a).css("zIndex"), 10 ), + bZIndex = parseInt( $(b).css("zIndex"), 10 ), + min; + + return ( aZIndex || 0) - ( bZIndex|| 0); + }); + + if (!group.length) { + return; + } + + min = parseInt(group[0].style.zIndex, 10) || 0; + + $(group).each(function(i) { + this.style.zIndex = min + i; + }); + + self.element[0].style.zIndex = min + group.length; + + }); + + } + + }); + } \ No newline at end of file From ddcb7695e3dd039f9254b483f0b24112ec4d4222 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Thu, 20 Dec 2012 18:04:32 -0500 Subject: [PATCH 131/190] Draggable Unit: Modified to actually reflect new API options --- tests/unit/draggable/draggable_common.js | 31 ++++++++++++------------ 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/tests/unit/draggable/draggable_common.js b/tests/unit/draggable/draggable_common.js index 9c59ef14f49..6bed7399593 100644 --- a/tests/unit/draggable/draggable_common.js +++ b/tests/unit/draggable/draggable_common.js @@ -14,34 +14,33 @@ TestHelpers.commonWidgetTests( "draggable", { cursor: "auto", cursorAt: false, grid: false, - iframeFix: false, opacity: false, refreshPositions: false, revert: false, revertDuration: 500, scroll: true, - scrollSensitivity: 20, - scrollSpeed: 20, + scrollSensitivity: null, + scrollSpeed: null, scope: "default", snap: false, snapMode: "both", snapTolerance: 20, stack: false, zIndex: false, - cancel: "input,textarea,button,select,option", + cancel: null, - // methods - destroy: null, - disable: null, - enable: null, - option: null, - widget: null, + // // methods + // destroy: null, + // disable: null, + // enable: null, + // option: null, + // widget: null, - // callbacks - beforeStart: null, - create: null, - drag: null, - start: null, - stop: null + // // callbacks + // beforeStart: null, + // create: null, + // drag: null, + // start: null, + // stop: null } }); From 15e3f28c4f7196c929f1772954896d12121b7700 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Fri, 21 Dec 2012 11:33:13 -0500 Subject: [PATCH 132/190] Grunt: Ran and fixed jshint errors --- tests/unit/draggable/draggable_common.js | 2 +- ui/jquery.ui.draggable.js | 23 ++++--- ui/jquery.ui.droppable.js | 4 +- ui/jquery.ui.interaction.js | 5 +- ui/jquery.ui.sortable.js | 84 +++++++++++------------- 5 files changed, 56 insertions(+), 62 deletions(-) diff --git a/tests/unit/draggable/draggable_common.js b/tests/unit/draggable/draggable_common.js index 6bed7399593..0a406f76801 100644 --- a/tests/unit/draggable/draggable_common.js +++ b/tests/unit/draggable/draggable_common.js @@ -27,7 +27,7 @@ TestHelpers.commonWidgetTests( "draggable", { snapTolerance: 20, stack: false, zIndex: false, - cancel: null, + cancel: null // // methods // destroy: null, diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 78fa189f7be..5d9f5abdbf8 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -555,7 +555,7 @@ if ( $.uiBackCompat !== false ) { body = $( this.document[0].body ); // Cache original cursor to set back - this.element.on( "dragstart", function( event, ui ) { + this.element.on( "dragstart", function() { if ( self.options.cursor ) { startCursor = body[0].style.cursor; @@ -564,14 +564,14 @@ if ( $.uiBackCompat !== false ) { }); // Set cursor to what user wants during drag - this.element.on( "drag", function( event, ui ) { + this.element.on( "drag", function() { if ( self.options.cursor ) { body.css( "cursor", self.options.cursor ); } }); // Set back cursor to whatever default was - this.element.on( "dragstop", function( event, ui ) { + this.element.on( "dragstop", function() { if ( self.options.cursor ) { body.css( "cursor", startCursor ); @@ -701,7 +701,7 @@ if ( $.uiBackCompat !== false ) { this._super(); - this.element.on( "dragstart", function( event, ui ) { + this.element.on( "dragstart", function() { // No need to continue if ( !self.options.opacity ) { @@ -716,7 +716,7 @@ if ( $.uiBackCompat !== false ) { }); - this.element.on( "dragstop", function( event, ui ) { + this.element.on( "dragstop", function() { // No need to continue if ( !self.options.opacity ) { @@ -747,7 +747,7 @@ if ( $.uiBackCompat !== false ) { this._super(); - this.element.on( "dragbeforestart", function( event, ui ) { + this.element.on( "dragbeforestart", function() { // No need to continue if ( !self.options.revert ) { @@ -761,7 +761,7 @@ if ( $.uiBackCompat !== false ) { }); - this.element.on( "dragstop", function( event, ui ) { + this.element.on( "dragstop", function() { // No need to continue if ( !self.options.revert ) { @@ -794,7 +794,7 @@ if ( $.uiBackCompat !== false ) { this._super(); - this.element.on( "dragstart", function( event, ui ) { + this.element.on( "dragstart", function() { // No need to continue if ( !self.options.zIndex ) { @@ -809,7 +809,7 @@ if ( $.uiBackCompat !== false ) { }); - this.element.on( "dragstop", function( event, ui ) { + this.element.on( "dragstop", function() { // No need to continue if ( !self.options.zIndex ) { @@ -893,7 +893,7 @@ if ( $.uiBackCompat !== false ) { this._super(); - this.element.on( "dragbeforestart", function( event, ui ) { + this.element.on( "dragbeforestart", function() { var stack = self.options.stack, group, min; @@ -905,8 +905,7 @@ if ( $.uiBackCompat !== false ) { group = $.makeArray( $(stack) ).sort(function(a,b) { var aZIndex = parseInt( $(a).css("zIndex"), 10 ), - bZIndex = parseInt( $(b).css("zIndex"), 10 ), - min; + bZIndex = parseInt( $(b).css("zIndex"), 10 ); return ( aZIndex || 0) - ( bZIndex|| 0); }); diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index 097c63cf91b..efb326d3832 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -63,7 +63,7 @@ $.widget( "ui.droppable", { /** internal **/ - _start: function( event, ui ) { + _start: function( event ) { if ( this.options.accept && !$( event.target ).is( this.options.accept ) ) { return false; } @@ -93,7 +93,7 @@ $.widget( "ui.droppable", { } }, - _stop: function( event, ui ) { + _stop: function( event ) { if ( this.over ) { this._trigger( "drop", event, this._uiHash() ); } diff --git a/ui/jquery.ui.interaction.js b/ui/jquery.ui.interaction.js index 3321e7978a0..eacb80e4d37 100644 --- a/ui/jquery.ui.interaction.js +++ b/ui/jquery.ui.interaction.js @@ -35,7 +35,7 @@ $.widget( "ui.interaction", { /** protected **/ - _isValidTarget: function( target ) { + _isValidTarget: function() { return true; }, @@ -138,8 +138,7 @@ interaction.hooks.mouse = { // WebKit doesn't support TouchList.identifiedTouch() function getTouch( event ) { - var touch, - touches = event.originalEvent.changedTouches, + var touches = event.originalEvent.changedTouches, i = 0, length = touches.length; for ( ; i < length; i++ ) { diff --git a/ui/jquery.ui.sortable.js b/ui/jquery.ui.sortable.js index b3888b7efd7..e6ac81071c4 100644 --- a/ui/jquery.ui.sortable.js +++ b/ui/jquery.ui.sortable.js @@ -29,7 +29,7 @@ $.widget( "ui.sortable", $.ui.interaction, { version: "@VERSION", widgetEventPrefix: "sort", items: 'li', // TODO: move to options when API is ready - + // dragEl: element being dragged (original or helper) // position: final CSS position of dragEl // offset: offset of dragEl @@ -49,56 +49,54 @@ $.widget( "ui.sortable", $.ui.interaction, { }, _create: function() { - + this._super(); this.element.addClass( "ui-sortable" ); - + this._setSortablePositions(); - + }, - + _setSortablePositions: function() { - + var sortablePositions = this.sortablePositions = []; - + this.element.find( this.items ).each( function() { - + var el = $(this); - + sortablePositions.push([{ el: el, offset: el.offset() }]); }); - - }, + + }, /** interaction interface **/ - + _isValidTarget: function( element ) { - + // TODO: options for what is actually valid return element.is( this.items ); }, _start: function( event, pointerPosition ) { - - var offset; // The actual dragging element, should always be a jQuery object // this.dragEl = this.options.helper ? // this._createHelper( pointerPosition ) : // this.element; - + this.dragEl = $(event.target); - + // Save original css position if there are currently styles // Otherwise the original css will be set back by removing attribute if ( this.dragEl[0].style.position ) { this.originalCssPosition = this.dragEl[0].style.position; } - + // Create placeholder for while element is dragging // TODO: what do we do about IDs? // TODO: possibly use CSS for visibility portion @@ -108,7 +106,7 @@ $.widget( "ui.sortable", $.ui.interaction, { }); this.dragEl.after( this.placeholder ); - + this.dragEl.css( 'position', 'absolute' ); // // _createHelper() ensures that helpers are in the correct position @@ -154,7 +152,7 @@ $.widget( "ui.sortable", $.ui.interaction, { if ( this._trigger( "beforeStart", event, this._originalHash( pointerPosition ) ) === false ) { return false; - + } this._setCss(); @@ -164,13 +162,13 @@ $.widget( "ui.sortable", $.ui.interaction, { this._trigger( "start", event, this._fullHash( pointerPosition ) ); this._blockFrames(); }, - + _move: function( event, pointerPosition ) { - - var sort, sortItem, top, left, sortIndex, + + var sort, sortItem, sortIndex, len = this.sortablePositions.length; - - + + this._preparePosition( pointerPosition ); // // If user cancels drag, don't move the element @@ -182,23 +180,23 @@ $.widget( "ui.sortable", $.ui.interaction, { // Scroll the scrollParent, if needed this._handleScrolling( pointerPosition ); - + for ( sortIndex=0; sortIndex ( sortItem.offset.top + sortItem.el.height()/2 ) ) { - + sortItem.el.after( this.dragEl ); this.dragEl.after( this.placeholder ); this._setSortablePositions(); @@ -208,18 +206,18 @@ $.widget( "ui.sortable", $.ui.interaction, { this.dragEl.before( this.placeholder ); this._setSortablePositions(); } - + } - - + + } } - + }, - + // TODO: swap out for real tolerance options _over: function( sortItem ) { - + // TODO: use same cache from _move for height and width of element var edges = { droppableRight: sortItem.offset.left + sortItem.el.width(), @@ -227,17 +225,15 @@ $.widget( "ui.sortable", $.ui.interaction, { draggableRight: this.offset.left + this.dragEl.width(), draggableBottom: this.offset.top + this.dragEl.height() }; - + return sortItem.offset.left < edges.draggableRight && edges.droppableRight > this.offset.left && sortItem.offset.top < edges.draggableBottom && edges.droppableBottom > sortItem.offset.top; - + }, _stop: function( event, pointerPosition ) { - - var parent, next; this._preparePosition( pointerPosition ); @@ -257,11 +253,11 @@ $.widget( "ui.sortable", $.ui.interaction, { else { this.dragEl.css( 'position', '' ); } - + // TODO: should same thing be done here as is done for position or is there better way altogether this.dragEl.css( 'left', '' ); this.dragEl.css( 'top', '' ); - + this.placeholder.remove(); // Unset properties only needed during draggin/sorting From 86dcc5ea8ff2f4f1c4b16e8c310b8b4478bde139 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Fri, 21 Dec 2012 12:01:23 -0500 Subject: [PATCH 133/190] Draggable: Got the easier failing unit tests corrected --- tests/unit/draggable/draggable_options.js | 7 +-- ui/jquery.ui.draggable.js | 65 +++++++++++++++++++++-- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index 172e864be98..ebac2c4e709 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -106,13 +106,10 @@ test("{ cancel: ? }, unexpected", function() { "{}": {}, "[]": [], "null": null, - "undefined": undefined, - "function() {return '';}": function() {return '';}, - "function() {return true;}": function() {return true;}, - "function() {return false;}": function() {return false;} + "undefined": undefined }; - expect( 9 ); + expect( 6 ); $.each(unexpected, function(key, val) { el = $("#draggable2").draggable({ cancel: val }); diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 5d9f5abdbf8..9615206a1d0 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -77,7 +77,7 @@ $.widget( "ui.draggable", $.ui.interaction, { var offset; // The actual dragging element, should always be a jQuery object - this.dragEl = this.options.helper ? + this.dragEl = ( this.options.helper === true || typeof this.options.helper === 'function' ) ? this._createHelper( pointerPosition ) : this.element; @@ -90,7 +90,7 @@ $.widget( "ui.draggable", $.ui.interaction, { }; offset = this.dragEl.offset(); this.dragEl - .appendTo( this.options.appendTo ) + .appendTo( this._appendToEl() ) .offset( offset ); } @@ -208,7 +208,7 @@ $.widget( "ui.draggable", $.ui.interaction, { // Ensure the helper is in the DOM; obey the appendTo option if it exists if ( this.options.appendTo || !helper.closest( "body" ).length ) { - helper.appendTo( this.options.appendTo || this.document[0].body ); + helper.appendTo( this._appendToEl() || this.document[0].body ); } return helper @@ -220,6 +220,11 @@ $.widget( "ui.draggable", $.ui.interaction, { }); }, + // TODO: Remove after 2.0, only used for backCompat + _appendToEl: function() { + return this.options.appendTo; + }, + _getPosition: function() { var left, top, position, scrollTop = this.scrollParent.scrollTop(), @@ -481,6 +486,60 @@ $.widget( "ui.draggable", $.ui.draggable, { // DEPRECATED if ( $.uiBackCompat !== false ) { + // appendTo 'parent' value + $.widget( "ui.draggable", $.ui.draggable, { + + _appendToEl: function() { + + var el = this.options.appendTo; + + if ( el === 'parent' ) { + el = this.dragEl.parent(); + } + + return el; + + } + + }); + + // helper 'original' or 'clone' value + $.widget( "ui.draggable", $.ui.draggable, { + + _create: function() { + + this._super(); + + if ( this.options.helper === 'original' ) { + this.options.helper = false; + } + + if ( this.options.helper === 'clone' ) { + this.options.helper = true; + } + + }, + + _setOption: function( key, value ) { + + if ( key !== 'helper' ) { + return this._super( key, value ); + } + + if ( value === 'clone' ) { + value = true; + } + + if ( value === 'original' ) { + value = false; + } + + this._super( key, value ); + + } + + }); + // axis option $.widget( "ui.draggable", $.ui.draggable, { options: { From 66bd7da551c7ea8c182965c0ac4cb6715be6f856 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Fri, 21 Dec 2012 17:26:10 -0500 Subject: [PATCH 134/190] Draggable: Fixed cursor backCompat timing --- ui/jquery.ui.draggable.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 9615206a1d0..bee2c80f929 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -614,19 +614,13 @@ if ( $.uiBackCompat !== false ) { body = $( this.document[0].body ); // Cache original cursor to set back - this.element.on( "dragstart", function() { + this.element.on( "dragbeforestart", function() { if ( self.options.cursor ) { startCursor = body[0].style.cursor; - } - - }); - - // Set cursor to what user wants during drag - this.element.on( "drag", function() { - if ( self.options.cursor ) { body.css( "cursor", self.options.cursor ); } + }); // Set back cursor to whatever default was From bc5bbd07637e77ee63a93edb73ac788acb994566 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Fri, 21 Dec 2012 17:40:47 -0500 Subject: [PATCH 135/190] Draggable: Added in ability to stop events from "start" as well as "beforeStart" --- ui/jquery.ui.draggable.js | 43 +++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index bee2c80f929..f002797ec9b 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -74,7 +74,7 @@ $.widget( "ui.draggable", $.ui.interaction, { }, _start: function( event, pointerPosition ) { - var offset; + var offset, startCssLeft, startCssTop, startPosition, startOffset; // The actual dragging element, should always be a jQuery object this.dragEl = ( this.options.helper === true || typeof this.options.helper === 'function' ) ? @@ -131,11 +131,32 @@ $.widget( "ui.draggable", $.ui.interaction, { } + // Save off the usual properties locally, so they can be reverted from start + startCssLeft = this.dragEl.css("left"); + startCssTop = this.dragEl.css("top"); + startPosition = copy( this._getPosition() ); + startOffset = copy( this.offset ); + this._setCss(); this.startPosition = this._getPosition(); this.startOffset = this.dragEl.offset(); - this._trigger( "start", event, this._fullHash( pointerPosition ) ); + // If user cancels on start, don't allow dragging + if ( this._trigger( "start", event, + this._fullHash( pointerPosition ) ) === false ) { + // domPosition needs to be undone even if start is stopped + // Otherwise this.dragEl will remain in the element appendTo is set to + + this.startPosition = startPosition; + this.startOffset = startOffset; + this.dragEl.css({ + left: startCssLeft, + top: startCssTop + }); + + this._resetDomPosition(); + return false; + } this._blockFrames(); }, @@ -163,7 +184,7 @@ $.widget( "ui.draggable", $.ui.interaction, { // If user cancels drag, don't move the element if ( this._trigger( "drag", event, this._fullHash( pointerPosition ) ) === false ) { - return; + return false; } this._setCss(); @@ -490,26 +511,26 @@ if ( $.uiBackCompat !== false ) { $.widget( "ui.draggable", $.ui.draggable, { _appendToEl: function() { - + var el = this.options.appendTo; - + if ( el === 'parent' ) { el = this.dragEl.parent(); } - + return el; - + } }); - + // helper 'original' or 'clone' value $.widget( "ui.draggable", $.ui.draggable, { _create: function() { this._super(); - + if ( this.options.helper === 'original' ) { this.options.helper = false; } @@ -525,11 +546,11 @@ if ( $.uiBackCompat !== false ) { if ( key !== 'helper' ) { return this._super( key, value ); } - + if ( value === 'clone' ) { value = true; } - + if ( value === 'original' ) { value = false; } From 1e58ab22ff2cffe587303ac08cd93ac9f48750a5 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Fri, 21 Dec 2012 17:53:40 -0500 Subject: [PATCH 136/190] Draggable: Added helper to the draggable data while it exists --- ui/jquery.ui.draggable.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index f002797ec9b..5e5c2c9d491 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -199,6 +199,7 @@ $.widget( "ui.draggable", $.ui.interaction, { // If user cancels stop, leave helper there if ( this._trigger( "stop", event, this._fullHash( pointerPosition ) ) !== false ) { if ( this.options.helper ) { + delete this.element.data( 'draggable' ).helper; this.dragEl.remove(); } this._resetDomPosition(); @@ -231,6 +232,8 @@ $.widget( "ui.draggable", $.ui.interaction, { if ( this.options.appendTo || !helper.closest( "body" ).length ) { helper.appendTo( this._appendToEl() || this.document[0].body ); } + + this.element.data( 'draggable' ).helper = helper; return helper // Helper must be absolute to function properly From 158bef12239679ee5f00d35a7b60e625b6ec6528 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sat, 22 Dec 2012 16:57:51 -0500 Subject: [PATCH 137/190] Draggable: Added snap/snapMode/snapTolerance via old code plus a little crying on the inside --- ui/jquery.ui.draggable.js | 246 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 239 insertions(+), 7 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 5e5c2c9d491..3493c0c77f0 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -49,6 +49,7 @@ $.widget( "ui.draggable", $.ui.interaction, { // overflow: object containing width and height keys of scroll parent // domPosition: object containing original parent and index when using // appendTo option without a helper + // dragDimensions: saved off width and height used for various options _create: function() { this._super(); @@ -76,6 +77,9 @@ $.widget( "ui.draggable", $.ui.interaction, { _start: function( event, pointerPosition ) { var offset, startCssLeft, startCssTop, startPosition, startOffset; + // Reset + this.dragDimensions = null; + // The actual dragging element, should always be a jQuery object this.dragEl = ( this.options.helper === true || typeof this.options.helper === 'function' ) ? this._createHelper( pointerPosition ) : @@ -102,6 +106,11 @@ $.widget( "ui.draggable", $.ui.interaction, { this.originalOffset = this.startOffset = this.dragEl.offset(); this.originalPointer = pointerPosition; + // If not already cached within _createHelper + if ( !this.dragDimensions ) { + this._cacheDragDimensions( this.dragEl ); + } + // Cache current position and offset this.position = copy( this.startPosition ); this.offset = copy( this.startOffset ); @@ -232,18 +241,27 @@ $.widget( "ui.draggable", $.ui.interaction, { if ( this.options.appendTo || !helper.closest( "body" ).length ) { helper.appendTo( this._appendToEl() || this.document[0].body ); } - + this.element.data( 'draggable' ).helper = helper; + this._cacheDragDimensions( helper ); + return helper // Helper must be absolute to function properly .css( "position", "absolute" ) .offset({ - left: pointerPosition.x - helper.outerWidth() * xPos, - top: pointerPosition.y - helper.outerHeight() * yPos + left: pointerPosition.x - this.dragDimensions.width * xPos, + top: pointerPosition.y - this.dragDimensions.height * yPos }); }, + _cacheDragDimensions: function( el) { + this.dragDimensions = { + width: el.outerWidth(), + height: el.outerHeight() + }; + }, + // TODO: Remove after 2.0, only used for backCompat _appendToEl: function() { return this.options.appendTo; @@ -463,8 +481,8 @@ $.widget( "ui.draggable", $.ui.draggable, { bottom: top + container.height(), leftDiff: ui.originalOffset.left - ui.originalPosition.left, topDiff: ui.originalOffset.top - ui.originalPosition.top, - width: this.dragEl.outerWidth(), - height: this.dragEl.outerHeight() + width: this.dragDimensions.width, + height: this.dragDimensions.height }; }, @@ -690,10 +708,10 @@ if ( $.uiBackCompat !== false ) { ui.position.left += ui.pointer.x - ui.offset.left - cursorAt.left; } if ( "bottom" in cursorAt ) { - ui.position.top += ui.pointer.y - ui.offset.top - elem.outerHeight() + cursorAt.bottom; + ui.position.top += ui.pointer.y - ui.offset.top - self.dragDimensions.height + cursorAt.bottom; } if ( "right" in cursorAt ) { - ui.position.left += ui.pointer.x - ui.offset.left - elem.outerWidth() + cursorAt.right; + ui.position.left += ui.pointer.x - ui.offset.left - self.dragDimensions.width + cursorAt.right; } }); @@ -1005,4 +1023,218 @@ if ( $.uiBackCompat !== false ) { }); + // snap snapMode snapTolerance options + // mainly copy-pasted from 1.9 since the code is so "insane" didn't want to reverse-engineer into sanity + $.widget( "ui.draggable", $.ui.draggable, { + options: { + snap: false, + snapMode: 'both', + snapTolerance: 20 + }, + + _create: function() { + + var inst = this, + snapElements; + + this._super(); + + this.element.on( 'dragstart', function() { + + // Nothing to do + if ( !inst.options.snap ) { + return; + } + + // Reset snapElements on every start in case there have been changes + snapElements = []; + + // Select either all draggable elements, or the selector that was passed in + $( inst.options.snap === true ? ':data(ui-draggable)' : inst.options.snap ).each(function() { + + var el = $(this), + offset = el.offset(); + + // Don't add this draggable to list of elements for snapping + if( this === inst.element[0] ) { + return; + } + + // Save off elements dimensions for later + snapElements.push({ + item: this, + width: el.outerWidth(), + height: el.outerHeight(), + top: offset.top, + left: offset.left + }); + + }); + + inst.margins = { + left: (parseInt(inst.element.css("marginLeft"),10) || 0), + top: (parseInt(inst.element.css("marginTop"),10) || 0), + right: (parseInt(inst.element.css("marginRight"),10) || 0), + bottom: (parseInt(inst.element.css("marginBottom"),10) || 0) + }; + + }); + + this.element.on( 'drag', function( event, ui ) { + + // Nothing to do + if ( !inst.options.snap ) { + return; + } + + var ts, bs, ls, rs, l, r, t, b, i, first, + o = inst.options, + d = o.snapTolerance, + x1 = ui.offset.left, x2 = x1 + inst.dragDimensions.width, + y1 = ui.offset.top, y2 = y1 + inst.dragDimensions.height; + + for (i = snapElements.length - 1; i >= 0; i--){ + + l = snapElements[i].left; + r = l + snapElements[i].width; + t = snapElements[i].top; + b = t + 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(snapElements[i].snapping) { + (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: snapElements[i].item }))); + } + snapElements[i].snapping = false; + continue; + } + + if(o.snapMode !== 'inner') { + ts = Math.abs(t - y2) <= d; + bs = Math.abs(b - y1) <= d; + ls = Math.abs(l - x2) <= d; + rs = Math.abs(r - x1) <= d; + if(ts) { + ui.position.top = inst._convertPositionTo("relative", { top: t - inst.dragDimensions.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.dragDimensions.width }).left - inst.margins.left; + } + if(rs) { + ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; + } + } + + first = (ts || bs || ls || rs); + + if(o.snapMode !== 'outer') { + ts = Math.abs(t - y1) <= d; + bs = Math.abs(b - y2) <= d; + ls = Math.abs(l - x1) <= d; + 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.dragDimensions.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.dragDimensions.width }).left - inst.margins.left; + } + } + + if(!snapElements[i].snapping && (ts || bs || ls || rs || first)) { + (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: snapElements[i].item }))); + } + snapElements[i].snapping = (ts || bs || ls || rs || first); + + } + }); + + + }, + + _convertPositionTo: function(d, pos) { + + if(!pos) { + pos = this.position; + } + + var mod = d === "absolute" ? 1 : -1, + offset = {}, + 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); + + $.extend(offset, { + parent: this._getParentOffset(), + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); + + return { + top: ( + pos.top + // The absolute mouse position + offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent + offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) + ( ( this.cssPosition === 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left + // The absolute mouse position + offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent + offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) + ( ( this.cssPosition === 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _getParentOffset: function() { + + //Get the offsetParent and cache its position + this.offsetParent = this.dragEl.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 + //Ugly IE fix + if((this.offsetParent[0] === document.body) || + (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === 'html' && $.ui.ie)) { + 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.dragEl.css("top"),10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.dragEl.css("left"),10) || 0) + this.scrollParent.scrollLeft() + }; + } + + return { top: 0, left: 0 }; + + } + + }); + } \ No newline at end of file From 1c00423538adbd9784c1e4e6392b731f17d85709 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sat, 22 Dec 2012 17:03:53 -0500 Subject: [PATCH 138/190] Draggable: Added refreshPositions backCompat + linted --- ui/jquery.ui.draggable.js | 41 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 3493c0c77f0..8a82f5b1943 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -693,8 +693,7 @@ if ( $.uiBackCompat !== false ) { this.element.on( "dragbeforestart", function( event, ui ) { - var elem = self.dragEl, - cursorAt = self.options.cursorAt; + var cursorAt = self.options.cursorAt; // No need to continue if ( !cursorAt ) { @@ -1167,7 +1166,7 @@ if ( $.uiBackCompat !== false ) { } var mod = d === "absolute" ? 1 : -1, - offset = {}, + offset = {}, 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); $.extend(offset, { @@ -1237,4 +1236,40 @@ if ( $.uiBackCompat !== false ) { }); + // refreshPositions option + $.widget( "ui.draggable", $.ui.draggable, { + options: { + refreshPositions: false + }, + + _create: function() { + + var self = this, + drops; + + this._super(); + + this.element.on( "dragstart", function() { + drops = $(':data(ui-sortable)'); + }); + + // On drag, make sure top does not change so axis is locked + this.element.on( "drag", function() { + + if ( self.options.refreshPositions !== true ) { + return; + } + + drops.each( function() { + $(this).sortable('refreshPositions'); + }); + + + }); + + } + + }); + + } \ No newline at end of file From c8d7e4c592aade6232f4abcd1e4f3c4ea8e66335 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sun, 23 Dec 2012 12:42:50 -0500 Subject: [PATCH 139/190] Draggable: Some fixes for updated unit tests --- ui/jquery.ui.draggable.js | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 8a82f5b1943..b404325a406 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -208,7 +208,7 @@ $.widget( "ui.draggable", $.ui.interaction, { // If user cancels stop, leave helper there if ( this._trigger( "stop", event, this._fullHash( pointerPosition ) ) !== false ) { if ( this.options.helper ) { - delete this.element.data( 'draggable' ).helper; + delete this.element.data( 'uiDraggable' ).helper; this.dragEl.remove(); } this._resetDomPosition(); @@ -242,7 +242,7 @@ $.widget( "ui.draggable", $.ui.interaction, { helper.appendTo( this._appendToEl() || this.document[0].body ); } - this.element.data( 'draggable' ).helper = helper; + this.element.data( 'uiDraggable' ).helper = helper; this._cacheDragDimensions( helper ); @@ -388,6 +388,7 @@ $.widget( "ui.draggable", $.ui.interaction, { }, _originalHash: function( pointerPosition ) { + var ret = { position: this.position, offset: copy( this.offset ), @@ -545,10 +546,13 @@ if ( $.uiBackCompat !== false ) { }); - // helper 'original' or 'clone' value + // helper 'original' or 'clone' value + helper return value $.widget( "ui.draggable", $.ui.draggable, { _create: function() { + + var self = this, + orig = this._originalHash; this._super(); @@ -559,6 +563,18 @@ if ( $.uiBackCompat !== false ) { if ( this.options.helper === 'clone' ) { this.options.helper = true; } + + this._originalHash = function() { + + var ret = orig.apply( self, arguments ); + + if ( !ret.helper ) { + ret.helper = self.element; + } + + return ret; + + }; }, From 914d74c998445862e955fe69f239be4bac68de2e Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sun, 23 Dec 2012 12:50:05 -0500 Subject: [PATCH 140/190] Draggable Unit: Removed tests against undocumentated functionality --- tests/unit/draggable/draggable_options.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index be53284367d..63bdb819ea7 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -260,13 +260,13 @@ test("{ cursorAt: false}, default", function() { */ test( "{ cursorAt: left, top }", function() { - expect( 16 ); + expect( 12 ); var deltaX = -3, deltaY = -3, tests = { "{ left: -5, top: -5 }": { x: -5, y: -5, cursorAt : { left: -5, top: -5 } }, - "[ 10, 20 ]": { x: 10, y: 20, cursorAt : [ 10, 20 ] }, + // "[ 10, 20 ]": { x: 10, y: 20, cursorAt : [ 10, 20 ] }, "{ left: 20, top: 40 }": { x: 20, y: 40, cursorAt : { left: 20, top: 40 } }, "{ right: 10, bottom: 20 }": { x: 10, y: 20, cursorAt : { right: 10, bottom: 20 } } }; From 64841031757469eea854e37b15bc0eba6d3b2a7f Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Sun, 23 Dec 2012 12:51:17 -0500 Subject: [PATCH 141/190] Draggable: Deleted line rather than commenting it out. --- tests/unit/draggable/draggable_options.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index 63bdb819ea7..7ad9ef1e8f8 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -266,7 +266,6 @@ test( "{ cursorAt: left, top }", function() { deltaY = -3, tests = { "{ left: -5, top: -5 }": { x: -5, y: -5, cursorAt : { left: -5, top: -5 } }, - // "[ 10, 20 ]": { x: 10, y: 20, cursorAt : [ 10, 20 ] }, "{ left: 20, top: 40 }": { x: 20, y: 40, cursorAt : { left: 20, top: 40 } }, "{ right: 10, bottom: 20 }": { x: 10, y: 20, cursorAt : { right: 10, bottom: 20 } } }; From abb847191e5fbd0396f0d83d8ec45152c741cb82 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Tue, 1 Jan 2013 21:59:18 -0500 Subject: [PATCH 142/190] Fix common tests, and add back in undocumented, but necessary array position format --- tests/unit/draggable/draggable_common.js | 13 +++---------- tests/unit/draggable/draggable_options.js | 1 + 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/tests/unit/draggable/draggable_common.js b/tests/unit/draggable/draggable_common.js index 0a406f76801..c2b6ee96e0c 100644 --- a/tests/unit/draggable/draggable_common.js +++ b/tests/unit/draggable/draggable_common.js @@ -27,18 +27,11 @@ TestHelpers.commonWidgetTests( "draggable", { snapTolerance: 20, stack: false, zIndex: false, - cancel: null + cancel: null, - // // methods - // destroy: null, - // disable: null, - // enable: null, - // option: null, - // widget: null, - - // // callbacks + // callbacks // beforeStart: null, - // create: null, + create: null // drag: null, // start: null, // stop: null diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index 7ad9ef1e8f8..ce7860c4580 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -266,6 +266,7 @@ test( "{ cursorAt: left, top }", function() { deltaY = -3, tests = { "{ left: -5, top: -5 }": { x: -5, y: -5, cursorAt : { left: -5, top: -5 } }, + "[ 10, 20 ]": { x: 10, y: 20, cursorAt : [ 10, 20 ] }, "{ left: 20, top: 40 }": { x: 20, y: 40, cursorAt : { left: 20, top: 40 } }, "{ right: 10, bottom: 20 }": { x: 10, y: 20, cursorAt : { right: 10, bottom: 20 } } }; From ac2c7fd2563ccbafba77416d51104fa8a5ee9914 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Tue, 1 Jan 2013 22:15:03 -0500 Subject: [PATCH 143/190] support array and string position notation for cursorAt --- tests/unit/draggable/draggable_options.js | 3 +- ui/jquery.ui.draggable.js | 36 +++++++++++++++-------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index ce7860c4580..59f42523608 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -260,13 +260,14 @@ test("{ cursorAt: false}, default", function() { */ test( "{ cursorAt: left, top }", function() { - expect( 12 ); + expect( 20 ); var deltaX = -3, deltaY = -3, tests = { "{ left: -5, top: -5 }": { x: -5, y: -5, cursorAt : { left: -5, top: -5 } }, "[ 10, 20 ]": { x: 10, y: 20, cursorAt : [ 10, 20 ] }, + "'10 20'": { x: 10, y: 20, cursorAt : "10 20" }, "{ left: 20, top: 40 }": { x: 20, y: 40, cursorAt : { left: 20, top: 40 } }, "{ right: 10, bottom: 20 }": { x: 10, y: 20, cursorAt : { right: 10, bottom: 20 } } }; diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index b404325a406..fb3ee7ccc29 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -388,7 +388,7 @@ $.widget( "ui.draggable", $.ui.interaction, { }, _originalHash: function( pointerPosition ) { - + var ret = { position: this.position, offset: copy( this.offset ), @@ -550,7 +550,7 @@ if ( $.uiBackCompat !== false ) { $.widget( "ui.draggable", $.ui.draggable, { _create: function() { - + var self = this, orig = this._originalHash; @@ -563,17 +563,17 @@ if ( $.uiBackCompat !== false ) { if ( this.options.helper === 'clone' ) { this.options.helper = true; } - + this._originalHash = function() { - + var ret = orig.apply( self, arguments ); - + if ( !ret.helper ) { ret.helper = self.element; } - + return ret; - + }; }, @@ -716,6 +716,18 @@ if ( $.uiBackCompat !== false ) { return; } + // support array and string position notation + // TODO: Remove after 2.0, only used for backCompat + if ( typeof cursorAt === "string" ) { + cursorAt = cursorAt.split(" "); + } + if ( $.isArray( cursorAt ) ) { + cursorAt = { + left: +cursorAt[ 0 ], + top: +cursorAt[ 1 ] || 0 + }; + } + if ( "top" in cursorAt ) { ui.position.top += ui.pointer.y - ui.offset.top - cursorAt.top; } @@ -1085,7 +1097,7 @@ if ( $.uiBackCompat !== false ) { }); }); - + inst.margins = { left: (parseInt(inst.element.css("marginLeft"),10) || 0), top: (parseInt(inst.element.css("marginTop"),10) || 0), @@ -1096,7 +1108,7 @@ if ( $.uiBackCompat !== false ) { }); this.element.on( 'drag', function( event, ui ) { - + // Nothing to do if ( !inst.options.snap ) { return; @@ -1264,7 +1276,7 @@ if ( $.uiBackCompat !== false ) { drops; this._super(); - + this.element.on( "dragstart", function() { drops = $(':data(ui-sortable)'); }); @@ -1279,7 +1291,7 @@ if ( $.uiBackCompat !== false ) { drops.each( function() { $(this).sortable('refreshPositions'); }); - + }); @@ -1287,5 +1299,5 @@ if ( $.uiBackCompat !== false ) { }); - + } \ No newline at end of file From 4e79d15c2bf5d635d0cba007f470fd889439d52c Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Wed, 2 Jan 2013 14:05:57 -0500 Subject: [PATCH 144/190] Draggable Demo: Fix htmllint failures --- demos/draggable/map.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/draggable/map.html b/demos/draggable/map.html index e57ea24dbe7..038b08ccb38 100644 --- a/demos/draggable/map.html +++ b/demos/draggable/map.html @@ -63,7 +63,7 @@
    - + Map of Vienna
    From 7ad8f54a5a056e742d7a7bab38f1a444cc2f72de Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 7 Jan 2013 11:22:24 -0500 Subject: [PATCH 145/190] Draggable: Removed test for "drag callback shuold happen exactly once" --- tests/unit/draggable/draggable_events.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/unit/draggable/draggable_events.js b/tests/unit/draggable/draggable_events.js index f4ab3a8ea9c..3e6fca56eb4 100644 --- a/tests/unit/draggable/draggable_events.js +++ b/tests/unit/draggable/draggable_events.js @@ -55,7 +55,7 @@ test("stopping the start callback", function() { test("stopping the drag callback", function() { - expect(3); + expect(2); var start = 0, stop = 0, @@ -72,7 +72,6 @@ test("stopping the drag callback", function() { }); equal(start, 1, "start callback should happen exactly once"); - equal(dragc, 1, "drag callback should happen exactly once"); equal(stop, 1, "stop callback should happen, as we need to actively stop the drag"); }); From 1495a6129892ab303e8854e9e39cfc1c968fd569 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 7 Jan 2013 11:35:18 -0500 Subject: [PATCH 146/190] Draggable: Grid will snap at >= half rather than just > --- ui/jquery.ui.draggable.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index e62b5ccf8fb..8e0d9358c81 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -789,18 +789,18 @@ if ( $.uiBackCompat !== false ) { // If x is actually something, check that user is at least half way to next point if ( x ) { - if ( ui.position.left - currentX > x/2 ) { + if ( ui.position.left - currentX >= x/2 ) { currentX = currentX + x; - } else if ( currentX - ui.position.left > x/2 ) { + } else if ( currentX - ui.position.left >= x/2 ) { currentX = currentX - x; } } // If y is actually something, check that user is at least half way to next point if ( y ) { - if ( ui.position.top - currentY > y/2 ) { + if ( ui.position.top - currentY >= y/2 ) { currentY = currentY + y; - } else if ( currentY - ui.position.top > y/2 ) { + } else if ( currentY - ui.position.top >= y/2 ) { currentY = currentY - y; } } From d84cf1d7169e02f85bf847d362192cb667c87059 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 7 Jan 2013 14:44:00 -0500 Subject: [PATCH 147/190] Draggable: Uncommented failing scrolling tests and fixed them --- .../unit/draggable/draggable_test_helpers.js | 4 +- ui/jquery.ui.draggable.js | 52 ++++++++++++++----- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/tests/unit/draggable/draggable_test_helpers.js b/tests/unit/draggable/draggable_test_helpers.js index c1ac0ab8889..681b458922e 100644 --- a/tests/unit/draggable/draggable_test_helpers.js +++ b/tests/unit/draggable/draggable_test_helpers.js @@ -38,9 +38,7 @@ TestHelpers.draggable = { }, setScroll: function( what ) { if(what) { - // todo: currently, the draggable interaction doesn't properly account for scrolled pages, - // uncomment the line below to make the tests fail that should when the page is scrolled - // $(document).scrollTop(100); $(document).scrollLeft(100); + $(document).scrollTop(100); $(document).scrollLeft(100); } else { $("#main").scrollTop(100); $("#main").scrollLeft(100); } diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 8e0d9358c81..8232682d412 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -305,7 +305,9 @@ $.widget( "ui.draggable", $.ui.interaction, { }, _handleScrolling: function( pointerPosition ) { - var scrollTop = this.scrollParent.scrollTop(), + + var newScrollTop, newScrollLeft, + scrollTop = this.scrollParent.scrollTop(), scrollLeft = this.scrollParent.scrollLeft(), scrollSensitivity = this.scrollSensitivity, // overflowOffset is only set when scrollParent is not doc/html @@ -318,24 +320,49 @@ $.widget( "ui.draggable", $.ui.interaction, { xRight = this.overflow.width + overflowLeft - pointerPosition.x, xLeft = pointerPosition.x- overflowLeft, yBottom = this.overflow.height + overflowTop - pointerPosition.y, - yTop = pointerPosition.y - overflowTop; + yTop = pointerPosition.y - overflowTop, + // accounts for change in scrollbar to modify "original" pointer so calc + change; // Handle vertical scrolling if ( yBottom < scrollSensitivity ) { - this.scrollParent.scrollTop( scrollTop + - this._speed( scrollSensitivity - yBottom ) ); + + change = this._speed( scrollSensitivity - yBottom ); + this.scrollParent.scrollTop( scrollTop + change ); + this.originalPointer.y = this.originalPointer.y + change; + } else if ( yTop < scrollSensitivity ) { - this.scrollParent.scrollTop( scrollTop - - this._speed( scrollSensitivity - yTop ) ); + + change = this._speed( scrollSensitivity - yTop ); + newScrollTop = scrollTop - change; + + // Don't do anything unless new value is "real" + if ( newScrollTop >= 0 ) { + this.scrollParent.scrollTop( newScrollTop ); + this._speed( scrollSensitivity - yTop ) + this.originalPointer.y = this.originalPointer.y - change; + } + } // Handle horizontal scrolling if ( xRight < scrollSensitivity ) { - this.scrollParent.scrollLeft( scrollLeft + - this._speed( scrollSensitivity - xRight ) ); + + change = this._speed( scrollSensitivity - xRight ); + this.scrollParent.scrollLeft( scrollLeft + change); + this.originalPointer.x = this.originalPointer.x + change; + } else if ( xLeft < scrollSensitivity ) { - this.scrollParent.scrollLeft( scrollLeft - - this._speed( scrollSensitivity - xLeft ) ); + + change = this._speed( scrollSensitivity - xLeft ); + newScrollLeft = scrollLeft - change; + + // Don't do anything unless new value is "real" + if ( newScrollLeft >= 0 ) { + this.scrollParent.scrollLeft( newScrollLeft ); + this.originalPointer.x = this.originalPointer.x - change; + } + } }, @@ -370,6 +397,7 @@ $.widget( "ui.draggable", $.ui.interaction, { // Places draggable where event, or user via event/callback, indicates _setCss: function() { + var newLeft = this.position.left, newTop = this.position.top; @@ -382,11 +410,11 @@ $.widget( "ui.draggable", $.ui.interaction, { } // TODO: does this work with nested scrollable parents? - if ( this.cssPosition !== "fixed" ) { + if ( this.cssPosition !== "fixed") { newLeft += this.scrollParent.scrollLeft(); newTop += this.scrollParent.scrollTop(); } - + this.dragEl.css({ left: newLeft, top: newTop From 6eb954f5eaa160d86c73e2fa52861c8f1babfb21 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 7 Jan 2013 15:07:42 -0500 Subject: [PATCH 148/190] Draggable: linted --- ui/jquery.ui.draggable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 8232682d412..4a47ac3b5b3 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -339,7 +339,7 @@ $.widget( "ui.draggable", $.ui.interaction, { // Don't do anything unless new value is "real" if ( newScrollTop >= 0 ) { this.scrollParent.scrollTop( newScrollTop ); - this._speed( scrollSensitivity - yTop ) + this._speed( scrollSensitivity - yTop ); this.originalPointer.y = this.originalPointer.y - change; } @@ -410,7 +410,7 @@ $.widget( "ui.draggable", $.ui.interaction, { } // TODO: does this work with nested scrollable parents? - if ( this.cssPosition !== "fixed") { + if ( this.cssPosition !== "fixed" ) { newLeft += this.scrollParent.scrollLeft(); newTop += this.scrollParent.scrollTop(); } From 4c7b57859f7b65da570bdcbb4a26c21b07ec45f1 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Sat, 12 Jan 2013 00:33:45 -0500 Subject: [PATCH 149/190] Draggable Tests: Remove Future Unsupported APIs --- tests/unit/draggable/draggable_events.js | 24 +++++++++++--------- tests/unit/draggable/draggable_options.js | 27 +++++------------------ 2 files changed, 20 insertions(+), 31 deletions(-) diff --git a/tests/unit/draggable/draggable_events.js b/tests/unit/draggable/draggable_events.js index f4ab3a8ea9c..49699a4834a 100644 --- a/tests/unit/draggable/draggable_events.js +++ b/tests/unit/draggable/draggable_events.js @@ -53,17 +53,23 @@ test("stopping the start callback", function() { }); -test("stopping the drag callback", function() { - - expect(3); +test( "stopping the drag callback", function() { + expect( 2 ); var start = 0, stop = 0, dragc = 0, el = $("#draggable2").draggable({ - start: function() { start++;}, - drag: function() { dragc++; return false; }, - stop: function() { stop++; } + start: function() { + start++; + }, + drag: function() { + dragc++; + return false; + }, + stop: function() { + stop++; + } }); el.simulate( "drag", { @@ -71,10 +77,8 @@ test("stopping the drag callback", function() { dy: 10 }); - equal(start, 1, "start callback should happen exactly once"); - equal(dragc, 1, "drag callback should happen exactly once"); - equal(stop, 1, "stop callback should happen, as we need to actively stop the drag"); - + equal( start, 1, "start callback should happen exactly once" ); + equal( stop, 1, "stop callback should happen, as we need to actively stop the drag" ); }); test("stopping the stop callback", function() { diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index a3f7169f2b8..caedad8f81c 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -114,7 +114,9 @@ test("{ cancel: 'span' }", function() { TestHelpers.draggable.testDrag(el, "#draggable2 span", 50, 50, 0, 0); }); -test("{ cancel: ? }, unexpected", function() { +test( "{ cancel: ? }, unexpected", function() { + expect( 6 ); + var el, unexpected = { "true": true, @@ -122,17 +124,12 @@ test("{ cancel: ? }, unexpected", function() { "{}": {}, "[]": [], "null": null, - "undefined": undefined, - "function() {return '';}": function() {return "";}, - "function() {return true;}": function() {return true;}, - "function() {return false;}": function() {return false;} + "undefined": undefined }; - expect( 9 ); - - $.each(unexpected, function(key, val) { + $.each( unexpected, function( key, val ) { el = $("#draggable2").draggable({ cancel: val }); - TestHelpers.draggable.shouldMove(el, "cancel: " + key); + TestHelpers.draggable.shouldMove( el, "cancel: " + key ); el.draggable("destroy"); }); }); @@ -311,18 +308,6 @@ test( "cursorAt", function() { }); }); -test("{ distance: 10 }", function() { - expect( 3 ); - - var el = $("#draggable2").draggable({ distance: 10 }); - TestHelpers.draggable.testDrag(el, el, -9, -9, 0, 0, "distance not met"); - - TestHelpers.draggable.testDrag(el, el, -10, -10, -10, -10, "distance met"); - - TestHelpers.draggable.testDrag(el, el, 9, 9, 0, 0, "distance not met"); - -}); - test("{ grid: [50, 50] }, relative", function() { expect( 2 ); From 430bd6834470da6bcbb8647c9c53ab9547113a4e Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Sat, 12 Jan 2013 00:49:02 -0500 Subject: [PATCH 150/190] Draggable Tests: Cleaned up events tests. --- tests/unit/draggable/draggable_events.js | 130 +++++++++++++---------- 1 file changed, 76 insertions(+), 54 deletions(-) diff --git a/tests/unit/draggable/draggable_events.js b/tests/unit/draggable/draggable_events.js index 49699a4834a..199561be30d 100644 --- a/tests/unit/draggable/draggable_events.js +++ b/tests/unit/draggable/draggable_events.js @@ -1,56 +1,76 @@ /* * draggable_events.js */ -(function($) { +(function( $ ) { -module("draggable: events"); +var element; -test("callbacks occurrence count", function() { +module( "draggable: events", { + setup: function() { + element = $("
    ").appendTo("#qunit-fixture"); + }, + teardown: function() { + element.draggable("destroy"); + } +}); - expect(3); +test( "callbacks occurrence count", function() { + expect( 3 ); var start = 0, stop = 0, - dragc = 0, - el = $("#draggable2").draggable({ - start: function() { start++; }, - drag: function() { dragc++; }, - stop: function() { stop++; } - }); - - el.simulate( "drag", { + dragc = 0; + + element.draggable({ + start: function() { + start++; + }, + drag: function() { + dragc++; + }, + stop: function() { + stop++; + } + }); + + element.simulate( "drag", { dx: 10, dy: 10 }); - equal(start, 1, "start callback should happen exactly once"); - equal(dragc, 3, "drag callback should happen exactly once per mousemove"); - equal(stop, 1, "stop callback should happen exactly once"); - + equal( start, 1, "start callback should happen exactly once" ); + equal( dragc, 3, "drag callback should happen exactly once per mousemove" ); + equal( stop, 1, "stop callback should happen exactly once" ); }); -test("stopping the start callback", function() { - - expect(3); +test( "stopping the start callback", function() { + expect( 3 ); var start = 0, stop = 0, - dragc = 0, - el = $("#draggable2").draggable({ - start: function() { start++; return false; }, - drag: function() { dragc++; }, - stop: function() { stop++; } - }); - - el.simulate( "drag", { + dragc = 0; + + element.draggable({ + start: function() { + start++; + return false; + }, + drag: function() { + dragc++; + }, + stop: function() { + stop++; + } + }); + + element.simulate( "drag", { dx: 10, dy: 10 }); - equal(start, 1, "start callback should happen exactly once"); - equal(dragc, 0, "drag callback should not happen at all"); - equal(stop, 0, "stop callback should not happen if there wasnt even a start"); - + equal( start, 1, "start callback should happen exactly once" ); + equal( dragc, 0, "drag callback should not happen at all" ); + equal( stop, 0, "stop callback should not happen if there wasnt even a start" ); }); test( "stopping the drag callback", function() { @@ -58,21 +78,22 @@ test( "stopping the drag callback", function() { var start = 0, stop = 0, - dragc = 0, - el = $("#draggable2").draggable({ - start: function() { - start++; - }, - drag: function() { - dragc++; - return false; - }, - stop: function() { - stop++; - } - }); - - el.simulate( "drag", { + dragc = 0; + + element.draggable({ + start: function() { + start++; + }, + drag: function() { + dragc++; + return false; + }, + stop: function() { + stop++; + } + }); + + element.simulate( "drag", { dx: 10, dy: 10 }); @@ -81,23 +102,24 @@ test( "stopping the drag callback", function() { equal( stop, 1, "stop callback should happen, as we need to actively stop the drag" ); }); -test("stopping the stop callback", function() { - - expect(1); +test( "stopping the stop callback", function() { + expect( 1 ); - var el = $("#draggable2").draggable({ + element.draggable({ helper: "clone", - stop: function() { return false; } + stop: function() { + return false; + } }); - el.simulate( "drag", { + element.simulate( "drag", { dx: 10, dy: 10 }); - ok($("#draggable2").data("ui-draggable").helper, "the clone should not be deleted if the stop callback is stopped"); + ok( element.data("ui-draggable").helper, "the clone should not be deleted if the stop callback is stopped" ); }); -})(jQuery); +})( jQuery ); From c70b3dc9e3d68d1f61b29665b1911b2e4a9ed336 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Sun, 13 Jan 2013 18:55:43 -0500 Subject: [PATCH 151/190] Draggable Tests: Cleaned up core and method tests. --- tests/unit/draggable/draggable.html | 10 +- tests/unit/draggable/draggable_core.js | 69 +++++++----- tests/unit/draggable/draggable_methods.js | 123 +++++++++++----------- 3 files changed, 111 insertions(+), 91 deletions(-) diff --git a/tests/unit/draggable/draggable.html b/tests/unit/draggable/draggable.html index cd068eb2086..554b49e8469 100644 --- a/tests/unit/draggable/draggable.html +++ b/tests/unit/draggable/draggable.html @@ -40,12 +40,12 @@

      -
      +
      -
      Relative
      -
      Absolute
      -
      -
      +
      Relative
      +
      Absolute
      +
      +
      diff --git a/tests/unit/draggable/draggable_core.js b/tests/unit/draggable/draggable_core.js index 00d9141942d..2090f2fd9ad 100644 --- a/tests/unit/draggable/draggable_core.js +++ b/tests/unit/draggable/draggable_core.js @@ -2,24 +2,40 @@ * draggable_core.js */ -(function($) { +(function( $ ) { -module("draggable"); +var relativeElement, absoluteElement; -test("element types", function() { - var typeNames = ("p,h1,h2,h3,h4,h5,h6,blockquote,ol,ul,dl,div,form" + - ",table,fieldset,address,ins,del,em,strong,q,cite,dfn,abbr" + - ",acronym,code,samp,kbd,var,img,hr" + - ",input,button,label,select,iframe").split(","); +module( "draggable: core", { + setup: function() { + relativeElement = $("
      Relative
      ").appendTo("#qunit-fixture"); + absoluteElement = $("
      Absolute
      ").appendTo("#qunit-fixture"); + }, + teardown: function() { + relativeElement.remove(); + absoluteElement.remove(); + } +}); + +test( "element types", function() { + var typeNames = ( + "p,h1,h2,h3,h4,h5,h6,blockquote,ol,ul,dl,div,form" + + ",table,fieldset,address,ins,del,em,strong,q,cite,dfn,abbr" + + ",acronym,code,samp,kbd,var,img,hr" + + ",input,button,label,select,iframe" + ).split(","); expect( typeNames.length * 2 ); - $.each(typeNames, function(i) { + $.each( typeNames, function( i ) { var offsetBefore, offsetAfter, - typeName = typeNames[i], - el = $(document.createElement(typeName)).appendTo("#qunit-fixture"); + typeName = typeNames[ i ], + el = $( document.createElement( typeName ) ).appendTo("#qunit-fixture"); + + if ( typeName === "table" ) { + el.append("content"); + } - (typeName === "table" && el.append("content")); el.draggable({ cancel: "" }); offsetBefore = el.offset(); el.simulate( "drag", { @@ -27,39 +43,38 @@ test("element types", function() { dy: 50 }); offsetAfter = el.offset(); - // there are some rounding errors in FF, Chrome, and IE9, so we can't say equal, we have to settle for close enough - closeEnough(offsetBefore.left, offsetAfter.left - 50, 1, "dragged[50, 50] " + "<" + typeName + ">"); - closeEnough(offsetBefore.top, offsetAfter.top - 50, 1, "dragged[50, 50] " + "<" + typeName + ">"); + + // Support: FF, Chrome, and IE9, + // there are some rounding errors in so we can't say equal, we have to settle for close enough + closeEnough( offsetBefore.left, offsetAfter.left - 50, 1, "dragged[50, 50] " + "<" + typeName + ">" ); + closeEnough( offsetBefore.top, offsetAfter.top - 50, 1, "dragged[50, 50] " + "<" + typeName + ">" ); el.draggable("destroy"); el.remove(); }); }); -test("No options, relative", function() { +test( "No options, relative", function() { expect( 1 ); - var el = $("#draggable1").draggable(); - TestHelpers.draggable.shouldMove(el); + TestHelpers.draggable.shouldMove( relativeElement.draggable() ); }); -test("No options, absolute", function() { +test( "No options, absolute", function() { expect( 1 ); - var el = $("#draggable2").draggable(); - TestHelpers.draggable.shouldMove(el); + TestHelpers.draggable.shouldMove( absoluteElement.draggable() ); }); -test("resizable handle with complex markup (#8756 / #8757)", function() { +test( "resizable handle with complex markup (#8756 / #8757)", function() { expect( 2 ); - $("#draggable1") + relativeElement .append( $("
      ") - .addClass("ui-resizable-handle") - .addClass("ui-resizable-w") - .append($("
      ")) + .addClass("ui-resizable-handle ui-resizable-w") + .append( $("
      ") ) ); var handle = $(".ui-resizable-w div"), - target = $("#draggable1").draggable().resizable({ handles: "all" }); + target = relativeElement.draggable().resizable({ handles: "all" }); // todo: fix resizable so it doesn't require a mouseover handle.simulate("mouseover").simulate( "drag", { dx: -50 } ); @@ -70,4 +85,4 @@ test("resizable handle with complex markup (#8756 / #8757)", function() { equal( target.width(), 200, "compare width" ); }); -})(jQuery); +})( jQuery ); diff --git a/tests/unit/draggable/draggable_methods.js b/tests/unit/draggable/draggable_methods.js index 43db285ce4c..901c261d6ed 100644 --- a/tests/unit/draggable/draggable_methods.js +++ b/tests/unit/draggable/draggable_methods.js @@ -1,94 +1,99 @@ /* * draggable_methods.js */ -(function($) { +(function( $ ) { -module("draggable: methods"); +var element; -test("init", function() { - expect(5); +module( "draggable: methods", { + setup: function() { + element = $("
      Absolute
      ").appendTo("#qunit-fixture"); + }, + teardown: function() { + element.remove(); + } +}); + +test( "init", function() { + expect( 5 ); - $("
      ").appendTo("body").draggable().remove(); - ok(true, ".draggable() called on element"); + element.draggable(); + ok( true, ".draggable() called on element" ); $([]).draggable(); - ok(true, ".draggable() called on empty collection"); + ok( true, ".draggable() called on empty collection" ); $("
      ").draggable(); - ok(true, ".draggable() called on disconnected DOMElement"); + ok( true, ".draggable() called on disconnected DOMElement" ); - $("
      ").draggable().draggable("option", "foo"); - ok(true, "arbitrary option getter after init"); + element.draggable( "option", "foo" ); + ok( true, "arbitrary option getter after init" ); - $("
      ").draggable().draggable("option", "foo", "bar"); - ok(true, "arbitrary option setter after init"); + element.draggable( "option", "foo", "bar" ); + ok( true, "arbitrary option setter after init" ); }); -test("destroy", function() { - expect(4); - $("
      ").appendTo("body").draggable().draggable("destroy").remove(); - ok(true, ".draggable('destroy') called on element"); +test( "destroy", function() { + expect( 4 ); + + element.draggable().draggable("destroy"); + ok( true, ".draggable('destroy') called on element" ); $([]).draggable().draggable("destroy"); - ok(true, ".draggable('destroy') called on empty collection"); + ok( true, ".draggable('destroy') called on empty collection" ); - $("
      ").draggable().draggable("destroy"); - ok(true, ".draggable('destroy') called on disconnected DOMElement"); + element.draggable().draggable("destroy"); + ok( true, ".draggable('destroy') called on disconnected DOMElement" ); - var expected = $("
      ").draggable(), + var expected = element.draggable(), actual = expected.draggable("destroy"); - equal(actual, expected, "destroy is chainable"); + equal( actual, expected, "destroy is chainable" ); }); -test("enable", function() { - expect(7); +test( "enable", function() { + expect( 7 ); - var expected, actual, el; + element.draggable({ disabled: true }); + TestHelpers.draggable.shouldNotMove( element, ".draggable({ disabled: true })" ); - el = $("#draggable2").draggable({ disabled: true }); - TestHelpers.draggable.shouldNotMove(el, ".draggable({ disabled: true })"); + element.draggable("enable"); + TestHelpers.draggable.shouldMove( element, ".draggable('enable')" ); + equal( element.draggable( "option", "disabled" ), false, "disabled option getter" ); - el.draggable("enable"); - TestHelpers.draggable.shouldMove(el, ".draggable('enable')"); - equal(el.draggable("option", "disabled"), false, "disabled option getter"); + element.draggable("destroy"); + element.draggable({ disabled: true }); + TestHelpers.draggable.shouldNotMove( element, ".draggable({ disabled: true })" ); - el.draggable("destroy"); - el.draggable({ disabled: true }); - TestHelpers.draggable.shouldNotMove(el, ".draggable({ disabled: true })"); + element.draggable( "option", "disabled", false ); + equal(element.draggable( "option", "disabled" ), false, "disabled option setter" ); + TestHelpers.draggable.shouldMove( element, ".draggable('option', 'disabled', false)" ); - el.draggable("option", "disabled", false); - equal(el.draggable("option", "disabled"), false, "disabled option setter"); - TestHelpers.draggable.shouldMove(el, ".draggable('option', 'disabled', false)"); - - expected = $("
      ").draggable(), - actual = expected.draggable("enable"); - equal(actual, expected, "enable is chainable"); + var expected = element.draggable(), + actual = expected.draggable("enable"); + equal( actual, expected, "enable is chainable" ); }); -test("disable", function() { - expect(7); - - var expected, actual, el; - - el = $("#draggable2").draggable({ disabled: false }); - TestHelpers.draggable.shouldMove(el, ".draggable({ disabled: false })"); +test( "disable", function() { + expect( 7 ); - el.draggable("disable"); - TestHelpers.draggable.shouldNotMove(el, ".draggable('disable')"); - equal(el.draggable("option", "disabled"), true, "disabled option getter"); + element = $("#draggable2").draggable({ disabled: false }); + TestHelpers.draggable.shouldMove( element, ".draggable({ disabled: false })" ); - el.draggable("destroy"); + element.draggable("disable"); + TestHelpers.draggable.shouldNotMove( element, ".draggable('disable')" ); + equal( element.draggable( "option", "disabled" ), true, "disabled option getter" ); - el.draggable({ disabled: false }); - TestHelpers.draggable.shouldMove(el, ".draggable({ disabled: false })"); + element.draggable("destroy"); + element.draggable({ disabled: false }); + TestHelpers.draggable.shouldMove( element, ".draggable({ disabled: false })" ); - el.draggable("option", "disabled", true); - equal(el.draggable("option", "disabled"), true, "disabled option setter"); - TestHelpers.draggable.shouldNotMove(el, ".draggable('option', 'disabled', true)"); + element.draggable( "option", "disabled", true ); + equal( element.draggable( "option", "disabled" ), true, "disabled option setter" ); + TestHelpers.draggable.shouldNotMove( element, ".draggable('option', 'disabled', true)" ); - expected = $("
      ").draggable(), - actual = expected.draggable("disable"); - equal(actual, expected, "disable is chainable"); + var expected = element.draggable(), + actual = expected.draggable("disable"); + equal( actual, expected, "disable is chainable" ); }); -})(jQuery); +})( jQuery ); From c9001874dcc6bbaf4308bde415984ea53e8e61be Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 14 Jan 2013 18:26:39 -0500 Subject: [PATCH 152/190] Draggable Tests: Added tests for appendTo and axis --- tests/unit/draggable/draggable_options.js | 109 +++++++++++++++++- .../unit/draggable/draggable_test_helpers.js | 19 +++ 2 files changed, 124 insertions(+), 4 deletions(-) diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index caedad8f81c..27a2b199728 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -21,7 +21,8 @@ test("{ addClasses: false }", function() { el.draggable("destroy"); }); -test("{ appendTo: 'parent' }, default", function() { +// TODO: This doesn't actually test whether append happened, possibly remove +test("{ appendTo: 'parent' }, default, no clone", function() { expect( 2 ); var el = $("#draggable2").draggable({ appendTo: "parent" }); TestHelpers.draggable.shouldMove(el); @@ -31,16 +32,19 @@ test("{ appendTo: 'parent' }, default", function() { }); -test("{ appendTo: Element }", function() { +// TODO: This doesn't actually test whether append happened, possibly remove +test("{ appendTo: Element }, no clone", function() { expect( 2 ); - var el = $("#draggable2").draggable({ appendTo: $("#draggable2").parent()[0] }); + var el = $("#draggable2").draggable({appendTo: $("#draggable2").parent()[0] }); + TestHelpers.draggable.shouldMove(el); el = $("#draggable1").draggable({ appendTo: $("#draggable2").parent()[0] }); TestHelpers.draggable.shouldMove(el); }); -test("{ appendTo: Selector }", function() { +// TODO: This doesn't actually test whether append happened, possibly remove +test("{ appendTo: Selector }, no clone", function() { expect( 2 ); var el = $("#draggable2").draggable({ appendTo: "#main" }); TestHelpers.draggable.shouldMove(el); @@ -49,6 +53,83 @@ test("{ appendTo: Selector }", function() { TestHelpers.draggable.shouldMove(el); }); +test("{ appendTo: 'parent' }, default", function() { + + expect(2); + + var el = $("#draggable1").draggable(); + + TestHelpers.draggable.trackAppendedParent(el); + + equal( el.draggable( "option", "appendTo" ), "parent" ); + + TestHelpers.draggable.move(el, 1, 1); + equal( el.data("last_parent"), $("#qunit-fixture")[0] ); + +}); + +test("{ appendTo: Element }", function() { + + expect(1); + + var appendTo = $("#draggable2").parent()[0], + el = $("#draggable1").draggable({ appendTo: appendTo }); + + TestHelpers.draggable.trackAppendedParent(el); + + TestHelpers.draggable.move(el, 1, 1); + equal( el.data("last_parent"), appendTo ); + +}); + +test("{ appendTo: jQuery }", function() { + + expect(1); + + var appendTo = $("#draggable2").parent(), + el = $("#draggable1").draggable({ appendTo: appendTo }); + + TestHelpers.draggable.trackAppendedParent(el); + + TestHelpers.draggable.move(el, 1, 1); + equal( el.data("last_parent"), appendTo[0] ); + +}); +test("{ appendTo: Selector }", function() { + + expect(1); + + + var appendTo = "#main", + el = $("#draggable1").draggable({ appendTo: appendTo }); + + TestHelpers.draggable.trackAppendedParent(el); + + TestHelpers.draggable.move(el, 1, 1); + equal( el.data("last_parent"), $(appendTo)[0] ); + +}); + + +test("{ appendTo: 'parent' }, switching after initialization", function() { + + expect(2); + + var el = $("#draggable1").draggable({ helper : "clone" }); + + TestHelpers.draggable.trackAppendedParent(el); + + // Move and make sure el was appended to fixture + TestHelpers.draggable.move(el, 1, 1); + equal( el.data("last_parent"), $("#qunit-fixture")[0] ); + + // Move and make sure el was appended to main + el.draggable( "option", "appendTo", $("#main") ); + TestHelpers.draggable.move(el, 2, 2); + equal( el.data("last_parent"), $("#main")[0] ); + +}); + test("{ axis: false }, default", function() { expect( 1 ); var el = $("#draggable2").draggable({ axis: false }); @@ -87,6 +168,26 @@ test("{ axis: ? }, unexpected", function() { }); }); +test("{ axis: false }, switching after initialization", function() { + + expect(3); + + var el; + + // Any direction + el = $("#draggable1").draggable({ axis : false }); + TestHelpers.draggable.testDrag(el, el, 50, 50, 50, 50); + + // Only horizontal + el.draggable("option", "axis", "x"); + TestHelpers.draggable.testDrag(el, el, 50, 50, 50, 0); + + // Vertical only + el.draggable("option", "axis", "y"); + TestHelpers.draggable.testDrag(el, el, 50, 50, 0, 50); + +}); + test("{ cancel: 'input,textarea,button,select,option' }, default", function() { expect( 2 ); diff --git a/tests/unit/draggable/draggable_test_helpers.js b/tests/unit/draggable/draggable_test_helpers.js index c1ac0ab8889..9d449051090 100644 --- a/tests/unit/draggable/draggable_test_helpers.js +++ b/tests/unit/draggable/draggable_test_helpers.js @@ -50,5 +50,24 @@ TestHelpers.draggable = { }, margin: function(el, side) { return parseInt(el.css("margin-" + side), 10) || 0; + }, + move: function( el, x, y ) { + + $( el ).simulate( "drag", { + dx: x, + dy: y + }); + + }, + trackAppendedParent : function( el ) { + + // appendTo ignored without being clone + el.draggable( "option", "helper", "clone" ); + + el.on( "drag", function(e,ui) { + // Get what parent is at time of drag + el.data( "last_parent", ui.helper.parent()[0] ); + }); + } }; \ No newline at end of file From e85402f553a9a506edc35108cab46a39a63f2370 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 14 Jan 2013 19:20:39 -0500 Subject: [PATCH 153/190] Draggable: Added tests for containment and cursor. --- tests/unit/draggable/draggable_options.js | 75 +++++++++++++++++-- .../unit/draggable/draggable_test_helpers.js | 9 ++- 2 files changed, 74 insertions(+), 10 deletions(-) diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index 27a2b199728..1b89581bef3 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -64,7 +64,7 @@ test("{ appendTo: 'parent' }, default", function() { equal( el.draggable( "option", "appendTo" ), "parent" ); TestHelpers.draggable.move(el, 1, 1); - equal( el.data("last_parent"), $("#qunit-fixture")[0] ); + equal( el.data("last_dragged_parent"), $("#qunit-fixture")[0] ); }); @@ -78,7 +78,7 @@ test("{ appendTo: Element }", function() { TestHelpers.draggable.trackAppendedParent(el); TestHelpers.draggable.move(el, 1, 1); - equal( el.data("last_parent"), appendTo ); + equal( el.data("last_dragged_parent"), appendTo ); }); @@ -92,7 +92,7 @@ test("{ appendTo: jQuery }", function() { TestHelpers.draggable.trackAppendedParent(el); TestHelpers.draggable.move(el, 1, 1); - equal( el.data("last_parent"), appendTo[0] ); + equal( el.data("last_dragged_parent"), appendTo[0] ); }); test("{ appendTo: Selector }", function() { @@ -106,12 +106,12 @@ test("{ appendTo: Selector }", function() { TestHelpers.draggable.trackAppendedParent(el); TestHelpers.draggable.move(el, 1, 1); - equal( el.data("last_parent"), $(appendTo)[0] ); + equal( el.data("last_dragged_parent"), $(appendTo)[0] ); }); -test("{ appendTo: 'parent' }, switching after initialization", function() { +test("appendTo, default, switching after initialization", function() { expect(2); @@ -121,12 +121,12 @@ test("{ appendTo: 'parent' }, switching after initialization", function() { // Move and make sure el was appended to fixture TestHelpers.draggable.move(el, 1, 1); - equal( el.data("last_parent"), $("#qunit-fixture")[0] ); + equal( el.data("last_dragged_parent"), $("#qunit-fixture")[0] ); // Move and make sure el was appended to main el.draggable( "option", "appendTo", $("#main") ); TestHelpers.draggable.move(el, 2, 2); - equal( el.data("last_parent"), $("#main")[0] ); + equal( el.data("last_dragged_parent"), $("#main")[0] ); }); @@ -168,7 +168,7 @@ test("{ axis: ? }, unexpected", function() { }); }); -test("{ axis: false }, switching after initialization", function() { +test("axis, default, switching after initialization", function() { expect(3); @@ -235,6 +235,24 @@ test( "{ cancel: ? }, unexpected", function() { }); }); +test("cancel, default, switching after initialization", function() { + expect( 3 ); + + $("
      ").appendTo("#main"); + + var input = $("#draggable-option-cancel-default input"), + el = $("#draggable-option-cancel-default").draggable(); + + TestHelpers.draggable.testDrag(el, input, 50, 50, 0, 0); + + el.draggable('option', 'cancel', 'textarea' ); + TestHelpers.draggable.testDrag(el, input, 50, 50, 50, 50); + + el.draggable('option', 'cancel', 'input' ); + TestHelpers.draggable.testDrag(el, input, 50, 50, 0, 0); + +}); + /* test("{ containment: false }, default", function() { expect( 1 ); @@ -289,6 +307,26 @@ test("{ containment: 'parent' }, absolute", function() { deepEqual(offsetAfter, expected, "compare offset to parent"); }); +test("containment, default, switching after initialization", function() { + expect( 2 ); + + var offsetAfter, + el = $("#draggable1").draggable({ containment: false }); + + TestHelpers.draggable.testDrag(el, el, -100, -100, -100, -100); + + el.draggable( "option", "containment", "parent" ) + .css({top:0,left:0}) + .appendTo( $("#main") ); + + TestHelpers.draggable.testDrag(el, el, -100, -100, 0, 0); + + // TODO: Switching back to false does not update to false + // el.draggable( "option", "containment", false ); + // TestHelpers.draggable.testDrag(el, el, -100, -100, -100, -100); + +}); + /* test("{ containment: 'document' }", function() { expect( 1 ); @@ -368,6 +406,27 @@ test("{ cursor: 'move' }", function() { }); +test("cursor, default, switching after initialization", function() { + + expect(3); + + var el = $("#draggable1").draggable(); + + TestHelpers.draggable.trackMouseCss( el ); + + TestHelpers.draggable.move( el, 1, 1 ); + equal( el.data("last_dragged_cursor"), "auto" ); + + el.draggable( "option", "cursor", "move" ); + TestHelpers.draggable.move( el, 1, 1 ); + equal( el.data("last_dragged_cursor"), "move" ); + + el.draggable( "option", "cursor", "ns-resize" ); + TestHelpers.draggable.move( el, 1, 1 ); + equal( el.data("last_dragged_cursor"), "ns-resize" ); + +}); + test( "cursorAt", function() { expect( 24 ); diff --git a/tests/unit/draggable/draggable_test_helpers.js b/tests/unit/draggable/draggable_test_helpers.js index 9d449051090..9f05828fe3a 100644 --- a/tests/unit/draggable/draggable_test_helpers.js +++ b/tests/unit/draggable/draggable_test_helpers.js @@ -11,7 +11,7 @@ TestHelpers.draggable = { }); offsetAfter = el.offset(); - actual = { left: offsetAfter.left, top: offsetAfter.top }, + actual = { left: offsetAfter.left, top: offsetAfter.top }; expected = { left: offsetBefore.left + expectedDX, top: offsetBefore.top + expectedDY }; msg = msg ? msg + "." : ""; @@ -59,6 +59,11 @@ TestHelpers.draggable = { }); }, + trackMouseCss : function( el ) { + el.on( "drag", function(e,ui) { + el.data( "last_dragged_cursor", $("body").css("cursor") ); + }); + }, trackAppendedParent : function( el ) { // appendTo ignored without being clone @@ -66,7 +71,7 @@ TestHelpers.draggable = { el.on( "drag", function(e,ui) { // Get what parent is at time of drag - el.data( "last_parent", ui.helper.parent()[0] ); + el.data( "last_dragged_parent", ui.helper.parent()[0] ); }); } From 4a238046bff9c4bb9d68c180506ba6bc2053ded5 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 15 Jan 2013 18:57:13 -0500 Subject: [PATCH 154/190] Draggable Tests: Grunted --- tests/unit/draggable/draggable_options.js | 7 +++---- tests/unit/draggable/draggable_test_helpers.js | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index 1b89581bef3..16664841513 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -245,10 +245,10 @@ test("cancel, default, switching after initialization", function() { TestHelpers.draggable.testDrag(el, input, 50, 50, 0, 0); - el.draggable('option', 'cancel', 'textarea' ); + el.draggable("option", "cancel", "textarea" ); TestHelpers.draggable.testDrag(el, input, 50, 50, 50, 50); - el.draggable('option', 'cancel', 'input' ); + el.draggable("option", "cancel", "input" ); TestHelpers.draggable.testDrag(el, input, 50, 50, 0, 0); }); @@ -310,8 +310,7 @@ test("{ containment: 'parent' }, absolute", function() { test("containment, default, switching after initialization", function() { expect( 2 ); - var offsetAfter, - el = $("#draggable1").draggable({ containment: false }); + var el = $("#draggable1").draggable({ containment: false }); TestHelpers.draggable.testDrag(el, el, -100, -100, -100, -100); diff --git a/tests/unit/draggable/draggable_test_helpers.js b/tests/unit/draggable/draggable_test_helpers.js index 9f05828fe3a..3c4680e9782 100644 --- a/tests/unit/draggable/draggable_test_helpers.js +++ b/tests/unit/draggable/draggable_test_helpers.js @@ -60,7 +60,7 @@ TestHelpers.draggable = { }, trackMouseCss : function( el ) { - el.on( "drag", function(e,ui) { + el.on( "drag", function() { el.data( "last_dragged_cursor", $("body").css("cursor") ); }); }, From 9846dbcfaa065a8040f040913cf810662e9bfa50 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 15 Jan 2013 19:11:34 -0500 Subject: [PATCH 155/190] Draggable: Added more tests for grid and cursorAt --- tests/unit/draggable/draggable_options.js | 63 +++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index 16664841513..7a0df6ea03a 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -467,6 +467,53 @@ test( "cursorAt", function() { }); }); +test( "cursorAt, switching after initialization", function() { + + expect( 24 ); + + var deltaX = -3, + deltaY = -3, + tests = { + "false": { cursorAt : false }, + "{ left: -5, top: -5 }": { x: -5, y: -5, cursorAt : { left: -5, top: -5 } }, + "[ 10, 20 ]": { x: 10, y: 20, cursorAt : [ 10, 20 ] }, + "'10 20'": { x: 10, y: 20, cursorAt : "10 20" }, + "{ left: 20, top: 40 }": { x: 20, y: 40, cursorAt : { left: 20, top: 40 } }, + "{ right: 10, bottom: 20 }": { x: 10, y: 20, cursorAt : { right: 10, bottom: 20 } } + }; + + $.each( tests, function( testName, testData ) { + $.each( [ "relative", "absolute" ], function( i, position ) { + var el = $( "#draggable" + ( i + 1 ) ); + + el.draggable({ + drag: function( event, ui ) { + if( !testData.cursorAt ) { + equal( ui.position.left - ui.originalPosition.left, deltaX, testName + " " + position + " left" ); + equal( ui.position.top - ui.originalPosition.top, deltaY, testName + " " + position + " top" ); + } else if( testData.cursorAt.right ) { + equal( ui.helper.width() - ( event.clientX - ui.offset.left ), testData.x - TestHelpers.draggable.unreliableOffset, testName + " " + position + " left" ); + equal( ui.helper.height() - ( event.clientY - ui.offset.top ), testData.y - TestHelpers.draggable.unreliableOffset, testName + " " +position + " top" ); + } else { + equal( event.clientX - ui.offset.left, testData.x + TestHelpers.draggable.unreliableOffset, testName + " " + position + " left" ); + equal( event.clientY - ui.offset.top, testData.y + TestHelpers.draggable.unreliableOffset, testName + " " + position + " top" ); + } + } + }); + + el.draggable( "option", "cursorAt", false ); + el.draggable( "option", "cursorAt", testData.cursorAt ); + + el.simulate( "drag", { + moves: 1, + dx: deltaX, + dy: deltaY + }); + }); + }); + +}); + test("{ grid: [50, 50] }, relative", function() { expect( 2 ); @@ -483,6 +530,22 @@ test("{ grid: [50, 50] }, absolute", function() { TestHelpers.draggable.testDrag(el, el, 26, 25, 50, 50); }); +test("grid, switching after initialization", function() { + + expect( 4 ); + + var el = $("#draggable1").draggable(); + // Forward + TestHelpers.draggable.testDrag(el, el, 24, 24, 24, 24); + TestHelpers.draggable.testDrag(el, el, 0, 0, 0, 0); + + el.draggable( "option", "grid", [50,50] ); + + TestHelpers.draggable.testDrag(el, el, 24, 24, 0, 0); + TestHelpers.draggable.testDrag(el, el, 26, 25, 50, 50); + +}); + test("{ handle: 'span' }", function() { expect( 2 ); From f616b62a5d28d258f174c3ec945e550246acbef7 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 15 Jan 2013 19:24:41 -0500 Subject: [PATCH 156/190] Draggable: Added tests for handle and helper, removed trailing whitespaces --- tests/unit/draggable/draggable_options.js | 68 +++++++++++++++++------ 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index 7a0df6ea03a..c01efc32485 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -237,20 +237,20 @@ test( "{ cancel: ? }, unexpected", function() { test("cancel, default, switching after initialization", function() { expect( 3 ); - + $("
      ").appendTo("#main"); var input = $("#draggable-option-cancel-default input"), el = $("#draggable-option-cancel-default").draggable(); - + TestHelpers.draggable.testDrag(el, input, 50, 50, 0, 0); - + el.draggable("option", "cancel", "textarea" ); TestHelpers.draggable.testDrag(el, input, 50, 50, 50, 50); - + el.draggable("option", "cancel", "input" ); TestHelpers.draggable.testDrag(el, input, 50, 50, 0, 0); - + }); /* @@ -313,13 +313,13 @@ test("containment, default, switching after initialization", function() { var el = $("#draggable1").draggable({ containment: false }); TestHelpers.draggable.testDrag(el, el, -100, -100, -100, -100); - + el.draggable( "option", "containment", "parent" ) .css({top:0,left:0}) .appendTo( $("#main") ); - + TestHelpers.draggable.testDrag(el, el, -100, -100, 0, 0); - + // TODO: Switching back to false does not update to false // el.draggable( "option", "containment", false ); // TestHelpers.draggable.testDrag(el, el, -100, -100, -100, -100); @@ -408,18 +408,18 @@ test("{ cursor: 'move' }", function() { test("cursor, default, switching after initialization", function() { expect(3); - + var el = $("#draggable1").draggable(); - + TestHelpers.draggable.trackMouseCss( el ); TestHelpers.draggable.move( el, 1, 1 ); equal( el.data("last_dragged_cursor"), "auto" ); - + el.draggable( "option", "cursor", "move" ); TestHelpers.draggable.move( el, 1, 1 ); equal( el.data("last_dragged_cursor"), "move" ); - + el.draggable( "option", "cursor", "ns-resize" ); TestHelpers.draggable.move( el, 1, 1 ); equal( el.data("last_dragged_cursor"), "ns-resize" ); @@ -485,7 +485,7 @@ test( "cursorAt, switching after initialization", function() { $.each( tests, function( testName, testData ) { $.each( [ "relative", "absolute" ], function( i, position ) { var el = $( "#draggable" + ( i + 1 ) ); - + el.draggable({ drag: function( event, ui ) { if( !testData.cursorAt ) { @@ -500,7 +500,7 @@ test( "cursorAt, switching after initialization", function() { } } }); - + el.draggable( "option", "cursorAt", false ); el.draggable( "option", "cursorAt", testData.cursorAt ); @@ -538,12 +538,12 @@ test("grid, switching after initialization", function() { // Forward TestHelpers.draggable.testDrag(el, el, 24, 24, 24, 24); TestHelpers.draggable.testDrag(el, el, 0, 0, 0, 0); - + el.draggable( "option", "grid", [50,50] ); - + TestHelpers.draggable.testDrag(el, el, 24, 24, 0, 0); TestHelpers.draggable.testDrag(el, el, 26, 25, 50, 50); - + }); test("{ handle: 'span' }", function() { @@ -555,6 +555,40 @@ test("{ handle: 'span' }", function() { TestHelpers.draggable.shouldNotMove(el, "drag element"); }); +test("handle, default, switching after initialization", function() { + expect( 6 ); + + var el = $("#draggable2").draggable(); + + TestHelpers.draggable.testDrag(el, el, 50, 50, 50, 50); + TestHelpers.draggable.testDrag(el, "#draggable2 span", 100, 100, 100, 100); + + // Switch + el.draggable( "option", "handle", "span" ); + TestHelpers.draggable.testDrag(el, el, 50, 50, 0, 0); + TestHelpers.draggable.testDrag(el, "#draggable2 span", 100, 100, 100, 100); + + // And back + el.draggable( "option", "handle", false ); + TestHelpers.draggable.testDrag(el, el, 50, 50, 50, 50); + TestHelpers.draggable.testDrag(el, "#draggable2 span", 100, 100, 100, 100); + +}); + +test("helper, default, switching after initialization", function() { + expect( 3 ); + + var el = $("#draggable1").draggable(); + TestHelpers.draggable.shouldMove(el); + + el.draggable( "option", "helper", "clone" ); + TestHelpers.draggable.shouldNotMove(el); + + el.draggable( "option", "helper", "original" ); + TestHelpers.draggable.shouldMove(el); + +}); + test("{ helper: 'clone' }, relative", function() { expect( 1 ); From 5f26d83c787a44d86232a10324e197471e5ddffe Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 15 Jan 2013 19:32:06 -0500 Subject: [PATCH 157/190] Draggable: Added tests for opacity and zIndex --- tests/unit/draggable/draggable_options.js | 50 +++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index c01efc32485..6f7e06ce706 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -942,6 +942,30 @@ test("{ opacity: 0.5 }", function() { }); +test("opacity, default, switching after initialization", function() { + + expect(3); + + var opacity = null, + el = $("#draggable2").draggable({ + start: function() { + opacity = $(this).css("opacity"); + } + }); + + TestHelpers.draggable.move( el, 1, 1 ); + equal( opacity, 1 ); + + el.draggable( "option", "opacity", 0.5 ); + TestHelpers.draggable.move( el, 2, 1 ); + equal( opacity, 0.5 ); + + el.draggable( "option", "opacity", false ); + TestHelpers.draggable.move( el, 3, 1 ); + equal( opacity, 1 ); + +}); + test("{ zIndex: 10 }", function() { expect(1); @@ -964,4 +988,30 @@ test("{ zIndex: 10 }", function() { }); +test("zIndex, default, switching after initialization", function() { + + expect(3); + + var zindex = null, + el = $("#draggable2").draggable({ + start: function() { + zindex = $(this).css("z-index"); + } + }); + + el.css( "z-index", 1 ); + + TestHelpers.draggable.move( el, 1, 1 ); + equal( zindex, 1 ); + + el.draggable( "option", "zIndex", 5 ); + TestHelpers.draggable.move( el, 2, 1 ); + equal( zindex, 5 ); + + el.draggable( "option", "zIndex", false ); + TestHelpers.draggable.move( el, 3, 1 ); + equal( zindex, 1 ); + +}); + })(jQuery); From b21904007fe46710497ec252e3feee9df3e5c6cb Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Tue, 15 Jan 2013 19:42:03 -0500 Subject: [PATCH 158/190] Draggable: Added test for disabled --- tests/unit/draggable/draggable_options.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index 6f7e06ce706..57b3da6b2cd 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -514,6 +514,23 @@ test( "cursorAt, switching after initialization", function() { }); + +test( "disabled", function() { + + expect( 3 ); + + var el = $("#draggable1").draggable(); + + TestHelpers.draggable.shouldMove(el); + + el.draggable( "option", "disabled", true ); + TestHelpers.draggable.shouldNotMove(el); + + el.draggable( "option", "disabled", false ); + TestHelpers.draggable.shouldMove(el); + +}); + test("{ grid: [50, 50] }, relative", function() { expect( 2 ); From ea6c9fb48b7a6d6decc94e3d097167a3280ffd26 Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 18 Feb 2013 11:59:31 -0500 Subject: [PATCH 159/190] Draggable: Changed data uiDraggable to ui-draggable --- ui/jquery.ui.draggable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 83e25294929..9c0b6844331 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -214,7 +214,7 @@ $.widget( "ui.draggable", $.ui.interaction, { // If user cancels stop, leave helper there if ( this._trigger( "stop", event, this._fullHash( pointerPosition ) ) !== false ) { if ( this.options.helper ) { - delete this.element.data( "uiDraggable" ).helper; + delete this.element.data( "ui-draggable" ).helper; this.dragEl.remove(); } this._resetDomPosition(); @@ -248,7 +248,7 @@ $.widget( "ui.draggable", $.ui.interaction, { helper.appendTo( this._appendToEl() || this.document[0].body ); } - this.element.data( "uiDraggable" ).helper = helper; + this.element.data( "ui-draggable" ).helper = helper; this._cacheDragDimensions( helper ); From 436ddbdd81bc62035ae004cb38dcbda53cf3891e Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 18 Feb 2013 12:28:12 -0500 Subject: [PATCH 160/190] Draggable: Changed "is" to "closest" for isValidTarget --- ui/jquery.ui.draggable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 9c0b6844331..ef8c7601d38 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -74,8 +74,8 @@ $.widget( "ui.draggable", $.ui.interaction, { /** interaction interface **/ _isValidTarget: function( element ) { - var handle = this.options.handle ? element.is( this.options.handle ) : true, - exclude = this.options.exclude ? element.is( this.options.exclude ) : false; + var handle = this.options.handle ? element.closest( this.options.handle ).length : true, + exclude = this.options.exclude ? element.closest( this.options.exclude ).length : false; return ( handle && !exclude ); }, From d438973983eb13499aa71cbbc89dcaabc2fe4c6c Mon Sep 17 00:00:00 2001 From: Nathanael Silverman Date: Mon, 18 Feb 2013 21:59:25 +0100 Subject: [PATCH 161/190] Build: Add 'jquery.ui.interaction.js' to core files for grunt. --- grunt.js | 1 + 1 file changed, 1 insertion(+) diff --git a/grunt.js b/grunt.js index d599496cc29..8c60ca4c021 100644 --- a/grunt.js +++ b/grunt.js @@ -8,6 +8,7 @@ var "jquery.ui.core.js", "jquery.ui.widget.js", "jquery.ui.mouse.js", + "jquery.ui.interaction.js", "jquery.ui.draggable.js", "jquery.ui.droppable.js", "jquery.ui.resizable.js", From 894d4c157a266e185e1fb4b45f35f65addbd8b3a Mon Sep 17 00:00:00 2001 From: Dave Stein Date: Mon, 18 Feb 2013 17:13:29 -0500 Subject: [PATCH 162/190] Draggable + Sortable: Fixed blockFrames. Added unit tests specifically for draggable since it should be moving up to "core" file shortly --- tests/unit/draggable/draggable_core.js | 81 ++++++++++++++++++++++++++ ui/jquery.ui.draggable.js | 10 ++-- ui/jquery.ui.sortable.js | 10 ++-- 3 files changed, 89 insertions(+), 12 deletions(-) diff --git a/tests/unit/draggable/draggable_core.js b/tests/unit/draggable/draggable_core.js index 0f0aa2e053e..b50a725609e 100644 --- a/tests/unit/draggable/draggable_core.js +++ b/tests/unit/draggable/draggable_core.js @@ -47,6 +47,87 @@ test("No options, absolute", function() { TestHelpers.draggable.shouldMove(el); }); +test("_blockFrames, absolute parent", function() { + expect( 3 ); + var el = $("#draggable1").draggable(), + parent = $("
      "), + iframe = $("