Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check whether element is in document before calling jQuery.fn.offset() #5584

Closed
wants to merge 3 commits into from

Conversation

kevin-j-morse
Copy link
Contributor

This pull request includes a

  • Bug fix
  • New feature
  • Translation

The following changes were made

As of jQuery 3.0, jQuery.fn.offset() requires an element connected to a document. In earlier versions of jQuery, the .offset() method would return a value of { top: 0, left: 0 } for some cases of invalid input. jQuery 3.0 throws errors in some of these cases.

This PR checks whether the element is within the document. If not, it sets the offset to { top: 0, left: 0 } which is what was happening before. I believe this covers all valid scenarios but perhaps someone else can comment?

See the jQuery migrate documentation for more info. https://github.com/jquery/jquery-migrate/blob/master/warnings.md#jqmigrate-jqueryfnoffset-requires-an-element-connected-to-a-document

@kevin-brown
Copy link
Member

I know this might be tough, since our positioning logic is not the easiest to read and test, but would it be possible for you to create a test for this?

It wouldn't be a whole lot different from

test('dropdown is positioned down with static margins', function (assert) {
var $ = require('jquery');
var $select = $('<select></select>');
var $parent = $('<div></div>');
$parent.css({
position: 'static',
marginTop: '5px',
marginLeft: '10px'
});
var $container = $('<span>test</span>');
var container = new MockContainer();
$('#qunit-fixture').empty();
$parent.appendTo($('#qunit-fixture'));
$container.appendTo($parent);
var Utils = require('select2/utils');
var Options = require('select2/options');
var Dropdown = require('select2/dropdown');
var AttachBody = require('select2/dropdown/attachBody');
var DropdownAdapter = Utils.Decorate(Dropdown, AttachBody);
var dropdown = new DropdownAdapter($select, new Options({
dropdownParent: $parent
}));
var $dropdown = dropdown.render();
assert.equal(
$dropdown[0].style.top,
0,
'The drodpown should not have any offset before it is displayed'
);
dropdown.bind(container, $container);
dropdown.position($dropdown, $container);
dropdown._showDropdown();
assert.ok(
dropdown.$dropdown.hasClass('select2-dropdown--below'),
'The dropdown should be forced down'
);
assert.equal(
$dropdown.css('top').replace(/\D+/, ''),
$container.outerHeight() + 5,
'The offset should be 5px at the top'
);
assert.equal(
$dropdown.css('left'),
'10px',
'The offset should be 10px on the left'
);
});

Except you don't need to play around with the CSS and you don't need to attach it to the QUnit fixture (since that would add it into the document).

@kevin-j-morse
Copy link
Contributor Author

kevin-j-morse commented Jul 23, 2019 via email

@kevin-j-morse
Copy link
Contributor Author

@kevin-brown should this test live within select2/tests/dropdown/positioning-tests.js

@kevin-brown
Copy link
Member

should this test live within select2/tests/dropdown/positioning-tests.js

That sounds like a good place for it, yes.

@kevin-brown kevin-brown modified the milestones: 4.0.9, 4.0.10 Aug 22, 2019
@kevin-brown
Copy link
Member

In the interest of getting 4.0.9 out the door without procrastinating even further, I'm moving this PR to land in 4.0.10.

@kevin-j-morse
Copy link
Contributor Author

kevin-j-morse commented Aug 26, 2019 via email

@kevin-brown kevin-brown modified the milestones: 4.0.10, 4.0.11 Aug 28, 2019
kevin-brown added a commit that referenced this pull request Sep 19, 2019
This fixes an error which is called out in jQuery Migrate but
probably never happens in real life. This is because we call
`jQuery.fn.offset` without checking if the element is in the
document. Based on testing done here and within the MediaWiki
team, I'm pretty sure jQuery never actually implemented explicit
checks and this jQuery Migrate warning is just to cover the case
where a browser might start returning inconsistnet results. And
we could at least reproduce the inconsistency, so that's something.

We now default the offset to 0/0 if the parent element happens to
not be in the document. This appears to be what jQuery used to do
in the past, and generally appears to be what people expect in
these cases.

This fixes #5584.
kevin-brown added a commit that referenced this pull request Sep 19, 2019
Fixes jQuery migrate error when getting offset when dropdownParent not in document
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants