alertifyjs
Version:
AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
220 lines (206 loc) • 8.73 kB
JavaScript
/* Controls moving a dialog around */
//holde the current instance being resized
var resizable = null,
//holds the staring left offset when resize starts.
startingLeft = Number.Nan,
//holds the staring width when resize starts.
startingWidth = 0,
//holds the initial width when resized for the first time.
minWidth = 0,
//holds the offset of the resize handle.
handleOffset = 0
;
/**
* Helper: sets the element width/height and updates left coordinate if neccessary.
*
* @param {Event} event DOM mousemove event object.
* @param {Node} element The element being moved.
* @param {Boolean} pinned A flag indicating if the element being resized is pinned to the screen.
*
* @return {undefined}
*/
function resizeElement(event, element, pageRelative) {
//calculate offsets from 0,0
var current = element;
var offsetLeft = 0;
var offsetTop = 0;
do {
offsetLeft += current.offsetLeft;
offsetTop += current.offsetTop;
} while (current = current.offsetParent);
// determine X,Y coordinates.
var X, Y;
if (pageRelative === true) {
X = event.pageX;
Y = event.pageY;
} else {
X = event.clientX;
Y = event.clientY;
}
// rtl handling
var isRTL = isRightToLeft();
if (isRTL) {
// reverse X
X = document.body.offsetWidth - X;
// if has a starting left, calculate offsetRight
if (!isNaN(startingLeft)) {
offsetLeft = document.body.offsetWidth - offsetLeft - element.offsetWidth;
}
}
// set width/height
element.style.height = (Y - offsetTop + handleOffset) + 'px';
element.style.width = (X - offsetLeft + handleOffset) + 'px';
// if the element being resized has a starting left, maintain it.
// the dialog is centered, divide by half the offset to maintain the margins.
if (!isNaN(startingLeft)) {
var diff = Math.abs(element.offsetWidth - startingWidth) * 0.5;
if (isRTL) {
//negate the diff, why?
//when growing it should decrease left
//when shrinking it should increase left
diff *= -1;
}
if (element.offsetWidth > startingWidth) {
//growing
element.style.left = (startingLeft + diff) + 'px';
} else if (element.offsetWidth >= minWidth) {
//shrinking
element.style.left = (startingLeft - diff) + 'px';
}
}
}
/**
* Triggers the start of a resize event, attached to the resize handle 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 beginResize(event, instance) {
if (!instance.isMaximized()) {
var eventSrc;
if (event.type === 'touchstart') {
event.preventDefault();
eventSrc = event.targetTouches[0];
} else if (event.button === 0) {
eventSrc = event;
}
if (eventSrc) {
// allow custom `onresize` method
dispatchEvent('onresize', instance);
resizable = instance;
handleOffset = instance.elements.resizeHandle.offsetHeight / 2;
var element = instance.elements.dialog;
addClass(element, classes.capture);
startingLeft = parseInt(element.style.left, 10);
element.style.height = element.offsetHeight + 'px';
element.style.minHeight = instance.elements.header.offsetHeight + instance.elements.footer.offsetHeight + 'px';
element.style.width = (startingWidth = element.offsetWidth) + 'px';
if (element.style.maxWidth !== 'none') {
element.style.minWidth = (minWidth = element.offsetWidth) + 'px';
}
element.style.maxWidth = 'none';
addClass(document.body, classes.noSelection);
return false;
}
}
}
/**
* The actual resize handler, attached to document.body mousemove event.
*
* @param {Event} event DOM event object.
*
* @return {undefined}
*/
function resize(event) {
if (resizable) {
var eventSrc;
if (event.type === 'touchmove') {
event.preventDefault();
eventSrc = event.targetTouches[0];
} else if (event.button === 0) {
eventSrc = event;
}
if (eventSrc) {
resizeElement(eventSrc, resizable.elements.dialog, !resizable.get('modal') && !resizable.get('pinned'));
}
}
}
/**
* Triggers the end of a resize event, attached to document.body mouseup event.
* Removes no-selection class from document.body, allowing selection.
*
* @return {undefined}
*/
function endResize() {
if (resizable) {
var instance = resizable;
resizable = null;
removeClass(document.body, classes.noSelection);
removeClass(instance.elements.dialog, classes.capture);
cancelClick = true;
// allow custom `onresized` method
dispatchEvent('onresized', instance);
}
}
/**
* Resets any changes made by resizing the element to its original state.
*
* @param {Object} instance The dilog instance.
*
* @return {undefined}
*/
function resetResize(instance) {
resizable = null;
var element = instance.elements.dialog;
if (element.style.maxWidth === 'none') {
//clear inline styles.
element.style.maxWidth = element.style.minWidth = element.style.width = element.style.height = element.style.minHeight = element.style.left = '';
//reset variables.
startingLeft = Number.Nan;
startingWidth = minWidth = handleOffset = 0;
}
}
/**
* 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 updateResizable(instance) {
if (instance.get('resizable')) {
// add class
addClass(instance.elements.root, classes.resizable);
if (instance.isOpen()) {
bindResizableEvents(instance);
}
} else {
//reset
resetResize(instance);
// remove class
removeClass(instance.elements.root, classes.resizable);
if (instance.isOpen()) {
unbindResizableEvents(instance);
}
}
}
/**
* Reset move/resize on window resize.
*
* @param {Event} event window resize event object.
*
* @return {undefined}
*/
function windowResize(/*event*/) {
for (var x = 0; x < openDialogs.length; x += 1) {
var instance = openDialogs[x];
if (instance.get('autoReset')) {
resetMove(instance);
resetResize(instance);
}
}
}