Add right click to file tree

This commit is contained in:
James Allen 2014-06-23 17:25:45 +01:00
parent a83f0fe054
commit cc0d45c678
4 changed files with 235 additions and 57 deletions

View file

@ -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'"

View file

@ -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

View 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);
});
}
};
}]);

View file

@ -140,6 +140,11 @@
padding: 0 12px;
}
}
.context-menu {
position: fixed;
z-index: 100;
}
}
}