jellyfin-web/dashboard-ui/components/navdrawer/navdrawer.js
2016-06-21 11:26:15 -04:00

257 lines
8.0 KiB
JavaScript

define(['hammer', 'css!./navdrawer'], function (Hammer) {
return function (options) {
var self,
defaults,
menuClassName = '',
mask,
maskHammer,
menuHammer,
newPos = 0,
currentPos = 0,
startPoint = 0,
countStart = 0,
velocity = 0.0;
options.target.classList.add('transition');
var draggingX;
var draggingY;
var scrollContainer = options.target.querySelector('.scrollContainer');
var TouchMenuLA = function () {
self = this;
defaults = {
width: 280,
handleSize: 30,
disableMask: false,
maxMaskOpacity: 0.5
};
this.isVisible = false;
this.initialize();
};
TouchMenuLA.prototype.setDefaultsOptions = function () {
for (var key in defaults) {
if (!options[key]) {
options[key] = defaults[key];
}
}
};
TouchMenuLA.prototype.initElements = function () {
options.target.classList.add('touch-menu-la');
options.target.style.width = options.width + 'px';
options.target.style.left = -options.width + 'px';
if (!options.disableEdgeSwipe) {
var handle = document.createElement('div');
handle.className = "tmla-handle";
handle.style.width = options.handleSize + 'px';
handle.style.right = -options.handleSize + 'px';
options.target.appendChild(handle);
}
if (!options.disableMask) {
mask = document.createElement('div');
mask.className = 'tmla-mask';
document.body.appendChild(mask);
maskHammer = new Hammer(mask, null);
}
};
function disableEvent(e) {
e.preventDefault();
e.stopPropagation();
}
TouchMenuLA.prototype.touchStartMenu = function () {
menuHammer.on('panstart', function (ev) {
options.target.classList.remove('transition');
velocity = Math.abs(ev.velocity);
});
menuHammer.on('panmove', function (ev) {
velocity = Math.abs(ev.velocity);
// Depending on the deltas, choose X or Y
var isOpen = self.visible;
// If it's already open, then treat any right-swipe as vertical pan
if (isOpen && !draggingX && ev.deltaX > 0) {
draggingY = true;
}
if (!draggingX && !draggingY && (!isOpen || Math.abs(ev.deltaX) >= 10)) {
draggingX = true;
scrollContainer.addEventListener('scroll', disableEvent);
options.target.classList.add('draggingX');
self.showMask();
} else if (!draggingY) {
draggingY = true;
}
if (draggingX) {
newPos = currentPos + ev.deltaX;
self.changeMenuPos();
}
});
};
TouchMenuLA.prototype.animateToPosition = function (pos) {
requestAnimationFrame(function() {
if (pos) {
options.target.style.transform = 'translate3d(' + pos + 'px, 0, 0)';
options.target.style.WebkitTransform = 'translate3d(' + pos + 'px, 0, 0)';
options.target.style.MozTransform = 'translate3d(' + pos + 'px, 0, 0)';
} else {
options.target.style.transform = 'none';
options.target.style.WebkitTransform = 'none';
options.target.style.MozTransform = 'none';
}
});
};
TouchMenuLA.prototype.changeMenuPos = function () {
if (newPos <= options.width) {
this.animateToPosition(newPos);
}
};
TouchMenuLA.prototype.touchEndMenu = function () {
menuHammer.on('panend pancancel', function (ev) {
options.target.classList.add('transition');
scrollContainer.removeEventListener('scroll', disableEvent);
draggingX = false;
draggingY = false;
currentPos = ev.deltaX;
self.checkMenuState(ev.deltaX, ev.deltaY);
});
};
TouchMenuLA.prototype.clickMaskClose = function () {
mask.addEventListener('click', function () {
self.close();
});
};
TouchMenuLA.prototype.checkMenuState = function (deltaX, deltaY) {
if (velocity >= 1.0) {
if (deltaX >= -80 || Math.abs(deltaY) >= 70) {
self.open();
} else {
self.close();
}
} else {
if (newPos >= 100) {
self.open();
} else {
self.close();
}
}
};
TouchMenuLA.prototype.open = function () {
this.animateToPosition(options.width);
currentPos = options.width;
this.isVisible = true;
options.target.classList.add('open');
self.showMask();
self.invoke(options.onChange);
};
TouchMenuLA.prototype.close = function () {
this.animateToPosition(0);
currentPos = 0;
self.isVisible = false;
options.target.classList.remove('open');
self.hideMask();
self.invoke(options.onChange);
};
TouchMenuLA.prototype.toggle = function () {
if (self.isVisible) {
self.close();
} else {
self.open();
}
};
TouchMenuLA.prototype.eventStartMask = function () {
maskHammer.on('panstart panmove', function (ev) {
if (ev.center.x <= options.width && self.isVisible) {
countStart++;
if (countStart == 1) {
startPoint = ev.deltaX;
}
if (ev.deltaX < 0) {
draggingX = true;
newPos = (ev.deltaX - startPoint) + options.width;
self.changeMenuPos();
velocity = Math.abs(ev.velocity);
}
}
});
};
TouchMenuLA.prototype.eventEndMask = function () {
maskHammer.on('panend pancancel', function (ev) {
self.checkMenuState(ev.deltaX);
countStart = 0;
});
};
TouchMenuLA.prototype.showMask = function () {
mask.classList.add('backdrop');
};
TouchMenuLA.prototype.hideMask = function () {
mask.classList.remove('backdrop');
};
TouchMenuLA.prototype.setMenuClassName = function () {
menuClassName = options.target.className;
};
TouchMenuLA.prototype.invoke = function (fn) {
if (fn) {
fn.apply(self);
}
};
TouchMenuLA.prototype.initialize = function () {
if (options.target) {
menuHammer = Hammer(options.target, null);
self.setDefaultsOptions();
self.setMenuClassName();
self.initElements();
self.touchStartMenu();
self.touchEndMenu();
self.eventStartMask();
self.eventEndMask();
if (!options.disableMask) {
self.clickMaskClose();
}
} else {
console.error('TouchMenuLA: The option \'target\' is required.');
}
};
return new TouchMenuLA();
};
});