﻿// ******************************************************************* Объект файл ******************************************************************

// Файл
function File(
        pFarOwner,              // ссылка на браузер файлов, к которому относится файл
        pName,                  // имя файла
        pPath,                  // путь к файлу (пустая строка в случае основного каталога)
        pOwnerName,             // владелец (имя пользователя или гость)
        pIsPhantom,             // фантомный ли файл (фантомный - т.е. не сохраненный на сервере)
        pPhantomType,           // тип фантомного файла (новый[new], пример[sample], опубликованный файл[public])
        pIsShared               // открыт ли файл для общего доступа
){

// ----------------------------------------- Поля

    this.farOwner = pFarOwner;                      // ссылка на браузер файлов, к которому относится файл
    this.name = pName;                              // имя файла
    this.viewName = file_GetViewName(pName);        // отображаемое имя файла (если не слишком длинное, то само pName)
    this.path = pPath;                              // путь к файлу
    this.fullName = pPath +                         // полное имя файла  
        ((pPath!="") ? "/" : "") + pName;    
    this.fullViewName = file_GetViewName(           // отображаемое полное имя файла
        this.fullName);                                 
    
    this.ownerStatus = (pOwnerName == Guest) ?      // статус владельца (пользователь или гость)
        Guest : User;
    this.isByUser = (this.ownerStatus != Guest);     // пользовательский ли это файл
    this.ownerName = (this.isByUser) ? pOwnerName :  // владелец (имя пользователя или ID сессии)
         currSessionID;
    
    this.isPhantom = (pIsPhantom != undefined) ?    // фантомный ли файл (фантомный - т.е. не сохраненный на сервере)
        pIsPhantom : false;
    this.phantomType = (pPhantomType) ?             // тип фантомного файла (новый[new], пример[sample], опубликованный файл[public])
        pPhantomType : null;
        
    this.isOpened = false;                          // открыт ли файл в редакторе
    this.tabID = null;                              // ID вкладки в редакторе
    
    this.sourceCode = "";                           // по необходимости можно использовать для хранения содержимого
    
    this.typeIsKnown = false;                       // известен ли тип файла
    this.type = null;                               // тип файла
    
    this.isShared = (pIsShared != undefined) ?      // открыт ли файл для общего доступа
        pIsShared : false;
    
// ----------------------------------------- Методы
    this.open = file_Open;                          // открывает файл (в редакторе тоже)
    this.close = file_Close;                        // закрывает файл (в редакторе тоже)
    this.active = file_Active;                      // активирует файл в редакторе
    this.save = file_Save;                          // устанавливает статус измененности в редакторе в ложь
    
    this.setFullName = file_SetFullName;            // изменяет имя файла по полному имени
    this.setName = file_SetName;                    // изменяет имя файла
    
    this.updateTabTitle = file_UpdateTabTitle;      // обновляет заголовок вкладки в соответствии с именем файла
    
    this.setSourceCode = file_SetSourceCode;        // изменяет содержимое файла
    
    this.setNotPhantom = file_SetNotPhantom;        // изменяет статус файла на нефантомный
    this.setStatusClosed = file_SetStatusClosed;    // изменяет статус файла на закрытый
    this.setStatusOpened = file_SetStatusOpened;    // изменяет статус файла на открытый
    
    this.share = file_Share;                        // изменяет статус файла на открытый в доступе
    this.unshare = file_Unshare;                    // изменяет статус файла на закрытый в доступе 
}

// ******************************************************************* Методы файла *****************************************************************

// Открывает файл
// fileContent - содержимое файла
function file_Open(fileContent){
    this.isOpened = true;
    this.tabID = newID;
    var pos = this.fullViewName.lastIndexOf('.');
    var ext = this.fullViewName.substring(pos);
    //alert(ext);
    if (ext == ".cs") {
        var newFile_cs = { id: newID, title: this.fullViewName, text: fileContent, syntax: 'csharp' };
        //alert(newFile_cs.syntax);
        editAreaLoader.openFile(EDIT_AREA_SOURCE_ID, newFile_cs);
    }
    else if (ext == ".fs") {
        var newFile_fs = { id: newID, title: this.fullViewName, text: fileContent, syntax: 'csharp' };
        //alert(newFile_cs.syntax);
        editAreaLoader.openFile(EDIT_AREA_SOURCE_ID, newFile_fs);
    }
    else {
        var newFile_pas = { id: newID, title: this.fullViewName, text: fileContent, syntax: 'pabc' };
        //alert(newFile_pas.syntax);
        editAreaLoader.openFile(EDIT_AREA_SOURCE_ID, newFile_pas);
    }
    NextFileParams();       // получение следующего newID
}
// Активирует файл в редакторе (это если файл уже был открыт)
function file_Active(){
    if (!this.isOpened)     // если файл в редакторе не открыт, значит метод вызван некорректно
        return;
    editAreaLoader.switchToFile(EDIT_AREA_SOURCE_ID, this.tabID);
}
// Закрывает файл
function file_Close() {
    if (!this.isOpened)     // если файл уже закрыт
        return;

    editAreaLoader.closeFile(EDIT_AREA_SOURCE_ID, this.tabID);
    this.setStatusClosed();
}

// Устанавливает статус измененности в редакторе в ложь
function file_Save(){
    editAreaLoader.setFileEditedMode(EDIT_AREA_SOURCE_ID, this.tabID, false);
}                      


// Изменяет имя файла по полному имени
function file_SetFullName(newFullFileName){
    this.name = file_GetNameByFullName(newFullFileName);
    this.viewName = file_GetViewName(this.name);
    this.fullName = newFullFileName;
    this.fullViewName = file_GetViewName(this.fullName);
}
// Изменяет имя файла
function file_SetName(newFileName){
    this.name = newFileName;
    this.viewName = file_GetViewName(newFileName);
    this.fullName = this.path + ((this.path!=MAIN_PATH) ? "/" : "") + newFileName;
    this.fullViewName = file_GetViewName(this.fullName);
}


// Обновляет заголовок вкладки в соответствии с именем файла
function file_UpdateTabTitle(){
    if (this.isOpened){
        this.active();
        var sourceCode = editAreaLoader.getValue(EDIT_AREA_SOURCE_ID);

        var newFile = {title: this.fullViewName, text: sourceCode};
        editAreaLoader.changeFile(EDIT_AREA_SOURCE_ID, newFile);
    }
} 


// Изменяет содержимое файла
function file_SetSourceCode(newSourceCode){
    this.sourceCode = newSourceCode;
}

// Изменяет статус файла на нефантомный
function file_SetNotPhantom(){
    this.isPhantom = false;
    this.phantomType = null;
}

// Изменяет статус файла на закрытый
function file_SetStatusClosed(){
    this.isOpened = false;
    this.tabID = null;
}
// Изменяет статус файла на открытый
function file_SetStatusOpened(tabID){
    this.isOpened = true;
    this.tabID = tabID;
}


// Вовращает имя файла, доступное для отображения
function file_GetViewName(FileName){
    if (FileName.length <= MAX_VIEW_FILE_NAME_LENGTH)
        return FileName;

    var ownFileNamePartLength = MAX_VIEW_FILE_NAME_LENGTH - VIEW_FILE_NAME_END.length;
    var ownFileNamePart = FileName.substr(0, ownFileNamePartLength);
    return ownFileNamePart + VIEW_FILE_NAME_END;
}
// Возвращает имя файла по полному пути
function file_GetNameByFullName(fullFileName){
    var lastIndOfDelim = fullFileName.lastIndexOf("/");
    var fileNameStartInd = lastIndOfDelim + 1;
    return fullFileName.substr(fileNameStartInd);
}

// Изменяет статус файла на открытый в доступе
function file_Share(){
    this.isShared = true;        
}
// Изменяет статус файла на закрытый в доступе 
function file_Unshare(){
    this.isShared = false; 
}                 


// **************************************************************** Объект директория ***************************************************************

// Каталог
function Directory(
    pName,                  // имя каталога
    pPath,                  // путь к каталогу (пустая строка в случае основного каталога)
    pOwnerName              // имя пользователя
){

// ----------------------------------------- Поля
    this.name = pName;                              // имя каталога
    this.viewName = directory_GetViewName(pName);   // отображаемое имя каталога
    this.path = pPath;                              // путь к каталогу
    this.fullName = pPath +                         // полное имя каталога
        ((pPath!="") ? "/" : "") + pName;
    this.ownerName = pOwnerName;                    // имя пользователя
    
// ----------------------------------------- Методы
    this.setFullName = directory_SetFullName;        // изменяет имя каталога по полному имени
    this.setName = directory_SetName;                // изменяет имя каталога
}

// Изменяет имя каталога по полному имени
function directory_SetFullName(newFullDirectoryName){
    this.name = directory_GetNameByFullName(newFullDirectoryName);
    this.viewName = directory_GetViewName(this.name);
    this.fullName = newFullDirectoryName;
}

// Изменяет имя каталога
function directory_SetName(newDirectoryName){
    this.name = newDirectoryName;
    this.viewName = directory_GetViewName(newDirectoryName);
    this.fullName = this.path + ((this.path!="") ? "/" : "") + newDirectoryName;
}


// Вовращает имя каталога, доступное для отображения
function directory_GetViewName(directoryName){
    if (directoryName.length <= MAX_VIEW_FILE_NAME_LENGTH)
        return directoryName;

    var ownDirectoryNamePartLength = MAX_VIEW_FILE_NAME_LENGTH - DOTS_STR.length;
    var ownDirectoryNamePart = directoryName.substr(0, ownDirectoryNamePartLength);
    return ownDirectoryNamePart + DOTS_STR;
}

// Возвращает имя каталога по полному пути
function directory_GetNameByFullName(fullDirectoryName){
    var lastIndOfDelim = fullDirectoryName.lastIndexOf("/");
    var directoryNameStartInd = lastIndOfDelim + 1;
    return fullDirectoryName.substr(directoryNameStartInd);
}   


// ***************************************************************** Браузер файлов *****************************************************************

// Объект каталога
function DirectoryContent(
    pFileItemsList,                 // список файловых единиц
    pLastAccessTime                 // время последнего доступа к каталогу
){
    this.fileItemsList = pFileItemsList;        // список файловых единиц
    this.lastAccessTime = pLastAccessTime;      // время последнего доступа к каталогу
    
    this.firstDirLink = null;                   // первая ссылка на каталог          
}


//Файловая единица
function ItemInfo(
    itemName,                       // имя
    itemType,                       // тип (файл или директория)
    isShared                        // расшарен ли
){
    this.ItemName = itemName;                   // имя
    this.ItemType = itemType;                   // тип (файл или директория)
    this.IsShared = isShared;                   // расшарен ли
}


// Браузер файлов
function Far(
    pDivID,                         // ID блока, к которому привязывать браузер
    pUserName,                      // имя пользователя (т.е. основного каталога) 
    pFarName                        // Имя переменной, которая отвечает за данный браузер файлов
){
// ----------------------------------------- Поля
    this.farName = pFarName;        // Имя переменной, которая отвечает за данный браузер файлов

    this.divID = pDivID;            // ID блока, к которому привязывать браузер
    this.tableID = FAR_TABLE;       // ID таблицы, которую представляет браузер
    this.userName = pUserName;      // имя пользователя (т.е. основного каталога)
    
    this.currentDir = MAIN_PATH;    // текущий каталог  
    this.lastChosenDir = MAIN_PATH; // последний выбранный каталог (для загрузки файлов)
    this.dirsHash = [];             // хэш всех каталогов 
    this.dirNames = new Array();    // массив имен каталогов
    
    this.currentDirLabelID = "currentFarDirLabel";
    this.parentDirLabelID = "parentFarDirLabel";
    
    this.filesCommonCount = 0;      // общее кол-во файлов

// ----------------------------------------- Методы
    this.load = far_Load;                                       // Загрузить
    this.directoryIsLoaded = far_DirectoryIsLoaded;             // Загружено ли содержимое каталога
    
    this.unload = far_Unload;                                   // Выгрузить браузер
    
    this.display = far_Display;                                 // Отобразить браузер
    this.loadParentDirectory = far_LoadParentDirectory;         // Загрузка родительского каталога
    
    this.deleteFile = far_DeleteFile;                           // Удаление файла из списка браузера 
    this.renameFile = far_RenameFile;                           // Переименование файла в списке браузера
    this.renameDirectory = far_RenameDirectory;                 // Переименование каталога в списке браузера
    this.addNewFile = far_AddNewFile;                           // Добавляет в список браузера файлов
    this.nameExists = far_NameExists;                           // Проверка существования такого имени
    this.addNewDirectory = far_AddNewDirectory;                 // Добавляет каталог в список браузера файлов
    this.deleteDirectory = far_DeleteDirectory;                 // Удаление каталога из списка браузера 
    this.clearDirectory = far_ClearDirectory;                   // Очищает список браузера от файлов и подкаталогов каталога
    
    this.removeFarTable = far_RemoveFarTable;                   // Удалить таблицу браузера
    this.addFarTable = far_AddFarTable;                         // Добавить таблицу браузера
    
    this.addManageLabels = far_AddManageLabels;                 // Добавить метку каталога
    
    this.getEldestDirectory = far_GetEldestDirectory;           // Возвращает имя каталога, использовавшегося раньше всех
    this.clearFirstDirLink = far_ClearFirstDirLink;             // Очищает ссылку на первый файл каталога
}

// ****************************************************************** Методы браузера ***************************************************************

// Загрузка браузера файлов
// fileItems - имена файлов каталога
// directory - имя каталога (пустой в случае основного)
function far_Load(fileItems, directory){
    var parDirectory;
    // приводим имя каталога к корректному виду
    if ((directory == undefined) || (directory == "")){
        directory = "";
        parDirectory = MAIN_PATH_ID;
    }
    else 
        parDirectory = directory;
    parDirectory = quote + parDirectory + quote;
    
    // проверяем, есть ли еще место в браузере, и,
    // если нет, то очищаем
    var clearDemanded = (this.filesCommonCount+fileItems.length > MAX_FILES_COUNT) &&
        (this.filesCommonCount > 0);
    while (clearDemanded){
        // находим имя подкаталога, к которому обращались раньше всего
        var eldestDir = this.getEldestDirectory();
        this.dirNames.splice(eldestDir.index, 1);
        this.filesCommonCount -= this.dirsHash[eldestDir.name].fileItemsList.length; 
        if (this.filesCommonCount < 0)
            this.filesCommonCount = 0;
        this.dirsHash[eldestDir.name] = null;
        
        clearDemanded = (this.filesCommonCount+fileItems.length > MAX_FILES_COUNT) &&
            (this.filesCommonCount > 0);
    }
    
    // добавляем каталог в список
    this.dirNames.push(parDirectory);
    this.dirsHash[parDirectory] = new DirectoryContent(fileItems, new Date());
    this.currentDir = directory;
    this.filesCommonCount += fileItems.length;
    
    var ndi = 0;
    // добавляем в хэш все каталоги
    for (ndi = 0; ndi < fileItems.length; ++ndi){
        if (fileItems[ndi].ItemType == IS_DIRECTORY){
            var parDirName = "\"" + fileItems[ndi].ItemName + "\"";
            this.dirsHash[parDirName] = null;//new DirectoryContent(new Array(), new Date());
            this.dirNames.push(parDirName);
        }
    }
    
    this.display();
}

// Отобразить браузер
function far_Display(){
    this.removeFarTable();
    this.addFarTable();
    
    // приводим параметр текущего каталога к корректному виду
    var parCurrentDir = (this.currentDir != MAIN_PATH) ? this.currentDir : MAIN_PATH_ID;
        currentDir = MAIN_PATH;
    parCurrentDir = quote + parCurrentDir + quote;
    
    // обновляем время обращения к каталогу
    this.dirsHash[parCurrentDir].lastAccessTime = new Date();
    // получаем список файловых единиц каталога
    var currentFileItems = this.dirsHash[parCurrentDir].fileItemsList;              // текущие файловые единицы
    
    var filesDiv = $get(this.divID);
    var filesTable = $get(this.tableID);
    var firstDirCreated = false;
    var cfi = 0;
    for (cfi = 0; cfi < currentFileItems.length; ++cfi){
        if (currentFileItems[cfi].ItemType == IS_FILE){
            var fullCurrentFileName = this.currentDir + ((this.currentDir!="") ? "/" :"") + currentFileItems[cfi].ItemName;
            var currentFileO = File_GetFile(fullCurrentFileName);                   // возможно, файл уже был сохранен
            if (currentFileO == null){
                currentFileO = new File(
                    this, file_GetNameByFullName(currentFileItems[cfi].ItemName), this.currentDir, 
                    this.userName, false, null, currentFileItems[cfi].IsShared);              
                EXISTING_FILES.push(currentFileO);                                  // Добавляем файл в список существующих
            }
            AddUserFileToDiv(currentFileO.name, filesTable, filesDiv, currentFileO);
        }
        else{
            var fullCurrentDirName = this.currentDir + ((this.currentDir!="") ? "/" :"") + currentFileItems[cfi].ItemName;
            var currentDirO = Directory_GetDirectory(fullCurrentDirName);
            if (currentDirO == null){
                currentDirO = new Directory(
                    file_GetNameByFullName(currentFileItems[cfi].ItemName),
                    this.currentDir, this.userName);
                EXISTING_DIRS.push(currentDirO);
            }
            AddUserDirectoryToDiv(currentDirO, filesTable, filesDiv);
            if (!firstDirCreated){
                this.dirsHash[parCurrentDir].firstDirLink = $get(userDirectoryLinkIDPrefix + currentDirO.fullName);
                firstDirCreated = true;
            }
        }
    }
}  

// Добавляет в список браузера файлов
function far_AddNewFile(dirName, newFileName){
    if (!this.directoryIsLoaded(dirName))
        return;
    
    if (dirName == "") 
        dirName = MAIN_PATH_ID;
    dirName = "\"" + dirName + "\"";
    
    var newFileItem = new ItemInfo(newFileName, IS_FILE);
    this.dirsHash[dirName].fileItemsList.push(newFileItem);
    this.filesCommonCount += 1;                         // Увеличиваем общее кол-во файлов
}  

// Добавляет каталог в список браузера файлов  
function far_AddNewDirectory(parentDirName, newDirName){
    if (!this.directoryIsLoaded(parentDirName))
        return;
        
    var parParentDirName = parentDirName;
    if (parParentDirName == "") 
        parParentDirName = MAIN_PATH_ID;
    parParentDirName = "\"" + parParentDirName + "\"";
    
    var newDirItem = new ItemInfo(newDirName, IS_DIRECTORY);
    this.dirsHash[parParentDirName].fileItemsList.push(newDirItem);
    
    var newDir = Directory_GetDirectory( ((parentDirName!="") ? parentDirName+"/" : "") + newDirName );     // добавляем визуальный элемент
    AddUserDirectoryToDiv(newDir, $get(this.tableID), $get(this.divID));
    
    var parNewDirName = "\"" + ((parentDirName!="") ? parentDirName+"/" : "") + newDirName + "\"";          // параметрическое имя нового каталога
    this.dirsHash[parNewDirName] = null;//new DirectoryContent(new Array(), new Date());                           // создаем в хэше объект этого каталога
    
    this.dirNames.push(parNewDirName);
    
    if (this.dirsHash[parParentDirName].firstDirLink == null)
        this.dirsHash[parParentDirName].firstDirLink = $get(userDirectoryLinkIDPrefix + newDir.fullName);
    this.filesCommonCount += 1;  
}                                      

// Удаление файла из списка браузера 
function far_DeleteFile(fullFileName){
    var lastSlashInd = fullFileName.lastIndexOf("/");
    var dirName = fullFileName.substring(0, lastSlashInd);
        if (dirName == "") 
            dirName = MAIN_PATH_ID;
        dirName = "\"" + dirName + "\"";
    var fileName = fullFileName.substr(lastSlashInd + 1);
    
    // Удаляем из списка нужного каталога
    var fileItems = this.dirsHash[dirName].fileItemsList;
    var fileInd = 0;
    for (dfi = 0; dfi < fileItems.length; ++dfi){
        if (fileItems[dfi].ItemName == fileName){
            fileInd = dfi;
            break;
        }
    }
    fileItems.splice(fileInd, 1);
    this.filesCommonCount -= 1;                                     // Уменьшаем общее кол-во файлов
}           

// Удаление каталога из списка браузера 
function far_DeleteDirectory(fullFolderName){
    var lastSlashInd = fullFolderName.lastIndexOf("/");
    var dirName = fullFolderName.substring(0, lastSlashInd);
        if (dirName == "") 
            dirName = MAIN_PATH_ID;
        dirName = "\"" + dirName + "\"";
    var folderName = fullFolderName.substr(lastSlashInd + 1);
    
    // Удаляем из списка нужного каталога
    var folderItems = this.dirsHash[dirName].fileItemsList;
    var folderInd = 0;
    for (ddi = 0; ddi < folderItems.length; ++ddi){
        if (folderItems[ddi].ItemName == folderName){
            folderInd = ddi;
            break;
        }
    }
    folderItems.splice(folderInd, 1);
    // Удаляем из списка каталогов и массива всех имен
    var deletingDirName = "\"" + fullFolderName + "\"";
    var dirNameInd = this.dirNames.indexOf(deletingDirName);
    this.dirNames.splice(dirNameInd, 1);
    this.filesCommonCount -= 1;                                    // Уменьшаем общее кол-во файлов
}     

// Переименование файла в списке браузера   
function far_RenameFile(dir, oldName, newName){
    if (dir == "") 
        dir = MAIN_PATH_ID;
    dir = "\"" + dir + "\"";
    
    // Ищем индекс файла в списке соответствующего каталога
    var fileItems = this.dirsHash[dir].fileItemsList;
    var fileInd = 0;
    for (dfi = 0; dfi < fileItems.length; ++dfi){
        if (fileItems[dfi].ItemName == oldName){
            fileInd = dfi;
            break;
        }
    }
    fileItems[fileInd].ItemName = newName;
}      

// Переименование каталога в списке браузера
function far_RenameDirectory(dir, oldName, newName){
    if (dir == "") 
        dir = MAIN_PATH_ID;
    dir = "\"" + dir + "\"";
    
    // Ищем индекс каталога в списке соответствующего каталога
    var fileItems = this.dirsHash[dir].fileItemsList;
    var dirInd = 0;
    for (dfi = 0; dfi < fileItems.length; ++dfi){
        if (fileItems[dfi].ItemName == oldName){
            dirInd = dfi;
            break;
        }
    }
    fileItems[dirInd].ItemName = newName;
}                

// Проверка существования такого имени                
function far_NameExists(directoryName, checkingName){
    if (directoryName == "") 
        directoryName = MAIN_PATH_ID;
    directoryName = "\"" + directoryName + "\"";
    
    // Ищем файл в списке соответствующего каталога
    var fileItems = this.dirsHash[directoryName].fileItemsList;
    var fileInd = 0;
    for (cfii = 0; cfii < fileItems.length; ++cfii){
        if (fileItems[cfii].ItemName == checkingName){
            return true;
        }
    }
    return false;
}                        

// Очищает список браузера от файлов и подкаталогов каталога [clearingDirectory]
function far_ClearDirectory(clearingDirectory){
    var newDirNames = new Array();
    for (dni = 0; dni < this.dirNames.length; ++dni){
        if (this.dirNames[dni].indexOf(clearingDirectory) == 1){
            if (this.dirsHash[this.dirNames[dni]] != null){
                this.filesCommonCount -= this.dirsHash[this.dirNames[dni]].fileItemsList.length;
                this.dirsHash[this.dirNames[dni]] = null;
            }
        }
        else{
            newDirNames.push(this.dirNames[dni]);
        }
    }
    this.dirNames = newDirNames;
}                                                    

// Удаляет таблицу файлов
function far_RemoveFarTable(){
    var filesDiv = $get(this.divID);
    var filesTable = $get(this.tableID);
    var currentDirLabel = $get(this.currentDirLabelID);
    var parentDirLabel = $get(this.parentDirLabelID);
    
    if (filesTable != null)
        filesDiv.removeChild(filesTable);
    if (currentDirLabel != null)
        filesDiv.removeChild(currentDirLabel);
    if (parentDirLabel != null)
        filesDiv.removeChild(parentDirLabel);
    
    filesCheckBoxList = new Array();        // список чекбоксов надо освободить
    foldersCheckBoxList = new Array();
}
// Добавляет таблицу файлов
function far_AddFarTable(){
    this.addManageLabels();
    filesDiv = $get(FAR_DIV);
    AddFilesTableToDiv(this.tableID, filesDiv);
}

// Добавление метки перехода в родительский каталог
function far_AddManageLabels() {
    var root = "Мои файлы"; // SSM - повтор строки - TODO
    var ll = document.getElementById("AllFilesLabel");
    ll.innerHTML = (this.currentDir != MAIN_PATH) ? root + "/" + this.currentDir : root; ;

    var currentDirLabel = document.createElement("label");
    currentDirLabel.id = this.currentDirLabelID;
    //currentDirLabel.innerHTML = (this.currentDir != MAIN_PATH) ? root+"/"+this.currentDir : root;
    currentDirLabel.innerHTML = ""; // SSM 5.07.11 чтобы не отображать
    
    currentDirLabel.style.fontSize = "11px";
    currentDirLabel.style.display = "block";
    currentDirLabel.style.fontWeight = "bold";
    currentDirLabel.style.fontStyle = "italic";
    currentDirLabel.style.marginLeft = "-17px";
    
    $get(this.divID).appendChild(currentDirLabel);
    
    if (this.currentDir != MAIN_PATH){
        var parentDirLink = document.createElement("a");
        parentDirLink.id = this.parentDirLabelID;
        parentDirLink.innerHTML = "...";
        
        parentDirLink.className = "directories_list_item__over";
        parentDirLink.style.cursor = "pointer";
        
        var OnClickAttrCurrDir = document.createAttribute("onclick");                   // установка действий события "нажата"
        // !!!!!!! ВНИМАНИЕ !!!!!!! Вызов ВНЕШНЕЙ функции (+) Отредактировано
        OnClickAttrCurrDir.value = this.farName + ".loadParentDirectory()";                         
        parentDirLink.attributes.setNamedItem(OnClickAttrCurrDir);
        
        $get(this.divID).appendChild(parentDirLink);
    }
}

// Загрузка родительского каталога
function far_LoadParentDirectory(){
    // если мы тут оказались, значит находимся не в основном каталоге
    // но на всякий случай выйдем в случае ошибки
    if (this.currentDir == MAIN_PATH)
        return;
    
    var lastSlashInd = this.currentDir.lastIndexOf("/");
    var parentDirectory = (lastSlashInd != -1) ? this.currentDir.substring(0, lastSlashInd) : MAIN_PATH;
    
    // Уходя, очищаем ссылку на каталог
    this.clearFirstDirLink();
    
    if (this.directoryIsLoaded(parentDirectory)){
        this.currentDir = parentDirectory;
        this.display();
    }
    else{
        if (someProcessIsRunning){
            alert(fullProcessMessage);
            return;
        }
        
        someProcessIsRunning = true;
        fullProcessMessage = inProcess + ofFilesListLoading;
        InformAboutNetworkOperation(inProcess + ofFilesListLoading);
        
        if (parentDirectory == MAIN_PATH_ID)
            parentDirectory = "";
        this.lastChosenDir = parentDirectory;
        var userDir = this.userName + ( (parentDirectory!="") ? "/"+parentDirectory : "" );
        var queryData = new LoadingUserFileItemsQueryData(parentDirectory);       // Данные запроса
        // Добавляем информацию о запросе в список
        var currQueryID = GenerateGuid();
        NetworkQueryViewer.AddQuery(currQueryID, new QueryInfo(
            QueryTypeEnum.LOADING_USER_FILE_ITEMS_LIST, queryData));
            
        /* Надо вызвать PageMethods, чтобы получить список файлов. 
        Пока я не знаю хорошего способа сделать это независимым от внешки */
        PageMethods.GetUserExistingFileItems(currQueryID, userDir, GetParentDirectoryExistingFileItems_CallBack);
    }
}

    // Обратный вызов загрузки содержимого родительского каталога
    function GetParentDirectoryExistingFileItems_CallBack(response){
        someProcessIsRunning = false;
        if (!ProcessServerQueryResponse(response)){                 // Обрабатываем глобальный ответ
            InformAboutError(LOADING_USER_FILE_ITEMS_SERVER_ERROR);
            return;
        }
        var fileItems = GetServerQueryResponseData(response);       // собственно результат выполнения запроса
        SetStatusLineHidden();
        
        // Вызов функции загрузки списка файловых единиц браузера файлов
        eval(this.farName + "load(fileItems, " + this.farName + "lastChosenDir);"); 
    }


// Загружено ли содержимое каталога
function far_DirectoryIsLoaded(directoryName){
    if ((directoryName == undefined) || (directoryName == ""))
        directoryName = MAIN_PATH_ID;
    var parDirectoryName = "\"" + directoryName + "\"";
    for (dni = 0; dni < this.dirNames.length; ++dni){
        if ((this.dirNames[dni] == parDirectoryName) && (this.dirsHash[parDirectoryName] != null))
            return true;
    }
    return false;
}          

// Выгрузить браузер
function far_Unload(){
    this.dirNames = new Array();
    this.dirsHash = [];
}                                  


// Возвращает имя каталога, использовавшегося раньше всех
function far_GetEldestDirectory(){
    // если мы тут находимся, значит каталоги еще есть
    // на всякий случай выйдем в случае ошибки
    if (this.dirNames.length == 0)
        return "";
    
    var eldestDir = new Object();
    eldestDir.name = this.dirNames[0];
    eldestDir.index = 0;
    var minDate = this.dirsHash[eldestDir.name].lastAccessTime;
    
    for (edi = 1; edi < this.dirNames.length; ++edi){
        if (this.dirsHash[this.dirNames[edi]].lastAccessTime < minDate){
            eldestDir.name = this.dirNames[edi];
            eldestDir.index = edi;
            minDate = this.dirsHash[eldestDir.name].lastAccessTime;
        }
    }
    return eldestDir;
}

// Очищает ссылку на первый файл каталога
function far_ClearFirstDirLink(){
    var currDir = this.currentDir;
    if (currDir == MAIN_PATH)
        currDir = MAIN_PATH_ID;
    var parParentDir = "\"" + currDir + "\"";
    if (this.dirsHash[parParentDir] != undefined)
        this.dirsHash[parParentDir].firstDirLink = null;
}        
