e260860789
There was a commit that landed in 4.0.1 that fixed positioning for
non-static elements, which are commonly used for the custom
`dropdownParent` option, but broke positioning for statically positioned
elements, commonly used in almost every other case. That commit was
c9216b4b96
This fixes the positioning issues caused by that commit by properly
calculating the offsets for statically positioned parents. Statically
positioned parents are unique, because the offset for the dropdown must
be calculated based on the closest element that is non-statically
positioned. Otherwise, the offset for any statically positioned parent
other than the body will be considerably higher than it should be,
resulting in the dropdown being offset by a large amount.
The offset parent for the body element is the html element, which is why
this works for both the body element and any custom parents for the
dropdown. This would not be needed if the parent wasn't customizable (as
seen in Select2 3.x) because you will never need to offset the body
element if it is statically positioned, because the html element almost
never has an offset.
This also fixes JSHint issues within the tests added in the last commit.
This closes https://github.com/select2/select2/issues/3970
This closes https://github.com/select2/select2/issues/3639
167 lines
4.1 KiB
JavaScript
167 lines
4.1 KiB
JavaScript
module('Dropdown - attachBody - positioning');
|
|
|
|
test('appends to the dropdown parent', function (assert) {
|
|
expect(4);
|
|
|
|
var $ = require('jquery');
|
|
|
|
var $select = $('<select></select>');
|
|
var $parent = $('<div></div>');
|
|
|
|
var $container = $('<span></span>');
|
|
var container = new MockContainer();
|
|
|
|
$parent.appendTo($('#qunit-fixture'));
|
|
$select.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
|
|
}));
|
|
|
|
assert.equal(
|
|
$parent.children().length,
|
|
1,
|
|
'Only the select should be in the container'
|
|
);
|
|
|
|
var $dropdown = dropdown.render();
|
|
|
|
dropdown.bind(container, $container);
|
|
|
|
dropdown.position($dropdown, $container);
|
|
|
|
assert.equal(
|
|
$parent.children().length,
|
|
1,
|
|
'The dropdown should not be placed until after it is opened'
|
|
);
|
|
|
|
dropdown._showDropdown();
|
|
|
|
assert.equal(
|
|
$parent.children().length,
|
|
2,
|
|
'The dropdown should now be in the container as well'
|
|
);
|
|
|
|
assert.ok(
|
|
$.contains($parent[0], $dropdown[0]),
|
|
'The dropdown should be contained within the parent container'
|
|
);
|
|
});
|
|
|
|
test('dropdown is positioned 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></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.equal(
|
|
$dropdown.css('top'),
|
|
'5px',
|
|
'The offset should be 5px at the top'
|
|
);
|
|
|
|
assert.equal(
|
|
$dropdown.css('left'),
|
|
'10px',
|
|
'The offset should be 10px on the left'
|
|
);
|
|
});
|
|
|
|
test('dropdown is positioned with absolute offsets', function (assert) {
|
|
var $ = require('jquery');
|
|
var $select = $('<select></select>');
|
|
var $parent = $('<div></div>');
|
|
$parent.css({
|
|
position: 'absolute',
|
|
top: '10px',
|
|
left: '5px'
|
|
});
|
|
|
|
var $container = $('<span></span>');
|
|
var container = new MockContainer();
|
|
|
|
$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.equal(
|
|
$dropdown.css('top'),
|
|
'0px',
|
|
'There should not be an extra top offset'
|
|
);
|
|
|
|
assert.equal(
|
|
$dropdown.css('left'),
|
|
'0px',
|
|
'There should not be an extra left offset'
|
|
);
|
|
}); |