diff --git a/json/config.json b/json/config.json index 3a8b6f66..5f9fc6cf 100644 --- a/json/config.json +++ b/json/config.json @@ -2,7 +2,7 @@ "api_url" : "/api/v1", "appcache" : false, "minification" : { - "js" : false, + "js" : true, "css" : true, "html" : true, "img" : true diff --git a/lib/client/dom.js b/lib/client/dom.js index c21e692f..6e449d9f 100644 --- a/lib/client/dom.js +++ b/lib/client/dom.js @@ -3,21 +3,17 @@ var CloudCommander, Util, DOM, CloudFunc; (function(Util){ 'use strict'; - var DOMProto = {}, - DOMConstructor = function(){}, - CURRENT_FILE = 'current-file', - SELECTED_FILE = 'selected-file', - XMLHTTP, Title, + var DOMFunc = function(){}, + DOMProto, - /* Обьект содержит функции для отображения картинок */ - ImagesProto = function(){ + ImagesProto = function(){ var LImagesProto = function (){ function getImage(pName){ var lId = pName + '-image', - lE = DOMProto.getById(lId); + lE = DOM.getById(lId); if (!lE) - lE = DOMProto.anyload({ + lE = DOM.anyload({ name : 'span', className : 'icon ' + pName, id : lId, @@ -47,14 +43,14 @@ var CloudCommander, Util, DOM, CloudFunc; lLoadingImage = lImages.loading(), lErrorImage = lImages.error(); - DOMProto.hide(lErrorImage); + DOM.hide(lErrorImage); var lCurrent; if(pPosition && pPosition.top) - lCurrent = DOMProto.getRefreshButton().parentElement; + lCurrent = DOM.getRefreshButton().parentElement; else{ - var lFile = DOMProto.getCurrentFile(); - lCurrent = DOMProto.getByClass('name', lFile)[0]; + var lFile = DOM.getCurrentFile(); + lCurrent = DOM.getByClass('name', lFile)[0]; } /* show loading icon if it not showed */ @@ -63,7 +59,7 @@ var CloudCommander, Util, DOM, CloudFunc; if(!lParent || (lParent && lParent !== lCurrent)) lCurrent.appendChild(lLoadingImage); - lRet_b = DOMProto.show(lLoadingImage); /* показываем загрузку*/ + lRet_b = DOM.show(lLoadingImage); /* показываем загрузку*/ return lRet_b; }; @@ -73,7 +69,7 @@ var CloudCommander, Util, DOM, CloudFunc; */ this.hideLoad = function(){ - DOMProto.hide( lImages.loading() ); + DOM.hide( lImages.loading() ); }; /** @@ -96,22 +92,21 @@ var CloudCommander, Util, DOM, CloudFunc; lText = lText.replace('Error: EACCES, p','P'); - DOMProto.show(lErrorImage); + DOM.show(lErrorImage); lErrorImage.title = lText; var lParent = lLoadingImage.parentElement; if(lParent) lParent.appendChild(lErrorImage); - DOMProto.hide(lLoadingImage); + DOM.hide(lLoadingImage); Util.log(lText); setTimeout( Util.retExec(alert, lText), 100); }; }, - /* Обьект содержит функции для работы с CloudCmd API */ - RESTfullProto = function(){ + RESTfullProto = function(){ this.delete = function(pUrl, pData, pCallBack, pQuery){ sendRequest({ method : 'DELETE', @@ -163,7 +158,7 @@ var CloudCommander, Util, DOM, CloudFunc; if(lRet){ var p = pParams; - DOMProto.Images.showLoad( p.imgPosition ); + Images.showLoad( p.imgPosition ); CloudCommander.getConfig(function(pConfig){ var lData; @@ -176,13 +171,13 @@ var CloudCommander, Util, DOM, CloudFunc; lData = p.data; p.url = pConfig && pConfig.api_url + p.url, - DOMProto.ajax({ + DOM.ajax({ method : p.method, url : p.url, data : lData, - error : DOMProto.Images.showError, + error : Images.showError, success : function(pData){ - DOMProto.Images.hideLoad(); + Images.hideLoad(); Util.log(pData); Util.exec(p.callback, pData); } @@ -193,7 +188,7 @@ var CloudCommander, Util, DOM, CloudFunc; return lRet; } }, - DOMTreeProto = function(){ + DOMTreeProto = function(){ /** * add class to element * @@ -256,8 +251,21 @@ var CloudCommander, Util, DOM, CloudFunc; this.getByClass = function(pClass, pElement){ return (pElement || document).getElementsByClassName(pClass); }; + + /** + * add class=hidden to element + * + * @param pElement + */ + this.hide = function(pElement){ + return this.addClass(pElement, 'hidden'); + }; + + this.show = function(pElement){ + this.removeClass(pElement, 'hidden'); + }; }, - EventsProto = function(){ + EventsProto = function(){ /** * safe add event listener * @@ -450,13 +458,7 @@ var CloudCommander, Util, DOM, CloudFunc; return lRet; }; }, - /** - * Обьект для работы с кэшем - * в него будут включены функции для - * работы с LocalStorage, webdb, - * indexed db etc. - */ - CacheProto = function(){ + CacheProto = function(){ /* приватный переключатель возможности работы с кэшем */ var CacheAllowed; @@ -528,1294 +530,1285 @@ var CloudCommander, Util, DOM, CloudFunc; return lRet; }; }, - RESTfull = function(){}, - Images = function(){}, - Cache = function(){}; - - DOMConstructor.prototype = DOMProto; - DOM = new DOMConstructor(); - - RESTfull.prototype = new RESTfullProto(); - DOMProto.RESTfull = new RESTfull(); - - Images.prototype = new ImagesProto(); - DOMProto.Images = new Images(); - - Cache.prototype = new CacheProto(); - DOMProto.Cache = new Cache(); - - Util.extend(DOMProto, [ - DOMTreeProto, - EventsProto - ]); - - /** - * private function thet unset currentfile - * - * @pCurrentFile - */ - function unsetCurrentFile(pCurrentFile){ - var lRet = DOMProto.isCurrentFile(pCurrentFile); - - if(lRet) - DOMProto.removeClass(pCurrentFile, CURRENT_FILE); - - return lRet; - } - - - /** - * load file countent thrue ajax - * - * @param pParams - */ - DOMProto.ajax = function(pParams){ - var lRet = Util.checkObjTrue(pParams, ['url', 'success']); - if(lRet){ - var p = pParams, - lType = p.type || p.method || 'GET'; + CmdProto = function(){ + var CURRENT_FILE = 'current-file', + SELECTED_FILE = 'selected-file', + XMLHTTP, Title; - if(!XMLHTTP) - XMLHTTP = new XMLHttpRequest(); - - XMLHTTP.open(lType, pParams.url, true); - XMLHTTP.send(p.data); - - XMLHTTP.onreadystatechange = function(pEvent){ - if (XMLHTTP.readyState === 4 /* Complete */){ - var lJqXHR = pEvent.target, - lType = XMLHTTP.getResponseHeader('content-type'); - - if (XMLHTTP.status === 200 /* OK */){ - var lData = lJqXHR.response; - - /* If it's json - parse it as json */ - if(lType && Util.isContainStr(lType, 'application/json') ) - lData = Util.parseJSON(lJqXHR.response) || lJqXHR.response; - - if( Util.isFunction(p.success) ) - p.success(lData, lJqXHR.statusText, lJqXHR); - } - /* file not found or connection lost */ - else{ - /* if html given or something like thet - * getBack just status of result - */ - if(lType && lType.indexOf('text/plain') !== 0) - lJqXHR.responseText = lJqXHR.statusText; - - Util.exec(p.error, lJqXHR); - } - } - }; - } - return lRet; - }; - - /** - * create new folder - * - * @pCurrentFile - */ - DOMProto.promptNewDir = function(){ - DOMProto.promptNewFile('directory', '?dir'); - }; - - /** - * create new file - * - * @pCurrentFile - */ - DOMProto.promptNewFile = function(pTypeName, pType){ - var lName = DOMProto.getCurrentName(), - lDir = DOMProto.getCurrentDirPath(), - lMsg = 'New ' + pTypeName || 'File', - lType = Util.isString(pType) ? pType : ''; - - if(lName === '..') - lName = ''; - - lName = prompt(lMsg, lName); - - if(lName) - DOMProto.RESTfull.save(lDir + lName + lType, null, CloudCommander.refresh); - }; - - - - /** - * delete currentfile, prompt before it - * - * @pCurrentFile - */ - DOMProto.promptDeleteSelected = function(pCurrentFile){ - var lRet, - lCurrent, lQuery, lMsg, - lName = '', - lMsgAsk = 'Do you really want to delete the ', - lMsgSel = 'selected ', - lFiles = DOMProto.getSelectedFiles(), - lSelected = DOMProto.getSelectedNames(lFiles), - i, n = lSelected && lSelected.length; - - if(n > 1){ - for(i = 0; i < 5 && i < n; i++) - lName += '\n' + lSelected[i]; - - if(n >= 5) - lName += '\n...'; - - lMsg = lMsgAsk + lMsgSel + n + ' files/directoris?\n' + lName ; - lQuery = '?files'; - }else{ - var lType, lIsDir; - - /* dom element passed and it is not event */ - if( pCurrentFile && !pCurrentFile.pType) - lCurrent = pCurrentFile; - else - lCurrent = DOMProto.getCurrentFile(); - - lIsDir = DOMProto.isCurrentIsDir(lCurrent); - - if(lIsDir){ - lQuery = '?dir'; - lType ='directory'; - } - else - lType = 'file'; - - lType += ' '; - - lName = DOMProto.getCurrentName(lCurrent); - lMsg = lMsgAsk + lMsgSel + lType + lName + '?'; - } - - if(lName !== '..') - lRet = confirm(lMsg); - else - alert('No files selected!'); - if(lRet){ - var lUrl; - - if(lCurrent) - lUrl = DOMProto.getCurrentPath(lCurrent); - else{ - lUrl = DOMProto.getCurrentDirPath(); - lCurrent = lFiles[0]; - } - - if(lCurrent || lSelected) - DOMProto.RESTfull.delete(lUrl, lSelected, function(){ - if(n > 1) - DOMProto.deleteSelected(lFiles); - else - DOMProto.deleteCurrent(lCurrent); - - var lDir = CloudFunc.removeLastSlash( - DOMProto.getCurrentDirPath() - ); - - DOMProto.Cache.remove(lDir); - }, lQuery); - - return lCurrent; - } - - return lRet; - }; - - /** - * Function gets id by src - * @param pSrc - * - * Example: http://domain.com/1.js -> 1_js - */ - DOMProto.getIdBySrc = function(pSrc){ - var lRet = Util.isString(pSrc); - - if(lRet){ - var lNum = pSrc.lastIndexOf('/') + 1, - lSub = pSrc.substr(pSrc, lNum), - lID = Util.removeStrOneTime(pSrc, lSub ); - - /* убираем точки */ - while(lID.indexOf('.') > 0) - lID = lID.replace('.', '_'); - - lRet = lID; - } - - return lRet; - }, - - /** - * create elements and load them to DOM-tree - * one-by-one - * - * @param pParams_a - * @param pFunc - onload function - */ - DOMProto.anyLoadOnLoad = function(pParams_a, pFunc){ - var lRet = this; - - if( Util.isArray(pParams_a) ) { - var lParam = pParams_a.pop(), - lFunc = function(){ - DOMProto.anyLoadOnLoad(pParams_a, pFunc); - }; - - if( Util.isString(lParam) ) - lParam = { src : lParam }; - else if( Util.isArray(lParam) ){ - - DOMProto.anyLoadInParallel(lParam, lFunc); - } - - if(lParam && !lParam.func){ - lParam.func = lFunc; - - DOMProto.anyload(lParam); - - }else - Util.exec(pFunc); - } - - return lRet; - }; - - /** - * improve callback of funcs so - * we pop number of function and - * if it's last we call pCallBack - * - * @param pParams_a - * @param pFunc - onload function - */ - DOMProto.anyLoadInParallel = function(pParams_a, pFunc){ - var lRet = this, - lDone = [], - - lDoneFunc = function (pCallBack){ - Util.exec(pCallBack); - - if( !lDone.pop() ) - Util.exec(pFunc); - }; - - if( !Util.isArray(pParams_a) ){ - pParams_a = [pParams_a]; - } - - for(var i = 0, n = pParams_a.length; i < n; i++){ - var lParam = pParams_a.pop(); - - if(lParam){ - lDone.push(i); - - if(Util.isString(lParam) ) - lParam = { src : lParam }; - - var lFunc = lParam.func; - lParam.func = Util.retExec(lDoneFunc, lFunc); - - DOMProto.anyload(lParam); - } - } - - return lRet; - }; - - /** - * Функция создаёт элемент и загружает файл с src. - * - * @param pParams_o = { - * name, - название тэга - * src', - путь к файлу - * func, - обьект, содержаий одну из функций - * или сразу две onload и onerror - * {onload: function(){}, onerror: function();} - * style, - * id, - * element, - * async, - true by default - * inner: 'id{color:red, }, - * class, - * not_append - false by default - * } - */ - DOMProto.anyload = function(pParams_o){ - - if( !pParams_o ) return; - - /* if a couple of params was - * processing every of params - * and quit - */ - if( Util.isArray(pParams_o) ){ - var lElements_a = []; - for(var i = 0, n = pParams_o.length; i < n ; i++) - lElements_a[i] = DOMProto.anyload(pParams_o[i]); - - return lElements_a; - } - - var lName = pParams_o.name, - lID = pParams_o.id, - lClass = pParams_o.className, - lSrc = pParams_o.src, - lFunc = pParams_o.func, - lOnError, - lAsync = pParams_o.async, - lParent = pParams_o.parent || document.body, - lInner = pParams_o.inner, - lStyle = pParams_o.style, - lNotAppend = pParams_o.not_append; - - if ( Util.isObject(lFunc) ){ - lOnError = lFunc.onerror; - lFunc = lFunc.onload; - } - /* убираем путь к файлу, оставляя только название файла */ - if(!lID && lSrc) - lID = DOMProto.getIdBySrc(lSrc); - - var lElement = DOMProto.getById(lID); - - /* если скрипт еще не загружен */ - if(!lElement){ - if(!lName && lSrc){ - - var lDot = lSrc.lastIndexOf('.'), - lExt = lSrc.substr(lDot); - switch(lExt){ - case '.js': - lName = 'script'; - break; - case '.css': - lName = 'link'; - lParent = document.head; - break; - default: - return {code: -1, text: 'name can not be empty'}; - } - } - lElement = document.createElement(lName); - - if(lID) - lElement.id = lID; - - if(lClass) - lElement.className = lClass; - - /* if working with external css - * using href in any other case - * using src + /** + * private function thet unset currentfile + * + * @pCurrentFile */ - if(lName === 'link'){ - lElement.href = lSrc; - lElement.rel = 'stylesheet'; - }else - lElement.src = lSrc; + function unsetCurrentFile(pCurrentFile){ + var lRet = DOM.isCurrentFile(pCurrentFile); + + if(lRet) + DOM.removeClass(pCurrentFile, CURRENT_FILE); + + return lRet; + } - /* - * if passed arguments function - * then it's onload by default + + /** + * load file countent thrue ajax + * + * @param pParams + */ + this.ajax = function(pParams){ + var lRet = Util.checkObjTrue(pParams, ['url', 'success']); + if(lRet){ + var p = pParams, + lType = p.type || p.method || 'GET'; + + if(!XMLHTTP) + XMLHTTP = new XMLHttpRequest(); + + XMLHTTP.open(lType, pParams.url, true); + XMLHTTP.send(p.data); + + XMLHTTP.onreadystatechange = function(pEvent){ + if (XMLHTTP.readyState === 4 /* Complete */){ + var lJqXHR = pEvent.target, + lType = XMLHTTP.getResponseHeader('content-type'); + + if (XMLHTTP.status === 200 /* OK */){ + var lData = lJqXHR.response; + + /* If it's json - parse it as json */ + if(lType && Util.isContainStr(lType, 'application/json') ) + lData = Util.parseJSON(lJqXHR.response) || lJqXHR.response; + + if( Util.isFunction(p.success) ) + p.success(lData, lJqXHR.statusText, lJqXHR); + } + /* file not found or connection lost */ + else{ + /* if html given or something like thet + * getBack just status of result + */ + if(lType && lType.indexOf('text/plain') !== 0) + lJqXHR.responseText = lJqXHR.statusText; + + Util.exec(p.error, lJqXHR); + } + } + }; + } + return lRet; + }; + + /** + * create new folder * - * if object - then onload and onerror + * @pCurrentFile */ - - var lLoad = function(pEvent){ - DOMProto.removeListener('load', lLoad, lElement); - DOMProto.removeListener('error', lError, lElement); - - Util.exec(lFunc, pEvent); - }, - - lError = function(){ - lParent.removeChild(lElement); - - DOMProto.Images.showError({ - responseText: 'file ' + - lSrc + - ' could not be loaded', - status : 404 - }); - - Util.exec(lOnError); - }; - - DOMProto.addListener('load', lLoad, lElement); - DOMProto.addErrorListener(lError, lElement); - - if(lStyle) - lElement.style.cssText = lStyle; - - if(lAsync || lAsync === undefined) - lElement.async = true; - - if(!lNotAppend) - lParent.appendChild(lElement); - - if(lInner) - lElement.innerHTML = lInner; - } - /* если js-файл уже загружен - * запускаем функцию onload - */ - else - Util.exec(lFunc); - - return lElement; - }, - - /** - * Функция загружает js-файл - * - * @param pSrc - * @param pFunc - */ - DOMProto.jsload = function(pSrc, pFunc){ - if( Util.isArray(pSrc) ){ - for(var i=0; i < pSrc.length; i++) - pSrc[i].name = 'script'; - - return DOMProto.anyload(pSrc); - } - - return DOMProto.anyload({ - name : 'script', - src : pSrc, - func : pFunc - }); - }, - - /** - * returns jsload functions - */ - DOMProto.retJSLoad = function(pSrc, pFunc){ - var lRet = function(){ - return DOMProto.jsload(pSrc, pFunc); - }; - - return lRet; - }, - - - /** - * Функция создаёт елемент style и записывает туда стили - * @param pParams_o - структура параметров, заполняеться таким - * образом: {src: ' ',func: '', id: '', element: '', inner: ''} - * все параметры опциональны - */ - DOMProto.cssSet = function(pParams_o){ - pParams_o.name = 'style'; - pParams_o.parent = pParams_o.parent || document.head; - - return DOMProto.anyload(pParams_o); - }, - - /** - * Function loads external css files - * @pParams_o - структура параметров, заполняеться таким - * образом: {src: ' ',func: '', id: '', element: '', inner: ''} - * все параметры опциональны - */ - DOMProto.cssLoad = function(pParams_o){ - if( Util.isArray(pParams_o) ){ - for(var i = 0, n = pParams_o.length; i < n; i++){ - pParams_o[i].name = 'link'; - pParams_o[i].parent = pParams_o.parent || document.head; - } - - return DOMProto.anyload(pParams_o); - } - - else if( Util.isString(pParams_o) ) - pParams_o = { src: pParams_o }; - - pParams_o.name = 'link'; - pParams_o.parent = pParams_o.parent || document.head; - - return DOMProto.anyload(pParams_o); - }; - - /** - * load jquery from google cdn or local copy - * @param pCallBack - */ - DOMProto.jqueryLoad = function(pCallBack){ - /* загружаем jquery: */ - DOMProto.jsload('//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js',{ - onload: Util.retExec(pCallBack), - - onerror: function(){ - DOMProto.jsload('/lib/client/jquery.js'); - - /* if could not load jquery from google server - * maybe we offline, load font from local - * directory */ - DOMProto.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");}' - }); - } - }); - }; - - /** - * load socket.io - * @param pCallBack - */ - DOMProto.socketLoad = function(pCallBack){ - DOMProto.jsload('/lib/client/socket.js', Util.retExec(pCallBack) ); - }; - - - /** - * get current direcotory name - */ - DOMProto.getCurrentDirName = function(){ - var lRet, - lSubstr, - lPanel = DOMProto.getPanel(), - /* получаем имя каталога в котором находимся */ - lHref = DOMProto.getByClass('path', lPanel); - - lHref = lHref[0].textContent; - - lHref = CloudFunc.removeLastSlash(lHref); - lSubstr = lHref.substr(lHref , lHref.lastIndexOf('/')); - lRet = Util.removeStrOneTime(lHref, lSubstr + '/') || '/'; - - return lRet; - }; - - /** - * get current direcotory path - */ - DOMProto.getCurrentDirPath = function(pPanel){ - var lPanel = pPanel || DOMProto.getPanel(), - lPath = DOMProto.getByClass('path', lPanel)[0], - lRet; - - if(lPath) - lRet = lPath.textContent; - - return lRet; - }; - - /** - * get current direcotory path - */ - DOMProto.getNotCurrentDirPath = function(){ - var lPanel = DOMProto.getPanel(true), - lPath = DOMProto.getByClass('path', lPanel)[0], - lRet; - - if(lPath) - lRet = lPath.textContent; - - return lRet; - }; - - /** - * unified way to get current file - * - * @pCurrentFile - */ - DOMProto.getCurrentFile = function(){ - var lRet = DOMProto.getByClass( CURRENT_FILE )[0]; - - return lRet; - }; - - /** - * unified way to get current file - * - * @pCurrentFile - */ - DOMProto.getSelectedFiles = function(){ - var lRet = DOMProto.getByClass(SELECTED_FILE); - - return lRet.length ? lRet : null; - }; - - /** - * get size - * @pCurrentFile - */ - DOMProto.getCurrentSize = function(pCurrentFile){ - var lRet, - lCurrent = pCurrentFile || DOMProto.getCurrentFile(), - lSize = DOMProto.getByClass('size', lCurrent); - lSize = lSize[0].textContent; - /* если это папка - возвращаем слово dir вместо размера*/ - lRet = Util.removeStrOneTime(lSize, ['<', '>']); - - return lRet; - }; - - /** - * get size - * @pCurrentFile - */ - DOMProto.loadCurrentSize = function(pCallBack, pCurrent){ - var lRet, - lCurrent = pCurrent || DOMProto.getCurrentFile(), - lLink = DOMProto.getCurrentPath(lCurrent), - lName = DOMProto.getCurrentName(lCurrent); - /* если это папка - возвращаем слово dir вместо размера*/ - - if(lName !== '..') - DOMProto.RESTfull.read(lLink, function(pSize){ - DOMProto.setCurrentSize(pSize, lCurrent); - Util.exec(pCallBack, lCurrent); - }, '?size'); - - return lRet; - }; - - /** - * set size - * @pCurrentFile - */ - DOMProto.setCurrentSize = function(pSize, pCurrentFile){ - var lCurrent = pCurrentFile || DOMProto.getCurrentFile(), - lSizeElement = DOMProto.getByClass('size', lCurrent), - lSize = CloudFunc.getShortSize(pSize); - - lSizeElement[0].textContent = lSize; - - }; - - /** - * @pCurrentFile - */ - DOMProto.getCurrentMode = function(pCurrentFile){ - var lRet, - lCurrent = pCurrentFile || DOMProto.getCurrentFile(), - lMode = DOMProto.getByClass('mode', lCurrent); - lRet = lMode[0].textContent; - - return lRet; - }; - - /** - * unified way to get current file content - * - * @pCallBack - callback function or data struct {sucess, error} - * @pCurrentFile - */ - DOMProto.getCurrentFileContent = function(pParams, pCurrentFile){ - var lRet, - lCurrentFile = pCurrentFile ? pCurrentFile : DOMProto.getCurrentFile(), - lParams = pParams ? pParams : {}, - lPath = DOMProto.getCurrentPath(lCurrentFile), - lErrorWas = pParams.error, - lError = function(jqXHR){ - Util.exec(lErrorWas); - DOMProto.Images.showError(jqXHR); + this.promptNewDir = function(){ + this.promptNewFile('directory', '?dir'); }; - - if( Util.isFunction(lParams) ) - lParams.success = Util.retExec(pParams); - - lParams.error = lError; - - - if( DOMProto.isCurrentIsDir(lCurrentFile) ) - lPath += '?json'; - - if(!lParams.url) - lParams.url = CloudFunc.FS + lPath; - - lRet = DOMProto.ajax(lParams); - - return lRet; - }; - - /** - * unified way to get current file content - * - * @pCallBack - function({data, name}){} - * @pCurrentFile - */ - DOMProto.getCurrentData = function(pCallBack, pCurrentFile){ - - var lParams, - lCurrentFile = pCurrentFile ? pCurrentFile : DOMProto.getCurrentFile(), - lFunc = function(pData){ - var lName = DOMProto.getCurrentName(lCurrentFile); - if( Util.isObject(pData) ){ - pData = Util.stringifyJSON(pData); + + /** + * create new file + * + * @pCurrentFile + */ + this.promptNewFile = function(pTypeName, pType){ + var lName = this.getCurrentName(), + lDir = this.getCurrentDirPath(), + lMsg = 'New ' + pTypeName || 'File', + lType = Util.isString(pType) ? pType : ''; + + if(lName === '..') + lName = ''; + + lName = prompt(lMsg, lName); + + if(lName) + RESTfull.save(lDir + lName + lType, null, CloudCommander.refresh); + }; + + + + /** + * delete currentfile, prompt before it + * + * @pCurrentFile + */ + this.promptDeleteSelected = function(pCurrentFile){ + var lRet, + lCurrent, lQuery, lMsg, + lName = '', + lMsgAsk = 'Do you really want to delete the ', + lMsgSel = 'selected ', + lFiles = this.getSelectedFiles(), + lSelected = this.getSelectedNames(lFiles), + i, n = lSelected && lSelected.length; - var lExt = '.json'; - if( !Util.checkExtension(lName, lExt) ) - lName += lExt; + if(n > 1){ + for(i = 0; i < 5 && i < n; i++) + lName += '\n' + lSelected[i]; + + if(n >= 5) + lName += '\n...'; + + lMsg = lMsgAsk + lMsgSel + n + ' files/directoris?\n' + lName ; + lQuery = '?files'; + }else{ + var lType, lIsDir; + + /* dom element passed and it is not event */ + if( pCurrentFile && !pCurrentFile.pType) + lCurrent = pCurrentFile; + else + lCurrent = this.getCurrentFile(); + + lIsDir = this.isCurrentIsDir(lCurrent); + + if(lIsDir){ + lQuery = '?dir'; + lType ='directory'; + } + else + lType = 'file'; + + lType += ' '; + + lName = this.getCurrentName(lCurrent); + lMsg = lMsgAsk + lMsgSel + lType + lName + '?'; } - Util.exec(pCallBack, { - data: pData, - name: lName + if(lName !== '..') + lRet = confirm(lMsg); + else + alert('No files selected!'); + if(lRet){ + var lUrl; + + if(lCurrent) + lUrl = this.getCurrentPath(lCurrent); + else{ + lUrl = this.getCurrentDirPath(); + lCurrent = lFiles[0]; + } + + if(lCurrent || lSelected) + RESTfull.delete(lUrl, lSelected, function(){ + if(n > 1) + DOM.deleteSelected(lFiles); + else + DOM.deleteCurrent(lCurrent); + + var lDir = CloudFunc.removeLastSlash( + DOM.getCurrentDirPath() + ); + + Cache.remove(lDir); + }, lQuery); + + return lCurrent; + } + + return lRet; + }; + + /** + * Function gets id by src + * @param pSrc + * + * Example: http://domain.com/1.js -> 1_js + */ + this.getIdBySrc = function(pSrc){ + var lRet = Util.isString(pSrc); + + if(lRet){ + var lNum = pSrc.lastIndexOf('/') + 1, + lSub = pSrc.substr(pSrc, lNum), + lID = Util.removeStrOneTime(pSrc, lSub ); + + /* убираем точки */ + while(lID.indexOf('.') > 0) + lID = lID.replace('.', '_'); + + lRet = lID; + } + + return lRet; + }, + + /** + * create elements and load them to DOM-tree + * one-by-one + * + * @param pParams_a + * @param pFunc - onload function + */ + this.anyLoadOnLoad = function(pParams_a, pFunc){ + var lRet = this; + + if( Util.isArray(pParams_a) ) { + var lParam = pParams_a.pop(), + lFunc = function(){ + this.anyLoadOnLoad(pParams_a, pFunc); + }; + + if( Util.isString(lParam) ) + lParam = { src : lParam }; + else if( Util.isArray(lParam) ){ + + this.anyLoadInParallel(lParam, lFunc); + } + + if(lParam && !lParam.func){ + lParam.func = lFunc; + + this.anyload(lParam); + + }else + Util.exec(pFunc); + } + + return lRet; + }; + + /** + * improve callback of funcs so + * we pop number of function and + * if it's last we call pCallBack + * + * @param pParams_a + * @param pFunc - onload function + */ + this.anyLoadInParallel = function(pParams_a, pFunc){ + var lRet = this, + lDone = [], + + lDoneFunc = function (pCallBack){ + Util.exec(pCallBack); + + if( !lDone.pop() ) + Util.exec(pFunc); + }; + + if( !Util.isArray(pParams_a) ){ + pParams_a = [pParams_a]; + } + + for(var i = 0, n = pParams_a.length; i < n; i++){ + var lParam = pParams_a.pop(); + + if(lParam){ + lDone.push(i); + + if(Util.isString(lParam) ) + lParam = { src : lParam }; + + var lFunc = lParam.func; + lParam.func = Util.retExec(lDoneFunc, lFunc); + + this.anyload(lParam); + } + } + + return lRet; + }; + + /** + * Функция создаёт элемент и загружает файл с src. + * + * @param pParams_o = { + * name, - название тэга + * src', - путь к файлу + * func, - обьект, содержаий одну из функций + * или сразу две onload и onerror + * {onload: function(){}, onerror: function();} + * style, + * id, + * element, + * async, - true by default + * inner: 'id{color:red, }, + * class, + * not_append - false by default + * } + */ + this.anyload = function(pParams_o){ + + if( !pParams_o ) return; + + /* if a couple of params was + * processing every of params + * and quit + */ + if( Util.isArray(pParams_o) ){ + var lElements_a = []; + for(var i = 0, n = pParams_o.length; i < n ; i++) + lElements_a[i] = this.anyload(pParams_o[i]); + + return lElements_a; + } + + var lName = pParams_o.name, + lID = pParams_o.id, + lClass = pParams_o.className, + lSrc = pParams_o.src, + lFunc = pParams_o.func, + lOnError, + lAsync = pParams_o.async, + lParent = pParams_o.parent || document.body, + lInner = pParams_o.inner, + lStyle = pParams_o.style, + lNotAppend = pParams_o.not_append; + + if ( Util.isObject(lFunc) ){ + lOnError = lFunc.onerror; + lFunc = lFunc.onload; + } + /* убираем путь к файлу, оставляя только название файла */ + if(!lID && lSrc) + lID = this.getIdBySrc(lSrc); + + var lElement = this.getById(lID); + + /* если скрипт еще не загружен */ + if(!lElement){ + if(!lName && lSrc){ + + var lDot = lSrc.lastIndexOf('.'), + lExt = lSrc.substr(lDot); + switch(lExt){ + case '.js': + lName = 'script'; + break; + case '.css': + lName = 'link'; + lParent = document.head; + break; + default: + return {code: -1, text: 'name can not be empty'}; + } + } + lElement = document.createElement(lName); + + if(lID) + lElement.id = lID; + + if(lClass) + lElement.className = lClass; + + /* if working with external css + * using href in any other case + * using src + */ + if(lName === 'link'){ + lElement.href = lSrc; + lElement.rel = 'stylesheet'; + }else + lElement.src = lSrc; + + /* + * if passed arguments function + * then it's onload by default + * + * if object - then onload and onerror + */ + + var lLoad = function(pEvent){ + Events.removeListener('load', lLoad, lElement); + Events.removeListener('error', lError, lElement); + + Util.exec(lFunc, pEvent); + }, + + lError = function(){ + lParent.removeChild(lElement); + + Images.showError({ + responseText: 'file ' + + lSrc + + ' could not be loaded', + status : 404 + }); + + Util.exec(lOnError); + }; + + Events.addListener('load', lLoad, lElement); + Events.addErrorListener(lError, lElement); + + if(lStyle) + lElement.style.cssText = lStyle; + + if(lAsync || lAsync === undefined) + lElement.async = true; + + if(!lNotAppend) + lParent.appendChild(lElement); + + if(lInner) + lElement.innerHTML = lInner; + } + /* если js-файл уже загружен + * запускаем функцию onload + */ + else + Util.exec(lFunc); + + return lElement; + }, + + /** + * Функция загружает js-файл + * + * @param pSrc + * @param pFunc + */ + this.jsload = function(pSrc, pFunc){ + if( Util.isArray(pSrc) ){ + 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 + }); + }, + + /** + * returns jsload functions + */ + this.retJSLoad = function(pSrc, pFunc){ + var lRet = function(){ + return this.jsload(pSrc, pFunc); + }; + + return lRet; + }, + + + /** + * Функция создаёт елемент style и записывает туда стили + * @param 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( Util.isArray(pParams_o) ){ + for(var i = 0, n = pParams_o.length; i < n; i++){ + pParams_o[i].name = 'link'; + pParams_o[i].parent = pParams_o.parent || document.head; + } + + return this.anyload(pParams_o); + } + + else if( Util.isString(pParams_o) ) + pParams_o = { src: pParams_o }; + + pParams_o.name = 'link'; + pParams_o.parent = pParams_o.parent || document.head; + + return this.anyload(pParams_o); + }; + + /** + * load jquery from google cdn or local copy + * @param pCallBack + */ + this.jqueryLoad = function(pCallBack){ + /* загружаем jquery: */ + this.jsload('//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js',{ + onload: Util.retExec(pCallBack), + + onerror: function(){ + this.jsload('/lib/client/jquery.js'); + + /* if could not load jquery from google server + * maybe we offline, load font from local + * directory */ + this.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");}' + }); + } }); }; - - if( !Util.isObject(pCallBack) ) - lParams = lFunc; - else - lParams = { - success : lFunc, - error : pCallBack.error + + /** + * load socket.io + * @param pCallBack + */ + this.socketLoad = function(pCallBack){ + this.jsload('/lib/client/socket.js', Util.retExec(pCallBack) ); }; - - return DOMProto.getCurrentFileContent(lParams, lCurrentFile); - }; - - /** - * unified way to get RefreshButton - */ - DOMProto.getRefreshButton = function(){ - var lPanel = DOMProto.getPanel(), - lRefresh = DOMProto.getByClass(CloudFunc.REFRESHICON, lPanel), - lRet = lRefresh[0]; - - return lRet; - }; - - - /** - * unified way to set current file - */ - DOMProto.setCurrentFile = function(pCurrentFile){ - var lRet, - lCurrentFileWas = DOMProto.getCurrentFile(); - - if(pCurrentFile){ - if (pCurrentFile.className === 'path') - pCurrentFile = pCurrentFile.nextSibling; - if (pCurrentFile.className === 'fm-header') - pCurrentFile = pCurrentFile.nextSibling; - - if(lCurrentFileWas) - unsetCurrentFile(lCurrentFileWas); - - DOMProto.addClass(pCurrentFile, CURRENT_FILE); - - /* scrolling to current file */ - DOMProto.scrollIntoViewIfNeeded(pCurrentFile); - - lRet = true; - } - - return lRet; - }; - - /** - * select current file - * @param pCurrent - */ - DOMProto.setSelectedFile = function(pCurrent){ - var lCurrent = pCurrent || DOMProto.getCurrentFile(), - lRet = DOMProto.addClass(pCurrent, SELECTED_FILE); - - if(!lRet) - DOMProto.unsetSelectedFile(lCurrent); - - return lRet; - }; - - /** - * unselect current file - * @param pCurrent - */ - DOMProto.unsetSelectedFile = function(pCurrent){ - var lCurrent = pCurrent || DOMProto.getCurrentFile(), - lRet = DOMProto.removeClass(lCurrent, SELECTED_FILE); - - return lRet; - }; - - /** - * setting history wrapper - */ - DOMProto.setHistory = function(pData, pTitle, pUrl){ - var lRet = window.history; - - if(lRet) - history.pushState(pData, pTitle, pUrl); - - return lRet; - }; - - /** - * set onclick handler on buttons f1-f10 - * @param pKey - 'f1'-'f10' - */ - DOMProto.setButtonKey = function(pKey, pFunc){ - Util.tryCatchLog(function(){ - CloudCommander.KeysPanel[pKey].onclick = pFunc; - }); - }; - - /** - * set title with pName - * create title element - * if it absent - * @param pName - */ - - DOMProto.setTitle = function(pName){ - if(!Title) - Title = DOMProto.getByTag('title')[0] || - DOMProto.anyload({ - name:'title', - parentElement: document.head, - innerHTML: pName - }); - if(Title) - Title.textContent = pName; - - return Title; - }; - - /** - * current file check - * - * @param pCurrentFile - */ - DOMProto.isCurrentFile = function(pCurrent){ - var lRet; - - if( pCurrent ) - lRet = DOMProto.isContainClass(pCurrent, CURRENT_FILE); - - return lRet; - }; - - /** - * selected file check - * - * @param pCurrentFile - */ - DOMProto.isSelected = function(pSelected){ - var lRet; - - if( pSelected ) - lRet = DOMProto.isContainClass(pSelected, SELECTED_FILE); - - return lRet; - }; - - /** - * check is current file is a directory - * - * @param pCurrentFile - */ - DOMProto.isCurrentIsDir = function(pCurrent){ - var lCurrent = pCurrent || DOMProto.getCurrentFile(), - lFileType = DOMProto.getByClass('mini-icon', lCurrent)[0], - lRet = DOMProto.isContainClass(lFileType, 'directory'); - - return lRet; - }; - - - /** - * get link from current (or param) file - * - * @param pCurrentFile - current file by default - */ - DOMProto.getCurrentLink = function(pCurrentFile){ - var lLink = DOMProto.getByTag( 'a', pCurrentFile || DOMProto.getCurrentFile() ), - - lRet = lLink.length > 0 ? lLink[0] : -1; - - return lRet; - }; - - /** - * get link from current (or param) file - * - * @param pCurrentFile - current file by default - */ - DOMProto.getCurrentPath = function(pCurrentFile){ - var lCurrent = pCurrentFile || DOMProto.getCurrentFile(), - lPath = DOMProto.getCurrentLink( lCurrent ).href; - - lPath = decodeURI(lPath); - /* убираем адрес хоста*/ - lPath = Util.removeStrOneTime( lPath, [CloudCommander.HOST, CloudFunc.FS] ); - - return lPath; - }; - - /** - * get name from current (or param) file - * - * @param pCurrentFile - */ - DOMProto.getCurrentName = function(pCurrentFile){ - var lCurrent = pCurrentFile || DOMProto.getCurrentFile(), - lLink = DOMProto.getCurrentLink( lCurrent ); - - if( Util.isObject(lLink) ) - lLink = lLink.title || lLink.textContent; - - return lLink; - }; - - DOMProto.getSelectedNames = function(pSelected){ - var lSelected = pSelected || DOMProto.getSelectedFiles(), - lRet = lSelected ? [] : null; - - if(lRet){ - var lFirst = lSelected[0], - lName = DOMProto.getCurrentName( lFirst ); - - if(lName === '..') - DOMProto.unsetSelectedFile( lFirst ); - - for(var i = 0, n = lSelected.length; i < n;i++) - lRet[i] = DOMProto.getCurrentName( lSelected[i] ); - } - return lRet; - }; - - /** - * set name from current (or param) file - * - * @param pCurrentFile - */ - DOMProto.setCurrentName = function(pName, pCurrentFile){ - var lLink = DOMProto.getCurrentLink( pCurrentFile ), - lDir = DOMProto.getCurrentDirName() + '/'; - - lLink.title = lLink.textContent = pName; - lLink.href = lDir + pName; - - return lLink; - }; - - /** function getting FM - * @param pPanel_o = {active: true} - */ - DOMProto.getFM = function(){ - return DOMProto.getPanel().parentElement; - }; - - /** function getting panel active, or passive - * @param pPanel_o = {active: true} - */ - DOMProto.getPanel = function(pActive){ - var lPanel = DOMProto.getCurrentFile().parentElement; - - /* if {active : false} getting passive panel */ - if(pActive && !pActive.active){ - var lId = lPanel.id === 'left' ? 'right' : 'left'; - lPanel = DOMProto.getById(lId); - } - - /* if two panels showed - * then always work with passive - * panel - */ - if(window.innerWidth < CloudCommander.MIN_ONE_PANEL_WIDTH) - lPanel = DOMProto.getById('left'); - - - if(!lPanel) - Util.log('Error can not find Active Panel'); - - return lPanel; - }; - - /** prevent default event */ - DOMProto.preventDefault = function(pEvent){ - var lRet, - lPreventDefault = pEvent && pEvent.preventDefault, - lFunc = Util.bind(lPreventDefault, pEvent); - - lRet = Util.exec(lFunc); - - return lRet; - }; - - DOMProto.show = function(pElement){ - DOMProto.removeClass(pElement, 'hidden'); - }; - - /** - * shows panel right or left (or active) - */ - DOMProto.showPanel = function(pActive){ - var lRet = true, - lPanel = DOMProto.getPanel(pActive); - - if(lPanel) - DOMProto.show(lPanel); - else - lRet = false; - - return lRet; - }; - - /** - * hides panel right or left (or active) - */ - DOMProto.hidePanel = function(pActive){ - var lRet = false, - lPanel = DOMProto.getPanel(pActive); - - if(lPanel) - lRet = DOMProto.hide(lPanel); - - return lRet; - }; - - /** - * add class=hidden to element - * - * @param pElement - */ - DOMProto.hide = function(pElement){ - return DOMProto.addClass(pElement, 'hidden'); - }; - - /** - * open window with URL - * @param pUrl - */ - DOMProto.openWindow = function(pUrl){ - var left = 140, - top = 187, - width = 1000, - height = 650, - - lOptions = 'left=' + left + - ',top=' + top + - ',width=' + width + - ',height=' + height + - ',personalbar=0,toolbar=0' + - ',scrollbars=1,resizable=1'; - - var lWind = window.open(pUrl, 'Cloud Commander Auth', lOptions); - if(!lWind) - Util.log('Pupup blocked!'); - }; - - /** - * remove child of element - * @param pChild - * @param pElement - */ - DOMProto.remove = function(pChild, pElement){ - return (pElement || document.body).removeChild(pChild); - }; - - /** - * remove class pClass from element pElement - * @param pElement - * @param pClass - */ - DOMProto.removeClass = function(pElement, pClass){ - var lRet_b = true, - lClassList = pElement.classList; - - if(pElement && lClassList) - lClassList.remove(pClass); - - else - lRet_b = false; - - return lRet_b; - }; - - /** - * remove current file from file table - * @pCurrent - */ - DOMProto.deleteCurrent = function(pCurrent, pNextFile, pPreviousFile, pNotSet){ - var lCurrent = pCurrent || DOMProto.getCurrentFile(), - lParent = lCurrent && lCurrent.parentElement, - lName = DOMProto.getCurrentName(lCurrent); - - if(lCurrent && lParent && lName !== '..'){ - var lNext = pNextFile || lCurrent.nextSibling, - lPrevious = pPreviousFile || lCurrent.previousSibling; - - if(!pNotSet) - if(lNext) - DOMProto.setCurrentFile(lNext); - else if(lPrevious) - DOMProto.setCurrentFile(lPrevious); - - lParent.removeChild(lCurrent); - } - - return lCurrent; - }; - - /** - * remove selected files from file table - * @Selected - */ - DOMProto.deleteSelected = function(pSelected){ - var lSelected = pSelected || DOMProto.getSelectedFiles(); - - if(lSelected){ - var n = lSelected.length, - lLast = n-1, - lNext = lSelected[lLast].nextSibling, - lPrev = lSelected[0].previousSibling; - - /* lSelected[0] - becouse lSelected is a link to DOM so - * when we remove 0 element, it's removed from lSelected to + /** + * get current direcotory name */ - for(var i = 0; i < n; i++) - DOMProto.deleteCurrent( lSelected[0], lNext, lPrev, i !== lLast); - } - - return lSelected; - }; - - /** - * rename current file - * - * @pCurrent - */ - DOMProto.renameCurrent = function(pCurrentFile){ - if( !DOMProto.isCurrentFile(pCurrentFile) ) - pCurrentFile = null; - - var lCurrent = pCurrentFile || DOMProto.getCurrentFile(), - lFrom = DOMProto.getCurrentName(lCurrent), - lTo = prompt('Rename', lFrom) || lFrom, - lDirPath = DOMProto.getCurrentDirPath(); - - if( !Util.strCmp(lFrom, lTo) ){ - var lFiles = { - from : lDirPath + lFrom, - to : lDirPath + lTo + this.getCurrentDirName = function(){ + var lRet, + lSubstr, + lPanel = this.getPanel(), + /* получаем имя каталога в котором находимся */ + lHref = this.getByClass('path', lPanel); + + lHref = lHref[0].textContent; + + lHref = CloudFunc.removeLastSlash(lHref); + lSubstr = lHref.substr(lHref , lHref.lastIndexOf('/')); + lRet = Util.removeStrOneTime(lHref, lSubstr + '/') || '/'; + + return lRet; }; - DOMProto.RESTfull.mv(lFiles, function(){ - DOMProto.setCurrentName(lTo, lCurrent); - }); - } - }; - - /** - * move current file - * - * @pCurrent - */ - DOMProto.moveCurrent = function(pCurrentFile){ - if( !DOMProto.isCurrentFile(pCurrentFile) ) - pCurrentFile = null; - - var lCurrent = pCurrentFile || DOMProto.getCurrentFile(), - lName = DOMProto.getCurrentName(lCurrent), - lFromPath = DOMProto.getCurrentPath(), - lToPath = DOMProto.getNotCurrentDirPath() + lName; - - lToPath = prompt( 'Rename/Move file "' + lName + '"', lToPath ); - - if( lToPath && !Util.strCmp(lFromPath, lToPath) ){ - var lFiles = { - from : lFromPath, - to : lToPath + /** + * get current direcotory path + */ + this.getCurrentDirPath = function(pPanel){ + var lPanel = pPanel || this.getPanel(), + lPath = this.getByClass('path', lPanel)[0], + lRet; + + if(lPath) + lRet = lPath.textContent; + + return lRet; }; - DOMProto.RESTfull.mv(lFiles, function(){ - DOMProto.deleteCurrent(lCurrent); + /** + * get current direcotory path + */ + this.getNotCurrentDirPath = function(){ + var lPanel = this.getPanel(true), + lPath = this.getByClass('path', lPanel)[0], + lRet; - var lPanel = DOMProto.getPanel(true), - lDotDot = DOMProto.getById( '..(' + lPanel.id + ')'); + if(lPath) + lRet = lPath.textContent; - DOMProto.setCurrentFile ( lDotDot ); - CloudCommander.refresh(); - }); - } - }; - - /** - * copy current file - * - * @pCurrent - */ - DOMProto.copyCurrent = function(pCurrentFile){ - if( !DOMProto.isCurrentFile(pCurrentFile) ) - pCurrentFile = null; - - var lCurrent = pCurrentFile || DOMProto.getCurrentFile(), - lName = DOMProto.getCurrentName(lCurrent), - lFromPath = DOMProto.getCurrentPath(), - lToPath = DOMProto.getNotCurrentDirPath() + lName; - lToPath = prompt( 'Copy file "' + lName + '" to', lToPath ); - - if( lToPath && !Util.strCmp(lFromPath, lToPath) ){ - var lFiles = { - from : lFromPath, - to : lToPath + return lRet; }; - DOMProto.RESTfull.cp(lFiles, function(){ - var lPanel = DOMProto.getPanel(true), - lDotDot = DOMProto.getById( '..(' + lPanel.id + ')'); + /** + * unified way to get current file + * + * @pCurrentFile + */ + this.getCurrentFile = function(){ + var lRet = this.getByClass( CURRENT_FILE )[0]; - DOMProto.setCurrentFile ( lDotDot ); - CloudCommander.refresh(); - }); - } - }; - - /** - * unified way to scrollIntoViewIfNeeded - * (native suporte by webkit only) - * @param pElement - */ - DOMProto.scrollIntoViewIfNeeded = function(pElement){ - var lRet = pElement && pElement.scrollIntoViewIfNeeded; - - if(lRet) - pElement.scrollIntoViewIfNeeded(); - - return lRet; - }; - - /* scroll on one page*/ - DOMProto.scrollByPages = function(pElement, pPages){ - var lRet = pElement && pElement.scrollByPages && pPages; - - if(lRet) - pElement.scrollByPages(pPages); - - return lRet; - }; - - /** - * function gets time - */ - DOMProto.getTime = function(){ - var lRet, - lDate = new Date(), - lHours = lDate.getHours(), - lMinutes = lDate.getMinutes(), - lSeconds = lDate.getSeconds(); + return lRet; + }; - lMinutes = lMinutes < 10 ? '0' + lMinutes : lMinutes; - lSeconds = lSeconds < 10 ? '0' + lSeconds : lSeconds; + /** + * unified way to get current file + * + * @pCurrentFile + */ + this.getSelectedFiles = function(){ + var lRet = this.getByClass(SELECTED_FILE); + + return lRet.length ? lRet : null; + }; + + /** + * get size + * @pCurrentFile + */ + this.getCurrentSize = function(pCurrentFile){ + var lRet, + lCurrent = pCurrentFile || this.getCurrentFile(), + lSize = this.getByClass('size', lCurrent); + lSize = lSize[0].textContent; + /* если это папка - возвращаем слово dir вместо размера*/ + lRet = Util.removeStrOneTime(lSize, ['<', '>']); + + return lRet; + }; + + /** + * get size + * @pCurrentFile + */ + this.loadCurrentSize = function(pCallBack, pCurrent){ + var lRet, + lCurrent = pCurrent || this.getCurrentFile(), + lLink = this.getCurrentPath(lCurrent), + lName = this.getCurrentName(lCurrent); + /* если это папка - возвращаем слово dir вместо размера*/ + + if(lName !== '..') + RESTfull.read(lLink, function(pSize){ + DOM.setCurrentSize(pSize, lCurrent); + Util.exec(pCallBack, lCurrent); + }, '?size'); + + return lRet; + }; + + /** + * set size + * @pCurrentFile + */ + this.setCurrentSize = function(pSize, pCurrentFile){ + var lCurrent = pCurrentFile || this.getCurrentFile(), + lSizeElement = this.getByClass('size', lCurrent), + lSize = CloudFunc.getShortSize(pSize); + + lSizeElement[0].textContent = lSize; + + }; + + /** + * @pCurrentFile + */ + this.getCurrentMode = function(pCurrentFile){ + var lRet, + lCurrent = pCurrentFile || this.getCurrentFile(), + lMode = this.getByClass('mode', lCurrent); + lRet = lMode[0].textContent; + + return lRet; + }; + + /** + * unified way to get current file content + * + * @pCallBack - callback function or data struct {sucess, error} + * @pCurrentFile + */ + this.getCurrentFileContent = function(pParams, pCurrentFile){ + var lRet, + lCurrentFile = pCurrentFile ? pCurrentFile : this.getCurrentFile(), + lParams = pParams ? pParams : {}, + lPath = this.getCurrentPath(lCurrentFile), + lErrorWas = pParams.error, + lError = function(jqXHR){ + Util.exec(lErrorWas); + Images.showError(jqXHR); + }; + + if( Util.isFunction(lParams) ) + lParams.success = Util.retExec(pParams); + + lParams.error = lError; + + + if( this.isCurrentIsDir(lCurrentFile) ) + lPath += '?json'; + + if(!lParams.url) + lParams.url = CloudFunc.FS + lPath; + + lRet = this.ajax(lParams); + + return lRet; + }; + + /** + * unified way to get current file content + * + * @pCallBack - function({data, name}){} + * @pCurrentFile + */ + this.getCurrentData = function(pCallBack, pCurrentFile){ + + var lParams, + lCurrentFile = pCurrentFile ? pCurrentFile : this.getCurrentFile(), + lFunc = function(pData){ + var lName = this.getCurrentName(lCurrentFile); + if( Util.isObject(pData) ){ + pData = Util.stringifyJSON(pData); + + var lExt = '.json'; + if( !Util.checkExtension(lName, lExt) ) + lName += lExt; + } + + Util.exec(pCallBack, { + data: pData, + name: lName + }); + }; + + if( !Util.isObject(pCallBack) ) + lParams = lFunc; + else + lParams = { + success : lFunc, + error : pCallBack.error + }; + + + return this.getCurrentFileContent(lParams, lCurrentFile); + }; + + /** + * unified way to get RefreshButton + */ + this.getRefreshButton = function(){ + var lPanel = this.getPanel(), + lRefresh = this.getByClass(CloudFunc.REFRESHICON, lPanel), + lRet = lRefresh[0]; + + return lRet; + }; + + + /** + * unified way to set current file + */ + this.setCurrentFile = function(pCurrentFile){ + var lRet, + lCurrentFileWas = this.getCurrentFile(); + + if(pCurrentFile){ + if (pCurrentFile.className === 'path') + pCurrentFile = pCurrentFile.nextSibling; + + if (pCurrentFile.className === 'fm-header') + pCurrentFile = pCurrentFile.nextSibling; + + if(lCurrentFileWas) + unsetCurrentFile(lCurrentFileWas); + + this.addClass(pCurrentFile, CURRENT_FILE); + + /* scrolling to current file */ + this.scrollIntoViewIfNeeded(pCurrentFile); + + lRet = true; + } + + return lRet; + }; + + /** + * select current file + * @param pCurrent + */ + this.setSelectedFile = function(pCurrent){ + var lCurrent = pCurrent || this.getCurrentFile(), + lRet = this.addClass(pCurrent, SELECTED_FILE); + + if(!lRet) + this.unsetSelectedFile(lCurrent); + + return lRet; + }; + + /** + * unselect current file + * @param pCurrent + */ + this.unsetSelectedFile = function(pCurrent){ + var lCurrent = pCurrent || this.getCurrentFile(), + lRet = this.removeClass(lCurrent, SELECTED_FILE); + + return lRet; + }; + + /** + * setting history wrapper + */ + this.setHistory = function(pData, pTitle, pUrl){ + var lRet = window.history; + + if(lRet) + history.pushState(pData, pTitle, pUrl); + + return lRet; + }; + + /** + * set onclick handler on buttons f1-f10 + * @param pKey - 'f1'-'f10' + */ + this.setButtonKey = function(pKey, pFunc){ + Util.tryCatchLog(function(){ + CloudCommander.KeysPanel[pKey].onclick = pFunc; + }); + }; + + /** + * set title with pName + * create title element + * if it absent + * @param pName + */ + + this.setTitle = function(pName){ + if(!Title) + Title = this.getByTag('title')[0] || + this.anyload({ + name:'title', + parentElement: document.head, + innerHTML: pName + }); + if(Title) + Title.textContent = pName; + + return Title; + }; + + /** + * current file check + * + * @param pCurrentFile + */ + this.isCurrentFile = function(pCurrent){ + var lRet; + + if( pCurrent ) + lRet = this.isContainClass(pCurrent, CURRENT_FILE); + + return lRet; + }; + + /** + * selected file check + * + * @param pCurrentFile + */ + this.isSelected = function(pSelected){ + var lRet; + + if( pSelected ) + lRet = this.isContainClass(pSelected, SELECTED_FILE); + + return lRet; + }; + + /** + * check is current file is a directory + * + * @param pCurrentFile + */ + this.isCurrentIsDir = function(pCurrent){ + var lCurrent = pCurrent || this.getCurrentFile(), + lFileType = this.getByClass('mini-icon', lCurrent)[0], + lRet = this.isContainClass(lFileType, 'directory'); + + return lRet; + }; + + + /** + * get link from current (or param) file + * + * @param pCurrentFile - current file by default + */ + this.getCurrentLink = function(pCurrentFile){ + var lLink = this.getByTag( 'a', pCurrentFile || this.getCurrentFile() ), + + lRet = lLink.length > 0 ? lLink[0] : -1; + + return lRet; + }; + + /** + * get link from current (or param) file + * + * @param pCurrentFile - current file by default + */ + this.getCurrentPath = function(pCurrentFile){ + var lCurrent = pCurrentFile || this.getCurrentFile(), + lPath = this.getCurrentLink( lCurrent ).href; + + lPath = decodeURI(lPath); + /* убираем адрес хоста*/ + lPath = Util.removeStrOneTime( lPath, [CloudCommander.HOST, CloudFunc.FS] ); + + return lPath; + }; + + /** + * get name from current (or param) file + * + * @param pCurrentFile + */ + this.getCurrentName = function(pCurrentFile){ + var lCurrent = pCurrentFile || this.getCurrentFile(), + lLink = this.getCurrentLink( lCurrent ); + + if( Util.isObject(lLink) ) + lLink = lLink.title || lLink.textContent; + + return lLink; + }; + + this.getSelectedNames = function(pSelected){ + var lSelected = pSelected || this.getSelectedFiles(), + lRet = lSelected ? [] : null; + + if(lRet){ + var lFirst = lSelected[0], + lName = this.getCurrentName( lFirst ); + + if(lName === '..') + this.unsetSelectedFile( lFirst ); + + for(var i = 0, n = lSelected.length; i < n;i++) + lRet[i] = this.getCurrentName( lSelected[i] ); + } + return lRet; + }; + + /** + * set name from current (or param) file + * + * @param pCurrentFile + */ + this.setCurrentName = function(pName, pCurrentFile){ + var lLink = this.getCurrentLink( pCurrentFile ), + lDir = this.getCurrentDirName() + '/'; + + lLink.title = lLink.textContent = pName; + lLink.href = lDir + pName; + + return lLink; + }; + + /** function getting FM + * @param pPanel_o = {active: true} + */ + this.getFM = function(){ + return this.getPanel().parentElement; + }; + + /** function getting panel active, or passive + * @param pPanel_o = {active: true} + */ + this.getPanel = function(pActive){ + var lPanel = this.getCurrentFile().parentElement; + + /* if {active : false} getting passive panel */ + if(pActive && !pActive.active){ + var lId = lPanel.id === 'left' ? 'right' : 'left'; + lPanel = this.getById(lId); + } + + /* if two panels showed + * then always work with passive + * panel + */ + if(window.innerWidth < CloudCommander.MIN_ONE_PANEL_WIDTH) + lPanel = this.getById('left'); + + + if(!lPanel) + Util.log('Error can not find Active Panel'); + + return lPanel; + }; + + /** prevent default event */ + this.preventDefault = function(pEvent){ + var lRet, + lPreventDefault = pEvent && pEvent.preventDefault, + lFunc = Util.bind(lPreventDefault, pEvent); + + lRet = Util.exec(lFunc); + + return lRet; + }; + + /** + * shows panel right or left (or active) + */ + this.showPanel = function(pActive){ + var lRet = true, + lPanel = this.getPanel(pActive); + + if(lPanel) + this.show(lPanel); + else + lRet = false; + + return lRet; + }; + + /** + * hides panel right or left (or active) + */ + this.hidePanel = function(pActive){ + var lRet = false, + lPanel = this.getPanel(pActive); + + if(lPanel) + lRet = this.hide(lPanel); + + return lRet; + }; + + /** + * open window with URL + * @param pUrl + */ + this.openWindow = function(pUrl){ + var left = 140, + top = 187, + width = 1000, + height = 650, + + lOptions = 'left=' + left + + ',top=' + top + + ',width=' + width + + ',height=' + height + + ',personalbar=0,toolbar=0' + + ',scrollbars=1,resizable=1'; + + var lWind = window.open(pUrl, 'Cloud Commander Auth', lOptions); + if(!lWind) + Util.log('Pupup blocked!'); + }; + + /** + * remove child of element + * @param pChild + * @param pElement + */ + this.remove = function(pChild, pElement){ + return (pElement || document.body).removeChild(pChild); + }; + + /** + * remove class pClass from element pElement + * @param pElement + * @param pClass + */ + this.removeClass = function(pElement, pClass){ + var lRet_b = true, + lClassList = pElement.classList; + + if(pElement && lClassList) + lClassList.remove(pClass); + + else + lRet_b = false; + + return lRet_b; + }; + + /** + * remove current file from file table + * @pCurrent + */ + this.deleteCurrent = function(pCurrent, pNextFile, pPreviousFile, pNotSet){ + var lCurrent = pCurrent || this.getCurrentFile(), + lParent = lCurrent && lCurrent.parentElement, + lName = this.getCurrentName(lCurrent); + + if(lCurrent && lParent && lName !== '..'){ + var lNext = pNextFile || lCurrent.nextSibling, + lPrevious = pPreviousFile || lCurrent.previousSibling; + + if(!pNotSet) + if(lNext) + this.setCurrentFile(lNext); + else if(lPrevious) + this.setCurrentFile(lPrevious); + + lParent.removeChild(lCurrent); + } + + return lCurrent; + }; + + /** + * remove selected files from file table + * @Selected + */ + this.deleteSelected = function(pSelected){ + var lSelected = pSelected || this.getSelectedFiles(); + + if(lSelected){ + var n = lSelected.length, + lLast = n-1, + lNext = lSelected[lLast].nextSibling, + lPrev = lSelected[0].previousSibling; + + /* lSelected[0] - becouse lSelected is a link to DOM so + * when we remove 0 element, it's removed from lSelected to + */ + for(var i = 0; i < n; i++) + this.deleteCurrent( lSelected[0], lNext, lPrev, i !== lLast); + } + + return lSelected; + }; + + /** + * rename current file + * + * @pCurrent + */ + this.renameCurrent = function(pCurrentFile){ + if( !this.isCurrentFile(pCurrentFile) ) + pCurrentFile = null; + + var lCurrent = pCurrentFile || this.getCurrentFile(), + lFrom = this.getCurrentName(lCurrent), + lTo = prompt('Rename', lFrom) || lFrom, + lDirPath = this.getCurrentDirPath(); + + if( !Util.strCmp(lFrom, lTo) ){ + var lFiles = { + from : lDirPath + lFrom, + to : lDirPath + lTo + }; + + RESTfull.mv(lFiles, function(){ + DOM.setCurrentName(lTo, lCurrent); + }); + } + }; + + /** + * move current file + * + * @pCurrent + */ + this.moveCurrent = function(pCurrentFile){ + if( !this.isCurrentFile(pCurrentFile) ) + pCurrentFile = null; + + var lCurrent = pCurrentFile || this.getCurrentFile(), + lName = this.getCurrentName(lCurrent), + lFromPath = this.getCurrentPath(), + lToPath = this.getNotCurrentDirPath() + lName; + + lToPath = prompt( 'Rename/Move file "' + lName + '"', lToPath ); + + if( lToPath && !Util.strCmp(lFromPath, lToPath) ){ + var lFiles = { + from : lFromPath, + to : lToPath + }; + + RESTfull.mv(lFiles, function(){ + DOM.deleteCurrent(lCurrent); + + var lPanel = DOM.getPanel(true), + lDotDot = DOM.getById( '..(' + lPanel.id + ')'); + + DOM.setCurrentFile ( lDotDot ); + CloudCommander.refresh(); + }); + } + }; + + /** + * copy current file + * + * @pCurrent + */ + this.copyCurrent = function(pCurrentFile){ + if( !this.isCurrentFile(pCurrentFile) ) + pCurrentFile = null; + + var lCurrent = pCurrentFile || this.getCurrentFile(), + lName = this.getCurrentName(lCurrent), + lFromPath = this.getCurrentPath(), + lToPath = this.getNotCurrentDirPath() + lName; + lToPath = prompt( 'Copy file "' + lName + '" to', lToPath ); + + if( lToPath && !Util.strCmp(lFromPath, lToPath) ){ + var lFiles = { + from : lFromPath, + to : lToPath + }; + + RESTfull.cp(lFiles, function(){ + var lPanel = DOM.getPanel(true), + lDotDot = DOM.getById( '..(' + lPanel.id + ')'); + + DOM.setCurrentFile ( lDotDot ); + CloudCommander.refresh(); + }); + } + }; + + /** + * unified way to scrollIntoViewIfNeeded + * (native suporte by webkit only) + * @param pElement + */ + this.scrollIntoViewIfNeeded = function(pElement){ + var lRet = pElement && pElement.scrollIntoViewIfNeeded; + + if(lRet) + pElement.scrollIntoViewIfNeeded(); + + return lRet; + }; + + /* scroll on one page*/ + this.scrollByPages = function(pElement, pPages){ + var lRet = pElement && pElement.scrollByPages && pPages; + + if(lRet) + pElement.scrollByPages(pPages); + + return lRet; + }; + + /** + * function gets time + */ + this.getTime = function(){ + var lRet, + lDate = new Date(), + lHours = lDate.getHours(), + lMinutes = lDate.getMinutes(), + lSeconds = lDate.getSeconds(); + + lMinutes = lMinutes < 10 ? '0' + lMinutes : lMinutes; + lSeconds = lSeconds < 10 ? '0' + lSeconds : lSeconds; + + lRet = lHours + ":" + lMinutes + ":" + lSeconds; + + return lRet; + }; + }, - lRet = lHours + ":" + lMinutes + ":" + lSeconds; - - return lRet; - }; + Images = Util.extendProto(ImagesProto), + RESTfull = Util.extendProto(RESTfullProto), + DOMTree = Util.extendProto(DOMTreeProto), + Events = Util.extendProto(EventsProto), + Cache = Util.extendProto(CacheProto); + + DOMProto = DOMFunc.prototype = new CmdProto(); + + Util.extend(DOMProto, [ + DOMTree, + Events, { + RESTfull: RESTfull, + Images : Images, + Cache : Cache + } + ]); + + DOM = new DOMFunc(); })(Util); \ No newline at end of file diff --git a/lib/util.js b/lib/util.js index b0d82633..b8103455 100644 --- a/lib/util.js +++ b/lib/util.js @@ -168,12 +168,31 @@ Util = exports || {}; return lRet; }; + Util.convertArrToObj = function(pArrKeys, pArrVal){ + var i, n, lName, lRet; + + if(pArrKeys && pArrVal){ + for(i = 0, n = pArrKeys; i < n; i++){ + lName = pArrKeys[i]; + lRet[lName] = pArrVal[i]; + } + } + + return lRet; + }; + + /** + * copy pObj properties to pTargetObject + * + * @pTarget + * @pObj + */ Util.extend = function(pTarget, PObj){ var i, n, lObj, lRet = Util.isObject(pTarget) ? pTarget : {}; if( Util.isArray(PObj) ) for(i = 0, n = PObj.length; i < n; i++) - Util.extend(pTarget, PObj[i]); + lRet = Util.extend(pTarget, PObj[i]); else if(PObj){ lObj = Util.isFunction(PObj) ? new PObj() : PObj; @@ -185,6 +204,20 @@ Util = exports || {}; return lRet; }; + /** + * copy pObj properties to pTargetObject + * + * @pTarget + * @pObj + */ + Util.extendProto = function(pObj){ + var lRet, F = function(){}; + F.prototype = Util.extend({}, pObj); + lRet = new F(); + + return lRet; + }; + /** for function * @param pI * @param pN