]> source.dussan.org Git - jquery-ui.git/commitdiff
Position: Added better collision detection for flip and fit, added visual tests for... 430/head
authorkborchers <kris.borchers@gmail.com>
Sat, 13 Aug 2011 03:19:52 +0000 (22:19 -0500)
committerkborchers <kris.borchers@gmail.com>
Sat, 13 Aug 2011 03:19:52 +0000 (22:19 -0500)
demos/position/default.html
tests/unit/position/position.html
tests/unit/position/position_core.js
tests/unit/position/position_core_within.js
tests/visual/position/position_fit.html [new file with mode: 0644]
tests/visual/position/position_flip.html [new file with mode: 0644]
tests/visual/position/position_flipfit.html [new file with mode: 0644]
ui/jquery.ui.position.js

index 6a753e2f16f52a9cae07f77fa6e76b71aab53c0b..f7cba888d623fdc2e06525c1797c138febd3a79f 100644 (file)
                <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>
index a47e910049bc9964b4c5350cda40eee3798db1a9..a3a97911ca8f2d6ecb0ca17dec6f3a21ca00290c 100644 (file)
@@ -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>
index fd6e643e9046c99106491621822c67a75397631b..ea1baee72fdf752dc478dccbc3c2ed83b555e4e0 100644 (file)
@@ -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 ) );
index bfb913335dcb1c3396ad322aea4d1a70626ed5db..392e409c5588db198bfedc49fc8ff9b3766ccd41 100644 (file)
@@ -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 (file)
index 0000000..a95fa9e
--- /dev/null
@@ -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 (file)
index 0000000..f4a3849
--- /dev/null
@@ -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 (file)
index 0000000..89ead10
--- /dev/null
@@ -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>
index 23a98b491079ccae8d9125d600bf23caa5860faf..24a033fc212758dd01608a44e763d4cc3f3b52d5 100644 (file)
@@ -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 );
                }
        }
 };