aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Gibson <richard.gibson@gmail.com>2017-08-28 13:23:04 -0400
committerGitHub <noreply@github.com>2017-08-28 13:23:04 -0400
commit692f9d4db30c9c6c4f6bc76005cf153586202fa6 (patch)
treee90a47a8b012a0758c0079918e9fe049831aeaad
parentb1b949d35ee995ee75c6968715a7f8c8ea601157 (diff)
downloadjquery-692f9d4db30c9c6c4f6bc76005cf153586202fa6.tar.gz
jquery-692f9d4db30c9c6c4f6bc76005cf153586202fa6.zip
CSS: Avoid unit-conversion interference from CSS upper bounds
Fixes gh-2144 Closes gh-3745
-rw-r--r--src/css/adjustCSS.js36
-rw-r--r--test/unit/css.js16
-rw-r--r--test/unit/effects.js3
3 files changed, 37 insertions, 18 deletions
diff --git a/src/css/adjustCSS.js b/src/css/adjustCSS.js
index ded3a1666..626ec7475 100644
--- a/src/css/adjustCSS.js
+++ b/src/css/adjustCSS.js
@@ -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 ) {
diff --git a/test/unit/css.js b/test/unit/css.js
index 4533e4692..79cce0549 100644
--- a/test/unit/css.js
+++ b/test/unit/css.js
@@ -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;
diff --git a/test/unit/effects.js b/test/unit/effects.js
index 54c7f7995..ec1669f54 100644
--- a/test/unit/effects.js
+++ b/test/unit/effects.js
@@ -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();
} );