Initial commit
This commit is contained in:
Родитель
821568ef6b
Коммит
7429e58f8a
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
42
README.md
42
README.md
|
@ -1,4 +1,40 @@
|
|||
dialog-polyfill
|
||||
===============
|
||||
dialog-polyfill.js is a polyfill for `<dialog>`.
|
||||
|
||||
Polyfill for the <dialog> element
|
||||
### Example
|
||||
|
||||
<head>
|
||||
<script src="dialog-polyfill.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="dialog-polyfill.css">
|
||||
</head>
|
||||
<body>
|
||||
<dialog>I'm a dialog!</dialog>
|
||||
<script>
|
||||
var dialog = document.querySelector('dialog');
|
||||
dialogPolyfill.registerDialog(dialog);
|
||||
|
||||
// Now dialog acts like a native <dialog>.
|
||||
dialog.showModal();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
### ::backdrop
|
||||
|
||||
In native `<dialog>`, the backdrop is a pseudo-element:
|
||||
|
||||
#mydialog::backdrop {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
With the polyfill, you do it like:
|
||||
|
||||
#mydialog + .backdrop {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
### Known limitations
|
||||
|
||||
- Modality isn't bulletproof (you can tab to inert elements)
|
||||
- The polyfill `<dialog>` should always be a child of `<body>`
|
||||
- Polyfill top layer stacking can be ruined by playing with z-index.
|
||||
- The polyfill `<dialog>` does not retain dynamically set CSS top/bottom values
|
||||
upon close
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
dialog {
|
||||
position: absolute;
|
||||
left: 0; right: 0;
|
||||
margin: auto;
|
||||
border: solid;
|
||||
padding: 1em;
|
||||
background: white;
|
||||
color: black;
|
||||
|
||||
display: none;
|
||||
}
|
||||
|
||||
.backdrop {
|
||||
position: absolute;
|
||||
background: rgba(0,0,0,0.1);
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
var dialogPolyfill = {}
|
||||
|
||||
dialogPolyfill.reposition = function(element) {
|
||||
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
|
||||
var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;
|
||||
element.style.top = topValue + 'px';
|
||||
element.dialogPolyfillInfo.isTopOverridden = true;
|
||||
}
|
||||
|
||||
dialogPolyfill.inNodeList = function(nodeList, node) {
|
||||
for (var i = 0; i < nodeList.length; ++i) {
|
||||
if (nodeList[i] == node)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
dialogPolyfill.isInlinePositionSetByStylesheet = function(element) {
|
||||
for (var i = 0; i < document.styleSheets.length; ++i) {
|
||||
var styleSheet = document.styleSheets[i];
|
||||
var cssRules = null;
|
||||
// Some browsers throw on cssRules.
|
||||
try {
|
||||
cssRules = styleSheet.cssRules;
|
||||
} catch (e) {}
|
||||
if (!cssRules)
|
||||
continue;
|
||||
for (var j = 0; j < cssRules.length; ++j) {
|
||||
var rule = cssRules[j];
|
||||
var selectedNodes = document.querySelectorAll(rule.selectorText);
|
||||
if (!dialogPolyfill.inNodeList(selectedNodes, element))
|
||||
continue;
|
||||
var cssTop = rule.style.getPropertyValue('top');
|
||||
var cssBottom = rule.style.getPropertyValue('bottom');
|
||||
if ((cssTop && cssTop != 'auto') || (cssBottom && cssBottom != 'auto'))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
dialogPolyfill.needsCentering = function(dialog) {
|
||||
var computedStyle = getComputedStyle(dialog);
|
||||
if (computedStyle.position != 'absolute')
|
||||
return false;
|
||||
|
||||
// We must determine whether the top/bottom specified value is non-auto. In
|
||||
// WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but
|
||||
// Firefox returns the used value. So we do this crazy thing instead: check
|
||||
// the inline style and then go through CSS rules.
|
||||
if ((dialog.style.top != 'auto' && dialog.style.top != '') ||
|
||||
(dialog.style.bottom != 'auto' && dialog.style.bottom != ''))
|
||||
return false;
|
||||
return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);
|
||||
}
|
||||
|
||||
dialogPolyfill.showDialog = function(isModal) {
|
||||
if (this.open) {
|
||||
throw 'InvalidStateError: showDialog called on open dialog';
|
||||
}
|
||||
this.open = true;
|
||||
this.style.display = 'block';
|
||||
|
||||
if (dialogPolyfill.needsCentering(this))
|
||||
dialogPolyfill.reposition(this);
|
||||
if (isModal) {
|
||||
this.dialogPolyfillInfo.modal = true;
|
||||
dialogPolyfill.dm.pushDialog(this);
|
||||
}
|
||||
};
|
||||
|
||||
dialogPolyfill.close = function(retval) {
|
||||
if (!this.open)
|
||||
throw new InvalidStateError;
|
||||
this.open = false;
|
||||
this.style.display = 'none';
|
||||
|
||||
// This won't match the native <dialog> exactly because if the user sets top
|
||||
// on a centered polyfill dialog, that top gets thrown away when the dialog is
|
||||
// closed. Not sure it's possible to polyfill this perfectly.
|
||||
if (this.dialogPolyfillInfo.isTopOverridden) {
|
||||
this.style.top = 'auto';
|
||||
}
|
||||
|
||||
if (this.dialogPolyfillInfo.modal) {
|
||||
dialogPolyfill.dm.removeDialog(this);
|
||||
}
|
||||
|
||||
if (typeof retval != 'undefined')
|
||||
return retval;
|
||||
}
|
||||
|
||||
dialogPolyfill.registerDialog = function(element) {
|
||||
element.show = dialogPolyfill.showDialog.bind(element, false);
|
||||
element.showModal = dialogPolyfill.showDialog.bind(element, true);
|
||||
element.close = dialogPolyfill.close.bind(element);
|
||||
element.dialogPolyfillInfo = {};
|
||||
};
|
||||
|
||||
// The overlay is used to simulate how a modal dialog blocks the document. The
|
||||
// blocking dialog is positioned on top of the overlay, and the rest of the
|
||||
// dialogs on the pending dialog stack are positioned below it. In the actual
|
||||
// implementation, the modal dialog stacking is controlled by the top layer,
|
||||
// where z-index has no effect.
|
||||
TOP_LAYER_ZINDEX = 100000;
|
||||
MAX_PENDING_DIALOGS = 100000;
|
||||
|
||||
dialogPolyfill.DialogManager = function() {
|
||||
this.pendingDialogStack = [];
|
||||
this.overlay = document.createElement('div');
|
||||
this.overlay.style.width = '100%';
|
||||
this.overlay.style.height = '100%';
|
||||
this.overlay.style.position = 'fixed';
|
||||
this.overlay.style.left = '0px';
|
||||
this.overlay.style.top = '0px';
|
||||
this.overlay.style.background = 'rgba(0,0,0,0.0)';
|
||||
|
||||
this.overlay.addEventListener('click', function(e) {
|
||||
var redirectedEvent = document.createEvent('MouseEvents');
|
||||
redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
|
||||
e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
|
||||
e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
|
||||
document.body.dispatchEvent(redirectedEvent);
|
||||
});
|
||||
}
|
||||
|
||||
dialogPolyfill.dm = new dialogPolyfill.DialogManager();
|
||||
|
||||
dialogPolyfill.DialogManager.prototype.blockDocument = function() {
|
||||
if (!document.body.contains(this.overlay))
|
||||
document.body.appendChild(this.overlay);
|
||||
}
|
||||
|
||||
dialogPolyfill.DialogManager.prototype.unblockDocument = function() {
|
||||
document.body.removeChild(this.overlay);
|
||||
}
|
||||
|
||||
dialogPolyfill.DialogManager.prototype.updateStacking = function() {
|
||||
if (this.pendingDialogStack.length == 0) {
|
||||
this.unblockDocument();
|
||||
return;
|
||||
}
|
||||
this.blockDocument();
|
||||
|
||||
var zIndex = TOP_LAYER_ZINDEX;
|
||||
for (var i = 0; i < this.pendingDialogStack.length; i++) {
|
||||
if (i == this.pendingDialogStack.length - 1)
|
||||
this.overlay.style.zIndex = zIndex++;
|
||||
var dialog = this.pendingDialogStack[i];
|
||||
dialog.dialogPolyfillInfo.backdrop.style.zIndex = zIndex++;
|
||||
dialog.style.zIndex = zIndex++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dialogPolyfill.DialogManager.prototype.pushDialog = function(dialog) {
|
||||
if (this.pendingDialogStack.length >= MAX_PENDING_DIALOGS) {
|
||||
throw "Too many modal dialogs";
|
||||
}
|
||||
|
||||
var backdrop = document.createElement('div');
|
||||
backdrop.classList.add('backdrop');
|
||||
backdrop.addEventListener('click', function(e) {
|
||||
var redirectedEvent = document.createEvent('MouseEvents');
|
||||
redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
|
||||
e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
|
||||
e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
|
||||
dialog.dispatchEvent(redirectedEvent);
|
||||
});
|
||||
dialog.parentNode.insertBefore(backdrop, dialog.nextSibling);
|
||||
dialog.dialogPolyfillInfo.backdrop = backdrop;
|
||||
this.pendingDialogStack.push(dialog);
|
||||
this.updateStacking();
|
||||
}
|
||||
|
||||
dialogPolyfill.DialogManager.prototype.removeDialog = function(dialog) {
|
||||
var index = this.pendingDialogStack.indexOf(dialog);
|
||||
if (index == -1)
|
||||
return;
|
||||
this.pendingDialogStack.splice(index, 1);
|
||||
var backdrop = dialog.dialogPolyfillInfo.backdrop;
|
||||
backdrop.parentNode.removeChild(backdrop);
|
||||
dialog.dialogPolyfillInfo.backdrop = null;
|
||||
this.updateStacking();
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset='utf-8'>
|
||||
<head>
|
||||
<script src="../dialog-polyfill.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../dialog-polyfill.css">
|
||||
<style>
|
||||
dialog {
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0,255,0,0.5);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for backdrop. The test passes if you see a green background behind the
|
||||
box.</p>
|
||||
<div id="console"></div>
|
||||
<dialog></dialog>
|
||||
<button id="inert-button">Can't click me</button>
|
||||
<script>
|
||||
function writeToConsole(s) {
|
||||
var console = document.getElementById('console');
|
||||
var span = document.createElement('span');
|
||||
span.textContent = s;
|
||||
console.appendChild(span);
|
||||
console.appendChild(document.createElement('br'));
|
||||
}
|
||||
|
||||
var dialog = document.querySelector('dialog');
|
||||
dialogPolyfill.registerDialog(dialog);
|
||||
dialog.showModal();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset='utf-8'>
|
||||
<head>
|
||||
<script src="../dialog-polyfill.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../dialog-polyfill.css">
|
||||
<style>
|
||||
dialog {
|
||||
width: 100px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test that dialog is centered in the viewport. The test passes if you see a
|
||||
box in the center of the screen.</p>
|
||||
<div id="console"></div>
|
||||
<dialog></dialog>
|
||||
<script>
|
||||
function writeToConsole(s) {
|
||||
var console = document.getElementById('console');
|
||||
var span = document.createElement('span');
|
||||
span.textContent = s;
|
||||
console.appendChild(span);
|
||||
console.appendChild(document.createElement('br'));
|
||||
}
|
||||
|
||||
function checkCentered(dialog) {
|
||||
var expectedTop = (window.innerHeight - dialog.offsetHeight) / 2;
|
||||
var expectedLeft = (window.innerWidth - dialog.offsetWidth) / 2;
|
||||
var rect = dialog.getBoundingClientRect();
|
||||
if (rect.top == expectedTop && rect.left == expectedLeft) {
|
||||
writeToConsole('SUCCESS');
|
||||
} else {
|
||||
writeToConsole('FAIL: expected dialog top,left to be ' +
|
||||
expectedTop + ',' + expectedLeft + ' and was actually ' +
|
||||
rect.top + ',' + rect.left);
|
||||
}
|
||||
}
|
||||
|
||||
var dialog = document.querySelector('dialog');
|
||||
dialogPolyfill.registerDialog(dialog);
|
||||
dialog.show();
|
||||
checkCentered(dialog);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset='utf-8'>
|
||||
<head>
|
||||
<script src="../dialog-polyfill.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../dialog-polyfill.css">
|
||||
<style>
|
||||
body {
|
||||
height: 10000px;
|
||||
}
|
||||
dialog {
|
||||
width: 100px;
|
||||
}
|
||||
#console {
|
||||
position: fixed;
|
||||
}
|
||||
#ruler {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test that dialog is recentered if reopened. The test passes if you see a
|
||||
box in the center of the screen.</p>
|
||||
<div id="ruler"></div>
|
||||
<div id="console"></div>
|
||||
<dialog></dialog>
|
||||
<script>
|
||||
function writeToConsole(s) {
|
||||
var console = document.getElementById('console');
|
||||
var span = document.createElement('span');
|
||||
span.textContent = s;
|
||||
console.appendChild(span);
|
||||
console.appendChild(document.createElement('br'));
|
||||
}
|
||||
|
||||
function windowWidthMinusScrollbar() {
|
||||
return document.getElementById('ruler').offsetWidth;
|
||||
}
|
||||
|
||||
function checkCentered(dialog) {
|
||||
var expectedTop = (window.innerHeight - dialog.offsetHeight) / 2;
|
||||
var expectedLeft = (windowWidthMinusScrollbar() - dialog.offsetWidth) / 2;
|
||||
var rect = dialog.getBoundingClientRect();
|
||||
if (rect.top == expectedTop && rect.left == expectedLeft) {
|
||||
writeToConsole('SUCCESS');
|
||||
} else {
|
||||
writeToConsole('FAIL: expected dialog top,left to be ' +
|
||||
expectedTop + ',' + expectedLeft + ' and was actually ' +
|
||||
rect.top + ',' + rect.left);
|
||||
}
|
||||
}
|
||||
|
||||
var dialog = document.querySelector('dialog');
|
||||
dialogPolyfill.registerDialog(dialog);
|
||||
dialog.show();
|
||||
dialog.close();
|
||||
window.scrollTo(0, 500);
|
||||
dialog.show();
|
||||
checkCentered(dialog);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,272 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="../dialog-polyfill.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../dialog-polyfill.css">
|
||||
<style>
|
||||
#close-button {
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
right: 7px;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
margin: 0;
|
||||
background-image: url('resources/close_dialog.png');
|
||||
}
|
||||
|
||||
#close-button:hover {
|
||||
background-image: url('resources/close_dialog_hover.png');
|
||||
}
|
||||
|
||||
dialog {
|
||||
width: 50%;
|
||||
-webkit-border-radius: 3px;
|
||||
-webkit-box-orient: vertical;
|
||||
opacity: 0;
|
||||
background: white;
|
||||
box-shadow: 0 4px 23px 5px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0,0,0,0.15);
|
||||
color: #333;
|
||||
min-width: 400px;
|
||||
padding: 0;
|
||||
z-index: 100;
|
||||
border: 0;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
dialog + .backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
dialog.no-backdrop + .backdrop {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dialog-setting {
|
||||
margin: 30px;
|
||||
}
|
||||
|
||||
/* keyframes used to pulse the overlay */
|
||||
@-webkit-keyframes pulse {
|
||||
0% {
|
||||
-webkit-transform: scale(1);
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: scale(1.05);
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: scale(1.05);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.pulse {
|
||||
-webkit-animation-duration: 180ms;
|
||||
-webkit-animation-iteration-count: 1;
|
||||
-webkit-animation-name: pulse;
|
||||
-webkit-animation-timing-function: ease-in-out;
|
||||
}
|
||||
#messages {
|
||||
background-color: red;
|
||||
}
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#open-button {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: lightgray;
|
||||
border: 1px solid;
|
||||
margin: 10px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
#open-button:active {
|
||||
background-color: lime;
|
||||
margin: 9px;
|
||||
}
|
||||
|
||||
#backdrop {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top:0;
|
||||
right:0;
|
||||
bottom:0;
|
||||
left:0;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 10;
|
||||
}
|
||||
.post {
|
||||
margin: 10px;
|
||||
padding: 5px;
|
||||
border: 2px solid;
|
||||
}
|
||||
|
||||
.post-buttons {
|
||||
margin: 5px;
|
||||
text-align: right;
|
||||
}
|
||||
.post-button:hover {
|
||||
color: green;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div id="messages"></div>
|
||||
<dialog id="dialog">
|
||||
<h3>Reshare</h3>
|
||||
<input type="text" style="width: 75%" value="I am resharing this."><br>
|
||||
<div class="dialog-setting">
|
||||
<input id="click-outside-to-close" type="checkbox">
|
||||
<label for="click-outside-to-close">Close dialog upon clicking outside</label>
|
||||
</div>
|
||||
<div class="dialog-setting">
|
||||
<input id="enable-backdrop" type="checkbox" checked>
|
||||
<label for="enable-backdrop">Enable ::backdrop</label>
|
||||
</div>
|
||||
<div id="close-button"></div>
|
||||
</dialog>
|
||||
<div id="post-container"></div>
|
||||
<script>
|
||||
var dialog = document.getElementById('dialog');
|
||||
dialogPolyfill.registerDialog(dialog);
|
||||
|
||||
function createPostButton(container, text) {
|
||||
var link = document.createElement('a');
|
||||
link.href = 'javascript:void(0)';
|
||||
link.textContent = text;
|
||||
link.className = 'post-button';
|
||||
container.appendChild(link);
|
||||
var span = document.createElement('span');
|
||||
span.textContent = ' ';
|
||||
container.appendChild(span);
|
||||
return link;
|
||||
}
|
||||
|
||||
SampleText = 'From this spot I rise not, valiant knight, until your ' +
|
||||
'courtesy grants me the boon I seek, one that will redound ' +
|
||||
'to your praise and the benefit of the human race.';
|
||||
|
||||
function createPost(container) {
|
||||
var post = document.createElement('div');
|
||||
post.className = 'post';
|
||||
var postContent = document.createElement('div');
|
||||
postContent.className = 'post-content';
|
||||
postContent.textContent = SampleText;
|
||||
post.appendChild(postContent);
|
||||
var postButtons = document.createElement('div');
|
||||
postButtons.className = 'post-buttons';
|
||||
post.appendChild(postButtons);
|
||||
var reshare = createPostButton(postButtons, 'Reshare');
|
||||
reshare.addEventListener('click', openDialog);
|
||||
var reply = createPostButton(postButtons, 'Reply');
|
||||
reply.addEventListener('click', openDialog);
|
||||
createPostButton(postButtons, 'Enjoyed this post');
|
||||
|
||||
container.appendChild(post);
|
||||
return post;
|
||||
}
|
||||
|
||||
function initPosts() {
|
||||
var container = document.getElementById('post-container');
|
||||
for (var i = 0; i < 25; ++i) {
|
||||
var post = createPost(container);
|
||||
}
|
||||
}
|
||||
|
||||
function shouldCloseDialogOnClickOutside() {
|
||||
return document.getElementById('click-outside-to-close').checked;
|
||||
}
|
||||
|
||||
function closeDialog() {
|
||||
if (dialog.open)
|
||||
dialog.close();
|
||||
}
|
||||
|
||||
function computeCenteredTop(dialog) {
|
||||
dialog.style.top = 'auto';
|
||||
dialog.style.webkitTransition = '';
|
||||
dialog.showModal();
|
||||
var computedTopPx = window.getComputedStyle(dialog).top;
|
||||
var computedTop = parseInt(computedTopPx.substring(0, computedTopPx.length - 2), 10);
|
||||
dialog.close();
|
||||
return computedTop;
|
||||
}
|
||||
|
||||
function openDialog() {
|
||||
centerTop = computeCenteredTop(dialog);
|
||||
dialog.style.top = window.scrollY + 'px';
|
||||
dialog.style.opacity = 0;
|
||||
dialog.style.webkitTransition = 'all 250ms ease';
|
||||
|
||||
dialog.showModal();
|
||||
|
||||
dialog.style.top = centerTop + 'px';
|
||||
dialog.style.opacity = 1;
|
||||
}
|
||||
|
||||
function pulseDialog() {
|
||||
dialog.classList.add('pulse');
|
||||
dialog.addEventListener('webkitAnimationEnd', function(e) {
|
||||
dialog.classList.remove('pulse');
|
||||
});
|
||||
}
|
||||
|
||||
function clickedInDialog(mouseEvent) {
|
||||
var rect = dialog.getBoundingClientRect();
|
||||
return rect.top <= mouseEvent.clientY && mouseEvent.clientY <= rect.top + rect.height
|
||||
&& rect.left <= mouseEvent.clientX && mouseEvent.clientX <= rect.left + rect.width;
|
||||
}
|
||||
|
||||
function handleClickOutsideDialog() {
|
||||
if (!shouldCloseDialogOnClickOutside()) {
|
||||
pulseDialog();
|
||||
return
|
||||
}
|
||||
closeDialog();
|
||||
}
|
||||
|
||||
document.body.addEventListener('keydown', function(e) {
|
||||
if (e.keyCode == 27)
|
||||
closeDialog();
|
||||
});
|
||||
|
||||
var enableBackdrop = document.getElementById('enable-backdrop');
|
||||
enableBackdrop.addEventListener('change', function(e) {
|
||||
if (document.getElementById('enable-backdrop').checked)
|
||||
dialog.classList.remove('no-backdrop');
|
||||
else
|
||||
dialog.classList.add('no-backdrop');
|
||||
|
||||
// FIXME: Without this ::backdrop is not redrawn. crbug.com/258759
|
||||
dialog.close();
|
||||
dialog.showModal();
|
||||
});
|
||||
|
||||
var closeButton = document.getElementById('close-button');
|
||||
closeButton.addEventListener('click', function(e) { closeDialog(); });
|
||||
|
||||
document.body.addEventListener('click', function(e) {
|
||||
if (!dialog.open)
|
||||
return;
|
||||
if (e.target != document.body)
|
||||
return;
|
||||
handleClickOutsideDialog();
|
||||
});
|
||||
|
||||
dialog.addEventListener('click', function(e) {
|
||||
if (clickedInDialog(e))
|
||||
return;
|
||||
handleClickOutsideDialog();
|
||||
});
|
||||
initPosts();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,89 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset='utf-8'>
|
||||
<head>
|
||||
<script src="../dialog-polyfill.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../dialog-polyfill.css">
|
||||
<style>
|
||||
dialog {
|
||||
padding: 0px;
|
||||
border: none;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#bottom + .backdrop {
|
||||
top: 100px;
|
||||
left: 100px;
|
||||
height: 300px;
|
||||
width: 300px;
|
||||
background-color: rgb(0, 50, 0);
|
||||
z-index: 100; /* z-index has no effect. */
|
||||
}
|
||||
|
||||
#bottom {
|
||||
top: 125px;
|
||||
left: 125px;
|
||||
height: 250px;
|
||||
width: 250px;
|
||||
background-color: rgb(0, 90, 0);
|
||||
}
|
||||
|
||||
#middle + .backdrop {
|
||||
top: 150px;
|
||||
left: 150px;
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
background-color: rgb(0, 130, 0);
|
||||
z-index: -100; /* z-index has no effect. */
|
||||
}
|
||||
|
||||
#middle {
|
||||
top: 175px;
|
||||
left: 175px;
|
||||
height: 150px;
|
||||
width: 150px;
|
||||
background-color: rgb(0, 170, 0);
|
||||
}
|
||||
|
||||
#top + .backdrop {
|
||||
top: 200px;
|
||||
left: 200px;
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
background-color: rgb(0, 210, 0);
|
||||
z-index: 0; /* z-index has no effect. */
|
||||
}
|
||||
|
||||
#top {
|
||||
top: 225px;
|
||||
left: 225px;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
background-color: rgb(0, 255, 0);
|
||||
z-index: -1000; /* z-index has no effect. */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
Test for modal dialog and backdrop stacking order. The test passes if there are
|
||||
6 boxes enclosed in each other, becoming increasingly smaller and brighter
|
||||
green.
|
||||
<dialog id="top"></dialog>
|
||||
<dialog id="middle"></dialog>
|
||||
<dialog id="bottom"></dialog>
|
||||
<script>
|
||||
var topDialog = document.getElementById('top');
|
||||
dialogPolyfill.registerDialog(topDialog);
|
||||
var middleDialog = document.getElementById('middle');
|
||||
dialogPolyfill.registerDialog(middleDialog);
|
||||
var bottomDialog = document.getElementById('bottom');
|
||||
dialogPolyfill.registerDialog(bottomDialog);
|
||||
|
||||
topDialog.showModal();
|
||||
bottomDialog.showModal();
|
||||
topDialog.close(); // Just to shuffle the top layer order around a little.
|
||||
middleDialog.showModal();
|
||||
topDialog.showModal();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset='utf-8'>
|
||||
<head>
|
||||
<script src="../dialog-polyfill.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../dialog-polyfill.css">
|
||||
<style>
|
||||
dialog {
|
||||
width: 100px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for modal dialog. The test passes if you can click on "Click me" button,
|
||||
but can't click or tab to the "Can't click me!" button</p>
|
||||
<div id="console"></div>
|
||||
<dialog>
|
||||
<button id="dialog-button">Click me</button>
|
||||
</dialog>
|
||||
<button id="inert-button">Can't click me</button>
|
||||
<script>
|
||||
function writeToConsole(s) {
|
||||
var console = document.getElementById('console');
|
||||
var span = document.createElement('span');
|
||||
span.textContent = s;
|
||||
console.appendChild(span);
|
||||
console.appendChild(document.createElement('br'));
|
||||
}
|
||||
|
||||
var dialog = document.querySelector('dialog');
|
||||
dialogPolyfill.registerDialog(dialog);
|
||||
dialog.showModal();
|
||||
|
||||
var dialogButton = document.getElementById('dialog-button');
|
||||
dialogButton.addEventListener('click', function(e) {
|
||||
writeToConsole("SUCCESS: dialog's button was clicked");
|
||||
});
|
||||
|
||||
var inertButton = document.getElementById('inert-button');
|
||||
inertButton.addEventListener('click', function(e) {
|
||||
writeToConsole('FAIL: inert button was clicked');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 140 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 215 B |
|
@ -0,0 +1,59 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset='utf-8'>
|
||||
<head>
|
||||
<script src="../dialog-polyfill.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../dialog-polyfill.css">
|
||||
<style>
|
||||
dialog {
|
||||
display: none;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
dialog.left {
|
||||
top: 100px;
|
||||
left: 100px;
|
||||
}
|
||||
|
||||
#middle {
|
||||
top: 100px;
|
||||
left: 200px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test that dialogs with an explicit static position don't get auto-centered.
|
||||
The test passes if there are three boxes aligned in a single row.</p>
|
||||
<div id="console"></div>
|
||||
<dialog id="left" class="left"></dialog>
|
||||
<dialog id="middle"></dialog>
|
||||
<dialog id="right"></dialog>
|
||||
<script>
|
||||
function writeToConsole(s) {
|
||||
var console = document.getElementById('console');
|
||||
var span = document.createElement('span');
|
||||
span.textContent = s;
|
||||
console.appendChild(span);
|
||||
console.appendChild(document.createElement('br'));
|
||||
}
|
||||
|
||||
var dialogs = document.querySelectorAll('dialog');
|
||||
for (var i = 0; i < dialogs.length; ++i)
|
||||
dialogPolyfill.registerDialog(dialogs[i]);
|
||||
|
||||
var leftDialog = document.getElementById('left');
|
||||
leftDialog.show();
|
||||
|
||||
var middleDialog = document.getElementById('middle');
|
||||
middleDialog.show();
|
||||
|
||||
var rightDialog = document.getElementById('right');
|
||||
rightDialog.style.top = '100px';
|
||||
rightDialog.style.left = '300px';
|
||||
rightDialog.show();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче