mirror of
https://github.com/jquery/jquery-ui.git
synced 2024-11-21 11:04:24 +00:00
Draggable: normalize lookups for rootNodes when to bust scroll cache. Fixes #9379 - Draggable: position bug in scrollable div
Core: update scrollParent() to support all current supported browsers.
This commit is contained in:
parent
77bf202e58
commit
44b2180782
@ -19,6 +19,9 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
#main-forceScrollable {
|
#main-forceScrollable {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
width: 1100px;
|
width: 1100px;
|
||||||
height: 1100px;
|
height: 1100px;
|
||||||
}
|
}
|
||||||
@ -33,6 +36,9 @@
|
|||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
#scrollParent-forceScrollable {
|
#scrollParent-forceScrollable {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
width: 1300px;
|
width: 1300px;
|
||||||
height: 1300px;
|
height: 1300px;
|
||||||
}
|
}
|
||||||
@ -78,7 +84,7 @@
|
|||||||
<div id="qunit-fixture">
|
<div id="qunit-fixture">
|
||||||
<div id="scrollParent">
|
<div id="scrollParent">
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<div id="draggable1" style="background: green; width: 200px; height: 100px;">Relative</div>
|
<div id="draggable1" style="background: green; width: 200px; height: 100px; position: relative; top: 0; left: 0;">Relative</div>
|
||||||
<div id="draggable2" style="background: green; width: 200px; height: 100px; position: absolute; top: 10px; left: 10px;"><span><em>Absolute</em></span></div>
|
<div id="draggable2" style="background: green; width: 200px; height: 100px; position: absolute; top: 10px; left: 10px;"><span><em>Absolute</em></span></div>
|
||||||
<div id="droppable" style="background: green; width: 200px; height: 100px; position: absolute; top: 110px; left: 110px;"><span>Absolute</span></div>
|
<div id="droppable" style="background: green; width: 200px; height: 100px; position: absolute; top: 110px; left: 110px;"><span>Absolute</span></div>
|
||||||
<div id="main-forceScrollable"></div>
|
<div id="main-forceScrollable"></div>
|
||||||
|
@ -136,7 +136,7 @@ test( "#6258: not following mouse when scrolled and using overflow-y: scroll", f
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test( "#9315: Draggable: jumps down with offset of scrollbar", function() {
|
test( "#9315: jumps down with offset of scrollbar", function() {
|
||||||
expect( 2 );
|
expect( 2 );
|
||||||
|
|
||||||
var element = $( "#draggable2" ).draggable({
|
var element = $( "#draggable2" ).draggable({
|
||||||
@ -186,6 +186,41 @@ test( "#5009: scroll not working with parent's position fixed", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test( "#9379: Draggable: position bug in scrollable div", function() {
|
||||||
|
expect( 2 );
|
||||||
|
|
||||||
|
$( "#qunit-fixture" ).html( "<div id='o_9379'><div id='i_9379'></div><div id='d_9379'>a</div></div>" );
|
||||||
|
$( "#i_9379" ).css({ position: "absolute", width: "500px", height: "500px" });
|
||||||
|
$( "#o_9379" ).css({ position: "absolute", width: "300px", height: "300px" });
|
||||||
|
$( "#d_9379" ).css({ width: "10px", height: "10px" });
|
||||||
|
|
||||||
|
var moves = 3,
|
||||||
|
startValue = 0,
|
||||||
|
dragDelta = 20,
|
||||||
|
delta = 100,
|
||||||
|
|
||||||
|
// we scroll after each drag event, so subtract 1 from number of moves for expected
|
||||||
|
expected = delta + ( ( moves - 1 ) * dragDelta ),
|
||||||
|
element = $( "#d_9379" ).draggable({
|
||||||
|
drag: function() {
|
||||||
|
startValue += dragDelta;
|
||||||
|
$( "#o_9379" ).scrollTop( startValue ).scrollLeft( startValue );
|
||||||
|
},
|
||||||
|
stop: function( event, ui ) {
|
||||||
|
equal( ui.position.left, expected, "left position is correct when grandparent is scrolled" );
|
||||||
|
equal( ui.position.top, expected, "top position is correct when grandparent is scrolled" );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$( "#o_9379" ).css( "overflow", "auto" );
|
||||||
|
|
||||||
|
element.simulate( "drag", {
|
||||||
|
dy: delta,
|
||||||
|
dx: delta,
|
||||||
|
moves: moves
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test( "#5727: draggable from iframe" , function() {
|
test( "#5727: draggable from iframe" , function() {
|
||||||
expect( 1 );
|
expect( 1 );
|
||||||
|
|
||||||
|
@ -377,7 +377,7 @@ test( "containment, account for border", function() {
|
|||||||
test( "containment, default, switching after initialization", function() {
|
test( "containment, default, switching after initialization", function() {
|
||||||
expect( 6 );
|
expect( 6 );
|
||||||
|
|
||||||
var element = $( "#draggable1" ).draggable({ containment: false });
|
var element = $( "#draggable1" ).draggable({ containment: false, scroll: false });
|
||||||
|
|
||||||
TestHelpers.draggable.testDrag( element, element, -100, -100, -100, -100, "containment: default" );
|
TestHelpers.draggable.testDrag( element, element, -100, -100, -100, -100, "containment: default" );
|
||||||
|
|
||||||
@ -692,7 +692,7 @@ test( "helper, default, switching after initialization", function() {
|
|||||||
scroll: false
|
scroll: false
|
||||||
});
|
});
|
||||||
|
|
||||||
if ( scrollElements.length === 1 && scrollElements[ 1 ] === "#scrollParent" ) {
|
if ( scrollElements.length === 1 && scrollElements[ 0 ] === "#scrollParent" ) {
|
||||||
TestHelpers.draggable.setScrollable( "#main", false );
|
TestHelpers.draggable.setScrollable( "#main", false );
|
||||||
TestHelpers.draggable.setScrollable( "#scrollParent", true );
|
TestHelpers.draggable.setScrollable( "#scrollParent", true );
|
||||||
}
|
}
|
||||||
@ -867,6 +867,8 @@ test( "scroll, scrollSensitivity, and scrollSpeed", function() {
|
|||||||
test( "#6817: auto scroll goes double distance when dragging", function() {
|
test( "#6817: auto scroll goes double distance when dragging", function() {
|
||||||
expect( 2 );
|
expect( 2 );
|
||||||
|
|
||||||
|
TestHelpers.draggable.restoreScroll( document );
|
||||||
|
|
||||||
var offsetBefore,
|
var offsetBefore,
|
||||||
distance = 10,
|
distance = 10,
|
||||||
viewportHeight = $( window ).height(),
|
viewportHeight = $( window ).height(),
|
||||||
@ -906,6 +908,7 @@ test( "snap, snapMode, and snapTolerance", function() {
|
|||||||
snapTolerance = 15,
|
snapTolerance = 15,
|
||||||
element = $( "#draggable1" ).draggable({
|
element = $( "#draggable1" ).draggable({
|
||||||
snap: true,
|
snap: true,
|
||||||
|
scroll: false,
|
||||||
snapMode: "both",
|
snapMode: "both",
|
||||||
snapTolerance: snapTolerance
|
snapTolerance: snapTolerance
|
||||||
}),
|
}),
|
||||||
@ -1028,6 +1031,7 @@ test( "#8459: element can snap to an element that was removed during drag", func
|
|||||||
snapTolerance = 15,
|
snapTolerance = 15,
|
||||||
element = $( "#draggable1" ).draggable({
|
element = $( "#draggable1" ).draggable({
|
||||||
snap: true,
|
snap: true,
|
||||||
|
scroll: false,
|
||||||
snapMode: "both",
|
snapMode: "both",
|
||||||
snapTolerance: snapTolerance,
|
snapTolerance: snapTolerance,
|
||||||
start: function() {
|
start: function() {
|
||||||
|
17
ui/jquery.ui.core.js
vendored
17
ui/jquery.ui.core.js
vendored
@ -55,18 +55,17 @@ $.fn.extend({
|
|||||||
})( $.fn.focus ),
|
})( $.fn.focus ),
|
||||||
|
|
||||||
scrollParent: function() {
|
scrollParent: function() {
|
||||||
var scrollParent;
|
var position = this.css( "position" ),
|
||||||
if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
|
excludeStaticParent = position === "absolute",
|
||||||
scrollParent = this.parents().filter( function() {
|
scrollParent = this.parents().filter( function() {
|
||||||
return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
|
var parent = $( this );
|
||||||
}).eq(0);
|
if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
|
||||||
} else {
|
return false;
|
||||||
scrollParent = this.parents().filter(function() {
|
|
||||||
return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
|
|
||||||
}).eq(0);
|
|
||||||
}
|
}
|
||||||
|
return (/(auto|scroll)/).test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) );
|
||||||
|
}).eq( 0 );
|
||||||
|
|
||||||
return ( /fixed/ ).test( this.css( "position") ) || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
|
return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
|
||||||
},
|
},
|
||||||
|
|
||||||
uniqueId: (function() {
|
uniqueId: (function() {
|
||||||
|
62
ui/jquery.ui.draggable.js
vendored
62
ui/jquery.ui.draggable.js
vendored
@ -334,6 +334,10 @@ $.widget("ui.draggable", $.ui.mouse, {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_isRootNode: function( element ) {
|
||||||
|
return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
|
||||||
|
},
|
||||||
|
|
||||||
_getParentOffset: function() {
|
_getParentOffset: function() {
|
||||||
|
|
||||||
//Get the offsetParent and cache its position
|
//Get the offsetParent and cache its position
|
||||||
@ -349,10 +353,7 @@ $.widget("ui.draggable", $.ui.mouse, {
|
|||||||
po.top += this.scrollParent.scrollTop();
|
po.top += this.scrollParent.scrollTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
//This needs to be actually done for all browsers, since pageX/pageY includes this information
|
if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
|
||||||
//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 };
|
po = { top: 0, left: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,17 +365,18 @@ $.widget("ui.draggable", $.ui.mouse, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_getRelativeOffset: function() {
|
_getRelativeOffset: function() {
|
||||||
|
if ( this.cssPosition !== "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 };
|
return { top: 0, left: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var p = this.element.position(),
|
||||||
|
scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
|
||||||
|
|
||||||
|
return {
|
||||||
|
top: p.top - ( parseInt(this.helper.css( "top" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
|
||||||
|
left: p.left - ( parseInt(this.helper.css( "left" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
|
||||||
|
};
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_cacheMargins: function() {
|
_cacheMargins: function() {
|
||||||
@ -458,31 +460,20 @@ $.widget("ui.draggable", $.ui.mouse, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var mod = d === "absolute" ? 1 : -1,
|
var mod = d === "absolute" ? 1 : -1,
|
||||||
document = this.document[ 0 ],
|
scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
|
||||||
useOffsetParent = this.cssPosition === "absolute" && ( this.scrollParent[ 0 ] === document || !$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ),
|
|
||||||
scroll = useOffsetParent ? this.offsetParent : this.scrollParent,
|
|
||||||
// we need to test if offsetParent was used here because Blink incorrectly reports a 0 scrollTop
|
|
||||||
// on document.documentElement when the page is scrolled. Checking for offsetParent normalizes
|
|
||||||
// this across browsers. Blink bug: https://code.google.com/p/chromium/issues/detail?id=157855
|
|
||||||
scrollIsRootNode = useOffsetParent && ( /(html|body)/i ).test( scroll[ 0 ].nodeName );
|
|
||||||
|
|
||||||
//Cache the scroll
|
|
||||||
if (!this.offset.scroll) {
|
|
||||||
this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
top: (
|
top: (
|
||||||
pos.top + // The absolute mouse position
|
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.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.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
|
||||||
( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod)
|
( ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod)
|
||||||
),
|
),
|
||||||
left: (
|
left: (
|
||||||
pos.left + // The absolute mouse position
|
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.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.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
|
||||||
( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : this.offset.scroll.left ) * mod)
|
( ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -492,19 +483,16 @@ $.widget("ui.draggable", $.ui.mouse, {
|
|||||||
|
|
||||||
var containment, co, top, left,
|
var containment, co, top, left,
|
||||||
o = this.options,
|
o = this.options,
|
||||||
document = this.document[ 0 ],
|
scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
|
||||||
useOffsetParent = this.cssPosition === "absolute" && ( this.scrollParent[ 0 ] === document || !$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ),
|
|
||||||
scroll = useOffsetParent ? this.offsetParent : this.scrollParent,
|
|
||||||
// we need to test if offsetParent was used here because Blink incorrectly reports a 0 scrollTop
|
|
||||||
// on document.documentElement when the page is scrolled. Checking for offsetParent normalizes
|
|
||||||
// this across browsers. Blink bug: https://code.google.com/p/chromium/issues/detail?id=157855
|
|
||||||
scrollIsRootNode = useOffsetParent && ( /(html|body)/i ).test( scroll[ 0 ].nodeName ),
|
|
||||||
pageX = event.pageX,
|
pageX = event.pageX,
|
||||||
pageY = event.pageY;
|
pageY = event.pageY;
|
||||||
|
|
||||||
// Cache the scroll
|
// Cache the scroll
|
||||||
if (!this.offset.scroll) {
|
if ( !scrollIsRootNode || !this.offset.scroll ) {
|
||||||
this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
|
this.offset.scroll = {
|
||||||
|
top: this.scrollParent.scrollTop(),
|
||||||
|
left: this.scrollParent.scrollLeft()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -566,14 +554,14 @@ $.widget("ui.draggable", $.ui.mouse, {
|
|||||||
this.offset.click.top - // Click offset (relative to the element)
|
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.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.offset.parent.top + // The offsetParent's offset without borders (offset + border)
|
||||||
( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
|
( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
|
||||||
),
|
),
|
||||||
left: (
|
left: (
|
||||||
pageX - // The absolute mouse position
|
pageX - // The absolute mouse position
|
||||||
this.offset.click.left - // Click offset (relative to the element)
|
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.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.offset.parent.left + // The offsetParent's offset without borders (offset + border)
|
||||||
( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
|
( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user