blob: 0e5cb293de77ce7bce878bbb43baed74818a7033 [file] [log] [blame]
/*
* Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
* for details. All rights reserved. Use of this source code is governed by a
* BSD-style license that can be found in the LICENSE file.
*/
/**
* @description Tests positioning of non-anchored dialogs.
*/
import "dart:html";
import "../../../../Utils/expect.dart";
import "../../../testcommon.dart";
main() {
var style = new Element.html('''
<style>
/* Remove body margin and dialog styles to allow comparing dialog's position with that of plain span elements. */
body {
margin: 0;
}
dialog {
border: 0;
padding: 0;
height: auto;
width: auto;
}
.filler {
height: 20000px;
}
</style>
''', treeSanitizer: new NullTreeSanitizer());
document.head.append(style);
document.body.setInnerHtml('''
<dialog id="mydialog">It is my dialog.</dialog>
<div class="filler" id="fillerDiv"></div>
''', treeSanitizer: new NullTreeSanitizer());
checkTopOfViewport(dialog) {
shouldBe(dialog.getBoundingClientRect().top, 0);
}
checkCentered(dialog) {
var expectedTop = (window.innerHeight - dialog.offsetHeight) / 2;
shouldBe(dialog.getBoundingClientRect().top, expectedTop);
}
// Helper to test both a non-modal and modal dialog.
showAndTestDialog(dialog, checker) {
dialog.show();
checker();
dialog.close('');
dialog.showModal();
checker();
dialog.close('');
}
var dialog = document.getElementById('mydialog');
debug('Dialog should be centered in the viewport.');
showAndTestDialog(dialog, () { checkCentered(dialog); });
debug('<br>The computed top and bottom of a centered dialog should still have position auto');
shouldBeEqualToString(dialog.getComputedStyle().top, 'auto');
shouldBeEqualToString(dialog.getComputedStyle().bottom, 'auto');
debug('<br>Dialog should be recentered if show() is called after close().');
window.scroll(0, 500);
dialog.show();
checkCentered(dialog);
debug('<br>Dialog should not be recentered on a relayout.');
var expectedTop = dialog.getBoundingClientRect().top;
window.scroll(0, 1000);
var forceRelayoutDiv = document.createElement('div');
forceRelayoutDiv.style.width = '100px';
forceRelayoutDiv.style.height = '100px';
forceRelayoutDiv.style.border = 'solid';
document.body.append(forceRelayoutDiv);
window.scroll(0, 500);
shouldBe(dialog.getBoundingClientRect().top, expectedTop);
forceRelayoutDiv.remove();
dialog.close('');
debug('<br>A tall dialog should be positioned at the top of the viewport.');
var dialogInner = document.createElement('div');
dialogInner.className = 'filler';
dialog.append(dialogInner);
showAndTestDialog(dialog, () { checkTopOfViewport(dialog); });
dialogInner.remove();
debug('<br>The dialog should be centered regardless of the presence of a horizontal scrollbar.');
var fillerDiv = document.getElementById('fillerDiv');
fillerDiv.style.width = '4000px';
showAndTestDialog(dialog, () { checkCentered(dialog); });
fillerDiv.style.width = 'auto';
debug('<br>Test that centering works when dialog is inside positioned containers.');
var absoluteContainer = document.createElement('div');
absoluteContainer.style.position = 'absolute';
absoluteContainer.style.top = '800px;';
absoluteContainer.style.height = '50px;';
absoluteContainer.style.width = '90%';
dialog.remove();
document.body.append(absoluteContainer);
absoluteContainer.append(dialog);
showAndTestDialog(dialog, () { checkCentered(dialog); });
dialog.remove();
var relativeContainer = document.createElement('div');
relativeContainer.style.position = 'relative';
relativeContainer.style.top = '20px';
relativeContainer.style.height = '30px';
absoluteContainer.append(relativeContainer);
relativeContainer.append(dialog);
dialog.show();
checkCentered(dialog);
debug("<br>Dialog's position should survive after becoming display:none temporarily.");
expectedTop = dialog.getBoundingClientRect().top;
window.scroll(0, 1000);
relativeContainer.style.display = 'none';
relativeContainer.style.display = 'block';
window.scroll(0, 500);
shouldBe(dialog.getBoundingClientRect().top, expectedTop);
debug("<br>Dialog's position should survive after being re-added to document without another call to show().");
expectedTop = dialog.getBoundingClientRect().top;
window.scroll(0, 1000);
dialog.remove();
relativeContainer.append(dialog);
window.scroll(0, 500);
shouldBe(dialog.getBoundingClientRect().top, expectedTop);
dialog.close('');
debug("<br>Dialog's position should survive after close() and show().");
dialog.show();
dialog.style.top = '0px';
expectedTop = dialog.getBoundingClientRect().top;
dialog.close('');
dialog.show();
shouldBe(dialog.getBoundingClientRect().top, expectedTop);
dialog.style.top = 'auto';
debug("<br>Dialog's position should survive after close() and manually reopen.");
dialog.show();
expectedTop = dialog.getBoundingClientRect().top;
dialog.close('');
document.body.offsetHeight;
dialog.open = true;
shouldBe(dialog.getBoundingClientRect().top, expectedTop);
dialog.close('');
debug("<br>Dialog is recentered if show() is called after removing 'open'");
dialog.show();
dialog.attributes.remove('open');
window.scroll(0, 1000);
dialog.show();
checkCentered(dialog);
dialog.close('');
window.scroll(0, 500);
debug("<br>Dialog should not be centered if show() was called when an ancestor had display 'none'.");
absoluteContainer.style.display = 'none';
dialog.show();
absoluteContainer.style.display = 'block';
// Since dialog's containing block is the ICB, it's statically positioned after <body>.
expectedTop = document.body.getBoundingClientRect().bottom;
shouldBe(dialog.getBoundingClientRect().top, expectedTop);
dialog.close('');
debug("<br>Test that setting 'top' on dialog results in the same position as for a plain, absolutely positioned span.");
var plainSpan = document.createElement('span');
plainSpan.style.position = 'absolute';
document.body.append(plainSpan);
plainSpan.style.top = '50px';
dialog.style.top = '50px';
expectedTop = plainSpan.getBoundingClientRect().top;
showAndTestDialog(dialog, () { shouldBe(dialog.getBoundingClientRect().top, expectedTop); });
debug("<br>Test that setting 'bottom' on dialog results in the same position as for a plain, absolutely positioned span.");
dialog.style.top = 'auto';
plainSpan.style.top = 'auto';
dialog.style.bottom = '50px';
plainSpan.style.bottom = '50px';
showAndTestDialog(dialog, () { shouldBe(dialog.getBoundingClientRect().bottom, plainSpan.getBoundingClientRect().bottom); });
debug('<br>Test that fixed positioning for dialog has same behavior as for a plain span.');
plainSpan.style.position = 'fixed';
plainSpan.style.top = '50px';
dialog.style.position = 'fixed';
dialog.style.top = '50px';
showAndTestDialog(dialog, () { shouldBe(dialog.getBoundingClientRect().top, plainSpan.getBoundingClientRect().top); });
debug('<br>Test that static position for a non-modal dialog has the same behavior as for a plain span.');
plainSpan.remove();
relativeContainer.append(plainSpan);
plainSpan.style.position = 'static';
expectedTop = plainSpan.getBoundingClientRect().top;
plainSpan.remove();
dialog.style.position = 'static';
// Just test non-modal since modal is covered by other tests (for modal, static computes to absolute)
dialog.show();
shouldBe(dialog.getBoundingClientRect().top, expectedTop);
dialog.close('');
debug('<br>Test that relative position for a non-modal dialog has the same behavior as for a plain span.');
relativeContainer.append(plainSpan);
plainSpan.style.position = 'relative';
plainSpan.style.top = '50px';
expectedTop = plainSpan.getBoundingClientRect().top;
plainSpan.remove();
dialog.style.position = 'relative';
dialog.style.top = '50px';
// Just test non-modal since modal is covered by other tests (for modal, relative computes to absolute)
dialog.show();
shouldBe(dialog.getBoundingClientRect().top, expectedTop);
dialog.close('');
}