8548 lines
No EOL
272 KiB
JavaScript
8548 lines
No EOL
272 KiB
JavaScript
/**
|
|
* @class mApp Metronic App class
|
|
*/
|
|
|
|
var mApp = function() {
|
|
|
|
/**
|
|
* Initializes bootstrap tooltip
|
|
*/
|
|
var initTooltip = function(el) {
|
|
var skin = el.data('skin') ? 'm-tooltip--skin-' + el.data('skin') : '';
|
|
var width = el.data('width') == 'auto' ? 'm-tooltop--auto-width' : '';
|
|
|
|
el.tooltip({
|
|
trigger: 'hover',
|
|
template: '<div class="m-tooltip ' + skin + ' ' + width + ' tooltip" role="tooltip">\
|
|
<div class="arrow"></div>\
|
|
<div class="tooltip-inner"></div>\
|
|
</div>'
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Initializes bootstrap tooltips
|
|
*/
|
|
var initTooltips = function() {
|
|
// init bootstrap tooltips
|
|
$('[data-toggle="m-tooltip"]').each(function() {
|
|
initTooltip($(this));
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Initializes bootstrap popover
|
|
*/
|
|
var initPopover = function(el) {
|
|
var skin = el.data('skin') ? 'm-popover--skin-' + el.data('skin') : '';
|
|
var triggerValue = el.data('trigger') ? el.data('trigger') : 'hover';
|
|
|
|
el.popover({
|
|
trigger: triggerValue,
|
|
template: '\
|
|
<div class="m-popover ' + skin + ' popover" role="tooltip">\
|
|
<div class="arrow"></div>\
|
|
<h3 class="popover-header"></h3>\
|
|
<div class="popover-body"></div>\
|
|
</div>'
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Initializes bootstrap popovers
|
|
*/
|
|
var initPopovers = function() {
|
|
// init bootstrap popover
|
|
$('[data-toggle="m-popover"]').each(function() {
|
|
initPopover($(this));
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Initializes bootstrap file input
|
|
*/
|
|
var initFileInput = function() {
|
|
// init bootstrap popover
|
|
$('.custom-file-input').on('change',function(){
|
|
var fileName = $(this).val();
|
|
$(this).next('.custom-file-control').addClass("selected").html(fileName);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Initializes metronic portlet
|
|
*/
|
|
var initPortlet = function(el, options) {
|
|
// init portlet tools
|
|
el.mPortlet(options);
|
|
}
|
|
|
|
/**
|
|
* Initializes metronic portlets
|
|
*/
|
|
var initPortlets = function() {
|
|
// init portlet tools
|
|
$('[data-portlet="true"]').each(function() {
|
|
var el = $(this);
|
|
|
|
if ( el.data('portlet-initialized') !== true ) {
|
|
initPortlet(el, {});
|
|
el.data('portlet-initialized', true);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Initializes scrollable contents
|
|
*/
|
|
var initScrollables = function() {
|
|
$('[data-scrollable="true"]').each(function(){
|
|
var maxHeight;
|
|
var height;
|
|
var el = $(this);
|
|
|
|
if (mUtil.isInResponsiveRange('tablet-and-mobile')) {
|
|
if (el.data('mobile-max-height')) {
|
|
maxHeight = el.data('mobile-max-height');
|
|
} else {
|
|
maxHeight = el.data('max-height');
|
|
}
|
|
|
|
if (el.data('mobile-height')) {
|
|
height = el.data('mobile-height');
|
|
} else {
|
|
height = el.data('height');
|
|
}
|
|
} else {
|
|
maxHeight = el.data('max-height');
|
|
height = el.data('max-height');
|
|
}
|
|
|
|
if (maxHeight) {
|
|
el.css('max-height', maxHeight);
|
|
}
|
|
if (height) {
|
|
el.css('height', height);
|
|
}
|
|
|
|
mApp.initScroller(el, {});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Initializes bootstrap alerts
|
|
*/
|
|
var initAlerts = function() {
|
|
// init bootstrap popover
|
|
$('body').on('click', '[data-close=alert]', function() {
|
|
$(this).closest('.alert').hide();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Initializes bootstrap collapse for Metronic's accordion feature
|
|
*/
|
|
var initAccordions = function(el) {
|
|
|
|
}
|
|
|
|
var hideTouchWarning = function() {
|
|
jQuery.event.special.touchstart = {
|
|
setup: function(_, ns, handle) {
|
|
if (typeof this === 'function')
|
|
if (ns.includes('noPreventDefault')) {
|
|
this.addEventListener('touchstart', handle, {passive: false});
|
|
} else {
|
|
this.addEventListener('touchstart', handle, {passive: true});
|
|
}
|
|
},
|
|
};
|
|
jQuery.event.special.touchmove = {
|
|
setup: function(_, ns, handle) {
|
|
if (typeof this === 'function')
|
|
if (ns.includes('noPreventDefault')) {
|
|
this.addEventListener('touchmove', handle, {passive: false});
|
|
} else {
|
|
this.addEventListener('touchmove', handle, {passive: true});
|
|
}
|
|
},
|
|
};
|
|
jQuery.event.special.wheel = {
|
|
setup: function(_, ns, handle) {
|
|
if (typeof this === 'function')
|
|
if (ns.includes('noPreventDefault')) {
|
|
this.addEventListener('wheel', handle, {passive: false});
|
|
} else {
|
|
this.addEventListener('wheel', handle, {passive: true});
|
|
}
|
|
},
|
|
};
|
|
};
|
|
|
|
return {
|
|
/**
|
|
* Main class initializer
|
|
*/
|
|
init: function() {
|
|
mApp.initComponents();
|
|
},
|
|
|
|
/**
|
|
* Initializes components
|
|
*/
|
|
initComponents: function() {
|
|
hideTouchWarning();
|
|
initScrollables();
|
|
initTooltips();
|
|
initPopovers();
|
|
initAlerts();
|
|
initPortlets();
|
|
initFileInput();
|
|
initAccordions();
|
|
},
|
|
|
|
/**
|
|
*
|
|
* @param {object} el jQuery element object
|
|
*/
|
|
// wrJangoer function to scroll(focus) to an element
|
|
initTooltips: function() {
|
|
initTooltips();
|
|
},
|
|
|
|
/**
|
|
*
|
|
* @param {object} el jQuery element object
|
|
*/
|
|
// wrJangoer function to scroll(focus) to an element
|
|
initTooltip: function(el) {
|
|
initTooltip(el);
|
|
},
|
|
|
|
/**
|
|
*
|
|
* @param {object} el jQuery element object
|
|
*/
|
|
// wrJangoer function to scroll(focus) to an element
|
|
initPopovers: function() {
|
|
initPopovers();
|
|
},
|
|
|
|
/**
|
|
*
|
|
* @param {object} el jQuery element object
|
|
*/
|
|
// wrJangoer function to scroll(focus) to an element
|
|
initPopover: function(el) {
|
|
initPopover(el);
|
|
},
|
|
|
|
/**
|
|
*
|
|
* @param {object} el jQuery element object
|
|
*/
|
|
// function to init portlet
|
|
initPortlet: function(el, options) {
|
|
initPortlet(el, options);
|
|
},
|
|
|
|
/**
|
|
*
|
|
* @param {object} el jQuery element object
|
|
*/
|
|
// function to init portlets
|
|
initPortlets: function() {
|
|
initPortlets();
|
|
},
|
|
|
|
/**
|
|
* Scrolls to an element with animation
|
|
* @param {object} el jQuery element object
|
|
* @param {number} offset Offset to element scroll position
|
|
*/
|
|
scrollTo: function(el, offset) {
|
|
var pos = (el && el.length > 0) ? el.offset().top : 0;
|
|
pos = pos + (offset ? offset : 0);
|
|
|
|
jQuery('html,body').animate({
|
|
scrollTop: pos
|
|
}, 'slow');
|
|
},
|
|
|
|
/**
|
|
* Scrolls until element is centered in the viewport
|
|
* @param {object} el jQuery element object
|
|
*/
|
|
// wrJangoer function to scroll(focus) to an element
|
|
scrollToViewport: function(el) {
|
|
var elOffset = el.offset().top;
|
|
var elHeight = el.height();
|
|
var windowHeight = mUtil.getViewPort().height;
|
|
var offset = elOffset - ((windowHeight / 2) - (elHeight / 2));
|
|
|
|
jQuery('html,body').animate({
|
|
scrollTop: offset
|
|
}, 'slow');
|
|
},
|
|
|
|
/**
|
|
* Scrolls to the top of the page
|
|
*/
|
|
// function to scroll to the top
|
|
scrollTop: function() {
|
|
mApp.scrollTo();
|
|
},
|
|
|
|
/**
|
|
* Initializes scrollable content using mCustomScrollbar plugin
|
|
* @param {object} el jQuery element object
|
|
* @param {object} options mCustomScrollbar plugin options(refer: http://manos.malihu.gr/jquery-custom-content-scroller/)
|
|
*/
|
|
initScroller: function(el, options) {
|
|
if (mUtil.isMobileDevice()) {
|
|
el.css('overflow', 'auto');
|
|
} else {
|
|
//el.mCustomScrollbar("destroy");
|
|
el.mCustomScrollbar({
|
|
scrollInertia: 0,
|
|
autoDraggerLength: true,
|
|
autoHideScrollbar: true,
|
|
autoExpandScrollbar: false,
|
|
alwaysShowScrollbar: 0,
|
|
axis: el.data('axis') ? el.data('axis') : 'y',
|
|
mouseWheel: {
|
|
scrollAmount: 120,
|
|
preventDefault: true
|
|
},
|
|
setHeight: (options.height ? options.height : ''),
|
|
theme:"minimal-dark"
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Destroys scrollable content's mCustomScrollbar plugin instance
|
|
* @param {object} el jQuery element object
|
|
*/
|
|
destroyScroller: function(el) {
|
|
el.mCustomScrollbar("destroy");
|
|
},
|
|
|
|
/**
|
|
* Shows bootstrap alert
|
|
* @param {object} options
|
|
* @returns {string} ID attribute of the created alert
|
|
*/
|
|
alert: function(options) {
|
|
options = $.extend(true, {
|
|
container: "", // alerts parent container(by default placed after the page breadcrumbs)
|
|
place: "append", // "append" or "prepend" in container
|
|
type: 'success', // alert's type
|
|
message: "", // alert's message
|
|
close: true, // make alert closable
|
|
reset: true, // close all previouse alerts first
|
|
focus: true, // auto scroll to the alert after shown
|
|
closeInSeconds: 0, // auto close after defined seconds
|
|
icon: "" // put icon before the message
|
|
}, options);
|
|
|
|
var id = mUtil.getUniqueID("App_alert");
|
|
|
|
var html = '<div id="' + id + '" class="custom-alerts alert alert-' + options.type + ' fade in">' + (options.close ? '<button type="button" class="close" data-dismiss="alert" aria-hidden="true"></button>' : '') + (options.icon !== "" ? '<i class="fa-lg fa fa-' + options.icon + '"></i> ' : '') + options.message + '</div>';
|
|
|
|
if (options.reset) {
|
|
$('.custom-alerts').remove();
|
|
}
|
|
|
|
if (!options.container) {
|
|
if ($('.page-fixed-main-content').size() === 1) {
|
|
$('.page-fixed-main-content').prepend(html);
|
|
} else if (($('body').hasClass("page-container-bg-solid") || $('body').hasClass("page-content-white")) && $('.page-head').size() === 0) {
|
|
$('.page-title').after(html);
|
|
} else {
|
|
if ($('.page-bar').size() > 0) {
|
|
$('.page-bar').after(html);
|
|
} else {
|
|
$('.page-breadcrumb, .breadcrumbs').after(html);
|
|
}
|
|
}
|
|
} else {
|
|
if (options.place == "append") {
|
|
$(options.container).append(html);
|
|
} else {
|
|
$(options.container).prepend(html);
|
|
}
|
|
}
|
|
|
|
if (options.focus) {
|
|
mApp.scrollTo($('#' + id));
|
|
}
|
|
|
|
if (options.closeInSeconds > 0) {
|
|
setTimeout(function() {
|
|
$('#' + id).remove();
|
|
}, options.closeInSeconds * 1000);
|
|
}
|
|
|
|
return id;
|
|
},
|
|
|
|
/**
|
|
* Blocks element with loading indiciator using http://malsup.com/jquery/block/
|
|
* @param {object} target jQuery element object
|
|
* @param {object} options
|
|
*/
|
|
block: function(target, options) {
|
|
var el = $(target);
|
|
|
|
options = $.extend(true, {
|
|
opacity: 0.03,
|
|
overlayColor: '#000000',
|
|
state: 'brand',
|
|
type: 'loader',
|
|
size: 'lg',
|
|
centerX: true,
|
|
centerY: true,
|
|
message: '',
|
|
shadow: true,
|
|
width: 'auto'
|
|
}, options);
|
|
|
|
var skin;
|
|
var state;
|
|
var loading;
|
|
|
|
if (options.type == 'spinner') {
|
|
skin = options.skin ? 'm-spinner--skin-' + options.skin : '';
|
|
state = options.state ? 'm-spinner--' + options.state : '';
|
|
loading = '<div class="m-spinner ' + skin + ' ' + state + '"></div';
|
|
} else {
|
|
skin = options.skin ? 'm-loader--skin-' + options.skin : '';
|
|
state = options.state ? 'm-loader--' + options.state : '';
|
|
size = options.size ? 'm-loader--' + options.size : '';
|
|
loading = '<div class="m-loader ' + skin + ' ' + state + ' ' + size + '"></div';
|
|
}
|
|
|
|
if (options.message && options.message.length > 0) {
|
|
var classes = 'm-blockui ' + (options.shadow === false ? 'm-blockui-no-shadow' : '');
|
|
|
|
html = '<div class="' + classes + '"><span>' + options.message + '</span><span>' + loading + '</span></div>';
|
|
options.width = mUtil.realWidth(html) + 10;
|
|
if (target == 'body') {
|
|
html = '<div class="' + classes + '" style="margin-left:-'+ (options.width / 2) +'px;"><span>' + options.message + '</span><span>' + loading + '</span></div>';
|
|
}
|
|
} else {
|
|
html = loading;
|
|
}
|
|
|
|
var params = {
|
|
message: html,
|
|
centerY: options.centerY,
|
|
centerX: options.centerX,
|
|
css: {
|
|
top: '30%',
|
|
left: '50%',
|
|
border: '0',
|
|
padding: '0',
|
|
backgroundColor: 'none',
|
|
width: options.width
|
|
},
|
|
overlayCSS: {
|
|
backgroundColor: options.overlayColor,
|
|
opacity: options.opacity,
|
|
cursor: 'wait',
|
|
zIndex: '10'
|
|
},
|
|
onUnblock: function() {
|
|
if (el) {
|
|
el.css('position', '');
|
|
el.css('zoom', '');
|
|
}
|
|
}
|
|
};
|
|
|
|
if (target == 'body') {
|
|
params.css.top = '50%';
|
|
$.blockUI(params);
|
|
} else {
|
|
var el = $(target);
|
|
el.block(params);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Un-blocks the blocked element
|
|
* @param {object} target jQuery element object
|
|
*/
|
|
unblock: function(target) {
|
|
if (target && target != 'body') {
|
|
$(target).unblock();
|
|
} else {
|
|
$.unblockUI();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Blocks the page body element with loading indicator
|
|
* @param {object} options
|
|
*/
|
|
blockPage: function(options) {
|
|
return mApp.block('body', options);
|
|
},
|
|
|
|
/**
|
|
* Un-blocks the blocked page body element
|
|
*/
|
|
unblockPage: function() {
|
|
return mApp.unblock('body');
|
|
},
|
|
|
|
/**
|
|
* Enable loader progress for button and other elements
|
|
* @param {object} target jQuery element object
|
|
* @param {object} options
|
|
*/
|
|
progress: function(target, options) {
|
|
var skin = (options && options.skin) ? options.skin : 'light';
|
|
var alignment = (options && options.alignment) ? options.alignment : 'right';
|
|
var size = (options && options.size) ? 'm-spinner--' + options.size : '';
|
|
var classes = 'm-loader ' + 'm-loader--' + skin + ' m-loader--' + alignment + ' m-loader--' + size;
|
|
|
|
mApp.unprogress(target);
|
|
|
|
$(target).addClass(classes);
|
|
$(target).data('progress-classes', classes);
|
|
},
|
|
|
|
/**
|
|
* Disable loader progress for button and other elements
|
|
* @param {object} target jQuery element object
|
|
*/
|
|
unprogress: function(target) {
|
|
$(target).removeClass($(target).data('progress-classes'));
|
|
}
|
|
};
|
|
}();
|
|
|
|
//== Initialize mApp class on document ready
|
|
$(document).ready(function() {
|
|
mApp.init();
|
|
});
|
|
/**
|
|
* @class mUtil Metronic base utilize class that privides helper functions
|
|
*/
|
|
|
|
var mUtil = function() {
|
|
var resizeHandlers = [];
|
|
|
|
/** @type {object} breakpoints The device width breakpoints **/
|
|
var breakpoints = {
|
|
sm: 544, // Small screen / phone
|
|
md: 768, // Medium screen / tablet
|
|
lg: 992, // Large screen / desktop
|
|
xl: 1200 // Extra large screen / wide desktop
|
|
};
|
|
|
|
/** @type {object} colors State colors **/
|
|
var colors = {
|
|
brand: '#716aca',
|
|
metal: '#c4c5d6',
|
|
light: '#ffffff',
|
|
accent: '#00c5dc',
|
|
primary: '#5867dd',
|
|
success: '#34bfa3',
|
|
info: '#36a3f7',
|
|
warning: '#ffb822',
|
|
danger: '#f4516c'
|
|
};
|
|
|
|
/**
|
|
* Handle window resize event with some
|
|
* delay to attach event handlers upon resize complete
|
|
*/
|
|
var _windowResizeHandler = function() {
|
|
var resize;
|
|
var _runResizeHandlers = function() {
|
|
// reinitialize other subscribed elements
|
|
for (var i = 0; i < resizeHandlers.length; i++) {
|
|
var each = resizeHandlers[i];
|
|
each.call();
|
|
}
|
|
};
|
|
|
|
jQuery(window).resize(function() {
|
|
if (resize) {
|
|
clearTimeout(resize);
|
|
}
|
|
resize = setTimeout(function() {
|
|
_runResizeHandlers();
|
|
}, 250); // wait 50ms until window resize finishes.
|
|
});
|
|
};
|
|
|
|
return {
|
|
/**
|
|
* Class main initializer.
|
|
* @param {object} options.
|
|
* @returns null
|
|
*/
|
|
//main function to initiate the theme
|
|
init: function(options) {
|
|
if (options && options.breakpoints) {
|
|
breakpoints = options.breakpoints;
|
|
}
|
|
|
|
if (options && options.colors) {
|
|
colors = options.colors;
|
|
}
|
|
|
|
_windowResizeHandler();
|
|
},
|
|
|
|
/**
|
|
* Adds window resize event handler.
|
|
* @param {function} callback function.
|
|
*/
|
|
addResizeHandler: function(callback) {
|
|
resizeHandlers.push(callback);
|
|
},
|
|
|
|
/**
|
|
* Trigger window resize handlers.
|
|
*/
|
|
runResizeHandlers: function() {
|
|
_runResizeHandlers();
|
|
},
|
|
|
|
/**
|
|
* Get GET parameter value from URL.
|
|
* @param {string} paramName Parameter name.
|
|
* @returns {string}
|
|
*/
|
|
getURLParam: function(paramName) {
|
|
var searchString = window.location.search.substring(1),
|
|
i, val, params = searchString.split("&");
|
|
|
|
for (i = 0; i < params.length; i++) {
|
|
val = params[i].split("=");
|
|
if (val[0] == paramName) {
|
|
return unescape(val[1]);
|
|
}
|
|
}
|
|
|
|
return null;
|
|
},
|
|
|
|
/**
|
|
* Checks whether current device is mobile touch.
|
|
* @returns {boolean}
|
|
*/
|
|
isMobileDevice: function() {
|
|
return (this.getViewPort().width < this.getBreakpoint('lg') ? true : false);
|
|
},
|
|
|
|
/**
|
|
* Checks whether current device is desktop.
|
|
* @returns {boolean}
|
|
*/
|
|
isDesktopDevice: function() {
|
|
return mUtil.isMobileDevice() ? false : true;
|
|
},
|
|
|
|
/**
|
|
* Gets browser window viewport size. Ref: http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/
|
|
* @returns {object}
|
|
*/
|
|
getViewPort: function() {
|
|
var e = window,
|
|
a = 'inner';
|
|
if (!('innerWidth' in window)) {
|
|
a = 'client';
|
|
e = document.documentElement || document.body;
|
|
}
|
|
|
|
return {
|
|
width: e[a + 'Width'],
|
|
height: e[a + 'Height']
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Checks whether given device mode is currently activated.
|
|
* @param {string} mode Responsive mode name(e.g: desktop, desktop-and-tablet, tablet, tablet-and-mobile, mobile)
|
|
* @returns {boolean}
|
|
*/
|
|
isInResponsiveRange: function(mode) {
|
|
var breakpoint = this.getViewPort().width;
|
|
|
|
if (mode == 'general') {
|
|
return true;
|
|
} else if (mode == 'desktop' && breakpoint >= (this.getBreakpoint('lg') + 1)) {
|
|
return true;
|
|
} else if (mode == 'tablet' && (breakpoint >= (this.getBreakpoint('md') + 1) && breakpoint < this.getBreakpoint('lg'))) {
|
|
return true;
|
|
} else if (mode == 'mobile' && breakpoint <= this.getBreakpoint('md')) {
|
|
return true;
|
|
} else if (mode == 'desktop-and-tablet' && breakpoint >= (this.getBreakpoint('md') + 1)) {
|
|
return true;
|
|
} else if (mode == 'tablet-and-mobile' && breakpoint <= this.getBreakpoint('lg')) {
|
|
return true;
|
|
} else if (mode == 'minimal-desktop-and-below' && breakpoint <= this.getBreakpoint('xl')) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* Generates unique ID for give prefix.
|
|
* @param {string} prefix Prefix for generated ID
|
|
* @returns {boolean}
|
|
*/
|
|
getUniqueID: function(prefix) {
|
|
return prefix + Math.floor(Math.random() * (new Date()).getTime());
|
|
},
|
|
|
|
/**
|
|
* Gets window width for give breakpoint mode.
|
|
* @param {string} mode Responsive mode name(e.g: xl, lg, md, sm)
|
|
* @returns {number}
|
|
*/
|
|
getBreakpoint: function(mode) {
|
|
if ($.inArray(mode, breakpoints)) {
|
|
return breakpoints[mode];
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Checks whether object has property matchs given key path.
|
|
* @param {object} obj Object contains values paired with given key path
|
|
* @param {string} keys Keys path seperated with dots
|
|
* @returns {object}
|
|
*/
|
|
isset: function(obj, keys) {
|
|
var stone;
|
|
|
|
keys = keys || '';
|
|
|
|
if (keys.indexOf('[') !== -1) {
|
|
throw new Error('Unsupported object path notation.');
|
|
}
|
|
|
|
keys = keys.split('.');
|
|
|
|
do {
|
|
if (obj === undefined) {
|
|
return false;
|
|
}
|
|
|
|
stone = keys.shift();
|
|
|
|
if (!obj.hasOwnProperty(stone)) {
|
|
return false;
|
|
}
|
|
|
|
obj = obj[stone];
|
|
|
|
} while (keys.length);
|
|
|
|
return true;
|
|
},
|
|
|
|
/**
|
|
* Gets highest z-index of the given element parents
|
|
* @param {object} el jQuery element object
|
|
* @returns {number}
|
|
*/
|
|
getHighestZindex: function(el) {
|
|
var elem = $(el),
|
|
position, value;
|
|
|
|
while (elem.length && elem[0] !== document) {
|
|
// Ignore z-index if position is set to a value where z-index is ignored by the browser
|
|
// This makes behavior of this function consistent across browsers
|
|
// WebKit always returns auto if the element is positioned
|
|
position = elem.css("position");
|
|
|
|
if (position === "absolute" || position === "relative" || position === "fixed") {
|
|
// IE returns 0 when zIndex is not specified
|
|
// other browsers return a string
|
|
// we ignore the case of nested elements with an explicit value of 0
|
|
// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
|
|
value = parseInt(elem.css("zIndex"), 10);
|
|
if (!isNaN(value) && value !== 0) {
|
|
return value;
|
|
}
|
|
}
|
|
elem = elem.parent();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Checks whether the element has given classes
|
|
* @param {object} el jQuery element object
|
|
* @param {string} Classes string
|
|
* @returns {boolean}
|
|
*/
|
|
hasClasses: function(el, classes) {
|
|
var classesArr = classes.split(" ");
|
|
|
|
for ( var i = 0; i < classesArr.length; i++ ) {
|
|
if ( el.hasClass( classesArr[i] ) == false ) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
},
|
|
|
|
/**
|
|
* Gets element actual/real width
|
|
* @param {object} el jQuery element object
|
|
* @returns {number}
|
|
*/
|
|
realWidth: function(el){
|
|
var clone = $(el).clone();
|
|
clone.css("visibility","hidden");
|
|
clone.css('overflow', 'hidden');
|
|
clone.css("height","0");
|
|
$('body').append(clone);
|
|
var width = clone.outerWidth();
|
|
clone.remove();
|
|
|
|
return width;
|
|
},
|
|
|
|
/**
|
|
* Checks whether the element has any parent with fixed position
|
|
* @param {object} el jQuery element object
|
|
* @returns {boolean}
|
|
*/
|
|
hasFixedPositionedParent: function(el) {
|
|
var result = false;
|
|
|
|
el.parents().each(function () {
|
|
if ($(this).css('position') == 'fixed') {
|
|
result = true;
|
|
return;
|
|
}
|
|
});
|
|
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Simulates delay
|
|
*/
|
|
sleep: function(milliseconds) {
|
|
var start = new Date().getTime();
|
|
for (var i = 0; i < 1e7; i++) {
|
|
if ((new Date().getTime() - start) > milliseconds){
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Gets randomly generated integer value within given min and max range
|
|
* @param {number} min Range start value
|
|
* @param {number} min Range end value
|
|
* @returns {number}
|
|
*/
|
|
getRandomInt: function(min, max) {
|
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
},
|
|
|
|
/**
|
|
* Gets state color's hex code by color name
|
|
* @param {string} name Color name
|
|
* @returns {string}
|
|
*/
|
|
getColor: function(name) {
|
|
return colors[name];
|
|
},
|
|
|
|
/**
|
|
* Checks whether Angular library is included
|
|
* @returns {boolean}
|
|
*/
|
|
isAngularVersion: function() {
|
|
return window.Zone !== undefined ? true : false;
|
|
}
|
|
}
|
|
}();
|
|
|
|
//== Initialize mUtil class on document ready
|
|
$(document).ready(function() {
|
|
mUtil.init();
|
|
});
|
|
(function($) {
|
|
|
|
if (typeof mUtil === 'undefined') throw new Error('mUtil is required and must be included before mDatatable.');
|
|
|
|
// plugin setup
|
|
$.fn.mDatatable = function(options) {
|
|
if ($(this).length === 0) throw new Error('No mDatatable element exist.');
|
|
|
|
// global variables
|
|
var datatable = this;
|
|
|
|
// debug enabled?
|
|
// 1) state will be cleared on each refresh
|
|
// 2) enable some logs
|
|
// 3) etc.
|
|
datatable.debug = false;
|
|
|
|
datatable.API = {
|
|
record: null,
|
|
value: null,
|
|
params: null,
|
|
};
|
|
|
|
var Plugin = {
|
|
/********************
|
|
** PRIVATE METHODS
|
|
********************/
|
|
isInit: false,
|
|
offset: 110,
|
|
stateId: 'meta',
|
|
ajaxParams: {},
|
|
|
|
init: function(options) {
|
|
Plugin.setupBaseDOM.call();
|
|
Plugin.setupDOM(datatable.table);
|
|
Plugin.spinnerCallback(true);
|
|
|
|
// set custom query from options
|
|
Plugin.setDataSourceQuery(Plugin.getOption('data.source.read.params.query'));
|
|
|
|
// on event after layout had done setup, show datatable
|
|
$(datatable).on('m-datatable--on-layout-updated', Plugin.afterRender);
|
|
|
|
if (datatable.debug) Plugin.stateRemove(Plugin.stateId);
|
|
|
|
// initialize extensions
|
|
$.each(Plugin.getOption('extensions'), function(extName, extOptions) {
|
|
if (typeof $.fn.mDatatable[extName] === 'function')
|
|
new $.fn.mDatatable[extName](datatable, extOptions);
|
|
});
|
|
|
|
// get data
|
|
if (options.data.type === 'remote' || options.data.type === 'local') {
|
|
if (options.data.saveState === false
|
|
|| options.data.saveState.cookie === false
|
|
&& options.data.saveState.webstorage === false) {
|
|
Plugin.stateRemove(Plugin.stateId);
|
|
}
|
|
// get data for local
|
|
if (options.data.type === 'local' &&
|
|
typeof options.data.source === 'object') {
|
|
if (options.data.source === null) {
|
|
// this is html table
|
|
Plugin.extractTable();
|
|
}
|
|
datatable.dataSet = datatable.originalDataSet = Plugin.dataMapCallback(options.data.source);
|
|
}
|
|
Plugin.dataRender();
|
|
}
|
|
|
|
Plugin.setHeadTitle.call();
|
|
Plugin.setHeadTitle.call(this, datatable.tableFoot);
|
|
|
|
// for normal table, setup layout right away
|
|
if (options.data.type === null) {
|
|
Plugin.setupCellField.call();
|
|
Plugin.setupTemplateCell.call();
|
|
// setup extra system column properties
|
|
Plugin.setupSystemColumn.call();
|
|
}
|
|
|
|
// hide header
|
|
if (typeof options.layout.header !== 'undefined' &&
|
|
options.layout.header === false) {
|
|
$(datatable.table).find('thead').remove();
|
|
}
|
|
|
|
// hide footer
|
|
if (typeof options.layout.footer !== 'undefined' &&
|
|
options.layout.footer === false) {
|
|
$(datatable.table).find('tfoot').remove();
|
|
}
|
|
|
|
// for normal and local data type, run layoutUpdate
|
|
if (options.data.type === null ||
|
|
options.data.type === 'local') {
|
|
// setup nested datatable, if option enabled
|
|
Plugin.setupSubDatatable.call();
|
|
// setup extra system column properties
|
|
Plugin.setupSystemColumn.call();
|
|
Plugin.redraw();
|
|
}
|
|
|
|
$(window).resize(Plugin.fullRender);
|
|
|
|
$(datatable).height('');
|
|
|
|
$(Plugin.getOption('search.input')).on('keyup', function(e) {
|
|
if (Plugin.getOption('search.onEnter') && e.which !== 13) return;
|
|
Plugin.search($(this).val().toLowerCase());
|
|
});
|
|
|
|
return datatable;
|
|
},
|
|
|
|
/**
|
|
* Extract static HTML table content into datasource
|
|
*/
|
|
extractTable: function() {
|
|
var columns = [];
|
|
var headers = $(datatable).
|
|
find('tr:first-child th').
|
|
get().
|
|
map(function(cell, i) {
|
|
var field = $(cell).data('field');
|
|
if (typeof field === 'undefined') {
|
|
field = $(cell).text().trim();
|
|
}
|
|
var column = {field: field, title: field};
|
|
for (var ii in options.columns) {
|
|
if (options.columns[ii].field === field) {
|
|
column = $.extend(true, {}, options.columns[ii], column);
|
|
}
|
|
}
|
|
columns.push(column);
|
|
return field;
|
|
});
|
|
// auto create columns config
|
|
options.columns = columns;
|
|
|
|
var data = $(datatable).find('tr').get().map(function(row) {
|
|
return $(row).find('td').get().map(function(cell, i) {
|
|
return $(cell).html();
|
|
});
|
|
});
|
|
var source = [];
|
|
$.each(data, function(i, row) {
|
|
if (row.length === 0) return;
|
|
var td = {};
|
|
$.each(row, function(index, value) {
|
|
td[headers[index]] = value;
|
|
});
|
|
source.push(td);
|
|
});
|
|
options.data.source = source;
|
|
},
|
|
|
|
/**
|
|
* One time layout update on init
|
|
*/
|
|
layoutUpdate: function() {
|
|
// setup nested datatable, if option enabled
|
|
Plugin.setupSubDatatable.call();
|
|
|
|
// setup extra system column properties
|
|
Plugin.setupSystemColumn.call();
|
|
|
|
Plugin.columnHide.call();
|
|
|
|
Plugin.sorting.call();
|
|
|
|
// setup cell hover event
|
|
Plugin.setupHover.call();
|
|
|
|
if (typeof options.detail === 'undefined'
|
|
// temporary disable lock column in subtable
|
|
&& Plugin.getDepth() === 1) {
|
|
// lock columns handler
|
|
Plugin.lockTable.call();
|
|
}
|
|
|
|
if (!Plugin.isInit) {
|
|
$(datatable).trigger('m-datatable--on-init', {table: $(datatable.wrap).attr('id'), options: options});
|
|
Plugin.isInit = true;
|
|
}
|
|
|
|
$(datatable).trigger('m-datatable--on-layout-updated', {table: $(datatable.wrap).attr('id')});
|
|
},
|
|
|
|
lockTable: function() {
|
|
// todo; revise lock table responsive
|
|
var lock = {
|
|
lockEnabled: false,
|
|
init: function() {
|
|
// check if table should be locked columns
|
|
lock.lockEnabled = Plugin.lockEnabledColumns();
|
|
if (lock.lockEnabled.left.length === 0 &&
|
|
lock.lockEnabled.right.length === 0) {
|
|
return;
|
|
}
|
|
lock.enable();
|
|
},
|
|
enable: function() {
|
|
var enableLock = function(tablePart) {
|
|
// check if already has lock column
|
|
if ($(tablePart).find('.m-datatable__lock').length > 0) {
|
|
Plugin.log('Locked container already exist in: ', tablePart);
|
|
return;
|
|
}
|
|
// check if no rows exists
|
|
if ($(tablePart).find('.m-datatable__row').length === 0) {
|
|
Plugin.log('No row exist in: ', tablePart);
|
|
return;
|
|
}
|
|
|
|
// locked div container
|
|
var lockLeft = $('<div/>').
|
|
addClass('m-datatable__lock m-datatable__lock--left');
|
|
var lockScroll = $('<div/>').
|
|
addClass('m-datatable__lock m-datatable__lock--scroll');
|
|
var lockRight = $('<div/>').
|
|
addClass('m-datatable__lock m-datatable__lock--right');
|
|
|
|
$(tablePart).find('.m-datatable__row').each(function() {
|
|
var rowLeft = $('<tr/>').
|
|
addClass('m-datatable__row').
|
|
appendTo(lockLeft);
|
|
var rowScroll = $('<tr/>').
|
|
addClass('m-datatable__row').
|
|
appendTo(lockScroll);
|
|
var rowRight = $('<tr/>').
|
|
addClass('m-datatable__row').
|
|
appendTo(lockRight);
|
|
$(this).find('.m-datatable__cell').each(function() {
|
|
var locked = $(this).data('locked');
|
|
if (typeof locked !== 'undefined') {
|
|
if (typeof locked.left !== 'undefined' || locked === true) {
|
|
// default locked to left
|
|
$(this).appendTo(rowLeft);
|
|
}
|
|
if (typeof locked.right !== 'undefined') {
|
|
$(this).appendTo(rowRight);
|
|
}
|
|
} else {
|
|
$(this).appendTo(rowScroll);
|
|
}
|
|
});
|
|
// remove old row
|
|
$(this).remove();
|
|
});
|
|
|
|
if (lock.lockEnabled.left.length > 0) {
|
|
$(datatable.wrap).addClass('m-datatable--lock');
|
|
$(lockLeft).appendTo(tablePart);
|
|
}
|
|
if (lock.lockEnabled.left.length > 0 || lock.lockEnabled.right.length > 0) {
|
|
$(lockScroll).appendTo(tablePart);
|
|
}
|
|
if (lock.lockEnabled.right.length > 0) {
|
|
$(datatable.wrap).addClass('m-datatable--lock');
|
|
$(lockRight).appendTo(tablePart);
|
|
}
|
|
};
|
|
|
|
$(datatable.table).find('thead,tbody,tfoot').each(function() {
|
|
var tablePart = this;
|
|
if ($(this).find('.m-datatable__lock').length === 0) {
|
|
$(this).ready(function() {
|
|
enableLock(tablePart);
|
|
});
|
|
}
|
|
});
|
|
},
|
|
};
|
|
lock.init();
|
|
return lock;
|
|
},
|
|
|
|
/**
|
|
* Render everything for resize
|
|
*/
|
|
fullRender: function() {
|
|
// todo; full render datatable for specific condition only
|
|
Plugin.spinnerCallback(true);
|
|
$(datatable.wrap).removeClass('m-datatable--loaded');
|
|
|
|
var lockEnabled = Plugin.lockEnabledColumns();
|
|
if (lockEnabled.left.length === 0 &&
|
|
lockEnabled.right.length === 0 && Plugin.isLocked()) {
|
|
// reset locked table head if not meet the requirements
|
|
$(datatable.tableHead).empty();
|
|
Plugin.setHeadTitle();
|
|
if (typeof datatable.tableFoot !== 'undefined') {
|
|
$(datatable.tableFoot).empty();
|
|
Plugin.setHeadTitle(datatable.tableFoot);
|
|
}
|
|
}
|
|
|
|
Plugin.insertData();
|
|
},
|
|
|
|
lockEnabledColumns: function() {
|
|
var screen = $(window).width();
|
|
var columns = options.columns;
|
|
var enabled = {left: [], right: []};
|
|
$.each(columns, function(i, column) {
|
|
if (typeof column.locked !== 'undefined') {
|
|
if (typeof column.locked.left !== 'undefined') {
|
|
if (mUtil.getBreakpoint(column.locked.left) <= screen) {
|
|
enabled['left'].push(column.locked.left);
|
|
}
|
|
}
|
|
if (typeof column.locked.right !== 'undefined') {
|
|
if (mUtil.getBreakpoint(column.locked.right) <= screen) {
|
|
enabled['right'].push(column.locked.right);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
return enabled;
|
|
},
|
|
|
|
/**
|
|
* After render event, called by m-datatable--on-layout-updated
|
|
* @param e
|
|
* @param args
|
|
*/
|
|
afterRender: function(e, args) {
|
|
if (args.table == $(datatable.wrap).attr('id')) {
|
|
if (!Plugin.isLocked()) {
|
|
Plugin.redraw();
|
|
// work on non locked columns
|
|
if (Plugin.getOption('rows.autoHide')) {
|
|
Plugin.autoHide();
|
|
// reset r
|
|
$(datatable.table).find('.m-datatable__row').css('height', '');
|
|
}
|
|
}
|
|
$(datatable).ready(function() {
|
|
// row even class
|
|
$(datatable.tableBody).find('.m-datatable__row').removeClass('m-datatable__row--even');
|
|
if ($(datatable.wrap).hasClass('m-datatable--subtable')) {
|
|
$(datatable.tableBody).find('.m-datatable__row:not(.m-datatable__row-detail):even').addClass('m-datatable__row--even');
|
|
} else {
|
|
$(datatable.tableBody).find('.m-datatable__row:nth-child(even)').addClass('m-datatable__row--even');
|
|
}
|
|
|
|
// redraw locked columns table
|
|
if (Plugin.isLocked()) Plugin.redraw();
|
|
$(datatable.tableBody).css('visibility', '');
|
|
$(datatable.wrap).addClass('m-datatable--loaded');
|
|
Plugin.scrollbar.call();
|
|
// Plugin.hoverColumn.call();
|
|
Plugin.spinnerCallback(false);
|
|
});
|
|
}
|
|
},
|
|
|
|
hoverTimer: 0,
|
|
isScrolling: false,
|
|
setupHover: function() {
|
|
$(window).scroll(function(e) {
|
|
// stop hover when scrolling
|
|
clearTimeout(Plugin.hoverTimer);
|
|
Plugin.isScrolling = true;
|
|
});
|
|
|
|
$(datatable.tableBody).
|
|
find('.m-datatable__cell').
|
|
off('mouseenter', 'mouseleave').
|
|
on('mouseenter', function() {
|
|
// reset scroll timer to hover class
|
|
Plugin.hoverTimer = setTimeout(function() {
|
|
Plugin.isScrolling = false;
|
|
}, 200);
|
|
if (Plugin.isScrolling) return;
|
|
|
|
// normal table
|
|
var row = $(this).
|
|
closest('.m-datatable__row').
|
|
addClass('m-datatable__row--hover');
|
|
var index = $(row).index() + 1;
|
|
|
|
// lock table
|
|
$(row).
|
|
closest('.m-datatable__lock').
|
|
parent().
|
|
find('.m-datatable__row:nth-child(' + index + ')').
|
|
addClass('m-datatable__row--hover');
|
|
}).
|
|
on('mouseleave', function() {
|
|
// normal table
|
|
var row = $(this).
|
|
closest('.m-datatable__row').
|
|
removeClass('m-datatable__row--hover');
|
|
var index = $(row).index() + 1;
|
|
|
|
// look table
|
|
$(row).
|
|
closest('.m-datatable__lock').
|
|
parent().
|
|
find('.m-datatable__row:nth-child(' + index + ')').
|
|
removeClass('m-datatable__row--hover');
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Adjust width of locked table containers by resize handler
|
|
* @returns {number}
|
|
*/
|
|
adjustLockContainer: function() {
|
|
if (!Plugin.isLocked()) return 0;
|
|
|
|
// refer to head dimension
|
|
var containerWidth = $(datatable.tableHead).width();
|
|
var lockLeft = $(datatable.tableHead).
|
|
find('.m-datatable__lock--left').
|
|
width();
|
|
var lockRight = $(datatable.tableHead).
|
|
find('.m-datatable__lock--right').
|
|
width();
|
|
|
|
if (typeof lockLeft === 'undefined') lockLeft = 0;
|
|
if (typeof lockRight === 'undefined') lockRight = 0;
|
|
|
|
var lockScroll = Math.floor(containerWidth - lockLeft - lockRight);
|
|
$(datatable.table).
|
|
find('.m-datatable__lock--scroll').
|
|
css('width', lockScroll);
|
|
|
|
return lockScroll;
|
|
},
|
|
|
|
/**
|
|
* todo; not in use
|
|
*/
|
|
dragResize: function() {
|
|
var pressed = false;
|
|
var start = undefined;
|
|
var startX, startWidth;
|
|
$(datatable.tableHead).
|
|
find('.m-datatable__cell').
|
|
mousedown(function(e) {
|
|
start = $(this);
|
|
pressed = true;
|
|
startX = e.pageX;
|
|
startWidth = $(this).width();
|
|
$(start).addClass('m-datatable__cell--resizing');
|
|
|
|
}).
|
|
mousemove(function(e) {
|
|
if (pressed) {
|
|
var i = $(start).index();
|
|
var tableBody = $(datatable.tableBody);
|
|
var ifLocked = $(start).closest('.m-datatable__lock');
|
|
|
|
if (ifLocked) {
|
|
var lockedIndex = $(ifLocked).index();
|
|
tableBody = $(datatable.tableBody).
|
|
find('.m-datatable__lock').
|
|
eq(lockedIndex);
|
|
}
|
|
|
|
$(tableBody).find('.m-datatable__row').each(function(tri, tr) {
|
|
$(tr).
|
|
find('.m-datatable__cell').
|
|
eq(i).
|
|
width(startWidth + (e.pageX - startX)).
|
|
children().
|
|
width(startWidth + (e.pageX - startX));
|
|
});
|
|
|
|
$(start).children().css('width', startWidth + (e.pageX - startX));
|
|
}
|
|
|
|
}).
|
|
mouseup(function() {
|
|
$(start).removeClass('m-datatable__cell--resizing');
|
|
pressed = false;
|
|
});
|
|
|
|
$(document).mouseup(function() {
|
|
$(start).removeClass('m-datatable__cell--resizing');
|
|
pressed = false;
|
|
});
|
|
},
|
|
|
|
/**
|
|
* To prepare placeholder for table before content is loading
|
|
*/
|
|
initHeight: function() {
|
|
if (options.layout.height && options.layout.scroll) {
|
|
var theadHeight = $(datatable.tableHead).find('.m-datatable__row').height();
|
|
var tfootHeight = $(datatable.tableFoot).find('.m-datatable__row').height();
|
|
var bodyHeight = options.layout.height;
|
|
if (theadHeight > 0) {
|
|
bodyHeight -= theadHeight;
|
|
}
|
|
if (tfootHeight > 0) {
|
|
bodyHeight -= tfootHeight;
|
|
}
|
|
$(datatable.tableBody).css('max-height', bodyHeight);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Setup base DOM (table, thead, tbody, tfoot) and create if not exist.
|
|
*/
|
|
setupBaseDOM: function() {
|
|
// keep original state before mDatatable initialize
|
|
datatable.initialDatatable = $(datatable).clone();
|
|
|
|
// main element
|
|
if ($(datatable).prop('tagName') === 'TABLE') {
|
|
// if main init element is <table>, wrap with div
|
|
datatable.table = $(datatable).
|
|
removeClass('m-datatable').
|
|
addClass('m-datatable__table');
|
|
if ($(datatable.table).parents('.m-datatable').length === 0) {
|
|
datatable.table.wrap($('<div/>').
|
|
addClass('m-datatable').
|
|
addClass('m-datatable--' + options.layout.theme));
|
|
datatable.wrap = $(datatable.table).parent();
|
|
}
|
|
} else {
|
|
// create table
|
|
datatable.wrap = $(datatable).
|
|
addClass('m-datatable').
|
|
addClass('m-datatable--' + options.layout.theme);
|
|
datatable.table = $('<table/>').
|
|
addClass('m-datatable__table').
|
|
appendTo(datatable);
|
|
}
|
|
|
|
if (typeof options.layout.class !== 'undefined') {
|
|
$(datatable.wrap).addClass(options.layout.class);
|
|
}
|
|
|
|
$(datatable.table).
|
|
removeClass('m-datatable--destroyed').
|
|
css('display', 'block');
|
|
|
|
// force disable save state
|
|
if (typeof $(datatable).attr('id') === 'undefined') {
|
|
Plugin.setOption('data.saveState', false);
|
|
$(datatable.table).attr('id', mUtil.getUniqueID('m-datatable--'));
|
|
}
|
|
|
|
// predefine table height
|
|
if (Plugin.getOption('layout.minHeight'))
|
|
$(datatable.table).css('min-height', Plugin.getOption('layout.minHeight'));
|
|
|
|
if (Plugin.getOption('layout.height'))
|
|
$(datatable.table).css('max-height', Plugin.getOption('layout.height'));
|
|
|
|
// for normal table load
|
|
if (options.data.type === null) {
|
|
$(datatable.table).css('width', '').css('display', '');
|
|
}
|
|
|
|
// create table head element
|
|
datatable.tableHead = $(datatable.table).find('thead');
|
|
if ($(datatable.tableHead).length === 0) {
|
|
datatable.tableHead = $('<thead/>').prependTo(datatable.table);
|
|
}
|
|
|
|
// create table head element
|
|
datatable.tableBody = $(datatable.table).find('tbody');
|
|
if ($(datatable.tableBody).length === 0) {
|
|
datatable.tableBody = $('<tbody/>').appendTo(datatable.table);
|
|
}
|
|
|
|
if (typeof options.layout.footer !== 'undefined' &&
|
|
options.layout.footer) {
|
|
// create table foot element
|
|
datatable.tableFoot = $(datatable.table).find('tfoot');
|
|
if ($(datatable.tableFoot).length === 0) {
|
|
datatable.tableFoot = $('<tfoot/>').appendTo(datatable.table);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Set column data before table manipulation.
|
|
*/
|
|
setupCellField: function(tableParts) {
|
|
if (typeof tableParts === 'undefined') tableParts = $(datatable.table).children();
|
|
var columns = options.columns;
|
|
$.each(tableParts, function(part, tablePart) {
|
|
$(tablePart).find('.m-datatable__row').each(function(tri, tr) {
|
|
// prepare data
|
|
$(tr).find('.m-datatable__cell').each(function(tdi, td) {
|
|
if (typeof columns[tdi] !== 'undefined') {
|
|
$(td).data(columns[tdi]);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Set column template callback
|
|
* @param tablePart
|
|
*/
|
|
setupTemplateCell: function(tablePart) {
|
|
if (typeof tablePart === 'undefined') tablePart = datatable.tableBody;
|
|
var columns = options.columns;
|
|
$(tablePart).find('.m-datatable__row').each(function(tri, tr) {
|
|
// row data object, if any
|
|
var obj = $(tr).data('obj') || {};
|
|
|
|
// @deprecated in v5.0.6
|
|
obj['getIndex'] = function() {
|
|
return tri;
|
|
};
|
|
// @deprecated in v5.0.6
|
|
obj['getDatatable'] = function() {
|
|
return datatable;
|
|
};
|
|
|
|
// @deprecated in v5.0.6
|
|
var rowCallback = Plugin.getOption('rows.callback');
|
|
if (typeof rowCallback === 'function') {
|
|
rowCallback($(tr), obj, tri);
|
|
}
|
|
// before template row callback
|
|
var beforeTemplate = Plugin.getOption('rows.beforeTemplate');
|
|
if (typeof beforeTemplate === 'function') {
|
|
beforeTemplate($(tr), obj, tri);
|
|
}
|
|
// if data object is undefined, collect from table
|
|
if (typeof obj === 'undefined') {
|
|
obj = {};
|
|
$(tr).find('.m-datatable__cell').each(function(tdi, td) {
|
|
// get column settings by field
|
|
var column = $.grep(columns, function(n, i) {
|
|
return $(td).data('field') === n.field;
|
|
})[0];
|
|
if (typeof column !== 'undefined') {
|
|
obj[column['field']] = $(td).text();
|
|
}
|
|
});
|
|
}
|
|
|
|
$(tr).find('.m-datatable__cell').each(function(tdi, td) {
|
|
// get column settings by field
|
|
var column = $.grep(columns, function(n, i) {
|
|
return $(td).data('field') === n.field;
|
|
})[0];
|
|
if (typeof column !== 'undefined') {
|
|
// column template
|
|
if (typeof column.template !== 'undefined') {
|
|
var finalValue = '';
|
|
// template string
|
|
if (typeof column.template === 'string') {
|
|
finalValue = Plugin.dataPlaceholder(column.template, obj);
|
|
}
|
|
// template callback function
|
|
if (typeof column.template === 'function') {
|
|
finalValue = column.template(obj, tri, datatable);
|
|
}
|
|
var span = $('<span/>').append(finalValue);
|
|
// insert to cell, wrap with span
|
|
$(td).html(span);
|
|
|
|
// set span overflow
|
|
if (typeof column.overflow !== 'undefined') {
|
|
$(span).css('overflow', column.overflow);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// after template row callback
|
|
var afterTemplate = Plugin.getOption('rows.afterTemplate');
|
|
if (typeof afterTemplate === 'function') {
|
|
afterTemplate($(tr), obj, tri);
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Setup extra system column properties
|
|
* Note: selector checkbox, subtable toggle
|
|
*/
|
|
setupSystemColumn: function() {
|
|
datatable.dataSet = datatable.dataSet || [];
|
|
// no records available
|
|
if (datatable.dataSet.length === 0) return;
|
|
|
|
var columns = options.columns;
|
|
$(datatable.tableBody).
|
|
find('.m-datatable__row').
|
|
each(function(tri, tr) {
|
|
$(tr).find('.m-datatable__cell').each(function(tdi, td) {
|
|
// get column settings by field
|
|
var column = $.grep(columns, function(n, i) {
|
|
return $(td).data('field') === n.field;
|
|
})[0];
|
|
if (typeof column !== 'undefined') {
|
|
var value = $(td).text();
|
|
|
|
// enable column selector
|
|
if (typeof column.selector !== 'undefined' &&
|
|
column.selector !== false) {
|
|
// check if checkbox exist
|
|
if ($(td).find('.m-checkbox [type="checkbox"]').length > 0) return;
|
|
$(td).addClass('m-datatable__cell--check');
|
|
// append checkbox
|
|
var chk = $('<label/>').
|
|
addClass('m-checkbox m-checkbox--single').
|
|
append($('<input/>').
|
|
attr('type', 'checkbox').
|
|
attr('value', value).
|
|
on('click', function() {
|
|
if ($(this).is(':checked')) {
|
|
// add checkbox active row class
|
|
Plugin.setActive(this);
|
|
} else {
|
|
// add checkbox active row class
|
|
Plugin.setInactive(this);
|
|
}
|
|
})).
|
|
append($('<span/>'));
|
|
|
|
// checkbox selector has outline style
|
|
if (typeof column.selector.class !== 'undefined') {
|
|
$(chk).addClass(column.selector.class);
|
|
}
|
|
|
|
$(td).children().html(chk);
|
|
}
|
|
|
|
// enable column subtable toggle
|
|
if (typeof column.subtable !== 'undefined' && column.subtable) {
|
|
// check if subtable toggle exist
|
|
if ($(td).find('.m-datatable__toggle-subtable').length > 0) return;
|
|
// append subtable toggle
|
|
$(td).
|
|
children().
|
|
html($('<a/>').
|
|
addClass('m-datatable__toggle-subtable').
|
|
attr('href', '#').
|
|
attr('data-value', value).
|
|
append($('<i/>').
|
|
addClass(Plugin.getOption('layout.icons.rowDetail.collapse'))));
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// init checkbox for header/footer
|
|
var initCheckbox = function(tr) {
|
|
// get column settings by field
|
|
var column = $.grep(columns, function(n, i) {
|
|
return typeof n.selector !== 'undefined' && n.selector !== false;
|
|
})[0];
|
|
|
|
if (typeof column !== 'undefined') {
|
|
// enable column selector
|
|
if (typeof column.selector !== 'undefined' && column.selector !== false) {
|
|
var td = $(tr).find('[data-field="' + column.field + '"]');
|
|
// check if checkbox exist
|
|
if ($(td).find('.m-checkbox [type="checkbox"]').length > 0) return;
|
|
$(td).addClass('m-datatable__cell--check');
|
|
|
|
// todo; check all, for server pagination
|
|
// append checkbox
|
|
var chk = $('<label/>').
|
|
addClass('m-checkbox m-checkbox--single m-checkbox--all').
|
|
append($('<input/>').
|
|
attr('type', 'checkbox').
|
|
on('click', function() {
|
|
if ($(this).is(':checked')) {
|
|
Plugin.setActiveAll(true);
|
|
} else {
|
|
Plugin.setActiveAll(false);
|
|
}
|
|
})).
|
|
append($('<span/>'));
|
|
|
|
// checkbox selector has outline style
|
|
if (typeof column.selector.class !== 'undefined') {
|
|
$(chk).addClass(column.selector.class);
|
|
}
|
|
|
|
$(td).children().html(chk);
|
|
}
|
|
}
|
|
};
|
|
|
|
if (options.layout.header) {
|
|
initCheckbox($(datatable.tableHead).find('.m-datatable__row').first());
|
|
}
|
|
if (options.layout.footer) {
|
|
initCheckbox($(datatable.tableFoot).find('.m-datatable__row').first());
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Adjust width to match container size
|
|
*/
|
|
adjustCellsWidth: function() {
|
|
// get table width
|
|
var containerWidth = $(datatable.tableHead).width();
|
|
|
|
// offset reserved for sort icon
|
|
var sortOffset = 20;
|
|
|
|
// get total number of columns
|
|
var columns = Plugin.getOneRow(datatable.tableHead, 1).length;
|
|
if (columns > 0) {
|
|
// remove reserved sort icon width
|
|
containerWidth = containerWidth - (sortOffset * columns);
|
|
var minWidth = Math.floor(containerWidth / columns);
|
|
|
|
// minimum width
|
|
if (minWidth <= Plugin.offset) {
|
|
minWidth = Plugin.offset;
|
|
}
|
|
|
|
$(datatable.table).
|
|
find('.m-datatable__row').
|
|
find('.m-datatable__cell').
|
|
each(function(tdi, td) {
|
|
var width = minWidth;
|
|
var dataWidth = $(td).data('width');
|
|
if (typeof dataWidth !== 'undefined') {
|
|
width = dataWidth;
|
|
}
|
|
$(td).children().css('width', width);
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Adjust height to match container size
|
|
*/
|
|
adjustCellsHeight: function() {
|
|
$.each($(datatable.table).children(), function(part, tablePart) {
|
|
var totalRows = $(tablePart).find('.m-datatable__row').first().parent().find('.m-datatable__row').length;
|
|
for (var i = 1; i <= totalRows; i++) {
|
|
var rows = $(tablePart).find('.m-datatable__row:nth-child(' + i + ')');
|
|
if ($(rows).length > 0) {
|
|
var maxHeight = Math.max.apply(null, $(rows).map(function() {
|
|
return $(this).height();
|
|
}).get());
|
|
$(rows).css('height', Math.ceil(parseInt(maxHeight)));
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Setup table DOM and classes
|
|
*/
|
|
setupDOM: function(table) {
|
|
// set table classes
|
|
$(table).find('> thead').addClass('m-datatable__head');
|
|
$(table).find('> tbody').addClass('m-datatable__body');
|
|
$(table).find('> tfoot').addClass('m-datatable__foot');
|
|
$(table).find('tr').addClass('m-datatable__row');
|
|
$(table).find('tr > th, tr > td').addClass('m-datatable__cell');
|
|
$(table).find('tr > th, tr > td').each(function(i, td) {
|
|
if ($(td).find('span').length === 0) {
|
|
$(td).wrapInner($('<span/>').css('width', Plugin.offset));
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Default scrollbar
|
|
* @returns {{tableLocked: null, init: init, onScrolling: onScrolling}}
|
|
*/
|
|
scrollbar: function() {
|
|
var scroll = {
|
|
scrollable: null,
|
|
tableLocked: null,
|
|
mcsOptions: {
|
|
scrollInertia: 0,
|
|
autoDraggerLength: true,
|
|
autoHideScrollbar: true,
|
|
autoExpandScrollbar: false,
|
|
alwaysShowScrollbar: 0,
|
|
mouseWheel: {
|
|
scrollAmount: 120,
|
|
preventDefault: false,
|
|
},
|
|
advanced: {
|
|
updateOnContentResize: true,
|
|
autoExpandHorizontalScroll: true,
|
|
},
|
|
theme: 'minimal-dark',
|
|
},
|
|
init: function() {
|
|
// destroy previous custom scrollbar
|
|
Plugin.destroyScroller(scroll.scrollable);
|
|
var screen = mUtil.getViewPort().width;
|
|
// setup scrollable datatable
|
|
if (options.layout.scroll) {
|
|
// add scrollable datatable class
|
|
$(datatable.wrap).addClass('m-datatable--scroll');
|
|
|
|
var scrollable = $(datatable.tableBody).find('.m-datatable__lock--scroll');
|
|
|
|
// check if scrollable area have rows
|
|
if ($(scrollable).find('.m-datatable__row').length > 0 && $(scrollable).length > 0) {
|
|
scroll.scrollHead = $(datatable.tableHead).find('> .m-datatable__lock--scroll > .m-datatable__row');
|
|
scroll.scrollFoot = $(datatable.tableFoot).find('> .m-datatable__lock--scroll > .m-datatable__row');
|
|
scroll.tableLocked = $(datatable.tableBody).find('.m-datatable__lock:not(.m-datatable__lock--scroll)');
|
|
if (screen > mUtil.getBreakpoint('lg')) {
|
|
scroll.mCustomScrollbar(scrollable);
|
|
} else {
|
|
scroll.defaultScrollbar(scrollable);
|
|
}
|
|
} else if ($(datatable.tableBody).find('.m-datatable__row').length > 0) {
|
|
scroll.scrollHead = $(datatable.tableHead).find('> .m-datatable__row');
|
|
scroll.scrollFoot = $(datatable.tableFoot).find('> .m-datatable__row');
|
|
if (screen > mUtil.getBreakpoint('lg')) {
|
|
scroll.mCustomScrollbar(datatable.tableBody);
|
|
} else {
|
|
scroll.defaultScrollbar(datatable.tableBody);
|
|
}
|
|
}
|
|
} else {
|
|
$(datatable.table).
|
|
// css('height', 'auto').
|
|
css('overflow-x', 'auto');
|
|
}
|
|
},
|
|
defaultScrollbar: function(scrollable) {
|
|
$(scrollable).
|
|
css('overflow', 'auto').
|
|
css('max-height', Plugin.getOption('layout.height')).
|
|
on('scroll', scroll.onScrolling);
|
|
},
|
|
onScrolling: function(e) {
|
|
var left = $(this).scrollLeft();
|
|
var top = $(this).scrollTop();
|
|
$(scroll.scrollHead).css('left', -left);
|
|
$(scroll.scrollFoot).css('left', -left);
|
|
$(scroll.tableLocked).each(function(i, table) {
|
|
$(table).css('top', -top);
|
|
});
|
|
},
|
|
mCustomScrollbar: function(scrollable) {
|
|
scroll.scrollable = scrollable;
|
|
var height = Plugin.getOption('layout.height');
|
|
// vertical and horizontal scrollbar
|
|
var axis = 'xy';
|
|
if (height === null) {
|
|
// horizontal scrollbar
|
|
axis = 'x';
|
|
}
|
|
var mcsOptions = $.extend({}, scroll.mcsOptions, {
|
|
axis: axis,
|
|
setHeight: $(datatable.tableBody).height(),
|
|
callbacks: {
|
|
whileScrolling: function() {
|
|
var mcs = this.mcs;
|
|
$(scroll.scrollHead).css('left', mcs.left);
|
|
$(scroll.scrollFoot).css('left', mcs.left);
|
|
$(scroll.tableLocked).each(function(i, table) {
|
|
$(table).css('top', mcs.top);
|
|
});
|
|
// stop hover when scrolling
|
|
clearTimeout(Plugin.hoverTimer);
|
|
Plugin.isScrolling = true;
|
|
},
|
|
},
|
|
});
|
|
|
|
if (Plugin.getOption('layout.smoothScroll.scrollbarShown') === true) {
|
|
$(scrollable).attr('data-scrollbar-shown', 'true');
|
|
}
|
|
|
|
// create a new instance for table body with scrollbar
|
|
Plugin.mCustomScrollbar(scrollable, mcsOptions);
|
|
},
|
|
};
|
|
scroll.init();
|
|
return scroll;
|
|
},
|
|
|
|
/**
|
|
* Init custom scrollbar and reset position
|
|
* @param element
|
|
* @param options
|
|
*/
|
|
mCustomScrollbar: function(element, options) {
|
|
$(datatable.tableBody).css('overflow', '');
|
|
// check if any custom scrollbar exist in the element
|
|
Plugin.destroyScroller($(datatable.table).find('.mCustomScrollbar'));
|
|
$(element).mCustomScrollbar(options);
|
|
},
|
|
|
|
/**
|
|
* Set column title from options.columns settings
|
|
*/
|
|
setHeadTitle: function(tablePart) {
|
|
if (typeof tablePart === 'undefined') tablePart = datatable.tableHead;
|
|
var columns = options.columns;
|
|
var row = $(tablePart).find('.m-datatable__row');
|
|
var ths = $(tablePart).find('.m-datatable__cell');
|
|
if ($(row).length === 0) {
|
|
row = $('<tr/>').appendTo(tablePart);
|
|
}
|
|
$.each(columns, function(i, column) {
|
|
var th = $(ths).eq(i);
|
|
if ($(th).length === 0) {
|
|
th = $('<th/>').appendTo(row);
|
|
}
|
|
// set column title
|
|
if (typeof column['title'] !== 'undefined') {
|
|
$(th).
|
|
html(column['title']).
|
|
attr('data-field', column.field).
|
|
data(column);
|
|
}
|
|
// apply text align to thead/tfoot
|
|
if (typeof column.textAlign !== 'undefined') {
|
|
var align = typeof datatable.textAlign[column.textAlign] !==
|
|
'undefined' ? datatable.textAlign[column.textAlign] : '';
|
|
$(th).addClass(align);
|
|
}
|
|
});
|
|
Plugin.setupDOM(tablePart);
|
|
},
|
|
|
|
/**
|
|
* Initiate to get remote or local data via ajax
|
|
*/
|
|
dataRender: function(action) {
|
|
$(datatable.table).
|
|
siblings('.m-datatable__pager').
|
|
removeClass('m-datatable--paging-loaded');
|
|
|
|
var buildMeta = function() {
|
|
datatable.dataSet = datatable.dataSet || [];
|
|
Plugin.localDataUpdate();
|
|
// local pagination meta
|
|
var meta = Plugin.getDataSourceParam('pagination');
|
|
if (meta.perpage === 0) {
|
|
meta.perpage = options.data.pageSize || 10;
|
|
}
|
|
meta.total = datatable.dataSet.length;
|
|
var start = Math.max(meta.perpage * (meta.page - 1), 0);
|
|
var end = Math.min(start + meta.perpage, meta.total);
|
|
datatable.dataSet = $(datatable.dataSet).slice(start, end);
|
|
return meta;
|
|
};
|
|
|
|
var afterGetData = function(result) {
|
|
var localPagingCallback = function(ctx, meta) {
|
|
if (!$(ctx.pager).hasClass('m-datatable--paging-loaded')) {
|
|
$(ctx.pager).remove();
|
|
ctx.init(meta);
|
|
}
|
|
$(ctx.pager).off().on('m-datatable--on-goto-page', function(e) {
|
|
$(ctx.pager).remove();
|
|
ctx.init(meta);
|
|
});
|
|
|
|
var start = Math.max(meta.perpage * (meta.page - 1), 0);
|
|
var end = Math.min(start + meta.perpage, meta.total);
|
|
|
|
Plugin.localDataUpdate();
|
|
datatable.dataSet = $(datatable.dataSet).slice(start, end);
|
|
|
|
// insert data into table content
|
|
Plugin.insertData();
|
|
};
|
|
|
|
$(datatable.wrap).removeClass('m-datatable--error');
|
|
// pagination enabled
|
|
if (options.pagination) {
|
|
if (options.data.serverPaging && options.data.type !== 'local') {
|
|
// server pagination
|
|
var serverMeta = Plugin.getObject('meta', result || null);
|
|
if (serverMeta !== null) {
|
|
Plugin.paging(serverMeta);
|
|
} else {
|
|
// no meta object from server response, fallback to local pagination
|
|
Plugin.paging(buildMeta(), localPagingCallback);
|
|
}
|
|
} else {
|
|
// local pagination can be used by remote data also
|
|
Plugin.paging(buildMeta(), localPagingCallback);
|
|
}
|
|
} else {
|
|
// pagination is disabled
|
|
Plugin.localDataUpdate();
|
|
}
|
|
// insert data into table content
|
|
Plugin.insertData();
|
|
};
|
|
|
|
// get local datasource
|
|
if (options.data.type === 'local'
|
|
// for remote json datasource
|
|
|| typeof options.data.source.read === 'undefined' &&
|
|
datatable.dataSet !== null
|
|
// for remote datasource, server sorting is disabled and data already received from remote
|
|
|| options.data.serverSorting === false && action === 'sort'
|
|
) {
|
|
afterGetData();
|
|
return;
|
|
}
|
|
|
|
// getting data from remote only
|
|
Plugin.getData().done(afterGetData);
|
|
},
|
|
|
|
/**
|
|
* Process ajax data
|
|
*/
|
|
insertData: function() {
|
|
datatable.dataSet = datatable.dataSet || [];
|
|
var params = Plugin.getDataSourceParam();
|
|
|
|
// todo; fix performance
|
|
var tableBody = $('<tbody/>').
|
|
addClass('m-datatable__body').
|
|
css('visibility', 'hidden');
|
|
var colLength = options.columns.length;
|
|
|
|
$.each(datatable.dataSet, function(i, row) {
|
|
// keep data object to row
|
|
var tr = $('<tr/>').attr('data-row', i).data('obj', row);
|
|
var idx = 0;
|
|
var tdArr = [];
|
|
for (var a = 0; a < colLength; a += 1) {
|
|
var column = options.columns[a];
|
|
var classes = [];
|
|
// add sorted class to cells
|
|
if (params.sort.field === column.field) {
|
|
classes.push('m-datatable__cell--sorted');
|
|
}
|
|
|
|
// apply text align
|
|
if (typeof column.textAlign !== 'undefined') {
|
|
var align = typeof datatable.textAlign[column.textAlign] !==
|
|
'undefined' ? datatable.textAlign[column.textAlign] : '';
|
|
classes.push(align);
|
|
}
|
|
|
|
tdArr[idx++] = '<td data-field="' + column.field + '"';
|
|
tdArr[idx++] = ' class="' + classes.join(' ') + '"';
|
|
tdArr[idx++] = '>';
|
|
tdArr[idx++] = Plugin.getObject(column.field, row);
|
|
tdArr[idx++] = '</td>';
|
|
}
|
|
$(tr).append(tdArr.join(''));
|
|
$(tableBody).append(tr);
|
|
});
|
|
|
|
// display no records message
|
|
if (datatable.dataSet.length === 0) {
|
|
Plugin.destroyScroller($(datatable.table).find('.mCustomScrollbar'));
|
|
$('<span/>').
|
|
addClass('m-datatable--error').
|
|
css('width', '100%').
|
|
html(Plugin.getOption('translate.records.noRecords')).
|
|
appendTo(tableBody);
|
|
$(datatable.wrap).addClass('m-datatable--error m-datatable--loaded');
|
|
Plugin.spinnerCallback(false);
|
|
}
|
|
|
|
// replace existing table body
|
|
$(datatable.tableBody).replaceWith(tableBody);
|
|
datatable.tableBody = tableBody;
|
|
|
|
// layout update
|
|
Plugin.setupDOM(datatable.table);
|
|
Plugin.setupCellField([datatable.tableBody]);
|
|
Plugin.setupTemplateCell(datatable.tableBody);
|
|
Plugin.layoutUpdate();
|
|
},
|
|
|
|
updateTableComponents: function() {
|
|
datatable.tableHead = $(datatable.table).children('thead');
|
|
datatable.tableBody = $(datatable.table).children('tbody');
|
|
datatable.tableFoot = $(datatable.table).children('tfoot');
|
|
},
|
|
|
|
/**
|
|
* Call ajax for raw JSON data
|
|
*/
|
|
getData: function() {
|
|
datatable.ajaxParams = {
|
|
dataType: 'json',
|
|
method: 'GET',
|
|
data: {},
|
|
timeout: 30000,
|
|
};
|
|
|
|
if (options.data.type === 'local') {
|
|
datatable.ajaxParams.url = options.data.source;
|
|
}
|
|
|
|
if (options.data.type === 'remote') {
|
|
datatable.ajaxParams.url = Plugin.getOption('data.source.read.url');
|
|
if (typeof datatable.ajaxParams.url !== 'string') datatable.ajaxParams.url = Plugin.getOption('data.source.read');
|
|
if (typeof datatable.ajaxParams.url !== 'string') datatable.ajaxParams.url = Plugin.getOption('data.source');
|
|
datatable.ajaxParams.headers = Plugin.getOption('data.source.read.headers');
|
|
datatable.ajaxParams.method = Plugin.getOption('data.source.read.method') || 'POST';
|
|
|
|
var data = Plugin.getDataSourceParam();
|
|
// remove if server params is not enabled
|
|
if (!Plugin.getOption('data.serverPaging')) {
|
|
delete data['pagination'];
|
|
}
|
|
if (!Plugin.getOption('data.serverSorting')) {
|
|
delete data['sort'];
|
|
}
|
|
datatable.ajaxParams.data['datatable'] = data;
|
|
}
|
|
|
|
return $.ajax(datatable.ajaxParams).done(function(response, textStatus, jqXHR) {
|
|
datatable.lastResponse = response;
|
|
// extendible data map callback for custom datasource
|
|
datatable.dataSet = datatable.originalDataSet = Plugin.dataMapCallback(response);
|
|
$(datatable).
|
|
trigger('m-datatable--on-ajax-done', [datatable.dataSet]);
|
|
}).fail(function(jqXHR, textStatus, errorThrown) {
|
|
Plugin.destroyScroller($(datatable.table).find('.mCustomScrollbar'));
|
|
$(datatable).trigger('m-datatable--on-ajax-fail', [jqXHR]);
|
|
$('<span/>').
|
|
addClass('m-datatable--error').
|
|
width('100%').
|
|
html(Plugin.getOption('translate.records.noRecords')).
|
|
appendTo(datatable.tableBody);
|
|
$(datatable.wrap).addClass('m-datatable--error m-datatable--loaded');
|
|
Plugin.spinnerCallback(false);
|
|
}).always(function() {
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Pagination object
|
|
* @param meta if null, local pagination, otherwise remote pagination
|
|
* @param callback for update data when navigating page
|
|
*/
|
|
paging: function(meta, callback) {
|
|
var pg = {
|
|
meta: null,
|
|
pager: null,
|
|
paginateEvent: null,
|
|
pagerLayout: {pagination: null, info: null},
|
|
callback: null,
|
|
init: function(meta) {
|
|
pg.meta = meta;
|
|
|
|
// todo; if meta object not exist will cause error
|
|
// always recount total pages
|
|
pg.meta.pages = Math.max(Math.ceil(pg.meta.total / pg.meta.perpage), 1);
|
|
|
|
// current page must be not over than total pages
|
|
if (pg.meta.page > pg.meta.pages) pg.meta.page = pg.meta.pages;
|
|
|
|
// set unique event name between tables
|
|
pg.paginateEvent = Plugin.getTablePrefix();
|
|
|
|
pg.pager = $(datatable.table).siblings('.m-datatable__pager');
|
|
if ($(pg.pager).hasClass('m-datatable--paging-loaded')) return;
|
|
|
|
// if class .m-datatable--paging-loaded not exist, recreate pagination
|
|
$(pg.pager).remove();
|
|
|
|
// if no pages available
|
|
if (pg.meta.pages === 0) return;
|
|
|
|
// update datasource params
|
|
Plugin.setDataSourceParam('pagination', {
|
|
page: pg.meta.page,
|
|
pages: pg.meta.pages,
|
|
perpage: pg.meta.perpage,
|
|
total: pg.meta.total,
|
|
});
|
|
|
|
// default callback function, contains remote pagination handler
|
|
pg.callback = pg.serverCallback;
|
|
// custom callback function
|
|
if (typeof callback === 'function') pg.callback = callback;
|
|
|
|
pg.addPaginateEvent();
|
|
pg.populate();
|
|
|
|
pg.meta.page = Math.max(pg.meta.page || 1, pg.meta.page);
|
|
|
|
$(datatable).trigger(pg.paginateEvent, pg.meta);
|
|
|
|
pg.pagingBreakpoint.call();
|
|
$(window).resize(pg.pagingBreakpoint);
|
|
},
|
|
serverCallback: function(ctx, meta) {
|
|
Plugin.dataRender();
|
|
},
|
|
populate: function() {
|
|
var icons = Plugin.getOption('layout.icons.pagination');
|
|
var title = Plugin.getOption('translate.toolbar.pagination.items.default');
|
|
// pager root element
|
|
pg.pager = $('<div/>').addClass('m-datatable__pager m-datatable--paging-loaded clearfix');
|
|
// numbering links
|
|
var pagerNumber = $('<ul/>').addClass('m-datatable__pager-nav');
|
|
pg.pagerLayout['pagination'] = pagerNumber;
|
|
|
|
// pager first/previous button
|
|
$('<li/>').
|
|
append($('<a/>').
|
|
attr('title', title.first).
|
|
addClass('m-datatable__pager-link m-datatable__pager-link--first').
|
|
append($('<i/>').addClass(icons.first)).
|
|
on('click', pg.gotoMorePage).
|
|
attr('data-page', 1)).
|
|
appendTo(pagerNumber);
|
|
$('<li/>').
|
|
append($('<a/>').
|
|
attr('title', title.prev).
|
|
addClass('m-datatable__pager-link m-datatable__pager-link--prev').
|
|
append($('<i/>').addClass(icons.prev)).
|
|
on('click', pg.gotoMorePage)).
|
|
appendTo(pagerNumber);
|
|
|
|
// more previous pages
|
|
$('<li/>').
|
|
append($('<a/>').
|
|
attr('title', title.more).
|
|
addClass('m-datatable__pager-link m-datatable__pager-link--more-prev').
|
|
html($('<i/>').addClass(icons.more)).
|
|
on('click', pg.gotoMorePage)).
|
|
appendTo(pagerNumber);
|
|
|
|
$('<li/>').
|
|
append($('<input/>').
|
|
attr('type', 'text').
|
|
addClass('m-pager-input form-control').
|
|
attr('title', title.input).
|
|
on('keyup', function() {
|
|
// on keyup update [data-page]
|
|
$(this).attr('data-page', Math.abs($(this).val()));
|
|
}).
|
|
on('keypress', function(e) {
|
|
// on keypressed enter button
|
|
if (e.which === 13) pg.gotoMorePage(e);
|
|
})).
|
|
appendTo(pagerNumber);
|
|
|
|
var pagesNumber = Plugin.getOption('toolbar.items.pagination.pages.desktop.pagesNumber');
|
|
var end = Math.ceil(pg.meta.page / pagesNumber) * pagesNumber;
|
|
var start = end - pagesNumber;
|
|
if (end > pg.meta.pages) {
|
|
end = pg.meta.pages;
|
|
}
|
|
for (var x = start; x < end; x++) {
|
|
var pageNumber = x + 1;
|
|
$('<li/>').
|
|
append($('<a/>').
|
|
addClass('m-datatable__pager-link m-datatable__pager-link-number').
|
|
text(pageNumber).
|
|
attr('data-page', pageNumber).
|
|
attr('title', pageNumber).
|
|
on('click', pg.gotoPage)).
|
|
appendTo(pagerNumber);
|
|
}
|
|
|
|
// more next pages
|
|
$('<li/>').
|
|
append($('<a/>').
|
|
attr('title', title.more).
|
|
addClass('m-datatable__pager-link m-datatable__pager-link--more-next').
|
|
html($('<i/>').addClass(icons.more)).
|
|
on('click', pg.gotoMorePage)).
|
|
appendTo(pagerNumber);
|
|
|
|
// pager next/last button
|
|
$('<li/>').
|
|
append($('<a/>').
|
|
attr('title', title.next).
|
|
addClass('m-datatable__pager-link m-datatable__pager-link--next').
|
|
append($('<i/>').addClass(icons.next)).
|
|
on('click', pg.gotoMorePage)).
|
|
appendTo(pagerNumber);
|
|
$('<li/>').
|
|
append($('<a/>').
|
|
attr('title', title.last).
|
|
addClass('m-datatable__pager-link m-datatable__pager-link--last').
|
|
append($('<i/>').addClass(icons.last)).
|
|
on('click', pg.gotoMorePage).
|
|
attr('data-page', pg.meta.pages)).
|
|
appendTo(pagerNumber);
|
|
|
|
// page info
|
|
if (Plugin.getOption('toolbar.items.info')) {
|
|
pg.pagerLayout['info'] = $('<div/>').
|
|
addClass('m-datatable__pager-info').
|
|
append($('<span/>').addClass('m-datatable__pager-detail'));
|
|
}
|
|
|
|
$.each(Plugin.getOption('toolbar.layout'), function(i, layout) {
|
|
$(pg.pagerLayout[layout]).appendTo(pg.pager);
|
|
});
|
|
|
|
// page size select
|
|
var pageSizeSelect = $('<select/>').
|
|
addClass('selectpicker m-datatable__pager-size').
|
|
attr('title', Plugin.getOption('translate.toolbar.pagination.items.default.select')).
|
|
attr('data-width', '70px').
|
|
val(pg.meta.perpage).
|
|
on('change', pg.updatePerpage).
|
|
prependTo(pg.pagerLayout['info']);
|
|
|
|
var pageSizes = Plugin.getOption('toolbar.items.pagination.pageSizeSelect');
|
|
// default value here, to fix override option by user
|
|
if (pageSizes.length == 0) pageSizes = [10, 20, 30, 50, 100];
|
|
$.each(pageSizes, function(i, size) {
|
|
var display = size;
|
|
if (size === -1) display = 'All';
|
|
$('<option/>').
|
|
attr('value', size).
|
|
html(display).
|
|
appendTo(pageSizeSelect);
|
|
});
|
|
|
|
// init selectpicker to dropdown
|
|
$(datatable).ready(function() {
|
|
$('.selectpicker').
|
|
selectpicker().
|
|
siblings('.dropdown-toggle').
|
|
attr('title', Plugin.getOption(
|
|
'translate.toolbar.pagination.items.default.select'));
|
|
});
|
|
|
|
pg.paste();
|
|
},
|
|
paste: function() {
|
|
// insert pagination based on placement position, top|bottom
|
|
$.each($.unique(Plugin.getOption('toolbar.placement')),
|
|
function(i, position) {
|
|
if (position === 'bottom') {
|
|
$(pg.pager).clone(true).insertAfter(datatable.table);
|
|
}
|
|
if (position === 'top') {
|
|
// pager top need some extra space
|
|
$(pg.pager).
|
|
clone(true).
|
|
addClass('m-datatable__pager--top').
|
|
insertBefore(datatable.table);
|
|
}
|
|
});
|
|
},
|
|
gotoMorePage: function(e) {
|
|
e.preventDefault();
|
|
// $(this) is a link of .m-datatable__pager-link
|
|
|
|
if ($(this).attr('disabled') === 'disabled') return false;
|
|
|
|
var page = $(this).attr('data-page');
|
|
|
|
// event from text input
|
|
if (typeof page === 'undefined') {
|
|
page = $(e.target).attr('data-page');
|
|
}
|
|
|
|
pg.openPage(parseInt(page));
|
|
return false;
|
|
},
|
|
gotoPage: function(e) {
|
|
e.preventDefault();
|
|
// prevent from click same page number
|
|
if ($(this).hasClass('m-datatable__pager-link--active')) return;
|
|
|
|
pg.openPage(parseInt($(this).data('page')));
|
|
},
|
|
openPage: function(page) {
|
|
// currentPage is 1-based index
|
|
pg.meta.page = parseInt(page);
|
|
|
|
$(datatable).trigger(pg.paginateEvent, pg.meta);
|
|
pg.callback(pg, pg.meta);
|
|
|
|
// update page callback function
|
|
$(pg.pager).trigger('m-datatable--on-goto-page', pg.meta);
|
|
},
|
|
updatePerpage: function(e) {
|
|
e.preventDefault();
|
|
if (Plugin.getOption('layout.height') === null) {
|
|
// fix white space, when perpage is set from many records to less records
|
|
$('html, body').animate({scrollTop: $(datatable).position().top});
|
|
}
|
|
|
|
pg.pager = $(datatable.table).
|
|
siblings('.m-datatable__pager').
|
|
removeClass('m-datatable--paging-loaded');
|
|
|
|
// on change select page size
|
|
if (e.originalEvent) {
|
|
pg.meta.perpage = parseInt($(this).val());
|
|
}
|
|
|
|
$(pg.pager).
|
|
find('select.m-datatable__pager-size').
|
|
val(pg.meta.perpage).
|
|
attr('data-selected', pg.meta.perpage);
|
|
|
|
// update datasource params
|
|
Plugin.setDataSourceParam('pagination', {
|
|
page: pg.meta.page,
|
|
pages: pg.meta.pages,
|
|
perpage: pg.meta.perpage,
|
|
total: pg.meta.total,
|
|
});
|
|
|
|
// update page callback function
|
|
$(pg.pager).trigger('m-datatable--on-update-perpage', pg.meta);
|
|
$(datatable).trigger(pg.paginateEvent, pg.meta);
|
|
pg.callback(pg, pg.meta);
|
|
|
|
// update pagination info
|
|
pg.updateInfo.call();
|
|
},
|
|
addPaginateEvent: function(e) {
|
|
// pagination event
|
|
$(datatable).
|
|
off(pg.paginateEvent).
|
|
on(pg.paginateEvent, function(e, meta) {
|
|
Plugin.spinnerCallback(true);
|
|
|
|
pg.pager = $(datatable.table).siblings('.m-datatable__pager');
|
|
var pagerNumber = $(pg.pager).find('.m-datatable__pager-nav');
|
|
|
|
// set sync active page class
|
|
$(pagerNumber).
|
|
find('.m-datatable__pager-link--active').
|
|
removeClass('m-datatable__pager-link--active');
|
|
$(pagerNumber).
|
|
find('.m-datatable__pager-link-number[data-page="' + meta.page + '"]').
|
|
addClass('m-datatable__pager-link--active');
|
|
|
|
// set next and previous link page number
|
|
$(pagerNumber).
|
|
find('.m-datatable__pager-link--prev').
|
|
attr('data-page', Math.max(meta.page - 1, 1));
|
|
$(pagerNumber).
|
|
find('.m-datatable__pager-link--next').
|
|
attr('data-page', Math.min(meta.page + 1, meta.pages));
|
|
|
|
// current page input value sync
|
|
$(pg.pager).each(function() {
|
|
$(this).
|
|
find('.m-pager-input[type="text"]').
|
|
prop('value', meta.page);
|
|
});
|
|
|
|
$(pg.pager).find('.m-datatable__pager-nav').show();
|
|
if (meta.pages <= 1) {
|
|
// hide pager if has 1 page
|
|
$(pg.pager).find('.m-datatable__pager-nav').hide();
|
|
}
|
|
|
|
// update datasource params
|
|
Plugin.setDataSourceParam('pagination', {
|
|
page: pg.meta.page,
|
|
pages: pg.meta.pages,
|
|
perpage: pg.meta.perpage,
|
|
total: pg.meta.total,
|
|
});
|
|
|
|
$(pg.pager).
|
|
find('select.m-datatable__pager-size').
|
|
val(meta.perpage).
|
|
attr('data-selected', meta.perpage);
|
|
|
|
// clear active rows
|
|
$(datatable.table).
|
|
find('.m-checkbox > [type="checkbox"]').
|
|
prop('checked', false);
|
|
$(datatable.table).
|
|
find('.m-datatable__row--active').
|
|
removeClass('m-datatable__row--active');
|
|
|
|
pg.updateInfo.call();
|
|
pg.pagingBreakpoint.call();
|
|
// Plugin.resetScroll();
|
|
});
|
|
},
|
|
updateInfo: function() {
|
|
var start = Math.max(pg.meta.perpage * (pg.meta.page - 1) + 1, 1);
|
|
var end = Math.min(start + pg.meta.perpage - 1, pg.meta.total);
|
|
// page info update
|
|
$(pg.pager).
|
|
find('.m-datatable__pager-info').
|
|
find('.m-datatable__pager-detail').
|
|
html(Plugin.dataPlaceholder(
|
|
Plugin.getOption('translate.toolbar.pagination.items.info'), {
|
|
start: start,
|
|
end: pg.meta.perpage === -1 ? pg.meta.total : end,
|
|
pageSize: pg.meta.perpage === -1 ||
|
|
pg.meta.perpage >= pg.meta.total
|
|
? pg.meta.total
|
|
: pg.meta.perpage,
|
|
total: pg.meta.total,
|
|
}));
|
|
},
|
|
|
|
/**
|
|
* Update pagination layout breakpoint
|
|
*/
|
|
pagingBreakpoint: function() {
|
|
// keep page links reference
|
|
var pagerNumber = $(datatable.table).
|
|
siblings('.m-datatable__pager').
|
|
find('.m-datatable__pager-nav');
|
|
if ($(pagerNumber).length === 0) return;
|
|
|
|
var currentPage = Plugin.getCurrentPage();
|
|
var pagerInput = $(pagerNumber).
|
|
find('.m-pager-input').
|
|
closest('li');
|
|
|
|
// reset
|
|
$(pagerNumber).find('li').show();
|
|
|
|
// pagination update
|
|
$.each(Plugin.getOption('toolbar.items.pagination.pages'),
|
|
function(mode, option) {
|
|
if (mUtil.isInResponsiveRange(mode)) {
|
|
switch (mode) {
|
|
case 'desktop':
|
|
case 'tablet':
|
|
var end = Math.ceil(currentPage / option.pagesNumber) *
|
|
option.pagesNumber;
|
|
var start = end - option.pagesNumber;
|
|
$(pagerInput).hide();
|
|
pg.meta = Plugin.getDataSourceParam('pagination');
|
|
pg.paginationUpdate();
|
|
break;
|
|
|
|
case 'mobile':
|
|
$(pagerInput).show();
|
|
$(pagerNumber).
|
|
find('.m-datatable__pager-link--more-prev').
|
|
closest('li').
|
|
hide();
|
|
$(pagerNumber).
|
|
find('.m-datatable__pager-link--more-next').
|
|
closest('li').
|
|
hide();
|
|
$(pagerNumber).
|
|
find('.m-datatable__pager-link-number').
|
|
closest('li').
|
|
hide();
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Update pagination number and button display
|
|
*/
|
|
paginationUpdate: function() {
|
|
var pager = $(datatable.table).
|
|
siblings('.m-datatable__pager').
|
|
find('.m-datatable__pager-nav'),
|
|
pagerMorePrev = $(pager).
|
|
find('.m-datatable__pager-link--more-prev'),
|
|
pagerMoreNext = $(pager).
|
|
find('.m-datatable__pager-link--more-next'),
|
|
pagerFirst = $(pager).find('.m-datatable__pager-link--first'),
|
|
pagerPrev = $(pager).find('.m-datatable__pager-link--prev'),
|
|
pagerNext = $(pager).find('.m-datatable__pager-link--next'),
|
|
pagerLast = $(pager).find('.m-datatable__pager-link--last');
|
|
|
|
// get visible page
|
|
var pagerNumber = $(pager).find('.m-datatable__pager-link-number');
|
|
// get page before of first visible
|
|
var morePrevPage = Math.max($(pagerNumber).first().data('page') - 1,
|
|
1);
|
|
$(pagerMorePrev).each(function(i, prev) {
|
|
$(prev).attr('data-page', morePrevPage);
|
|
});
|
|
// show/hide <li>
|
|
if (morePrevPage === 1) {
|
|
$(pagerMorePrev).parent().hide();
|
|
} else {
|
|
$(pagerMorePrev).parent().show();
|
|
}
|
|
|
|
// get page after of last visible
|
|
var moreNextPage = Math.min($(pagerNumber).last().data('page') + 1,
|
|
pg.meta.pages);
|
|
$(pagerMoreNext).each(function(i, prev) {
|
|
$(pagerMoreNext).attr('data-page', moreNextPage).show();
|
|
});
|
|
|
|
// show/hide <li>
|
|
if (moreNextPage === pg.meta.pages
|
|
// missing dot fix when last hidden page is one left
|
|
&& moreNextPage === $(pagerNumber).last().data('page')) {
|
|
$(pagerMoreNext).parent().hide();
|
|
} else {
|
|
$(pagerMoreNext).parent().show();
|
|
}
|
|
|
|
// begin/end of pages
|
|
if (pg.meta.page === 1) {
|
|
$(pagerFirst).
|
|
attr('disabled', true).
|
|
addClass('m-datatable__pager-link--disabled');
|
|
$(pagerPrev).
|
|
attr('disabled', true).
|
|
addClass('m-datatable__pager-link--disabled');
|
|
} else {
|
|
$(pagerFirst).
|
|
removeAttr('disabled').
|
|
removeClass('m-datatable__pager-link--disabled');
|
|
$(pagerPrev).
|
|
removeAttr('disabled').
|
|
removeClass('m-datatable__pager-link--disabled');
|
|
}
|
|
if (pg.meta.page === pg.meta.pages) {
|
|
$(pagerNext).
|
|
attr('disabled', true).
|
|
addClass('m-datatable__pager-link--disabled');
|
|
$(pagerLast).
|
|
attr('disabled', true).
|
|
addClass('m-datatable__pager-link--disabled');
|
|
} else {
|
|
$(pagerNext).
|
|
removeAttr('disabled').
|
|
removeClass('m-datatable__pager-link--disabled');
|
|
$(pagerLast).
|
|
removeAttr('disabled').
|
|
removeClass('m-datatable__pager-link--disabled');
|
|
}
|
|
|
|
// display more buttons
|
|
var nav = Plugin.getOption('toolbar.items.pagination.navigation');
|
|
if (!nav.first) $(pagerFirst).remove();
|
|
if (!nav.prev) $(pagerPrev).remove();
|
|
if (!nav.next) $(pagerNext).remove();
|
|
if (!nav.last) $(pagerLast).remove();
|
|
},
|
|
};
|
|
pg.init(meta);
|
|
return pg;
|
|
},
|
|
|
|
/**
|
|
* Hide/show table cell defined by options[columns][i][responsive][visible/hidden]
|
|
*/
|
|
columnHide: function() {
|
|
var screen = mUtil.getViewPort().width;
|
|
// foreach columns setting
|
|
$.each(options.columns, function(i, column) {
|
|
if (typeof column.responsive !== 'undefined') {
|
|
var field = column.field;
|
|
var tds = $.grep($(datatable.table).find('.m-datatable__cell'), function(n, i) {
|
|
return field === $(n).data('field');
|
|
});
|
|
if (mUtil.getBreakpoint(column.responsive.hidden) >= screen) {
|
|
$(tds).hide();
|
|
} else {
|
|
$(tds).show();
|
|
}
|
|
if (mUtil.getBreakpoint(column.responsive.visible) <= screen) {
|
|
$(tds).show();
|
|
} else {
|
|
$(tds).hide();
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Setup sub datatable
|
|
*/
|
|
setupSubDatatable: function() {
|
|
var subTableCallback = Plugin.getOption('detail.content');
|
|
if (typeof subTableCallback !== 'function') return;
|
|
|
|
// subtable already exist
|
|
if ($(datatable.table).find('.m-datatable__subtable').length > 0) return;
|
|
|
|
$(datatable.wrap).addClass('m-datatable--subtable');
|
|
|
|
options.columns[0]['subtable'] = true;
|
|
|
|
// toggle on open sub table
|
|
var toggleSubTable = function(e) {
|
|
e.preventDefault();
|
|
// get parent row of this subtable
|
|
var parentRow = $(this).closest('.m-datatable__row');
|
|
|
|
// get subtable row for sub table
|
|
var subTableRow = $(parentRow).next('.m-datatable__row-subtable');
|
|
if ($(subTableRow).length === 0) {
|
|
// prepare DOM for sub table, each <tr> as parent and add <tr> as child table
|
|
subTableRow = $('<tr/>').
|
|
addClass('m-datatable__row-subtable m-datatable__row-loading').
|
|
hide().
|
|
append($('<td/>').
|
|
addClass('m-datatable__subtable').
|
|
attr('colspan', Plugin.getTotalColumns()));
|
|
$(parentRow).after(subTableRow);
|
|
// add class to even row
|
|
if ($(parentRow).hasClass('m-datatable__row--even')) {
|
|
$(subTableRow).addClass('m-datatable__row-subtable--even');
|
|
}
|
|
}
|
|
|
|
$(subTableRow).toggle();
|
|
|
|
var subTable = $(subTableRow).find('.m-datatable__subtable');
|
|
|
|
// get id from first column of parent row
|
|
var primaryKey = $(this).
|
|
closest('[data-field]:first-child').
|
|
find('.m-datatable__toggle-subtable').
|
|
data('value');
|
|
|
|
var icon = $(this).find('i').removeAttr('class');
|
|
|
|
// prevent duplicate datatable init
|
|
if ($(parentRow).hasClass('m-datatable__row--subtable-expanded')) {
|
|
$(icon).addClass(Plugin.getOption('layout.icons.rowDetail.collapse'));
|
|
// remove expand class from parent row
|
|
$(parentRow).removeClass('m-datatable__row--subtable-expanded');
|
|
// trigger event on collapse
|
|
$(datatable).trigger('m-datatable--on-collapse-subtable', [parentRow]);
|
|
} else {
|
|
// expand and run callback function
|
|
$(icon).addClass(Plugin.getOption('layout.icons.rowDetail.expand'));
|
|
// add expand class to parent row
|
|
$(parentRow).addClass('m-datatable__row--subtable-expanded');
|
|
// trigger event on expand
|
|
$(datatable).trigger('m-datatable--on-expand-subtable', [parentRow]);
|
|
}
|
|
|
|
// prevent duplicate datatable init
|
|
if ($(subTable).find('.m-datatable').length === 0) {
|
|
// get data by primary id
|
|
$.map(datatable.dataSet, function(n, i) {
|
|
if (primaryKey === n[options.columns[0].field]) {
|
|
e.data = n;
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
// deprecated in v5.0.6
|
|
e.detailCell = subTable;
|
|
|
|
e.parentRow = parentRow;
|
|
e.subTable = subTable;
|
|
|
|
// run callback with event
|
|
subTableCallback(e);
|
|
|
|
$(subTable).children('.m-datatable').on('m-datatable--on-init', function(e) {
|
|
$(subTableRow).removeClass('m-datatable__row-loading');
|
|
});
|
|
if (Plugin.getOption('data.type') === 'local') {
|
|
$(subTableRow).removeClass('m-datatable__row-loading');
|
|
}
|
|
}
|
|
};
|
|
|
|
var columns = options.columns;
|
|
$(datatable.tableBody).
|
|
find('.m-datatable__row').
|
|
each(function(tri, tr) {
|
|
$(tr).find('.m-datatable__cell').each(function(tdi, td) {
|
|
// get column settings by field
|
|
var column = $.grep(columns, function(n, i) {
|
|
return $(td).data('field') === n.field;
|
|
})[0];
|
|
if (typeof column !== 'undefined') {
|
|
var value = $(td).text();
|
|
// enable column subtable toggle
|
|
if (typeof column.subtable !== 'undefined' && column.subtable) {
|
|
// check if subtable toggle exist
|
|
if ($(td).find('.m-datatable__toggle-subtable').length > 0) return;
|
|
// append subtable toggle
|
|
$(td).html($('<a/>').
|
|
addClass('m-datatable__toggle-subtable').
|
|
attr('href', '#').
|
|
attr('data-value', value).
|
|
attr('title', Plugin.getOption('detail.title')).
|
|
on('click', toggleSubTable).
|
|
append($('<i/>').
|
|
css('width', $(td).data('width')).
|
|
addClass(Plugin.getOption('layout.icons.rowDetail.collapse'))));
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// $(datatable.tableHead).find('.m-datatable__row').first()
|
|
},
|
|
|
|
/**
|
|
* Datasource mapping callback
|
|
*/
|
|
dataMapCallback: function(raw) {
|
|
// static dataset array
|
|
var dataSet = raw;
|
|
// dataset mapping callback
|
|
if (typeof Plugin.getOption('data.source.read.map') === 'function') {
|
|
return Plugin.getOption('data.source.read.map')(raw);
|
|
} else {
|
|
// default data mapping fallback
|
|
if (typeof raw.data !== 'undefined') {
|
|
dataSet = raw.data;
|
|
}
|
|
}
|
|
return dataSet;
|
|
},
|
|
|
|
isSpinning: false,
|
|
/**
|
|
* BlockUI spinner callback
|
|
* @param block
|
|
*/
|
|
spinnerCallback: function(block) {
|
|
if (block) {
|
|
if (!Plugin.isSpinning) {
|
|
// get spinner options
|
|
var spinnerOptions = Plugin.getOption('layout.spinner');
|
|
if (spinnerOptions.message === true) {
|
|
// use default spinner message from translation
|
|
spinnerOptions.message = Plugin.getOption('translate.records.processing');
|
|
}
|
|
Plugin.isSpinning = true;
|
|
if (typeof mApp !== 'undefined') {
|
|
mApp.block(datatable, spinnerOptions);
|
|
}
|
|
}
|
|
} else {
|
|
Plugin.isSpinning = false;
|
|
if (typeof mApp !== 'undefined') {
|
|
mApp.unblock(datatable);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Default sort callback function
|
|
* @param data
|
|
* @param sort
|
|
* @param column
|
|
* @returns {*|Array.<T>|{sort, field}|{asc, desc}}
|
|
*/
|
|
sortCallback: function(data, sort, column) {
|
|
var type = column['type'] || 'string';
|
|
var format = column['format'] || '';
|
|
var field = column['field'];
|
|
|
|
if (type === 'date' && typeof moment === 'undefined') {
|
|
throw new Error('Moment.js is required.');
|
|
}
|
|
|
|
return $(data).sort(function(a, b) {
|
|
var aField = a[field];
|
|
var bField = b[field];
|
|
|
|
switch (type) {
|
|
case 'date':
|
|
var diff = moment(aField, format).diff(moment(bField, format));
|
|
if (sort === 'asc') {
|
|
return diff > 0 ? 1 : diff < 0 ? -1 : 0;
|
|
} else {
|
|
return diff < 0 ? 1 : diff > 0 ? -1 : 0;
|
|
}
|
|
break;
|
|
|
|
case 'number':
|
|
if (isNaN(parseFloat(aField)) && aField != null) {
|
|
aField = Number(aField.replace(/[^0-9\.-]+/g, ''));
|
|
}
|
|
if (isNaN(parseFloat(bField)) && bField != null) {
|
|
bField = Number(bField.replace(/[^0-9\.-]+/g, ''));
|
|
}
|
|
aField = parseFloat(aField);
|
|
bField = parseFloat(bField);
|
|
if (sort === 'asc') {
|
|
return aField > bField ? 1 : aField < bField ? -1 : 0;
|
|
} else {
|
|
return aField < bField ? 1 : aField > bField ? -1 : 0;
|
|
}
|
|
break;
|
|
|
|
case 'string':
|
|
default:
|
|
if (sort === 'asc') {
|
|
return aField > bField ? 1 : aField < bField ? -1 : 0;
|
|
} else {
|
|
return aField < bField ? 1 : aField > bField ? -1 : 0;
|
|
}
|
|
break;
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Custom debug log
|
|
* @param text
|
|
* @param obj
|
|
*/
|
|
log: function(text, obj) {
|
|
if (typeof obj === 'undefined') obj = '';
|
|
if (datatable.debug) {
|
|
console.log(text, obj);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Auto hide columnds overflow in row
|
|
*/
|
|
autoHide: function() {
|
|
$(datatable.table).find('.m-datatable__cell').show();
|
|
$(datatable.tableBody).each(function() {
|
|
while ($(this)[0].offsetWidth < $(this)[0].scrollWidth) {
|
|
$(this).find('.m-datatable__row').each(function(i) {
|
|
var cell = $(this).find('.m-datatable__cell').not(':hidden').last();
|
|
$(cell).hide();
|
|
if (i === 0) {
|
|
$(datatable.tableHead).find('.m-datatable__cell').eq($(cell).index()).hide();
|
|
$(datatable.tableFoot).find('.m-datatable__cell').eq($(cell).index()).hide();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
var toggleHiddenColumns = function(e) {
|
|
e.preventDefault();
|
|
|
|
var row = $(this).closest('.m-datatable__row');
|
|
var detailRow = $(row).next();
|
|
|
|
if (!$(detailRow).hasClass('m-datatable__row-detail')) {
|
|
$(this).find('i').
|
|
removeClass(Plugin.getOption('layout.icons.rowDetail.collapse')).
|
|
addClass(Plugin.getOption('layout.icons.rowDetail.expand'));
|
|
|
|
var hidden = $(row).find('.m-datatable__cell:hidden').clone().show();
|
|
|
|
detailRow = $('<tr/>').addClass('m-datatable__row-detail').insertAfter(row);
|
|
var detailRowTd = $('<td/>').
|
|
addClass('m-datatable__detail').
|
|
attr('colspan', Plugin.getTotalColumns()).appendTo(detailRow);
|
|
|
|
var detailSubTable = $('<table/>');
|
|
$(hidden).each(function() {
|
|
$(detailSubTable).
|
|
append($('<tr class="m-datatable__row"></tr>').
|
|
append($('<td class="m-datatable__cell"></td>').
|
|
append($('<span/>').
|
|
css('width', Plugin.offset).
|
|
append($(this).data('field')))).
|
|
append(this));
|
|
});
|
|
$(detailRowTd).append(detailSubTable);
|
|
|
|
} else {
|
|
$(this).find('i').
|
|
removeClass(Plugin.getOption('layout.icons.rowDetail.expand')).
|
|
addClass(Plugin.getOption('layout.icons.rowDetail.collapse'));
|
|
$(detailRow).remove();
|
|
}
|
|
};
|
|
|
|
// toggle show hidden columns
|
|
$(datatable.tableBody).find('.m-datatable__row').each(function() {
|
|
$(this).prepend($('<td/>').addClass('m-datatable__cell m-datatable__toggle--detail').
|
|
append($('<a/>').
|
|
addClass('m-datatable__toggle-detail').
|
|
attr('href', '#').
|
|
on('click', toggleHiddenColumns).
|
|
append($('<i/>').
|
|
css('width', '21px').// maintain width for both icons expand and collapse
|
|
addClass(Plugin.getOption('layout.icons.rowDetail.collapse')))));
|
|
|
|
// check if subtable toggle exist
|
|
if ($(datatable.tableHead).find('.m-datatable__toggle-detail').length === 0) {
|
|
$(datatable.tableHead).
|
|
find('.m-datatable__row').
|
|
first().
|
|
prepend('<th class="m-datatable__cell m-datatable__toggle-detail"><span style="width: 21px"></span></th>');
|
|
$(datatable.tableFoot).
|
|
find('.m-datatable__row').
|
|
first().
|
|
prepend('<th class="m-datatable__cell m-datatable__toggle-detail"><span style="width: 21px"></span></th>');
|
|
} else {
|
|
$(datatable.tableHead).find('.m-datatable__toggle-detail').find('span').css('width', '21px');
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* todo; implement hover column
|
|
*/
|
|
hoverColumn: function() {
|
|
$(datatable.tableBody).on('mouseenter', '.m-datatable__cell', function() {
|
|
var colIdx = $(Plugin.cell(this).nodes()).index();
|
|
$(Plugin.cells().nodes()).removeClass('m-datatable__cell--hover');
|
|
$(Plugin.column(colIdx).nodes()).addClass('m-datatable__cell--hover');
|
|
});
|
|
},
|
|
|
|
/********************
|
|
** HELPERS
|
|
********************/
|
|
|
|
/**
|
|
* Check if table is a locked colums table
|
|
*/
|
|
isLocked: function() {
|
|
return $(datatable.wrap).hasClass('m-datatable--lock') || false;
|
|
},
|
|
|
|
/**
|
|
* Insert html into table content, take count mCustomScrollbar DOM to prevent replace
|
|
* @param html
|
|
* @param tablePart
|
|
*/
|
|
replaceTableContent: function(html, tablePart) {
|
|
if (typeof tablePart === 'undefined') tablePart = datatable.tableBody;
|
|
if ($(tablePart).hasClass('mCustomScrollbar')) {
|
|
$(tablePart).find('.mCSB_container').html(html);
|
|
} else {
|
|
$(tablePart).html(html);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Get total extra space of an element for width calculation, including padding, margin, border
|
|
* @param element
|
|
* @returns {number}
|
|
*/
|
|
getExtraSpace: function(element) {
|
|
var padding = parseInt($(element).css('paddingRight')) +
|
|
parseInt($(element).css('paddingLeft'));
|
|
var margin = parseInt($(element).css('marginRight')) +
|
|
parseInt($(element).css('marginLeft'));
|
|
var border = Math.ceil(
|
|
$(element).css('border-right-width').replace('px', ''));
|
|
return padding + margin + border;
|
|
},
|
|
|
|
/**
|
|
* Insert data of array into {{ }} template placeholder
|
|
* @param template
|
|
* @param data
|
|
* @returns {*}
|
|
*/
|
|
dataPlaceholder: function(template, data) {
|
|
var result = template;
|
|
$.each(data, function(key, val) {
|
|
result = result.replace('{{' + key + '}}', val);
|
|
});
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Get table unique ID
|
|
* Note: table unique change each time refreshed
|
|
* @param suffix
|
|
* @returns {*}
|
|
*/
|
|
getTableId: function(suffix) {
|
|
if (typeof suffix === 'undefined') suffix = '';
|
|
var id = $(datatable).attr('id');
|
|
if (typeof id === 'undefined') {
|
|
id = $(datatable).attr('class').split(' ')[0];
|
|
}
|
|
return id + suffix;
|
|
},
|
|
|
|
/**
|
|
* Get table prefix with depth number
|
|
*/
|
|
getTablePrefix: function(suffix) {
|
|
if (typeof suffix !== 'undefined') suffix = '-' + suffix;
|
|
return Plugin.getTableId() + '-' + Plugin.getDepth() + suffix;
|
|
},
|
|
|
|
/**
|
|
* Get current table depth of sub table
|
|
* @returns {number}
|
|
*/
|
|
getDepth: function() {
|
|
var depth = 0;
|
|
var table = datatable.table;
|
|
do {
|
|
table = $(table).parents('.m-datatable__table');
|
|
depth++;
|
|
} while ($(table).length > 0);
|
|
return depth;
|
|
},
|
|
|
|
/**
|
|
* Keep state item
|
|
* @param key
|
|
* @param value
|
|
*/
|
|
stateKeep: function(key, value) {
|
|
key = Plugin.getTablePrefix(key);
|
|
if (Plugin.getOption('data.saveState') === false) return;
|
|
if (Plugin.getOption('data.saveState.webstorage') && localStorage) {
|
|
localStorage.setItem(key, JSON.stringify(value));
|
|
}
|
|
if (Plugin.getOption('data.saveState.cookie')) {
|
|
Cookies.set(key, JSON.stringify(value));
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Get state item
|
|
* @param key
|
|
* @param defValue
|
|
*/
|
|
stateGet: function(key, defValue) {
|
|
key = Plugin.getTablePrefix(key);
|
|
if (Plugin.getOption('data.saveState') === false) return;
|
|
var value = null;
|
|
if (Plugin.getOption('data.saveState.webstorage') && localStorage) {
|
|
value = localStorage.getItem(key);
|
|
} else {
|
|
value = Cookies.get(key);
|
|
}
|
|
if (typeof value !== 'undefined' && value !== null) {
|
|
return JSON.parse(value);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Update data in state without clear existing
|
|
* @param key
|
|
* @param value
|
|
*/
|
|
stateUpdate: function(key, value) {
|
|
var ori = Plugin.stateGet(key);
|
|
if (typeof ori === 'undefined' || ori === null) ori = {};
|
|
Plugin.stateKeep(key, $.extend({}, ori, value));
|
|
},
|
|
|
|
/**
|
|
* Remove state item
|
|
* @param key
|
|
*/
|
|
stateRemove: function(key) {
|
|
key = Plugin.getTablePrefix(key);
|
|
if (localStorage) {
|
|
localStorage.removeItem(key);
|
|
}
|
|
Cookies.remove(key);
|
|
},
|
|
|
|
/**
|
|
* Get total columns.
|
|
*/
|
|
getTotalColumns: function(tablePart) {
|
|
if (typeof tablePart === 'undefined') tablePart = datatable.tableBody;
|
|
return $(tablePart).
|
|
find('.m-datatable__row').
|
|
first().
|
|
find('.m-datatable__cell').length;
|
|
},
|
|
|
|
/**
|
|
* Get table row. Useful to get row when current table is in lock mode.
|
|
* Can be used for both lock and normal table mode.
|
|
* By default, returning result will be in a list of <td>.
|
|
* @param tablePart
|
|
* @param row 1-based index
|
|
* @param tdOnly Optional. Default true
|
|
* @returns {*}
|
|
*/
|
|
getOneRow: function(tablePart, row, tdOnly) {
|
|
if (typeof tdOnly === 'undefined') tdOnly = true;
|
|
// get list of <tr>
|
|
var result = $(tablePart).find('.m-datatable__row:not(.m-datatable__row-detail):nth-child(' + row + ')');
|
|
if (tdOnly) {
|
|
// get list of <td> or <th>
|
|
result = result.find('.m-datatable__cell');
|
|
}
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Check if element has vertical overflow
|
|
* @param element
|
|
* @returns {boolean}
|
|
*/
|
|
hasOverflowY: function(element) {
|
|
var children = $(element).find('.m-datatable__row');
|
|
var maxHeight = 0;
|
|
|
|
if (children.length > 0) {
|
|
$(children).each(function(tdi, td) {
|
|
maxHeight += Math.floor($(td).innerHeight());
|
|
});
|
|
|
|
return maxHeight > $(element).innerHeight();
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* Sort table row at HTML level by column index.
|
|
* todo; Not in use.
|
|
* @param header Header sort clicked
|
|
* @param sort asc|desc. Optional. Default asc
|
|
* @param int Boolean. Optional. Comparison value parse to integer. Default false
|
|
*/
|
|
sortColumn: function(header, sort, int) {
|
|
if (typeof sort === 'undefined') sort = 'asc'; // desc
|
|
if (typeof int === 'undefined') int = false;
|
|
|
|
var column = $(header).index();
|
|
var rows = $(datatable.tableBody).find('.m-datatable__row');
|
|
var hIndex = $(header).closest('.m-datatable__lock').index();
|
|
if (hIndex !== -1) {
|
|
rows = $(datatable.tableBody).
|
|
find('.m-datatable__lock:nth-child(' + (hIndex + 1) + ')').
|
|
find('.m-datatable__row');
|
|
}
|
|
|
|
var container = $(rows).parent();
|
|
$(rows).sort(function(a, b) {
|
|
var tda = $(a).find('td:nth-child(' + column + ')').text();
|
|
var tdb = $(b).find('td:nth-child(' + column + ')').text();
|
|
|
|
if (int) {
|
|
// useful for integer type sorting
|
|
tda = parseInt(tda);
|
|
tdb = parseInt(tdb);
|
|
}
|
|
|
|
if (sort === 'asc') {
|
|
return tda > tdb ? 1 : tda < tdb ? -1 : 0;
|
|
} else {
|
|
return tda < tdb ? 1 : tda > tdb ? -1 : 0;
|
|
}
|
|
}).appendTo(container);
|
|
},
|
|
|
|
/**
|
|
* Perform sort remote and local
|
|
*/
|
|
sorting: function() {
|
|
var sortObj = {
|
|
init: function() {
|
|
if (options.sortable) {
|
|
$(datatable.tableHead).
|
|
find('.m-datatable__cell:not(.m-datatable__cell--check)').
|
|
addClass('m-datatable__cell--sort').
|
|
off('click').
|
|
on('click', sortObj.sortClick);
|
|
// first init
|
|
sortObj.setIcon();
|
|
}
|
|
},
|
|
setIcon: function() {
|
|
var meta = Plugin.getDataSourceParam('sort');
|
|
// sort icon beside column header
|
|
var td = $(datatable.tableHead).
|
|
find('.m-datatable__cell[data-field="' + meta.field + '"]').
|
|
attr('data-sort', meta.sort);
|
|
var sorting = $(td).find('span');
|
|
var icon = $(sorting).find('i');
|
|
|
|
var icons = Plugin.getOption('layout.icons.sort');
|
|
// update sort icon; desc & asc
|
|
if ($(icon).length > 0) {
|
|
$(icon).removeAttr('class').addClass(icons[meta.sort]);
|
|
} else {
|
|
$(sorting).append($('<i/>').addClass(icons[meta.sort]));
|
|
}
|
|
},
|
|
sortClick: function(e) {
|
|
var meta = Plugin.getDataSourceParam('sort');
|
|
var field = $(this).data('field');
|
|
var column = Plugin.getColumnByField(field);
|
|
// sort is disabled for this column
|
|
if (typeof column.sortable !== 'undefined' &&
|
|
column.sortable === false) return;
|
|
|
|
$(datatable.tableHead).
|
|
find('.m-datatable__cell > span > i').
|
|
remove();
|
|
|
|
if (options.sortable) {
|
|
Plugin.spinnerCallback(true);
|
|
|
|
var sort = 'desc';
|
|
if (meta.field === field) {
|
|
sort = meta.sort;
|
|
}
|
|
|
|
// toggle sort
|
|
sort = typeof sort === 'undefined' || sort === 'desc'
|
|
? 'asc'
|
|
: 'desc';
|
|
|
|
// update field and sort params
|
|
meta = {field: field, sort: sort};
|
|
Plugin.setDataSourceParam('sort', meta);
|
|
|
|
sortObj.setIcon();
|
|
|
|
setTimeout(function() {
|
|
Plugin.dataRender('sort');
|
|
$(datatable).trigger('m-datatable--on-sort', meta);
|
|
}, 300);
|
|
}
|
|
},
|
|
};
|
|
sortObj.init();
|
|
},
|
|
|
|
/**
|
|
* Update JSON data list linked with sort, filter and pagination.
|
|
* Call this method, before using dataSet variable.
|
|
* @returns {*|null}
|
|
*/
|
|
localDataUpdate: function() {
|
|
var params = Plugin.getDataSourceParam();
|
|
if (typeof datatable.originalDataSet === 'undefined') {
|
|
datatable.originalDataSet = datatable.dataSet;
|
|
}
|
|
|
|
var field = params.sort.field;
|
|
var sort = params.sort.sort;
|
|
var column = Plugin.getColumnByField(field);
|
|
if (typeof column !== 'undefined') {
|
|
if (typeof column.sortCallback === 'function') {
|
|
datatable.dataSet = column.sortCallback(datatable.originalDataSet, sort, column);
|
|
} else {
|
|
datatable.dataSet = Plugin.sortCallback(datatable.originalDataSet, sort, column);
|
|
}
|
|
} else {
|
|
datatable.dataSet = datatable.originalDataSet;
|
|
}
|
|
|
|
if (typeof params.query === 'object') {
|
|
params.query = params.query || {};
|
|
|
|
var search = $(Plugin.getOption('search.input')).val();
|
|
if (typeof search !== 'undefined' && search !== '') {
|
|
search = search.toLowerCase();
|
|
datatable.dataSet = $.grep(datatable.dataSet, function(obj) {
|
|
for (var field in obj) {
|
|
if (!obj.hasOwnProperty(field)) continue;
|
|
if (typeof obj[field] === 'string') {
|
|
if (obj[field].toLowerCase().indexOf(search) > -1) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
});
|
|
// remove generalSearch as we don't need this for next columns filter
|
|
delete params.query[Plugin.getGeneralSearchKey()];
|
|
}
|
|
|
|
// remove empty element from array
|
|
$.each(params.query, function(k, v) {
|
|
if (v === '') {
|
|
delete params.query[k];
|
|
}
|
|
});
|
|
|
|
// filter array by query
|
|
datatable.dataSet = Plugin.filterArray(datatable.dataSet, params.query);
|
|
|
|
// reset array index
|
|
datatable.dataSet = datatable.dataSet.filter(function() {
|
|
return true;
|
|
});
|
|
}
|
|
|
|
return datatable.dataSet;
|
|
},
|
|
|
|
/**
|
|
* Utility helper to filter array by object pair of {key:value}
|
|
* @param list
|
|
* @param args
|
|
* @param operator
|
|
* @returns {*}
|
|
*/
|
|
filterArray: function(list, args, operator) {
|
|
if (typeof list !== 'object') {
|
|
return [];
|
|
}
|
|
|
|
if (typeof operator === 'undefined') operator = 'AND';
|
|
|
|
if (typeof args !== 'object') {
|
|
return list;
|
|
}
|
|
|
|
operator = operator.toUpperCase();
|
|
|
|
if ($.inArray(operator, ['AND', 'OR', 'NOT']) === -1) {
|
|
return [];
|
|
}
|
|
|
|
var count = Object.keys(args).length;
|
|
var filtered = [];
|
|
|
|
$.each(list, function(key, obj) {
|
|
var to_match = obj;
|
|
|
|
var matched = 0;
|
|
$.each(args, function(m_key, m_value) {
|
|
if (to_match.hasOwnProperty(m_key) && m_value == to_match[m_key]) {
|
|
matched++;
|
|
}
|
|
});
|
|
|
|
if (('AND' == operator && matched == count) ||
|
|
('OR' == operator && matched > 0) ||
|
|
('NOT' == operator && 0 == matched)) {
|
|
filtered[key] = obj;
|
|
}
|
|
});
|
|
|
|
list = filtered;
|
|
|
|
return list;
|
|
},
|
|
|
|
/**
|
|
* Reset lock column scroll to 0 when resize
|
|
*/
|
|
resetScroll: function() {
|
|
if (typeof options.detail === 'undefined' && Plugin.getDepth() === 1) {
|
|
$(datatable.table).find('.m-datatable__row').css('left', 0);
|
|
$(datatable.table).find('.m-datatable__lock').css('top', 0);
|
|
$(datatable.tableBody).scrollTop(0);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Get column options by field
|
|
* @param field
|
|
* @returns {boolean}
|
|
*/
|
|
getColumnByField: function(field) {
|
|
var result;
|
|
$.each(options.columns, function(i, column) {
|
|
if (field === column.field) {
|
|
result = column;
|
|
return false;
|
|
}
|
|
});
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Get default sort column
|
|
*/
|
|
getDefaultSortColumn: function() {
|
|
var result = {sort: '', field: ''};
|
|
$.each(options.columns, function(i, column) {
|
|
if (typeof column.sortable !== 'undefined'
|
|
&& $.inArray(column.sortable, ['asc', 'desc']) !== -1) {
|
|
result = {sort: column.sortable, field: column.field};
|
|
return false;
|
|
}
|
|
});
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Helper to get element dimensions, when the element is hidden
|
|
* @param element
|
|
* @param includeMargin
|
|
* @returns {{width: number, height: number, innerWidth: number, innerHeight: number, outerWidth: number, outerHeight: number}}
|
|
*/
|
|
getHiddenDimensions: function(element, includeMargin) {
|
|
var props = {
|
|
position: 'absolute',
|
|
visibility: 'hidden',
|
|
display: 'block',
|
|
},
|
|
dim = {
|
|
width: 0,
|
|
height: 0,
|
|
innerWidth: 0,
|
|
innerHeight: 0,
|
|
outerWidth: 0,
|
|
outerHeight: 0,
|
|
},
|
|
hiddenParents = $(element).parents().addBack().not(':visible');
|
|
includeMargin = (typeof includeMargin === 'boolean')
|
|
? includeMargin
|
|
: false;
|
|
|
|
var oldProps = [];
|
|
hiddenParents.each(function() {
|
|
var old = {};
|
|
|
|
for (var name in props) {
|
|
old[name] = this.style[name];
|
|
this.style[name] = props[name];
|
|
}
|
|
|
|
oldProps.push(old);
|
|
});
|
|
|
|
dim.width = $(element).width();
|
|
dim.outerWidth = $(element).outerWidth(includeMargin);
|
|
dim.innerWidth = $(element).innerWidth();
|
|
dim.height = $(element).height();
|
|
dim.innerHeight = $(element).innerHeight();
|
|
dim.outerHeight = $(element).outerHeight(includeMargin);
|
|
|
|
hiddenParents.each(function(i) {
|
|
var old = oldProps[i];
|
|
for (var name in props) {
|
|
this.style[name] = old[name];
|
|
}
|
|
});
|
|
|
|
return dim;
|
|
},
|
|
|
|
getGeneralSearchKey: function() {
|
|
var searchInput = $(Plugin.getOption('search.input'));
|
|
return $(searchInput).prop('name') || $(searchInput).prop('id');
|
|
},
|
|
|
|
/**
|
|
* Get value by dot notation path string and to prevent undefined errors
|
|
* @param path String Dot notation path in string
|
|
* @param object Object to iterate
|
|
* @returns {*}
|
|
*/
|
|
getObject: function(path, object) {
|
|
return path.split('.').reduce(function(obj, i) {
|
|
return obj !== null && typeof obj[i] !== 'undefined' ? obj[i] : null;
|
|
}, object);
|
|
},
|
|
|
|
/**
|
|
* Extend object
|
|
* @param obj
|
|
* @param path
|
|
* @param value
|
|
* @returns {*}
|
|
*/
|
|
extendObj: function(obj, path, value) {
|
|
var levels = path.split('.'),
|
|
i = 0;
|
|
|
|
function createLevel(child) {
|
|
var name = levels[i++];
|
|
if (typeof child[name] !== 'undefined' && child[name] !== null) {
|
|
if (typeof child[name] !== 'object' &&
|
|
typeof child[name] !== 'function') {
|
|
child[name] = {};
|
|
}
|
|
} else {
|
|
child[name] = {};
|
|
}
|
|
if (i === levels.length) {
|
|
child[name] = value;
|
|
} else {
|
|
createLevel(child[name]);
|
|
}
|
|
}
|
|
|
|
createLevel(obj);
|
|
return obj;
|
|
},
|
|
|
|
/********************
|
|
** PUBLIC API METHODS
|
|
********************/
|
|
|
|
// delay timer
|
|
timer: 0,
|
|
|
|
/**
|
|
* Redraw datatable by recalculating its DOM elements, etc.
|
|
* @returns {jQuery}
|
|
*/
|
|
redraw: function() {
|
|
Plugin.adjustCellsWidth.call();
|
|
Plugin.adjustCellsHeight.call();
|
|
Plugin.adjustLockContainer.call();
|
|
Plugin.initHeight.call();
|
|
return datatable;
|
|
},
|
|
|
|
/**
|
|
* Shortcode to reload
|
|
* @returns {jQuery}
|
|
*/
|
|
load: function() {
|
|
Plugin.reload();
|
|
return datatable;
|
|
},
|
|
|
|
/**
|
|
* Datasource reload
|
|
* @returns {jQuery}
|
|
*/
|
|
reload: function() {
|
|
var delay = (function() {
|
|
return function(callback, ms) {
|
|
clearTimeout(Plugin.timer);
|
|
Plugin.timer = setTimeout(callback, ms);
|
|
};
|
|
})();
|
|
delay(function() {
|
|
// local only. remote pagination will skip this block
|
|
if (options.data.serverFiltering === false) {
|
|
Plugin.localDataUpdate();
|
|
}
|
|
Plugin.dataRender();
|
|
$(datatable).trigger('m-datatable--on-reloaded');
|
|
}, Plugin.getOption('search.delay'));
|
|
return datatable;
|
|
},
|
|
|
|
/**
|
|
* Get record by record ID
|
|
* @param id
|
|
* @returns {jQuery}
|
|
*/
|
|
getRecord: function(id) {
|
|
if (typeof datatable.tableBody === 'undefined') datatable.tableBody = $(datatable.table).children('tbody');
|
|
$(datatable.tableBody).find('.m-datatable__cell:first-child').each(function(i, cell) {
|
|
if (id == $(cell).text()) {
|
|
var rowNumber = $(cell).closest('.m-datatable__row').index() + 1;
|
|
datatable.API.record = datatable.API.value = Plugin.getOneRow(datatable.tableBody, rowNumber);
|
|
return datatable;
|
|
}
|
|
});
|
|
return datatable;
|
|
},
|
|
|
|
/**
|
|
* @deprecated in v5.0.6
|
|
* Get column of current record ID
|
|
* @param columnName
|
|
* @returns {jQuery}
|
|
*/
|
|
getColumn: function(columnName) {
|
|
Plugin.setSelectedRecords();
|
|
datatable.API.value = $(datatable.API.record).find('[data-field="' + columnName + '"]');
|
|
return datatable;
|
|
},
|
|
|
|
/**
|
|
* Destroy datatable to original DOM state before datatable was initialized
|
|
* @returns {jQuery}
|
|
*/
|
|
destroy: function() {
|
|
$(datatable).parent().find('.m-datatable__pager').remove();
|
|
var initialDatatable = $(datatable.initialDatatable).addClass('m-datatable--destroyed').show();
|
|
$(datatable).replaceWith(initialDatatable);
|
|
datatable = initialDatatable;
|
|
$(datatable).trigger('m-datatable--on-destroy');
|
|
Plugin.isInit = false;
|
|
initialDatatable = null;
|
|
return initialDatatable;
|
|
},
|
|
|
|
/**
|
|
* Sort by column field
|
|
* @param field
|
|
* @param sort
|
|
*/
|
|
sort: function(field, sort) {
|
|
if (typeof sort === 'undefined') sort = 'asc';
|
|
$(datatable.tableHead).
|
|
find('.m-datatable__cell[data-field="' + field + '"]').
|
|
trigger('click');
|
|
return datatable;
|
|
},
|
|
|
|
/**
|
|
* @deprecated in v5.0.6
|
|
* Get current selected column value
|
|
* @returns {jQuery}
|
|
*/
|
|
getValue: function() {
|
|
return $(datatable.API.value).text();
|
|
},
|
|
|
|
/**
|
|
* Set checkbox active
|
|
* @param cell JQuery selector or checkbox ID
|
|
*/
|
|
setActive: function(cell) {
|
|
if (typeof cell === 'string') {
|
|
// set by checkbox id
|
|
cell = $(datatable.tableBody).
|
|
find('.m-checkbox--single > [type="checkbox"][value="' + cell + '"]');
|
|
}
|
|
|
|
$(cell).prop('checked', true);
|
|
|
|
// normal table
|
|
var row = $(cell).
|
|
closest('.m-datatable__row').
|
|
addClass('m-datatable__row--active');
|
|
|
|
var index = $(row).index() + 1;
|
|
// lock table
|
|
$(row).
|
|
closest('.m-datatable__lock').
|
|
parent().
|
|
find('.m-datatable__row:nth-child(' + index + ')').
|
|
addClass('m-datatable__row--active');
|
|
|
|
var ids = [];
|
|
$(row).each(function(i, td) {
|
|
var id = $(td).find('.m-checkbox--single:not(.m-checkbox--all) > [type="checkbox"]').val();
|
|
if (typeof id !== 'undefined') {
|
|
ids.push(id);
|
|
}
|
|
});
|
|
|
|
$(datatable).trigger('m-datatable--on-check', [ids]);
|
|
},
|
|
|
|
/**
|
|
* Set checkbox inactive
|
|
* @param cell JQuery selector or checkbox ID
|
|
*/
|
|
setInactive: function(cell) {
|
|
if (typeof cell === 'string') {
|
|
// set by checkbox id
|
|
cell = $(datatable.tableBody).
|
|
find('.m-checkbox--single > [type="checkbox"][value="' + cell + '"]');
|
|
}
|
|
|
|
$(cell).prop('checked', false);
|
|
|
|
// normal table
|
|
var row = $(cell).
|
|
closest('.m-datatable__row').
|
|
removeClass('m-datatable__row--active');
|
|
var index = $(row).index() + 1;
|
|
|
|
// lock table
|
|
$(row).
|
|
closest('.m-datatable__lock').
|
|
parent().
|
|
find('.m-datatable__row:nth-child(' + index + ')').
|
|
removeClass('m-datatable__row--active');
|
|
|
|
var ids = [];
|
|
$(row).each(function(i, td) {
|
|
var id = $(td).find('.m-checkbox--single:not(.m-checkbox--all) > [type="checkbox"]').val();
|
|
if (typeof id !== 'undefined') {
|
|
ids.push(id);
|
|
}
|
|
});
|
|
|
|
$(datatable).trigger('m-datatable--on-uncheck', [ids]);
|
|
},
|
|
|
|
/**
|
|
* Set all checkboxes active or inactive
|
|
* @param active
|
|
*/
|
|
setActiveAll: function(active) {
|
|
// todo; check if child table also will set active?
|
|
var checkboxes = $(datatable.table).find('.m-datatable__body .m-datatable__row').
|
|
find('.m-datatable__cell .m-checkbox [type="checkbox"]');
|
|
if (active) {
|
|
Plugin.setActive(checkboxes);
|
|
} else {
|
|
Plugin.setInactive(checkboxes);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @deprecated in v5.0.6
|
|
* Get selected rows which are active
|
|
* @returns {jQuery}
|
|
*/
|
|
setSelectedRecords: function() {
|
|
datatable.API.record = $(datatable.tableBody).find('.m-datatable__row--active');
|
|
return datatable;
|
|
},
|
|
|
|
/**
|
|
* Get selected records
|
|
* @returns {null}
|
|
*/
|
|
getSelectedRecords: function() {
|
|
// support old method
|
|
Plugin.setSelectedRecords();
|
|
datatable.API.record = datatable.rows('.m-datatable__row--active').nodes();
|
|
return datatable.API.record;
|
|
},
|
|
|
|
/**
|
|
* Get options by dots notation path
|
|
* @param path String Dot notation path in string
|
|
* @returns {*}
|
|
*/
|
|
getOption: function(path) {
|
|
return Plugin.getObject(path, options);
|
|
},
|
|
|
|
/**
|
|
* Set global options nodes by dots notation path
|
|
* @param path
|
|
* @param object
|
|
*/
|
|
setOption: function(path, object) {
|
|
options = Plugin.extendObj(options, path, object);
|
|
},
|
|
|
|
/**
|
|
* Search filter for local & remote
|
|
* @param value
|
|
* @param columns. Optional list of columns to be filtered.
|
|
*/
|
|
search: function(value, columns) {
|
|
if (typeof columns !== 'undefined') columns = $.makeArray(columns);
|
|
var delay = (function() {
|
|
return function(callback, ms) {
|
|
clearTimeout(Plugin.timer);
|
|
Plugin.timer = setTimeout(callback, ms);
|
|
};
|
|
})();
|
|
|
|
delay(function() {
|
|
// get query parameters
|
|
var query = Plugin.getDataSourceQuery();
|
|
|
|
// search not by columns
|
|
if (typeof columns === 'undefined' && typeof value !== 'undefined') {
|
|
var key = Plugin.getGeneralSearchKey();
|
|
query[key] = value;
|
|
}
|
|
|
|
// search by columns, support multiple columns
|
|
if (typeof columns === 'object') {
|
|
$.each(columns, function(k, column) {
|
|
query[column] = value;
|
|
});
|
|
// remove empty element from arrays
|
|
$.each(query, function(k, v) {
|
|
if (v === '') {
|
|
delete query[k];
|
|
}
|
|
});
|
|
}
|
|
|
|
Plugin.setDataSourceQuery(query);
|
|
|
|
// local filter only. remote pagination will skip this block
|
|
if (options.data.serverFiltering === false) {
|
|
Plugin.localDataUpdate();
|
|
}
|
|
Plugin.dataRender();
|
|
}, Plugin.getOption('search.delay'));
|
|
},
|
|
|
|
/**
|
|
* Set datasource params
|
|
* @param param
|
|
* @param value
|
|
*/
|
|
setDataSourceParam: function(param, value) {
|
|
var defaultSort = Plugin.getDefaultSortColumn();
|
|
datatable.API.params = $.extend({}, {
|
|
pagination: {page: 1, perpage: Plugin.getOption('data.pageSize')},
|
|
sort: {sort: defaultSort.sort, field: defaultSort.field},
|
|
query: {},
|
|
}, datatable.API.params, Plugin.stateGet(Plugin.stateId));
|
|
|
|
datatable.API.params = Plugin.extendObj(datatable.API.params, param, value);
|
|
|
|
Plugin.stateKeep(Plugin.stateId, datatable.API.params);
|
|
},
|
|
|
|
/**
|
|
* Get datasource params
|
|
* @param param
|
|
*/
|
|
getDataSourceParam: function(param) {
|
|
var defaultSort = Plugin.getDefaultSortColumn();
|
|
datatable.API.params = $.extend({}, {
|
|
pagination: {page: 1, perpage: Plugin.getOption('data.pageSize')},
|
|
sort: {sort: defaultSort.sort, field: defaultSort.field},
|
|
query: {},
|
|
}, datatable.API.params, Plugin.stateGet(Plugin.stateId));
|
|
|
|
if (typeof param === 'string') {
|
|
return Plugin.getObject(param, datatable.API.params);
|
|
}
|
|
|
|
return datatable.API.params;
|
|
},
|
|
|
|
/**
|
|
* Shortcode to datatable.getDataSourceParam('query');
|
|
* @returns {*}
|
|
*/
|
|
getDataSourceQuery: function() {
|
|
return Plugin.getDataSourceParam('query') || {};
|
|
},
|
|
|
|
/**
|
|
* Shortcode to datatable.setDataSourceParam('query', query);
|
|
* @param query
|
|
*/
|
|
setDataSourceQuery: function(query) {
|
|
Plugin.setDataSourceParam('query', query);
|
|
},
|
|
|
|
/**
|
|
* Get current page number
|
|
* @returns {number}
|
|
*/
|
|
getCurrentPage: function() {
|
|
return $(datatable.table).
|
|
siblings('.m-datatable__pager').
|
|
last().
|
|
find('.m-datatable__pager-nav').
|
|
find('.m-datatable__pager-link.m-datatable__pager-link--active').
|
|
data('page') || 1;
|
|
},
|
|
|
|
/**
|
|
* Get selected dropdown page size
|
|
* @returns {*|number}
|
|
*/
|
|
getPageSize: function() {
|
|
return $(datatable.table).
|
|
siblings('.m-datatable__pager').
|
|
last().
|
|
find('.m-datatable__pager-size').
|
|
val() || 10;
|
|
},
|
|
|
|
/**
|
|
* Get total rows
|
|
*/
|
|
getTotalRows: function() {
|
|
return datatable.API.params.pagination.total;
|
|
},
|
|
|
|
/**
|
|
* Get full dataset in grid
|
|
* @returns {*|null|Array}
|
|
*/
|
|
getDataSet: function() {
|
|
return datatable.originalDataSet;
|
|
},
|
|
|
|
/**
|
|
* @deprecated in v5.0.6
|
|
* Hide column by column's field name
|
|
* @param fieldName
|
|
*/
|
|
hideColumn: function(fieldName) {
|
|
// add hide option for this column
|
|
$.map(options.columns, function(column) {
|
|
if (fieldName === column.field) {
|
|
column.responsive = {hidden: 'xl'};
|
|
}
|
|
return column;
|
|
});
|
|
// hide current displayed column
|
|
var tds = $.grep($(datatable.table).find('.m-datatable__cell'), function(n, i) {
|
|
return fieldName === $(n).data('field');
|
|
});
|
|
$(tds).hide();
|
|
},
|
|
|
|
/**
|
|
* @deprecated in v5.0.6
|
|
* Show column by column's field name
|
|
* @param fieldName
|
|
*/
|
|
showColumn: function(fieldName) {
|
|
// add hide option for this column
|
|
$.map(options.columns, function(column) {
|
|
if (fieldName === column.field) {
|
|
delete column.responsive;
|
|
}
|
|
return column;
|
|
});
|
|
// hide current displayed column
|
|
var tds = $.grep($(datatable.table).find('.m-datatable__cell'), function(n, i) {
|
|
return fieldName === $(n).data('field');
|
|
});
|
|
$(tds).show();
|
|
},
|
|
|
|
destroyScroller: function(element) {
|
|
if (typeof element === 'undefined') element = datatable.tableBody;
|
|
$(element).each(function() {
|
|
if ($(this).hasClass('mCustomScrollbar')) {
|
|
try {
|
|
mApp.destroyScroller($(this));
|
|
} catch (e) {
|
|
console.log(e);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* NEW API
|
|
*/
|
|
|
|
nodeTr: [],
|
|
nodeTd: [],
|
|
nodeCols: [],
|
|
recentNode: [],
|
|
|
|
table: function() {
|
|
return datatable.table;
|
|
},
|
|
|
|
/**
|
|
* Select a single row from the table
|
|
* @param selector
|
|
* @returns {jQuery}
|
|
*/
|
|
row: function(selector) {
|
|
Plugin.rows(selector);
|
|
Plugin.nodeTr = Plugin.recentNode = $(Plugin.nodeTr).first();
|
|
return datatable;
|
|
},
|
|
|
|
/**
|
|
* Select multiple rows from the table
|
|
* @param selector
|
|
* @returns {jQuery}
|
|
*/
|
|
rows: function(selector) {
|
|
Plugin.nodeTr = Plugin.recentNode = $(datatable.tableBody).find(selector).filter('.m-datatable__row');
|
|
return datatable;
|
|
},
|
|
|
|
/**
|
|
* Select a single column from the table
|
|
* @param index zero-based index
|
|
* @returns {jQuery}
|
|
*/
|
|
column: function(index) {
|
|
Plugin.nodeCols = Plugin.recentNode = $(datatable.tableBody).find('.m-datatable__cell:nth-child(' + (index + 1) + ')');
|
|
return datatable;
|
|
},
|
|
|
|
/**
|
|
* Select multiple columns from the table
|
|
* @param selector
|
|
* @returns {jQuery}
|
|
*/
|
|
columns: function(selector) {
|
|
var context = datatable.table;
|
|
if (Plugin.nodeTr === Plugin.recentNode) {
|
|
context = Plugin.nodeTr;
|
|
}
|
|
var columns = $(context).find('.m-datatable__cell[data-field="' + selector + '"]');
|
|
if (columns.length > 0) {
|
|
Plugin.nodeCols = Plugin.recentNode = columns;
|
|
} else {
|
|
Plugin.nodeCols = Plugin.recentNode = $(context).find(selector).filter('.m-datatable__cell');
|
|
}
|
|
return datatable;
|
|
},
|
|
|
|
cell: function(selector) {
|
|
Plugin.cells(selector);
|
|
Plugin.nodeTd = Plugin.recentNode = $(Plugin.nodeTd).first();
|
|
return datatable;
|
|
},
|
|
|
|
cells: function(selector) {
|
|
var cells = $(datatable.tableBody).find('.m-datatable__cell');
|
|
if (typeof selector !== 'undefined') {
|
|
cells = $(cells).filter(selector);
|
|
}
|
|
Plugin.nodeTd = Plugin.recentNode = cells;
|
|
return datatable;
|
|
},
|
|
|
|
/**
|
|
* Delete the selected row from the table
|
|
* @returns {jQuery}
|
|
*/
|
|
remove: function() {
|
|
if ($(Plugin.nodeTr.length) && Plugin.nodeTr === Plugin.recentNode) {
|
|
$(Plugin.nodeTr).remove();
|
|
}
|
|
return datatable;
|
|
},
|
|
|
|
/**
|
|
* Show or hide the columns or rows
|
|
*/
|
|
visible: function(bool) {
|
|
if ($(Plugin.recentNode.length)) {
|
|
if (bool) {
|
|
if (Plugin.recentNode === Plugin.nodeCols) {
|
|
Plugin.setOption('columns.' + Plugin.recentNode.index() + '.responsive', {});
|
|
}
|
|
$(Plugin.recentNode).show();
|
|
} else {
|
|
if (Plugin.recentNode === Plugin.nodeCols) {
|
|
Plugin.setOption('columns.' + Plugin.recentNode.index() + '.responsive', {hidden: 'xl'});
|
|
}
|
|
$(Plugin.recentNode).hide();
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Get the the DOM element for the selected rows or columns
|
|
* @returns {Array}
|
|
*/
|
|
nodes: function() {
|
|
return Plugin.recentNode;
|
|
},
|
|
|
|
/**
|
|
* will be implemented soon
|
|
* @returns {jQuery}
|
|
*/
|
|
dataset: function() {
|
|
return datatable;
|
|
},
|
|
|
|
};
|
|
|
|
/**
|
|
* Public API methods can be used directly by datatable
|
|
*/
|
|
$.each(Plugin, function(funcName, func) {
|
|
datatable[funcName] = func;
|
|
});
|
|
|
|
// initialize main datatable plugin
|
|
if (typeof options !== 'undefined') {
|
|
if (typeof options === 'string') {
|
|
var method = options;
|
|
datatable = $(this).data('mDatatable');
|
|
if (typeof datatable !== 'undefined') {
|
|
options = datatable.options;
|
|
Plugin[method].apply(this, Array.prototype.slice.call(arguments, 1));
|
|
}
|
|
} else {
|
|
if (!datatable.data('mDatatable') && !$(this).hasClass('m-datatable--loaded')) {
|
|
datatable.dataSet = null;
|
|
datatable.textAlign = {
|
|
left: 'm-datatable__cell--left',
|
|
center: 'm-datatable__cell--center',
|
|
right: 'm-datatable__cell--right',
|
|
};
|
|
|
|
// merge default and user defined options
|
|
options = $.extend(true, {}, $.fn.mDatatable.defaults, options);
|
|
|
|
datatable.options = options;
|
|
|
|
// init plugin process
|
|
Plugin.init.apply(this, [options]);
|
|
|
|
$(datatable).data('mDatatable', datatable);
|
|
}
|
|
}
|
|
} else {
|
|
// get existing instance datatable
|
|
datatable = $(this).data('mDatatable');
|
|
if (typeof datatable === 'undefined') {
|
|
$.error('mDatatable not initialized');
|
|
}
|
|
options = datatable.options;
|
|
}
|
|
|
|
return datatable;
|
|
};
|
|
|
|
// default options
|
|
$.fn.mDatatable.defaults = {
|
|
// datasource definition
|
|
data: {
|
|
type: 'local',
|
|
source: null,
|
|
pageSize: 10, // display records per page
|
|
saveState: {
|
|
// save datatable state(pagination, filtering, sorting, etc) in cookie or browser webstorage
|
|
cookie: false,
|
|
webstorage: true,
|
|
},
|
|
|
|
serverPaging: false,
|
|
serverFiltering: false,
|
|
serverSorting: false,
|
|
},
|
|
|
|
// layout definition
|
|
layout: {
|
|
theme: 'default', // datatable will support multiple themes and designs
|
|
class: 'm-datatable--brand', // custom wrapper class
|
|
scroll: false, // enable/disable datatable scroll both horizontal and vertical when needed.
|
|
height: null, // datatable's body's fixed height
|
|
minHeight: 300,
|
|
footer: false, // display/hide footer
|
|
header: true, // display/hide header
|
|
|
|
// datatable custom scroll params
|
|
smoothScroll: {
|
|
scrollbarShown: true,
|
|
},
|
|
|
|
// datatable spinner
|
|
spinner: {
|
|
overlayColor: '#000000',
|
|
opacity: 0,
|
|
type: 'loader',
|
|
state: 'brand',
|
|
message: true,
|
|
},
|
|
|
|
// datatable UI icons
|
|
icons: {
|
|
sort: {asc: 'la la-arrow-up', desc: 'la la-arrow-down'},
|
|
pagination: {
|
|
next: 'la la-angle-right',
|
|
prev: 'la la-angle-left',
|
|
first: 'la la-angle-double-left',
|
|
last: 'la la-angle-double-right',
|
|
more: 'la la-ellipsis-h',
|
|
},
|
|
rowDetail: {expand: 'fa fa-caret-down', collapse: 'fa fa-caret-right'},
|
|
},
|
|
},
|
|
|
|
// column sorting
|
|
sortable: true,
|
|
|
|
// resize column size with mouse drag coming soon)
|
|
resizable: false,
|
|
|
|
// column based filtering (coming soon)
|
|
filterable: false,
|
|
|
|
pagination: true,
|
|
|
|
// inline and bactch editing (cooming soon)
|
|
editable: false,
|
|
|
|
// columns definition
|
|
columns: [],
|
|
|
|
search: {
|
|
// enable trigger search by keyup enter
|
|
onEnter: false,
|
|
// input text for search
|
|
input: null,
|
|
// search delay in milliseconds
|
|
delay: 400,
|
|
},
|
|
|
|
rows: {
|
|
// deprecated
|
|
callback: function() {},
|
|
// call before row template
|
|
beforeTemplate: function() {},
|
|
// call after row template
|
|
afterTemplate: function() {},
|
|
// auto hide columns, if rows overflow. work on non locked columns
|
|
autoHide: false,
|
|
},
|
|
|
|
// toolbar
|
|
toolbar: {
|
|
// place pagination and displayInfo blocks according to the array order
|
|
layout: ['pagination', 'info'],
|
|
|
|
// toolbar placement can be at top or bottom or both top and bottom repeated
|
|
placement: ['bottom'], //'top', 'bottom'
|
|
|
|
// toolbar items
|
|
items: {
|
|
// pagination
|
|
pagination: {
|
|
// pagination type(default or scroll)
|
|
type: 'default',
|
|
|
|
// number of pages to display by breakpoints
|
|
pages: {
|
|
desktop: {
|
|
layout: 'default',
|
|
pagesNumber: 6,
|
|
},
|
|
tablet: {
|
|
layout: 'default',
|
|
pagesNumber: 3,
|
|
},
|
|
mobile: {
|
|
layout: 'compact',
|
|
},
|
|
},
|
|
|
|
// navigation buttons
|
|
navigation: {
|
|
prev: true, // display prev link
|
|
next: true, // display next link
|
|
first: true, // display first link
|
|
last: true // display last link
|
|
},
|
|
|
|
// page size select
|
|
pageSizeSelect: [] // display dropdown to select pagination size. -1 is used for "ALl" option
|
|
},
|
|
|
|
// records info
|
|
info: true,
|
|
},
|
|
},
|
|
|
|
// here we will keep all strings and message used by datatable UI so developer can easiliy translate to any language.
|
|
// By default the stirngs will be in the plugin source and here can override it
|
|
translate: {
|
|
records: {
|
|
processing: 'Please wait...',
|
|
noRecords: 'No records found',
|
|
},
|
|
toolbar: {
|
|
pagination: {
|
|
items: {
|
|
default: {
|
|
first: 'First',
|
|
prev: 'Previous',
|
|
next: 'Next',
|
|
last: 'Last',
|
|
more: 'More pages',
|
|
input: 'Page number',
|
|
select: 'Select page size',
|
|
},
|
|
info: 'Displaying {{start}} - {{end}} of {{total}} records',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
extensions: {},
|
|
};
|
|
|
|
}(jQuery));
|
|
// jquery extension to add animation class into element
|
|
jQuery.fn.extend({
|
|
animateClass: function(animationName, callback) {
|
|
var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
|
|
jQuery(this).addClass('animated ' + animationName).one(animationEnd, function() {
|
|
jQuery(this).removeClass('animated ' + animationName);
|
|
});
|
|
|
|
if (callback) {
|
|
jQuery(this).one(animationEnd, callback);
|
|
}
|
|
},
|
|
animateDelay: function(value) {
|
|
var vendors = ['webkit-', 'moz-', 'ms-', 'o-', ''];
|
|
for (var i = 0; i < vendors.length; i++) {
|
|
jQuery(this).css(vendors[i] + 'animation-delay', value);
|
|
}
|
|
},
|
|
animateDuration: function(value) {
|
|
var vendors = ['webkit-', 'moz-', 'ms-', 'o-', ''];
|
|
for (var i = 0; i < vendors.length; i++) {
|
|
jQuery(this).css(vendors[i] + 'animation-duration', value);
|
|
}
|
|
}
|
|
});
|
|
(function ($) {
|
|
// Plugin function
|
|
$.fn.mDropdown = function (options) {
|
|
// Plugin scope variable
|
|
var dropdown = {};
|
|
var element = $(this);
|
|
|
|
// Plugin class
|
|
var Plugin = {
|
|
/**
|
|
* Run
|
|
*/
|
|
run: function (options) {
|
|
if (!element.data('dropdown')) {
|
|
// create instance
|
|
Plugin.init(options);
|
|
Plugin.build();
|
|
Plugin.setup();
|
|
|
|
// assign instance to the element
|
|
element.data('dropdown', dropdown);
|
|
} else {
|
|
// get instance from the element
|
|
dropdown = element.data('dropdown');
|
|
}
|
|
|
|
return dropdown;
|
|
},
|
|
|
|
/**
|
|
* Initialize
|
|
*/
|
|
init: function(options) {
|
|
dropdown.events = [];
|
|
dropdown.eventOne = false;
|
|
dropdown.close = element.find('.m-dropdown__close');
|
|
dropdown.toggle = element.find('.m-dropdown__toggle');
|
|
dropdown.arrow = element.find('.m-dropdown__arrow');
|
|
dropdown.wrapper = element.find('.m-dropdown__wrapper');
|
|
dropdown.scrollable = element.find('.m-dropdown__scrollable');
|
|
dropdown.defaultDropPos = element.hasClass('m-dropdown--up') ? 'up' : 'down';
|
|
dropdown.currentDropPos = dropdown.defaultDropPos;
|
|
|
|
dropdown.options = $.extend(true, {}, $.fn.mDropdown.defaults, options);
|
|
if (element.data('drop-auto') === true) {
|
|
dropdown.options.dropAuto = true;
|
|
} else if (element.data('drop-auto') === false) {
|
|
dropdown.options.dropAuto = false;
|
|
}
|
|
|
|
if (dropdown.scrollable.length > 0) {
|
|
if (dropdown.scrollable.data('min-height')) {
|
|
dropdown.options.minHeight = dropdown.scrollable.data('min-height');
|
|
}
|
|
|
|
if (dropdown.scrollable.data('max-height')) {
|
|
dropdown.options.maxHeight = dropdown.scrollable.data('max-height');
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Build DOM and init event handlers
|
|
*/
|
|
build: function () {
|
|
if (mUtil.isMobileDevice()) {
|
|
if (element.data('dropdown-toggle') == 'hover' || element.data('dropdown-toggle') == 'click') {
|
|
dropdown.options.toggle = 'click';
|
|
} else {
|
|
dropdown.options.toggle = 'click';
|
|
dropdown.toggle.click(Plugin.toggle);
|
|
}
|
|
} else {
|
|
if (element.data('dropdown-toggle') == 'hover') {
|
|
dropdown.options.toggle = 'hover';
|
|
element.mouseleave(Plugin.hide);
|
|
} else if(element.data('dropdown-toggle') == 'click') {
|
|
dropdown.options.toggle = 'click';
|
|
} else {
|
|
if (dropdown.options.toggle == 'hover') {
|
|
element.mouseenter(Plugin.show);
|
|
element.mouseleave(Plugin.hide);
|
|
} else {
|
|
dropdown.toggle.click(Plugin.toggle);
|
|
}
|
|
}
|
|
}
|
|
|
|
// handle dropdown close icon
|
|
if (dropdown.close.length) {
|
|
dropdown.close.on('click', Plugin.hide);
|
|
}
|
|
|
|
// disable dropdown close
|
|
Plugin.disableClose();
|
|
},
|
|
|
|
/**
|
|
* Setup dropdown
|
|
*/
|
|
setup: function () {
|
|
if (dropdown.options.placement) {
|
|
element.addClass('m-dropdown--' + dropdown.options.placement);
|
|
}
|
|
|
|
if (dropdown.options.align) {
|
|
element.addClass('m-dropdown--align-' + dropdown.options.align);
|
|
}
|
|
|
|
if (dropdown.options.width) {
|
|
dropdown.wrapper.css('width', dropdown.options.width);
|
|
}
|
|
|
|
if (element.data('dropdown-persistent')) {
|
|
dropdown.options.persistent = true;
|
|
}
|
|
|
|
// handle height
|
|
if (dropdown.options.minHeight) {
|
|
dropdown.scrollable.css('min-height', dropdown.options.minHeight);
|
|
}
|
|
|
|
if (dropdown.options.maxHeight) {
|
|
dropdown.scrollable.css('max-height', dropdown.options.maxHeight);
|
|
dropdown.scrollable.css('overflow-y', 'auto');
|
|
|
|
if (mUtil.isDesktopDevice()) {
|
|
mApp.initScroller(dropdown.scrollable, {});
|
|
}
|
|
}
|
|
|
|
// set zindex
|
|
Plugin.setZindex();
|
|
},
|
|
|
|
/**
|
|
* sync
|
|
*/
|
|
sync: function () {
|
|
$(element).data('dropdown', dropdown);
|
|
},
|
|
|
|
/**
|
|
* Sync dropdown object with jQuery element
|
|
*/
|
|
disableClose: function () {
|
|
element.on('click', '.m-dropdown--disable-close, .mCSB_1_scrollbar', function (e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Toggle dropdown
|
|
*/
|
|
toggle: function () {
|
|
if (dropdown.open) {
|
|
return Plugin.hide();
|
|
} else {
|
|
return Plugin.show();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Set content
|
|
*/
|
|
setContent: function (content) {
|
|
element.find('.m-dropdown__content').html(content);
|
|
|
|
return dropdown;
|
|
},
|
|
|
|
/**
|
|
* Show dropdown
|
|
*/
|
|
show: function() {
|
|
if (dropdown.options.toggle == 'hover' && element.data('hover')) {
|
|
Plugin.clearHovered();
|
|
return dropdown;
|
|
}
|
|
|
|
if (dropdown.open) {
|
|
return dropdown;
|
|
}
|
|
|
|
if (dropdown.arrow.length > 0) {
|
|
Plugin.adjustArrowPos();
|
|
}
|
|
|
|
Plugin.eventTrigger('beforeShow');
|
|
|
|
Plugin.hideOpened();
|
|
|
|
element.addClass('m-dropdown--open');
|
|
|
|
if (mUtil.isMobileDevice() && dropdown.options.mobileOverlay) {
|
|
var zIndex = dropdown.wrapper.css('zIndex') - 1;
|
|
var dropdownoff = $('<div class="m-dropdown__dropoff"></div>');
|
|
|
|
dropdownoff.css('zIndex', zIndex);
|
|
dropdownoff.data('dropdown', element);
|
|
element.data('dropoff', dropdownoff);
|
|
element.after(dropdownoff);
|
|
dropdownoff.click(function(e) {
|
|
Plugin.hide();
|
|
$(this).remove();
|
|
e.preventDefault();
|
|
});
|
|
}
|
|
|
|
element.focus();
|
|
element.attr('aria-expanded', 'true');
|
|
dropdown.open = true;
|
|
|
|
Plugin.handleDropPosition();
|
|
|
|
Plugin.eventTrigger('afterShow');
|
|
|
|
return dropdown;
|
|
},
|
|
|
|
/**
|
|
* Clear dropdown hover
|
|
*/
|
|
clearHovered: function () {
|
|
element.removeData('hover');
|
|
var timeout = element.data('timeout');
|
|
element.removeData('timeout');
|
|
clearTimeout(timeout);
|
|
},
|
|
|
|
/**
|
|
* Hide hovered dropdown
|
|
*/
|
|
hideHovered: function(force) {
|
|
if (force) {
|
|
if (Plugin.eventTrigger('beforeHide') === false) {
|
|
// cancel hide
|
|
return;
|
|
}
|
|
|
|
Plugin.clearHovered();
|
|
element.removeClass('m-dropdown--open');
|
|
dropdown.open = false;
|
|
Plugin.eventTrigger('afterHide');
|
|
} else {
|
|
if (Plugin.eventTrigger('beforeHide') === false) {
|
|
// cancel hide
|
|
return;
|
|
}
|
|
var timeout = setTimeout(function() {
|
|
if (element.data('hover')) {
|
|
Plugin.clearHovered();
|
|
element.removeClass('m-dropdown--open');
|
|
dropdown.open = false;
|
|
Plugin.eventTrigger('afterHide');
|
|
}
|
|
}, dropdown.options.hoverTimeout);
|
|
|
|
element.data('hover', true);
|
|
element.data('timeout', timeout);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Hide clicked dropdown
|
|
*/
|
|
hideClicked: function() {
|
|
if (Plugin.eventTrigger('beforeHide') === false) {
|
|
// cancel hide
|
|
return;
|
|
}
|
|
element.removeClass('m-dropdown--open');
|
|
if (element.data('dropoff')) {
|
|
element.data('dropoff').remove();
|
|
}
|
|
dropdown.open = false;
|
|
Plugin.eventTrigger('afterHide');
|
|
},
|
|
|
|
/**
|
|
* Hide dropdown
|
|
*/
|
|
hide: function(force) {
|
|
if (dropdown.open === false) {
|
|
return dropdown;
|
|
}
|
|
|
|
if (dropdown.options.toggle == 'hover') {
|
|
Plugin.hideHovered(force);
|
|
} else {
|
|
Plugin.hideClicked();
|
|
}
|
|
|
|
if (dropdown.defaultDropPos == 'down' && dropdown.currentDropPos == 'up') {
|
|
element.removeClass('m-dropdown--up');
|
|
dropdown.arrow.prependTo(dropdown.wrapper);
|
|
dropdown.currentDropPos = 'down';
|
|
}
|
|
|
|
return dropdown;
|
|
},
|
|
|
|
/**
|
|
* Hide opened dropdowns
|
|
*/
|
|
hideOpened: function() {
|
|
$('.m-dropdown.m-dropdown--open').each(function() {
|
|
$(this).mDropdown().hide(true);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Adjust dropdown arrow positions
|
|
*/
|
|
adjustArrowPos: function() {
|
|
var width = element.outerWidth();
|
|
var alignment = dropdown.arrow.hasClass('m-dropdown__arrow--right') ? 'right' : 'left';
|
|
var pos = 0;
|
|
|
|
if (dropdown.arrow.length > 0) {
|
|
if (mUtil.isInResponsiveRange('mobile') && element.hasClass('m-dropdown--mobile-full-width')) {
|
|
pos = element.offset().left + (width / 2) - Math.abs(dropdown.arrow.width() / 2) - parseInt(dropdown.wrapper.css('left'));
|
|
dropdown.arrow.css('right', 'auto');
|
|
dropdown.arrow.css('left', pos);
|
|
dropdown.arrow.css('margin-left', 'auto');
|
|
dropdown.arrow.css('margin-right', 'auto');
|
|
} else if (dropdown.arrow.hasClass('m-dropdown__arrow--adjust')) {
|
|
pos = width / 2 - Math.abs(dropdown.arrow.width() / 2);
|
|
if (element.hasClass('m-dropdown--align-push')) {
|
|
pos = pos + 20;
|
|
}
|
|
if (alignment == 'right') {
|
|
dropdown.arrow.css('left', 'auto');
|
|
dropdown.arrow.css('right', pos);
|
|
} else {
|
|
dropdown.arrow.css('right', 'auto');
|
|
dropdown.arrow.css('left', pos);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Change dropdown drop position
|
|
*/
|
|
handleDropPosition: function() {
|
|
return;
|
|
|
|
if (dropdown.options.dropAuto == true) {
|
|
if (Plugin.isInVerticalViewport() === false) {
|
|
if (dropdown.currentDropPos == 'up') {
|
|
element.removeClass('m-dropdown--up');
|
|
dropdown.arrow.prependTo(dropdown.wrapper);
|
|
dropdown.currentDropPos = 'down';
|
|
} else if (dropdown.currentDropPos == 'down') {
|
|
element.addClass('m-dropdown--up');
|
|
dropdown.arrow.appendTo(dropdown.wrapper);
|
|
dropdown.currentDropPos = 'up';
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Get zindex
|
|
*/
|
|
setZindex: function() {
|
|
var oldZindex = dropdown.wrapper.css('z-index');
|
|
var newZindex = mUtil.getHighestZindex(element);
|
|
if (newZindex > oldZindex) {
|
|
dropdown.wrapper.css('z-index', zindex);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Check persistent
|
|
*/
|
|
isPersistent: function () {
|
|
return dropdown.options.persistent;
|
|
},
|
|
|
|
/**
|
|
* Check persistent
|
|
*/
|
|
isShown: function () {
|
|
return dropdown.open;
|
|
},
|
|
|
|
/**
|
|
* Check if dropdown is in viewport
|
|
*/
|
|
isInVerticalViewport: function() {
|
|
var el = dropdown.wrapper;
|
|
var offset = el.offset();
|
|
var height = el.outerHeight();
|
|
var width = el.width();
|
|
var scrollable = el.find('[data-scrollable]');
|
|
|
|
if (scrollable.length) {
|
|
if (scrollable.data('max-height')) {
|
|
height += parseInt(scrollable.data('max-height'));
|
|
} else if(scrollable.data('height')) {
|
|
height += parseInt(scrollable.data('height'));
|
|
}
|
|
}
|
|
|
|
return (offset.top + height < $(window).scrollTop() + $(window).height());
|
|
},
|
|
|
|
/**
|
|
* Trigger events
|
|
*/
|
|
eventTrigger: function(name) {
|
|
for (i = 0; i < dropdown.events.length; i++) {
|
|
var event = dropdown.events[i];
|
|
if (event.name == name) {
|
|
if (event.one == true) {
|
|
if (event.fired == false) {
|
|
dropdown.events[i].fired = true;
|
|
return event.handler.call(this, dropdown);
|
|
}
|
|
} else {
|
|
return event.handler.call(this, dropdown);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
addEvent: function(name, handler, one) {
|
|
dropdown.events.push({
|
|
name: name,
|
|
handler: handler,
|
|
one: one,
|
|
fired: false
|
|
});
|
|
|
|
Plugin.sync();
|
|
|
|
return dropdown;
|
|
}
|
|
};
|
|
|
|
// Run plugin
|
|
Plugin.run.apply(this, [options]);
|
|
|
|
//////////////////////
|
|
// ** Public API ** //
|
|
//////////////////////
|
|
|
|
/**
|
|
* Show dropdown
|
|
* @returns {mDropdown}
|
|
*/
|
|
dropdown.show = function () {
|
|
return Plugin.show();
|
|
};
|
|
|
|
/**
|
|
* Hide dropdown
|
|
* @returns {mDropdown}
|
|
*/
|
|
dropdown.hide = function () {
|
|
return Plugin.hide();
|
|
};
|
|
|
|
/**
|
|
* Toggle dropdown
|
|
* @returns {mDropdown}
|
|
*/
|
|
dropdown.toggle = function () {
|
|
return Plugin.toggle();
|
|
};
|
|
|
|
/**
|
|
* Toggle dropdown
|
|
* @returns {mDropdown}
|
|
*/
|
|
dropdown.isPersistent = function () {
|
|
return Plugin.isPersistent();
|
|
};
|
|
|
|
/**
|
|
* Check shown state
|
|
* @returns {mDropdown}
|
|
*/
|
|
dropdown.isShown = function () {
|
|
return Plugin.isShown();
|
|
};
|
|
|
|
/**
|
|
* Check shown state
|
|
* @returns {mDropdown}
|
|
*/
|
|
dropdown.fixDropPosition = function () {
|
|
return Plugin.handleDropPosition();
|
|
};
|
|
|
|
/**
|
|
* Set dropdown content
|
|
* @returns {mDropdown}
|
|
*/
|
|
dropdown.setContent = function (content) {
|
|
return Plugin.setContent(content);
|
|
};
|
|
|
|
/**
|
|
* Set dropdown content
|
|
* @returns {mDropdown}
|
|
*/
|
|
dropdown.on = function (name, handler) {
|
|
return Plugin.addEvent(name, handler);
|
|
};
|
|
|
|
/**
|
|
* Set dropdown content
|
|
* @returns {mDropdown}
|
|
*/
|
|
dropdown.one = function (name, handler) {
|
|
return Plugin.addEvent(name, handler, true);
|
|
};
|
|
|
|
return dropdown;
|
|
};
|
|
|
|
// default options
|
|
$.fn.mDropdown.defaults = {
|
|
toggle: 'click',
|
|
hoverTimeout: 300,
|
|
skin: 'default',
|
|
height: 'auto',
|
|
dropAuto: true,
|
|
maxHeight: false,
|
|
minHeight: false,
|
|
persistent: false,
|
|
mobileOverlay: true
|
|
};
|
|
|
|
// global init
|
|
if (mUtil.isMobileDevice()) {
|
|
$(document).on('click', '[data-dropdown-toggle="click"] .m-dropdown__toggle, [data-dropdown-toggle="hover"] .m-dropdown__toggle', function(e) {
|
|
e.preventDefault();
|
|
$(this).parent('.m-dropdown').mDropdown().toggle();
|
|
});
|
|
} else {
|
|
$(document).on('click', '[data-dropdown-toggle="click"] .m-dropdown__toggle', function(e) {
|
|
e.preventDefault();
|
|
$(this).parent('.m-dropdown').mDropdown().toggle();
|
|
});
|
|
$(document).on('mouseenter', '[data-dropdown-toggle="hover"]', function(e) {
|
|
$(this).mDropdown().toggle();
|
|
});
|
|
}
|
|
|
|
// handle global document click
|
|
$(document).on('click', function(e) {
|
|
$('.m-dropdown.m-dropdown--open').each(function() {
|
|
if (!$(this).data('dropdown')) {
|
|
return;
|
|
}
|
|
|
|
var target = $(e.target);
|
|
var dropdown = $(this).mDropdown();
|
|
var toggle = $(this).find('.m-dropdown__toggle');
|
|
|
|
if (toggle.length > 0 && target.is(toggle) !== true && toggle.find(target).length === 0 && target.find(toggle).length === 0 && dropdown.isPersistent() == false) {
|
|
dropdown.hide();
|
|
} else if ($(this).find(target).length === 0) {
|
|
dropdown.hide();
|
|
}
|
|
});
|
|
});
|
|
}(jQuery));
|
|
(function ($) {
|
|
// Plugin function
|
|
$.fn.mExample = function (options) {
|
|
// Plugin scope variable
|
|
var example = {};
|
|
var element = $(this);
|
|
|
|
// Plugin class
|
|
var Plugin = {
|
|
/**
|
|
* Run
|
|
*/
|
|
run: function (options) {
|
|
if (!element.data('example')) {
|
|
// create instance
|
|
Plugin.init(options);
|
|
Plugin.build();
|
|
Plugin.setup();
|
|
|
|
// assign instance to the element
|
|
element.data('example', example);
|
|
} else {
|
|
// get instance from the element
|
|
example = element.data('example');
|
|
}
|
|
|
|
return example;
|
|
},
|
|
|
|
/**
|
|
* Initialize
|
|
*/
|
|
init: function(options) {
|
|
example.events = [];
|
|
example.scrollable = element.find('.m-example__scrollable');
|
|
example.options = $.extend(true, {}, $.fn.mExample.defaults, options);
|
|
if (example.scrollable.length > 0) {
|
|
if (example.scrollable.data('data-min-height')) {
|
|
example.options.minHeight = example.scrollable.data('data-min-height');
|
|
}
|
|
|
|
if (example.scrollable.data('data-max-height')) {
|
|
example.options.maxHeight = example.scrollable.data('data-max-height');
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Build DOM and init event handlers
|
|
*/
|
|
build: function () {
|
|
if (mUtil.isMobileDevice()) {
|
|
|
|
} else {
|
|
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Setup example
|
|
*/
|
|
setup: function () {
|
|
|
|
},
|
|
|
|
/**
|
|
* Trigger events
|
|
*/
|
|
eventTrigger: function(name) {
|
|
for (i = 0; i < example.events.length; i++) {
|
|
var event = example.events[i];
|
|
if (event.name == name) {
|
|
if (event.one == true) {
|
|
if (event.fired == false) {
|
|
example.events[i].fired = true;
|
|
return event.handler.call(this, example);
|
|
}
|
|
} else {
|
|
return event.handler.call(this, example);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
addEvent: function(name, handler, one) {
|
|
example.events.push({
|
|
name: name,
|
|
handler: handler,
|
|
one: one,
|
|
fired: false
|
|
});
|
|
|
|
Plugin.sync();
|
|
}
|
|
};
|
|
|
|
// Run plugin
|
|
Plugin.run.apply(this, [options]);
|
|
|
|
//////////////////////
|
|
// ** Public API ** //
|
|
//////////////////////
|
|
|
|
|
|
/**
|
|
* Set example content
|
|
* @returns {mExample}
|
|
*/
|
|
example.on = function (name, handler) {
|
|
return Plugin.addEvent(name, handler);
|
|
};
|
|
|
|
/**
|
|
* Set example content
|
|
* @returns {mExample}
|
|
*/
|
|
example.one = function (name, handler) {
|
|
return Plugin.addEvent(name, handler, true);
|
|
};
|
|
|
|
return example;
|
|
};
|
|
|
|
// default options
|
|
$.fn.mExample.defaults = {
|
|
|
|
};
|
|
}(jQuery));
|
|
(function($) {
|
|
|
|
// Plugin function
|
|
$.fn.mHeader = function(options) {
|
|
// Plugin scope variable
|
|
var header = this;
|
|
var element = $(this);
|
|
|
|
// Plugin class
|
|
var Plugin = {
|
|
/**
|
|
* Run plugin
|
|
* @returns {mHeader}
|
|
*/
|
|
run: function(options) {
|
|
if (element.data('header')) {
|
|
header = element.data('header');
|
|
} else {
|
|
// reset header
|
|
Plugin.init(options);
|
|
|
|
// reset header
|
|
Plugin.reset();
|
|
|
|
// build header
|
|
Plugin.build();
|
|
|
|
element.data('header', header);
|
|
}
|
|
|
|
return header;
|
|
},
|
|
|
|
/**
|
|
* Handles subheader click toggle
|
|
* @returns {mHeader}
|
|
*/
|
|
init: function(options) {
|
|
header.options = $.extend(true, {}, $.fn.mHeader.defaults, options);
|
|
},
|
|
|
|
/**
|
|
* Reset header
|
|
* @returns {mHeader}
|
|
*/
|
|
build: function() {
|
|
Plugin.toggle();
|
|
},
|
|
|
|
toggle: function() {
|
|
var lastScrollTop = 0;
|
|
|
|
if (header.options.minimize.mobile === false && header.options.minimize.desktop === false) {
|
|
return;
|
|
}
|
|
|
|
$(window).scroll(function() {
|
|
var offset = 0;
|
|
|
|
if (mUtil.isInResponsiveRange('desktop')) {
|
|
offset = header.options.offset.desktop;
|
|
on = header.options.minimize.desktop.on;
|
|
off = header.options.minimize.desktop.off;
|
|
} else if (mUtil.isInResponsiveRange('tablet-and-mobile')) {
|
|
offset = header.options.offset.mobile;
|
|
on = header.options.minimize.mobile.on;
|
|
off = header.options.minimize.mobile.off;
|
|
}
|
|
|
|
var st = $(this).scrollTop();
|
|
|
|
if (header.options.classic) {
|
|
if (st > offset){ // down scroll mode
|
|
$("body").addClass(on);
|
|
$("body").removeClass(off);
|
|
} else { // back scroll mode
|
|
$("body").addClass(off);
|
|
$("body").removeClass(on);
|
|
}
|
|
} else {
|
|
if (st > offset && lastScrollTop < st){ // down scroll mode
|
|
$("body").addClass(on);
|
|
$("body").removeClass(off);
|
|
} else { // back scroll mode
|
|
$("body").addClass(off);
|
|
$("body").removeClass(on);
|
|
}
|
|
|
|
lastScrollTop = st;
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Reset menu
|
|
* @returns {mMenu}
|
|
*/
|
|
reset: function() {
|
|
}
|
|
};
|
|
|
|
// Run plugin
|
|
Plugin.run.apply(header, [options]);
|
|
|
|
//////////////////////
|
|
// ** Public API ** //
|
|
//////////////////////
|
|
|
|
/**
|
|
* Disable header for given time
|
|
* @returns {jQuery}
|
|
*/
|
|
header.publicMethod = function() {
|
|
//return Plugin.publicMethod();
|
|
};
|
|
|
|
// Return plugin instance
|
|
return header;
|
|
};
|
|
|
|
// Plugin default options
|
|
$.fn.mHeader.defaults = {
|
|
classic: false,
|
|
offset: {
|
|
mobile: 150,
|
|
desktop: 200
|
|
},
|
|
minimize: {
|
|
mobile: false,
|
|
desktop: false
|
|
}
|
|
};
|
|
}(jQuery));
|
|
(function($) {
|
|
|
|
// Plugin function
|
|
$.fn.mMenu = function(options) {
|
|
// Plugin scope variable
|
|
var menu = this;
|
|
var element = $(this);
|
|
|
|
// Plugin class
|
|
var Plugin = {
|
|
/**
|
|
* Run plugin
|
|
* @returns {mMenu}
|
|
*/
|
|
run: function(options, reinit) {
|
|
if (element.data('menu') && reinit !== true) {
|
|
menu = element.data('menu');
|
|
} else {
|
|
// reset menu
|
|
Plugin.init(options);
|
|
|
|
// reset menu
|
|
Plugin.reset();
|
|
|
|
// build menu
|
|
Plugin.build();
|
|
|
|
element.data('menu', menu);
|
|
}
|
|
|
|
return menu;
|
|
},
|
|
|
|
/**
|
|
* Handles submenu click toggle
|
|
* @returns {mMenu}
|
|
*/
|
|
init: function(options) {
|
|
menu.events = [];
|
|
|
|
// merge default and user defined options
|
|
menu.options = $.extend(true, {}, $.fn.mMenu.defaults, options);
|
|
|
|
// pause menu
|
|
menu.pauseDropdownHoverTime = 0;
|
|
},
|
|
|
|
/**
|
|
* Reset menu
|
|
* @returns {mMenu}
|
|
*/
|
|
build: function() {
|
|
element.on('click', '.m-menu__toggle', Plugin.handleSubmenuAccordion);
|
|
|
|
|
|
// dropdown mode(hoverable)
|
|
if (Plugin.getSubmenuMode() === 'dropdown' || Plugin.isConditionalSubmenuDropdown()) {
|
|
// dropdown submenu - hover toggle
|
|
element.on({mouseenter: Plugin.handleSubmenuDrodownHoverEnter, mouseleave: Plugin.handleSubmenuDrodownHoverExit}, '[data-menu-submenu-toggle="hover"]');
|
|
|
|
// dropdown submenu - click toggle
|
|
element.on('click', '[data-menu-submenu-toggle="click"] .m-menu__toggle', Plugin.handleSubmenuDropdownClick);
|
|
}
|
|
|
|
element.find('.m-menu__item:not(.m-menu__item--submenu) > .m-menu__link:not(.m-menu__toggle)').click(Plugin.handleLinkClick);
|
|
},
|
|
|
|
/**
|
|
* Reset menu
|
|
* @returns {mMenu}
|
|
*/
|
|
reset: function() {
|
|
// remove accordion handler
|
|
element.off('click', '.m-menu__toggle', Plugin.handleSubmenuAccordion);
|
|
|
|
// remove dropdown handlers
|
|
element.off({mouseenter: Plugin.handleSubmenuDrodownHoverEnter, mouseleave: Plugin.handleSubmenuDrodownHoverExit}, '[data-menu-submenu-toggle="hover"]');
|
|
element.off('click', '[data-menu-submenu-toggle="click"] .m-menu__toggle', Plugin.handleSubmenuDropdownClick);
|
|
|
|
// reset mobile menu attributes
|
|
menu.find('.m-menu__submenu, .m-menu__inner').css('display', '');
|
|
menu.find('.m-menu__item--hover').removeClass('m-menu__item--hover');
|
|
menu.find('.m-menu__item--open:not(.m-menu__item--expanded)').removeClass('m-menu__item--open');
|
|
},
|
|
|
|
/**
|
|
* Get submenu mode for current breakpoint and menu state
|
|
* @returns {mMenu}
|
|
*/
|
|
getSubmenuMode: function() {
|
|
if (mUtil.isInResponsiveRange('desktop')) {
|
|
if (mUtil.isset(menu.options.submenu, 'desktop.state.body')) {
|
|
if ($('body').hasClass(menu.options.submenu.desktop.state.body)) {
|
|
return menu.options.submenu.desktop.state.mode;
|
|
} else {
|
|
return menu.options.submenu.desktop.default;
|
|
}
|
|
} else if (mUtil.isset(menu.options.submenu, 'desktop') ){
|
|
return menu.options.submenu.desktop;
|
|
}
|
|
} else if (mUtil.isInResponsiveRange('tablet') && mUtil.isset(menu.options.submenu, 'tablet')) {
|
|
return menu.options.submenu.tablet;
|
|
} else if (mUtil.isInResponsiveRange('mobile') && mUtil.isset(menu.options.submenu, 'mobile')) {
|
|
return menu.options.submenu.mobile;
|
|
} else {
|
|
return false;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Get submenu mode for current breakpoint and menu state
|
|
* @returns {mMenu}
|
|
*/
|
|
isConditionalSubmenuDropdown: function() {
|
|
if (mUtil.isInResponsiveRange('desktop') && mUtil.isset(menu.options.submenu, 'desktop.state.body')) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handles menu link click
|
|
* @returns {mMenu}
|
|
*/
|
|
handleLinkClick: function(e) {
|
|
|
|
if (Plugin.eventTrigger('linkClick', $(this)) === false) {
|
|
e.preventDefault();
|
|
};
|
|
|
|
if (Plugin.getSubmenuMode() === 'dropdown' || Plugin.isConditionalSubmenuDropdown()) {
|
|
Plugin.handleSubmenuDropdownClose(e, $(this));
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handles submenu hover toggle
|
|
* @returns {mMenu}
|
|
*/
|
|
handleSubmenuDrodownHoverEnter: function(e) {
|
|
if (Plugin.getSubmenuMode() === 'accordion') {
|
|
return;
|
|
}
|
|
|
|
if (menu.resumeDropdownHover() === false) {
|
|
return;
|
|
}
|
|
|
|
var item = $(this);
|
|
|
|
Plugin.showSubmenuDropdown(item);
|
|
|
|
if (item.data('hover') == true) {
|
|
Plugin.hideSubmenuDropdown(item, false);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handles submenu hover toggle
|
|
* @returns {mMenu}
|
|
*/
|
|
handleSubmenuDrodownHoverExit: function(e) {
|
|
if (menu.resumeDropdownHover() === false) {
|
|
return;
|
|
}
|
|
|
|
if (Plugin.getSubmenuMode() === 'accordion') {
|
|
return;
|
|
}
|
|
|
|
var item = $(this);
|
|
var time = menu.options.dropdown.timeout;
|
|
|
|
var timeout = setTimeout(function() {
|
|
if (item.data('hover') == true) {
|
|
Plugin.hideSubmenuDropdown(item, true);
|
|
}
|
|
}, time);
|
|
|
|
item.data('hover', true);
|
|
item.data('timeout', timeout);
|
|
},
|
|
|
|
/**
|
|
* Handles submenu click toggle
|
|
* @returns {mMenu}
|
|
*/
|
|
handleSubmenuDropdownClick: function(e) {
|
|
if (Plugin.getSubmenuMode() === 'accordion') {
|
|
return;
|
|
}
|
|
|
|
var item = $(this).closest('.m-menu__item');
|
|
|
|
if (item.data('menu-submenu-mode') == 'accordion') {
|
|
return;
|
|
}
|
|
|
|
if (item.hasClass('m-menu__item--hover') == false) {
|
|
item.addClass('m-menu__item--open-dropdown');
|
|
Plugin.showSubmenuDropdown(item);
|
|
} else {
|
|
item.removeClass('m-menu__item--open-dropdown');
|
|
Plugin.hideSubmenuDropdown(item, true);
|
|
}
|
|
|
|
e.preventDefault();
|
|
},
|
|
|
|
/**
|
|
* Handles submenu dropdown close on link click
|
|
* @returns {mMenu}
|
|
*/
|
|
handleSubmenuDropdownClose: function(e, el) {
|
|
// exit if its not submenu dropdown mode
|
|
if (Plugin.getSubmenuMode() === 'accordion') {
|
|
return;
|
|
}
|
|
|
|
var shown = element.find('.m-menu__item.m-menu__item--submenu.m-menu__item--hover');
|
|
|
|
// check if currently clicked link's parent item ha
|
|
if (shown.length > 0 && el.hasClass('m-menu__toggle') === false && el.find('.m-menu__toggle').length === 0) {
|
|
// close opened dropdown menus
|
|
shown.each(function() {
|
|
Plugin.hideSubmenuDropdown($(this), true);
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* helper functions
|
|
* @returns {mMenu}
|
|
*/
|
|
handleSubmenuAccordion: function(e, el) {
|
|
var item = el ? $(el) : $(this);
|
|
|
|
if (Plugin.getSubmenuMode() === 'dropdown' && item.closest('.m-menu__item').data('menu-submenu-mode') != 'accordion') {
|
|
e.preventDefault();
|
|
return;
|
|
}
|
|
|
|
var li = item.closest('li');
|
|
var submenu = li.children('.m-menu__submenu, .m-menu__inner');
|
|
|
|
if (submenu.parent('.m-menu__item--expanded').length != 0) {
|
|
//return;
|
|
}
|
|
|
|
if (submenu.length > 0) {
|
|
e.preventDefault();
|
|
var speed = menu.options.accordion.slideSpeed;
|
|
var hasClosables = false;
|
|
|
|
if (li.hasClass('m-menu__item--open') === false) {
|
|
// hide other accordions
|
|
if (menu.options.accordion.expandAll === false) {
|
|
var closables = item.closest('.m-menu__nav, .m-menu__subnav').find('> .m-menu__item.m-menu__item--open.m-menu__item--submenu:not(.m-menu__item--expanded)');
|
|
closables.each(function() {
|
|
$(this).children('.m-menu__submenu').slideUp(speed, function() {
|
|
Plugin.scrollToItem(item);
|
|
});
|
|
$(this).removeClass('m-menu__item--open');
|
|
});
|
|
|
|
if (closables.length > 0) {
|
|
hasClosables = true;
|
|
}
|
|
}
|
|
|
|
if (hasClosables) {
|
|
submenu.slideDown(speed, function() {
|
|
Plugin.scrollToItem(item);
|
|
});
|
|
li.addClass('m-menu__item--open');
|
|
} else {
|
|
submenu.slideDown(speed, function() {
|
|
Plugin.scrollToItem(item);
|
|
});
|
|
li.addClass('m-menu__item--open');
|
|
}
|
|
} else {
|
|
submenu.slideUp(speed, function() {
|
|
Plugin.scrollToItem(item);
|
|
});
|
|
li.removeClass('m-menu__item--open');
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* scroll to item function
|
|
* @returns {mMenu}
|
|
*/
|
|
scrollToItem: function(item) {
|
|
// handle auto scroll for accordion submenus
|
|
if (mUtil.isInResponsiveRange('desktop') && menu.options.accordion.autoScroll && !element.data('menu-scrollable')) {
|
|
mApp.scrollToViewport(item);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* helper functions
|
|
* @returns {mMenu}
|
|
*/
|
|
hideSubmenuDropdown: function(item, classAlso) {
|
|
// remove submenu activation class
|
|
if (classAlso) {
|
|
item.removeClass('m-menu__item--hover');
|
|
}
|
|
// clear timeout
|
|
item.removeData('hover');
|
|
if (item.data('menu-dropdown-toggle-class')) {
|
|
$('body').removeClass(item.data('menu-dropdown-toggle-class'));
|
|
}
|
|
var timeout = item.data('timeout');
|
|
item.removeData('timeout');
|
|
clearTimeout(timeout);
|
|
},
|
|
|
|
/**
|
|
* helper functions
|
|
* @returns {mMenu}
|
|
*/
|
|
showSubmenuDropdown: function(item) {
|
|
// close active submenus
|
|
element.find('.m-menu__item--submenu.m-menu__item--hover').each(function() {
|
|
var el = $(this);
|
|
if (item.is(el) || el.find(item).length > 0 || item.find(el).length > 0) {
|
|
return;
|
|
} else {
|
|
Plugin.hideSubmenuDropdown(el, true);
|
|
}
|
|
});
|
|
|
|
// adjust submenu position
|
|
Plugin.adjustSubmenuDropdownArrowPos(item);
|
|
|
|
// add submenu activation class
|
|
item.addClass('m-menu__item--hover');
|
|
|
|
if (item.data('menu-dropdown-toggle-class')) {
|
|
$('body').addClass(item.data('menu-dropdown-toggle-class'));
|
|
}
|
|
|
|
// handle auto scroll for accordion submenus
|
|
if (Plugin.getSubmenuMode() === 'accordion' && menu.options.accordion.autoScroll) {
|
|
mApp.scrollTo(item.children('.m-menu__item--submenu'));
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handles submenu click toggle
|
|
* @returns {mMenu}
|
|
*/
|
|
resize: function(e) {
|
|
if (Plugin.getSubmenuMode() !== 'dropdown') {
|
|
return;
|
|
}
|
|
|
|
var resize = element.find('> .m-menu__nav > .m-menu__item--resize');
|
|
var submenu = resize.find('> .m-menu__submenu');
|
|
var breakpoint;
|
|
var currentWidth = mUtil.getViewPort().width;
|
|
var itemsNumber = element.find('> .m-menu__nav > .m-menu__item').length - 1;
|
|
var check;
|
|
|
|
if (
|
|
Plugin.getSubmenuMode() == 'dropdown' &&
|
|
(
|
|
(mUtil.isInResponsiveRange('desktop') && mUtil.isset(menu.options, 'resize.desktop') && (check = menu.options.resize.desktop) && currentWidth <= (breakpoint = resize.data('menu-resize-desktop-breakpoint'))) ||
|
|
(mUtil.isInResponsiveRange('tablet') && mUtil.isset(menu.options, 'resize.tablet') && (check = menu.options.resize.tablet) && currentWidth <= (breakpoint = resize.data('menu-resize-tablet-breakpoint'))) ||
|
|
(mUtil.isInResponsiveRange('mobile') && mUtil.isset(menu.options, 'resize.mobile') && (check = menu.options.resize.mobile) && currentWidth <= (breakpoint = resize.data('menu-resize-mobile-breakpoint')))
|
|
)
|
|
) {
|
|
|
|
var moved = submenu.find('> .m-menu__subnav > .m-menu__item').length; // currently move
|
|
var left = element.find('> .m-menu__nav > .m-menu__item:not(.m-menu__item--resize)').length; // currently left
|
|
var total = moved + left;
|
|
|
|
if (check.apply() === true) {
|
|
// return
|
|
if (moved > 0) {
|
|
submenu.find('> .m-menu__subnav > .m-menu__item').each(function() {
|
|
var item = $(this);
|
|
|
|
var elementsNumber = submenu.find('> .m-menu__nav > .m-menu__item:not(.m-menu__item--resize)').length;
|
|
element.find('> .m-menu__nav > .m-menu__item:not(.m-menu__item--resize)').eq(elementsNumber - 1).after(item);
|
|
|
|
if (check.apply() === false) {
|
|
item.appendTo(submenu.find('> .m-menu__subnav'));
|
|
return false;
|
|
}
|
|
|
|
moved--;
|
|
left++;
|
|
});
|
|
}
|
|
} else {
|
|
// move
|
|
if (left > 0) {
|
|
var items = element.find('> .m-menu__nav > .m-menu__item:not(.m-menu__item--resize)');
|
|
var index = items.length - 1;
|
|
|
|
for(var i = 0; i < items.length; i++) {
|
|
var item = $(items.get(index));
|
|
index--;
|
|
|
|
if (check.apply() === true) {
|
|
break;
|
|
}
|
|
|
|
item.appendTo(submenu.find('> .m-menu__subnav'));
|
|
|
|
moved++;
|
|
left--;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (moved > 0) {
|
|
resize.show();
|
|
} else {
|
|
resize.hide();
|
|
}
|
|
} else {
|
|
submenu.find('> .m-menu__subnav > .m-menu__item').each(function() {
|
|
var elementsNumber = submenu.find('> .m-menu__subnav > .m-menu__item').length;
|
|
element.find('> .m-menu__nav > .m-menu__item').get(elementsNumber).after($(this));
|
|
});
|
|
|
|
resize.hide();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handles submenu slide toggle
|
|
* @returns {mMenu}
|
|
*/
|
|
createSubmenuDropdownClickDropoff: function(el) {
|
|
var zIndex = el.find('> .m-menu__submenu').css('zIndex') - 1;
|
|
var dropoff = $('<div class="m-menu__dropoff" style="background: transparent; position: fixed; top: 0; bottom: 0; left: 0; right: 0; z-index: ' + zIndex + '"></div>');
|
|
$('body').after(dropoff);
|
|
dropoff.on('click', function(e) {
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
$(this).remove();
|
|
|
|
alert(1);
|
|
Plugin.hideSubmenuDropdown(el, true);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Handles submenu click toggle
|
|
* @returns {mMenu}
|
|
*/
|
|
adjustSubmenuDropdownArrowPos: function(item) {
|
|
var arrow = item.find('> .m-menu__submenu > .m-menu__arrow.m-menu__arrow--adjust');
|
|
var submenu = item.find('> .m-menu__submenu');
|
|
var subnav = item.find('> .m-menu__submenu > .m-menu__subnav');
|
|
|
|
if (arrow.length > 0) {
|
|
var pos;
|
|
var link = item.children('.m-menu__link');
|
|
|
|
if (submenu.hasClass('m-menu__submenu--classic') || submenu.hasClass('m-menu__submenu--fixed')) {
|
|
if (submenu.hasClass('m-menu__submenu--right')) {
|
|
pos = item.outerWidth() / 2;
|
|
if (submenu.hasClass('m-menu__submenu--pull')) {
|
|
pos = pos + Math.abs(parseInt(submenu.css('margin-right')));
|
|
}
|
|
pos = submenu.width() - pos;
|
|
} else if (submenu.hasClass('m-menu__submenu--left')) {
|
|
pos = item.outerWidth() / 2;
|
|
if (submenu.hasClass('m-menu__submenu--pull')) {
|
|
pos = pos + Math.abs(parseInt(submenu.css('margin-left')));
|
|
}
|
|
}
|
|
} else {
|
|
if (submenu.hasClass('m-menu__submenu--center') || submenu.hasClass('m-menu__submenu--full')) {
|
|
pos = item.offset().left - ((mUtil.getViewPort().width - submenu.outerWidth()) / 2);
|
|
pos = pos + (item.outerWidth() / 2);
|
|
} else if (submenu.hasClass('m-menu__submenu--left')) {
|
|
// to do
|
|
} else if (submenu.hasClass('m-menu__submenu--right')) {
|
|
// to do
|
|
}
|
|
}
|
|
|
|
arrow.css('left', pos);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handles submenu hover toggle
|
|
* @returns {mMenu}
|
|
*/
|
|
pauseDropdownHover: function(time) {
|
|
var date = new Date();
|
|
|
|
menu.pauseDropdownHoverTime = date.getTime() + time;
|
|
},
|
|
|
|
/**
|
|
* Handles submenu hover toggle
|
|
* @returns {mMenu}
|
|
*/
|
|
resumeDropdownHover: function() {
|
|
var date = new Date();
|
|
|
|
return (date.getTime() > menu.pauseDropdownHoverTime ? true : false);
|
|
},
|
|
|
|
/**
|
|
* Reset menu's current active item
|
|
* @returns {mMenu}
|
|
*/
|
|
resetActiveItem: function(item) {
|
|
element.find('.m-menu__item--active').each(function() {
|
|
$(this).removeClass('m-menu__item--active');
|
|
$(this).children('.m-menu__submenu').css('display', '');
|
|
|
|
$(this).parents('.m-menu__item--submenu').each(function() {
|
|
$(this).removeClass('m-menu__item--open');
|
|
$(this).children('.m-menu__submenu').css('display', '');
|
|
});
|
|
});
|
|
|
|
// close open submenus
|
|
if (menu.options.accordion.expandAll === false) {
|
|
element.find('.m-menu__item--open').each(function() {
|
|
$(this).removeClass('m-menu__item--open');
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Sets menu's active item
|
|
* @returns {mMenu}
|
|
*/
|
|
setActiveItem: function(item) {
|
|
// reset current active item
|
|
Plugin.resetActiveItem();
|
|
|
|
var item = $(item);
|
|
item.addClass('m-menu__item--active');
|
|
item.parents('.m-menu__item--submenu').each(function() {
|
|
$(this).addClass('m-menu__item--open');
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Returns page breadcrumbs for the menu's active item
|
|
* @returns {mMenu}
|
|
*/
|
|
getBreadcrumbs: function(item) {
|
|
var breadcrumbs = [];
|
|
var item = $(item);
|
|
var link = item.children('.m-menu__link');
|
|
|
|
breadcrumbs.push({
|
|
text: link.find('.m-menu__link-text').html(),
|
|
title: link.attr('title'),
|
|
href: link.attr('href')
|
|
});
|
|
|
|
item.parents('.m-menu__item--submenu').each(function() {
|
|
var submenuLink = $(this).children('.m-menu__link');
|
|
breadcrumbs.push({
|
|
text: submenuLink.find('.m-menu__link-text').html(),
|
|
title: submenuLink.attr('title'),
|
|
href: submenuLink.attr('href')
|
|
});
|
|
});
|
|
|
|
breadcrumbs.reverse();
|
|
|
|
return breadcrumbs;
|
|
},
|
|
|
|
/**
|
|
* Returns page title for the menu's active item
|
|
* @returns {mMenu}
|
|
*/
|
|
getPageTitle: function(item) {
|
|
item = $(item);
|
|
|
|
return item.children('.m-menu__link').find('.m-menu__link-text').html();
|
|
},
|
|
|
|
/**
|
|
* Sync
|
|
*/
|
|
sync: function () {
|
|
$(element).data('menu', menu);
|
|
},
|
|
|
|
/**
|
|
* Trigger events
|
|
*/
|
|
eventTrigger: function(name, args) {
|
|
for (i = 0; i < menu.events.length; i++) {
|
|
var event = menu.events[i];
|
|
if (event.name == name) {
|
|
if (event.one == true) {
|
|
if (event.fired == false) {
|
|
menu.events[i].fired = true;
|
|
return event.handler.call(this, menu, args);
|
|
}
|
|
} else {
|
|
return event.handler.call(this, menu, args);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
addEvent: function(name, handler, one) {
|
|
menu.events.push({
|
|
name: name,
|
|
handler: handler,
|
|
one: one,
|
|
fired: false
|
|
});
|
|
|
|
Plugin.sync();
|
|
}
|
|
};
|
|
|
|
// Run plugin
|
|
Plugin.run.apply(menu, [options]);
|
|
|
|
// Handle plugin on window resize
|
|
if (typeof(options) !== "undefined") {
|
|
$(window).resize(function() {
|
|
Plugin.run.apply(menu, [options, true]);
|
|
});
|
|
}
|
|
|
|
//////////////////////
|
|
// ** Public API ** //
|
|
//////////////////////
|
|
|
|
/**
|
|
* Set active menu item
|
|
*/
|
|
menu.setActiveItem = function(item) {
|
|
return Plugin.setActiveItem(item);
|
|
};
|
|
|
|
/**
|
|
* Set breadcrumb for menu item
|
|
*/
|
|
menu.getBreadcrumbs = function(item) {
|
|
return Plugin.getBreadcrumbs(item);
|
|
};
|
|
|
|
/**
|
|
* Set page title for menu item
|
|
*/
|
|
menu.getPageTitle = function(item) {
|
|
return Plugin.getPageTitle(item);
|
|
};
|
|
|
|
/**
|
|
* Get submenu mode
|
|
*/
|
|
menu.getSubmenuMode = function() {
|
|
return Plugin.getSubmenuMode();
|
|
};
|
|
|
|
/**
|
|
* Hide dropdown submenu
|
|
* @returns {jQuery}
|
|
*/
|
|
menu.hideDropdown = function(item) {
|
|
Plugin.hideSubmenuDropdown(item, true);
|
|
};
|
|
|
|
/**
|
|
* Disable menu for given time
|
|
* @returns {jQuery}
|
|
*/
|
|
menu.pauseDropdownHover = function(time) {
|
|
Plugin.pauseDropdownHover(time);
|
|
};
|
|
|
|
/**
|
|
* Disable menu for given time
|
|
* @returns {jQuery}
|
|
*/
|
|
menu.resumeDropdownHover = function() {
|
|
return Plugin.resumeDropdownHover();
|
|
};
|
|
|
|
/**
|
|
* Register event
|
|
*/
|
|
menu.on = function (name, handler) {
|
|
return Plugin.addEvent(name, handler);
|
|
};
|
|
|
|
// Return plugin instance
|
|
return menu;
|
|
};
|
|
|
|
// Plugin default options
|
|
$.fn.mMenu.defaults = {
|
|
// accordion submenu mode
|
|
accordion: {
|
|
slideSpeed: 200, // accordion toggle slide speed in milliseconds
|
|
autoScroll: true, // enable auto scrolling(focus) to the clicked menu item
|
|
expandAll: true // allow having multiple expanded accordions in the menu
|
|
},
|
|
|
|
// dropdown submenu mode
|
|
dropdown: {
|
|
timeout: 500 // timeout in milliseconds to show and hide the hoverable submenu dropdown
|
|
}
|
|
};
|
|
|
|
// Plugin global lazy initialization
|
|
$(document).on('click', function(e) {
|
|
$('.m-menu__nav .m-menu__item.m-menu__item--submenu.m-menu__item--hover[data-menu-submenu-toggle="click"]').each(function() {
|
|
var element = $(this).parent('.m-menu__nav').parent();
|
|
menu = element.mMenu();
|
|
|
|
if (menu.getSubmenuMode() !== 'dropdown') {
|
|
return;
|
|
}
|
|
|
|
if ($(e.target).is(element) == false && element.find($(e.target)).length == 0) {
|
|
var items = element.find('.m-menu__item--submenu.m-menu__item--hover[data-menu-submenu-toggle="click"]');
|
|
items.each(function() {
|
|
menu.hideDropdown($(this));
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}(jQuery));
|
|
(function ($) {
|
|
// Plugin function
|
|
$.fn.mMessenger = function (options) {
|
|
// Plugin scope variable
|
|
var messenger = {};
|
|
var element = $(this);
|
|
|
|
// Plugin class
|
|
var Plugin = {
|
|
/**
|
|
* Run
|
|
*/
|
|
run: function (options) {
|
|
if (!element.data('messenger')) {
|
|
// create instance
|
|
Plugin.init(options);
|
|
Plugin.build();
|
|
Plugin.setup();
|
|
|
|
// assign instance to the element
|
|
element.data('messenger', messenger);
|
|
} else {
|
|
// get instance from the element
|
|
messenger = element.data('messenger');
|
|
}
|
|
|
|
return messenger;
|
|
},
|
|
|
|
/**
|
|
* Initialize
|
|
*/
|
|
init: function(options) {
|
|
messenger.events = [];
|
|
messenger.scrollable = element.find('.m-messenger__scrollable');
|
|
messenger.options = $.extend(true, {}, $.fn.mMessenger.defaults, options);
|
|
if (messenger.scrollable.length > 0) {
|
|
if (messenger.scrollable.data('data-min-height')) {
|
|
messenger.options.minHeight = messenger.scrollable.data('data-min-height');
|
|
}
|
|
|
|
if (messenger.scrollable.data('data-max-height')) {
|
|
messenger.options.maxHeight = messenger.scrollable.data('data-max-height');
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Build DOM and init event handlers
|
|
*/
|
|
build: function () {
|
|
if (mUtil.isMobileDevice()) {
|
|
|
|
} else {
|
|
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Setup messenger
|
|
*/
|
|
setup: function () {
|
|
|
|
},
|
|
|
|
/**
|
|
* Trigger events
|
|
*/
|
|
eventTrigger: function(name) {
|
|
for (i = 0; i < messenger.events.length; i++) {
|
|
var event = messenger.events[i];
|
|
if (event.name == name) {
|
|
if (event.one == true) {
|
|
if (event.fired == false) {
|
|
messenger.events[i].fired = true;
|
|
return event.handler.call(this, messenger);
|
|
}
|
|
} else {
|
|
return event.handler.call(this, messenger);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
addEvent: function(name, handler, one) {
|
|
messenger.events.push({
|
|
name: name,
|
|
handler: handler,
|
|
one: one,
|
|
fired: false
|
|
});
|
|
|
|
Plugin.sync();
|
|
}
|
|
};
|
|
|
|
// Run plugin
|
|
Plugin.run.apply(this, [options]);
|
|
|
|
//////////////////////
|
|
// ** Public API ** //
|
|
//////////////////////
|
|
|
|
|
|
/**
|
|
* Set messenger content
|
|
* @returns {mMessenger}
|
|
*/
|
|
messenger.on = function (name, handler) {
|
|
return Plugin.addEvent(name, handler);
|
|
};
|
|
|
|
/**
|
|
* Set messenger content
|
|
* @returns {mMessenger}
|
|
*/
|
|
messenger.one = function (name, handler) {
|
|
return Plugin.addEvent(name, handler, true);
|
|
};
|
|
|
|
return messenger;
|
|
};
|
|
|
|
// default options
|
|
$.fn.mMessenger.defaults = {
|
|
|
|
};
|
|
}(jQuery));
|
|
(function($) {
|
|
// plugin setup
|
|
$.fn.mOffcanvas = function(options) {
|
|
// main object
|
|
var offcanvas = this;
|
|
var element = $(this);
|
|
|
|
/********************
|
|
** PRIVATE METHODS
|
|
********************/
|
|
var Plugin = {
|
|
/**
|
|
* Run
|
|
*/
|
|
run: function (options) {
|
|
if (!element.data('offcanvas')) {
|
|
// create instance
|
|
Plugin.init(options);
|
|
Plugin.build();
|
|
|
|
// assign instance to the element
|
|
element.data('offcanvas', offcanvas);
|
|
} else {
|
|
// get instance from the element
|
|
offcanvas = element.data('offcanvas');
|
|
}
|
|
|
|
return offcanvas;
|
|
},
|
|
|
|
/**
|
|
* Handles suboffcanvas click toggle
|
|
*/
|
|
init: function(options) {
|
|
offcanvas.events = [];
|
|
|
|
// merge default and user defined options
|
|
offcanvas.options = $.extend(true, {}, $.fn.mOffcanvas.defaults, options);
|
|
|
|
offcanvas.overlay;
|
|
|
|
offcanvas.classBase = offcanvas.options.class;
|
|
offcanvas.classShown = offcanvas.classBase + '--on';
|
|
offcanvas.classOverlay = offcanvas.classBase + '-overlay';
|
|
|
|
offcanvas.state = element.hasClass(offcanvas.classShown) ? 'shown' : 'hidden';
|
|
offcanvas.close = offcanvas.options.close;
|
|
|
|
if (offcanvas.options.toggle && offcanvas.options.toggle.target) {
|
|
offcanvas.toggleTarget = offcanvas.options.toggle.target;
|
|
offcanvas.toggleState = offcanvas.options.toggle.state;
|
|
} else {
|
|
offcanvas.toggleTarget = offcanvas.options.toggle;
|
|
offcanvas.toggleState = '';
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Setup offcanvas
|
|
*/
|
|
build: function() {
|
|
// offcanvas toggle
|
|
$(offcanvas.toggleTarget).on('click', Plugin.toggle);
|
|
|
|
if (offcanvas.close) {
|
|
$(offcanvas.close).on('click', Plugin.hide);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* sync
|
|
*/
|
|
sync: function () {
|
|
$(element).data('offcanvas', offcanvas);
|
|
},
|
|
|
|
/**
|
|
* Handles offcanvas click toggle
|
|
*/
|
|
toggle: function() {
|
|
if (offcanvas.state == 'shown') {
|
|
Plugin.hide();
|
|
} else {
|
|
Plugin.show();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handles offcanvas click toggle
|
|
*/
|
|
show: function() {
|
|
if (offcanvas.state == 'shown') {
|
|
return;
|
|
}
|
|
|
|
Plugin.eventTrigger('beforeShow');
|
|
|
|
if (offcanvas.toggleState != '') {
|
|
$(offcanvas.toggleTarget).addClass(offcanvas.toggleState);
|
|
}
|
|
|
|
$('body').addClass(offcanvas.classShown);
|
|
element.addClass(offcanvas.classShown);
|
|
|
|
offcanvas.state = 'shown';
|
|
|
|
if (offcanvas.options.overlay) {
|
|
var overlay = $('<div class="' + offcanvas.classOverlay + '"></div>');
|
|
element.after(overlay);
|
|
offcanvas.overlay = overlay;
|
|
offcanvas.overlay.on('click', function(e) {
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
Plugin.hide();
|
|
});
|
|
}
|
|
|
|
Plugin.eventTrigger('afterShow');
|
|
|
|
return offcanvas;
|
|
},
|
|
|
|
/**
|
|
* Handles offcanvas click toggle
|
|
*/
|
|
hide: function() {
|
|
if (offcanvas.state == 'hidden') {
|
|
return;
|
|
}
|
|
|
|
Plugin.eventTrigger('beforeHide');
|
|
|
|
if (offcanvas.toggleState != '') {
|
|
$(offcanvas.toggleTarget).removeClass(offcanvas.toggleState);
|
|
}
|
|
|
|
$('body').removeClass(offcanvas.classShown)
|
|
element.removeClass(offcanvas.classShown);
|
|
|
|
offcanvas.state = 'hidden';
|
|
|
|
if (offcanvas.options.overlay) {
|
|
offcanvas.overlay.remove();
|
|
}
|
|
|
|
Plugin.eventTrigger('afterHide');
|
|
|
|
return offcanvas;
|
|
},
|
|
|
|
/**
|
|
* Trigger events
|
|
*/
|
|
eventTrigger: function(name) {
|
|
for (i = 0; i < offcanvas.events.length; i++) {
|
|
var event = offcanvas.events[i];
|
|
if (event.name == name) {
|
|
if (event.one == true) {
|
|
if (event.fired == false) {
|
|
offcanvas.events[i].fired = true;
|
|
return event.handler.call(this, offcanvas);
|
|
}
|
|
} else {
|
|
return event.handler.call(this, offcanvas);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
addEvent: function(name, handler, one) {
|
|
offcanvas.events.push({
|
|
name: name,
|
|
handler: handler,
|
|
one: one,
|
|
fired: false
|
|
});
|
|
|
|
Plugin.sync();
|
|
}
|
|
};
|
|
|
|
// main variables
|
|
var the = this;
|
|
|
|
// init plugin
|
|
Plugin.run.apply(this, [options]);
|
|
|
|
/********************
|
|
** PUBLIC API METHODS
|
|
********************/
|
|
|
|
/**
|
|
* Hide
|
|
*/
|
|
offcanvas.hide = function () {
|
|
return Plugin.hide();
|
|
};
|
|
|
|
/**
|
|
* Show
|
|
*/
|
|
offcanvas.show = function () {
|
|
return Plugin.show();
|
|
};
|
|
|
|
/**
|
|
* Get suboffcanvas mode
|
|
*/
|
|
offcanvas.on = function (name, handler) {
|
|
return Plugin.addEvent(name, handler);
|
|
};
|
|
|
|
/**
|
|
* Set offcanvas content
|
|
* @returns {mOffcanvas}
|
|
*/
|
|
offcanvas.one = function (name, handler) {
|
|
return Plugin.addEvent(name, handler, true);
|
|
};
|
|
|
|
return offcanvas;
|
|
};
|
|
|
|
// default options
|
|
$.fn.mOffcanvas.defaults = {
|
|
|
|
};
|
|
}(jQuery));
|
|
(function ($) {
|
|
// Plugin function
|
|
$.fn.mPortlet = function (options) {
|
|
// Plugin scope variable
|
|
var portlet = {};
|
|
var element = $(this);
|
|
|
|
// Plugin class
|
|
var Plugin = {
|
|
/**
|
|
* Run
|
|
*/
|
|
run: function (options) {
|
|
if (element.data('portlet-object')) {
|
|
// get instance from the element
|
|
portlet = element.data('portlet-object');
|
|
} else {
|
|
// create instance
|
|
Plugin.init(options);
|
|
Plugin.build();
|
|
|
|
// assign instance to the element
|
|
element.data('portlet-object', portlet);
|
|
}
|
|
|
|
return portlet;
|
|
},
|
|
|
|
/**
|
|
* Initialize
|
|
*/
|
|
init: function(options) {
|
|
portlet.options = $.extend(true, {}, $.fn.mPortlet.defaults, options);
|
|
portlet.events = [];
|
|
portlet.eventOne = false;
|
|
|
|
if ( element.find('> .m-portlet__body').length !== 0 ) {
|
|
portlet.body = element.find('> .m-portlet__body');
|
|
} else if ( element.find('> .m-form').length !== 0 ) {
|
|
portlet.body = element.find('> .m-form');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Build DOM and init event handlers
|
|
*/
|
|
build: function () {
|
|
// remove
|
|
var remove = element.find('> .m-portlet__head [data-portlet-tool=remove]');
|
|
if (remove.length === 1) {
|
|
remove.click(function(e) {
|
|
e.preventDefault();
|
|
Plugin.remove();
|
|
});
|
|
}
|
|
|
|
// reload
|
|
var reload = element.find('> .m-portlet__head [data-portlet-tool=reload]')
|
|
if (reload.length === 1) {
|
|
reload.click(function(e) {
|
|
e.preventDefault();
|
|
Plugin.reload();
|
|
});
|
|
}
|
|
|
|
// toggle
|
|
var toggle = element.find('> .m-portlet__head [data-portlet-tool=toggle]');
|
|
if (toggle.length === 1) {
|
|
toggle.click(function(e) {
|
|
e.preventDefault();
|
|
Plugin.toggle();
|
|
});
|
|
}
|
|
|
|
// fullscreen
|
|
var fullscreen = element.find('> .m-portlet__head [data-portlet-tool=fullscreen]');
|
|
if (fullscreen.length === 1) {
|
|
fullscreen.click(function(e) {
|
|
e.preventDefault();
|
|
Plugin.fullscreen();
|
|
});
|
|
}
|
|
|
|
Plugin.setupTooltips();
|
|
},
|
|
|
|
/**
|
|
* Remove portlet
|
|
*/
|
|
remove: function () {
|
|
if (Plugin.eventTrigger('beforeRemove') === false) {
|
|
return;
|
|
}
|
|
|
|
if ( $('body').hasClass('m-portlet--fullscreen') && element.hasClass('m-portlet--fullscreen') ) {
|
|
Plugin.fullscreen('off');
|
|
}
|
|
|
|
Plugin.removeTooltips();
|
|
|
|
element.remove();
|
|
|
|
Plugin.eventTrigger('afterRemove');
|
|
},
|
|
|
|
/**
|
|
* Set content
|
|
*/
|
|
setContent: function (html) {
|
|
if (html) {
|
|
portlet.body.html(html);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Get body
|
|
*/
|
|
getBody: function () {
|
|
return portlet.body;
|
|
},
|
|
|
|
/**
|
|
* Get self
|
|
*/
|
|
getSelf: function () {
|
|
return element;
|
|
},
|
|
|
|
/**
|
|
* Setup tooltips
|
|
*/
|
|
setupTooltips: function () {
|
|
if (portlet.options.tooltips) {
|
|
var collapsed = element.hasClass('m-portlet--collapse') || element.hasClass('m-portlet--collapsed');
|
|
var fullscreenOn = $('body').hasClass('m-portlet--fullscreen') && element.hasClass('m-portlet--fullscreen');
|
|
|
|
var remove = element.find('> .m-portlet__head [data-portlet-tool=remove]');
|
|
if (remove.length === 1) {
|
|
remove.attr('title', portlet.options.tools.remove);
|
|
remove.data('placement', fullscreenOn ? 'bottom' : 'top');
|
|
remove.data('offset', fullscreenOn ? '0,10px,0,0' : '0,5px');
|
|
remove.tooltip('dispose');
|
|
mApp.initTooltip(remove);
|
|
}
|
|
|
|
var reload = element.find('> .m-portlet__head [data-portlet-tool=reload]');
|
|
if (reload.length === 1) {
|
|
reload.attr('title', portlet.options.tools.reload);
|
|
reload.data('placement', fullscreenOn ? 'bottom' : 'top');
|
|
reload.data('offset', fullscreenOn ? '0,10px,0,0' : '0,5px');
|
|
reload.tooltip('dispose');
|
|
mApp.initTooltip(reload);
|
|
}
|
|
|
|
var toggle = element.find('> .m-portlet__head [data-portlet-tool=toggle]');
|
|
if (toggle.length === 1) {
|
|
if (collapsed) {
|
|
toggle.attr('title', portlet.options.tools.toggle.expand);
|
|
} else {
|
|
toggle.attr('title', portlet.options.tools.toggle.collapse);
|
|
}
|
|
toggle.data('placement', fullscreenOn ? 'bottom' : 'top');
|
|
toggle.data('offset', fullscreenOn ? '0,10px,0,0' : '0,5px');
|
|
toggle.tooltip('dispose');
|
|
mApp.initTooltip(toggle);
|
|
}
|
|
|
|
var fullscreen = element.find('> .m-portlet__head [data-portlet-tool=fullscreen]');
|
|
if (fullscreen.length === 1) {
|
|
if (fullscreenOn) {
|
|
fullscreen.attr('title', portlet.options.tools.fullscreen.off);
|
|
} else {
|
|
fullscreen.attr('title', portlet.options.tools.fullscreen.on);
|
|
}
|
|
fullscreen.data('placement', fullscreenOn ? 'bottom' : 'top');
|
|
fullscreen.data('offset', fullscreenOn ? '0,10px,0,0' : '0,5px');
|
|
fullscreen.tooltip('dispose');
|
|
mApp.initTooltip(fullscreen);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Setup tooltips
|
|
*/
|
|
removeTooltips: function () {
|
|
if (portlet.options.tooltips) {
|
|
var remove = element.find('> .m-portlet__head [data-portlet-tool=remove]');
|
|
if (remove.length === 1) {
|
|
remove.tooltip('dispose');
|
|
}
|
|
|
|
var reload = element.find('> .m-portlet__head [data-portlet-tool=reload]');
|
|
if (reload.length === 1) {
|
|
reload.tooltip('dispose');
|
|
}
|
|
|
|
var toggle = element.find('> .m-portlet__head [data-portlet-tool=toggle]');
|
|
if (toggle.length === 1) {
|
|
toggle.tooltip('dispose');
|
|
}
|
|
|
|
var fullscreen = element.find('> .m-portlet__head [data-portlet-tool=fullscreen]');
|
|
if (fullscreen.length === 1) {
|
|
fullscreen.tooltip('dispose');
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Reload
|
|
*/
|
|
reload: function () {
|
|
Plugin.eventTrigger('reload');
|
|
},
|
|
|
|
/**
|
|
* Toggle
|
|
*/
|
|
toggle: function (mode) {
|
|
if (mode === 'collapse' || element.hasClass('m-portlet--collapse') || element.hasClass('m-portlet--collapsed')) {
|
|
if (Plugin.eventTrigger('beforeExpand') === false) {
|
|
return;
|
|
}
|
|
|
|
portlet.body.slideDown(portlet.options.bodyToggleSpeed, function(){
|
|
Plugin.eventTrigger('afterExpand');
|
|
});
|
|
|
|
element.removeClass('m-portlet--collapse');
|
|
element.removeClass('m-portlet--collapsed');
|
|
Plugin.setupTooltips();
|
|
|
|
} else {
|
|
if (Plugin.eventTrigger('beforeCollapse') === false) {
|
|
return;
|
|
}
|
|
|
|
portlet.body.slideUp(portlet.options.bodyToggleSpeed, function() {
|
|
Plugin.eventTrigger('afterCollapse');
|
|
});
|
|
|
|
element.addClass('m-portlet--collapse');
|
|
Plugin.setupTooltips();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Toggle
|
|
*/
|
|
fullscreen: function (mode) {
|
|
var d = {};
|
|
var speed = 300;
|
|
|
|
if (mode === 'off' || ($('body').hasClass('m-portlet--fullscreen') && element.hasClass('m-portlet--fullscreen'))) {
|
|
Plugin.eventTrigger('beforeFullscreenOff');
|
|
|
|
$('body').removeClass('m-portlet--fullscreen');
|
|
element.removeClass('m-portlet--fullscreen');
|
|
|
|
Plugin.setupTooltips();
|
|
|
|
Plugin.eventTrigger('afterFullscreenOff');
|
|
} else {
|
|
Plugin.eventTrigger('beforeFullscreenOn');
|
|
|
|
element.addClass('m-portlet--fullscreen');
|
|
$('body').addClass('m-portlet--fullscreen');
|
|
|
|
Plugin.setupTooltips();
|
|
|
|
Plugin.eventTrigger('afterFullscreenOn');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* sync
|
|
*/
|
|
sync: function () {
|
|
$(element).data('portlet', portlet);
|
|
},
|
|
|
|
/**
|
|
* Trigger events
|
|
*/
|
|
eventTrigger: function(name) {
|
|
for (i = 0; i < portlet.events.length; i++) {
|
|
var event = portlet.events[i];
|
|
if (event.name == name) {
|
|
if (event.one == true) {
|
|
if (event.fired == false) {
|
|
portlet.events[i].fired = true;
|
|
return event.handler.call(this, portlet);
|
|
}
|
|
} else {
|
|
return event.handler.call(this, portlet);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Add event
|
|
*/
|
|
addEvent: function(name, handler, one) {
|
|
portlet.events.push({
|
|
name: name,
|
|
handler: handler,
|
|
one: one,
|
|
fired: false
|
|
});
|
|
|
|
Plugin.sync();
|
|
|
|
return portlet;
|
|
}
|
|
};
|
|
|
|
// Run plugin
|
|
Plugin.run.apply(this, [options]);
|
|
|
|
//////////////////////
|
|
// ** Public API ** //
|
|
//////////////////////
|
|
|
|
/**
|
|
* Remove portlet
|
|
* @returns {mPortlet}
|
|
*/
|
|
portlet.remove = function () {
|
|
return Plugin.remove(html);
|
|
};
|
|
|
|
/**
|
|
* Reload portlet
|
|
* @returns {mPortlet}
|
|
*/
|
|
portlet.reload = function () {
|
|
return Plugin.reload();
|
|
};
|
|
|
|
/**
|
|
* Set portlet content
|
|
* @returns {mPortlet}
|
|
*/
|
|
portlet.setContent = function (html) {
|
|
return Plugin.setContent(html);
|
|
};
|
|
|
|
/**
|
|
* Collapse portlet
|
|
* @returns {mPortlet}
|
|
*/
|
|
portlet.collapse = function () {
|
|
return Plugin.toggle('collapse');
|
|
};
|
|
|
|
/**
|
|
* Expand portlet
|
|
* @returns {mPortlet}
|
|
*/
|
|
portlet.expand = function () {
|
|
return Plugin.toggle('expand');
|
|
};
|
|
|
|
/**
|
|
* Fullscreen portlet
|
|
* @returns {mPortlet}
|
|
*/
|
|
portlet.fullscreen = function () {
|
|
return Plugin.fullscreen('on');
|
|
};
|
|
|
|
/**
|
|
* Fullscreen portlet
|
|
* @returns {mPortlet}
|
|
*/
|
|
portlet.unFullscreen = function () {
|
|
return Plugin.fullscreen('off');
|
|
};
|
|
|
|
/**
|
|
* Get portletbody
|
|
* @returns {jQuery}
|
|
*/
|
|
portlet.getBody = function () {
|
|
return Plugin.getBody();
|
|
};
|
|
|
|
/**
|
|
* Get portletbody
|
|
* @returns {jQuery}
|
|
*/
|
|
portlet.getSelf = function () {
|
|
return Plugin.getSelf();
|
|
};
|
|
|
|
/**
|
|
* Set portlet content
|
|
* @returns {mPortlet}
|
|
*/
|
|
portlet.on = function (name, handler) {
|
|
return Plugin.addEvent(name, handler);
|
|
};
|
|
|
|
/**
|
|
* Set portlet content
|
|
* @returns {mPortlet}
|
|
*/
|
|
portlet.one = function (name, handler) {
|
|
return Plugin.addEvent(name, handler, true);
|
|
};
|
|
|
|
return portlet;
|
|
};
|
|
|
|
// default options
|
|
$.fn.mPortlet.defaults = {
|
|
bodyToggleSpeed: 400,
|
|
tooltips: true,
|
|
tools: {
|
|
toggle: {
|
|
collapse: 'Collapse',
|
|
expand: 'Expand'
|
|
},
|
|
reload: 'Reload',
|
|
remove: 'Remove',
|
|
fullscreen: {
|
|
on: 'Fullscreen',
|
|
off: 'Exit Fullscreen'
|
|
}
|
|
}
|
|
};
|
|
}(jQuery));
|
|
(function($) {
|
|
// Plugin function
|
|
$.fn.mQuicksearch = function(options) {
|
|
|
|
// Plugin scope variables
|
|
var qs = this;
|
|
var element = $(this);
|
|
|
|
// Plugin class
|
|
var Plugin = {
|
|
/**
|
|
* Run plugin
|
|
*/
|
|
run: function(options) {
|
|
if (!element.data('qs')) {
|
|
// init plugin
|
|
Plugin.init(options);
|
|
// build dom
|
|
Plugin.build();
|
|
// store the instance in the element's data
|
|
element.data('qs', qs);
|
|
} else {
|
|
// retrieve the instance fro the element's data
|
|
qs = element.data('qs');
|
|
}
|
|
|
|
return qs;
|
|
},
|
|
|
|
/**
|
|
* Init plugin
|
|
*/
|
|
init: function(options) {
|
|
// merge default and user defined options
|
|
qs.options = $.extend(true, {}, $.fn.mQuicksearch.defaults, options);
|
|
|
|
// form
|
|
qs.form = element.find('form');
|
|
|
|
// input element
|
|
qs.input = $(qs.options.input);
|
|
|
|
// close icon
|
|
qs.iconClose = $(qs.options.iconClose);
|
|
|
|
if (qs.options.type == 'default') {
|
|
// search icon
|
|
qs.iconSearch = $(qs.options.iconSearch);
|
|
|
|
// cancel icon
|
|
qs.iconCancel = $(qs.options.iconCancel);
|
|
}
|
|
|
|
// dropdown
|
|
qs.dropdown = element.mDropdown({mobileOverlay: false});
|
|
|
|
// cancel search timeout
|
|
qs.cancelTimeout;
|
|
|
|
// ajax processing state
|
|
qs.processing = false;
|
|
},
|
|
|
|
/**
|
|
* Build plugin
|
|
*/
|
|
build: function() {
|
|
// attach input keyup handler
|
|
qs.input.keyup(Plugin.handleSearch);
|
|
|
|
if (qs.options.type == 'default') {
|
|
qs.input.focus(Plugin.showDropdown);
|
|
|
|
qs.iconCancel.click(Plugin.handleCancel);
|
|
|
|
qs.iconSearch.click(function() {
|
|
if (mUtil.isInResponsiveRange('tablet-and-mobile')) {
|
|
$('body').addClass('m-header-search--mobile-expanded');
|
|
qs.input.focus();
|
|
}
|
|
});
|
|
|
|
qs.iconClose.click(function() {
|
|
if (mUtil.isInResponsiveRange('tablet-and-mobile')) {
|
|
$('body').removeClass('m-header-search--mobile-expanded');
|
|
Plugin.closeDropdown();
|
|
}
|
|
});
|
|
|
|
} else if (qs.options.type == 'dropdown') {
|
|
qs.dropdown.on('afterShow', function() {
|
|
qs.input.focus();
|
|
});
|
|
qs.iconClose.click(Plugin.closeDropdown);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Search handler
|
|
*/
|
|
handleSearch: function(e) {
|
|
var query = qs.input.val();
|
|
|
|
if (query.length === 0) {
|
|
qs.dropdown.hide();
|
|
Plugin.handleCancelIconVisibility('on');
|
|
Plugin.closeDropdown();
|
|
element.removeClass(qs.options.hasResultClass);
|
|
}
|
|
|
|
if (query.length < qs.options.minLength || qs.processing == true) {
|
|
return;
|
|
}
|
|
|
|
qs.processing = true;
|
|
qs.form.addClass(qs.options.spinner);
|
|
Plugin.handleCancelIconVisibility('off');
|
|
|
|
$.ajax({
|
|
url: qs.options.source,
|
|
data: {query: query},
|
|
dataType: 'html',
|
|
success: function(res) {
|
|
qs.processing = false;
|
|
qs.form.removeClass(qs.options.spinner);
|
|
Plugin.handleCancelIconVisibility('on');
|
|
qs.dropdown.setContent(res).show();
|
|
element.addClass(qs.options.hasResultClass);
|
|
},
|
|
error: function(res) {
|
|
qs.processing = false;
|
|
qs.form.removeClass(qs.options.spinner);
|
|
Plugin.handleCancelIconVisibility('on');
|
|
qs.dropdown.setContent(qs.options.templates.error.apply(qs, res)).show();
|
|
element.addClass(qs.options.hasResultClass);
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Handle cancel icon visibility
|
|
*/
|
|
handleCancelIconVisibility: function(status) {
|
|
if (qs.options.type == 'dropdown') {
|
|
return;
|
|
}
|
|
|
|
if (status == 'on') {
|
|
if (qs.input.val().length === 0) {
|
|
qs.iconCancel.css('visibility', 'hidden');
|
|
qs.iconClose.css('visibility', 'hidden');
|
|
} else {
|
|
clearTimeout(qs.cancelTimeout);
|
|
qs.cancelTimeout = setTimeout(function() {
|
|
qs.iconCancel.css('visibility', 'visible');
|
|
qs.iconClose.css('visibility', 'visible');
|
|
}, 500);
|
|
}
|
|
} else {
|
|
qs.iconCancel.css('visibility', 'hidden');
|
|
qs.iconClose.css('visibility', 'hidden');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Cancel handler
|
|
*/
|
|
handleCancel: function(e) {
|
|
qs.input.val('');
|
|
qs.iconCancel.css('visibility', 'hidden');
|
|
element.removeClass(qs.options.hasResultClass);
|
|
//qs.input.focus();
|
|
|
|
Plugin.closeDropdown();
|
|
},
|
|
|
|
/**
|
|
* Cancel handler
|
|
*/
|
|
closeDropdown: function() {
|
|
qs.dropdown.hide();
|
|
},
|
|
|
|
/**
|
|
* Show dropdown
|
|
*/
|
|
showDropdown: function(e) {
|
|
if (qs.dropdown.isShown() == false && qs.input.val().length > qs.options.minLength && qs.processing == false) {
|
|
qs.dropdown.show();
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
}
|
|
};
|
|
|
|
// Run plugin
|
|
Plugin.run.apply(qs, [options]);
|
|
|
|
//////////////////////
|
|
// ** Public API ** //
|
|
//////////////////////
|
|
|
|
/**
|
|
* Public method
|
|
* @returns {mQuicksearch}
|
|
*/
|
|
qs.test = function(time) {
|
|
//Plugin.method(time);
|
|
};
|
|
|
|
// Return plugin object
|
|
return qs;
|
|
};
|
|
|
|
// Plugin default options
|
|
$.fn.mQuicksearch.defaults = {
|
|
minLength: 1,
|
|
maxHeight: 300,
|
|
};
|
|
|
|
}(jQuery));
|
|
(function($) {
|
|
// plugin setup
|
|
$.fn.mScrollTop = function(options) {
|
|
// main object
|
|
var scrollTop = this;
|
|
var element = $(this);
|
|
|
|
/********************
|
|
** PRIVATE METHODS
|
|
********************/
|
|
var Plugin = {
|
|
/**
|
|
* Run
|
|
*/
|
|
run: function (options) {
|
|
if (!element.data('scrollTop')) {
|
|
// create instance
|
|
Plugin.init(options);
|
|
Plugin.build();
|
|
|
|
// assign instance to the element
|
|
element.data('scrollTop', scrollTop);
|
|
} else {
|
|
// get instance from the element
|
|
scrollTop = element.data('scrollTop');
|
|
}
|
|
|
|
return scrollTop;
|
|
},
|
|
|
|
/**
|
|
* Handles subscrollTop click scrollTop
|
|
*/
|
|
init: function(options) {
|
|
scrollTop.element = element;
|
|
scrollTop.events = [];
|
|
|
|
// merge default and user defined options
|
|
scrollTop.options = $.extend(true, {}, $.fn.mScrollTop.defaults, options);
|
|
},
|
|
|
|
/**
|
|
* Setup scrollTop
|
|
*/
|
|
build: function() {
|
|
// handle window scroll
|
|
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
|
|
$(window).bind("touchend touchcancel touchleave", function() {
|
|
Plugin.handle();
|
|
});
|
|
} else {
|
|
$(window).scroll(function() {
|
|
Plugin.handle();
|
|
});
|
|
}
|
|
|
|
// handle button click
|
|
element.on('click', Plugin.scroll);
|
|
},
|
|
|
|
/**
|
|
* sync
|
|
*/
|
|
sync: function () {
|
|
$(element).data('scrollTop', scrollTop);
|
|
},
|
|
|
|
/**
|
|
* Handles offcanvas click scrollTop
|
|
*/
|
|
handle: function() {
|
|
var pos = $(window).scrollTop(); // current vertical position
|
|
if (pos > scrollTop.options.offset) {
|
|
$("body").addClass('m-scroll-top--shown');
|
|
} else {
|
|
$("body").removeClass('m-scroll-top--shown');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handles offcanvas click scrollTop
|
|
*/
|
|
scroll: function(e) {
|
|
e.preventDefault();
|
|
|
|
$("html, body").animate({
|
|
scrollTop: 0
|
|
}, scrollTop.options.speed);
|
|
},
|
|
|
|
/**
|
|
* Trigger events
|
|
*/
|
|
eventTrigger: function(name) {
|
|
for (i = 0; i < scrollTop.events.length; i++) {
|
|
var event = scrollTop.events[i];
|
|
if (event.name == name) {
|
|
if (event.one == true) {
|
|
if (event.fired == false) {
|
|
scrollTop.events[i].fired = true;
|
|
return event.handler.call(this, scrollTop);
|
|
}
|
|
} else {
|
|
return event.handler.call(this, scrollTop);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
addEvent: function(name, handler, one) {
|
|
scrollTop.events.push({
|
|
name: name,
|
|
handler: handler,
|
|
one: one,
|
|
fired: false
|
|
});
|
|
|
|
Plugin.sync();
|
|
}
|
|
};
|
|
|
|
// main variables
|
|
var the = this;
|
|
|
|
// init plugin
|
|
Plugin.run.apply(this, [options]);
|
|
|
|
/********************
|
|
** PUBLIC API METHODS
|
|
********************/
|
|
|
|
/**
|
|
* Get subscrollTop mode
|
|
*/
|
|
scrollTop.on = function (name, handler) {
|
|
return Plugin.addEvent(name, handler);
|
|
};
|
|
|
|
/**
|
|
* Set scrollTop content
|
|
* @returns {mScrollTop}
|
|
*/
|
|
scrollTop.one = function (name, handler) {
|
|
return Plugin.addEvent(name, handler, true);
|
|
};
|
|
|
|
return scrollTop;
|
|
};
|
|
|
|
// default options
|
|
$.fn.mScrollTop.defaults = {
|
|
offset: 300,
|
|
speed: 600
|
|
};
|
|
}(jQuery));
|
|
(function($) {
|
|
// plugin setup
|
|
$.fn.mToggle = function(options) {
|
|
// main object
|
|
var toggle = this;
|
|
var element = $(this);
|
|
|
|
/********************
|
|
** PRIVATE METHODS
|
|
********************/
|
|
var Plugin = {
|
|
/**
|
|
* Run
|
|
*/
|
|
run: function (options) {
|
|
if (!element.data('toggle')) {
|
|
// create instance
|
|
Plugin.init(options);
|
|
Plugin.build();
|
|
|
|
// assign instance to the element
|
|
element.data('toggle', toggle);
|
|
} else {
|
|
// get instance from the element
|
|
toggle = element.data('toggle');
|
|
}
|
|
|
|
return toggle;
|
|
},
|
|
|
|
/**
|
|
* Handles subtoggle click toggle
|
|
*/
|
|
init: function(options) {
|
|
toggle.element = element;
|
|
toggle.events = [];
|
|
|
|
// merge default and user defined options
|
|
toggle.options = $.extend(true, {}, $.fn.mToggle.defaults, options);
|
|
|
|
toggle.target = $(toggle.options.target);
|
|
toggle.targetState = toggle.options.targetState;
|
|
toggle.togglerState = toggle.options.togglerState;
|
|
|
|
toggle.state = mUtil.hasClasses(toggle.target, toggle.targetState) ? 'on' : 'off';
|
|
},
|
|
|
|
/**
|
|
* Setup toggle
|
|
*/
|
|
build: function() {
|
|
element.on('click', Plugin.toggle);
|
|
},
|
|
|
|
/**
|
|
* sync
|
|
*/
|
|
sync: function () {
|
|
$(element).data('toggle', toggle);
|
|
},
|
|
|
|
/**
|
|
* Handles offcanvas click toggle
|
|
*/
|
|
toggle: function() {
|
|
if (toggle.state == 'off') {
|
|
Plugin.toggleOn();
|
|
} else {
|
|
Plugin.toggleOff();
|
|
}
|
|
Plugin.eventTrigger('toggle');
|
|
|
|
return toggle;
|
|
},
|
|
|
|
/**
|
|
* Handles toggle click toggle
|
|
*/
|
|
toggleOn: function() {
|
|
Plugin.eventTrigger('beforeOn');
|
|
|
|
toggle.target.addClass(toggle.targetState);
|
|
|
|
if (toggle.togglerState) {
|
|
element.addClass(toggle.togglerState);
|
|
}
|
|
|
|
toggle.state = 'on';
|
|
|
|
Plugin.eventTrigger('afterOn');
|
|
|
|
return toggle;
|
|
},
|
|
|
|
/**
|
|
* Handles toggle click toggle
|
|
*/
|
|
toggleOff: function() {
|
|
Plugin.eventTrigger('beforeOff');
|
|
|
|
toggle.target.removeClass(toggle.targetState);
|
|
|
|
if (toggle.togglerState) {
|
|
element.removeClass(toggle.togglerState);
|
|
}
|
|
|
|
toggle.state = 'off';
|
|
|
|
Plugin.eventTrigger('afterOff');
|
|
|
|
return toggle;
|
|
},
|
|
|
|
/**
|
|
* Trigger events
|
|
*/
|
|
eventTrigger: function(name) {
|
|
toggle.trigger(name);
|
|
for (i = 0; i < toggle.events.length; i++) {
|
|
var event = toggle.events[i];
|
|
if (event.name == name) {
|
|
if (event.one == true) {
|
|
if (event.fired == false) {
|
|
toggle.events[i].fired = true;
|
|
return event.handler.call(this, toggle);
|
|
}
|
|
} else {
|
|
return event.handler.call(this, toggle);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
addEvent: function(name, handler, one) {
|
|
toggle.events.push({
|
|
name: name,
|
|
handler: handler,
|
|
one: one,
|
|
fired: false
|
|
});
|
|
|
|
Plugin.sync();
|
|
|
|
return toggle;
|
|
}
|
|
};
|
|
|
|
// main variables
|
|
var the = this;
|
|
|
|
// init plugin
|
|
Plugin.run.apply(this, [options]);
|
|
|
|
/********************
|
|
** PUBLIC API METHODS
|
|
********************/
|
|
|
|
/**
|
|
* Toggle
|
|
*/
|
|
toggle.toggle = function () {
|
|
return Plugin.toggle();
|
|
};
|
|
|
|
/**
|
|
* Toggle on
|
|
*/
|
|
toggle.toggleOn = function () {
|
|
return Plugin.toggleOn();
|
|
};
|
|
|
|
/**
|
|
* Toggle off
|
|
*/
|
|
toggle.toggleOff = function () {
|
|
return Plugin.toggleOff();
|
|
};
|
|
|
|
/**
|
|
* Attach event
|
|
* @returns {mToggle}
|
|
*/
|
|
toggle.on = function (name, handler) {
|
|
return Plugin.addEvent(name, handler);
|
|
};
|
|
|
|
/**
|
|
* Attach event that will be fired once
|
|
* @returns {mToggle}
|
|
*/
|
|
toggle.one = function (name, handler) {
|
|
return Plugin.addEvent(name, handler, true);
|
|
};
|
|
|
|
return toggle;
|
|
};
|
|
|
|
// default options
|
|
$.fn.mToggle.defaults = {
|
|
togglerState: '',
|
|
targetState: ''
|
|
};
|
|
}(jQuery));
|
|
(function($) {
|
|
// plugin setup
|
|
$.fn.mWizard = function(options) {
|
|
//== Main object
|
|
var wizard = this;
|
|
var element = $(this);
|
|
|
|
/********************
|
|
** PRIVATE METHODS
|
|
********************/
|
|
var Plugin = {
|
|
/**
|
|
* Run
|
|
*/
|
|
run: function (options) {
|
|
if (!element.data('wizard')) {
|
|
//== Create instance
|
|
Plugin.init(options);
|
|
Plugin.build();
|
|
|
|
//== Assign instance to the element
|
|
element.data('wizard', wizard);
|
|
} else {
|
|
// get instance from the element
|
|
wizard = element.data('wizard');
|
|
}
|
|
|
|
return wizard;
|
|
},
|
|
|
|
/**
|
|
* Initialize Form Wizard
|
|
*/
|
|
init: function(options) {
|
|
//== Elements
|
|
wizard.steps = wizard.find('.m-wizard__step');
|
|
wizard.progress = wizard.find('.m-wizard__progress .progress-bar');
|
|
wizard.btnSubmit = wizard.find('[data-wizard-action="submit"]');
|
|
wizard.btnNext = wizard.find('[data-wizard-action="next"]');
|
|
wizard.btnPrev = wizard.find('[data-wizard-action="prev"]');
|
|
wizard.btnLast = wizard.find('[data-wizard-action="last"]');
|
|
wizard.btnFirst = wizard.find('[data-wizard-action="first"]');
|
|
|
|
//== Merge default and user defined options
|
|
wizard.options = $.extend(true, {}, $.fn.mWizard.defaults, options);
|
|
|
|
//== Variables
|
|
wizard.events = [];
|
|
wizard.currentStep = 1;
|
|
wizard.totalSteps = wizard.steps.length;
|
|
|
|
//== Init current step
|
|
if (wizard.options.startStep > 1) {
|
|
Plugin.goTo(wizard.options.startStep);
|
|
}
|
|
|
|
//== Init UI
|
|
Plugin.updateUI();
|
|
},
|
|
|
|
/**
|
|
* Build Form Wizard
|
|
*/
|
|
build: function() {
|
|
//== Next button event handler
|
|
wizard.btnNext.on('click', function (e) {
|
|
e.preventDefault();
|
|
Plugin.goNext();
|
|
});
|
|
|
|
//== Prev button event handler
|
|
wizard.btnPrev.on('click', function (e) {
|
|
e.preventDefault();
|
|
Plugin.goPrev();
|
|
});
|
|
|
|
//== First button event handler
|
|
wizard.btnFirst.on('click', function (e) {
|
|
e.preventDefault();
|
|
Plugin.goFirst();
|
|
});
|
|
|
|
//== Last button event handler
|
|
wizard.btnLast.on('click', function (e) {
|
|
e.preventDefault();
|
|
Plugin.goLast();
|
|
});
|
|
|
|
wizard.find('.m-wizard__step a.m-wizard__step-number').on('click', function() {
|
|
var step = $(this).parents('.m-wizard__step');
|
|
var num;
|
|
$(this).parents('.m-wizard__steps').find('.m-wizard__step').each(function(index) {
|
|
if (step.is( $(this) )) {
|
|
num = (index + 1);
|
|
return;
|
|
}
|
|
});
|
|
|
|
if (num) {
|
|
Plugin.goTo(num);
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Sync object instance
|
|
*/
|
|
sync: function () {
|
|
$(element).data('wizard', wizard);
|
|
},
|
|
|
|
/**
|
|
* Handles wizard click toggle
|
|
*/
|
|
goTo: function(number) {
|
|
//== Skip if this step is already shown
|
|
if (number === wizard.currentStep) {
|
|
return;
|
|
}
|
|
|
|
//== Validate step number
|
|
if (number) {
|
|
number = parseInt(number);
|
|
} else {
|
|
number = Plugin.getNextStep();
|
|
}
|
|
|
|
//== Before next and prev events
|
|
var callback;
|
|
|
|
if (number > wizard.currentStep) {
|
|
callback = Plugin.eventTrigger('beforeNext');
|
|
} else {
|
|
callback = Plugin.eventTrigger('beforePrev');
|
|
}
|
|
|
|
//== Continue if no exit
|
|
if (callback !== false) {
|
|
//== Set current step
|
|
wizard.currentStep = number;
|
|
|
|
//== Update UI
|
|
Plugin.updateUI();
|
|
|
|
//== Trigger change event
|
|
Plugin.eventTrigger('change')
|
|
}
|
|
|
|
//== After next and prev events
|
|
if (number > wizard.startStep) {
|
|
Plugin.eventTrigger('afterNext');
|
|
} else {
|
|
Plugin.eventTrigger('afterPrev');
|
|
}
|
|
|
|
return wizard;
|
|
},
|
|
|
|
updateUI: function(argument) {
|
|
//== Update progress bar
|
|
Plugin.updateProgress();
|
|
|
|
//== Show current target content
|
|
Plugin.handleTarget();
|
|
|
|
//== Set classes
|
|
Plugin.setStepClass();
|
|
|
|
//== Apply nav step classes
|
|
wizard.find('.m-wizard__step').removeClass('m-wizard__step--current').removeClass('m-wizard__step--done');
|
|
for (var i = 1; i < wizard.currentStep; i++) {
|
|
wizard.find('.m-wizard__step').eq(i - 1).addClass('m-wizard__step--done');
|
|
}
|
|
wizard.find('.m-wizard__step').eq(wizard.currentStep - 1).addClass('m-wizard__step--current');
|
|
},
|
|
|
|
/**
|
|
* Check last step
|
|
*/
|
|
isLastStep: function() {
|
|
return wizard.currentStep === wizard.totalSteps;
|
|
},
|
|
|
|
/**
|
|
* Check first step
|
|
*/
|
|
isFirstStep: function() {
|
|
return wizard.currentStep === 1;
|
|
},
|
|
|
|
/**
|
|
* Check between step
|
|
*/
|
|
isBetweenStep: function() {
|
|
return Plugin.isLastStep() === false && Plugin.isFirstStep() === false;
|
|
},
|
|
|
|
/**
|
|
* Set step class
|
|
*/
|
|
setStepClass: function() {
|
|
if (Plugin.isLastStep()) {
|
|
element.addClass('m-wizard--step-last');
|
|
} else {
|
|
element.removeClass('m-wizard--step-last');
|
|
}
|
|
|
|
if (Plugin.isFirstStep()) {
|
|
element.addClass('m-wizard--step-first');
|
|
} else {
|
|
element.removeClass('m-wizard--step-first');
|
|
}
|
|
|
|
if (Plugin.isBetweenStep()) {
|
|
element.addClass('m-wizard--step-between');
|
|
} else {
|
|
element.removeClass('m-wizard--step-between');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Go to the next step
|
|
*/
|
|
goNext: function() {
|
|
return Plugin.goTo( Plugin.getNextStep() );
|
|
},
|
|
|
|
/**
|
|
* Go to the prev step
|
|
*/
|
|
goPrev: function() {
|
|
return Plugin.goTo( Plugin.getPrevStep() );
|
|
},
|
|
|
|
/**
|
|
* Go to the last step
|
|
*/
|
|
goLast: function() {
|
|
return Plugin.goTo( wizard.totalSteps );
|
|
},
|
|
|
|
/**
|
|
* Go to the first step
|
|
*/
|
|
goFirst: function() {
|
|
return Plugin.goTo( 1 );
|
|
},
|
|
|
|
/**
|
|
* Set progress
|
|
*/
|
|
updateProgress: function() {
|
|
//== Calculate progress position
|
|
|
|
if (!wizard.progress) {
|
|
return;
|
|
}
|
|
|
|
//== Update progress
|
|
if (element.hasClass('m-wizard--1')) {
|
|
var width = 100 * ((wizard.currentStep) / (wizard.totalSteps));
|
|
var offset = element.find('.m-wizard__step-number').width();
|
|
wizard.progress.css('width', 'calc(' + width + '% + ' + (offset / 2) + 'px)');
|
|
} else if (element.hasClass('m-wizard--2')) {
|
|
if (wizard.currentStep === 1) {
|
|
return;
|
|
}
|
|
|
|
var step = element.find('.m-wizard__step').eq(0);
|
|
var progress = (wizard.currentStep - 1) * (100 * (1 / (wizard.totalSteps - 1)));
|
|
|
|
if (mUtil.isInResponsiveRange('minimal-desktop-and-below')) {
|
|
wizard.progress.css('height', progress + '%');
|
|
} else {
|
|
wizard.progress.css('width', progress + '%');
|
|
}
|
|
} else {
|
|
var width = 100 * ((wizard.currentStep) / (wizard.totalSteps));
|
|
wizard.progress.css('width', width + '%');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Show/hide target content
|
|
*/
|
|
handleTarget: function() {
|
|
var step = wizard.steps.eq(wizard.currentStep - 1);
|
|
var target = element.find( step.data('wizard-target') );
|
|
|
|
element.find('.m-wizard__form-step--current').removeClass('m-wizard__form-step--current');
|
|
target.addClass('m-wizard__form-step--current');
|
|
},
|
|
|
|
/**
|
|
* Get next step
|
|
*/
|
|
getNextStep: function() {
|
|
if (wizard.totalSteps >= (wizard.currentStep + 1)) {
|
|
return wizard.currentStep + 1;
|
|
} else {
|
|
return wizard.totalSteps;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Get prev step
|
|
*/
|
|
getPrevStep: function() {
|
|
if ((wizard.currentStep - 1) >= 1) {
|
|
return wizard.currentStep - 1;
|
|
} else {
|
|
return 1;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Trigger event
|
|
*/
|
|
eventTrigger: function(name) {
|
|
for (i = 0; i < wizard.events.length; i++) {
|
|
var event = wizard.events[i];
|
|
if (event.name == name) {
|
|
if (event.one == true) {
|
|
if (event.fired == false) {
|
|
wizard.events[i].fired = true;
|
|
return event.handler.call(this, wizard);
|
|
}
|
|
} else {
|
|
return event.handler.call(this, wizard);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Register event
|
|
*/
|
|
addEvent: function(name, handler, one) {
|
|
wizard.events.push({
|
|
name: name,
|
|
handler: handler,
|
|
one: one,
|
|
fired: false
|
|
});
|
|
|
|
Plugin.sync();
|
|
}
|
|
};
|
|
|
|
//== Main variables
|
|
var the = this;
|
|
|
|
//== Init plugin
|
|
Plugin.run.apply(this, [options]);
|
|
|
|
/********************
|
|
** PUBLIC API METHODS
|
|
********************/
|
|
|
|
/**
|
|
* Go to the next step
|
|
*/
|
|
wizard.goNext = function () {
|
|
return Plugin.goNext();
|
|
};
|
|
|
|
/**
|
|
* Go to the prev step
|
|
*/
|
|
wizard.goPrev = function () {
|
|
return Plugin.goPrev();
|
|
};
|
|
|
|
/**
|
|
* Go to the last step
|
|
*/
|
|
wizard.goLast = function () {
|
|
return Plugin.goLast();
|
|
};
|
|
|
|
/**
|
|
* Go to the first step
|
|
*/
|
|
wizard.goFirst = function () {
|
|
return Plugin.goFirst();
|
|
};
|
|
|
|
/**
|
|
* Go to a step
|
|
*/
|
|
wizard.goTo = function ( number ) {
|
|
return Plugin.goTo( number );
|
|
};
|
|
|
|
/**
|
|
* Get current step number
|
|
*/
|
|
wizard.getStep = function () {
|
|
return wizard.currentStep;
|
|
};
|
|
|
|
/**
|
|
* Check last step
|
|
*/
|
|
wizard.isLastStep = function () {
|
|
return Plugin.isLastStep();
|
|
};
|
|
|
|
/**
|
|
* Check first step
|
|
*/
|
|
wizard.isFirstStep = function () {
|
|
return Plugin.isFirstStep();
|
|
};
|
|
|
|
/**
|
|
* Attach event
|
|
* @returns {mwizard}
|
|
*/
|
|
wizard.on = function (name, handler) {
|
|
return Plugin.addEvent(name, handler);
|
|
};
|
|
|
|
/**
|
|
* Attach event that will be fired once
|
|
* @returns {mwizard}
|
|
*/
|
|
wizard.one = function (name, handler) {
|
|
return Plugin.addEvent(name, handler, true);
|
|
};
|
|
|
|
return wizard;
|
|
};
|
|
|
|
//== Default options
|
|
$.fn.mWizard.defaults = {
|
|
startStep: 1
|
|
};
|
|
}(jQuery));
|
|
|
|
$.fn.markdown.defaults.iconlibrary = 'fa';
|
|
//$.fn.bootstrapSwitch.defaults.size = 'large';
|
|
//$.fn.bootstrapSwitch.defaults.onColor = 'success';
|
|
$.fn.timepicker.defaults = $.extend(true, {}, $.fn.timepicker.defaults, {
|
|
icons: {
|
|
up: 'la la-angle-up',
|
|
down: 'la la-angle-down'
|
|
}
|
|
});
|
|
jQuery.validator.setDefaults({
|
|
errorElement: 'div', //default input error message container
|
|
errorClass: 'form-control-feedback', // default input error message class
|
|
focusInvalid: false, // do not focus the last invalid input
|
|
ignore: "", // validate all fields including form hidden input
|
|
|
|
errorPlacement: function(error, element) { // render error placement for each input type
|
|
var group = $(element).closest('.m-form__group-sub').length > 0 ? $(element).closest('.m-form__group-sub') : $(element).closest('.m-form__group');
|
|
var help = group.find('.m-form__help');
|
|
|
|
if (group.find('.form-control-feedback').length !== 0) {
|
|
return;
|
|
}
|
|
|
|
if (help.length > 0) {
|
|
help.before(error);
|
|
} else {
|
|
if ($(element).closest('.input-group').length > 0) {
|
|
$(element).closest('.input-group').after(error);
|
|
} else {
|
|
if ($(element).is(':checkbox')) {
|
|
$(element).closest('.m-checkbox').find('>span').after(error);
|
|
} else {
|
|
$(element).after(error);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
highlight: function(element) { // hightlight error inputs
|
|
var group = $(element).closest('.m-form__group-sub').length > 0 ? $(element).closest('.m-form__group-sub') : $(element).closest('.m-form__group');
|
|
|
|
console.log('add' + group.attr('class'));
|
|
|
|
group.addClass('has-danger'); // set error class to the control groupx
|
|
},
|
|
|
|
unhighlight: function(element) { // revert the change done by hightlight
|
|
var group = $(element).closest('.m-form__group-sub').length > 0 ? $(element).closest('.m-form__group-sub') : $(element).closest('.m-form__group');
|
|
|
|
group.removeClass('has-danger'); // set error class to the control group
|
|
},
|
|
|
|
success: function(label, element) {
|
|
var group = $(label).closest('.m-form__group-sub').length > 0 ? $(label).closest('.m-form__group-sub') : $(label).closest('.m-form__group');
|
|
|
|
//group.addClass('has-success').removeClass('has-danger'); // set success class and hide error class
|
|
group.removeClass('has-danger'); // hide error class
|
|
group.find('.form-control-feedback').remove();
|
|
}
|
|
});
|
|
Chart.elements.Rectangle.prototype.draw = function() {
|
|
var ctx = this._chart.ctx;
|
|
var vm = this._view;
|
|
var left, right, top, bottom, signX, signY, borderSkipped, radius;
|
|
var borderWidth = vm.borderWidth;
|
|
|
|
// Set Radius Here
|
|
// If radius is large enough to cause drawing errors a max radius is imposed
|
|
var cornerRadius = this._chart.options.barRadius ? this._chart.options.barRadius : 0;
|
|
|
|
if (!vm.horizontal) {
|
|
// bar
|
|
left = vm.x - vm.width / 2;
|
|
right = vm.x + vm.width / 2;
|
|
|
|
if (vm.y > 2 * cornerRadius) {
|
|
top = vm.y - cornerRadius;
|
|
} else {
|
|
top = vm.y;
|
|
}
|
|
|
|
bottom = vm.base;
|
|
signX = 1;
|
|
signY = bottom > top? 1: -1;
|
|
borderSkipped = vm.borderSkipped || 'bottom';
|
|
//console.log(vm.base + '-' + vm.y);
|
|
} else {
|
|
// horizontal bar
|
|
left = vm.base;
|
|
right = vm.x;
|
|
top = vm.y - vm.height / 2;
|
|
bottom = vm.y + vm.height / 2;
|
|
signX = right > left? 1: -1;
|
|
signY = 1;
|
|
borderSkipped = vm.borderSkipped || 'left';
|
|
}
|
|
|
|
// Canvas doesn't allow us to stroke inside the width so we can
|
|
// adjust the sizes to fit if we're setting a stroke on the line
|
|
if (borderWidth) {
|
|
// borderWidth shold be less than bar width and bar height.
|
|
var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom));
|
|
borderWidth = borderWidth > barSize? barSize: borderWidth;
|
|
var halfStroke = borderWidth / 2;
|
|
// Adjust borderWidth when bar top position is near vm.base(zero).
|
|
var borderLeft = left + (borderSkipped !== 'left'? halfStroke * signX: 0);
|
|
var borderRight = right + (borderSkipped !== 'right'? -halfStroke * signX: 0);
|
|
var borderTop = top + (borderSkipped !== 'top'? halfStroke * signY: 0);
|
|
var borderBottom = bottom + (borderSkipped !== 'bottom'? -halfStroke * signY: 0);
|
|
// not become a vertical line?
|
|
if (borderLeft !== borderRight) {
|
|
top = borderTop;
|
|
bottom = borderBottom;
|
|
}
|
|
// not become a horizontal line?
|
|
if (borderTop !== borderBottom) {
|
|
left = borderLeft;
|
|
right = borderRight;
|
|
}
|
|
}
|
|
|
|
ctx.beginPath();
|
|
ctx.fillStyle = vm.backgroundColor;
|
|
ctx.strokeStyle = vm.borderColor;
|
|
ctx.lineWidth = borderWidth;
|
|
|
|
// Corner points, from bottom-left to bottom-right clockwise
|
|
// | 1 2 |
|
|
// | 0 3 |
|
|
var corners = [
|
|
[left, bottom],
|
|
[left, top],
|
|
[right, top],
|
|
[right, bottom]
|
|
];
|
|
|
|
// Find first (starting) corner with fallback to 'bottom'
|
|
var borders = ['bottom', 'left', 'top', 'right'];
|
|
var startCorner = borders.indexOf(borderSkipped, 0);
|
|
if (startCorner === -1) {
|
|
startCorner = 0;
|
|
}
|
|
|
|
function cornerAt(index) {
|
|
return corners[(startCorner + index) % 4];
|
|
}
|
|
|
|
// Draw rectangle from 'startCorner'
|
|
var corner = cornerAt(0);
|
|
ctx.moveTo(corner[0], corner[1]);
|
|
|
|
for (var i = 1; i < 4; i++) {
|
|
corner = cornerAt(i);
|
|
nextCornerId = i+1;
|
|
if(nextCornerId == 4){
|
|
nextCornerId = 0
|
|
}
|
|
|
|
nextCorner = cornerAt(nextCornerId);
|
|
|
|
width = corners[2][0] - corners[1][0];
|
|
height = corners[0][1] - corners[1][1];
|
|
x = corners[1][0];
|
|
y = corners[1][1];
|
|
|
|
var radius = cornerRadius;
|
|
|
|
// Fix radius being too large
|
|
if(radius > height/2){
|
|
radius = height/2;
|
|
}if(radius > width/2){
|
|
radius = width/2;
|
|
}
|
|
|
|
ctx.moveTo(x + radius, y);
|
|
ctx.lineTo(x + width - radius, y);
|
|
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
|
|
ctx.lineTo(x + width, y + height - radius);
|
|
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
|
|
ctx.lineTo(x + radius, y + height);
|
|
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
|
|
ctx.lineTo(x, y + radius);
|
|
ctx.quadraticCurveTo(x, y, x + radius, y);
|
|
}
|
|
|
|
ctx.fill();
|
|
if (borderWidth) {
|
|
ctx.stroke();
|
|
}
|
|
};
|
|
(function($) {
|
|
|
|
$.fn.mDatatable = $.fn.mDatatable || {};
|
|
|
|
/**
|
|
* @param datatable Main datatable plugin instance
|
|
* @param options Extension options
|
|
* @returns {*}
|
|
*/
|
|
$.fn.mDatatable.checkbox = function(datatable, options) {
|
|
|
|
var Extension = {
|
|
selectedAllRows: false,
|
|
selectedRows: [],
|
|
unselectedRows: [],
|
|
|
|
init: function() {
|
|
if (Extension.selectorEnabled()) {
|
|
// requestIds is not null
|
|
if (options.vars.requestIds) {
|
|
// request ids in response
|
|
datatable.setDataSourceParam(options.vars.requestIds, true);
|
|
}
|
|
|
|
// select all on extension init
|
|
Extension.selectedAllRows = datatable.getDataSourceParam(options.vars.selectedAllRows);
|
|
|
|
$(datatable).on('m-datatable--on-layout-updated', function(e, args) {
|
|
if (args.table != $(datatable.wrap).attr('id')) return;
|
|
datatable.ready(function() {
|
|
Extension.initVars();
|
|
Extension.initEvent();
|
|
Extension.initSelect();
|
|
});
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Init checkbox clicks event
|
|
*/
|
|
initEvent: function() {
|
|
// select all checkbox click
|
|
$(datatable.tableHead).find('.m-checkbox--all > [type="checkbox"]').click(function(e) {
|
|
// clear selected and unselected rows
|
|
Extension.selectedRows = Extension.unselectedRows = [];
|
|
datatable.stateRemove('checkbox');
|
|
|
|
// select all rows
|
|
if ($(this).is(':checked')) {
|
|
Extension.selectedAllRows = true;
|
|
} else {
|
|
Extension.selectedAllRows = false;
|
|
}
|
|
|
|
// local select all current page rows
|
|
if (!options.vars.requestIds) {
|
|
if ($(this).is(':checked')) {
|
|
Extension.selectedRows = $.makeArray($(datatable.tableBody).find('.m-checkbox--single > [type="checkbox"]').
|
|
map(function(i, chk) {
|
|
return $(chk).val();
|
|
}));
|
|
}
|
|
var storage = {};
|
|
storage['selectedRows'] = $.unique(Extension.selectedRows);
|
|
datatable.stateKeep('checkbox', storage);
|
|
}
|
|
|
|
// keep selectedAllRows in datasource params
|
|
datatable.setDataSourceParam(options.vars.selectedAllRows, Extension.selectedAllRows);
|
|
|
|
$(datatable).trigger('m-datatable--on-click-checkbox', [$(this)]);
|
|
});
|
|
|
|
// single row checkbox click
|
|
$(datatable.tableBody).find('.m-checkbox--single > [type="checkbox"]').click(function(e) {
|
|
var id = $(this).val();
|
|
if ($(this).is(':checked')) {
|
|
Extension.selectedRows.push(id);
|
|
// remove from unselected rows
|
|
Extension.unselectedRows = Extension.remove(Extension.unselectedRows, id);
|
|
} else {
|
|
Extension.unselectedRows.push(id);
|
|
// remove from selected rows
|
|
Extension.selectedRows = Extension.remove(Extension.selectedRows, id);
|
|
}
|
|
|
|
// local checkbox header check
|
|
if (!options.vars.requestIds && Extension.selectedRows.length < 1) {
|
|
// remove select all checkbox, if there is no checked checkbox left
|
|
$(datatable.tableHead).find('.m-checkbox--all > [type="checkbox"]').prop('checked', false);
|
|
}
|
|
|
|
var storage = {};
|
|
storage['selectedRows'] = $.unique(Extension.selectedRows);
|
|
storage['unselectedRows'] = $.unique(Extension.unselectedRows);
|
|
datatable.stateKeep('checkbox', storage);
|
|
|
|
$(datatable).trigger('m-datatable--on-click-checkbox', [$(this)]);
|
|
});
|
|
},
|
|
|
|
initSelect: function() {
|
|
// selected all rows from server
|
|
if (Extension.selectedAllRows && options.vars.requestIds) {
|
|
if (!datatable.hasClass('m-datatable--error')) {
|
|
// set header select all checkbox checked
|
|
$(datatable.tableHead).find('.m-checkbox--all > [type="checkbox"]').prop('checked', true);
|
|
}
|
|
|
|
// set all checkbox in table body
|
|
datatable.setActiveAll(true);
|
|
|
|
// remove unselected rows
|
|
Extension.unselectedRows.forEach(function(id) {
|
|
datatable.setInactive(id);
|
|
});
|
|
|
|
} else {
|
|
// single check for server and local
|
|
Extension.selectedRows.forEach(function(id) {
|
|
datatable.setActive(id);
|
|
});
|
|
|
|
// local checkbox; check if all checkboxes of currect page are checked
|
|
if (!datatable.hasClass('m-datatable--error') && $(datatable.tableBody).find('.m-checkbox--single > [type="checkbox"]').not(':checked').length < 1) {
|
|
// set header select all checkbox checked
|
|
$(datatable.tableHead).find('.m-checkbox--all > [type="checkbox"]').prop('checked', true);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Check if selector is enabled from options
|
|
*/
|
|
selectorEnabled: function() {
|
|
return $.grep(datatable.options.columns, function(n, i) {
|
|
return n.selector || false;
|
|
})[0];
|
|
},
|
|
|
|
initVars: function() {
|
|
// get single select/unselect from localstorage
|
|
var storage = datatable.stateGet('checkbox');
|
|
if (typeof storage !== 'undefined') {
|
|
Extension.selectedRows = storage['selectedRows'] || [];
|
|
Extension.unselectedRows = storage['unselectedRows'] || [];
|
|
}
|
|
},
|
|
|
|
getSelectedId: function(path) {
|
|
Extension.initVars();
|
|
|
|
// server selected all rows
|
|
if (Extension.selectedAllRows && options.vars.requestIds) {
|
|
if (typeof path === 'undefined') path = options.vars.rowIds;
|
|
|
|
// if selected all rows, return id from response meta
|
|
var selectedAllRows = datatable.getObject(path, datatable.lastResponse) || [];
|
|
|
|
if (selectedAllRows.length > 0) {
|
|
// remove single unselected rows from selectedAllRows ids from server response emta
|
|
Extension.unselectedRows.forEach(function(id) {
|
|
selectedAllRows = Extension.remove(selectedAllRows, parseInt(id));
|
|
});
|
|
}
|
|
return selectedAllRows;
|
|
}
|
|
|
|
// else return single checked selected rows
|
|
return Extension.selectedRows;
|
|
},
|
|
|
|
remove: function(array, element) {
|
|
return array.filter(function(e) {
|
|
return e !== element;
|
|
});
|
|
},
|
|
};
|
|
|
|
// make the extension accessible from datatable init
|
|
datatable.checkbox = function() {
|
|
return Extension;
|
|
};
|
|
|
|
if (typeof options === 'object') {
|
|
options = $.extend(true, {}, $.fn.mDatatable.checkbox.default, options);
|
|
Extension.init.apply(this, [options]);
|
|
}
|
|
|
|
return datatable;
|
|
};
|
|
|
|
$.fn.mDatatable.checkbox.default = {
|
|
vars: {
|
|
// select all rows flag to be sent to the server
|
|
selectedAllRows: 'selectedAllRows',
|
|
// request id parameter's name
|
|
requestIds: 'requestIds',
|
|
// response path to all rows id
|
|
rowIds: 'meta.rowIds',
|
|
},
|
|
};
|
|
|
|
}(jQuery));
|
|
//== Set defaults
|
|
|
|
$.notifyDefaults({
|
|
template: '' +
|
|
'<div data-notify="container" class="alert alert-{0} m-alert" role="alert">' +
|
|
'<button type="button" aria-hidden="true" class="close" data-notify="dismiss"></button>' +
|
|
'<span data-notify="icon"></span>' +
|
|
'<span data-notify="title">{1}</span>' +
|
|
'<span data-notify="message">{2}</span>' +
|
|
'<div class="progress" data-notify="progressbar">' +
|
|
'<div class="progress-bar progress-bar-animated bg-{0}" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div>' +
|
|
'</div>' +
|
|
'<a href="{3}" target="{4}" data-notify="url"></a>' +
|
|
'</div>'
|
|
});
|
|
//== Set defaults
|
|
swal.setDefaults({
|
|
width: 400,
|
|
padding: '2.5rem',
|
|
buttonsStyling: false,
|
|
confirmButtonClass: 'btn btn-success m-btn m-btn--custom',
|
|
confirmButtonColor: null,
|
|
cancelButtonClass: 'btn btn-secondary m-btn m-btn--custom',
|
|
cancelButtonColor: null
|
|
});
|
|
var mLayout = function() {
|
|
var horMenu;
|
|
var asideMenu;
|
|
var asideMenuOffcanvas;
|
|
var horMenuOffcanvas;
|
|
|
|
var initStickyHeader = function() {
|
|
var header = $('.m-header');
|
|
var options = {
|
|
offset: {},
|
|
minimize:{}
|
|
};
|
|
|
|
if (header.data('minimize-mobile') == 'hide') {
|
|
options.minimize.mobile = {};
|
|
options.minimize.mobile.on = 'm-header--hide';
|
|
options.minimize.mobile.off = 'm-header--show';
|
|
} else {
|
|
options.minimize.mobile = false;
|
|
}
|
|
|
|
if (header.data('minimize') == 'hide') {
|
|
options.minimize.desktop = {};
|
|
options.minimize.desktop.on = 'm-header--hide';
|
|
options.minimize.desktop.off = 'm-header--show';
|
|
} else {
|
|
options.minimize.desktop = false;
|
|
}
|
|
|
|
if (header.data('minimize-offset')) {
|
|
options.offset.desktop = header.data('minimize-offset');
|
|
}
|
|
|
|
if (header.data('minimize-mobile-offset')) {
|
|
options.offset.mobile = header.data('minimize-mobile-offset');
|
|
}
|
|
|
|
header.mHeader(options);
|
|
}
|
|
|
|
// handle horizontal menu
|
|
var initHorMenu = function() {
|
|
// init aside left offcanvas
|
|
horMenuOffcanvas = $('#m_header_menu').mOffcanvas({
|
|
class: 'm-aside-header-menu-mobile',
|
|
overlay: true,
|
|
close: '#m_aside_header_menu_mobile_close_btn',
|
|
toggle: {
|
|
target: '#m_aside_header_menu_mobile_toggle',
|
|
state: 'm-brand__toggler--active'
|
|
}
|
|
});
|
|
|
|
horMenu = $('#m_header_menu').mMenu({
|
|
// submenu modes
|
|
submenu: {
|
|
desktop: 'dropdown',
|
|
tablet: 'accordion',
|
|
mobile: 'accordion'
|
|
},
|
|
// resize menu on window resize
|
|
resize: {
|
|
desktop: function() {
|
|
var headerNavWidth = $('#m_header_nav').width();
|
|
var headerMenuWidth = $('#m_header_menu_container').width();
|
|
var headerTopbarWidth = $('#m_header_topbar').width();
|
|
var spareWidth = 20;
|
|
|
|
if ((headerMenuWidth + headerTopbarWidth + spareWidth) > headerNavWidth ) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// handle vertical menu
|
|
var initLeftAsideMenu = function() {
|
|
var menu = $('#m_ver_menu');
|
|
|
|
// init aside menu
|
|
var menuOptions = {
|
|
// submenu setup
|
|
submenu: {
|
|
desktop: {
|
|
// by default the menu mode set to accordion in desktop mode
|
|
default: (menu.data('menu-dropdown') == true ? 'dropdown' : 'accordion'),
|
|
// whenever body has this class switch the menu mode to dropdown
|
|
state: {
|
|
body: 'm-aside-left--minimize',
|
|
mode: 'dropdown'
|
|
}
|
|
},
|
|
tablet: 'accordion', // menu set to accordion in tablet mode
|
|
mobile: 'accordion' // menu set to accordion in mobile mode
|
|
},
|
|
|
|
//accordion setup
|
|
accordion: {
|
|
autoScroll: true,
|
|
expandAll: false
|
|
}
|
|
};
|
|
|
|
asideMenu = menu.mMenu(menuOptions);
|
|
|
|
// handle fixed aside menu
|
|
if (menu.data('menu-scrollable')) {
|
|
function initScrollableMenu(obj) {
|
|
if (mUtil.isInResponsiveRange('tablet-and-mobile')) {
|
|
// destroy if the instance was previously created
|
|
mApp.destroyScroller(obj);
|
|
return;
|
|
}
|
|
|
|
var height = mUtil.getViewPort().height - $('.m-header').outerHeight()
|
|
- ($('.m-aside-left .m-aside__header').length != 0 ? $('.m-aside-left .m-aside__header').outerHeight() : 0)
|
|
- ($('.m-aside-left .m-aside__footer').length != 0 ? $('.m-aside-left .m-aside__footer').outerHeight() : 0);
|
|
//- $('.m-footer').outerHeight();
|
|
|
|
// create/re-create a new instance
|
|
mApp.initScroller(obj, {height: height});
|
|
}
|
|
|
|
initScrollableMenu(asideMenu);
|
|
|
|
mUtil.addResizeHandler(function() {
|
|
initScrollableMenu(asideMenu);
|
|
});
|
|
}
|
|
}
|
|
|
|
// handle vertical menu
|
|
var initLeftAside = function() {
|
|
// init aside left offcanvas
|
|
var asideOffcanvasClass = ($('#m_aside_left').hasClass('m-aside-left--offcanvas-default') ? 'm-aside-left--offcanvas-default' : 'm-aside-left');
|
|
|
|
asideMenuOffcanvas = $('#m_aside_left').mOffcanvas({
|
|
class: asideOffcanvasClass,
|
|
overlay: true,
|
|
close: '#m_aside_left_close_btn',
|
|
toggle: {
|
|
target: '#m_aside_left_offcanvas_toggle',
|
|
state: 'm-brand__toggler--active'
|
|
}
|
|
});
|
|
}
|
|
|
|
// handle sidebar toggle
|
|
var initLeftAsideToggle = function() {
|
|
var asideLeftToggle = $('#m_aside_left_minimize_toggle').mToggle({
|
|
target: 'body',
|
|
targetState: 'm-brand--minimize m-aside-left--minimize',
|
|
togglerState: 'm-brand__toggler--active'
|
|
}).on('toggle', function() {
|
|
horMenu.pauseDropdownHover(800);
|
|
asideMenu.pauseDropdownHover(800);
|
|
});
|
|
|
|
//== Example: minimize the left aside on page load
|
|
//== asideLeftToggle.toggleOn();
|
|
|
|
$('#m_aside_left_hide_toggle').mToggle({
|
|
target: 'body',
|
|
targetState: 'm-aside-left--hide',
|
|
togglerState: 'm-brand__toggler--active'
|
|
}).on('toggle', function() {
|
|
horMenu.pauseDropdownHover(800);
|
|
asideMenu.pauseDropdownHover(800);
|
|
})
|
|
}
|
|
|
|
var initTopbar = function() {
|
|
$('#m_aside_header_topbar_mobile_toggle').click(function() {
|
|
$('body').toggleClass('m-topbar--on');
|
|
});
|
|
|
|
// Animated Notification Icon
|
|
setInterval(function() {
|
|
$('#m_topbar_notification_icon .m-nav__link-icon').addClass('m-animate-shake');
|
|
$('#m_topbar_notification_icon .m-nav__link-badge').addClass('m-animate-blink');
|
|
}, 3000);
|
|
|
|
setInterval(function() {
|
|
$('#m_topbar_notification_icon .m-nav__link-icon').removeClass('m-animate-shake');
|
|
$('#m_topbar_notification_icon .m-nav__link-badge').removeClass('m-animate-blink');
|
|
}, 6000);
|
|
}
|
|
|
|
// handle quick search
|
|
var initQuicksearch = function() {
|
|
var qs = $('#m_quicksearch');
|
|
|
|
qs.mQuicksearch({
|
|
type: qs.data('search-type'), // quick search type
|
|
source: 'http://keenthemes.com/metronic/preview/inc/api/quick_search.php',
|
|
spinner: 'm-loader m-loader--skin-light m-loader--right',
|
|
|
|
input: '#m_quicksearch_input',
|
|
iconClose: '#m_quicksearch_close',
|
|
iconCancel: '#m_quicksearch_cancel',
|
|
iconSearch: '#m_quicksearch_search',
|
|
|
|
hasResultClass: 'm-list-search--has-result',
|
|
minLength: 1,
|
|
templates: {
|
|
error: function(qs) {
|
|
return '<div class="m-search-results m-search-results--skin-light"><span class="m-search-result__message">Something went wrong</div></div>';
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
var initScrollTop = function() {
|
|
$('[data-toggle="m-scroll-top"]').mScrollTop({
|
|
offset: 300,
|
|
speed: 600
|
|
});
|
|
}
|
|
|
|
return {
|
|
init: function() {
|
|
this.initHeader();
|
|
this.initAside();
|
|
},
|
|
|
|
initHeader: function() {
|
|
initStickyHeader();
|
|
initHorMenu();
|
|
initTopbar();
|
|
initQuicksearch();
|
|
initScrollTop();
|
|
},
|
|
|
|
initAside: function() {
|
|
initLeftAside();
|
|
initLeftAsideMenu();
|
|
initLeftAsideToggle();
|
|
|
|
this.onLeftSidebarToggle(function(e) {
|
|
var datatables = $('.m-datatable');
|
|
$(datatables).each(function() {
|
|
$(this).mDatatable('redraw');
|
|
});
|
|
});
|
|
},
|
|
|
|
getAsideMenu: function() {
|
|
return asideMenu;
|
|
},
|
|
|
|
onLeftSidebarToggle: function(func) {
|
|
$('#m_aside_left_minimize_toggle').mToggle().on('toggle', func);
|
|
},
|
|
|
|
closeMobileAsideMenuOffcanvas: function() {
|
|
if (mUtil.isMobileDevice()) {
|
|
asideMenuOffcanvas.hide();
|
|
}
|
|
},
|
|
|
|
closeMobileHorMenuOffcanvas: function() {
|
|
if (mUtil.isMobileDevice()) {
|
|
horMenuOffcanvas.hide();
|
|
}
|
|
}
|
|
};
|
|
}();
|
|
|
|
$(document).ready(function() {
|
|
if (mUtil.isAngularVersion() === false) {
|
|
mLayout.init();
|
|
}
|
|
});
|
|
|
|
|
|
var mQuickSidebar = function() {
|
|
var topbarAside = $('#m_quick_sidebar');
|
|
var topbarAsideTabs = $('#m_quick_sidebar_tabs');
|
|
var topbarAsideClose = $('#m_quick_sidebar_close');
|
|
var topbarAsideToggle = $('#m_quick_sidebar_toggle');
|
|
var topbarAsideContent = topbarAside.find('.m-quick-sidebar__content');
|
|
|
|
var initMessages = function() {
|
|
var init = function() {
|
|
var messenger = $('#m_quick_sidebar_tabs_messenger');
|
|
var messengerMessages = messenger.find('.m-messenger__messages');
|
|
|
|
var height = topbarAside.outerHeight(true) -
|
|
topbarAsideTabs.outerHeight(true) -
|
|
messenger.find('.m-messenger__form').outerHeight(true) - 120;
|
|
|
|
// init messages scrollable content
|
|
messengerMessages.css('height', height);
|
|
mApp.initScroller(messengerMessages, {});
|
|
}
|
|
|
|
init();
|
|
|
|
// reinit on window resize
|
|
mUtil.addResizeHandler(init);
|
|
}
|
|
|
|
var initSettings = function() {
|
|
// init dropdown tabbable content
|
|
var init = function() {
|
|
var settings = $('#m_quick_sidebar_tabs_settings');
|
|
var height = mUtil.getViewPort().height - topbarAsideTabs.outerHeight(true) - 60;
|
|
|
|
// init settings scrollable content
|
|
settings.css('height', height);
|
|
mApp.initScroller(settings, {});
|
|
}
|
|
|
|
init();
|
|
|
|
// reinit on window resize
|
|
mUtil.addResizeHandler(init);
|
|
}
|
|
|
|
var initLogs = function() {
|
|
// init dropdown tabbable content
|
|
var init = function() {
|
|
var logs = $('#m_quick_sidebar_tabs_logs');
|
|
var height = mUtil.getViewPort().height - topbarAsideTabs.outerHeight(true) - 60;
|
|
|
|
// init settings scrollable content
|
|
logs.css('height', height);
|
|
mApp.initScroller(logs, {});
|
|
}
|
|
|
|
init();
|
|
|
|
// reinit on window resize
|
|
mUtil.addResizeHandler(init);
|
|
}
|
|
|
|
var initOffcanvasTabs = function() {
|
|
initMessages();
|
|
initSettings();
|
|
initLogs();
|
|
}
|
|
|
|
var initOffcanvas = function() {
|
|
topbarAside.mOffcanvas({
|
|
class: 'm-quick-sidebar',
|
|
overlay: true,
|
|
close: topbarAsideClose,
|
|
toggle: topbarAsideToggle
|
|
});
|
|
|
|
// run once on first time dropdown shown
|
|
topbarAside.mOffcanvas().one('afterShow', function() {
|
|
mApp.block(topbarAside);
|
|
|
|
setTimeout(function() {
|
|
mApp.unblock(topbarAside);
|
|
|
|
topbarAsideContent.removeClass('m--hide');
|
|
|
|
initOffcanvasTabs();
|
|
}, 1000);
|
|
});
|
|
}
|
|
|
|
return {
|
|
init: function() {
|
|
initOffcanvas();
|
|
}
|
|
};
|
|
}();
|
|
|
|
$(document).ready(function() {
|
|
mQuickSidebar.init();
|
|
}); |