mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-11 10:24:04 +00:00
Add right click to file tree
This commit is contained in:
parent
a83f0fe054
commit
cc0d45c678
4 changed files with 235 additions and 57 deletions
services/web
app/views/project/editor
public
|
@ -56,6 +56,9 @@ script(type='text/ng-template', id='entityListItemTemplate')
|
|||
ng-click="select()"
|
||||
ng-dblclick="startRenaming()"
|
||||
draggable
|
||||
context-menu
|
||||
data-target="context-menu-{{ entity.id }}"
|
||||
context-menu-container="body"
|
||||
)
|
||||
//- Just a spacer to align with folders
|
||||
i.fa.fa-fw.toggle(ng-if="entity.type != 'folder'")
|
||||
|
@ -92,6 +95,23 @@ script(type='text/ng-template', id='entityListItemTemplate')
|
|||
ng-click="openDeleteModal()"
|
||||
) Delete
|
||||
|
||||
div.dropdown.context-menu(id="context-menu-{{ entity.id }}")
|
||||
ul.dropdown-menu
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
stop-propagation="click"
|
||||
ng-click="startRenaming()"
|
||||
) Rename
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
stop-propagation="click"
|
||||
ng-click="openDeleteModal()"
|
||||
) Delete
|
||||
|
||||
|
||||
.entity(ng-if="entity.type == 'folder'", ng-controller="FileTreeFolderController")
|
||||
.entity-name(
|
||||
|
@ -101,69 +121,112 @@ script(type='text/ng-template', id='entityListItemTemplate')
|
|||
droppable
|
||||
on-drop-callback="onDrop"
|
||||
)
|
||||
i.fa.fa-fw.toggle(
|
||||
ng-if="entity.type == 'folder'"
|
||||
ng-class="{'fa-chevron-right': !expanded, 'fa-chevron-down': expanded}"
|
||||
ng-click="toggleExpanded()"
|
||||
div(
|
||||
context-menu
|
||||
data-target="context-menu-{{ entity.id }}"
|
||||
context-menu-container="body"
|
||||
)
|
||||
i.fa.fa-fw.toggle(
|
||||
ng-if="entity.type == 'folder'"
|
||||
ng-class="{'fa-chevron-right': !expanded, 'fa-chevron-down': expanded}"
|
||||
ng-click="toggleExpanded()"
|
||||
)
|
||||
|
||||
i.fa.fa-fw(
|
||||
ng-if="entity.type == 'folder'"
|
||||
ng-class="{\
|
||||
'fa-folder': !expanded, \
|
||||
'fa-folder-open': expanded \
|
||||
}"
|
||||
ng-click="select()"
|
||||
)
|
||||
i.fa.fa-fw(
|
||||
ng-if="entity.type == 'folder'"
|
||||
ng-class="{\
|
||||
'fa-folder': !expanded, \
|
||||
'fa-folder-open': expanded \
|
||||
}"
|
||||
ng-click="select()"
|
||||
)
|
||||
|
||||
span(
|
||||
ng-hide="entity.renaming"
|
||||
) {{ entity.name }}
|
||||
input(
|
||||
ng-show="entity.renaming",
|
||||
ng-model="inputs.name",
|
||||
ng-blur="finishRenaming()",
|
||||
select-name-when="entity.renaming",
|
||||
on-enter="finishRenaming()"
|
||||
)
|
||||
span(
|
||||
ng-hide="entity.renaming"
|
||||
) {{ entity.name }}
|
||||
input(
|
||||
ng-show="entity.renaming",
|
||||
ng-model="inputs.name",
|
||||
ng-blur="finishRenaming()",
|
||||
select-name-when="entity.renaming",
|
||||
on-enter="finishRenaming()"
|
||||
)
|
||||
|
||||
span.dropdown(ng-show="entity.selected")
|
||||
a.dropdown-toggle(href)
|
||||
i.fa.fa-chevron-down
|
||||
span.dropdown(ng-show="entity.selected")
|
||||
a.dropdown-toggle(href)
|
||||
i.fa.fa-chevron-down
|
||||
|
||||
ul.dropdown-menu.dropdown-menu-right
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
ng-click="startRenaming()"
|
||||
) Rename
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
ng-click="openDeleteModal()"
|
||||
) Delete
|
||||
li.divider
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
ng-click="openNewDocModal()"
|
||||
) New File
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
ng-click="openNewFolderModal()"
|
||||
) New Folder
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
ng-click="openUploadFileModal()"
|
||||
) Upload File
|
||||
ul.dropdown-menu.dropdown-menu-right
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
ng-click="startRenaming()"
|
||||
) Rename
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
ng-click="openDeleteModal()"
|
||||
) Delete
|
||||
li.divider
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
ng-click="openNewDocModal()"
|
||||
) New File
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
ng-click="openNewFolderModal()"
|
||||
) New Folder
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
ng-click="openUploadFileModal()"
|
||||
) Upload File
|
||||
|
||||
.dropdown.context-menu(id="context-menu-{{ entity.id }}")
|
||||
ul.dropdown-menu
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
stop-propagation="click"
|
||||
ng-click="startRenaming()"
|
||||
) Rename
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
stop-propagation="click"
|
||||
ng-click="openDeleteModal()"
|
||||
) Delete
|
||||
li.divider
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
stop-propagation="click"
|
||||
ng-click="openNewDocModal()"
|
||||
) New File
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
stop-propagation="click"
|
||||
ng-click="openNewFolderModal()"
|
||||
) New Folder
|
||||
li
|
||||
a(
|
||||
href="#"
|
||||
prevent-default="click"
|
||||
stop-propagation="click"
|
||||
ng-click="openUploadFileModal()"
|
||||
) Upload File
|
||||
|
||||
ul.list-unstyled(
|
||||
ng-if="entity.type == 'folder'"
|
||||
|
|
|
@ -2,11 +2,13 @@ define [
|
|||
"../libs/angular-autocomplete/angular-autocomplete"
|
||||
"../libs/ui-bootstrap"
|
||||
"modules/recursionHelper"
|
||||
"../libs/ng-context-menu-0.1.4"
|
||||
], () ->
|
||||
App = angular.module("SharelatexApp", [
|
||||
"ui.bootstrap"
|
||||
"autocomplete"
|
||||
"RecursionHelper"
|
||||
"ng-context-menu"
|
||||
])
|
||||
|
||||
return App
|
108
services/web/public/js/libs/ng-context-menu-0.1.4.js
Normal file
108
services/web/public/js/libs/ng-context-menu-0.1.4.js
Normal file
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* ng-context-menu - v0.1.4 - An AngularJS directive to display a context menu when a right-click event is triggered
|
||||
*
|
||||
* @author Ian Kennington Walter (http://ianvonwalter.com)
|
||||
*/
|
||||
angular
|
||||
.module('ng-context-menu', [])
|
||||
.factory('ContextMenuService', function() {
|
||||
return {
|
||||
element: null,
|
||||
menuElement: null,
|
||||
container: null
|
||||
};
|
||||
})
|
||||
.directive('contextMenu', ['$document', 'ContextMenuService', function($document, ContextMenuService) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
'callback': '&contextMenu',
|
||||
'disabled': '&contextMenuDisabled'
|
||||
},
|
||||
link: function($scope, $element, $attrs) {
|
||||
var opened = false;
|
||||
|
||||
function open(event, menuElement, container) {
|
||||
menuElement.addClass('open');
|
||||
|
||||
if (container) {
|
||||
container.append(menuElement);
|
||||
}
|
||||
|
||||
var doc = $document[0].documentElement;
|
||||
var docLeft = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0),
|
||||
docTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0),
|
||||
elementHeight = menuElement[0].scrollHeight;
|
||||
var docHeight = doc.clientHeight + docTop,
|
||||
totalHeight = elementHeight + event.pageY,
|
||||
top = Math.max(event.pageY - docTop, 0);
|
||||
|
||||
if (totalHeight > docHeight) {
|
||||
top = top - (totalHeight - docHeight);
|
||||
}
|
||||
|
||||
menuElement.css('top', top + 'px');
|
||||
menuElement.css('left', Math.max(event.pageX - docLeft, 0) + 'px');
|
||||
opened = true;
|
||||
}
|
||||
|
||||
function close(menuElement) {
|
||||
menuElement.removeClass('open');
|
||||
opened = false;
|
||||
}
|
||||
|
||||
$element.bind('contextmenu', function(event) {
|
||||
if (!$scope.disabled()) {
|
||||
if (ContextMenuService.menuElement !== null) {
|
||||
close(ContextMenuService.menuElement);
|
||||
}
|
||||
ContextMenuService.menuElement = angular.element(document.getElementById($attrs.target));
|
||||
if (typeof($attrs.contextMenuContainer) != "undefined") {
|
||||
ContextMenuService.container = angular.element($attrs.contextMenuContainer)
|
||||
}
|
||||
ContextMenuService.element = event.target;
|
||||
console.log('set', ContextMenuService.element);
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
$scope.$apply(function() {
|
||||
$scope.callback({ $event: event });
|
||||
open(event, ContextMenuService.menuElement, ContextMenuService.container);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function handleKeyUpEvent(event) {
|
||||
//console.log('keyup');
|
||||
if (!$scope.disabled() && opened && event.keyCode === 27) {
|
||||
$scope.$apply(function() {
|
||||
close(ContextMenuService.menuElement);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleClickEvent(event) {
|
||||
if (!$scope.disabled() &&
|
||||
opened &&
|
||||
(event.button !== 2 || event.target !== ContextMenuService.element)) {
|
||||
$scope.$apply(function() {
|
||||
close(ContextMenuService.menuElement);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$document.bind('keyup', handleKeyUpEvent);
|
||||
// Firefox treats a right-click as a click and a contextmenu event while other browsers
|
||||
// just treat it as a contextmenu event
|
||||
$document.bind('click', handleClickEvent);
|
||||
$document.bind('contextmenu', handleClickEvent);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
//console.log('destroy');
|
||||
$document.unbind('keyup', handleKeyUpEvent);
|
||||
$document.unbind('click', handleClickEvent);
|
||||
$document.unbind('contextmenu', handleClickEvent);
|
||||
});
|
||||
}
|
||||
};
|
||||
}]);
|
|
@ -140,6 +140,11 @@
|
|||
padding: 0 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.context-menu {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue