]> source.dussan.org Git - jquery.git/commitdiff
CSS: Avoid unit-conversion interference from CSS upper bounds
authorRichard Gibson <richard.gibson@gmail.com>
Mon, 28 Aug 2017 17:23:04 +0000 (13:23 -0400)
committerGitHub <noreply@github.com>
Mon, 28 Aug 2017 17:23:04 +0000 (13:23 -0400)
Fixes gh-2144
Closes gh-3745

src/css/adjustCSS.js
test/unit/css.js
test/unit/effects.js

index ded3a16667177f5b6c8508ab3ae0e9e54fddc963..626ec74758f2d04e56bafed9932efb2d8cd8cbf2 100644 (file)
@@ -6,8 +6,7 @@ define( [
 "use strict";
 
 function adjustCSS( elem, prop, valueParts, tween ) {
-       var adjusted,
-               scale = 1,
+       var adjusted, scale,
                maxIterations = 20,
                currentValue = tween ?
                        function() {
@@ -25,30 +24,33 @@ function adjustCSS( elem, prop, valueParts, tween ) {
 
        if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
 
+               // Support: Firefox <=54
+               // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)
+               initial = initial / 2;
+
                // Trust units reported by jQuery.css
                unit = unit || initialInUnit[ 3 ];
 
-               // Make sure we update the tween properties later on
-               valueParts = valueParts || [];
-
                // Iteratively approximate from a nonzero starting point
                initialInUnit = +initial || 1;
 
-               do {
-
-                       // If previous iteration zeroed out, double until we get *something*.
-                       // Use string for doubling so we don't accidentally see scale as unchanged below
-                       scale = scale || ".5";
+               while ( maxIterations-- ) {
 
-                       // Adjust and apply
-                       initialInUnit = initialInUnit / scale;
+                       // Evaluate and update our best guess (doubling guesses that zero out).
+                       // Finish if the scale equals or crosses 1 (making the old*new product non-positive).
                        jQuery.style( elem, prop, initialInUnit + unit );
+                       if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {
+                               maxIterations = 0;
+                       }
+                       initialInUnit = initialInUnit / scale;
+
+               }
 
-               // Update scale, tolerating zero or NaN from tween.cur()
-               // Break the loop if scale is unchanged or perfect, or if we've just had enough.
-               } while (
-                       scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
-               );
+               initialInUnit = initialInUnit * 2;
+               jQuery.style( elem, prop, initialInUnit + unit );
+
+               // Make sure we update the tween properties later on
+               valueParts = valueParts || [];
        }
 
        if ( valueParts ) {
index 4533e46926c1260ce03e947348e2f566df1c3761..79cce0549dba3d2724d86fef78d57f1b81bd5676 100644 (file)
@@ -271,6 +271,22 @@ QUnit.test( "css() non-px relative values (gh-1711)", function( assert ) {
        add( "lineHeight",  50,  "%" );
 } );
 
+QUnit.test( "css() mismatched relative values with bounded styles (gh-2144)", function( assert ) {
+       assert.expect( 1 );
+
+       var right,
+               $container = jQuery( "<div/>" )
+                       .css( { position: "absolute", width: "400px", fontSize: "4px" } )
+                       .appendTo( "#qunit-fixture" ),
+               $el = jQuery( "<div/>" )
+                       .css( { position: "absolute", left: "50%", right: "50%" } )
+                       .appendTo( $container );
+
+       $el.css( "right", "-=25em" );
+       assert.equal( Math.round( parseFloat( $el.css( "right" ) ) ), 100,
+               "Constraints do not interfere with unit conversion" );
+} );
+
 QUnit.test( "css(String, Object)", function( assert ) {
        assert.expect( 19 );
        var j, div, display, ret, success;
index 54c7f7995d74fa4e9c3565cba53c761ea7be787f..ec1669f54e915c9858a96949f4d7114e36dc4742 100644 (file)
@@ -1807,7 +1807,8 @@ QUnit.test( "animate does not change start value for non-px animation (#7109)",
                }
        } ).queue( function( next ) {
                var ratio = computed[ 0 ] / actual;
-               assert.ok( ratio > 0.9 && ratio < 1.1, "Starting width was close enough" );
+               assert.ok( ratio > 0.9 && ratio < 1.1,
+                       "Starting width was close enough (" + computed[ 0 ] + " approximates " + actual + ")" );
                next();
                parent.remove();
        } );