Add expend/collapse to the tree, fix CSS, add list/grid view modes

This commit is contained in:
yflory 2016-11-08 18:53:47 +01:00
parent c9cd06514c
commit cfe3d38197
2 changed files with 462 additions and 80 deletions

View File

@ -7,6 +7,8 @@ html, body {
padding: 0; padding: 0;
margin: 0; margin: 0;
position: relative; position: relative;
font-size: 20px;
overflow: auto;
} }
.fa { .fa {
@ -28,10 +30,6 @@ li {
user-select: none; user-select: none;
} }
li > span.element:hover {
text-decoration: underline;
}
.folder, .file { .folder, .file {
margin-right: 5px; margin-right: 5px;
} }
@ -63,6 +61,7 @@ li > span.element:hover {
border: 2px solid blue; border: 2px solid blue;
box-sizing: border-box; box-sizing: border-box;
background: white; background: white;
overflow: auto;
} }
#tree li { #tree li {
@ -73,6 +72,10 @@ li > span.element:hover {
cursor: pointer; cursor: pointer;
} }
#tree li > span.element:hover {
text-decoration: underline;
}
#tree .active { #tree .active {
text-decoration: underline; text-decoration: underline;
} }
@ -83,10 +86,29 @@ li > span.element:hover {
#tree .fa.expcol { #tree .fa.expcol {
margin-left: -10px; margin-left: -10px;
font-size: 14px;
position: absolute;
left: -20px;
top: 9px;
width: auto;
height: 11px;
padding: 0;
margin: 0;
background: white;
z-index: 10;
cursor: default;
}
#tree .fa.expcol:before {
position:relative;
top: -1px;
} }
#tree .non-collapsable { #tree li.collapsed ul {
padding-left: 12px; display: none;
}
#tree li input {
width: calc(100% - 30px);
} }
/* Tree lines */ /* Tree lines */
@ -101,16 +123,13 @@ li > span.element:hover {
#tree ul li:before { #tree ul li:before {
position: absolute; position: absolute;
left: -15px; left: -15px;
top: 0px; top: -0.25em;
content: ''; content: '';
display: block; display: block;
border-left: 1px solid #ddd; border-left: 1px solid #888;
height: 0.75em; height: 1em;
border-bottom: 1px solid #ddd; border-bottom: 1px solid #888;
width: 10px; width: 17.5px;
}
#tree ul li.non-collapsable:before {
width: 27px;
} }
#tree ul li:after { #tree ul li:after {
position: absolute; position: absolute;
@ -118,7 +137,7 @@ li > span.element:hover {
bottom: -7px; bottom: -7px;
content: ''; content: '';
display: block; display: block;
border-left: 1px solid #ddd; border-left: 1px solid #888;
height: 100%; height: 100%;
} }
#tree ul li.root { #tree ul li.root {
@ -146,6 +165,12 @@ li > span.element:hover {
border: 2px solid green; border: 2px solid green;
box-sizing: border-box; box-sizing: border-box;
background: #eee; background: #eee;
overflow: auto;
}
.changeViewModeContainer {
border: 1px solid #ccc;
float: right;
} }
.parentFolder { .parentFolder {
@ -158,6 +183,52 @@ li > span.element:hover {
} }
#folderContent { #folderContent {
display: inline-block; /*display: inline-block;*/
}
#content li:hover .name {
text-decoration: underline;
}
#content .grid li {
display: inline-block;
margin: 10px 10px;
width: 140px;
text-align: center;
height: 70px;
vertical-align: top;
}
#content .grid li input {
width: 100%;
}
#content .grid li .fa {
display: block;
margin: auto;
font-size: 40px;
width: auto;
text-align: center;
}
#content .list li {
display: flex;
flex-flow: row;
align-items: center;
}
#content .list li .element {
display: inline-flex;
flex: 1;
}
#content .list .element span {
margin-right: 20px;
display: inline-block;
}
#content .list .element span.name {
flex: 1;
}
#content .list .element span.date {
width: 120px;
} }

View File

@ -27,13 +27,39 @@ define([
var saveAs = window.saveAs; var saveAs = window.saveAs;
var $iframe = $('#pad-iframe').contents(); var $iframe = $('#pad-iframe').contents();
var ifrw = $('#pad-iframe')[0].contentWindow; var ifrw = $('#pad-iframe')[0].contentWindow;
var ROOT = "root";
var ROOT_NAME = "My files";
var FILES_DATA = "filesData";
var FILES_DATA_NAME = "Unsorted files";
var TRASH = "trash";
var TRASH_NAME = "Trash";
var TIME_BEFORE_RENAME = 1000;
var LOCALSTORAGE_LAST = "cryptpad-file-lastOpened";
var LOCALSTORAGE_OPENED = "cryptpad-file-openedFolders";
var LOCALSTORAGE_VIEWMODE = "cryptpad-file-viewMode";
var FOLDER_CONTENT_ID = "folderContent";
var files = module.files = { var files = module.files = {
root: { root: {
"Directory 1": { "Directory 1": {
"Dir A": { "Dir A": {
"Dir D": {
"Dir E": {},
},
"File a": "#hash_a", "File a": "#hash_a",
"File b": "#hash_b" "File b": "#hash_b",
"File c": "#hash_c",
"File d": "#hash_d",
"File e": "#hash_e",
"File f": "#hash_f",
"File g": "#hash_g",
"File h": "#hash_h",
"File i": "#hash_i",
"File j": "#hash_j",
"File k": "#hash_k"
}, },
"Dir C": {},
"Dir B": {}, "Dir B": {},
"File A": "#hash_A" "File A": "#hash_A"
}, },
@ -42,6 +68,83 @@ define([
"File C": "#hash_C" "File C": "#hash_C"
} }
}, },
filesData: {
"#hash_a": {
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
title: "Pad A"
},
"#hash_b": {
ctime: "Mon Nov 07 2016 16:38:21 GMT+0100 (CET)",
atime: "Tue Nov 08 2016 12:38:21 GMT+0100 (CET)",
title: "Pad B"
},
"#hash_c": {
ctime: "Tue Nov 08 2016 16:34:21 GMT+0100 (CET)",
atime: "Sun Nov 06 2016 12:34:21 GMT+0100 (CET)",
title: "Pad C With A Long Title"
},
"#hash_d": {
ctime: "Tue Nov 08 2016 16:30:21 GMT+0100 (CET)",
atime: "Tue Nov 08 2016 12:30:21 GMT+0100 (CET)",
title: "Pad D"
},
"#hash_e": {
ctime: "Tue Nov 08 2016 16:26:21 GMT+0100 (CET)",
atime: "Tue Nov 08 2016 12:26:21 GMT+0100 (CET)",
title: "Pad E"
},
"#hash_f": {
ctime: "Tue Nov 08 2016 16:22:21 GMT+0100 (CET)",
atime: "Tue Nov 08 2016 12:22:21 GMT+0100 (CET)",
title: "Pad F"
},
"#hash_g": {
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
title: "Pad A"
},
"#hash_h": {
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
title: "Pad A"
},
"#hash_i": {
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
title: "Pad A"
},
"#hash_j": {
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
title: "Pad A"
},
"#hash_k": {
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
title: "Pad A"
},
"#hash_Z": {
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
title: "Code Z"
},
"#hash_A": {
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
title: "Code A"
},
"#hash_B": {
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
title: "Code B"
},
"#hash_C": {
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
title: "Code C"
}
},
trash: { trash: {
"File Z": [{ "File Z": [{
element: "#hash_Z", element: "#hash_Z",
@ -49,15 +152,78 @@ define([
}] }]
} }
}; };
module.defaultFiles = JSON.parse(JSON.stringify(files));
// TODO translate // TODO translate
// TODO translate contextmenu in inner.html // TODO translate contextmenu in inner.html
var ROOT = "root"; var getLastOpenedFolder = function () {
var ROOT_NAME = "My files"; var path;
var TRASH = "trash"; try {
var TRASH_NAME = "Trash"; path = localStorage[LOCALSTORAGE_LAST] ? JSON.parse(localStorage[LOCALSTORAGE_LAST]) : [ROOT];
var TIME_BEFORE_RENAME = 1000; } catch (e) {
path = [ROOT];
}
return path;
};
var setLastOpenedFolder = function (path) {
localStorage[LOCALSTORAGE_LAST] = JSON.stringify(path);
};
var currentPath = module.currentPath = [ROOT]; var initLSOpened = function () {
try {
var store = JSON.parse(localStorage[LOCALSTORAGE_OPENED]);
if (!$.isArray(store)) {
localStorage[LOCALSTORAGE_OPENED] = '[]';
}
} catch (e) {
localStorage[LOCALSTORAGE_OPENED] = '[]';
}
};
initLSOpened();
var wasFolderOpened = function (path) {
var store = JSON.parse(localStorage[LOCALSTORAGE_OPENED]);
return store.indexOf(JSON.stringify(path)) !== -1;
};
var setFolderOpened = function (path, opened) {
var s = JSON.stringify(path);
var store = JSON.parse(localStorage[LOCALSTORAGE_OPENED]);
if (opened && store.indexOf(s) === -1) {
store.push(s);
}
if (!opened) {
var idx = store.indexOf(s);
if (idx !== -1) {
store.splice(idx, 1);
}
}
localStorage[LOCALSTORAGE_OPENED] = JSON.stringify(store);
};
var getViewModeClass = function () {
var mode = localStorage[LOCALSTORAGE_VIEWMODE];
if (mode === 'list') { return 'list'; }
return 'grid';
};
var getViewMode = function () {
return localStorage[LOCALSTORAGE_VIEWMODE] || 'grid';
};
var setViewMode = function (mode) {
if (typeof(mode) !== "string") {
console.error("Incorrect view mode: ", mode);
return;
}
localStorage[LOCALSTORAGE_VIEWMODE] = mode;
};
var DEBUG = window.DEBUG = {
resetLocalStorage : function () {
delete localStorage[LOCALSTORAGE_OPENED];
delete localStorage[LOCALSTORAGE_LAST];
}
};
var currentPath = module.currentPath = getLastOpenedFolder();
var lastSelectTime; var lastSelectTime;
var selectedElement; var selectedElement;
@ -76,6 +242,8 @@ define([
var $trashEmptyIcon = $('<span>', {"class": "fa fa-trash-o"}); var $trashEmptyIcon = $('<span>', {"class": "fa fa-trash-o"});
var $collapseIcon = $('<span>', {"class": "fa fa-minus-square-o expcol"}); var $collapseIcon = $('<span>', {"class": "fa fa-minus-square-o expcol"});
var $expandIcon = $('<span>', {"class": "fa fa-plus-square-o expcol"}); var $expandIcon = $('<span>', {"class": "fa fa-plus-square-o expcol"});
var $listIcon = $('<span>', {"class": "fa fa-list"});
var $gridIcon = $('<span>', {"class": "fa fa-th"});
var removeSelected = function () { var removeSelected = function () {
$iframe.find('.selected').removeClass("selected"); $iframe.find('.selected').removeClass("selected");
@ -109,6 +277,63 @@ define([
return typeof(element) !== "string"; return typeof(element) !== "string";
}; };
var isFolderEmpty = function (element) {
if (typeof(element) !== "object") { return false; }
return Object.keys(element).length === 0;
};
var hasSubfolder = function (element) {
if (typeof(element) !== "object") { return false; }
var subfolder = false;
for (var f in element) {
subfolder = isFolder(element[f]);
if (subfolder) { break; }
}
return subfolder;
};
var isSubpath = function (path, parentPath) {
var pathA = parentPath.slice();
var pathB = path.slice(0, pathA.length);
return comparePath(pathA, pathB);
};
var getAvailableName = function (parentEl, name) {
if (typeof(parentEl[name]) === "undefined") { return name; }
var newName = name;
var i = 1;
while (typeof(parentEl[newName]) !== "undefined") {
newName = name + "_" + i;
i++;
}
return newName;
};
var compareDays = function (date1, date2) {
var day1 = Date.UTC(date1.getFullYear(), date1.getMonth(), date1.getDate());
var day2 = Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate());
var ms = Math.abs(day1-day2);
return Math.floor(ms/1000/60/60/24);
};
var getDate = function (sDate) {
var ret = sDate.toString();
try {
var date = new Date(sDate);
var today = new Date();
var diff = compareDays(date, today);
if (diff === 0) {
ret = date.toLocaleTimeString();
} else {
ret = date.toLocaleDateString();
}
} catch (e) {
// TODO
console.error("Unable to display that string to a date with .toLocaleString", sDate, e);
}
return ret;
};
// Find an element in a object following a path, resursively // Find an element in a object following a path, resursively
var findElement = function (root, pathInput) { var findElement = function (root, pathInput) {
if (!pathInput) { if (!pathInput) {
@ -148,7 +373,8 @@ define([
} else { } else {
parentPath = elementPath.slice(); parentPath = elementPath.slice();
name = parentPath.pop(); name = parentPath.pop();
newName = name; // Automatically rename if we were in the trash since we can't rename from the trash
newName = elementPath[0] === TRASH ? getAvailableName(newParent, name) : name;
} }
var parentEl = findElement(files, parentPath); var parentEl = findElement(files, parentPath);
@ -159,7 +385,7 @@ define([
} }
newParent[newName] = element; newParent[newName] = element;
delete parentEl[name]; delete parentEl[name];
displayDirectory(newParentPath); module.displayDirectory(newParentPath);
}; };
// Move to trash // Move to trash
@ -184,9 +410,9 @@ define([
trashArray.push(trashElement); trashArray.push(trashElement);
delete parentEl[name]; delete parentEl[name];
if (displayTrash) { if (displayTrash) {
displayDirectory([TRASH]); module.displayDirectory([TRASH]);
} else { } else {
displayDirectory(currentPath); module.displayDirectory(currentPath);
} }
}; };
Cryptpad.confirm("Are you sure you want to move " + name + " to the trash?", function(res) { Cryptpad.confirm("Are you sure you want to move " + name + " to the trash?", function(res) {
@ -195,17 +421,6 @@ define([
}); });
}; };
var getAvailableName = function (parentEl, name) {
if (typeof(parentEl[name]) === "undefined") { return name; }
var newName = name;
var i = 1;
while (typeof(parentEl[newName]) !== "undefined") {
newName = name + "_" + i;
i++;
}
return newName;
};
var removeFromTrashArray = function (element, name) { var removeFromTrashArray = function (element, name) {
var array = files.trash[name]; var array = files.trash[name];
if (!array || !$.isArray(array)) { return; } if (!array || !$.isArray(array)) { return; }
@ -231,13 +446,12 @@ define([
var name = getAvailableName(newParentEl, path[1]); var name = getAvailableName(newParentEl, path[1]);
newParentEl[name] = element; newParentEl[name] = element;
removeFromTrashArray(parentEl, path[1]); removeFromTrashArray(parentEl, path[1]);
displayDirectory(currentPath); module.displayDirectory(currentPath);
}; };
var removeFromTrash = function (path) { var removeFromTrash = function (path) {
if (!path || path.length < 4 || path[0] !== TRASH) { return; } if (!path || path.length < 4 || path[0] !== TRASH) { return; }
// Remove the last element from the path to get the parent path and the element name // Remove the last element from the path to get the parent path and the element name
console.log(path);
var parentPath = path.slice(); var parentPath = path.slice();
var name; var name;
if (path.length === 4) { // Trash root if (path.length === 4) { // Trash root
@ -245,7 +459,7 @@ define([
parentPath.pop(); parentPath.pop();
var parentElement = findElement(files, parentPath); var parentElement = findElement(files, parentPath);
removeFromTrashArray(parentElement, name); removeFromTrashArray(parentElement, name);
displayDirectory(currentPath); module.displayDirectory(currentPath);
return; return;
} }
name = parentPath.pop(); name = parentPath.pop();
@ -255,24 +469,25 @@ define([
return; return;
} }
delete parentEl[name]; delete parentEl[name];
displayDirectory(currentPath); module.displayDirectory(currentPath);
}; };
var emptyTrash = function () { var emptyTrash = function () {
files.trash = {}; files.trash = {};
displayDirectory(currentPath); module.displayDirectory(currentPath);
}; };
var onDrag = function (ev, path) { var onDrag = function (ev, path) {
var data = { var data = {
'path': path 'path': path
}; };
ev.dataTransfer.setData("data", JSON.stringify(data)); ev.dataTransfer.setData("text", JSON.stringify(data));
}; };
var onDrop = function (ev) { var onDrop = function (ev) {
ev.preventDefault(); ev.preventDefault();
var data = ev.dataTransfer.getData("data"); $iframe.find('.droppable').removeClass('droppable');
var data = ev.dataTransfer.getData("text");
var oldPath = JSON.parse(data).path; var oldPath = JSON.parse(data).path;
var newPath = $(ev.target).data('path') || $(ev.target).parent('li').data('path'); var newPath = $(ev.target).data('path') || $(ev.target).parent('li').data('path');
if (!oldPath || !newPath) { return; } if (!oldPath || !newPath) { return; }
@ -313,8 +528,8 @@ define([
} }
parentEl[newName] = element; parentEl[newName] = element;
delete parentEl[oldName]; delete parentEl[oldName];
resetTree(); module.resetTree();
displayDirectory(currentPath); module.displayDirectory(currentPath);
}; };
var displayRenameInput = function ($element, path) { var displayRenameInput = function ($element, path) {
@ -379,7 +594,7 @@ define([
}; };
var openContextMenu = function (e) { var openContextMenu = function (e) {
hideMenu(); module.hideMenu();
onElementClick($(e.target)); onElementClick($(e.target));
e.stopPropagation(); e.stopPropagation();
var path = $(e.target).data('path') || $(e.target).parent('li').data('path'); var path = $(e.target).data('path') || $(e.target).parent('li').data('path');
@ -408,7 +623,7 @@ define([
}; };
var openTrashTreeContextMenu = function (e) { var openTrashTreeContextMenu = function (e) {
hideMenu(); module.hideMenu();
onElementClick($(e.target)); onElementClick($(e.target));
e.stopPropagation(); e.stopPropagation();
var path = $(e.target).data('path') || $(e.target).parent('li').data('path'); var path = $(e.target).data('path') || $(e.target).parent('li').data('path');
@ -424,7 +639,7 @@ define([
}; };
var openTrashContextMenu = function (e) { var openTrashContextMenu = function (e) {
hideMenu(); module.hideMenu();
onElementClick($(e.target)); onElementClick($(e.target));
e.stopPropagation(); e.stopPropagation();
var path = $(e.target).data('path') || $(e.target).parent('li').data('path'); var path = $(e.target).data('path') || $(e.target).parent('li').data('path');
@ -444,8 +659,16 @@ define([
}; };
var addDragAndDropHandlers = function ($element, path, isFolder, droppable) { var addDragAndDropHandlers = function ($element, path, isFolder, droppable) {
// "dragenter" is fired for an element and all its children
// "dragleave" may be fired when entering a child
// --> We store the number of enter/leave and the element entered and we remove the
// highlighting only when we have left everything
var counter = 0;
var dragenterList = [];
$element.on('dragstart', function (e) { $element.on('dragstart', function (e) {
e.stopPropagation(); e.stopPropagation();
counter = 0;
dragenterList = [];
onDrag(e.originalEvent, path); onDrag(e.originalEvent, path);
}); });
@ -458,28 +681,51 @@ define([
$element.on('drop', function (e) { $element.on('drop', function (e) {
onDrop(e.originalEvent); onDrop(e.originalEvent);
}); });
var counter = 0;
$element.on('dragenter', function (e) { $element.on('dragenter', function (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (dragenterList.indexOf(e.target) !== -1) { return; }
dragenterList.push(e.target);
counter++; counter++;
$element.addClass('droppable'); $element.addClass('droppable');
}); });
$element.on('dragleave', function (e) { $element.on('dragleave', function (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
var idx = dragenterList.indexOf(e.target);
dragenterList.splice(idx, 1);
counter--; counter--;
if (counter === 0) { if (counter <= 0) {
$element.removeClass('droppable'); $element.removeClass('droppable');
} }
}); });
}; };
var addFileData = function (parentPath, key, $span) {
var parentEl = findElement(files, parentPath);
if (!parentEl || !parentEl[key] || !isFile(parentEl[key])) { return; }
var element = parentEl[key];
if (typeof(files[FILES_DATA][element]) === "undefined") {
return;
}
var data = files[FILES_DATA][element];
$span.html('');
// The element with the class '.name' is underlined when the 'li' is hovered
$span.removeClass('name');
var $name = $('<span>', {'class': 'name'}).text(key);
var $title = $('<span>', {'class': 'title'}).text(data.title);
var $adate = $('<span>', {'class': 'date'}).text(getDate(data.atime));
var $cdate = $('<span>', {'class': 'date'}).text(getDate(data.ctime));
$span.append($name).append($title).append($adate).append($cdate);
return;
};
var createElement = function (path, elPath, root, isFolder) { var createElement = function (path, elPath, root, isFolder) {
// Forbid drag&drop inside the trash // Forbid drag&drop inside the trash
var isTrash = path[0] === TRASH; var isTrash = path[0] === TRASH;
var newPath = path.slice(); var newPath = path.slice();
var key;
if (isTrash && $.isArray(elPath)) { if (isTrash && $.isArray(elPath)) {
key = elPath[0]; key = elPath[0];
@ -490,20 +736,22 @@ define([
} }
var $icon = $fileIcon.clone(); var $icon = $fileIcon.clone();
var spanClass = 'file-element element'; var spanClass = 'file-element name element';
if (isFolder) { if (isFolder) {
spanClass = 'folder-element element'; spanClass = 'folder-element name element';
$icon = Object.keys(root[key]).length === 0 ? $folderEmptyIcon.clone() : $folderIcon.clone(); $icon = isFolderEmpty(root[key]) ? $folderEmptyIcon.clone() : $folderIcon.clone();
} }
var $name = $('<span>', { 'class': spanClass }).text(key); var $name = $('<span>', { 'class': spanClass }).text(key);
if(!isFolder && getViewMode() === 'list') {
addFileData(path, key, $name);
}
var $element = $('<li>', { var $element = $('<li>', {
draggable: true draggable: true
}).append($icon).append($name).dblclick(function () { }).append($icon).append($name).dblclick(function () {
if (isFolder) { if (isFolder) {
displayDirectory(newPath); module.displayDirectory(newPath);
return; return;
} }
// Prevent users from opening files from the trash TODO ??
if (isTrash) { return; } if (isTrash) { return; }
openFile(root[key]); openFile(root[key]);
}); });
@ -536,7 +784,7 @@ define([
} }
} }
return title; return title;
} };
var createTitle = function (path) { var createTitle = function (path) {
var isTrash = path[0] === TRASH; var isTrash = path[0] === TRASH;
@ -556,16 +804,50 @@ define([
// --> parent is TRASH // --> parent is TRASH
newPath = [TRASH]; newPath = [TRASH];
} }
displayDirectory(newPath); module.displayDirectory(newPath);
}); });
$title.append($parentFolder); $title.append($parentFolder);
} }
return $title; return $title;
}; };
var createViewModeButton = function () {
var $block = $('<div>', {
'class': 'btn-group changeViewModeContainer'
});
var $listButton = $('<button>', {
'class': 'btn'
}).append($listIcon.clone());
var $gridButton = $('<button>', {
'class': 'btn'
}).append($gridIcon.clone());
$listButton.click(function () {
$gridButton.removeClass('active');
$listButton.addClass('active');
setViewMode('list');
$iframe.find('#' + FOLDER_CONTENT_ID).removeClass('grid');
});
$gridButton.click(function () {
$listButton.removeClass('active');
$gridButton.addClass('active');
setViewMode('grid');
$iframe.find('#' + FOLDER_CONTENT_ID).addClass('grid');
});
if (getViewMode() === 'list') {
$listButton.addClass('active');
} else {
$gridButton.addClass('active');
}
$block.append($listButton).append($gridButton);
return $block;
};
// Display the selected directory into the content part (rightside) // Display the selected directory into the content part (rightside)
// NOTE: Elements in the trash are not using the same storage structure as the others // NOTE: Elements in the trash are not using the same storage structure as the others
var displayDirectory = function (path) { var displayDirectory = module.displayDirectory = function (path) {
currentPath = path; currentPath = path;
module.resetTree(); module.resetTree();
$content.html(""); $content.html("");
@ -586,9 +868,16 @@ define([
return; return;
} }
setLastOpenedFolder(path);
var $title = createTitle(path); var $title = createTitle(path);
var $dirContent = $('<div>', {id: "folderContent"}); var $modeButton = createViewModeButton().appendTo($title);
var $dirContent = $('<div>', {id: FOLDER_CONTENT_ID});
if (getViewModeClass()) {
$dirContent.addClass(getViewModeClass());
}
var $list = $('<ul>').appendTo($dirContent); var $list = $('<ul>').appendTo($dirContent);
if (isTrashRoot) { if (isTrashRoot) {
@ -633,17 +922,39 @@ define([
var createTreeElement = function (name, $icon, path, draggable, collapsable, active) { var createTreeElement = function (name, $icon, path, draggable, collapsable, active) {
var $name = $('<span>', { 'class': 'folder-element element' }).text(name) var $name = $('<span>', { 'class': 'folder-element element' }).text(name)
.click(function () { .click(function () {
displayDirectory(path); module.displayDirectory(path);
}); });
var $collapse; var $collapse;
if (collapsable) { if (collapsable) {
$collapse = $collapseIcon.clone(); $collapse = $expandIcon.clone();
} }
var $element = $('<li>', { var $element = $('<li>', {
draggable: draggable draggable: draggable
}).append($collapse).append($icon).append($name); }).append($collapse).append($icon).append($name);
if (!collapsable) { if (collapsable) {
$element.addClass('non-collapsable'); $element.addClass('collapsed');
$collapse.click(function() {
if ($element.hasClass('collapsed')) {
// It is closed, open it
$element.removeClass('collapsed');
setFolderOpened(path, true);
$collapse.removeClass('fa-plus-square-o');
$collapse.addClass('fa-minus-square-o');
} else {
// Collapse the folder
$element.addClass('collapsed');
setFolderOpened(path, false);
$collapse.removeClass('fa-minus-square-o');
$collapse.addClass('fa-plus-square-o');
// Change the current opened folder if it was collapsed
if (isSubpath(currentPath, path)) {
displayDirectory(path);
}
}
});
if (wasFolderOpened(path)) {
$collapse.click();
}
} }
$element.data('path', path); $element.data('path', path);
addDragAndDropHandlers($element, path, true, true); addDragAndDropHandlers($element, path, true, true);
@ -678,13 +989,13 @@ define([
var createTree = function ($container, path) { var createTree = function ($container, path) {
var root = findElement(files, path); var root = findElement(files, path);
if (Object.keys(root).length === 0) { return; } if (isFolderEmpty(root)) { return; }
// Display the root element in the tree // Display the root element in the tree
var displayingRoot = comparePath([ROOT], path); var displayingRoot = comparePath([ROOT], path);
if (displayingRoot) { if (displayingRoot) {
var isRootOpened = comparePath([ROOT], currentPath); var isRootOpened = comparePath([ROOT], currentPath);
var $rootIcon = Object.keys(files[ROOT]).length === 0 ? var $rootIcon = isFolderEmpty(files[ROOT]) ?
(isRootOpened ? $folderOpenedEmptyIcon : $folderEmptyIcon) : (isRootOpened ? $folderOpenedEmptyIcon : $folderEmptyIcon) :
(isRootOpened ? $folderOpenedIcon : $folderIcon); (isRootOpened ? $folderOpenedIcon : $folderIcon);
var $rootElement = createTreeElement(ROOT_NAME, $rootIcon.clone(), [ROOT], false, false, isRootOpened); var $rootElement = createTreeElement(ROOT_NAME, $rootIcon.clone(), [ROOT], false, false, isRootOpened);
@ -701,11 +1012,12 @@ define([
var newPath = path.slice(); var newPath = path.slice();
newPath.push(key); newPath.push(key);
var isCurrentFolder = comparePath(newPath, currentPath); var isCurrentFolder = comparePath(newPath, currentPath);
var isEmpty = Object.keys(root[key]).length === 0; var isEmpty = isFolderEmpty(root[key]);
var subfolder = hasSubfolder(root[key]);
var $icon = isEmpty ? var $icon = isEmpty ?
(isCurrentFolder ? $folderOpenedEmptyIcon : $folderEmptyIcon) : (isCurrentFolder ? $folderOpenedEmptyIcon : $folderEmptyIcon) :
(isCurrentFolder ? $folderOpenedIcon : $folderIcon); (isCurrentFolder ? $folderOpenedIcon : $folderIcon);
var $element = createTreeElement(key, $icon.clone(), newPath, true, !isEmpty, isCurrentFolder); var $element = createTreeElement(key, $icon.clone(), newPath, true, subfolder, isCurrentFolder);
$element.appendTo($list); $element.appendTo($list);
$element.contextmenu(openContextMenu); $element.contextmenu(openContextMenu);
createTree($element, newPath); createTree($element, newPath);
@ -713,13 +1025,13 @@ define([
}; };
var createTrash = function ($container, path) { var createTrash = function ($container, path) {
var $icon = Object.keys(files.trash).length === 0 ? $trashEmptyIcon.clone() : $trashIcon.clone(); var $icon = isFolderEmpty(files.trash) ? $trashEmptyIcon.clone() : $trashIcon.clone();
var isOpened = comparePath(path, currentPath); var isOpened = comparePath(path, currentPath);
var $trash = $('<span>', { var $trash = $('<span>', {
'class': 'tree-trash element' 'class': 'tree-trash element'
}).text(TRASH_NAME).prepend($icon) }).text(TRASH_NAME).prepend($icon)
.click(function () { .click(function () {
displayDirectory(path); module.displayDirectory(path);
}); });
var $trashElement = $('<li>').append($trash); var $trashElement = $('<li>').append($trash);
$trashElement.addClass('root'); $trashElement.addClass('root');
@ -737,10 +1049,10 @@ define([
createTree($tree, [ROOT]); createTree($tree, [ROOT]);
createTrash($tree, [TRASH]); createTrash($tree, [TRASH]);
}; };
displayDirectory(currentPath); module.displayDirectory(currentPath);
//resetTree(); //already called by displayDirectory //resetTree(); //already called by displayDirectory
var hideMenu = function () { var hideMenu = module.hideMenu = function () {
$contextMenu.hide(); $contextMenu.hide();
$trashTreeContextMenu.hide(); $trashTreeContextMenu.hide();
$trashContextMenu.hide(); $trashContextMenu.hide();
@ -760,7 +1072,7 @@ define([
else if ($(this).hasClass('open')) { else if ($(this).hasClass('open')) {
$element.dblclick(); $element.dblclick();
} }
hideMenu(); module.hideMenu();
}); });
$trashTreeContextMenu.on('click', 'a', function (e) { $trashTreeContextMenu.on('click', 'a', function (e) {
@ -775,7 +1087,7 @@ define([
emptyTrash(); emptyTrash();
}); });
} }
hideMenu(); module.hideMenu();
}); });
$trashContextMenu.on('click', 'a', function (e) { $trashContextMenu.on('click', 'a', function (e) {
@ -783,8 +1095,8 @@ define([
var path = $(this).data('path'); var path = $(this).data('path');
var $element = $(this).data('element'); var $element = $(this).data('element');
if (!$element || !path || path.length < 2) { return; } // TODO: error if (!$element || !path || path.length < 2) { return; } // TODO: error
var name = path[path.length - 1];
if ($(this).hasClass("remove")) { if ($(this).hasClass("remove")) {
var name = path[path.length - 1];
if (path.length === 4) { name = path[1]; } if (path.length === 4) { name = path[1]; }
// TODO translate // TODO translate
Cryptpad.confirm("Are you sure you want to remove " + name + " from the trash permanently?", function(res) { Cryptpad.confirm("Are you sure you want to remove " + name + " from the trash permanently?", function(res) {
@ -793,7 +1105,6 @@ define([
}); });
} }
else if ($(this).hasClass("restore")) { else if ($(this).hasClass("restore")) {
var name = path[path.length - 1];
if (path.length === 4) { name = path[1]; } if (path.length === 4) { name = path[1]; }
// TODO translate // TODO translate
Cryptpad.confirm("Are you sure you want to restore " + name + " to its previous location?", function(res) { Cryptpad.confirm("Are you sure you want to restore " + name + " to its previous location?", function(res) {
@ -801,18 +1112,18 @@ define([
restoreTrash(path); restoreTrash(path);
}); });
} }
hideMenu(); module.hideMenu();
}); });
$(ifrw).on('click', function (e) { $(ifrw).on('click', function (e) {
if (e.which !== 1) { return ; } if (e.which !== 1) { return ; }
removeSelected(e); removeSelected(e);
removeInput(e); removeInput(e);
hideMenu(e); module.hideMenu(e);
}); });
$(ifrw).on('drag drop', function (e) { $(ifrw).on('drag drop', function (e) {
removeInput(e); removeInput(e);
hideMenu(e); module.hideMenu(e);
}); });
$(ifrw).on('mouseup drop', function (e) { $(ifrw).on('mouseup drop', function (e) {
$iframe.find('.droppable').removeClass('droppable'); $iframe.find('.droppable').removeClass('droppable');