Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Position: Added better collision detection for flip and fit and added flipfit. #430

Merged
merged 1 commit into from

2 participants

@kborchers
Owner

Position: Added better collision detection for flip and fit, added visual tests for each and updated the unit tests to take the changes into account. In the process, I removed the rounding that was being done to the position since older jQuery couldn't handle the fractions. There was another pull for this same issue and I have merged the unit tests from that pull into this commit. Also added flipfit!

@jzaefferer
Owner

There's a console.log statement in position_core.js.

Could you add flipfit to the default demo? Add flipfit

The unit tests have 10 failures in IE6 for me, but not the one about fractionals.

That's all I found, the actual collision detection is awesome :-)

@kborchers
Owner

@jzaefferer OK, I think this should do it

@kborchers kborchers Position: Added better collision detection for flip and fit, added vi…
…sual tests for each and updated the unit tests to take the changes into account. In the process, I removed the rounding that was being done to the position since older jQuery couldn't handle the fractions. There was another pull for this same issue and I have merged the unit tests from that pull into this commit. Also added flipfit!
80bbebd
@jzaefferer jzaefferer merged commit 80bbebd into jquery:master
@jzaefferer
Owner

Still getting inconsistent results from unit tests in IEs: IE9 fails on the fractions-test, IE6 produces some other random failsure (7 and 8 pass).

Whatever, just landed it. Let's see what issues popup in when run via TestSwarm, then fix those later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Aug 13, 2011
  1. @kborchers

    Position: Added better collision detection for flip and fit, added vi…

    kborchers authored
    …sual tests for each and updated the unit tests to take the changes into account. In the process, I removed the rounding that was being done to the position since older jQuery couldn't handle the fractions. There was another pull for this same issue and I have merged the unit tests from that pull into this commit. Also added flipfit!
This page is out of date. Refresh to see the latest.
View
2  demos/position/default.html
@@ -142,11 +142,13 @@
<select id="collision_horizontal">
<option value="flip">flip</option>
<option value="fit">fit</option>
+ <option value="flipfit">flipfit</option>
<option value="none">none</option>
</select>
<select id="collision_vertical">
<option value="flip">flip</option>
<option value="fit">fit</option>
+ <option value="flipfit">flipfit</option>
<option value="none">none</option>
</select>
</div>
View
54 tests/unit/position/position.html
@@ -16,7 +16,7 @@
<script src="../testsuite.js"></script>
<script src="position_core.js"></script>
- <script src="position_core_within.js"></script>
+ <script src="position_core_within.js"></script>
<script src="../swarminject.js"></script>
</head>
@@ -36,30 +36,34 @@ <h2 id="qunit-userAgent"></h2>
-->
<div id="qunit-fixture" style="top: 0; left: 0; z-index:1">
- <div id="within-container">
- <div id="el1" style="position: absolute; width: 6px; height: 6px; line-height: 6px;"></div>
- <div id="el2" style="position: absolute; width: 6px; height: 6px; line-height: 6px;"></div>
- <div id="parent" style="position: absolute; width: 6px; height: 6px; top: 4px; left: 4px; line-height: 6px;"></div>
-
- <div style="position: absolute; top: 0px; left: 0px">
- <div id="elx" style="position: absolute; width: 10px; height: 10px; line-height: 10px;"></div>
- <div id="parentx" style="position: absolute; width: 20px; height: 20px; top: 40px; left: 40px;"></div>
- </div>
-
- <div style="position: absolute; top: 200px; left: 100px;">
- <div id="el-offset-100-200" style="position: absolute; width: 10px; height: 10px; line-height: 10px;"></div>
- <div style="position: absolute; top: 100px; left: 50px;">
- <div id="el-two-offset-150-300" style="position: absolute; width: 10px; height: 10px; line-height: 10px;"></div>
- <div id="el-fixed" style="position: fixed; top: 200px; left: 200px;"></div>
- </div>
- </div>
-
- <div style="position: absolute; height: 5000px; width: 5000px;"></div>
-
- <div id="bug-5280" style="height: 30px; width: 201px;">
- <div style="width: 50px; height: 10px;"></div>
- </div>
- </div>
+ <div id="within-container">
+ <div id="el1" style="position: absolute; width: 6px; height: 6px; line-height: 6px;"></div>
+ <div id="el2" style="position: absolute; width: 6px; height: 6px; line-height: 6px;"></div>
+ <div id="parent" style="position: absolute; width: 6px; height: 6px; top: 4px; left: 4px; line-height: 6px;"></div>
+
+ <div style="position: absolute; top: 0px; left: 0px">
+ <div id="elx" style="position: absolute; width: 10px; height: 10px; line-height: 10px;"></div>
+ <div id="parentx" style="position: absolute; width: 20px; height: 20px; top: 40px; left: 40px;"></div>
+ </div>
+
+ <div style="position: absolute; top: 200px; left: 100px;">
+ <div id="el-offset-100-200" style="position: absolute; width: 10px; height: 10px; line-height: 10px;"></div>
+ <div style="position: absolute; top: 100px; left: 50px;">
+ <div id="el-two-offset-150-300" style="position: absolute; width: 10px; height: 10px; line-height: 10px;"></div>
+ <div id="el-fixed" style="position: fixed; top: 200px; left: 200px;"></div>
+ </div>
+ </div>
+
+ <div style="position: absolute; height: 5000px; width: 5000px;"></div>
+
+ <div id="bug-5280" style="height: 30px; width: 201px;">
+ <div style="width: 50px; height: 10px;"></div>
+ </div>
+
+ <div id="fractions-parent" style="position: absolute; left: 10.7432222px; top: 10.532325px; height: 30px; width: 201px;">
+ <div id="fractions-element"></div>
+ </div>
+ </div>
</div>
</body>
View
72 tests/unit/position/position_core.js
@@ -332,28 +332,28 @@ test( "collision: fit, window scrolled", function() {
test( "collision: flip, no offset", function() {
collisionTest({
collision: "flip"
- }, { top: -10, left: -10 }, "left top" );
+ }, { top: $( window ).height(), left: $( window ).width() }, "left top" );
collisionTest2({
collision: "flip"
- }, { top: $( window ).height(), left: $( window ).width() }, "right bottom" );
+ }, { top: -10, left: -10 }, "right bottom" );
});
test( "collision: flip, with offset", function() {
collisionTest({
collision: "flip",
at: "right+2 bottom+3"
- }, { top: -13, left: -12 }, "left top, with offset added" );
+ }, { top: $( window ).height() + 3, left: $( window ).width() + 2 }, "left top, with offset added" );
collisionTest2({
collision: "flip",
at: "left+2 top+3"
- }, { top: $( window ).height() - 3, left: $( window ).width() - 2 }, "bottom, positive offset" );
+ }, { top: -7, left: -8 }, "bottom, positive offset" );
collisionTest2({
collision: "flip",
at: "left-2 top-3"
- }, { top: $( window ).height() + 3, left: $( window ).width() + 2 }, "right bottom, negative offset" );
+ }, { top: -13, left: -12 }, "right bottom, negative offset" );
});
test( "collision: none, no offset", function() {
@@ -427,12 +427,12 @@ test( "collision: flip, with margin", function() {
collisionTest({
collision: "flip",
at: "left top"
- }, { top: $( window ).height() - 10, left: $( window ).width() - 10 }, "left top" );
+ }, { top: 0, left: 0 }, "left top" );
collisionTest2({
collision: "flip",
at: "right bottom"
- }, { top: 0, left: 0 }, "right bottom" );
+ }, { top: $( window ).height() - 10, left: $( window ).width() - 10 }, "right bottom" );
});
test( "addClass: flipped left", function() {
@@ -443,7 +443,7 @@ test( "addClass: flipped left", function() {
at: "right center"
});
- same( elem.hasClass( 'ui-flipped-left' ), true, 'Has ui-flipped-left class' );
+ same( elem.hasClass( 'ui-flipped-left' ), false, 'Has ui-flipped-left class' );
elem.position( {
my: "right center",
@@ -451,7 +451,7 @@ test( "addClass: flipped left", function() {
collision: "flip",
at: "left center"
})
-
+
same( elem.hasClass( 'ui-flipped-left' ), false, 'Removed ui-flipped-left class' );
});
@@ -463,8 +463,8 @@ test( "addClass: flipped top", function() {
at: "right bottom"
});
- same( elem.hasClass( 'ui-flipped-top' ), true, 'Has ui-flipped-top class' );
-
+ same( elem.hasClass( 'ui-flipped-top' ), false, 'Has ui-flipped-top class' );
+
elem.position( {
my: "left bottom",
of: window,
@@ -483,7 +483,7 @@ test( "addClass: flipped right", function() {
at: "left center"
});
- same( elem.hasClass( 'ui-flipped-right' ), true, 'Has ui-flipped-right class' );
+ same( elem.hasClass( 'ui-flipped-right' ), false, 'Has ui-flipped-right class' );
elem.position( {
my: "left center",
@@ -504,8 +504,8 @@ test( "addClass: flipped bottom", function() {
at: "right top"
});
- same( elem.hasClass( 'ui-flipped-bottom' ), true, 'Has ui-flipped-bottom class' );
-
+ same( elem.hasClass( 'ui-flipped-bottom' ), false, 'Has ui-flipped-bottom class' );
+
elem.position( {
my: "left top",
of: window,
@@ -516,22 +516,32 @@ test( "addClass: flipped bottom", function() {
same( elem.hasClass( 'ui-flipped-bottom' ), false, 'Removed ui-flipped-bottom class' );
});
-//test( "bug #5280: consistent results (avoid fractional values)", function() {
-// var wrapper = $( "#bug-5280" ),
-// elem = wrapper.children(),
-// offset1 = elem.position({
-// my: "center",
-// at: "center",
-// of: wrapper,
-// collision: "none"
-// }).offset(),
-// offset2 = elem.position({
-// my: "center",
-// at: "center",
-// of: wrapper,
-// collision: "none"
-// }).offset();
-// same( offset1, offset2 );
-//});
+test( "fractions", function() {
+ $( "#fractions-element" ).position({
+ my: "left top",
+ at: "left top",
+ of: "#fractions-parent",
+ collision: "none"
+ });
+ same( $( "#fractions-element" ).offset(), $( "#fractions-parent" ).offset(), "left top, left top" );
+});
+
+test( "bug #5280: consistent results (avoid fractional values)", function() {
+ var wrapper = $( "#bug-5280" ),
+ elem = wrapper.children(),
+ offset1 = elem.position({
+ my: "center",
+ at: "center",
+ of: wrapper,
+ collision: "none"
+ }).offset(),
+ offset2 = elem.position({
+ my: "center",
+ at: "center",
+ of: wrapper,
+ collision: "none"
+ }).offset();
+ same( offset1, offset2 );
+});
}( jQuery ) );
View
153 tests/unit/position/position_core_within.js
@@ -7,7 +7,7 @@ function scrollTopSupport() {
module( "position - within", {
setup: function(){
- $("#within-container").css({"width": "500px", "height": "500px", "top": "20px", "left": "20px", "position": "relative"}).show();
+ $("#within-container").css({"width": "70px", "height": "70px", "top": "20px", "left": "20px", "position": "relative"}).show();
}
});
@@ -20,13 +20,13 @@ $.fn.addOffsets = function() {
elOffset.top -= offset.top;
elOffset.left -= offset.left;
-
+
return {top: elOffset.top - offset.top, left: elOffset.left - offset.left };
};
test( "my, at, of", function() {
var within = $("#within-container");
-
+
$( "#elx" ).position({
my: "left top",
at: "left top",
@@ -121,7 +121,7 @@ test( "positions", function() {
test( "of", function() {
var within = $("#within-container");
-
+
$( "#elx" ).position({
my: "left top",
at: "left top",
@@ -178,7 +178,7 @@ test( "of", function() {
test( "within:offsets", function() {
var within = $("#within-container");
-
+
$( "#elx" ).position({
my: "left top",
at: "left+10 bottom+10",
@@ -218,7 +218,7 @@ test( "within:offsets", function() {
test( "using", function() {
expect( 6 );
-
+
var within = $("#within-container");
var count = 0,
@@ -226,7 +226,7 @@ test( "using", function() {
expectedPosition = { top: addTop + 40, left: addLeft + 40 },
originalPosition = elems.position({
my: "right bottom",
- at: "rigt bottom",
+ at: "right bottom",
of: "#parentx",
collision: "none",
within: within
@@ -253,14 +253,14 @@ test( "using", function() {
function collisionTest( config, result, msg ) {
var within = $("#within-container");
-
+
var elem = $( "#elx" ).position( $.extend({
my: "left top",
at: "right bottom",
- of: within[0],
+ of: "#parentx",
within: within
}, config ) );
-
+
same( elem.addOffsets(), result, msg );
}
@@ -272,128 +272,136 @@ function collisionTest2( config, result, msg ) {
}
test( "collision: fit, no offset", function() {
- var within = $("#within-container");
-
+ var within = $("#within-container"),
+ of = $("#parentx");
+
collisionTest({
collision: "fit"
- }, { top: addTop + within.height() - 10 - $.position.getScrollInfo( within ).height, left: addLeft + within.width() - 10 - $.position.getScrollInfo( within ).width }, "right bottom" );
+ }, { top: addTop + of.position().top + of.height() - $.position.getScrollInfo( within ).height, left: addLeft + of.position().left + of.width() - $.position.getScrollInfo( within ).width }, "right bottom" );
collisionTest2({
collision: "fit"
- }, { top: addTop + 0, left: addLeft + 0 }, "left top" );
+ }, { top: addTop + of.position().top - 10, left: addLeft + of.position().left - 10 }, "left top" );
});
test( "collision: fit, with offset", function() {
- var within = $("#within-container");
-
+ var within = $("#within-container"),
+ of = $("#parentx");
+
collisionTest({
collision: "fit",
at: "right+2 bottom+3"
- }, { top: addTop + within.height() - 10 - $.position.getScrollInfo( within ).height, left: addLeft + within.width() - 10 - $.position.getScrollInfo( within ).width }, "right bottom");
+ }, { top: addTop + of.position().top + of.height() - $.position.getScrollInfo( within ).height, left: addLeft + of.position().left + of.width() - $.position.getScrollInfo( within ).width }, "right bottom");
collisionTest2({
collision: "fit",
at: "left+2 top+3"
- }, { top: addTop + 0, left: addLeft + 0 }, "left top, positive offset" );
+ }, { top: addTop + of.position().top - 7, left: addLeft + of.position().left - 8 }, "left top, positive offset" );
collisionTest2({
collision: "fit",
at: "left-2 top-3"
- }, { top: addTop + 0, left: addLeft + 0 }, "left top, negative offset" );
+ }, { top: addTop + of.position().top - 13, left: addLeft + of.position().left - 12 }, "left top, negative offset" );
});
-test( "collision: fit, within scrolled", function() {
+test( "collision: none, within scrolled", function() {
if ( scrollTopSupport() ) {
- var within = $("#within-container").css({"width": "1000px", "height": "800px", "overflow": "auto"});
+ var within = $("#within-container").css({"width": "1000px", "height": "800px", "overflow": "auto"}),
+ of = $("#parentx");
within.scrollTop( 300 ).scrollLeft( 150 );
-
+
collisionTest({
- collision: "fit",
+ collision: "none",
at: "left-100 top-100"
- }, { top: addTop, left: addLeft }, "top left" );
+ }, { top: of.offset().top + addTop - 100 - of.height(), left: of.offset().left + addLeft - 100 - of.width() }, "top left" );
collisionTest2({
- collision: "fit",
+ collision: "none",
at: "right+100 bottom+100"
- }, { top: addTop + within.height() - 10 - $.position.getScrollInfo( within ).height, left: addLeft + within.width() - 10 - $.position.getScrollInfo( within ).width }, "right bottom" );
+ }, { top: of.offset().top + addTop + 100 - 10, left: of.offset().left + addLeft + 100 - 10 }, "right bottom" );
within.scrollTop( 0 ).scrollLeft( 0 );
}
});
-
+
test( "collision: flip, no offset", function() {
- var within = $("#within-container");
-
+ var within = $("#within-container"),
+ of = $("#parentx");
+
collisionTest({
collision: "flip"
- }, { top: addTop + -10, left: addLeft + -10 }, "left top" );
+ }, { top: addTop + of.position().top + of.height(), left: addLeft + of.position().left + of.width() }, "left top" );
collisionTest2({
collision: "flip"
- }, { top: addTop + within.height(), left: addLeft + within.width() }, "right bottom" );
+ }, { top: addTop + of.position().top - 10, left: addTop + of.position().top - 10 }, "right bottom" );
});
test( "collision: flip, with offset", function() {
- var within = $("#within-container");
-
+ var within = $("#within-container"),
+ of = $("#parentx");
+
collisionTest({
collision: "flip",
at: "right+2 bottom+3"
- }, { top: addTop + -13, left: addLeft + -12 }, "left top, with offset added" );
+ }, { top: addTop + of.position().top - 13, left: addLeft + of.position().left - 12 }, "left top, with offset added" );
collisionTest2({
collision: "flip",
at: "left+2 top+3"
- }, { top: addTop + within.height() - 3, left: addLeft + within.width() - 2 }, "bottom, positive offset" );
+ }, { top: addTop + of.position().top - 10 + 3, left: addLeft + of.position().left - 10 + 2 }, "right bottom, positive offset" );
collisionTest2({
collision: "flip",
at: "left-2 top-3"
- }, { top: addTop + within.height() + 3, left: addLeft + within.width() + 2 }, "right bottom, negative offset" );
+ }, { top: addTop + of.position().top - 13, left: addLeft + of.position().left - 12 }, "right bottom, negative offset" );
});
test( "collision: none, no offset", function() {
- var within = $("#within-container");
-
+ var within = $("#within-container"),
+ of = $("#parentx");
+
collisionTest({
collision: "none"
- }, { top: addTop + within.height(), left: addLeft + within.width() }, "left top" );
+ }, { top: addTop + of.position().top + of.height(), left: addLeft + of.position().left + of.width() }, "left top" );
collisionTest2({
collision: "none"
- }, { top: addTop + -10, left: addLeft + -10 }, "moved to the right bottom" );
+ }, { top: addTop + of.position().top - 10, left: addLeft + of.position().left - 10 }, "right bottom" );
});
test( "collision: none, with offset", function() {
- var within = $("#within-container");
-
+ var within = $("#within-container"),
+ of = $("#parentx");
+
collisionTest({
collision: "none",
at: "right+2 bottom+3"
- }, { top: addTop + within.height() + 3, left: addLeft + within.width() + 2 }, "right bottom, with offset added" );
+ }, { top: addTop + of.position().top + of.height() + 3, left: addLeft + of.position().left + of.width() + 2 }, "right bottom, with offset added" );
collisionTest2({
collision: "none",
at: "left+2 top+3"
- }, { top: addTop + -7, left: addLeft + -8 }, "left top, positive offset" );
+ }, { top: addTop + of.position().top - 7, left: addTop + of.position().top - 8 }, "left top, positive offset" );
collisionTest2({
collision: "none",
at: "left-2 top-3"
- }, { top: addTop + -13, left: addLeft + -12 }, "left top, negative offset" );
+ }, { top: addTop + of.position().top - 13, left: addTop + of.position().top - 12 }, "left top, negative offset" );
});
test( "collision: fit, with margin", function() {
- var within = $("#within-container");
-
+ var within = $("#within-container"),
+ of = $("#parentx");
+
$( "#elx" ).css( "margin", 10 );
collisionTest({
collision: "fit"
- }, { top: addTop + within.height() - 20 - $.position.getScrollInfo( within ).height, left: addLeft + within.width() - 20 - $.position.getScrollInfo( within ).width }, "right bottom" );
+ }, { top: addTop + of.position().top + of.height() - 10 - $.position.getScrollInfo( within ).height, left: addLeft + of.position().left + of.width() - 10 - $.position.getScrollInfo( within ).width }, "right bottom" );
collisionTest2({
collision: "fit"
- }, { top: addTop + 10, left: addLeft + 10 }, "left top" );
+ }, { top: addTop + of.position().top - 10, left: addLeft + of.position().left - 10 }, "left top" );
$( "#elx" ).css({
"margin-left": 5,
@@ -402,11 +410,11 @@ test( "collision: fit, with margin", function() {
collisionTest({
collision: "fit"
- }, { top: addTop + within.height() - 20 - $.position.getScrollInfo( within ).height, left: addLeft + within.width() - 20 - $.position.getScrollInfo( within ).width }, "right bottom" );
+ }, { top: addTop + of.position().top + of.height() - 10 - $.position.getScrollInfo( within ).height, left: addLeft + of.position().left + of.width() - 10 - $.position.getScrollInfo( within ).width }, "right bottom" );
collisionTest2({
collision: "fit"
- }, { top: addTop + 5, left: addLeft + 5 }, "left top" );
+ }, { top: addTop + of.position().top - 10, left: addLeft + of.position().left - 10 }, "left top" );
$( "#elx" ).css({
"margin-right": 15,
@@ -415,32 +423,33 @@ test( "collision: fit, with margin", function() {
collisionTest({
collision: "fit"
- }, { top: addTop + within.height() - 25 - $.position.getScrollInfo( within ).height, left: addLeft + within.width() - 25 - $.position.getScrollInfo( within ).width }, "right bottom" );
+ }, { top: addTop + of.position().top + of.height() - 15 - $.position.getScrollInfo( within ).height, left: addLeft + of.position().left + of.width() - 15 - $.position.getScrollInfo( within ).width }, "right bottom" );
collisionTest2({
collision: "fit"
- }, { top: addTop + 5, left: addLeft + 5 }, "left top" );
+ }, { top: addTop + of.position().top - 10, left: addLeft + of.position().left - 10 }, "left top" );
});
test( "collision: flip, with margin", function() {
- var within = $("#within-container");
-
+ var within = $("#within-container"),
+ of = $("#parentx");
+
$( "#elx" ).css( "margin", 10 );
collisionTest({
- collision: "flip",
- at: "left top"
- }, { top: addTop + within.height() - 10, left: addLeft + within.width() - 10 }, "left top" );
+ collision: "flip"
+ }, { top: addTop + of.position().top - 10, left: addLeft + of.position().left - 10 }, "left top" );
collisionTest2({
- collision: "flip",
- at: "right bottom"
- }, { top: addTop + 0, left: addLeft + 0 }, "right bottom" );
+ collision: "flip"
+ }, { top: addTop + of.position().top - 10, left: addLeft + of.position().left - 10 }, "right bottom" );
+
+ $( "#elx" ).css( "margin", 0 );
});
test( "addClass: flipped left", function() {
var within = $("#within-container");
-
+
var elem = $( "#elx" ).position( {
my: "left center",
of: within[0],
@@ -449,7 +458,7 @@ test( "addClass: flipped left", function() {
at: "right center"
});
- same( elem.hasClass( 'ui-flipped-left' ), true, 'Has ui-flipped-left class' );
+ same( elem.hasClass( 'ui-flipped-left' ), false, 'Has ui-flipped-left class' );
elem.position( {
my: "right center",
@@ -458,13 +467,13 @@ test( "addClass: flipped left", function() {
collision: "flip",
at: "left center"
})
-
+
same( elem.hasClass( 'ui-flipped-left' ), false, 'Removed ui-flipped-left class' );
});
test( "addClass: flipped top", function() {
var within = $("#within-container");
-
+
var elem = $( "#elx" ).position( {
my: "left top",
of: within[0],
@@ -473,8 +482,8 @@ test( "addClass: flipped top", function() {
at: "right bottom"
});
- same( elem.hasClass( 'ui-flipped-top' ), true, 'Has ui-flipped-top class' );
-
+ same( elem.hasClass( 'ui-flipped-top' ), false, 'Has ui-flipped-top class' );
+
elem.position( {
my: "left bottom",
of: within[0],
@@ -488,7 +497,7 @@ test( "addClass: flipped top", function() {
test( "addClass: flipped right", function() {
var within = $("#within-container");
-
+
var elem = $( "#elx" ).position( {
my: "right center",
of: within[0],
@@ -497,7 +506,7 @@ test( "addClass: flipped right", function() {
at: "left center"
});
- same( elem.hasClass( 'ui-flipped-right' ), true, 'Has ui-flipped-right class' );
+ same( elem.hasClass( 'ui-flipped-right' ), false, 'Has ui-flipped-right class' );
elem.position( {
my: "left center",
@@ -513,7 +522,7 @@ test( "addClass: flipped right", function() {
test( "addClass: flipped bottom", function() {
var within = $("#within-container");
-
+
var elem = $( "#elx" ).position( {
my: "left bottom",
of: window,
@@ -521,8 +530,8 @@ test( "addClass: flipped bottom", function() {
at: "right top"
});
- same( elem.hasClass( 'ui-flipped-bottom' ), true, 'Has ui-flipped-bottom class' );
-
+ same( elem.hasClass( 'ui-flipped-bottom' ), false, 'Has ui-flipped-bottom class' );
+
elem.position( {
my: "left top",
of: window,
View
148 tests/visual/position/position_fit.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>Position Visual Test: Fit</title>
+ <link rel="stylesheet" href="../visual.css" type="text/css" />
+ <link rel="stylesheet" href="../../../themes/base/jquery.ui.all.css" type="text/css" title="ui-theme" />
+ <script type="text/javascript" src="../../../jquery-1.6.2.js"></script>
+ <script type="text/javascript" src="../../../ui/jquery.ui.core.js"></script>
+ <script type="text/javascript" src="../../../ui/jquery.ui.widget.js"></script>
+ <script type="text/javascript" src="../../../ui/jquery.ui.position.js"></script>
+ <script type="text/javascript" src="../../../ui/jquery.ui.menu.js"></script>
+ <script type="text/javascript" src="http://jqueryui.com/themeroller/themeswitchertool/"></script>
+ <script type="text/javascript">
+ $(function() {
+ var inputs = $("input");
+ $("ul").insertAfter(inputs);
+ inputs.each(function(index) {
+ $(this).position({
+ my: this.id.replace(/-/, " "),
+ at: this.id.replace(/-/, " "),
+ of: "#container"+index,
+ collision: "none"
+ });
+ if(index < 3) {
+ $(this).next().menu().position({
+ my: "left top",
+ at: "left bottom",
+ of: this,
+ within: "#container"+index,
+ collision: "fit"
+ });
+ }
+ if(index >= 3 && index < 6) {
+ $(this).next().menu().position({
+ my: "right top",
+ at: "right bottom",
+ of: this,
+ within: "#container"+index,
+ collision: "fit"
+ });
+ }
+ if(index >= 6 && index < 9) {
+ $(this).next().menu().position({
+ my: "center top",
+ at: "center bottom",
+ of: this,
+ within: "#container"+index,
+ collision: "fit"
+ });
+ }
+ if(index >= 9 && index < 12) {
+ $(this).next().menu().position({
+ my: "left top",
+ at: "left bottom",
+ of: this,
+ within: "#container"+index,
+ collision: "fit"
+ });
+ }
+ if(index >= 12 && index < 15) {
+ $(this).next().menu().position({
+ my: "center center",
+ at: "center center",
+ of: this,
+ within: "#container"+index,
+ collision: "fit"
+ });
+ }
+ if(index >= 15) {
+ $(this).next().menu().position({
+ my: "left bottom",
+ at: "left top",
+ of: this,
+ within: "#container"+index,
+ collision: "fit"
+ });
+ }
+ });
+ });
+ </script>
+ <style>
+ input, .ui-menu { position: absolute; }
+ .ui-menu { width: 300px; }
+ #ui-menu-9, #ui-menu-10, #ui-menu-11, #ui-menu-12, #ui-menu-13, #ui-menu-14, #ui-menu-15, #ui-menu-16, #ui-menu-17 { width: auto; }
+ html, body { width: 99%; height: 99%; min-height:700px; min-width:700px; }
+ .container { width: 200px; height: 200px; border: 1px solid black; display:inline-block; margin-left: 230px; margin-top: 15px; margin-bottom: 135px; }
+ .container2 { width: 200px; height: 100px; border: 1px solid black; display:inline-block; margin-left: 230px; margin-top: 15px; margin-bottom: 135px; }
+ </style>
+</head>
+<body>
+
+<div id="container0" class="container"></div>
+<div id="container1" class="container"></div>
+<div id="container2" class="container"></div>
+<div style="clear:both;"></div>
+<div id="container3" class="container"></div>
+<div id="container4" class="container"></div>
+<div id="container5" class="container"></div>
+<div style="clear:both;"></div>
+<div id="container6" class="container"></div>
+<div id="container7" class="container"></div>
+<div id="container8" class="container"></div>
+<div style="clear:both;"></div>
+<div id="container9" class="container2"></div>
+<div id="container10" class="container2"></div>
+<div id="container11" class="container2"></div>
+<div style="clear:both;"></div>
+<div id="container12" class="container2"></div>
+<div id="container13" class="container2"></div>
+<div id="container14" class="container2"></div>
+<div style="clear:both;"></div>
+<div id="container15" class="container2"></div>
+<div id="container16" class="container2"></div>
+<div id="container17" class="container2"></div>
+
+<input id="left-top" />
+<input id="center-top" />
+<input id="right-top" />
+<input id="left-top" />
+<input id="center-top" />
+<input id="right-top" />
+<input id="left-top" />
+<input id="center-top" />
+<input id="right-top" />
+
+<input id="left-top" />
+<input id="center-center" />
+<input id="right-bottom" />
+<input id="left-top" />
+<input id="center-center" />
+<input id="right-bottom" />
+<input id="left-top" />
+<input id="center-center" />
+<input id="right-bottom" />
+
+<ul>
+ <li><a href="#">Java</a></li>
+ <li><a href="#">JavaScript</a></li>
+ <li><a href="#">Perl</a></li>
+ <li><a href="#">Ruby</a></li>
+ <li><a href="#">C++</a></li>
+ <li><a href="#">Python</a></li>
+ <li><a href="#">C#</a></li>
+</ul>
+
+</body>
+</html>
View
77 tests/visual/position/position_flip.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>Position Visual Test: Flip</title>
+ <link rel="stylesheet" href="../visual.css" type="text/css" />
+ <link rel="stylesheet" href="../../../themes/base/jquery.ui.all.css" type="text/css" title="ui-theme" />
+ <script type="text/javascript" src="../../../jquery-1.6.2.js"></script>
+ <script type="text/javascript" src="../../../ui/jquery.ui.core.js"></script>
+ <script type="text/javascript" src="../../../ui/jquery.ui.widget.js"></script>
+ <script type="text/javascript" src="../../../ui/jquery.ui.position.js"></script>
+ <script type="text/javascript" src="../../../ui/jquery.ui.menu.js"></script>
+ <script type="text/javascript" src="http://jqueryui.com/themeroller/themeswitchertool/"></script>
+ <script type="text/javascript">
+ $(function() {
+ var inputs = $("input");
+ $("ul").insertAfter(inputs);
+ inputs.each(function(index) {
+ $(this).position({
+ my: this.id.replace(/-/, " "),
+ at: this.id.replace(/-/, " "),
+ of: "#container"+index,
+ collision: "none"
+ });
+ $(this).next().menu().position({
+ my: "left top",
+ at: "left bottom",
+ of: this,
+ within: "#container"+index
+ });
+ });
+ });
+ </script>
+ <style>
+ input, .ui-menu { position: absolute; }
+ .ui-menu { width: 300px; }
+ #ui-menu-6, #ui-menu-7, #ui-menu-8 { width: auto; }
+ html, body { width: 99%; height: 99%; min-height:700px; min-width:700px; }
+ .container { width: 200px; height: 200px; border: 1px solid black; display:inline-block; margin-left: 230px; margin-top: 150px; }
+ </style>
+</head>
+<body>
+
+<div id="container0" class="container"></div>
+<div id="container1" class="container"></div>
+<div id="container2" class="container"></div><br>
+<div style="clear:both;"></div>
+<div id="container3" class="container" style="width:300px;"></div>
+<div id="container4" class="container" style="width:300px;"></div>
+<div id="container5" class="container" style="width:300px;"></div>
+<div style="clear:both;"></div>
+<div id="container6" class="container" style="height:100px; margin-bottom: 500px;"></div>
+<div id="container7" class="container" style="height:100px; margin-bottom: 500px;"></div>
+<div id="container8" class="container" style="height:100px; margin-bottom: 500px;"></div>
+
+<input id="left-top" />
+<input id="center-top" />
+<input id="right-top" />
+<input id="left-center" />
+<input id="center-center" />
+<input id="right-center" />
+<input id="left-bottom" />
+<input id="center-center" />
+<input id="right-bottom" />
+
+<ul>
+ <li><a href="#">Java</a></li>
+ <li><a href="#">JavaScript</a></li>
+ <li><a href="#">Perl</a></li>
+ <li><a href="#">Ruby</a></li>
+ <li><a href="#">C++</a></li>
+ <li><a href="#">Python</a></li>
+ <li><a href="#">C#</a></li>
+</ul>
+
+</body>
+</html>
View
86 tests/visual/position/position_flipfit.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>Position Visual Test: FlipFit</title>
+ <link rel="stylesheet" href="../visual.css" type="text/css" />
+ <link rel="stylesheet" href="../../../themes/base/jquery.ui.all.css" type="text/css" title="ui-theme" />
+ <script type="text/javascript" src="../../../jquery-1.6.2.js"></script>
+ <script type="text/javascript" src="../../../ui/jquery.ui.core.js"></script>
+ <script type="text/javascript" src="../../../ui/jquery.ui.widget.js"></script>
+ <script type="text/javascript" src="../../../ui/jquery.ui.position.js"></script>
+ <script type="text/javascript" src="../../../ui/jquery.ui.menu.js"></script>
+ <script type="text/javascript" src="http://jqueryui.com/themeroller/themeswitchertool/"></script>
+ <script type="text/javascript">
+ $(function() {
+ var inputs = $("input");
+ $("ul").insertAfter(inputs);
+ inputs.each(function(index) {
+ $(this).position({
+ my: this.id.replace(/-/, " "),
+ at: this.id.replace(/-/, " "),
+ of: "#container"+index,
+ collision: "none"
+ });
+ $(this).next().menu().position({
+ my: index > 2 && index < 6 ? "right top" : "left top",
+ at: index > 2 && index < 6 ? "right bottom" : "left bottom",
+ of: this,
+ within: "#container"+index,
+ collision: "flipfit"
+ });
+ });
+ });
+ </script>
+ <style>
+ input, .ui-menu { position: absolute; }
+ .ui-menu { width: 300px; }
+ #ui-menu-3, #ui-menu-4, #ui-menu-5 { width: 185px; }
+ #ui-menu-9, #ui-menu-10, #ui-menu-11 { width: auto; }
+ html, body { width: 99%; height: 99%; min-height:700px; min-width:700px; }
+ .container { width: 200px; height: 200px; border: 1px solid black; display:inline-block; margin-left: 230px; margin-top: 150px; }
+ </style>
+</head>
+<body>
+
+<div id="container0" class="container"></div>
+<div id="container1" class="container"></div>
+<div id="container2" class="container"></div><br>
+<div style="clear:both;"></div>
+<div id="container3" class="container"></div>
+<div id="container4" class="container"></div>
+<div id="container5" class="container"></div><br>
+<div style="clear:both;"></div>
+<div id="container6" class="container" style="width:300px;"></div>
+<div id="container7" class="container" style="width:300px;"></div>
+<div id="container8" class="container" style="width:300px;"></div>
+<div style="clear:both;"></div>
+<div id="container9" class="container" style="height:100px; margin-bottom: 500px;"></div>
+<div id="container10" class="container" style="height:100px; margin-bottom: 500px;"></div>
+<div id="container11" class="container" style="height:100px; margin-bottom: 500px;"></div>
+
+<input id="left-top" />
+<input id="center-top" />
+<input id="right-top" />
+<input id="left-top" />
+<input id="center-top" />
+<input id="right-top" />
+<input id="left-center" />
+<input id="center-center" />
+<input id="right-center" />
+<input id="left-bottom" />
+<input id="center-center" />
+<input id="right-bottom" />
+
+<ul>
+ <li><a href="#">Java</a></li>
+ <li><a href="#">JavaScript</a></li>
+ <li><a href="#">Perl</a></li>
+ <li><a href="#">Ruby</a></li>
+ <li><a href="#">C++</a></li>
+ <li><a href="#">Python</a></li>
+ <li><a href="#">C#</a></li>
+</ul>
+
+</body>
+</html>
View
172 ui/jquery.ui.position.js
@@ -39,15 +39,16 @@ $.position = {
return w1 - w2;
},
- getScrollInfo: function( within ) {
- var that = within[0],
- scrollHeight = within.height() < that.scrollHeight,
- scrollWidth = within.width() < that.scrollWidth,
- scrollbarWidth = $.position.scrollbarWidth();
+ getScrollInfo: function(within) {
+ var notWindow = within[0] !== window,
+ overflowX = notWindow ? within.css( "overflow-x" ) : "",
+ overflowY = notWindow ? within.css( "overflow-y" ) : "",
+ scrollbarWidth = overflowX === "auto" || overflowX === "scroll" ? $.position.scrollbarWidth() : 0,
+ scrollbarHeight = overflowY === "auto" || overflowY === "scroll" ? $.position.scrollbarWidth() : 0;
return {
- height: scrollHeight ? scrollbarWidth : 0,
- width : scrollWidth ? scrollbarWidth : 0
+ height: within.height() < within[0].scrollHeight ? scrollbarHeight : 0,
+ width: within.width() < within[0].scrollWidth ? scrollbarWidth : 0
};
}
};
@@ -182,13 +183,9 @@ $.fn.position = function( options ) {
position.left += myOffset[ 0 ];
position.top += myOffset[ 1 ];
- // prevent fractions (see #5280)
- position.left = Math.round( position.left );
- position.top = Math.round( position.top );
-
collisionPosition = {
- left: position.left - marginLeft,
- top: position.top - marginTop
+ marginLeft: marginLeft,
+ marginTop: marginTop
};
$.each( [ "left", "top" ], function( i, dir ) {
@@ -225,18 +222,38 @@ $.ui.position = {
isWindow = $.isWindow( data.within[0] ),
withinOffset = isWindow ? win.scrollLeft() : within.offset().left,
outerWidth = isWindow ? win.width() : within.outerWidth(),
- overLeft = withinOffset - data.collisionPosition.left,
- overRight = data.collisionPosition.left + data.collisionWidth - outerWidth - withinOffset;
-
- // element is wider than window or too far left -> align with left edge
- if ( data.collisionWidth > outerWidth || overLeft > 0 ) {
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
+ overLeft = withinOffset - collisionPosLeft,
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
+ newOverRight,
+ newOverLeft;
+
+ // element is wider than within
+ if ( data.collisionWidth > outerWidth ) {
+ // element is initially over the left side of within
+ if ( overLeft > 0 && overRight <= 0 ) {
+ newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
+ position.left += overLeft - newOverRight;
+ // element is initially over right side of within
+ } else if ( overRight > 0 && overLeft <= 0 ) {
+ position.left = withinOffset;
+ // element is initially over both left and right sides of within
+ } else {
+ if ( overLeft > overRight ) {
+ position.left = withinOffset + outerWidth - data.collisionWidth;
+ } else {
+ position.left = withinOffset;
+ }
+ }
+ // too far left -> align with left edge
+ } else if ( overLeft > 0 ) {
position.left += overLeft;
// too far right -> align with right edge
} else if ( overRight > 0 ) {
position.left -= overRight;
// adjust based on position and margin
} else {
- position.left = Math.max( position.left - data.collisionPosition.left, position.left );
+ position.left = Math.max( position.left - collisionPosLeft, position.left );
}
},
top: function( position, data ) {
@@ -245,18 +262,38 @@ $.ui.position = {
isWindow = $.isWindow( data.within[0] ),
withinOffset = isWindow ? win.scrollTop() : within.offset().top,
outerHeight = isWindow ? win.height() : within.outerHeight(),
- overTop = withinOffset - data.collisionPosition.top,
- overBottom = data.collisionPosition.top + data.collisionHeight - outerHeight - withinOffset;
-
- // element is taller than window or too far up -> align with top edge
- if ( data.collisionHeight > outerHeight || overTop > 0 ) {
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
+ overTop = withinOffset - collisionPosTop,
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
+ newOverTop,
+ newOverBottom;
+
+ // element is taller than within
+ if ( data.collisionHeight > outerHeight ) {
+ // element is initially over the top of within
+ if ( overTop > 0 && overBottom <= 0 ) {
+ newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
+ position.top += overTop - newOverBottom;
+ // element is initially over bottom of within
+ } else if ( overBottom > 0 && overTop <= 0 ) {
+ position.top = withinOffset;
+ // element is initially over both top and bottom of within
+ } else {
+ if ( overTop > overBottom ) {
+ position.top = withinOffset + outerHeight - data.collisionHeight;
+ } else {
+ position.top = withinOffset;
+ }
+ }
+ // too far up -> align with top
+ } else if ( overTop > 0 ) {
position.top += overTop;
// too far down -> align with bottom edge
} else if ( overBottom > 0 ) {
position.top -= overBottom;
// adjust based on position and margin
} else {
- position.top = Math.max( position.top - data.collisionPosition.top, position.top );
+ position.top = Math.max( position.top - collisionPosTop, position.top );
}
}
},
@@ -268,14 +305,15 @@ $.ui.position = {
data.elem
.removeClass( "ui-flipped-left ui-flipped-right" );
-
+
var within = data.within,
win = $( window ),
isWindow = $.isWindow( data.within[0] ),
- withinOffset = isWindow ? 0 : within.offset().left,
+ withinOffset = ( isWindow ? 0 : within.offset().left ) + within.scrollLeft(),
outerWidth = isWindow ? within.width() : within.outerWidth(),
- overLeft = data.collisionPosition.left - withinOffset,
- overRight = data.collisionPosition.left + data.collisionWidth - outerWidth - withinOffset,
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
+ overLeft = collisionPosLeft - withinOffset,
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
left = data.my[ 0 ] === "left",
myOffset = data.my[ 0 ] === "left" ?
-data.elemWidth :
@@ -285,30 +323,45 @@ $.ui.position = {
atOffset = data.at[ 0 ] === "left" ?
data.targetWidth :
-data.targetWidth,
- offset = -2 * data.offset[ 0 ];
- if ( overLeft < 0 || overRight > 0 ) {
-
- data.elem
- .addClass( "ui-flipped-" + ( overLeft < 0 ? "right" : "left" ) );
-
- position.left += myOffset + atOffset + offset;
+ offset = -2 * data.offset[ 0 ],
+ newOverRight,
+ newOverLeft;
+
+ if ( overLeft < 0 ) {
+ newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
+ if ( newOverRight < 0 || newOverRight < Math.abs( overLeft ) ) {
+ data.elem
+ .addClass( "ui-flipped-right" );
+
+ position.left += myOffset + atOffset + offset;
+ }
+ }
+ else if ( overRight > 0 ) {
+ newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - withinOffset;
+ if ( newOverLeft > 0 || Math.abs( newOverLeft ) < overRight ) {
+ data.elem
+ .addClass( "ui-flipped-left" );
+
+ position.left += myOffset + atOffset + offset;
+ }
}
},
top: function( position, data ) {
if ( data.at[ 1 ] === center ) {
return;
}
-
+
data.elem
.removeClass( "ui-flipped-top ui-flipped-bottom" );
-
+
var within = data.within,
win = $( window ),
isWindow = $.isWindow( data.within[0] ),
- withinOffset = isWindow ? 0 : within.offset().top,
+ withinOffset = ( isWindow ? 0 : within.offset().top ) + within.scrollTop(),
outerHeight = isWindow ? within.height() : within.outerHeight(),
- overTop = data.collisionPosition.top - withinOffset,
- overBottom = data.collisionPosition.top + data.collisionHeight - outerHeight - withinOffset,
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
+ overTop = collisionPosTop - withinOffset,
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
top = data.my[ 1 ] === "top",
myOffset = top ?
-data.elemHeight :
@@ -318,14 +371,37 @@ $.ui.position = {
atOffset = data.at[ 1 ] === "top" ?
data.targetHeight :
-data.targetHeight,
- offset = -2 * data.offset[ 1 ];
- if ( overTop < 0 || overBottom > 0 ) {
-
- data.elem
- .addClass( "ui-flipped-" + ( overTop < 0 ? "bottom" : "top" ) );
-
- position.top += myOffset + atOffset + offset;
+ offset = -2 * data.offset[ 1 ],
+ newOverTop,
+ newOverBottom;
+ if ( overTop < 0 ) {
+ newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
+ if ( newOverBottom < 0 || newOverBottom < Math.abs( overTop ) ) {
+ data.elem
+ .addClass( "ui-flipped-bottom" );
+
+ position.top += myOffset + atOffset + offset;
+ }
}
+ else if ( overBottom > 0 ) {
+ newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - withinOffset;
+ if ( newOverTop > 0 || Math.abs( newOverTop ) < overBottom ) {
+ data.elem
+ .addClass( "ui-flipped-top" );
+
+ position.top += myOffset + atOffset + offset;
+ }
+ }
+ }
+ },
+ flipfit: {
+ left: function() {
+ $.ui.position.flip.left.apply( this, arguments );
+ $.ui.position.fit.left.apply( this, arguments );
+ },
+ top: function() {
+ $.ui.position.flip.top.apply( this, arguments );
+ $.ui.position.fit.top.apply( this, arguments );
}
}
};
Something went wrong with that request. Please try again.