This commit is contained in:
Ilya Kantor 2017-03-19 16:59:53 +03:00
parent af0ee2a49e
commit e2443e8de6
115 changed files with 3177 additions and 866 deletions

View file

@ -1,8 +1,4 @@
Модальное окно делается путём добавления к документу `DIV`, полностью перекрывающего документ и имеющего больший `z-index`.
В результате все клики будут доставаться этому `DIV'у`:
Стиль:
A modal window can be implemented using a half-transparent `<div id="cover-div">` that covers the whole window, like this:
```css
#cover-div {
@ -17,5 +13,8 @@
}
```
Самой форме можно дать еще больший `z-index`, чтобы она была над `DIV'ом`. Мы не помещаем форму в контейнер, чтобы она не унаследовала полупрозрачность.
Because the `<div>` covers everything, it gets all clicks, not the page below it.
Also we can prevent page scroll by setting `body.style.overflowY='hidden'`.
The form should be not in the `<div>`, but next to it, because we don't want it to have `opacity`.

View file

@ -3,96 +3,49 @@
<head>
<meta charset="utf-8">
<style>
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#prompt-form {
display: inline-block;
padding: 5px 5px 5px 70px;
width: 200px;
border: 1px solid black;
background: white url(https://js.cx/clipart/prompt.png) no-repeat left 5px;
vertical-align: middle;
}
#prompt-form-container {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
display: none;
width: 100%;
height: 100%;
text-align: center;
}
#prompt-form-container:before {
display: inline-block;
height: 100%;
content: '';
vertical-align: middle;
}
#cover-div {
position: fixed;
top: 0;
left: 0;
z-index: 9000;
width: 100%;
height: 100%;
background-color: gray;
opacity: 0.3;
}
#prompt-form input[name="text"] {
display: block;
margin: 5px;
width: 180px;
}
</style>
<link rel="stylesheet" href="style.css">
</head>
<body style="height:3000px">
<h1>Нажмите на кнопку ниже</h1>
<h2>Click the button below</h2>
<input type="button" value="Нажмите для показа формы ввода" id="show-button">
<input type="button" value="Click to show the form" id="show-button">
<div id="prompt-form-container">
<form id="prompt-form">
<div id="prompt-message"></div>
<input name="text" type="text">
<input type="submit" value="Ок">
<input type="button" name="cancel" value="Отмена">
<input type="submit" value="Ok">
<input type="button" name="cancel" value="Cancel">
</form>
</div>
<script>
// Показать полупрозрачный DIV, затеняющий всю страницу
// (а форма будет не в нем, а рядом с ним, чтобы не полупрозрачная)
// Show a half-transparent DIV to "shadow" the page
// (the form is not inside, but near it, because it shouldn't be half-transparent)
function showCover() {
var coverDiv = document.createElement('div');
let coverDiv = document.createElement('div');
coverDiv.id = 'cover-div';
document.body.appendChild(coverDiv);
// make the page unscrollable while the modal form is open
document.body.style.overflowY = 'hidden';
document.body.append(coverDiv);
}
function hideCover() {
document.body.removeChild(document.getElementById('cover-div'));
document.getElementById('cover-div').remove();
document.body.style.overflowY = '';
}
function showPrompt(text, callback) {
showCover();
var form = document.getElementById('prompt-form');
var container = document.getElementById('prompt-form-container');
let form = document.getElementById('prompt-form');
let container = document.getElementById('prompt-form-container');
document.getElementById('prompt-message').innerHTML = text;
form.elements.text.value = '';
form.text.value = '';
function complete(value) {
hideCover();
@ -102,54 +55,51 @@
}
form.onsubmit = function() {
var value = form.elements.text.value;
if (value == '') return false; // игнорировать пустой submit
let value = form.text.value;
if (value == '') return false; // ignore empty submit
complete(value);
return false;
};
form.elements.cancel.onclick = function() {
form.cancel.onclick = function() {
complete(null);
};
document.onkeydown = function(e) {
if (e.keyCode == 27) { // escape
if (e.key == 'Escape') {
complete(null);
}
};
var lastElem = form.elements[form.elements.length - 1];
var firstElem = form.elements[0];
let lastElem = form.elements[form.elements.length - 1];
let firstElem = form.elements[0];
lastElem.onkeydown = function(e) {
if (e.keyCode == 9 && !e.shiftKey) {
if (e.key == 'Tab' && !e.shiftKey) {
firstElem.focus();
return false;
}
};
firstElem.onkeydown = function(e) {
if (e.keyCode == 9 && e.shiftKey) {
if (e.key == 'Tab' && e.shiftKey) {
lastElem.focus();
return false;
}
};
container.style.display = 'block';
form.elements.text.focus();
}
document.getElementById('show-button').onclick = function() {
showPrompt("Введите что-нибудь<br>...умное :)", function(value) {
alert("Вы ввели: " + value);
showPrompt("Enter something<br>...smart :)", function(value) {
alert("You entered: " + value);
});
};
</script>
</body>
</html>
</html>

View file

@ -0,0 +1,51 @@
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#prompt-form {
display: inline-block;
padding: 5px 5px 5px 70px;
width: 200px;
border: 1px solid black;
background: white url(https://en.js.cx/clipart/prompt.png) no-repeat left 5px;
vertical-align: middle;
}
#prompt-form-container {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
display: none;
width: 100%;
height: 100%;
text-align: center;
}
#prompt-form-container:before {
display: inline-block;
height: 100%;
content: '';
vertical-align: middle;
}
#cover-div {
position: fixed;
top: 0;
left: 0;
z-index: 9000;
width: 100%;
height: 100%;
background-color: gray;
opacity: 0.3;
}
#prompt-form input[name="text"] {
display: block;
margin: 5px;
width: 180px;
}

View file

@ -3,47 +3,7 @@
<head>
<meta charset="utf-8">
<style>
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
#prompt-form {
display: inline-block;
padding: 5px 5px 5px 70px;
width: 200px;
border: 1px solid black;
background: white url(https://js.cx/clipart/prompt.png) no-repeat left 5px;
vertical-align: middle;
}
#prompt-form-container {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
width: 100%;
height: 100%;
text-align: center;
}
#prompt-form-container:before {
display: inline-block;
height: 100%;
content: '';
vertical-align: middle;
}
#prompt-form input[name="text"] {
display: block;
margin: 5px;
width: 180px;
}
</style>
<link rel="stylesheet" href="style.css">
</head>
<body>
@ -51,15 +11,15 @@
<div id="prompt-form-container">
<form id="prompt-form">
<div id="prompt-message">Введите, пожалуйста...
<br>Что-то..</div>
<div id="prompt-message">Enter something...
<br>Please..</div>
<input name="text" type="text">
<input type="submit" value="Ок">
<input type="button" name="cancel" value="Отмена">
<input type="submit" value="Ok">
<input type="button" name="cancel" value="Cancel">
</form>
</div>
</body>
</html>
</html>

View file

@ -0,0 +1,39 @@
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
#prompt-form {
display: inline-block;
padding: 5px 5px 5px 70px;
width: 200px;
border: 1px solid black;
background: white url(https://en.js.cx/clipart/prompt.png) no-repeat left 5px;
vertical-align: middle;
}
#prompt-form-container {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
width: 100%;
height: 100%;
text-align: center;
}
#prompt-form-container:before {
display: inline-block;
height: 100%;
content: '';
vertical-align: middle;
}
#prompt-form input[name="text"] {
display: block;
margin: 5px;
width: 180px;
}

View file

@ -2,32 +2,32 @@ importance: 5
---
# Модальное диалоговое окно
# Modal form
Создайте функцию `showPrompt(text, callback)`, которая выводит форму для ввода с сообщением `text` и кнопками `ОК/Отмена`.
Create a function `showPrompt(html, callback)` that shows a form with the message `html`, an input field and buttons `OK/CANCEL`.
- При отправке формы (OK/ввод в текстовом поле) -- должна вызываться функция `callback` со значением поля.
- При нажатии на `Отмена` или на клавишу `key:Esc` -- должна вызываться функция `callback(null)`. Клавиша `key:Esc` должна закрывать форму всегда, даже если поле для ввода сообщения не в фокусе.
- A user should type something into a text field and press `key:Enter` or the OK button, then `callback(value)` is called with the value he entered.
- Otherwise if the user presses `key:Esc` or CANCEL, then `callback(null)` is called.
Особенности реализации:
In both cases that ends the input process and removes the form.
- Форма должна показываться в центре окна (и оставаться в центре при изменении его размеров, а также при прокрутке окна!).
- Текст может состоять из нескольких строк, возможен любой HTML
- При показе формы остальные элементы страницы использовать нельзя, не работают другие кнопки и т.п, это окно -- *модальное*.
- При показе формы -- сразу фокус на `INPUT` для ввода.
- Нажатия `key:Tab`/`key:Shift+Tab` переключают в цикле только по полям формы, они не позволяют переключиться на другие элементы страницы.
Requirements:
- The form should be in the center of the window.
- The form is *modal*. In other words, no interaction with the rest of the page is possible until the user closes it.
- When the form is shown, the focus should be inside the `<input>` for the user.
- Keys `key:Tab`/`key:Shift+Tab` should shift the focus between form fields, don't allow it to leave for other page elements.
Пример использования:
```js
showPrompt("Введите что-нибудь<br>... умное :)", function(value) {
alert( value );
showPrompt("Enter something<br>...smart :)", function(value) {
alert(value);
});
```
Демо в ифрейме:
A demo in the iframe:
[iframe src="solution" height=160 border=1]
Исходный HTML/CSS для формы с готовым fixed-позиционированием - в песочнице.
P.S. The source document has HTML/CSS for the form with fixed positioning, but it's up to you to make it modal.