Написал на JS обычное дерево файловой структуры. (добавление, редактирование, удаление папки), после каждого события объект перезаписывается в localStorage и при перезагрузки страницы отрисовка идет уже измененного объекта.
Хотелось бы получить от вас критику по коду, как говорится - “разнесите меня в щепки”, уровень js у меня - junior, хочу развиваться дальше, поэтому прошу вашей критики.
Рабочий вариант по ссылке - http://kustov-work.ru/
HTML
<div class="wrapper">
<div id="file_structure">
</div>
</div>
JS
window.onload = function() {
const parent_tree = document.querySelector('#file_structure');
$.getJSON("ajax/tree.json",function(result) {
let tree; // создаем переменную которая будет ссылкой на объект дерева
if (localStorage.getItem('tree') != null) { // проверка наличия объекта в localStorage
tree = JSON.parse(localStorage.getItem('tree')); // возвращенный объект из localstorage
console.log('объект подгруженный из localStorage -', tree);
} else {
tree = result; // запись результата JSON в переменную
console.log('объект подгруженный из JSON -', tree);
}
drawingTree(tree, parent_tree);
parent_tree.onclick = function(e) {
let el = e.target;
let el_parent = findAncestor(el ,'li');
let el_parent_id = el_parent.id;
let arr_path = el_parent_id.split('.'); // разбиваем полученный id на массив, это будет путь до текущего вложенного объекта
let path_obj = findFolder(arr_path, tree); // путь до ключа объекта
/*событие для добавления новой папки*/
if (el.classList.contains('add_folder')) {
let nameFolder = prompt('Введите название папки');
if (nameFolder === null || nameFolder === '') {
return;
} else {
let el_list = el_parent.querySelector('ul');
let elem_li = document.createElement('li');
if (el_list === undefined || el_list === null) {
el_list = document.createElement('ul');
el_parent.append(el_list);
}
addElementInObj(path_obj, nameFolder, el_list, elem_li);
}
/*событие для изминения имени папки*/
} else if (el.classList.contains('edit_folder')) {
let editNameFolder = prompt('Введите новое название папки');
if (editNameFolder === null || editNameFolder === '') {
return;
} else {
let el_span = el_parent.querySelector('span');
editElementInObj(path_obj, el_span, editNameFolder);
}
/*событие для удаления папки*/
} else if (el.classList.contains('remove_folder')) {
let el_list = el_parent.parentElement;
el_parent.remove();
/*проверка, если в ul не осталось потомков li, то удаляем родительский ul*/
if (el_list.querySelectorAll('li').length === 0) {
el_list.remove();
}
removeElementInObj(path_obj, tree);
}
loacalStorageWrite(tree);
console.log('Измененый объект, после события -', tree);
}
});
function loacalStorageWrite(obj) {
localStorage.clear(); // очищаем localStorage
let serialObj = JSON.stringify(obj);
localStorage.setItem('tree', serialObj);
}
/*Добавление новой папки в объект и отображеие на странице*/
function addElementInObj(path, nameFolder, el_list, el_li) {
let id = generateID(path);
elemCreate(el_list,el_li,nameFolder, id[0]);
path.dother['div'+id[1]] = {
nameFolder: nameFolder,
id: id[0],
dother: {}
};
}
/*изинения имени папки (в объекте)*/
function editElementInObj(path, el_span, editNameFolder) {
path.nameFolder = editNameFolder;
el_span.innerHTML = editNameFolder;
}
/*удаление ключа папки*/
function removeElementInObj(path , obj) {
delete path.id;
delete path.nameFolder;
delete path.dother;
removeEmptyObj(obj);
}
function removeEmptyObj(obj) { // удаляет пустой ключ объекта
for (var key in obj) {
if (isEmpty(obj[key])) {
delete obj[key];
return false;
}
removeEmptyObj(obj[key]['dother']);
}
}
/*генерируем id в зависимости от вложенности текущей папки*/
function generateID (path) {
let this_id = path.id; // текущий id
if (typeof path.dother === 'undefined') { // если по нашему пути еще нет созданных дочерних папок, то создаем для них объект
path.dother = {};
}
/*определяем номер последней дочерней папки по нашему пути*/
/*в дальнейшем этот номер используем для создания следующей папки с новым номером, чтобы объект не перезаписывался*/
let arr_dother = Object.keys(path.dother);
let number_dother;
if (arr_dother.length === 0) {
number_dother = 0;
} else {
let arr_number_dother = arr_dother[arr_dother.length - 1].split('v');
number_dother = arr_number_dother[1];
}
let count_dother = Number(number_dother) + 1;
let id_result = this_id + '.' + count_dother; // генерация id
let arr = [id_result,count_dother]; // id для папки/номер для ключа div в объекте
return arr;
}
/*поиск нужного родителя*/
function findAncestor (el, cls) {
while ((el = el.parentElement) && !el.matches(cls));
return el;
}
/*ищет путь по объекту до нужного ключа*/
function findFolder(array, obj) {
let newLinkObject = Object;
for (var i = 0; i < array.length; i++) {
if (isEmpty(newLinkObject)) {
newLinkObject = obj['div'+array[i]];
} else {
newLinkObject = newLinkObject['dother']['div'+array[i]];
}
if (array.length === i+1) {
return newLinkObject;
}
}
return newLinkObject;
}
/*проверка объекта на пустоту*/
function isEmpty(obj) {
for (var key in obj) {
return false;
}
return true;
}
/*отрисовка дерева в DOM*/
function drawingTree(obj,parent) {
let obgKey = obj;
let element = document.createElement('ul');
if (obgKey != null) {
for (var key in obj) {
if (Object.keys(obj[key]).length !== 0) {
let elem_li = document.createElement('li');
elemCreate(element,elem_li,obj[key]['nameFolder'],obj[key]['id']);
parent.append(element);
if (typeof obj[key]['dother'] !== "undefined" && obj[key]['dother'] !== null) {
drawingTree(obj[key]['dother'],elem_li);
} else {
continue;
}
}
}
} else {
return false;
}
}
/*создает элемент дерева в DOM*/
function elemCreate(element,elem_li,name,id) {
let wrap = document.createElement('div');
wrap.innerHTML = '<div class="item_img">'+
'<img src="../img/folder.png" alt="папка" title="папка"/>'+
'</div>'+
'<div class="item_name">'+
'<span>'+name+'</span>'+
'</div>', wrap.classList = 'item_wrap';
elem_li.append(wrap);
elem_li.id = id;
element.append(elem_li);
btnCreate(wrap,'button', '', 'add_folder');
btnCreate(wrap,'button', '', 'edit_folder');
btnCreate(wrap,'button', '', 'remove_folder');
}
function btnCreate(parent,type, text, class_name) {
let btn_add = document.createElement(type);
btn_add.innerHTML = text;
btn_add.classList.add(class_name);
parent.append(btn_add);
}
}
Изначальный JSON
{
"div1": {
"nameFolder": "папка",
"id": "1"
}
}