344 lines
12 KiB
JavaScript
344 lines
12 KiB
JavaScript
let onPickedElement = function (element) {
|
|
};
|
|
|
|
jQuery(function ($) {
|
|
let lastClicked = null;
|
|
|
|
const explrSidebarOpenFromFolder = function (folderId) {
|
|
const $leaf = $('.li-explr-folder-' + folderId);
|
|
let $parent = $leaf;
|
|
while ($parent.length > 0) {
|
|
const $toggler = $parent.find('.explr-toggler:eq(0)');
|
|
if ($toggler.hasClass('explr-plus')) {
|
|
$parent.find('.explr-toggler:eq(0)').trigger('click');
|
|
}
|
|
$parent = $parent.parents('.li-explr-folder:eq(0)');
|
|
}
|
|
};
|
|
|
|
const initExplr = function () {
|
|
$('.explr').each(function () {
|
|
$(this).explr({
|
|
classesPlus: 'fa fa-chevron-right',
|
|
classesMinus: 'fa fa-chevron-down',
|
|
onLoadFinish: function ($tree) {
|
|
$tree.removeClass('hidden');
|
|
}
|
|
});
|
|
|
|
// Open complete path in explorer sidebar
|
|
explrSidebarOpenFromFolder($(this).attr('data-working-folder-id'));
|
|
});
|
|
|
|
$('.draggable').each(function () {
|
|
$(this).draggable({
|
|
revert: "invalid",
|
|
});
|
|
});
|
|
|
|
$('.droppable').each(function () {
|
|
$(this).droppable({
|
|
accept: ".draggable",
|
|
over: function (event, ui) {
|
|
$(this).addClass("highlight-drop");
|
|
},
|
|
out: function (event, ui) {
|
|
$(this).removeClass("highlight-drop");
|
|
},
|
|
drop: function (event, ui) {
|
|
$(this).removeClass("highlight-drop");
|
|
const $form = $('#folder-move-form');
|
|
const $moved = ui.draggable;
|
|
const $target = $(this);
|
|
$form.find('[name=is_folder]').val($moved.attr('data-folder'))
|
|
$form.find('[name=entity_id]').val($moved.attr('data-id'))
|
|
$form.find('[name=new_folder_id]').val($target.attr('data-id'))
|
|
ui.draggable.position({
|
|
my: "center",
|
|
at: "center",
|
|
of: $(this),
|
|
using: function (pos) {
|
|
$(this).animate(pos, 50);
|
|
}
|
|
});
|
|
$form.submit();
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
const main = function () {
|
|
initExplr();
|
|
};
|
|
|
|
const updateBodyClasses = function () {
|
|
const $selectedLinks = $('a.explr-link.highlight-clicked');
|
|
const isMultiSelect = $selectedLinks.length > 1;
|
|
const isSingleSelect = $selectedLinks.length === 1;
|
|
const $link = $selectedLinks.last();
|
|
|
|
$('body')
|
|
.toggleClass('explr-selection', isSingleSelect)
|
|
.toggleClass('explr-selection-actionable', isSingleSelect && $link.hasClass('explr-item-actionable'))
|
|
.toggleClass('explr-selection-entity', isSingleSelect && $link.hasClass('explr-item-entity'))
|
|
.toggleClass('explr-selection-folder', isSingleSelect && $link.hasClass('explr-item-folder'))
|
|
.toggleClass('explr-multiselection', isMultiSelect)
|
|
.toggleClass('explr-multiselection-actionable', isMultiSelect && $selectedLinks.hasClass('explr-item-actionable'))
|
|
.toggleClass('explr-multiselection-entity', isMultiSelect && $selectedLinks.hasClass('explr-item-entity'))
|
|
.toggleClass('explr-multiselection-folder', isMultiSelect && $selectedLinks.hasClass('explr-item-folder'));
|
|
};
|
|
|
|
const selectEpxlrLink = function ($link) {
|
|
$link.addClass('highlight-clicked');
|
|
$link.parent().addClass('highlight-clicked');
|
|
updateBodyClasses();
|
|
};
|
|
|
|
const clearSelection = function () {
|
|
$('a.explr-link').removeClass('highlight-clicked');
|
|
$('a.explr-link').parent().removeClass('highlight-clicked');
|
|
$('body').removeClass('explr-selection explr-selection-actionable explr-selection-entity explr-selection-folder explr-multiselection explr-multiselection-actionable explr-multiselection-entity explr-multiselection-folder');
|
|
};
|
|
|
|
const handleShiftClick = function ($link) {
|
|
const $links = $('li > a.explr-link');
|
|
const start = $links.index(lastClicked);
|
|
const end = $links.index($link);
|
|
const [from, to] = start < end ? [start, end] : [end, start];
|
|
$links.slice(from, to + 1).each(function () {
|
|
selectEpxlrLink($(this));
|
|
});
|
|
updateBodyClasses();
|
|
};
|
|
|
|
const handleCmdCtrlClick = function ($link) {
|
|
if ($link.hasClass('highlight-clicked')) {
|
|
$link.removeClass('highlight-clicked');
|
|
$link.parent().removeClass('highlight-clicked');
|
|
} else {
|
|
selectEpxlrLink($link);
|
|
}
|
|
updateBodyClasses();
|
|
};
|
|
|
|
|
|
const getExplrSelection = function () {
|
|
return $('.explr-dirview li.highlight-clicked');
|
|
};
|
|
|
|
const renameExplrItem = function ($item) {
|
|
|
|
$('.dirview .renaming').removeClass('renaming');
|
|
$item.addClass('renaming');
|
|
$item.find('input').focus().select();
|
|
}
|
|
|
|
$(document).on('click', '.explr-item-edit', function () {
|
|
document.location.href = $(this).attr('data-entity-route').replace('!c!', getExplrSelection().attr('data-id'));
|
|
});
|
|
|
|
$(document).on('click', '.explr-item-rename', function () {
|
|
renameExplrItem(getExplrSelection());
|
|
});
|
|
|
|
$(document).on('click', '.explr-item-delete', function () {
|
|
const $item = getExplrSelection();
|
|
const is_folder = $item.attr('data-folder') === '1';
|
|
let route;
|
|
|
|
if (is_folder) {
|
|
route = $(this).attr('data-folder-route') + '&id=' + $item.attr('data-id');
|
|
} else {
|
|
route = $(this).attr('data-entity-route') + '&id=' + $item.attr('data-id');
|
|
}
|
|
|
|
if (confirm(l.js_common_are_you_sure)) {
|
|
document.location.href = route;
|
|
}
|
|
});
|
|
|
|
$(document).on('click', '.explr-items-delete', function () {
|
|
const $items = getExplrSelection();
|
|
const folder_ids = [], entity_ids = [];
|
|
|
|
$items.each(function() {
|
|
const is_folder = $(this).attr('data-folder') === '1';
|
|
const id = $(this).attr('data-id');
|
|
|
|
if (is_folder) {
|
|
folder_ids.push(id);
|
|
} else {
|
|
entity_ids.push(id);
|
|
}
|
|
});
|
|
|
|
if (confirm(l.js_common_are_you_sure)) {
|
|
document.location.href = $(this).attr('data-route')
|
|
+ '&folder_ids=' + folder_ids.join(',')
|
|
+ '&entity_ids=' + entity_ids.join(',')
|
|
;
|
|
}
|
|
});
|
|
|
|
$(document).keyup(function (e) {
|
|
const $selectedLink = $('.explr-item-selectable.highlight-clicked');
|
|
const $selectedLi = $selectedLink.parents('li:eq(0)');
|
|
|
|
if (e.key === "Escape") {
|
|
$('.dirview .new-folder').addClass('hidden');
|
|
$('.dirview .renaming').removeClass('renaming');
|
|
clearSelection();
|
|
}
|
|
|
|
if ($('.renaming input:focus').length > 0) {
|
|
return;
|
|
}
|
|
|
|
if (e.code === "Space") {
|
|
renameExplrItem($selectedLi);
|
|
} else if ($selectedLink.length) {
|
|
const $prevLi = $selectedLi.prev('li:visible');
|
|
const $nextLi = $selectedLi.next('li:visible');
|
|
const verticalNeighbors = getAboveBelowElement($selectedLi);
|
|
|
|
if (e.key === "Enter") {
|
|
$selectedLink.trigger('dblclick');
|
|
} else if (e.key === "ArrowLeft" && $prevLi.length) {
|
|
selectEpxlrLink($prevLi.find('.explr-link'));
|
|
} else if (e.key === "ArrowRight" && $nextLi.length) {
|
|
selectEpxlrLink($nextLi.find('.explr-link'));
|
|
} else if (e.key === "ArrowUp" && verticalNeighbors.above) {
|
|
selectEpxlrLink(verticalNeighbors.above.find('.explr-link'));
|
|
} else if (e.key === "ArrowDown" && verticalNeighbors.below) {
|
|
selectEpxlrLink(verticalNeighbors.below.find('.explr-link'));
|
|
} else if (e.key === "Backspace") {
|
|
if ($('.explr-item-delete:visible').length) {
|
|
$('.explr-item-delete:visible').click();
|
|
}
|
|
if ($('.explr-items-delete:visible').length) {
|
|
$('.explr-items-delete:visible').click();
|
|
}
|
|
}
|
|
} else if (e.key.indexOf('Arrow') === 0) {
|
|
selectEpxlrLink($('.explr-dirview li:visible:eq(0)').find('.explr-link'));
|
|
}
|
|
});
|
|
|
|
// Explorer item selection
|
|
$(document).on('click', 'a.explr-link', function (event) {
|
|
event.preventDefault();
|
|
const $link = $(this);
|
|
|
|
if (event.shiftKey && lastClicked) {
|
|
handleShiftClick($link);
|
|
} else if (event.metaKey || event.ctrlKey) {
|
|
handleCmdCtrlClick($link);
|
|
} else {
|
|
clearSelection();
|
|
selectEpxlrLink($link);
|
|
}
|
|
lastClicked = $link;
|
|
});
|
|
$(document).on('click', 'a.explr-pick-element', function (event) {
|
|
event.preventDefault();
|
|
const callback = $(this).attr('data-callback');
|
|
|
|
if (callback) {
|
|
window[callback]($(this));
|
|
}
|
|
});
|
|
$(document).on('dblclick', 'a.explr-link', function (event) {
|
|
event.preventDefault();
|
|
$(this).off('click');
|
|
const href = $(this).attr('href');
|
|
const callback = $(this).attr('data-callback');
|
|
|
|
if (callback) {
|
|
window[callback]($(this));
|
|
} else if ($(this).attr('target') === '_blank') {
|
|
window.open(href);
|
|
} else {
|
|
window.location.href = href;
|
|
}
|
|
});
|
|
$(document).on('click', function (event) {
|
|
const $parentClickable = $(event.target).parents('a, button');
|
|
if ($parentClickable.length === 0) {
|
|
$('a.explr-link').removeClass('highlight-clicked');
|
|
$('a.explr-link').parent().removeClass('highlight-clicked');
|
|
$('body').removeClass('explr-selection explr-selection-entity explr-selection-folder explr-selection-actionable');
|
|
}
|
|
});
|
|
|
|
$(document).on('click', '.modal-explr-picker .explr-pick-folder', function () {
|
|
$(this).parents('li:eq(0)').find('.explr-toggler').click();
|
|
});
|
|
|
|
$(document).on('click', '.modal-explr-picker .explr-pick-element', function () {
|
|
onPickedElement(JSON.parse($(this).parents('li:eq(0)').attr('data-entity-json')));
|
|
hidePicker();
|
|
});
|
|
|
|
const getAboveBelowElement = function ($elem) {
|
|
const $liElements = $elem.parents('ul:eq(0)').find('li');
|
|
const positions = [];
|
|
|
|
// Get the Y positions of each element
|
|
$liElements.each(function () {
|
|
const $this = $(this);
|
|
positions.push({
|
|
element: $this,
|
|
y: $this.offset().top,
|
|
x: $this.offset().left
|
|
});
|
|
});
|
|
|
|
// Group elements by their Y position
|
|
const groupedByY = positions.reduce((acc, pos) => {
|
|
if (!acc[pos.y]) {
|
|
acc[pos.y] = [];
|
|
}
|
|
acc[pos.y].push(pos);
|
|
return acc;
|
|
}, {});
|
|
|
|
// Convert groupedByY to an array of arrays
|
|
const rows = Object.values(groupedByY);
|
|
|
|
let targetRowIndex = -1;
|
|
let targetColIndex = -1;
|
|
|
|
// Find the row and column index of the target element
|
|
rows.forEach((row, rowIndex) => {
|
|
row.forEach((pos, colIndex) => {
|
|
if (pos.element.is($elem)) {
|
|
targetRowIndex = rowIndex;
|
|
targetColIndex = colIndex;
|
|
}
|
|
});
|
|
});
|
|
|
|
const result = {
|
|
above: null,
|
|
below: null
|
|
};
|
|
|
|
if (targetRowIndex > 0) {
|
|
const aboveRow = rows[targetRowIndex - 1];
|
|
if (targetColIndex < aboveRow.length) {
|
|
result.above = aboveRow[targetColIndex].element;
|
|
}
|
|
}
|
|
|
|
if (targetRowIndex < rows.length - 1) {
|
|
const belowRow = rows[targetRowIndex + 1];
|
|
if (targetColIndex < belowRow.length) {
|
|
result.below = belowRow[targetColIndex].element;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
main();
|
|
}); |