alertifyjs
Version:
AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
216 lines (191 loc) • 7.88 kB
JavaScript
/* Controls moving a dialog around */
//holde the current moving instance
var movable = null,
//holds the current X offset when move starts
offsetX = 0,
//holds the current Y offset when move starts
offsetY = 0,
xProp = 'pageX',
yProp = 'pageY',
bounds = null,
refreshTop = false,
moveDelegate = null
;
/**
* Helper: sets the element top/left coordinates
*
* @param {Event} event DOM event object.
* @param {Node} element The element being moved.
*
* @return {undefined}
*/
function moveElement(event, element) {
var left = (event[xProp] - offsetX),
top = (event[yProp] - offsetY);
if(refreshTop){
top -= document.body.scrollTop;
}
element.style.left = left + 'px';
element.style.top = top + 'px';
}
/**
* Helper: sets the element top/left coordinates within screen bounds
*
* @param {Event} event DOM event object.
* @param {Node} element The element being moved.
*
* @return {undefined}
*/
function moveElementBounded(event, element) {
var left = (event[xProp] - offsetX),
top = (event[yProp] - offsetY);
if(refreshTop){
top -= document.body.scrollTop;
}
element.style.left = Math.min(bounds.maxLeft, Math.max(bounds.minLeft, left)) + 'px';
if(refreshTop){
element.style.top = Math.min(bounds.maxTop, Math.max(bounds.minTop, top)) + 'px';
}else{
element.style.top = Math.max(bounds.minTop, top) + 'px';
}
}
/**
* Triggers the start of a move event, attached to the header element mouse down event.
* Adds no-selection class to the body, disabling selection while moving.
*
* @param {Event} event DOM event object.
* @param {Object} instance The dilog instance.
*
* @return {Boolean} false
*/
function beginMove(event, instance) {
if (resizable === null && !instance.isMaximized() && instance.get('movable')) {
var eventSrc, left=0, top=0;
if (event.type === 'touchstart') {
event.preventDefault();
eventSrc = event.targetTouches[0];
xProp = 'clientX';
yProp = 'clientY';
} else if (event.button === 0) {
eventSrc = event;
}
if (eventSrc) {
var element = instance.elements.dialog;
addClass(element, classes.capture);
if (element.style.left) {
left = parseInt(element.style.left, 10);
}
if (element.style.top) {
top = parseInt(element.style.top, 10);
}
offsetX = eventSrc[xProp] - left;
offsetY = eventSrc[yProp] - top;
if(instance.isModal()){
offsetY += instance.elements.modal.scrollTop;
}else if(instance.isPinned()){
offsetY -= document.body.scrollTop;
}
if(instance.get('moveBounded')){
var current = element,
offsetLeft = -left,
offsetTop = -top;
//calc offset
do {
offsetLeft += current.offsetLeft;
offsetTop += current.offsetTop;
} while (current = current.offsetParent);
bounds = {
maxLeft : offsetLeft,
minLeft : -offsetLeft,
maxTop : document.documentElement.clientHeight - element.clientHeight - offsetTop,
minTop : -offsetTop
};
moveDelegate = moveElementBounded;
}else{
bounds = null;
moveDelegate = moveElement;
}
// allow custom `onmove` method
dispatchEvent('onmove', instance);
refreshTop = !instance.isModal() && instance.isPinned();
movable = instance;
moveDelegate(eventSrc, element);
addClass(document.body, classes.noSelection);
return false;
}
}
}
/**
* The actual move handler, attached to document.body mousemove event.
*
* @param {Event} event DOM event object.
*
* @return {undefined}
*/
function move(event) {
if (movable) {
var eventSrc;
if (event.type === 'touchmove') {
event.preventDefault();
eventSrc = event.targetTouches[0];
} else if (event.button === 0) {
eventSrc = event;
}
if (eventSrc) {
moveDelegate(eventSrc, movable.elements.dialog);
}
}
}
/**
* Triggers the end of a move event, attached to document.body mouseup event.
* Removes no-selection class from document.body, allowing selection.
*
* @return {undefined}
*/
function endMove() {
if (movable) {
var instance = movable;
movable = bounds = null;
removeClass(document.body, classes.noSelection);
removeClass(instance.elements.dialog, classes.capture);
// allow custom `onmoved` method
dispatchEvent('onmoved', instance);
}
}
/**
* Resets any changes made by moving the element to its original state,
*
* @param {Object} instance The dilog instance.
*
* @return {undefined}
*/
function resetMove(instance) {
movable = null;
var element = instance.elements.dialog;
element.style.left = element.style.top = '';
}
/**
* Updates the dialog move behavior.
*
* @param {Object} instance The dilog instance.
* @param {Boolean} on True to add the behavior, removes it otherwise.
*
* @return {undefined}
*/
function updateMovable(instance) {
if (instance.get('movable')) {
// add class
addClass(instance.elements.root, classes.movable);
if (instance.isOpen()) {
bindMovableEvents(instance);
}
} else {
//reset
resetMove(instance);
// remove class
removeClass(instance.elements.root, classes.movable);
if (instance.isOpen()) {
unbindMovableEvents(instance);
}
}
}