diff --git a/.travis.yml b/.travis.yml index fa13ab9d..015e3dc5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,11 @@ - language: node_js - node_js: - #- 0.4 #jshint fails to install (no gzip, jshint test not working out) - - 0.6 - - 0.8 - - 0.9 - notifications: - webhooks: - #http://requestb.in/12h5bl71 - urls: - # http://webhooks.jit.su/deploy ## - - http://webhooks.nodejitsu.com/1/deploy \ No newline at end of file +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.9 +notifications: + #webhooks: + #http://requestb.in/12h5bl71 + email: + on_success: never + on_failure: change \ No newline at end of file diff --git a/ChangeLog b/ChangeLog index 57c811fe..d4707bf5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,196 @@ +2012.10.*, Version 0.1.8 + +* Added ability to shutdown Cloud Commander +thru terminal command: "cloudcmd exit" + +* Fixed bug with showing terminal and viewer +at the same time. + +* Fixed bug with appcache config. Windows reads +file not just like Linux. + +* Added ability to update thru git. + +* Added ability to change charset on terminal only if +it's build in command on win32. + +* Fixed bug with testing mode. If was same arguments, +Cloud Commander works in testing mode and server do not +started. + +* Added more demo mirrors to readme (appfog, cloudfoundry). + +* Removed resize event from jquery-terminal. + +* Fixed bug with error code of program execution in terminal. + +* Fixed bug with menu itmes edit and view. + +* Added function jsLoadOnLoad, thet loads js files +one-by-one, and then calls callback if needed. + +* Added function anyloadOnLoad thet loads any files or +elements one-by-one. + +* Added function loadModule thet make it easier to connect +new module. + +* Fixed bug with context menu hiding (on Esc). +Keys was unbinded. + +* Added ability to disable web sockets. + +* Moved cloudRequire to srvfunc.js file. + +* Fixed bug with directory pathes detection +(used document.location.href, now using +document.location.origin) + +* Fixed bug with keybinding in FireFox +(removed KeyBinding call on window load). + +* Fixed bug with getting current url in Firefox. + +* Util cleaned up (addClass and removeClass +moved to ie.js). + +* Index processing function moved out from +server.js to cloudcmd.js. + +* Added ability of authorithation in GitHub. + +* Rewrited sizing of names if they are to +long thru css, from JavaScript. + +* Fixed bug with application cahe forming on windows +and linux. + +* Removed unneeded windows check. + +* Fixed bug with downloading directory +listing in json from menu. + +* Changed default port to 80. + +* Util object moved from client.js to modules +dom.js and util.js. + +* Fixed bug with navigation thru path panel. + +* Added functions DOM.addKeyListener and Util.loadOnLoad + +* Added buttons panel. + +* Fixed bug with config file, when no need to minification. + +* Added ability to hide keys panel thru config option. + +* CodeMirror upgraded to version 2.35.0. + +* Fixed bug with keys panel and fm bottom margin, +when CodeMirror is open on the right panel. + +* Fixed bug with positioning of CodeMirror on the +right panel. + +* Function generateHeaders moved to main module. + +* Setted up auth on GitHub thru rest. + +* Fixed bug with context menu. Now it disabled +before load menu module to. + +* Throw out jquery from github module, moved Cache +object from client to DOM module, +refactored Cache object and added polyfill. + +* Added ability to connect github development id, +to Cloud Commander instance working in any host, +for this all the needed to be done is: +set enveronment varibles "oauth_client_id" and +"oauth_client_secret" values from github profile. + +* Changed funcyBox version to 2.1.3. + +* Improved reading file with streams. + +* Improved download speed of js and css files by +adding DOM.anyLoadInParallel function that is +loading files in parallel and then execute +callback function. + +* Added ability to load a couple scripts after one main, +in any position in anyLoadOnLoad function. + +* Added chainable to Cache object in DOM. + +* Changed default ip to null so IP would be geted from +config.json only if it setted up. + +* Fixed bug with starting node from other then projects dir. + +* Fixed bug with slashes on win32. + +* Fixed bug with editor close, when started from menu. + +* Added url change on folder changing. + +* Fixed bug with traveling in directories with +Javascript dissabled. + +* client.js and server.js moved to lib directory. + +* Improved work with browsers history api. + +* Fixed bug with setting path of index.html. + +* Added dropbox module. + +* Renamed config options ouath_client_id and +oauth_client_secre to github_id and github_secret. +Added dropbox_id option. + +* Fixed bug in github show function. + +* Added ability to call dropbox chooser on + . + +* Added ability to read dropbox key from config. + +* Fixed bug with menu load, when dir other then root. + +* Added confirmation before (not real) deleting file. + +* Added ability to upload file to gists on github thru menu. + +* Added getCurrentPath function to Util module. + +* GitHub and DropBox secret's moved out from +config.json to env. + +* Fixed bug with auth in github. + +* Fixed bug with opening empty files in CodeMiror. +Editor window could not be cloused. + +* Added windows support on terminal command: "cloudcmd exit". + +* Fixed IP on windows. + +* Added ability to delete files (not for real for now) +thru keys panel (F8). + +* Changed "Upload" menu item to "Upload to". + +* Fixed bug with minified styles. + +* If git not installed do not show error. +Just propose install git and clone from github repo. + +* Fixed bug with client.js minifying. + +* Fixed bug with appcache. + + 2012.10.01, Version 0.1.7 * Changed name of menu files, fixed npm and jitsu @@ -5,6 +198,7 @@ problem with menu showing. * Fixed bug with empty directorys. If directory was empty, we could not go in. + * Removed packed versions of files, uglifing would be doing on-a-fly @@ -17,7 +211,7 @@ loaded any time by any extension. * Fixed bug with getByClass IE version. * Fixed bug with keyboard not responding when go deeper -in file tree thrue mouse double click. +in file tree thru mouse double click. * Removed property keyBinded. From not it's private member of KeyBinding class. @@ -27,11 +221,11 @@ Function scrollIntoViewIfNeeded was polyfilled. * Added classic borders to panels. -* Added ability to download files thrue drag'n'drop. +* Added ability to download files thru drag'n'drop. * Fixed bug with setting current file when mouse down. -* Improved borders over CodeMirror and panels thrue css. +* Improved borders over CodeMirror and panels thru css. * Added ability to watch is file changed wile server is running @@ -58,7 +252,7 @@ disabled in browsers. * Added plagin terminal ( ` button under TAB). -* Added ability to execute commands on server thrue terminal. +* Added ability to execute commands on server thru terminal. * Added appcache paramter to config.json diff --git a/README.md b/README.md deleted file mode 100644 index 746f82ec..00000000 --- a/README.md +++ /dev/null @@ -1,156 +0,0 @@ -Cloud Commander [![Build Status](https://secure.travis-ci.org/coderaiser/cloudcmd.png?branch=master)](http://travis-ci.org/coderaiser/cloudcmd) -=============== -**Cloud Commander** - two-panels file manager, totally writed on js. -View [demo](http://cloudcmd.cloudfoundry.com/ "demo"). - -Google PageSpeed Score : [100](https://developers.google.com/speed/pagespeed/insights#url=http_3A_2F_2Fdemo-cloudcmd.cloudfoundry.com_2F&mobile=false "score") (out of 100). - -Benefits ---------------- -- full browser compatibility *(ie6+,chrome,safari,opera,firefox)*; -- responsible design -- one full page loading, *and then just one-time json-dir-listings loading -(with refresh opportunity).* -- caching readed directories *to localStorage (for now) -(so if network will disconnected or something heppen with a signal, we -definitely will can work with cached copy of directory listings)*; -- key binding -- disabled js support *(working in limited mode)*. -- automated minification *client js-files and onstart-reading Cloud manager files on server starting.* - -**Cloud Commander** uses all benefits of js, so if js is disabled, -we moves to *limited mode*. - -Limited-mode features ---------------- -- only 1 panel available -- no keybinding -- no local caching -- full loading of all web page(with styles, js-scripts, html-page etc). - -Hot keys ---------------- -In all modern web browsers (but not in IE, becouse he special) hot keys works. -There is a short list: -- Ctrl + r - reload dir content -- Ctrl + d - clear local cache (wich contains dir contents) -- Alt + q - disable key bindings -- Alt + s - get all key bindings back -- up, down, enter - filesystem navigation - -Viewer's hot keys ---------------- -- Shift + F3 - open viewer window -- Esc - close viewer window - -Editor's hot keys ---------------- -- F3 - open CodeMirror editor in read only mode -- F4 - open CodeMirror editor -- Esc - close CodeMirror editor - -Installing ---------------- -**Cloud Commander** installing is very easy. All you need it's just clone -repository from github. Just 2 commands: - - git clone git://github.com/coderaiser/cloudcmd.git - cd cloudcmd -or - - npm i cloudcmd - mv node_modules/cloudcmd ./ - -Configuration ---------------- -All main configuration could be done thrue config.json. -```js -{ - "cache" : {"allowed" : true}, /* cashing of js and css files in memory */ - "minification" : { /* minification of js,css,html and img */ - "js" : false, /* minify module neaded */ - "css" : false, /* npm i minify */ - "html" : true, - "img" : false - }, - "server" : true, /* server mode or testing mode */ - "logs" : false, /* logs or console ouput */ - "port" : 31337, /* Cloud Commander port */ - "ip" : "127.0.0.1" /* Cloud Commander IP */ -} -``` -Starting ---------------- -To start **Cloud Commander** only one command neaded: - - node cloudcmd -or on win platform just - - cloudcmd -After thet Cloud Commander reads config file **config.json** and start server -on 31337 port, if none of port varibles(*cloud9*, *cloudfoundry* and *nodester*) -isn't exist. -Then type in browser - - http://127.0.0.1:31337 -or - - http://localhost:31337 -Updating ---------------- -**Cloud Commander** is very buggy and alfa so it's very often updated. For update -you can just type in cloudcmd directory: - - git pull -or check new version on npm - npm info cloudcmd - -and then, if there is new version - npm r cloudcmd - npm i cloudcmd - -Additional modules ---------------- -**Cloud Commander's Server Side** not using additional modules for main functionality. -But for minification and optimization tricks optional can be -assingned (and installed) modules: [Minify] (https://github.com/coderaiser/minify "Minify") -and [socket.io] (https://github.com/LearnBoost/socket.io "Socket.IO"). - -Install addtitional modules: - - npm i - -**Cloud Commander's Client Side** use module jquery for ajaxing. -We could not use this module, but this way is fast: -- google cdn -- gzip -- cache - -Perhaps in the future, it will not be used, but so far it has no effect on -start loading of Cloud Commander Client Side and do things fast and stable -it is using now. - -Extensions ---------------- -**Cloud Commander** desinged to easily porting extensions. -For extend main functionality Cloud Commander use next modules: -- [CodeMirror] (http://codemirror.net "CodeMirror") -- [FancyBox] (https://github.com/fancyapps/fancyBox "FancyBox") -- [jQuery-contextMenu] (https://github.com/medialize/jQuery-contextMenu "jQuery-contextMenu") -- [jquery.terminal] (https://github.com/jcubic/jquery.terminal "jquery.terminal") - -Contributing ---------------- -If you would like to contribute - send pull request to dev branch. -Getting dev version of **Cloud Commander**: - - git clone git://github.com/coderaiser/cloudcmd.git - git checkout dev - -It is possible thet dev version Cloud Commander will needed dev version of Minify, -so to get it you should type a couple more commands: - - cd node_modules - rm -rf minify - git clone git://github.com/coderaiser/minify - git checkout dev \ No newline at end of file diff --git a/client.js b/client.js deleted file mode 100644 index bef3f31b..00000000 --- a/client.js +++ /dev/null @@ -1,1566 +0,0 @@ -/* Функция которая возвратит обьект CloudCommander - * @window - обьект window - * @document - обьект document - * @CloudFunc - обьект содержащий общий функционал - * клиентский и серверный - */ - -var CloudCommander = (function(){ -"use strict"; - -/* Клиентский обьект, содержащий функциональную часть*/ -var CloudClient = { - /* Конструктор CloudClient, который выполняет - * весь функционал по инициализации - */ - init : null, /* start initialization */ - - KeyBinding : null, /* обьект обработки нажатий клавишь */ - Config : null, /* function loads and shows config */ - Editor : null, /* function loads and shows editor */ - Viewer : null, /* function loads and shows viewer */ - Terminal : null, /* function loads and shows terminal*/ - Menu : null, /* function loads and shows menu */ - GoogleAnalytics : null, - - _loadDir : null, /* Функция привязываеться ко всем - * ссылкам и - * загружает содержимое каталогов */ - - /* ОБЬЕКТЫ */ - /* Обьект для работы с кэшем */ - Cache : {}, - /* Object contain additional system functional */ - Util : {}, - - /* ПРИВАТНЫЕ ФУНКЦИИ */ - /* функция загружает json-данные о файловой системе */ - _ajaxLoad : null, - - /* Функция генерирует JSON из html-таблицы файлов */ - _getJSONfromFileTable : null, - - /* функция меняет ссыки на ajax-овые */ - _changeLinks : null, - - /* КОНСТАНТЫ*/ - /* название css-класа текущего файла*/ - CURRENT_FILE : 'current-file', - LIBDIR : '/lib/', - LIBDIRCLIENT : '/lib/client/', - /* height of Cloud Commander - * seting up in init() - */ - HEIGHT : 0, - MIN_ONE_PANEL_WIDTH : 1155, - OLD_BROWSER : false -}; - - - -var cloudcmd = CloudClient; - -/* глобальные переменные */ -var CloudFunc, $, Util, KeyBinding, -/* short names used all the time functions */ - getByClass, getById; - -/* - * Обьект для работы с кэшем - * в него будут включены функции для - * работы с LocalStorage, webdb, - * indexed db etc. - */ -CloudClient.Cache = { - _allowed : true, /* приватный переключатель возможности работы с кэшем */ - - /* функция проверяет возможно ли работать с кэшем каким-либо образом */ - isAllowed : function(){}, - - /* Тип кэша, который доступен*/ - type : {}, - - /* Функция устанавливает кэш, если выбранный вид поддерживаеться браузером*/ - set :function(){}, - - /* Функция достаёт кэш, если выбранный вид поддерживаеться браузером*/ - get : function(){}, - - /* функция чистит весь кэш для всех каталогов*/ - clear : function(){} -}; - - -/* функция проверяет поддерживаеться ли localStorage */ -CloudClient.Cache.isAllowed = (function(){ - if(window.localStorage && - localStorage.setItem && - localStorage.getItem){ - CloudClient.Cache._allowed=true; - }else - { - CloudClient.Cache._allowed=false; - /* загружаем PolyFill для localStorage, - * если он не поддерживаеться браузером - * https://gist.github.com/350433 - */ - /* - Util.jsload('https://raw.github.com/gist/350433/c9d3834ace63e5f5d7c8e1f6e3e2874d477cb9c1/gistfile1.js', - function(){CloudClient.Cache._allowed=true; - }); - */ - } -}); - /* если доступен localStorage и - * в нём есть нужная нам директория - - * записываем данные в него - */ -CloudClient.Cache.set = (function(pName, pData){ - if(CloudClient.Cache._allowed && pName && pData){ - localStorage.setItem(pName,pData); - } -}); -/* Если доступен Cache принимаем из него данные*/ -CloudClient.Cache.get = (function(pName){ - if(CloudClient.Cache._allowed && pName){ - return localStorage.getItem(pName); - } - else return null; -}); -/* Функция очищает кэш*/ -CloudClient.Cache.clear = (function(){ - if(CloudClient.Cache._allowed){ - localStorage.clear(); - } -}); - -/* Object contain additional system functional */ -CloudClient.Util = (function(){ - - /* Load file countent thrue ajax - */ - var lXMLHTTP; - - this.addClass = function(pElement, pClass){ - var lClassList = pElement.classList; - if(lClassList) - lClassList.add(pClass); - else{ - var lSpaceChar = ''; - if(pElement.className) - lSpaceChar = ' '; - pElement.className += lSpaceChar + 'hidden'; - } - }; - - this.ajax = function(pParams){ - /* if on webkit - */ - if(window.XMLHttpRequest){ - if(!lXMLHTTP) - lXMLHTTP = new XMLHttpRequest(); - - var lMethod = 'GET'; - if(pParams.method) - lMethod = pParams.method; - - lXMLHTTP.open(lMethod, pParams.url, true); - lXMLHTTP.send(null); - - var lSuccess_f = pParams.success; - if(typeof lSuccess_f !== 'function') - console.log('error in Util.ajax onSuccess:', pParams); - - lXMLHTTP.onreadystatechange = function(pEvent){ - if (lXMLHTTP.readyState === 4 /* Complete */){ - var lJqXHR = pEvent.target; - var lContentType = lXMLHTTP.getResponseHeader('content-type'); - - if (lXMLHTTP.status === 200 /* OK */){ - var lData = lJqXHR.response; - - /* If it's json - parse it as json */ - if(lContentType && - lContentType.indexOf('application/json') === 0){ - try{ - lData = JSON.parse(lJqXHR.response); - } - catch(pError) { - /* if could not parse */ - console.log('Error: could not parse' + - 'json from server from url: ' + - pParams.url); - - lData = lJqXHR.response; - } - } - - lSuccess_f(lData, lJqXHR.statusText, lJqXHR); - } - else/* file not found or connection lost */{ - var lError_f = pParams.error; - - /* if html given or something like it - * getBack just status of result - */ - if(lContentType && - lContentType.indexOf('text/plain') !== 0){ - lJqXHR.responseText = lJqXHR.statusText; - } - - if(typeof lError_f === 'function') - lError_f(lJqXHR); - } - } - }; - } - else $.ajax(pParams); - }; - - /* setting function context (this) */ - this.bind = function(pFunction, pContext){ - return pFunction.bind(pContext); - }; - - /* - * Function gets id by src - * from http://domain.com/1.js to - * 1_js - */ - this.getIdBySrc = function(pSrc){ - var lID = pSrc.replace(pSrc.substr(pSrc, - pSrc.lastIndexOf('/')+1), - ''); - - /* убираем точки */ - while(lID.indexOf('.') > 0) - lID = lID.replace('.','_'); - - return lID; - }, - - this.loadOnload = function(pFunc_a){ - if(pFunc_a instanceof Array) { - - var lFunc_f = pFunc_a.pop(); - - if(typeof lFunc_f === 'function') - lFunc_f(); - - return this.loadOnload(pFunc_a); - } - else if(typeof pFunc_a === 'function') - return pFunc_a(); - }; - - this.anyLoadOnload = function(pParams_a){ - if(pParams_a instanceof Array) { - - var lParams_o = pParams_a.pop(); - - if(!lParams_o.func) - lParams_o.func = function(){ - lThis.anyLoadOnload(pParams_a); - }; - - return this.anyload(lParams_o); - } - }; - - /* - * Функция создаёт элемент и - * загружает файл с src. - * @pName - название тэга - * @pSrc - путь к файлу - * @pFunc - обьект, содержаий одну из функций - * или сразу две onload и onerror - * {onload: function(){}, onerror: function();} - * @pStyle - стиль - * @pId - id - * @pElement - элемент, дочерним которо будет этот - * @pParams_o = {name: '', src: ' ',func: '', style: '', id: '', parent: '', - async: false, inner: 'id{color:red, }, class:'', not_append: false} - */ - this.anyload = function(pParams_o){ - /* if a couple of params was - * processing every of params - * and quit - */ - if(pParams_o instanceof Array){ - var lElements_a = []; - for(var i=0; i < pParams_o.length; i++) - lElements_a[i] = this.anyload(pParams_o[i]); - - return lElements_a; - } - - /* убираем путь к файлу, оставляя только название файла */ - var lID = pParams_o.id; - var lClass = pParams_o.className; - var lSrc = pParams_o.src; - var lFunc = pParams_o.func; - var lAsync = pParams_o.async; - - if(!lID && lSrc) - lID = this.getIdBySrc(lSrc); - - var element = getById(lID); - /* если скрипт еще не загружен */ - if(!element) - { - if(!pParams_o.name) - return {code: -1, text: 'name can not be empty'}; - - element = document.createElement(pParams_o.name); - - if(lID) - element.id = lID; - - if(lClass) - element.className = lClass; - /* if working with external css - * using href in any other case - * using src - */ - pParams_o.name === 'link' ? - ((element.href = lSrc) && (element.rel = 'stylesheet')) - : element.src = lSrc; - - /* if passed arguments function - * then it's onload by default - */ - if(pParams_o.func) - if(typeof lFunc === 'function'){ - element.onload = lFunc; - /* - element.onreadystatechange = function(){ - if(this.readyState === 'loaded') - lFunc(); - };*/ /* ie */ - - /* if object - then onload or onerror */ - }else if (typeof lFunc === 'object') { - if(lFunc.onload && - typeof lFunc.onload === 'function'){ - element.onload = lFunc.onload; - /* - element.onreadystatechange = function(){ - if(this.readyState === 'loaded') - lFunc(); - };*/ /* ie */ - } - } - - /* if element (js/css) will not loaded - * it would be removed from DOM tree - * and error image would be shown - */ - element.onerror = (function(){ - (pParams_o.parent || document.body) - .removeChild(element); - - Util.Images.showError({ - responseText: 'file ' + - lSrc + - ' could not be loaded', - status : 404 - }); - - if(lFunc && lFunc.onerror && - typeof lFunc.onerror === 'function') - lFunc.onerror(); - }); - - if(pParams_o.style){ - element.style.cssText=pParams_o.style; - } - - if(lAsync || lAsync === undefined) - element.async = true; - - if(!pParams_o.not_append) - (pParams_o.parent || document.body).appendChild(element); - - if(pParams_o.inner){ - element.innerHTML = pParams_o.inner; - } - } - /* если js-файл уже загружен - * запускаем функцию onload - */ - else if(lFunc){ - if(typeof lFunc === 'function') - lFunc(); - - else if(typeof lFunc === 'object' && - typeof lFunc.onload === 'function') - lFunc.onload(); - - } - return element; - }, - - /* Функция загружает js-файл */ - this.jsload = function(pSrc, pFunc){ - if(pSrc instanceof Array){ - for(var i=0; i < pSrc.length; i++) - pSrc[i].name = 'script'; - - return this.anyload(pSrc); - } - - return this.anyload({ - name : 'script', - src : pSrc, - func : pFunc - }); - }, - - /* Функция создаёт елемент style и записывает туда стили - * @pParams_o - структура параметров, заполняеться таким - * образом: {src: ' ',func: '', id: '', element: '', inner: ''} - * все параметры опциональны - */ - - this.cssSet = function(pParams_o){ - pParams_o.name = 'style'; - pParams_o.parent = pParams_o.parent || document.head; - - return this.anyload(pParams_o); - }, - /* Function loads external css files - * @pParams_o - структура параметров, заполняеться таким - * образом: {src: ' ',func: '', id: '', element: '', inner: ''} - * все параметры опциональны - */ - this.cssLoad = function(pParams_o){ - if(pParams_o instanceof Array){ - for(var i=0; i < pParams_o.length; i++){ - pParams_o[i].name = 'link'; - pParams_o[i].parent = pParams_o.parent || document.head; - } - - return this.anyload(pParams_o); - } - - pParams_o.name = 'link'; - pParams_o.parent = pParams_o.parent || document.head; - - return this.anyload(pParams_o); - }; - - this.jqueryLoad = function(pCallBack){ - /* загружаем jquery: */ - Util.jsload('//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js',{ - onload: function(){ - $ = window.jQuery; - if(typeof pCallBack === 'function') - pCallBack(); - }, - - onerror: function(){ - Util.jsload('lib/client/jquery.js'); - - /* - * if could not load jquery from google server - * maybe we offline, load font from local - * directory - */ - Util.cssSet({id:'local-droids-font', - element : document.head, - inner : '@font-face {font-family: "Droid Sans Mono";' + - 'font-style: normal;font-weight: normal;' + - 'src: local("Droid Sans Mono"), local("DroidSansMono"),'+ - ' url("font/DroidSansMono.woff") format("woff");}' - }); - } - }); - }; - - this.getByTag = function(pTag, pElement){ - return (pElement || document).getElementsByTagName(pTag); - }; - - this.getById = function(pId, pElement){ - return (pElement || document).getElementById(pId); - }; - - - /* - * Function search element by class name - * @pClass - className - * @pElement - element - */ - this.getByClass = function(pClass, pElement){ - return (pElement || document).getElementsByClassName(pClass); - }; - - /* private members */ - var lLoadingImage; - var lErrorImage; - - /* Обьект, который содержит - * функции для отображения - * картинок - */ - var LImages_o = { - /* Функция создаёт картинку загрузки*/ - loading : function(){ - var lE = Util.getById('loading-image'); - if (!lE) - lE = Util.anyload({ - name : 'span', - className : 'icon loading', - id : 'loading-image', - not_append : true - }); - - lLoadingImage = lE; - - return lE; - }, - - /* Функция создаёт картинку ошибки загрузки*/ - error : function(){ - var lE = Util.getById('error-image'); - if (!lE) - lE = Util.anyload({ - name : 'span', - className : 'icon error', - id : 'error-image', - not_append : true - }); - - return lE; - } - }; - - var lThis = this; - this.Images = { - /* - * Function shows loading spinner - * @pElem - top element of screen - * pPosition = {top: true}; - */ - showLoad : function(pPosition){ - var lRet_b = true; - - lLoadingImage = LImages_o.loading(); - lErrorImage = LImages_o.error(); - - Util.hide(lErrorImage); - - var lCurrent; - if(pPosition){ - if(pPosition.top){ - lCurrent = lThis.getRefreshButton(); - if(lCurrent) - lCurrent = lCurrent.parentElement; - else - lRet_b = false; - } - } - else - { - lCurrent = lThis.getCurrentFile(); - lCurrent = lCurrent.firstChild.nextSibling; - } - - /* show loading icon - * if it not showed - * and if error was not - * heppen - */ - if(lRet_b){ - var lParent = lLoadingImage.parentElement; - if(!lParent || - (lParent && lParent !== lCurrent)) - lCurrent.appendChild(lLoadingImage); - - Util.show(lLoadingImage); /* показываем загрузку*/ - } - - return lRet_b; - }, - - hideLoad : function(){ - lLoadingImage = LImages_o.loading(); - Util.hide(lLoadingImage); - }, - - showError : function(jqXHR, textStatus, errorThrown){ - lLoadingImage = LImages_o.loading(); - - lErrorImage = LImages_o.error(); - - var lText; - if(jqXHR.status === 404) - lText = jqXHR.responseText; - else - lText = jqXHR.statusText; - - /* если файла не существует*/ - if(!lText.indexOf('Error: ENOENT, ')) - lText = lText.replace('Error: ENOENT, n','N'); - - /* если не хватает прав для чтения файла*/ - else if(!lText.indexOf('Error: EACCES,')) - lText = lText.replace('Error: EACCES, p','P'); - - Util.show(lErrorImage); - lErrorImage.title = lText; - - var lParent = lLoadingImage.parentElement; - if(lParent) - lParent.appendChild(lErrorImage); - - Util.hide(lLoadingImage); - - console.log(lText); - } - }; - - this.getCurrentFile = function(){ - var lCurrent = lThis.getByClass(CloudCommander.CURRENT_FILE)[0]; - if(!lCurrent) - this.addCloudStatus({ - code : -1, - msg : 'Error: can not find ' + - 'CurrentFile ' + - 'in getCurrentFile' - }); - - return lCurrent; - }; - - this.getRefreshButton = function(){ - var lPanel = this.getPanel(); - var lRefresh = this.getByClass(CloudFunc.REFRESHICON, lPanel); - - if (lRefresh.length) - lRefresh = lRefresh[0]; - else { - this.addCloudStatus({ - code : -3, - msg : 'Error Refresh icon not found' - }); - lRefresh = false; - } - - return lRefresh; - }; - - this.setCurrentFile = function(pCurrentFile){ - var lRet_b = true; - - if(!pCurrentFile){ - this.addCloudStatus({ - code : -1, - msg : 'Error pCurrentFile in' + - 'setCurrentFile' + - 'could not be none' - }); - - lRet_b = false; - } - var lCurrentFileWas = this.getCurrentFile(); - - if (pCurrentFile.className === 'path') - pCurrentFile = pCurrentFile.nextSibling; - - if (pCurrentFile.className === 'fm_header') - pCurrentFile = pCurrentFile.nextSibling; - - if(lCurrentFileWas) - lUnSetCurrentFile(lCurrentFileWas); - - var lCurrentClass = CloudCommander.CURRENT_FILE; - - this.addClass(pCurrentFile, lCurrentClass); - - /* scrolling to current file */ - Util.scrollIntoViewIfNeeded(pCurrentFile); - - return lRet_b; - }; - - var lUnSetCurrentFile = function(pCurrentFile){ - if(!pCurrentFile) - Util.addCloudStatus({ - code : -1, - msg : 'Error pCurrentFile in' + - 'unSetCurrentFile' + - 'could not be none' - }); - - var lRet_b = Util.isCurrentFile(pCurrentFile); - var lCurrentClass = CloudCommander.CURRENT_FILE; - - if(lRet_b) - Util.removeClass(pCurrentFile, lCurrentClass); - - return lRet_b; - }; - - this.isCurrentFile = function(pCurrentFile){ - if(!pCurrentFile) - this.addCloudStatus({ - code : -1, - msg : 'Error pCurrentFile in' + - 'isCurrentFile' + - 'could not be none' - }); - - var lCurrentClass = CloudCommander.CURRENT_FILE; - var lCurrentFileClass = pCurrentFile.className; - - return ( lCurrentFileClass.indexOf(lCurrentClass) >= 0 ); - }; - - this.getCurrentLink = function(pCurrentFile){ - var lLink; - if(pCurrentFile) - lLink = this.getByTag('a', pCurrentFile)[0]; - else{ - var lCurrentFile = this.getCurrentFile(); - lLink = this.getByTag('a', lCurrentFile)[0]; - } - - if(!lLink) - this.addCloudStatus({ - code : -1, - msg : 'Error current element do not contain links' - }); - - return lLink; - }; - - this.getCurrentName = function(pCurrentFile){ - var lCurrent = this.getCurrentFile(); - - var lLink; - lLink = this.getCurrentLink(pCurrentFile ? pCurrentFile : lCurrent); - - if(!lLink) - this.addCloudStatus({ - code : -1, - msg : 'Error current element do not contain links' - }); - else lLink = lLink.textContent; - - return lLink; - }; - - /* function getting panel active, or passive - * @pPanel_o = {active: true} - */ - this.getPanel = function(pActive){ - var lPanel; - - lPanel = lThis.getCurrentFile().parentElement; - - /* if {active : false} getting passive panel */ - if(pActive && !pActive.active){ - var lId = lPanel.id === 'left' ? 'right' : 'left'; - lPanel = lThis.getById(lId); - } - - /* if two panels showed - * then always work with passive - * panel - */ - if(window.innerWidth < CloudCommander.MIN_ONE_PANEL_WIDTH) - lPanel = lThis.getById('left'); - - - if(!lPanel) - console.log('Error can not find Active Panel'); - - return lPanel; - }; - - this.show = function(pElement){ - Util.removeClass(pElement, 'hidden'); - }; - - this.showPanel = function(pActive){ - var lPanel = lThis.getPanel(pActive); - - if(lPanel) - this.show(lPanel); - }; - - this.hidePanel = function(pActive){ - var lPanel = lThis.getPanel(pActive); - - if(lPanel) - this.hide(lPanel); - }; - - this.hide = function(pElement){ - return this.addClass(pElement, 'hidden'); - }; - - this.removeClass = function(pElement, pClass){ - if(pElement.classList) - pElement.classList.remove(pClass); - - else if(pElement.className.length > pClass.length) - pElement.className = pElement.className.replace(pClass, ''); - }; - - this.removeCurrent = function(pCurrent){ - var lParent = pCurrent.parentElement; - - if(!pCurrent) - pCurrent = this.getCurrentFile(); - var lName = this.getCurrentName(pCurrent); - - if(pCurrent && lParent){ - if(lName !== '..'){ - var lNext = pCurrent.nextSibling; - var lPrevious = pCurrent.previousSibling; - if(lNext) - Util.setCurrentFile(lNext); - else if(lPrevious) - Util.setCurrentFile(lPrevious); - - lParent.removeChild(pCurrent); - } - else - this.addCloudStatus({ - code : -1, - msg : 'Could not remove parrent dir' - }); - } - else - this.addCloudStatus({ - code : -1, - msg : 'Current file (or parent of current) could not be empty' - }); - - return pCurrent; - }; - - this.scrollIntoViewIfNeeded = function(pElement){ - var lOk = true; - if(pElement && pElement.scrollIntoViewIfNeeded) - pElement.scrollIntoViewIfNeeded(); - else lOk = false; - - return lOk; - }; - - - this.CloudStatus = []; - - this.addCloudStatus = function(pStatus){ - this.CloudStatus[this.CloudStatus.length] = pStatus; - }; -}); - -CloudClient.Util = new CloudClient.Util(); - -/* функция обработки нажатий клавишь */ -CloudClient.KeyBinding = (function(){ - /* loading keyBinding module and start it */ - Util.jsload(CloudClient.LIBDIRCLIENT+'keyBinding.js', function(){ - cloudcmd.KeyBinding.init(); - - KeyBinding = cloudcmd.KeyBinding; - }); -}); - -/* function loads and shows editor */ -CloudClient.Editor = (function(pCurrentFile, pIsReadOnly) { - /* loading CloudMirror plagin */ - Util.jsload(CloudClient.LIBDIRCLIENT + - 'editor/_codemirror.js',{ - //'editor/_ace.js',{ - onload:(function(){ - cloudcmd.Editor.Keys(pCurrentFile, pIsReadOnly); - }) - }); -}); - - -CloudClient.Config = (function() { - Util.Images.showLoad({top: true}); - Util.jsload(CloudClient.LIBDIRCLIENT + - 'config.js',{ - onload: function(){ - cloudcmd.Config.Keys(); - } - }); -}); - -CloudClient.GoogleAnalytics = (function(){ - /* google analytics */ - var lFunc = document.onmousemove; - document.onmousemove = function(){ - setTimeout(function(){ - Util.jsload('lib/client/google_analytics.js'); - },5000); - - if(typeof lFunc === 'function') - lFunc(); - - document.onmousemove = lFunc; - }; -}); - -/* function loads and shows viewer */ -CloudClient.Viewer = (function(pCurrentFile){ - Util.jsload(CloudClient.LIBDIRCLIENT + - 'viewer.js',{ - onload: (function(){ - cloudcmd.Viewer.Keys(pCurrentFile); - }) - }); -}); - -/* function loads and shows terminal */ -CloudClient.Terminal = (function(){ - Util.jsload(CloudClient.LIBDIRCLIENT + - 'terminal.js',{ - onload: (function(){ - cloudcmd.Terminal.Keys(); - }) - }); -}); - -/* function loads and shows menu - * @pPosition - coordinates of menu {x, y} - */ -CloudClient.Menu = (function(pPosition){ - Util.jsload(CloudClient.LIBDIRCLIENT + - 'menu.js',{ - onload: (function(){ - cloudcmd.Menu.Keys(pPosition); - }) - }); -}); - -/* - * Функция привязываеться ко всем ссылкам и - * загружает содержимое каталогов - */ -CloudClient._loadDir = (function(pLink,pNeedRefresh){ - /* @pElem - элемент, - * для которого нужно - * выполнить загрузку - */ - return function(){ - /* показываем гиф загрузки возле пути папки сверху*/ - /* ctrl+r нажата? */ - - Util.Images.showLoad(pNeedRefresh ? {top:true} : null); - - var lPanel = Util.getPanel(); - /* получаем имя каталога в котором находимся*/ - var lHref = Util.getByClass('path', lPanel); - lHref = lHref[0].textContent; - - lHref = CloudFunc.removeLastSlash(lHref); - var lSubstr = lHref.substr(lHref,lHref.lastIndexOf('/')); - lHref = lHref.replace(lSubstr+'/',''); - - /* загружаем содержимое каталога */ - CloudClient._ajaxLoad(pLink, pNeedRefresh); - - /* получаем все элементы выделенной папки*/ - /* при этом, если мы нажали обновить - * или +R - ссылок мы ненайдём - * и заходить не будем - */ - var lA = Util.getCurrentLink(this); - - /* если нажали на ссылку на верхний каталог*/ - if(lA && lA.textContent==='..' && lHref!=='/'){ - - /* функция устанавливает курсор на каталог - * с которого мы пришли, если мы поднялись - * в верх по файловой структуре - */ - CloudClient._currentToParent(lHref); - } - - /* что бы не переходить по ссылкам - * а грузить всё ajax'ом, - * возвращаем false на событие - * onclick - */ - return false; - }; - }); - - -/* - * Function edits file name - * - * @pParent - parent element - * @pEvent - */ -CloudClient._editFileName = (function(pParent){ - var lA = Util.getCurrentLink(pParent); - - if (lA && lA.textContent !== '..'){ - - lA.contentEditable = true; - KeyBinding.unSet(); - - var lDocumentOnclick = document.onclick; - - /* setting event handler onclick - * if user clicks somewhere keyBinded - * backs - */ - document.onclick = (function(){ - var lA = Util.getCurrentLink(pParent); - if (lA && lA.textContent !== '..') - lA.contentEditable = false; - - KeyBinding.set(); - - /* backs old document.onclick - * and call it if it was - * setted up earlier - */ - document.onclick = lDocumentOnclick; - if(typeof lDocumentOnclick === 'function') - lDocumentOnclick(); - - }); - } -}); - -/* Функция устанавливает текущим файлом, тот - * на который кликнули единожды - */ -CloudClient._setCurrent=(function(){ - /* - * @pFromEnter - если мы сюда попали - * из события нажатия на энтер - - * вызоветься _loadDir - */ - return function(pFromEnter){ - var lCurrentFile = Util.getCurrentFile(); - if(lCurrentFile){ - if (Util.isCurrentFile(this) && - typeof pFromEnter !== 'boolean'){ - //var lParent = this; - - //setTimeout(function(){ - /* waiting a few seconds - * and if classes still equal - * make file name editable - * in other case - * double click event happend - */ - // if(Util.getCurrentFile() === lParent) - // CloudClient._editFileName(lParent); - // },1000); - } - else{ - /* устанавливаем курсор на файл, - * на который нажали */ - Util.setCurrentFile(this); - } - } - /* если мы попали сюда с энтера*/ - if(pFromEnter===true){ - if(typeof this.ondblclick === 'function') - this.ondblclick(this); - /* enter pressed on file */ - else{ - var lA = this.getElementsByTagName('a')[0]; - if(typeof lA.ondblclick === 'function') - lA.ondblclick(this); - } - }/* если мы попали сюда от клика мышки */ - else{pFromEnter.returnValue=false;} - - /* что бы не переходить по ссылкам - * а грузить всё ajax'ом, - * возвращаем false на событие - * onclick - */ - return false; - }; - }); - -/* функция устанавливает курсор на каталог - * с которого мы пришли, если мы поднялись - * в верх по файловой структуре - * @pDirName - имя каталога с которого мы пришли - */ -CloudClient._currentToParent = (function(pDirName){ - /* опредиляем в какой мы панели: - * правой или левой - */ - var lPanel = Util.getPanel(); - - /* убираем слэш с имени каталога*/ - pDirName = pDirName.replace('/',''); - - var lRootDir = getById(pDirName + '(' + lPanel.id + ')'); - - /* if found li element with ID directory name - * set it to current file - */ - if(lRootDir){ - Util.setCurrentFile(lRootDir); - Util.scrollIntoViewIfNeeded(lRootDir, true); - } -}); - -/* Конструктор CloudClient, который - * выполняет весь функционал по - * инициализации - */ -CloudClient.init = (function(){ - Util = cloudcmd.Util; - KeyBinding = cloudcmd.KeyBinding; - getByClass = Util.getByClass; - getById = Util.getById; - - if(!document.body.scrollIntoViewIfNeeded){ - this.OLD_BROWSER = true; - Util.jsload(CloudClient.LIBDIRCLIENT + 'ie.js', - function(){ - Util.jqueryLoad(CloudClient.baseInit); - }); - } - else CloudClient.baseInit(); -}); - -CloudClient.baseInit = (function(){ - if(applicationCache){ - var lFunc = applicationCache.onupdateready; - applicationCache.onupdateready = function(){ - console.log('app cacheed'); - location.reload(); - if(typeof lFunc === 'function') - lFunc(); - }; - } - /* меняем title - * если js включен - имена папок отображать необязательно... - * а может и обязательно при переходе, можно будет это сделать - */ - var lTitle = Util.getByTag('title'); - if(lTitle.length > 0) - lTitle[0].textContent = 'Cloud Commander'; - - /* загружаем общие функции для клиента и сервера */ - Util.jsload(CloudClient.LIBDIR+'cloudfunc.js',function(){ - /* берём из обьекта window общий с сервером функционал */ - CloudFunc=window.CloudFunc; - - /* меняем ссылки на ajax'овые */ - CloudClient._changeLinks(CloudFunc.LEFTPANEL); - CloudClient._changeLinks(CloudFunc.RIGHTPANEL); - - /* устанавливаем переменную доступности кэша */ - CloudClient.Cache.isAllowed(); - /* Устанавливаем кэш корневого каталога */ - if(!CloudClient.Cache.get('/')) - CloudClient.Cache.set('/', CloudClient._getJSONfromFileTable()); - }); - - /* устанавливаем размер высоты таблицы файлов - * исходя из размеров разрешения экрана - */ - - /* выделяем строку с первым файлом */ - var lFmHeader = getByClass('fm_header'); - if(lFmHeader && lFmHeader[0].nextSibling) - Util.setCurrentFile(lFmHeader[0].nextSibling); - - /* показываем элементы, которые будут работать только, если есть js */ - var lFM = getById('fm'); - if(lFM) - lFM.className='localstorage'; - - /* формируем и округляем высоту экрана - * при разрешениии 1024x1280: - * 658 -> 700 - */ - - var lHeight = - window.screen.height - - (window.screen.height/3).toFixed(); - - lHeight=(lHeight/100).toFixed()*100; - - CloudClient.HEIGHT = lHeight; - - Util.cssSet({id:'cloudcmd', - element:document.head, - inner: - '.panel{' + - 'height:' + lHeight +'px;' + - '}' - }); -}); - -/* функция меняет ссыки на ajax-овые */ -CloudClient._changeLinks = function(pPanelID){ - /* назначаем кнопку очистить кэш и показываем её */ - var lClearcache = getById('clear-cache'); - if(lClearcache) - lClearcache.onclick = CloudClient.Cache.clear; - - /* меняем ссылки на ajax-запросы */ - var lPanel = getById(pPanelID); - var a = lPanel.getElementsByTagName('a'); - - /* номер ссылки иконки обновления страницы */ - var lREFRESHICON = 0; - - /* путь в ссылке, который говорит - * что js отключен - */ - var lNoJS_s = CloudFunc.NOJS; - var lFS_s = CloudFunc.FS; - - /* right mouse click function varible */ - var lOnContextMenu_f = function(pEvent){ - var lReturn_b = true; - - KeyBinding.unSet(); - - /* getting html element - * currentTarget - DOM event - * target - jquery event - */ - var lTarget = pEvent.currentTarget || pEvent.target; - Util.setCurrentFile(lTarget); - - if(typeof CloudCommander.Menu === 'function'){ - CloudCommander.Menu({ - x: pEvent.x, - y: pEvent.y - }); - - /* disabling browsers menu*/ - lReturn_b = false; - Util.Images.showLoad(); - } - - return lReturn_b; - }; - - /* drag and drop function varible - * download file from browser to descktop - * in Chrome (HTML5) - */ - var lOnDragStart_f = function(pEvent){ - var lElement = pEvent.target; - - var lLink = lElement.href; - var lName = lElement.textContent; - - /* if it's directory - adding json extension */ - var lType = lElement.parentElement.nextSibling; - if(lType && lType.textContent === ''){ - lLink = lLink.replace(lNoJS_s,''); - lName += '.json'; - } - - pEvent.dataTransfer.setData("DownloadURL", - 'application/octet-stream' + ':' + - lName + ':' + - lLink); - }; - - var lSetCurrentFile_f = function(pEvent){ - var pElement = pEvent.target; - - var lTag = pElement.tagName; - if(lTag !== 'LI') - do{ - pElement = pElement.parentElement; - lTag = pElement.tagName; - }while(lTag !== 'LI'); - - Util.setCurrentFile(pElement); - }; - - for(var i=0; i < a.length ; i++) - { - /* убираем адрес хоста*/ - var link = '/'+a[i].href.replace(document.location.href,''); - - /* убираем значения, которые говорят, * - * об отсутствии js */ - if(link.indexOf(lNoJS_s) === lFS_s.length){ - link = link.replace(lNoJS_s,''); - } - /* ставим загрузку гифа на клик*/ - if(i === lREFRESHICON){ - a[i].onclick = CloudClient._loadDir(link,true); - - a[i].parentElement.onclick = a[i].onclick; - } - - /* устанавливаем обработчики на строку на одинарное и * - * двойное нажатие на левую кнопку мышки */ - else{ - var lLi; - - try{ - lLi = a[i].parentElement.parentElement; - }catch(error){console.log(error);} - - /* if we in path changing onclick events */ - if (lLi.className === 'path') { - a[i].onclick = CloudClient._loadDir(link); - } - else { - lLi.onclick = CloudClient._setCurrent(); - - lLi.onmousedown = lSetCurrentFile_f; - - a[i].ondragstart = lOnDragStart_f; - - /* if right button clicked menu will - * loads and shows - */ - lLi.oncontextmenu = lOnContextMenu_f; - - /* если ссылка на папку, а не файл */ - if(a[i].target !== '_blank'){ - lLi.ondblclick = CloudClient._loadDir(link); - - if(lLi.addEventListener) - lLi.addEventListener('touchend', - CloudClient._loadDir(link), - false); - } - - lLi.id = (a[i].title ? a[i].title : a[i].textContent) + - '(' + pPanelID + ')'; - } - } - } -}; - -/* - * Функция загружает json-данные о Файловой Системе - * через ajax-запрос. - * @path - каталог для чтения - * @pNeedRefresh - необходимость обновить данные о каталоге - */ -CloudClient._ajaxLoad = function(path, pNeedRefresh) -{ - /* Отображаем красивые пути */ - /* added supporting of russian language */ - var lPath = decodeURI(path); - var lFS_s = CloudFunc.FS; - if(lPath.indexOf(lFS_s) === 0){ - lPath = lPath.replace(lFS_s,''); - - if(lPath === '') lPath='/'; - } - console.log ('reading dir: "'+lPath+'";'); - - /* если доступен localStorage и - * в нём есть нужная нам директория - - * читаем данные с него и - * выходим - * если стоит поле обязательной перезагрузки - - * перезагружаемся - */ - - /* опредиляем в какой мы панели: - * правой или левой - */ - var lPanel; - try{ - lPanel = Util.getPanel().id; - }catch(error){console.log("Current panel not found\n"+error);} - - if(pNeedRefresh === undefined && lPanel){ - var lJSON = CloudClient.Cache.get(lPath); - if (lJSON !== null){ - - /* переводим из текста в JSON */ - if(window && !window.JSON){ - try{ - lJSON = eval('('+lJSON+')'); - }catch(err){ - console.log(err); - } - }else lJSON = JSON.parse(lJSON); - - CloudClient._createFileTable(lPanel,lJSON); - CloudClient._changeLinks(lPanel); - - return; - } - } - - /* ######################## */ - try{ - Util.ajax({ - url: path, - error: Util.Images.showError, - - success:function(data, textStatus, jqXHR){ - /* если такой папки (или файла) нет - * прячем загрузку и показываем ошибку - */ - if(!jqXHR.responseText.indexOf('Error:')) - return Util.showError(jqXHR); - - CloudClient._createFileTable(lPanel, data); - CloudClient._changeLinks(lPanel); - - /* Сохраняем структуру каталогов в localStorage, - * если он поддерживаеться браузером - */ - /* переводим таблицу файлов в строку, для - * сохранения в localStorage - */ - var lJSON_s = JSON.stringify(data); - console.log(lJSON_s.length); - - /* если размер данных не очень бошьой - * сохраняем их в кэше - */ - if(lJSON_s.length<50000) - CloudClient.Cache.set(lPath,lJSON_s); - } - }); - }catch(err){console.log(err);} -}; - -/* - * Функция строит файловую таблицу - * @pEleme - родительский элемент - * @pJSON - данные о файлах - */ -CloudClient._createFileTable = function(pElem, pJSON) -{ - var lElem = getById(pElem); - - /* getting current element if was refresh */ - var lPath = getByClass('path', lElem); - var lWasRefresh_b = lPath[0].textContent === pJSON[0].path; - var lCurrent; - if(lWasRefresh_b) - lCurrent = Util.getCurrentFile(); - - /* говорим построителю, - * что бы он в нужный момент - * выделил строку с первым файлом - */ - - /* очищаем панель */ - var i = lElem.childNodes.length; - while(i--) - lElem.removeChild(lElem.lastChild); - - /* заполняем панель новыми элементами */ - lElem.innerHTML = CloudFunc.buildFromJSON(pJSON,true); - - /* searching current file */ - if(lWasRefresh_b && lCurrent){ - for(i = 0; i < lElem.childNodes.length; i++) - if(lElem.childNodes[i].textContent === lCurrent.textContent){ - lCurrent = lElem.childNodes[i]; - break; - } - Util.setCurrentFile(lCurrent); - //lCurrent.parentElement.focus(); - } -}; - -/* - * Функция генерирует JSON из html-таблицы файлов и - * используеться при первом заходе в корень - */ -CloudClient._getJSONfromFileTable=function() -{ - var lLeft = getById('left'); - var lPath = getByClass('path')[0].textContent; - var lFileTable = [{path:lPath,size:'dir'}]; - var lLI = lLeft.getElementsByTagName('li'); - - var j=1;/* счётчик реальных файлов */ - var i=1;/* счётчик элементов файлов в DOM */ - /* Если путь отличный от корневного - * второй элемент li - это ссылка на верхний - * каталог '..' - */ - i=2; /* пропускам Path и Header*/ - - for(;iCloud Commander', + '' + CloudFunc.getTitle() + ''); + + if(!srv.Config.appcache) + lData = Util.removeStr(lData, ' manifest="/cloudcmd.appcache"'); + + if(!srv.Config.show_keys_panel){ + var lKeysPanel = '
- + Cloud Commander - - - - - + + @@ -30,19 +24,23 @@
-