diff options
author | kborchers <kris.borchers@gmail.com> | 2011-08-12 22:19:52 -0500 |
---|---|---|
committer | kborchers <kris.borchers@gmail.com> | 2011-08-12 22:19:52 -0500 |
commit | 80bbebd4893ca0d75d556553a74550d01f52892f (patch) | |
tree | dabf8003668671617441d275d7f15200fed9042a | |
parent | ac04462d22d30f4b1a5e0dd34d57fbcc0450b48d (diff) | |
download | jquery-ui-80bbebd4893ca0d75d556553a74550d01f52892f.tar.gz jquery-ui-80bbebd4893ca0d75d556553a74550d01f52892f.zip |
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!
-rw-r--r-- | demos/position/default.html | 2 | ||||
-rw-r--r-- | tests/unit/position/position.html | 54 | ||||
-rw-r--r-- | tests/unit/position/position_core.js | 72 | ||||
-rw-r--r-- | tests/unit/position/position_core_within.js | 153 | ||||
-rw-r--r-- | tests/visual/position/position_fit.html | 148 | ||||
-rw-r--r-- | tests/visual/position/position_flip.html | 77 | ||||
-rw-r--r-- | tests/visual/position/position_flipfit.html | 86 | ||||
-rw-r--r-- | ui/jquery.ui.position.js | 172 |
8 files changed, 588 insertions, 176 deletions
diff --git a/demos/position/default.html b/demos/position/default.html index 6a753e2f1..f7cba888d 100644 --- a/demos/position/default.html +++ b/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> diff --git a/tests/unit/position/position.html b/tests/unit/position/position.html index a47e91004..a3a97911c 100644 --- a/tests/unit/position/position.html +++ b/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 @@ elements smaller than 10px have a line-height set on them to avoid a bug in IE6 --> <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> diff --git a/tests/unit/position/position_core.js b/tests/unit/position/position_core.js index fd6e643e9..ea1baee72 100644 --- a/tests/unit/position/position_core.js +++ b/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 ) ); diff --git a/tests/unit/position/position_core_within.js b/tests/unit/position/position_core_within.js index bfb913335..392e409c5 100644 --- a/tests/unit/position/position_core_within.js +++ b/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, diff --git a/tests/visual/position/position_fit.html b/tests/visual/position/position_fit.html new file mode 100644 index 000000000..a95fa9e01 --- /dev/null +++ b/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> diff --git a/tests/visual/position/position_flip.html b/tests/visual/position/position_flip.html new file mode 100644 index 000000000..f4a3849ef --- /dev/null +++ b/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> diff --git a/tests/visual/position/position_flipfit.html b/tests/visual/position/position_flipfit.html new file mode 100644 index 000000000..89ead1098 --- /dev/null +++ b/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> diff --git a/ui/jquery.ui.position.js b/ui/jquery.ui.position.js index 23a98b491..24a033fc2 100644 --- a/ui/jquery.ui.position.js +++ b/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 ); } } }; |