/**
* @class elFinder contextmenu
*
* @author Dmitry (dio) Levashov
**/
jQuery.fn.elfindercontextmenu = function(fm) {
"use strict";
return this.each(function() {
var self = jQuery(this),
cmItem = 'elfinder-contextmenu-item',
smItem = 'elfinder-contextsubmenu-item',
exIcon = 'elfinder-contextmenu-extra-icon',
cHover = fm.res('class', 'hover'),
dragOpt = {
distance: 8,
start: function() {
menu.data('drag', true).data('touching') && menu.find('.'+cHover).removeClass(cHover);
},
stop: function() {
menu.data('draged', true).removeData('drag');
}
},
menu = jQuery(this).addClass('touch-punch ui-helper-reset ui-front ui-widget ui-state-default ui-corner-all elfinder-contextmenu elfinder-contextmenu-'+fm.direction)
.hide()
.on('touchstart', function(e) {
menu.data('touching', true).children().removeClass(cHover);
})
.on('touchend', function(e) {
menu.removeData('touching');
})
.on('mouseenter mouseleave', '.'+cmItem, function(e) {
jQuery(this).toggleClass(cHover, (e.type === 'mouseenter' || (! menu.data('draged') && menu.data('submenuKeep'))? true : false));
if (menu.data('draged') && menu.data('submenuKeep')) {
menu.find('.elfinder-contextmenu-sub:visible').parent().addClass(cHover);
}
})
.on('mouseenter mouseleave', '.'+exIcon, function(e) {
jQuery(this).parent().toggleClass(cHover, e.type === 'mouseleave');
})
.on('mouseenter mouseleave', '.'+cmItem+',.'+smItem, function(e) {
var setIndex = function(target, sub) {
jQuery.each(sub? subnodes : nodes, function(i, n) {
if (target[0] === n) {
(sub? subnodes : nodes)._cur = i;
if (sub) {
subselected = target;
} else {
selected = target;
}
return false;
}
});
};
if (e.originalEvent) {
var target = jQuery(this),
unHover = function() {
if (selected && !selected.children('div.elfinder-contextmenu-sub:visible').length) {
selected.removeClass(cHover);
}
};
if (e.type === 'mouseenter') {
// mouseenter
if (target.hasClass(smItem)) {
// submenu
if (subselected) {
subselected.removeClass(cHover);
}
if (selected) {
subnodes = selected.find('div.'+smItem);
}
setIndex(target, true);
} else {
// menu
unHover();
setIndex(target);
}
} else {
// mouseleave
if (target.hasClass(smItem)) {
//submenu
subselected = null;
subnodes = null;
} else {
// menu
unHover();
(function(sel) {
setTimeout(function() {
if (sel === selected) {
selected = null;
}
}, 250);
})(selected);
}
}
}
})
.on('contextmenu', function(){return false;})
.on('mouseup', function() {
setTimeout(function() {
menu.removeData('draged');
}, 100);
})
.draggable(dragOpt),
ltr = fm.direction === 'ltr',
subpos = ltr? 'left' : 'right',
types = Object.assign({}, fm.options.contextmenu),
tpl = '<div class="'+cmItem+'{className}"><span class="elfinder-button-icon {icon} elfinder-contextmenu-icon"{style}></span><span>{label}</span></div>',
item = function(label, icon, callback, opts) {
var className = '',
style = '',
iconClass = '',
v, pos;
if (opts) {
if (opts.className) {
className = ' ' + opts.className;
}
if (opts.iconClass) {
iconClass = opts.iconClass;
icon = '';
}
if (opts.iconImg) {
v = opts.iconImg.split(/ +/);
pos = v[1] && v[2]? fm.escape(v[1] + 'px ' + v[2] + 'px') : '';
style = ' style="background:url(\''+fm.escape(v[0])+'\') '+(pos? pos : '0 0')+' no-repeat;'+(pos? '' : 'posbackground-size:contain;')+'"';
}
}
return jQuery(tpl.replace('{icon}', icon ? 'elfinder-button-icon-'+icon : (iconClass? iconClass : ''))
.replace('{label}', label)
.replace('{style}', style)
.replace('{className}', className))
.on('click', function(e) {
e.stopPropagation();
e.preventDefault();
callback();
});
},
urlIcon = function(iconUrl) {
var v = iconUrl.split(/ +/),
pos = v[1] && v[2]? (v[1] + 'px ' + v[2] + 'px') : '';
return {
backgroundImage: 'url("'+v[0]+'")',
backgroundRepeat: 'no-repeat',
backgroundPosition: pos? pos : '',
backgroundSize: pos? '' : 'contain'
};
},
base, cwd,
nodes, selected, subnodes, subselected, autoSyncStop, subHoverTm,
autoToggle = function() {
var evTouchStart = 'touchstart.contextmenuAutoToggle';
menu.data('hideTm') && clearTimeout(menu.data('hideTm'));
if (menu.is(':visible')) {
menu.on('touchstart', function(e) {
if (e.originalEvent.touches.length > 1) {
return;
}
menu.stop();
fm.toFront(menu);
menu.data('hideTm') && clearTimeout(menu.data('hideTm'));
})
.data('hideTm', setTimeout(function() {
if (menu.is(':visible')) {
cwd.find('.elfinder-cwd-file').off(evTouchStart);
cwd.find('.elfinder-cwd-file.ui-selected')
.one(evTouchStart, function(e) {
if (e.originalEvent.touches.length > 1) {
return;
}
var tgt = jQuery(e.target);
if (menu.first().length && !tgt.is('input:checkbox') && !tgt.hasClass('elfinder-cwd-select')) {
e.stopPropagation();
//e.preventDefault();
open(e.originalEvent.touches[0].pageX, e.originalEvent.touches[0].pageY);
cwd.data('longtap', true)
tgt.one('touchend', function() {
setTimeout(function() {
cwd.removeData('longtap');
}, 80);
});
return;
}
cwd.find('.elfinder-cwd-file').off(evTouchStart);
})
.one('unselect.'+fm.namespace, function() {
cwd.find('.elfinder-cwd-file').off(evTouchStart);
});
menu.fadeOut({
duration: 300,
fail: function() {
menu.css('opacity', '1').show();
},
done: function() {
fm.toHide(menu);
}
});
}
}, 4500));
}
},
keyEvts = function(e) {
var code = e.keyCode,
ESC = jQuery.ui.keyCode.ESCAPE,
ENT = jQuery.ui.keyCode.ENTER,
LEFT = jQuery.ui.keyCode.LEFT,
RIGHT = jQuery.ui.keyCode.RIGHT,
UP = jQuery.ui.keyCode.UP,
DOWN = jQuery.ui.keyCode.DOWN,
subent = fm.direction === 'ltr'? RIGHT : LEFT,
sublev = subent === RIGHT? LEFT : RIGHT;
if (jQuery.inArray(code, [ESC, ENT, LEFT, RIGHT, UP, DOWN]) !== -1) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
if (code == ESC || code === sublev) {
if (selected && subnodes && subselected) {
subselected.trigger('mouseleave').trigger('submenuclose');
selected.addClass(cHover);
subnodes = null;
subselected = null;
} else {
code == ESC && close();
fm.trigger('closecontextmenu');
}
} else if (code == UP || code == DOWN) {
if (subnodes) {
if (subselected) {
subselected.trigger('mouseleave');
}
if (code == DOWN && (! subselected || subnodes.length <= ++subnodes._cur)) {
subnodes._cur = 0;
} else if (code == UP && (! subselected || --subnodes._cur < 0)) {
subnodes._cur = subnodes.length - 1;
}
subselected = subnodes.eq(subnodes._cur).trigger('mouseenter');
} else {
subnodes = null;
if (selected) {
selected.trigger('mouseleave');
}
if (code == DOWN && (! selected || nodes.length <= ++nodes._cur)) {
nodes._cur = 0;
} else if (code == UP && (! selected || --nodes._cur < 0)) {
nodes._cur = nodes.length - 1;
}
selected = nodes.eq(nodes._cur).addClass(cHover);
}
} else if (selected && (code == ENT || code === subent)) {
if (selected.hasClass('elfinder-contextmenu-group')) {
if (subselected) {
code