en.javascript.info/archive/widget-tasks/3-window-manager/solution.view/draggableWindow.js
2015-02-21 14:58:02 +03:00

142 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// если начать перенос и передвинуть мышь максимально вверх -- верхний край окна не должен вылетать за край страницы.
// в другие стороны
// чтобы даже при резких движениях мыши -- окно прилипало к краю но не вылезало за край
// исключение -- максимальная нижняя позиция окна -- это когда только заголовок виден
// позиция мыши смещается
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') + "]";
}
}