init
This commit is contained in:
parent
06f61d8ce8
commit
f301cb744d
2271 changed files with 103162 additions and 0 deletions
1
02-ui/05-widgets/08-widget-tasks-2/03-window-manager/solution/.plnkr
Executable file
1
02-ui/05-widgets/08-widget-tasks-2/03-window-manager/solution/.plnkr
Executable file
|
@ -0,0 +1 @@
|
|||
{"name":"window","plunk":"4EQ5K3IYSLg2jE7DOgpy"}
|
126
02-ui/05-widgets/08-widget-tasks-2/03-window-manager/solution/draggableWindow.js
Executable file
126
02-ui/05-widgets/08-widget-tasks-2/03-window-manager/solution/draggableWindow.js
Executable file
|
@ -0,0 +1,126 @@
|
|||
// если начать перенос и передвинуть мышь максимально вверх -- верхний край окна не должен вылетать за край страницы.
|
||||
// в другие стороны
|
||||
|
||||
// чтобы даже при резких движениях мыши -- окно прилипало к краю но не вылезало за край
|
||||
// исключение -- максимальная нижняя позиция окна -- это когда только заголовок виден
|
||||
|
||||
// позиция мыши смещается
|
||||
function DraggableWindow(options) {
|
||||
var self = this;
|
||||
|
||||
var title = options.title;
|
||||
var template = typeof options.template == 'function' ? // компиляция, если строка
|
||||
options.template : _.template(options.template);
|
||||
|
||||
var elem, contentElem;
|
||||
|
||||
var mouseDownShift;
|
||||
|
||||
function render() {
|
||||
elem = $('<div/>', {
|
||||
"class": "window",
|
||||
html: template({
|
||||
title: title
|
||||
})
|
||||
});
|
||||
|
||||
$('form', elem).on('submit', onSubmit);
|
||||
|
||||
titleElem = elem.find('.window-title');
|
||||
|
||||
titleElem.on('selectstart dragstart', false);
|
||||
titleElem.on('mousedown', onTitleMouseDown);
|
||||
|
||||
contentElem = elem.find('.window-content'); // = children[1]
|
||||
}
|
||||
|
||||
this.getElement = function() {
|
||||
if (!elem) render();
|
||||
return elem;
|
||||
}
|
||||
|
||||
function onTitleMouseDown(e) {
|
||||
startDrag(e.pageX, e.pageY);
|
||||
return false;
|
||||
};
|
||||
|
||||
function startDrag(mouseDownX, mouseDownY) {
|
||||
// запомнить координаты нажатия
|
||||
var coords = elem.offset();
|
||||
mouseDownShift = {
|
||||
x: mouseDownX - coords.left,
|
||||
y: mouseDownY - coords.top
|
||||
};
|
||||
|
||||
// двигать
|
||||
$(document).on({
|
||||
'mousemove.draggablewindow': onDocumentMouseMove,
|
||||
'mouseup.draggablewindow': onDocumentMouseUp
|
||||
});
|
||||
|
||||
elem.addClass('window-moving');
|
||||
}
|
||||
|
||||
function onDocumentMouseUp() {
|
||||
$(document).off('.draggablewindow');
|
||||
elem.removeClass('window-moving');
|
||||
}
|
||||
|
||||
function onDocumentMouseMove(e) {
|
||||
moveWindowAtCursor(e.pageX, e.pageY);
|
||||
}
|
||||
|
||||
function moveWindowAtCursor(pageX, pageY) {
|
||||
var newLeft = pageX - mouseDownShift.x;
|
||||
var newTop = pageY - mouseDownShift.y;
|
||||
|
||||
// проверим, не вылезем ли мы за границы экрана
|
||||
var windowLeft = window.pageXOffset || document.documentElement.scrollLeft;
|
||||
var windowTop = window.pageYOffset || document.documentElement.scrollTop;
|
||||
var windowRight = windowLeft + document.documentElement.clientWidth;
|
||||
var windowBottom = windowTop + document.documentElement.clientHeight;
|
||||
|
||||
// тут не if..else, а if т.к., возможно, обе координаты надо поправить
|
||||
if (newLeft < windowLeft) {
|
||||
newLeft = windowLeft;
|
||||
}
|
||||
if (newLeft > windowRight - elem.outerWidth()) {
|
||||
newLeft = windowRight - elem.outerWidth(); // внешняя ширина с учетом рамки внешней
|
||||
}
|
||||
if (newTop < windowTop) {
|
||||
newTop = windowTop;
|
||||
}
|
||||
if (newTop > windowBottom - titleElem.outerHeight()) {
|
||||
newTop = windowBottom - titleElem.outerHeight();
|
||||
// внизу заголовок будет немного залезать за край, т.к. нужно мерять вместе с рамкой верхней на самом деле
|
||||
// но здесь это не страшно
|
||||
}
|
||||
|
||||
elem.css({
|
||||
left: newLeft,
|
||||
top: newTop
|
||||
});
|
||||
};
|
||||
|
||||
function onSubmit(e) {
|
||||
// принять события, совершить обработку события, связанную с формой
|
||||
var form = e.currentTarget;
|
||||
var value = form.elements.message.value;
|
||||
form.elements.message.value = '';
|
||||
if (value) {
|
||||
submit(value); // логика по отправке сообщения
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function submit(message) {
|
||||
// добавить
|
||||
var newMessageElem = $('<div>', {text: message }).appendTo(contentElem);
|
||||
|
||||
// прокрутить к новому сообщению
|
||||
contentElem.prop('scrollTop', 999999999);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
45
02-ui/05-widgets/08-widget-tasks-2/03-window-manager/solution/index.html
Executable file
45
02-ui/05-widgets/08-widget-tasks-2/03-window-manager/solution/index.html
Executable file
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script src="http://code.jquery.com/jquery.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>
|
||||
<link type="text/css" rel="stylesheet" href="window.css" />
|
||||
<style>
|
||||
html, body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
<script src="draggableWindow.js"></script>
|
||||
</head>
|
||||
<body style="height:2000px">
|
||||
|
||||
Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст
|
||||
Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст
|
||||
Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст
|
||||
Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст
|
||||
Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст
|
||||
Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст
|
||||
|
||||
<script type="text/template" id="draggable-window-template">
|
||||
<div class="window-title"><%=title%></div>
|
||||
<div class="window-content"></div>
|
||||
<form class="window-message-form">
|
||||
<input type="text" name="message" class="window-message-text"><input type="submit" name="submit" class="window-message-submit" value="Послать">
|
||||
</form>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
||||
var win = new DraggableWindow({
|
||||
title: "Чат с Петей",
|
||||
template: $('#draggable-window-template').html()
|
||||
});
|
||||
|
||||
win.getElement().appendTo('body');
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
{"name":"window-manager","plunk":"WahQdnjtnXesAuix7gsv"}
|
|
@ -0,0 +1,142 @@
|
|||
// если начать перенос и передвинуть мышь максимально вверх -- верхний край окна не должен вылетать за край страницы.
|
||||
// в другие стороны
|
||||
|
||||
// чтобы даже при резких движениях мыши -- окно прилипало к краю но не вылезало за край
|
||||
// исключение -- максимальная нижняя позиция окна -- это когда только заголовок виден
|
||||
|
||||
// позиция мыши смещается
|
||||
function DraggableWindow(options) {
|
||||
var self = this;
|
||||
|
||||
var title = options.title;
|
||||
var template = typeof options.template == 'function' ? // компиляция, если строка
|
||||
options.template : _.template(options.template);
|
||||
|
||||
var elem, contentElem;
|
||||
|
||||
var mouseDownShift;
|
||||
|
||||
function render() {
|
||||
elem = $('<div tabindex="0" class="window"/>').html(template({
|
||||
title: title
|
||||
}));
|
||||
|
||||
$('form', elem).on('submit', onSubmit);
|
||||
|
||||
titleElem = elem.find('.window-title');
|
||||
|
||||
titleElem.on('selectstart dragstart', false);
|
||||
titleElem.on('mousedown', onTitleMouseDown);
|
||||
|
||||
contentElem = elem.find('.window-content'); // = children[1]
|
||||
elem.on('focusin', onFocus);
|
||||
}
|
||||
|
||||
this.getElement = function() {
|
||||
if (!elem) render();
|
||||
return elem;
|
||||
}
|
||||
|
||||
function onFocus() {
|
||||
$(self).triggerHandler({ type: 'focus' });
|
||||
}
|
||||
|
||||
function onTitleMouseDown(e) {
|
||||
startDrag(e.pageX, e.pageY);
|
||||
|
||||
setTimeout(onFocus, 0);
|
||||
return false; // returning false prevents onfocus
|
||||
};
|
||||
|
||||
function startDrag(mouseDownX, mouseDownY) {
|
||||
// запомнить координаты нажатия
|
||||
var coords = elem.offset();
|
||||
mouseDownShift = {
|
||||
x: mouseDownX - coords.left,
|
||||
y: mouseDownY - coords.top
|
||||
};
|
||||
|
||||
// двигать
|
||||
$(document).on({
|
||||
'mousemove.draggablewindow': onDocumentMouseMove,
|
||||
'mouseup.draggablewindow': onDocumentMouseUp
|
||||
});
|
||||
|
||||
elem.addClass('window-moving');
|
||||
}
|
||||
|
||||
function onDocumentMouseUp() {
|
||||
$(document).off('.draggablewindow');
|
||||
elem.removeClass('window-moving');
|
||||
}
|
||||
|
||||
function onDocumentMouseMove(e) {
|
||||
moveWindowAtCursor(e.pageX, e.pageY);
|
||||
}
|
||||
|
||||
function moveWindowAtCursor(pageX, pageY) {
|
||||
var newLeft = pageX - mouseDownShift.x;
|
||||
var newTop = pageY - mouseDownShift.y;
|
||||
|
||||
// проверим, не вылезем ли мы за границы экрана
|
||||
var windowLeft = window.pageXOffset || document.documentElement.scrollLeft;
|
||||
var windowTop = window.pageYOffset || document.documentElement.scrollTop;
|
||||
var windowRight = windowLeft + document.documentElement.clientWidth;
|
||||
var windowBottom = windowTop + document.documentElement.clientHeight;
|
||||
|
||||
// тут не if..else, а if т.к., возможно, обе координаты надо поправить
|
||||
if (newLeft < windowLeft) {
|
||||
newLeft = windowLeft;
|
||||
}
|
||||
if (newLeft > windowRight - elem.outerWidth()) {
|
||||
newLeft = windowRight - elem.outerWidth(); // внешняя ширина с учетом рамки внешней
|
||||
}
|
||||
if (newTop < windowTop) {
|
||||
newTop = windowTop;
|
||||
}
|
||||
if (newTop > windowBottom - titleElem.outerHeight()) {
|
||||
newTop = windowBottom - titleElem.outerHeight();
|
||||
// внизу заголовок будет немного залезать за край, т.к. нужно мерять вместе с рамкой верхней на самом деле
|
||||
// но здесь это не страшно
|
||||
}
|
||||
|
||||
elem.css({
|
||||
left: newLeft,
|
||||
top: newTop
|
||||
});
|
||||
};
|
||||
|
||||
function onSubmit(e) {
|
||||
// принять события, совершить обработку события, связанную с формой
|
||||
var form = e.currentTarget;
|
||||
var value = form.elements.message.value;
|
||||
form.elements.message.value = '';
|
||||
if (value) {
|
||||
submit(value); // логика по отправке сообщения
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function submit(message) {
|
||||
// добавить
|
||||
var newMessageElem = $('<div>', {text: message }).appendTo(contentElem);
|
||||
|
||||
// прокрутить к новому сообщению
|
||||
contentElem.prop('scrollTop', 999999999);
|
||||
}
|
||||
|
||||
|
||||
this.setZIndex = function(zIndex) {
|
||||
elem.css('z-index', zIndex);
|
||||
};
|
||||
|
||||
this.getZIndex = function() {
|
||||
return +elem.css('z-index') || 0;
|
||||
};
|
||||
|
||||
this.toString = function() {
|
||||
return "[Window " + options.title + " " + elem.css('z-index') + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script src="http://code.jquery.com/jquery.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>
|
||||
<link type="text/css" rel="stylesheet" href="window.css" />
|
||||
<style>
|
||||
html, body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
<script src="draggableWindow.js"></script>
|
||||
<script src="windowManager.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст
|
||||
Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст
|
||||
Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст
|
||||
Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст
|
||||
Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст
|
||||
Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст Текст
|
||||
|
||||
<script type="text/template" id="draggable-window-template">
|
||||
<div class="window-title"><%=title%></div>
|
||||
<div class="window-content"></div>
|
||||
<form class="window-message-form">
|
||||
<input type="text" name="message" class="window-message-text"><input type="submit" name="submit" class="window-message-submit" value="Послать">
|
||||
</form>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
WindowManager.setTemplate( $('#draggable-window-template').html().trim() );
|
||||
|
||||
WindowManager.addWindow({
|
||||
title: "Чат с Петей"
|
||||
});
|
||||
|
||||
WindowManager.addWindow({
|
||||
title: "Чат с Машей"
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,56 @@
|
|||
|
||||
.window {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
|
||||
width: 200px;
|
||||
height: 300px;
|
||||
border: 2px #ADD8E6 groove;
|
||||
/* раскомментировать для проверки, вылезает ли внешняя рамка за экран
|
||||
border: 2px red solid;
|
||||
*/
|
||||
background: white;
|
||||
}
|
||||
|
||||
.window-title {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
|
||||
background-color: #4169E1;
|
||||
color: white;
|
||||
text-align:center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.window-moving .window-title {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.window-message-form {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
width: 100%;
|
||||
|
||||
background: #ADD8E6;
|
||||
}
|
||||
|
||||
.window-content {
|
||||
height: 240px;
|
||||
padding: 3px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.window-message-text {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.window-message-submit {
|
||||
width: 70px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
var WindowManager = new function() {
|
||||
|
||||
var windows = [];
|
||||
var activeWindow;
|
||||
|
||||
var template;
|
||||
|
||||
this.setTemplate = function(newTemplate) {
|
||||
template = _.template(newTemplate);
|
||||
};
|
||||
|
||||
this.addWindow = function(options) {
|
||||
|
||||
var win = new DraggableWindow({
|
||||
title: options.title,
|
||||
template: template
|
||||
});
|
||||
|
||||
$(win).on("focus", function() {
|
||||
activateWindow(this);
|
||||
});
|
||||
|
||||
win.getElement().appendTo('body');
|
||||
|
||||
windows.push(win);
|
||||
activateWindow(win);
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
function activateWindow(win) {
|
||||
if (activeWindow == win) return;
|
||||
activeWindow = win;
|
||||
sortWindows();
|
||||
}
|
||||
|
||||
/**
|
||||
* пересортировать окна
|
||||
*/
|
||||
function sortWindows() {
|
||||
windows.sort(function(a, b) {
|
||||
if (activeWindow == a) return 1; // активное окно больше всех
|
||||
if (activeWindow == b) return -1; // активное окно больше всех
|
||||
return a.getZIndex() - b.getZIndex(); // порядок среди остальных - оставляем "как есть"
|
||||
});
|
||||
for(var i=0; i<windows.length; i++) {
|
||||
windows[i].setZIndex(i+1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
56
02-ui/05-widgets/08-widget-tasks-2/03-window-manager/solution/window.css
Executable file
56
02-ui/05-widgets/08-widget-tasks-2/03-window-manager/solution/window.css
Executable file
|
@ -0,0 +1,56 @@
|
|||
|
||||
.window {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
|
||||
width: 200px;
|
||||
height: 300px;
|
||||
border: 2px #ADD8E6 groove;
|
||||
/* раскомментировать для проверки, вылезает ли внешняя рамка за экран
|
||||
border: 2px red solid;
|
||||
*/
|
||||
background: white;
|
||||
}
|
||||
|
||||
.window-title {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
|
||||
background-color: #4169E1;
|
||||
color: white;
|
||||
text-align:center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.window-moving .window-title {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.window-message-form {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
width: 100%;
|
||||
|
||||
background: #ADD8E6;
|
||||
}
|
||||
|
||||
.window-content {
|
||||
height: 240px;
|
||||
padding: 3px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.window-message-text {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.window-message-submit {
|
||||
width: 70px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue