mirror of
https://github.com/VTECRM/vtenext.git
synced 2026-02-26 16:18:47 +00:00
418 lines
14 KiB
JavaScript
418 lines
14 KiB
JavaScript
/*************************************
|
|
* SPDX-FileCopyrightText: 2009-2020 Vtenext S.r.l. <info@vtenext.com>
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
************************************/
|
|
(function ($) {
|
|
|
|
var methods = {
|
|
init : function(options) {
|
|
var defaults = {
|
|
menuWidth: 300,
|
|
edge: 'left',
|
|
closeOnClick: false,
|
|
draggable: true,
|
|
onOpen: null,
|
|
onClose: null
|
|
};
|
|
options = $.extend(defaults, options);
|
|
|
|
$(this).each(function(){
|
|
var $this = $(this);
|
|
var menuId = $this.attr('data-activates');
|
|
var menu = $("#"+ menuId);
|
|
|
|
// Set to width
|
|
if (options.menuWidth != 300) {
|
|
menu.css('width', options.menuWidth);
|
|
}
|
|
|
|
// Add Touch Area
|
|
var $dragTarget = $('.drag-target[data-sidenav="' + menuId + '"]');
|
|
if (options.draggable) {
|
|
// Regenerate dragTarget
|
|
if ($dragTarget.length) {
|
|
$dragTarget.remove();
|
|
}
|
|
|
|
$dragTarget = $('<div class="drag-target"></div>').attr('data-sidenav', menuId);
|
|
$('body').append($dragTarget);
|
|
} else {
|
|
$dragTarget = $();
|
|
}
|
|
|
|
if (options.edge == 'left') {
|
|
menu.css('transform', 'translateX(-100%)');
|
|
$dragTarget.css({'left': 0}); // Add Touch Area
|
|
}
|
|
else {
|
|
menu.addClass('right-aligned') // Change text-alignment to right
|
|
.css('transform', 'translateX(100%)');
|
|
$dragTarget.css({'right': 0}); // Add Touch Area
|
|
}
|
|
|
|
// If fixed sidenav, bring menu out
|
|
if (menu.hasClass('fixed')) {
|
|
if (window.innerWidth > 992) {
|
|
menu.css('transform', 'translateX(0)');
|
|
}
|
|
}
|
|
|
|
// Window resize to reset on large screens fixed
|
|
if (menu.hasClass('fixed')) {
|
|
$(window).resize( function() {
|
|
if (window.innerWidth > 992) {
|
|
// Close menu if window is resized bigger than 992 and user has fixed sidenav
|
|
if ($('#sidenav-overlay').length !== 0 && menuOut) {
|
|
removeMenu(true);
|
|
}
|
|
else {
|
|
// menu.removeAttr('style');
|
|
menu.css('transform', 'translateX(0%)');
|
|
// menu.css('width', options.menuWidth);
|
|
}
|
|
}
|
|
else if (menuOut === false){
|
|
if (options.edge === 'left') {
|
|
menu.css('transform', 'translateX(-100%)');
|
|
} else {
|
|
menu.css('transform', 'translateX(100%)');
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
// if closeOnClick, then add close event for all a tags in side sideNav
|
|
if (options.closeOnClick === true) {
|
|
menu.on("click.itemclick", "a:not(.collapsible-header)", function(){
|
|
if (!(window.innerWidth > 992 && menu.hasClass('fixed'))){
|
|
removeMenu();
|
|
}
|
|
});
|
|
}
|
|
|
|
var removeMenu = function(restoreNav) {
|
|
panning = false;
|
|
menuOut = false;
|
|
// Reenable scrolling
|
|
$('body').css({
|
|
overflow: '',
|
|
width: ''
|
|
});
|
|
|
|
$('#sidenav-overlay').velocity({opacity: 0}, {duration: 200,
|
|
queue: false, easing: 'easeOutQuad',
|
|
complete: function() {
|
|
$(this).remove();
|
|
} });
|
|
if (options.edge === 'left') {
|
|
// Reset phantom div
|
|
$dragTarget.css({width: '', right: '', left: '0'});
|
|
menu.velocity(
|
|
{'translateX': '-100%'},
|
|
{ duration: 200,
|
|
queue: false,
|
|
easing: 'easeOutCubic',
|
|
complete: function() {
|
|
if (restoreNav === true) {
|
|
// Restore Fixed sidenav
|
|
menu.removeAttr('style');
|
|
menu.css('width', options.menuWidth);
|
|
}
|
|
}
|
|
|
|
});
|
|
}
|
|
else {
|
|
// Reset phantom div
|
|
$dragTarget.css({width: '', right: '0', left: ''});
|
|
menu.velocity(
|
|
{'translateX': '100%'},
|
|
{ duration: 200,
|
|
queue: false,
|
|
easing: 'easeOutCubic',
|
|
complete: function() {
|
|
if (restoreNav === true) {
|
|
// Restore Fixed sidenav
|
|
menu.removeAttr('style');
|
|
menu.css('width', options.menuWidth);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Callback
|
|
if (typeof(options.onClose) === 'function') {
|
|
options.onClose.call(this, menu);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Touch Event
|
|
var panning = false;
|
|
var menuOut = false;
|
|
|
|
if (options.draggable) {
|
|
$dragTarget.on('click', function(){
|
|
if (menuOut) {
|
|
removeMenu();
|
|
}
|
|
});
|
|
|
|
$dragTarget.hammer({
|
|
prevent_default: false
|
|
}).on('pan', function(e) {
|
|
|
|
if (e.gesture.pointerType == "touch") {
|
|
|
|
var direction = e.gesture.direction;
|
|
var x = e.gesture.center.x;
|
|
var y = e.gesture.center.y;
|
|
var velocityX = e.gesture.velocityX;
|
|
|
|
// Vertical scroll bugfix
|
|
if (x === 0 && y === 0) {
|
|
return;
|
|
}
|
|
|
|
// Disable Scrolling
|
|
var $body = $('body');
|
|
var $overlay = $('#sidenav-overlay');
|
|
var oldWidth = $body.innerWidth();
|
|
$body.css('overflow', 'hidden');
|
|
$body.width(oldWidth);
|
|
|
|
// If overlay does not exist, create one and if it is clicked, close menu
|
|
if ($overlay.length === 0) {
|
|
$overlay = $('<div id="sidenav-overlay"></div>');
|
|
$overlay.css('opacity', 0).click( function(){
|
|
removeMenu();
|
|
});
|
|
|
|
// Run 'onOpen' when sidenav is opened via touch/swipe if applicable
|
|
if (typeof(options.onOpen) === 'function') {
|
|
options.onOpen.call(this, menu);
|
|
}
|
|
|
|
$('body').append($overlay);
|
|
}
|
|
|
|
// Keep within boundaries
|
|
if (options.edge === 'left') {
|
|
if (x > options.menuWidth) { x = options.menuWidth; }
|
|
else if (x < 0) { x = 0; }
|
|
}
|
|
|
|
if (options.edge === 'left') {
|
|
// Left Direction
|
|
if (x < (options.menuWidth / 2)) { menuOut = false; }
|
|
// Right Direction
|
|
else if (x >= (options.menuWidth / 2)) { menuOut = true; }
|
|
menu.css('transform', 'translateX(' + (x - options.menuWidth) + 'px)');
|
|
}
|
|
else {
|
|
// Left Direction
|
|
if (x < (window.innerWidth - options.menuWidth / 2)) {
|
|
menuOut = true;
|
|
}
|
|
// Right Direction
|
|
else if (x >= (window.innerWidth - options.menuWidth / 2)) {
|
|
menuOut = false;
|
|
}
|
|
var rightPos = (x - options.menuWidth / 2);
|
|
if (rightPos < 0) {
|
|
rightPos = 0;
|
|
}
|
|
|
|
menu.css('transform', 'translateX(' + rightPos + 'px)');
|
|
}
|
|
|
|
|
|
// Percentage overlay
|
|
var overlayPerc;
|
|
if (options.edge === 'left') {
|
|
overlayPerc = x / options.menuWidth;
|
|
$overlay.velocity({opacity: overlayPerc }, {duration: 10, queue: false, easing: 'easeOutQuad'});
|
|
}
|
|
else {
|
|
overlayPerc = Math.abs((x - window.innerWidth) / options.menuWidth);
|
|
$overlay.velocity({opacity: overlayPerc }, {duration: 10, queue: false, easing: 'easeOutQuad'});
|
|
}
|
|
}
|
|
|
|
}).on('panend', function(e) {
|
|
|
|
if (e.gesture.pointerType == "touch") {
|
|
var $overlay = $('#sidenav-overlay');
|
|
var velocityX = e.gesture.velocityX;
|
|
var x = e.gesture.center.x;
|
|
var leftPos = x - options.menuWidth;
|
|
var rightPos = x - options.menuWidth / 2;
|
|
if (leftPos > 0 ) {
|
|
leftPos = 0;
|
|
}
|
|
if (rightPos < 0) {
|
|
rightPos = 0;
|
|
}
|
|
panning = false;
|
|
|
|
if (options.edge === 'left') {
|
|
// If velocityX <= 0.3 then the user is flinging the menu closed so ignore menuOut
|
|
if ((menuOut && velocityX <= 0.3) || velocityX < -0.5) {
|
|
// Return menu to open
|
|
if (leftPos !== 0) {
|
|
menu.velocity({'translateX': [0, leftPos]}, {duration: 300, queue: false, easing: 'easeOutQuad'});
|
|
}
|
|
|
|
$overlay.velocity({opacity: 1 }, {duration: 50, queue: false, easing: 'easeOutQuad'});
|
|
$dragTarget.css({width: '50%', right: 0, left: ''});
|
|
menuOut = true;
|
|
}
|
|
else if (!menuOut || velocityX > 0.3) {
|
|
// Enable Scrolling
|
|
$('body').css({
|
|
overflow: '',
|
|
width: ''
|
|
});
|
|
// Slide menu closed
|
|
menu.velocity({'translateX': [-1 * options.menuWidth - 10, leftPos]}, {duration: 200, queue: false, easing: 'easeOutQuad'});
|
|
$overlay.velocity({opacity: 0 }, {duration: 200, queue: false, easing: 'easeOutQuad',
|
|
complete: function () {
|
|
// Run 'onClose' when sidenav is closed via touch/swipe if applicable
|
|
if (typeof(options.onClose) === 'function') {
|
|
options.onClose.call(this, menu);
|
|
}
|
|
|
|
$(this).remove();
|
|
}});
|
|
$dragTarget.css({width: '10px', right: '', left: 0});
|
|
}
|
|
}
|
|
else {
|
|
if ((menuOut && velocityX >= -0.3) || velocityX > 0.5) {
|
|
// Return menu to open
|
|
if (rightPos !== 0) {
|
|
menu.velocity({'translateX': [0, rightPos]}, {duration: 300, queue: false, easing: 'easeOutQuad'});
|
|
}
|
|
|
|
$overlay.velocity({opacity: 1 }, {duration: 50, queue: false, easing: 'easeOutQuad'});
|
|
$dragTarget.css({width: '50%', right: '', left: 0});
|
|
menuOut = true;
|
|
}
|
|
else if (!menuOut || velocityX < -0.3) {
|
|
// Enable Scrolling
|
|
$('body').css({
|
|
overflow: '',
|
|
width: ''
|
|
});
|
|
|
|
// Slide menu closed
|
|
menu.velocity({'translateX': [options.menuWidth + 10, rightPos]}, {duration: 200, queue: false, easing: 'easeOutQuad'});
|
|
$overlay.velocity({opacity: 0 }, {duration: 200, queue: false, easing: 'easeOutQuad',
|
|
complete: function () {
|
|
// Run 'onClose' when sidenav is closed via touch/swipe if applicable
|
|
if (typeof(options.onClose) === 'function') {
|
|
options.onClose.call(this, menu);
|
|
}
|
|
|
|
$(this).remove();
|
|
}});
|
|
$dragTarget.css({width: '10px', right: 0, left: ''});
|
|
}
|
|
}
|
|
|
|
}
|
|
});
|
|
}
|
|
|
|
$this.off('click.sidenav').on('click.sidenav', function() {
|
|
if (menuOut === true) {
|
|
menuOut = false;
|
|
panning = false;
|
|
removeMenu();
|
|
}
|
|
else {
|
|
|
|
// Disable Scrolling
|
|
var $body = $('body');
|
|
var $overlay = $('<div id="sidenav-overlay"></div>');
|
|
var oldWidth = $body.innerWidth();
|
|
$body.css('overflow', 'hidden');
|
|
$body.width(oldWidth);
|
|
|
|
// Push current drag target on top of DOM tree
|
|
$('body').append($dragTarget);
|
|
|
|
if (options.edge === 'left') {
|
|
$dragTarget.css({width: '50%', right: 0, left: ''});
|
|
menu.velocity({'translateX': [0, -1 * options.menuWidth]}, {duration: 300, queue: false, easing: 'easeOutQuad'});
|
|
}
|
|
else {
|
|
$dragTarget.css({width: '50%', right: '', left: 0});
|
|
menu.velocity({'translateX': [0, options.menuWidth]}, {duration: 300, queue: false, easing: 'easeOutQuad'});
|
|
}
|
|
|
|
// Overlay close on click
|
|
$overlay.css('opacity', 0)
|
|
.click(function() {
|
|
menuOut = false;
|
|
panning = false;
|
|
removeMenu();
|
|
$overlay.velocity({opacity: 0}, {duration: 300, queue: false, easing: 'easeOutQuad',
|
|
complete: function() {
|
|
$(this).remove();
|
|
}
|
|
});
|
|
});
|
|
|
|
// Append body
|
|
$('body').append($overlay);
|
|
$overlay.velocity({opacity: 1}, {duration: 300, queue: false, easing: 'easeOutQuad',
|
|
complete: function () {
|
|
menuOut = true;
|
|
panning = false;
|
|
}
|
|
});
|
|
|
|
// Callback
|
|
if (typeof(options.onOpen) === 'function') {
|
|
options.onOpen.call(this, menu);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
});
|
|
});
|
|
|
|
|
|
},
|
|
destroy: function () {
|
|
var $overlay = $('#sidenav-overlay');
|
|
var $dragTarget = $('.drag-target[data-sidenav="' + $(this).attr('data-activates') + '"]');
|
|
$overlay.trigger('click');
|
|
$dragTarget.remove();
|
|
$(this).off('click');
|
|
$overlay.remove();
|
|
},
|
|
show : function() {
|
|
this.trigger('click');
|
|
},
|
|
hide : function() {
|
|
$('#sidenav-overlay').trigger('click');
|
|
}
|
|
};
|
|
|
|
|
|
$.fn.sideNav = function(methodOrOptions) {
|
|
if ( methods[methodOrOptions] ) {
|
|
return methods[ methodOrOptions ].apply( this, Array.prototype.slice.call( arguments, 1 ));
|
|
} else if ( typeof methodOrOptions === 'object' || ! methodOrOptions ) {
|
|
// Default to "init"
|
|
return methods.init.apply( this, arguments );
|
|
} else {
|
|
$.error( 'Method ' + methodOrOptions + ' does not exist on jQuery.sideNav' );
|
|
}
|
|
}; // Plugin end
|
|
}( jQuery )); |