From f4ba5598daf8f115fe7098e64011ddaed5e35d21 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 6 Feb 2013 14:38:26 -0500 Subject: [PATCH] fixed bug with scrolling in opera and firefox --- ChangeLog | 2 + lib/client/dom.js | 2594 +++++++++++++++++++------------------- lib/client/ie.js | 543 ++++---- lib/client/keyBinding.js | 614 ++++----- 4 files changed, 1884 insertions(+), 1869 deletions(-) diff --git a/ChangeLog b/ChangeLog index b2ed6afc..7716e29f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -126,6 +126,8 @@ time was changed. * Fixed bug with old browsers suport. +* Fixed bug with scrolling in opera and firefox. + 2012.12.12, Version 0.1.8 diff --git a/lib/client/dom.js b/lib/client/dom.js index 49e4ad64..9d28f9b3 100644 --- a/lib/client/dom.js +++ b/lib/client/dom.js @@ -1,1292 +1,1304 @@ -var CloudCommander, Util, - DOM = {}, - CloudFunc; - -(function(Util, DOM){ - 'use strict'; - - /* PRIVATE */ - - /* private members */ - var /* название css-класа текущего файла*/ - CURRENT_FILE = 'current-file', - Listeners = [], - XMLHTTP, - Title, - - /* Обьект, который содержит - * функции для отображения - * картинок - */ - Images = function (){ - var getImage = function(pName){ - var lId = pName + '-image', - lE = DOM.getById(lId); - if (!lE) - lE = DOM.anyload({ - name : 'span', - className : 'icon ' + pName, - id : lId, - not_append : true - }); - - return lE; - }; - /* Функция создаёт картинку загрузки*/ - this.loading = function(){ - return getImage('loading'); - }; - - /* Функция создаёт картинку ошибки загрузки*/ - this.error = function(){ - return getImage('error'); - }; - }; - - Images = new Images(); - - function removeListenerFromList(pElement){ - var lRet; - - for(var i = 0, n = Listeners.length; i < n; i++){ - if(Listeners[i].element === pElement){ - Listeners[i] = null; - break; - } - } - - return lRet; - } - - /** - * private function thet unset currentfile - */ - function unSetCurrentFile(pCurrentFile){ - var lRet_b = DOM.isCurrentFile(pCurrentFile); - - if(!pCurrentFile) - DOM.addCloudStatus({ - code : -1, - msg : 'Error pCurrentFile in' + - 'unSetCurrentFile' + - 'could not be none' - }); - - if(lRet_b) - DOM.removeClass(pCurrentFile, CURRENT_FILE); - - return lRet_b; - } - - /** - * add class to current element - * @param pElement - * @param pClass - */ - DOM.addClass = function(pElement, pClass){ - var lRet; - - if(pElement){ - var lClassList = pElement.classList; - - if(lClassList){ - if( !lClassList.contains(pClass) ) - lClassList.add(pClass); - lRet = true; - } - } - - return lRet; - }; - - /** - * safe add event listener - * @param pType - * @param pListener - * @param pUseCapture - * @param pElement {document by default} - */ - DOM.addListener = function(pType, pListener, pElement, pUseCapture){ - var lRet = this, - lElement = (pElement || window); - - - lElement.addEventListener( - pType, - pListener, - pUseCapture || false - ); - - Listeners.push({ - element : lElement, - callback: pListener - }); - - return lRet; - }; - - /** - * safe add event listener - * @param pType - * @param pListener - * @param pUseCapture - * @param pElement {document by default} - */ - DOM.addOneTimeListener = function(pType, pListener, pElement, pUseCapture){ - var lRet = this; - - DOM.addListener(pType, - function oneTime(pEvent){ - DOM.removeListener(pType, oneTime, pElement, pUseCapture); - pListener(pEvent); - }, - pUseCapture, pElement); - - return lRet; - }; - - /** - * safe remove event listener - * @param pType - * @param pListener - * @param pUseCapture - * @param pElement {document by default} - */ - DOM.removeListener = function(pType, pListener, pElement, pUseCapture){ - var lRet = this; - - (pElement || window).removeEventListener( - pType, - pListener, - pUseCapture || false - ); - - return lRet; - }; - - - /** - * safe add event keydown listener - * @param pListener - * @param pUseCapture - */ - DOM.addKeyListener = function(pListener, pElement, pUseCapture){ - return DOM.addListener('keydown', pListener, pElement, pUseCapture); - }; - - /** - * safe add event click listener - * @param pListener - * @param pUseCapture - */ - DOM.addClickListener = function(pListener, pElement, pUseCapture){ - return DOM.addListener('click', pListener, pElement, pUseCapture); - }; - - /** - * safe add event click listener - * @param pListener - * @param pUseCapture - */ - DOM.addErrorListener = function(pListener, pElement, pUseCapture){ - return DOM.addListener('error', pListener, pElement, pUseCapture); - }; - - /** - * getListener for element - * - * @param pElement - */ - DOM.getListener = function(pElement){ - var lRet; - - for(var i = 0, n = Listeners.length; i < n; i++){ - if(Listeners[i].element === pElement){ - lRet = Listeners[i].callback; - break; - } - } - - return lRet; - }; - - /** - * load file countent thrue ajax - */ - DOM.ajax = function(pParams){ - var lType = pParams.type || 'GET', - lData = pParams.data, - lSuccess_f = pParams.success; - - if(!XMLHTTP) - XMLHTTP = new XMLHttpRequest(); - - XMLHTTP.open(lType, pParams.url, true); - XMLHTTP.send(lData); - - if( !Util.isFunction(lSuccess_f) ){ - Util.log('error in DOM.ajax onSuccess:', pParams); - Util.log(pParams); - } - - 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') ){ - var lResult = Util.tryCatch(function(){ - lData = Util.parseJSON(lJqXHR.response); - }); - - if( Util.log(lResult) ) - lData = lJqXHR.response; - } - - lSuccess_f(lData, lJqXHR.statusText, lJqXHR); - } - else/* file not found or connection lost */{ - /* if html given or something like it - * getBack just status of result - */ - if(lType && - lType.indexOf('text/plain') !== 0){ - lJqXHR.responseText = lJqXHR.statusText; - } - Util.exec(pParams.error, lJqXHR); - } - } - }; - }; - - /** - * Обьект для работы с кэшем - * в него будут включены функции для - * работы с LocalStorage, webdb, - * indexed db etc. - */ - DOM.Cache = function(){ - /* приватный переключатель возможности работы с кэшем */ - var CacheAllowed; - - /* функция проверяет возможно ли работать с кэшем каким-либо образом */ - this.isAllowed = function(){ - return ( CacheAllowed = Util.isObject( window.localStorage ) ); - }; - - - /** - * allow cache usage - */ - this.setAllowed = function(){ - var lRet = this; - CacheAllowed = true; - - return lRet; - }; - - /** - * dissalow cache usage - */ - this.UnSetAllowed = function(){ - var lRet = this; - CacheAllowed = false; - - return lRet; - }; - - /** remove element */ - this.remove = function(pItem){ - var lRet = this; - - if(CacheAllowed) - localStorage.removeItem(pItem); - - return lRet; - }; - - /** если доступен localStorage и - * в нём есть нужная нам директория - - * записываем данные в него - */ - this.set = function(pName, pData){ - var lRet = this; - - if(CacheAllowed && pName && pData) - localStorage.setItem(pName,pData); - - return lRet; - }, - - /** Если доступен Cache принимаем из него данные*/ - this.get = function(pName){ - var lRet = this; - - if(CacheAllowed) - lRet = localStorage.getItem(pName); - - return lRet; - }, - - /* get all cache from local storage */ - this.getAll = function(){ - var lRet = null; - - if(CacheAllowed) - lRet = localStorage; - - return lRet; - }; - - /** функция чистит весь кэш для всех каталогов*/ - this.clear = function(){ - var lRet = this; - - if(CacheAllowed) - localStorage.clear(); - - return lRet; - }; - }; - - DOM.Cache = new DOM.Cache(); - - /** - * delete currentfile, prompt before it - * - * @pCurrentFile - */ - DOM.promptRemoveCurrent = function(pCurrentFile){ - var lRet, - lCurrent, - lName, - lMsg = 'Are you sure thet you wont delete '; - - /* dom element passed and it is not event */ - if(pCurrentFile && !pCurrentFile.type) - lCurrent = pCurrentFile; - - lName = DOM.getCurrentName(lCurrent); - - lRet = confirm(lMsg + lName + '?'); - - if(lRet) - DOM.removeCurrent(lCurrent); - - return lRet; - }; - - /** - * Function gets id by src - * @param pSrc - * - * Example: http://domain.com/1.js -> 1_js - */ - DOM.getIdBySrc = function(pSrc){ - var lID = pSrc.replace(pSrc.substr(pSrc, - pSrc.lastIndexOf('/')+1), - ''); - - /* убираем точки */ - while(lID.indexOf('.') > 0) - lID = lID.replace('.','_'); - - return lID; - }, - - /** - * create elements and load them to DOM-tree - * one-by-one - * - * @param pParams_a - * @param pFunc - onload function - */ - DOM.anyLoadOnLoad = function(pParams_a, pFunc){ - var lRet = this; - - if( Util.isArray(pParams_a) ) { - var lParam = pParams_a.pop(), - lFunc = function(){ - DOM.anyLoadOnLoad(pParams_a, pFunc); - }; - - if( Util.isString(lParam) ) - lParam = { src : lParam }; - else if( Util.isArray(lParam) ){ - - DOM.anyLoadInParallel(lParam, lFunc); - } - - if(lParam && !lParam.func){ - lParam.func = lFunc; - - DOM.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 - */ - DOM.anyLoadInParallel = function(pParams_a, pFunc){ - var lRet = this, - done = [], - - doneFunc = function (pCallBack){ - Util.exec(pCallBack); - - if( !done.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){ - done.push(i); - - if(Util.isString(lParam) ) - lParam = { src : lParam }; - - var lFunc = lParam.func; - lParam.func = Util.retExec(doneFunc, lFunc); - - DOM.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 - * } - */ - DOM.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] = DOM.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 = DOM.getIdBySrc(lSrc); - - var lElement = DOM.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){ - DOM.removeListener('load', lLoad, false, lElement); - DOM.removeListener('error', lError, false, lElement); - - Util.exec(lFunc, pEvent); - }, - - lError = function(){ - lParent.removeChild(lElement); - - DOM.Images.showError({ - responseText: 'file ' + - lSrc + - ' could not be loaded', - status : 404 - }); - - Util.exec(lOnError); - }; - - DOM.addListener('load', lLoad, lElement); - DOM.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 - */ - DOM.jsload = function(pSrc, pFunc){ - if( Util.isArray(pSrc) ){ - for(var i=0; i < pSrc.length; i++) - pSrc[i].name = 'script'; - - return DOM.anyload(pSrc); - } - - return DOM.anyload({ - name : 'script', - src : pSrc, - func : pFunc - }); - }, - - /** - * returns jsload functions - */ - DOM.retJSLoad = function(pSrc, pFunc){ - var lRet = function(){ - return DOM.jsload(pSrc, pFunc); - }; - - return lRet; - }, - - - /** - * Функция создаёт елемент style и записывает туда стили - * @param pParams_o - структура параметров, заполняеться таким - * образом: {src: ' ',func: '', id: '', element: '', inner: ''} - * все параметры опциональны - */ - DOM.cssSet = function(pParams_o){ - pParams_o.name = 'style'; - pParams_o.parent = pParams_o.parent || document.head; - - return DOM.anyload(pParams_o); - }, - - /** - * Function loads external css files - * @pParams_o - структура параметров, заполняеться таким - * образом: {src: ' ',func: '', id: '', element: '', inner: ''} - * все параметры опциональны - */ - DOM.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 DOM.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 DOM.anyload(pParams_o); - }; - - /** - * load jquery from google cdn or local copy - * @param pCallBack - */ - DOM.jqueryLoad = function(pCallBack){ - /* загружаем jquery: */ - DOM.jsload('//code.jquery.com/jquery-1.9.0.min.js',{ - onload: Util.retExec(pCallBack), - - onerror: function(){ - DOM.jsload('lib/client/jquery.js'); - - /* - * if could not load jquery from google server - * maybe we offline, load font from local - * directory - */ - DOM.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 - */ - DOM.socketLoad = function(pCallBack){ - DOM.jsload('/lib/client/socket.js', Util.retExec(pCallBack) ); - }; - - /* DOM */ - - /** - * Function search element by tag - * @param pTag - className - * @param pElement - element - */ - DOM.getByTag = function(pTag, pElement){ - return (pElement || document).getElementsByTagName(pTag); - }; - - /** - * Function search element by id - * @param Id - className - * @param pElement - element - */ - DOM.getById = function(pId, pElement){ - return (pElement || document).getElementById(pId); - }; - - /** - * Function search element by class name - * @param pClass - className - * @param pElement - element - */ - DOM.getByClass = function(pClass, pElement){ - return (pElement || document).getElementsByClassName(pClass); - }; - - - DOM.Images = { - /** - * Function shows loading spinner - * pPosition = {top: true}; - */ - showLoad : function(pPosition){ - var lRet_b, - lLoadingImage = Images.loading(), - lErrorImage = Images.error(); - - DOM.hide(lErrorImage); - - var lCurrent; - if(pPosition && pPosition.top) - lCurrent = DOM.getRefreshButton().parentElement; - else - lCurrent = DOM.getCurrentFile().firstChild.nextSibling; - - /* show loading icon if it not showed */ - - var lParent = lLoadingImage.parentElement; - if(!lParent || (lParent && lParent !== lCurrent)) - lCurrent.appendChild(lLoadingImage); - - lRet_b = DOM.show(lLoadingImage); /* показываем загрузку*/ - - return lRet_b; - }, - - /** - * hide load image - */ - hideLoad : function(){ - - DOM.hide( Images.loading() ); - }, - - /** - * show error image (usualy after error on ajax request) - */ - showError : function(jqXHR, textStatus, errorThrown){ - var lLoadingImage = Images.loading(), - lErrorImage = Images.error(), - lResponce = jqXHR.responseText, - lStatusText = jqXHR.statusText, - lStatus = jqXHR.status, - lText = (lStatus === 404 ? lResponce : lStatusText); - - /* если файла не существует*/ - if( Util.isContainStr(lText, 'Error: ENOENT, ') ) - lText = lText.replace('Error: ENOENT, n','N'); - - /* если не хватает прав для чтения файла*/ - else if( Util.isContainStr(lText, 'Error: EACCES,') ) - lText = lText.replace('Error: EACCES, p','P'); - - - DOM.show(lErrorImage); - lErrorImage.title = lText; - - var lParent = lLoadingImage.parentElement; - if(lParent) - lParent.appendChild(lErrorImage); - - DOM.hide(lLoadingImage); - - Util.log(lText); - } - }; - - /** - * get current direcotory path - */ - DOM.getCurrentDir = function(){ - var lRet, - lSubstr, - lPanel = DOM.getPanel(), - /* получаем имя каталога в котором находимся */ - lHref = DOM.getByClass('path', lPanel); - - lHref = lHref[0].textContent; - - lHref = CloudFunc.removeLastSlash(lHref); - lSubstr = lHref.substr(lHref , lHref.lastIndexOf('/')); - lRet = Util.removeStr(lHref, lSubstr + '/'); - - return lRet; - }; - - /** - * unified way to get current file - * - * @pCurrentFile - */ - DOM.getCurrentFile = function(){ - var lRet = DOM.getByClass(CURRENT_FILE )[0]; - - return lRet; - }; - - - DOM.getCurrentSize = function(pCurrentFile){ - var lRet, - lCurrent = pCurrentFile || DOM.getCurrentFile(), - lSize = DOM.getByClass('size', lCurrent); - lRet = lSize[0].textContent; - - return lRet; - }; - - /** - * unified way to get current file content - * - * @pCallBack - callback function or data struct {sucess, error} - * @pCurrentFile - */ - DOM.getCurrentFileContent = function(pParams, pCurrentFile){ - var lRet, - lParams = pParams ? pParams : {}, - lPath = DOM.getCurrentPath(pCurrentFile), - lErrorWas = pParams.error, - lError = function(jqXHR){ - Util.exec(lErrorWas); - DOM.Images.showError(jqXHR); - }; - if( Util.isFunction(lParams) ) - lParams.success = Util.retExec(pParams); - - lParams.error = lError; - - if(!lParams.url) - lParams.url = lPath; - - lRet = DOM.ajax(lParams); - - return lRet; - }; - - /** - * unified way to get current file content - * - * @pCallBack - function({data, name}){} - * @pCurrentFile - */ - DOM.getCurrentData = function(pCallBack, pCurrentFile){ - var lParams, - lFunc = function(pData){ - var lName = DOM.getCurrentName(pCurrentFile); - 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 DOM.getCurrentFileContent(lParams, pCurrentFile); - }; - - /** - * unified way to get RefreshButton - */ - DOM.getRefreshButton = function(){ - var lPanel = DOM.getPanel(), - lRefresh = DOM.getByClass(CloudFunc.REFRESHICON, lPanel); - - if (lRefresh.length) - lRefresh = lRefresh[0]; - else { - DOM.addCloudStatus({ - code : -3, - msg : 'Error Refresh icon not found' - }); - lRefresh = false; - } - - return lRefresh; - }; - - - /** - * unified way to set current file - */ - DOM.setCurrentFile = function(pCurrentFile){ - var lRet, - lCurrentFileWas = DOM.getCurrentFile(); - - if(pCurrentFile){ - if (pCurrentFile.className === 'path') - pCurrentFile = pCurrentFile.nextSibling; - - if (pCurrentFile.className === 'fm-header') - pCurrentFile = pCurrentFile.nextSibling; - - if(lCurrentFileWas) - unSetCurrentFile(lCurrentFileWas); - - DOM.addClass(pCurrentFile, CURRENT_FILE); - - /* scrolling to current file */ - DOM.scrollIntoViewIfNeeded(pCurrentFile); - - lRet = true; - } - return lRet; - }; - - /** - * setting history wrapper - */ - DOM.setHistory = function(pData, pTitle, pUrl){ - var lRet = true; - - if(window.history) - history.pushState(pData, pTitle, pUrl); - else - lRet = false; - - return lRet; - }; - - /** - * set onclick handler on buttons f1-f10 - * @param pKey - 'f1'-'f10' - */ - DOM.setButtonKey = function(pKey, pFunc){ - return CloudCommander.KeysPanel[pKey].onclick = pFunc; - }; - - /** - * set title with pName - * create title element - * if it absent - * @param pName - */ - - DOM.setTitle = function(pName){ - if(!Title) - Title = DOM.getByTag('title')[0] || - DOM.anyload({ - name:'title', - parentElement: document.head, - innerHTML: pName - }); - if(Title) - Title.textContent = pName; - - return Title; - }; - - /** - * current file check - * - * @param pCurrentFile - */ - DOM.isCurrentFile = function(pCurrentFile){ - var lCurrentFileClass = pCurrentFile.className, - lIsCurrent = lCurrentFileClass.indexOf(CURRENT_FILE) >= 0; - - return lIsCurrent; - }; - - - /** - * get link from current (or param) file - * - * @param pCurrentFile - current file by default - */ - DOM.getCurrentLink = function(pCurrentFile){ - var lLink = DOM.getByTag( 'a', pCurrentFile || DOM.getCurrentFile() ), - - lRet = lLink.length > 0 ? lLink[0] : -1; - - return lRet; - }; - - /** - * get link from current (or param) file - * - * @param pCurrentFile - current file by default - */ - DOM.getCurrentPath = function(pCurrentFile){ - var lCurrent = pCurrentFile || DOM.getCurrentFile(), - lPath = DOM.getCurrentLink( lCurrent ).href; - /* убираем адрес хоста*/ - lPath = Util.removeStr(lPath, CloudCommander.HOST); - lPath = Util.removeStr(lPath, CloudFunc.NOJS); - - return lPath; - }; - - /** - * get name from current (or param) file - * - * @param pCurrentFile - */ - DOM.getCurrentName = function(pCurrentFile){ - var lCurrent = pCurrentFile || DOM.getCurrentFile(), - lLink = DOM.getCurrentLink( lCurrent ); - - if(lLink) - lLink = lLink.textContent; - - return lLink; - }; - - /** function getting FM - * @param pPanel_o = {active: true} - */ - DOM.getFM = function(){ - return DOM.getPanel().parentElement; - }; - - /** function getting panel active, or passive - * @param pPanel_o = {active: true} - */ - DOM.getPanel = function(pActive){ - var lPanel = DOM.getCurrentFile().parentElement; - - /* if {active : false} getting passive panel */ - if(pActive && !pActive.active){ - var lId = lPanel.id === 'left' ? 'right' : 'left'; - lPanel = DOM.getById(lId); - } - - /* if two panels showed - * then always work with passive - * panel - */ - if(window.innerWidth < CloudCommander.MIN_ONE_PANEL_WIDTH) - lPanel = DOM.getById('left'); - - - if(!lPanel) - Util.log('Error can not find Active Panel'); - - return lPanel; - }; - - /** prevent default event */ - DOM.preventDefault = function(pEvent){ - var lRet, - lPreventDefault = pEvent && pEvent.preventDefault, - lFunc = Util.bind(lPreventDefault, pEvent); - - lRet = Util.exec(lFunc); - - return lRet; - }; - - DOM.show = function(pElement){ - DOM.removeClass(pElement, 'hidden'); - }; - - /** - * shows panel right or left (or active) - */ - DOM.showPanel = function(pActive){ - var lRet = true, - lPanel = DOM.getPanel(pActive); - - if(lPanel) - DOM.show(lPanel); - else - lRet = false; - - return lRet; - }; - - /** - * hides panel right or left (or active) - */ - DOM.hidePanel = function(pActive){ - var lRet = false, - lPanel = DOM.getPanel(pActive); - - if(lPanel) - lRet = DOM.hide(lPanel); - - return lRet; - }; - - /** - * add class=hidden to element - * - * @param pElement - */ - DOM.hide = function(pElement){ - return DOM.addClass(pElement, 'hidden'); - }; - - /** - * open window with URL - * @param pUrl - */ - DOM.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 - */ - DOM.remove = function(pChild, pElement){ - return (pElement || document.body).removeChild(pChild); - }; - - /** - * remove class pClass from element pElement - * @param pElement - * @param pClass - */ - DOM.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 - */ - DOM.removeCurrent = function(pCurrent){ - var lCurrent = pCurrent || DOM.getCurrentFile(), - lParent = lCurrent.parentElement, - lName = DOM.getCurrentName(lCurrent); - - if(lCurrent && lParent){ - if(lName !== '..'){ - var lNext = lCurrent.nextSibling; - var lPrevious = lCurrent.previousSibling; - if(lNext) - DOM.setCurrentFile(lNext); - else if(lPrevious) - DOM.setCurrentFile(lPrevious); - - lParent.removeChild(lCurrent); - } - else - DOM.addCloudStatus({ - code : -1, - msg : 'Could not remove parrent dir' - }); - } - else - DOM.addCloudStatus({ - code : -1, - msg : 'Current file (or parent of current) could not be empty' - }); - - return lCurrent; - }; - - /** - * unified way to scrollIntoViewIfNeeded - * (native suporte by webkit only) - * @param pElement - */ - DOM.scrollIntoViewIfNeeded = function(pElement){ - var lRet = true; - - if(pElement && pElement.scrollIntoViewIfNeeded) - pElement.scrollIntoViewIfNeeded(); - else - lRet = false; - - return lRet; - }; - - /** - * function gets time - */ - DOM.getTime = function(){ - var date = new Date(), - hours = date.getHours(), - minutes = date.getMinutes(), - seconds = date.getSeconds(); - - minutes = minutes < 10 ? '0' + minutes : minutes; - seconds = seconds < 10 ? '0' + seconds : seconds; - - return hours + ":" + minutes + ":" + seconds; - }; - - /** - * array of all statuses of opertattions - */ - DOM.CloudStatus = []; - - /** - * adds status of operation - * @param pStatus - */ - DOM.addCloudStatus = function(pStatus){ - DOM.CloudStatus[DOM.CloudStatus.length] = pStatus; - }; +var CloudCommander, Util, + DOM = {}, + CloudFunc; + +(function(Util, DOM){ + 'use strict'; + + /* PRIVATE */ + + /* private members */ + var /* название css-класа текущего файла*/ + CURRENT_FILE = 'current-file', + Listeners = [], + XMLHTTP, + Title, + + /* Обьект, который содержит + * функции для отображения + * картинок + */ + Images = function (){ + var getImage = function(pName){ + var lId = pName + '-image', + lE = DOM.getById(lId); + if (!lE) + lE = DOM.anyload({ + name : 'span', + className : 'icon ' + pName, + id : lId, + not_append : true + }); + + return lE; + }; + /* Функция создаёт картинку загрузки*/ + this.loading = function(){ + return getImage('loading'); + }; + + /* Функция создаёт картинку ошибки загрузки*/ + this.error = function(){ + return getImage('error'); + }; + }; + + Images = new Images(); + + function removeListenerFromList(pElement){ + var lRet; + + for(var i = 0, n = Listeners.length; i < n; i++){ + if(Listeners[i].element === pElement){ + Listeners[i] = null; + break; + } + } + + return lRet; + } + + /** + * private function thet unset currentfile + */ + function unSetCurrentFile(pCurrentFile){ + var lRet_b = DOM.isCurrentFile(pCurrentFile); + + if(!pCurrentFile) + DOM.addCloudStatus({ + code : -1, + msg : 'Error pCurrentFile in' + + 'unSetCurrentFile' + + 'could not be none' + }); + + if(lRet_b) + DOM.removeClass(pCurrentFile, CURRENT_FILE); + + return lRet_b; + } + + /** + * add class to current element + * @param pElement + * @param pClass + */ + DOM.addClass = function(pElement, pClass){ + var lRet; + + if(pElement){ + var lClassList = pElement.classList; + + if(lClassList){ + if( !lClassList.contains(pClass) ) + lClassList.add(pClass); + lRet = true; + } + } + + return lRet; + }; + + /** + * safe add event listener + * @param pType + * @param pListener + * @param pUseCapture + * @param pElement {document by default} + */ + DOM.addListener = function(pType, pListener, pElement, pUseCapture){ + var lRet = this, + lElement = (pElement || window); + + + lElement.addEventListener( + pType, + pListener, + pUseCapture || false + ); + + Listeners.push({ + element : lElement, + callback: pListener + }); + + return lRet; + }; + + /** + * safe add event listener + * @param pType + * @param pListener + * @param pUseCapture + * @param pElement {document by default} + */ + DOM.addOneTimeListener = function(pType, pListener, pElement, pUseCapture){ + var lRet = this; + + DOM.addListener(pType, + function oneTime(pEvent){ + DOM.removeListener(pType, oneTime, pElement, pUseCapture); + pListener(pEvent); + }, + pUseCapture, pElement); + + return lRet; + }; + + /** + * safe remove event listener + * @param pType + * @param pListener + * @param pUseCapture + * @param pElement {document by default} + */ + DOM.removeListener = function(pType, pListener, pElement, pUseCapture){ + var lRet = this; + + (pElement || window).removeEventListener( + pType, + pListener, + pUseCapture || false + ); + + return lRet; + }; + + + /** + * safe add event keydown listener + * @param pListener + * @param pUseCapture + */ + DOM.addKeyListener = function(pListener, pElement, pUseCapture){ + return DOM.addListener('keydown', pListener, pElement, pUseCapture); + }; + + /** + * safe add event click listener + * @param pListener + * @param pUseCapture + */ + DOM.addClickListener = function(pListener, pElement, pUseCapture){ + return DOM.addListener('click', pListener, pElement, pUseCapture); + }; + + /** + * safe add event click listener + * @param pListener + * @param pUseCapture + */ + DOM.addErrorListener = function(pListener, pElement, pUseCapture){ + return DOM.addListener('error', pListener, pElement, pUseCapture); + }; + + /** + * getListener for element + * + * @param pElement + */ + DOM.getListener = function(pElement){ + var lRet; + + for(var i = 0, n = Listeners.length; i < n; i++){ + if(Listeners[i].element === pElement){ + lRet = Listeners[i].callback; + break; + } + } + + return lRet; + }; + + /** + * load file countent thrue ajax + */ + DOM.ajax = function(pParams){ + var lType = pParams.type || 'GET', + lData = pParams.data, + lSuccess_f = pParams.success; + + if(!XMLHTTP) + XMLHTTP = new XMLHttpRequest(); + + XMLHTTP.open(lType, pParams.url, true); + XMLHTTP.send(lData); + + if( !Util.isFunction(lSuccess_f) ){ + Util.log('error in DOM.ajax onSuccess:', pParams); + Util.log(pParams); + } + + 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') ){ + var lResult = Util.tryCatch(function(){ + lData = Util.parseJSON(lJqXHR.response); + }); + + if( Util.log(lResult) ) + lData = lJqXHR.response; + } + + lSuccess_f(lData, lJqXHR.statusText, lJqXHR); + } + else/* file not found or connection lost */{ + /* if html given or something like it + * getBack just status of result + */ + if(lType && + lType.indexOf('text/plain') !== 0){ + lJqXHR.responseText = lJqXHR.statusText; + } + Util.exec(pParams.error, lJqXHR); + } + } + }; + }; + + /** + * Обьект для работы с кэшем + * в него будут включены функции для + * работы с LocalStorage, webdb, + * indexed db etc. + */ + DOM.Cache = function(){ + /* приватный переключатель возможности работы с кэшем */ + var CacheAllowed; + + /* функция проверяет возможно ли работать с кэшем каким-либо образом */ + this.isAllowed = function(){ + return ( CacheAllowed = Util.isObject( window.localStorage ) ); + }; + + + /** + * allow cache usage + */ + this.setAllowed = function(){ + var lRet = this; + CacheAllowed = true; + + return lRet; + }; + + /** + * dissalow cache usage + */ + this.UnSetAllowed = function(){ + var lRet = this; + CacheAllowed = false; + + return lRet; + }; + + /** remove element */ + this.remove = function(pItem){ + var lRet = this; + + if(CacheAllowed) + localStorage.removeItem(pItem); + + return lRet; + }; + + /** если доступен localStorage и + * в нём есть нужная нам директория - + * записываем данные в него + */ + this.set = function(pName, pData){ + var lRet = this; + + if(CacheAllowed && pName && pData) + localStorage.setItem(pName,pData); + + return lRet; + }, + + /** Если доступен Cache принимаем из него данные*/ + this.get = function(pName){ + var lRet = this; + + if(CacheAllowed) + lRet = localStorage.getItem(pName); + + return lRet; + }, + + /* get all cache from local storage */ + this.getAll = function(){ + var lRet = null; + + if(CacheAllowed) + lRet = localStorage; + + return lRet; + }; + + /** функция чистит весь кэш для всех каталогов*/ + this.clear = function(){ + var lRet = this; + + if(CacheAllowed) + localStorage.clear(); + + return lRet; + }; + }; + + DOM.Cache = new DOM.Cache(); + + /** + * delete currentfile, prompt before it + * + * @pCurrentFile + */ + DOM.promptRemoveCurrent = function(pCurrentFile){ + var lRet, + lCurrent, + lName, + lMsg = 'Are you sure thet you wont delete '; + + /* dom element passed and it is not event */ + if(pCurrentFile && !pCurrentFile.type) + lCurrent = pCurrentFile; + + lName = DOM.getCurrentName(lCurrent); + + lRet = confirm(lMsg + lName + '?'); + + if(lRet) + DOM.removeCurrent(lCurrent); + + return lRet; + }; + + /** + * Function gets id by src + * @param pSrc + * + * Example: http://domain.com/1.js -> 1_js + */ + DOM.getIdBySrc = function(pSrc){ + var lID = pSrc.replace(pSrc.substr(pSrc, + pSrc.lastIndexOf('/')+1), + ''); + + /* убираем точки */ + while(lID.indexOf('.') > 0) + lID = lID.replace('.','_'); + + return lID; + }, + + /** + * create elements and load them to DOM-tree + * one-by-one + * + * @param pParams_a + * @param pFunc - onload function + */ + DOM.anyLoadOnLoad = function(pParams_a, pFunc){ + var lRet = this; + + if( Util.isArray(pParams_a) ) { + var lParam = pParams_a.pop(), + lFunc = function(){ + DOM.anyLoadOnLoad(pParams_a, pFunc); + }; + + if( Util.isString(lParam) ) + lParam = { src : lParam }; + else if( Util.isArray(lParam) ){ + + DOM.anyLoadInParallel(lParam, lFunc); + } + + if(lParam && !lParam.func){ + lParam.func = lFunc; + + DOM.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 + */ + DOM.anyLoadInParallel = function(pParams_a, pFunc){ + var lRet = this, + done = [], + + doneFunc = function (pCallBack){ + Util.exec(pCallBack); + + if( !done.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){ + done.push(i); + + if(Util.isString(lParam) ) + lParam = { src : lParam }; + + var lFunc = lParam.func; + lParam.func = Util.retExec(doneFunc, lFunc); + + DOM.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 + * } + */ + DOM.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] = DOM.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 = DOM.getIdBySrc(lSrc); + + var lElement = DOM.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){ + DOM.removeListener('load', lLoad, false, lElement); + DOM.removeListener('error', lError, false, lElement); + + Util.exec(lFunc, pEvent); + }, + + lError = function(){ + lParent.removeChild(lElement); + + DOM.Images.showError({ + responseText: 'file ' + + lSrc + + ' could not be loaded', + status : 404 + }); + + Util.exec(lOnError); + }; + + DOM.addListener('load', lLoad, lElement); + DOM.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 + */ + DOM.jsload = function(pSrc, pFunc){ + if( Util.isArray(pSrc) ){ + for(var i=0; i < pSrc.length; i++) + pSrc[i].name = 'script'; + + return DOM.anyload(pSrc); + } + + return DOM.anyload({ + name : 'script', + src : pSrc, + func : pFunc + }); + }, + + /** + * returns jsload functions + */ + DOM.retJSLoad = function(pSrc, pFunc){ + var lRet = function(){ + return DOM.jsload(pSrc, pFunc); + }; + + return lRet; + }, + + + /** + * Функция создаёт елемент style и записывает туда стили + * @param pParams_o - структура параметров, заполняеться таким + * образом: {src: ' ',func: '', id: '', element: '', inner: ''} + * все параметры опциональны + */ + DOM.cssSet = function(pParams_o){ + pParams_o.name = 'style'; + pParams_o.parent = pParams_o.parent || document.head; + + return DOM.anyload(pParams_o); + }, + + /** + * Function loads external css files + * @pParams_o - структура параметров, заполняеться таким + * образом: {src: ' ',func: '', id: '', element: '', inner: ''} + * все параметры опциональны + */ + DOM.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 DOM.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 DOM.anyload(pParams_o); + }; + + /** + * load jquery from google cdn or local copy + * @param pCallBack + */ + DOM.jqueryLoad = function(pCallBack){ + /* загружаем jquery: */ + DOM.jsload('//code.jquery.com/jquery-1.9.0.min.js',{ + onload: Util.retExec(pCallBack), + + onerror: function(){ + DOM.jsload('lib/client/jquery.js'); + + /* + * if could not load jquery from google server + * maybe we offline, load font from local + * directory + */ + DOM.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 + */ + DOM.socketLoad = function(pCallBack){ + DOM.jsload('/lib/client/socket.js', Util.retExec(pCallBack) ); + }; + + /* DOM */ + + /** + * Function search element by tag + * @param pTag - className + * @param pElement - element + */ + DOM.getByTag = function(pTag, pElement){ + return (pElement || document).getElementsByTagName(pTag); + }; + + /** + * Function search element by id + * @param Id - className + * @param pElement - element + */ + DOM.getById = function(pId, pElement){ + return (pElement || document).getElementById(pId); + }; + + /** + * Function search element by class name + * @param pClass - className + * @param pElement - element + */ + DOM.getByClass = function(pClass, pElement){ + return (pElement || document).getElementsByClassName(pClass); + }; + + + DOM.Images = { + /** + * Function shows loading spinner + * pPosition = {top: true}; + */ + showLoad : function(pPosition){ + var lRet_b, + lLoadingImage = Images.loading(), + lErrorImage = Images.error(); + + DOM.hide(lErrorImage); + + var lCurrent; + if(pPosition && pPosition.top) + lCurrent = DOM.getRefreshButton().parentElement; + else + lCurrent = DOM.getCurrentFile().firstChild.nextSibling; + + /* show loading icon if it not showed */ + + var lParent = lLoadingImage.parentElement; + if(!lParent || (lParent && lParent !== lCurrent)) + lCurrent.appendChild(lLoadingImage); + + lRet_b = DOM.show(lLoadingImage); /* показываем загрузку*/ + + return lRet_b; + }, + + /** + * hide load image + */ + hideLoad : function(){ + + DOM.hide( Images.loading() ); + }, + + /** + * show error image (usualy after error on ajax request) + */ + showError : function(jqXHR, textStatus, errorThrown){ + var lLoadingImage = Images.loading(), + lErrorImage = Images.error(), + lResponce = jqXHR.responseText, + lStatusText = jqXHR.statusText, + lStatus = jqXHR.status, + lText = (lStatus === 404 ? lResponce : lStatusText); + + /* если файла не существует*/ + if( Util.isContainStr(lText, 'Error: ENOENT, ') ) + lText = lText.replace('Error: ENOENT, n','N'); + + /* если не хватает прав для чтения файла*/ + else if( Util.isContainStr(lText, 'Error: EACCES,') ) + lText = lText.replace('Error: EACCES, p','P'); + + + DOM.show(lErrorImage); + lErrorImage.title = lText; + + var lParent = lLoadingImage.parentElement; + if(lParent) + lParent.appendChild(lErrorImage); + + DOM.hide(lLoadingImage); + + Util.log(lText); + } + }; + + /** + * get current direcotory path + */ + DOM.getCurrentDir = function(){ + var lRet, + lSubstr, + lPanel = DOM.getPanel(), + /* получаем имя каталога в котором находимся */ + lHref = DOM.getByClass('path', lPanel); + + lHref = lHref[0].textContent; + + lHref = CloudFunc.removeLastSlash(lHref); + lSubstr = lHref.substr(lHref , lHref.lastIndexOf('/')); + lRet = Util.removeStr(lHref, lSubstr + '/'); + + return lRet; + }; + + /** + * unified way to get current file + * + * @pCurrentFile + */ + DOM.getCurrentFile = function(){ + var lRet = DOM.getByClass(CURRENT_FILE )[0]; + + return lRet; + }; + + + DOM.getCurrentSize = function(pCurrentFile){ + var lRet, + lCurrent = pCurrentFile || DOM.getCurrentFile(), + lSize = DOM.getByClass('size', lCurrent); + lRet = lSize[0].textContent; + + return lRet; + }; + + /** + * unified way to get current file content + * + * @pCallBack - callback function or data struct {sucess, error} + * @pCurrentFile + */ + DOM.getCurrentFileContent = function(pParams, pCurrentFile){ + var lRet, + lParams = pParams ? pParams : {}, + lPath = DOM.getCurrentPath(pCurrentFile), + lErrorWas = pParams.error, + lError = function(jqXHR){ + Util.exec(lErrorWas); + DOM.Images.showError(jqXHR); + }; + if( Util.isFunction(lParams) ) + lParams.success = Util.retExec(pParams); + + lParams.error = lError; + + if(!lParams.url) + lParams.url = lPath; + + lRet = DOM.ajax(lParams); + + return lRet; + }; + + /** + * unified way to get current file content + * + * @pCallBack - function({data, name}){} + * @pCurrentFile + */ + DOM.getCurrentData = function(pCallBack, pCurrentFile){ + var lParams, + lFunc = function(pData){ + var lName = DOM.getCurrentName(pCurrentFile); + 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 DOM.getCurrentFileContent(lParams, pCurrentFile); + }; + + /** + * unified way to get RefreshButton + */ + DOM.getRefreshButton = function(){ + var lPanel = DOM.getPanel(), + lRefresh = DOM.getByClass(CloudFunc.REFRESHICON, lPanel); + + if (lRefresh.length) + lRefresh = lRefresh[0]; + else { + DOM.addCloudStatus({ + code : -3, + msg : 'Error Refresh icon not found' + }); + lRefresh = false; + } + + return lRefresh; + }; + + + /** + * unified way to set current file + */ + DOM.setCurrentFile = function(pCurrentFile){ + var lRet, + lCurrentFileWas = DOM.getCurrentFile(); + + if(pCurrentFile){ + if (pCurrentFile.className === 'path') + pCurrentFile = pCurrentFile.nextSibling; + + if (pCurrentFile.className === 'fm-header') + pCurrentFile = pCurrentFile.nextSibling; + + if(lCurrentFileWas) + unSetCurrentFile(lCurrentFileWas); + + DOM.addClass(pCurrentFile, CURRENT_FILE); + + /* scrolling to current file */ + DOM.scrollIntoViewIfNeeded(pCurrentFile); + + lRet = true; + } + return lRet; + }; + + /** + * setting history wrapper + */ + DOM.setHistory = function(pData, pTitle, pUrl){ + var lRet = true; + + if(window.history) + history.pushState(pData, pTitle, pUrl); + else + lRet = false; + + return lRet; + }; + + /** + * set onclick handler on buttons f1-f10 + * @param pKey - 'f1'-'f10' + */ + DOM.setButtonKey = function(pKey, pFunc){ + return CloudCommander.KeysPanel[pKey].onclick = pFunc; + }; + + /** + * set title with pName + * create title element + * if it absent + * @param pName + */ + + DOM.setTitle = function(pName){ + if(!Title) + Title = DOM.getByTag('title')[0] || + DOM.anyload({ + name:'title', + parentElement: document.head, + innerHTML: pName + }); + if(Title) + Title.textContent = pName; + + return Title; + }; + + /** + * current file check + * + * @param pCurrentFile + */ + DOM.isCurrentFile = function(pCurrentFile){ + var lCurrentFileClass = pCurrentFile.className, + lIsCurrent = lCurrentFileClass.indexOf(CURRENT_FILE) >= 0; + + return lIsCurrent; + }; + + + /** + * get link from current (or param) file + * + * @param pCurrentFile - current file by default + */ + DOM.getCurrentLink = function(pCurrentFile){ + var lLink = DOM.getByTag( 'a', pCurrentFile || DOM.getCurrentFile() ), + + lRet = lLink.length > 0 ? lLink[0] : -1; + + return lRet; + }; + + /** + * get link from current (or param) file + * + * @param pCurrentFile - current file by default + */ + DOM.getCurrentPath = function(pCurrentFile){ + var lCurrent = pCurrentFile || DOM.getCurrentFile(), + lPath = DOM.getCurrentLink( lCurrent ).href; + /* убираем адрес хоста*/ + lPath = Util.removeStr(lPath, CloudCommander.HOST); + lPath = Util.removeStr(lPath, CloudFunc.NOJS); + + return lPath; + }; + + /** + * get name from current (or param) file + * + * @param pCurrentFile + */ + DOM.getCurrentName = function(pCurrentFile){ + var lCurrent = pCurrentFile || DOM.getCurrentFile(), + lLink = DOM.getCurrentLink( lCurrent ); + + if(lLink) + lLink = lLink.textContent; + + return lLink; + }; + + /** function getting FM + * @param pPanel_o = {active: true} + */ + DOM.getFM = function(){ + return DOM.getPanel().parentElement; + }; + + /** function getting panel active, or passive + * @param pPanel_o = {active: true} + */ + DOM.getPanel = function(pActive){ + var lPanel = DOM.getCurrentFile().parentElement; + + /* if {active : false} getting passive panel */ + if(pActive && !pActive.active){ + var lId = lPanel.id === 'left' ? 'right' : 'left'; + lPanel = DOM.getById(lId); + } + + /* if two panels showed + * then always work with passive + * panel + */ + if(window.innerWidth < CloudCommander.MIN_ONE_PANEL_WIDTH) + lPanel = DOM.getById('left'); + + + if(!lPanel) + Util.log('Error can not find Active Panel'); + + return lPanel; + }; + + /** prevent default event */ + DOM.preventDefault = function(pEvent){ + var lRet, + lPreventDefault = pEvent && pEvent.preventDefault, + lFunc = Util.bind(lPreventDefault, pEvent); + + lRet = Util.exec(lFunc); + + return lRet; + }; + + DOM.show = function(pElement){ + DOM.removeClass(pElement, 'hidden'); + }; + + /** + * shows panel right or left (or active) + */ + DOM.showPanel = function(pActive){ + var lRet = true, + lPanel = DOM.getPanel(pActive); + + if(lPanel) + DOM.show(lPanel); + else + lRet = false; + + return lRet; + }; + + /** + * hides panel right or left (or active) + */ + DOM.hidePanel = function(pActive){ + var lRet = false, + lPanel = DOM.getPanel(pActive); + + if(lPanel) + lRet = DOM.hide(lPanel); + + return lRet; + }; + + /** + * add class=hidden to element + * + * @param pElement + */ + DOM.hide = function(pElement){ + return DOM.addClass(pElement, 'hidden'); + }; + + /** + * open window with URL + * @param pUrl + */ + DOM.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 + */ + DOM.remove = function(pChild, pElement){ + return (pElement || document.body).removeChild(pChild); + }; + + /** + * remove class pClass from element pElement + * @param pElement + * @param pClass + */ + DOM.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 + */ + DOM.removeCurrent = function(pCurrent){ + var lCurrent = pCurrent || DOM.getCurrentFile(), + lParent = lCurrent.parentElement, + lName = DOM.getCurrentName(lCurrent); + + if(lCurrent && lParent){ + if(lName !== '..'){ + var lNext = lCurrent.nextSibling; + var lPrevious = lCurrent.previousSibling; + if(lNext) + DOM.setCurrentFile(lNext); + else if(lPrevious) + DOM.setCurrentFile(lPrevious); + + lParent.removeChild(lCurrent); + } + else + DOM.addCloudStatus({ + code : -1, + msg : 'Could not remove parrent dir' + }); + } + else + DOM.addCloudStatus({ + code : -1, + msg : 'Current file (or parent of current) could not be empty' + }); + + return lCurrent; + }; + + /** + * unified way to scrollIntoViewIfNeeded + * (native suporte by webkit only) + * @param pElement + */ + DOM.scrollIntoViewIfNeeded = function(pElement){ + var lRet = true; + + if(pElement && pElement.scrollIntoViewIfNeeded) + pElement.scrollIntoViewIfNeeded(); + else + lRet = false; + + return lRet; + }; + + /* scroll on one page*/ + DOM.scrollByPages = function(pElement, pPages){ + var lRet = true; + + if(pElement && pElement.scrollByPages && pPages) + pElement.scrollByPages(pPages); + else + lRet = false; + + return lRet; + }; + + /** + * function gets time + */ + DOM.getTime = function(){ + var date = new Date(), + hours = date.getHours(), + minutes = date.getMinutes(), + seconds = date.getSeconds(); + + minutes = minutes < 10 ? '0' + minutes : minutes; + seconds = seconds < 10 ? '0' + seconds : seconds; + + return hours + ":" + minutes + ":" + seconds; + }; + + /** + * array of all statuses of opertattions + */ + DOM.CloudStatus = []; + + /** + * adds status of operation + * @param pStatus + */ + DOM.addCloudStatus = function(pStatus){ + DOM.CloudStatus[DOM.CloudStatus.length] = pStatus; + }; })(Util, DOM); \ No newline at end of file diff --git a/lib/client/ie.js b/lib/client/ie.js index 25df0b02..b0c63dfc 100644 --- a/lib/client/ie.js +++ b/lib/client/ie.js @@ -1,272 +1,273 @@ -/* script, fixes ie */ -//var Util, DOM, jQuery; - -(function(Util, DOM, $){ - 'use strict'; - - if(!window.XMLHttpRequest || !document.head) - DOM.ajax = $.ajax; - - /* setting head ie6 - ie8 */ - if(!document.head){ - document.head = $('head')[0]; - - /* - {name: '', src: ' ',func: '', style: '', id: '', parent: '', - async: false, inner: 'id{color:red, }, class:'', not_append: false} - */ - DOM.cssSet = function(pParams_o){ - var lElement = ''; + + return $(lElement) + .appendTo(pParams_o.parent || document.head); + }; + } + + /* setting function context (this) */ + Util.bind = function(pFunction, pContext){ + var lRet; + + lRet = $.proxy(pFunction, pContext); + + return lRet; + }; + + /* + * typeof callback === "function" should not be used, + * as older browsers may report objects to be a function, + * which they are not + */ + Util.isFunction = $.isFunction; + + if (!document.addEventListener) + /** + * safe add event listener on ie + * @param pType + * @param pListener + */ + DOM.addListener = function(pType, pListener, pCapture, pElement){ + var lRet; + + if(!pElement) + pElement = window; + + lRet = $(pElement).bind(pType, null, pListener); + + return lRet; + }; + + if(!document.removeEventListener){ + DOM.removeListener = function(pType, pListener, pCapture, pElement){ + var lRet; + + if(!pElement) + pElement = window; + + $(pElement).unbind(pType, pListener); + + return lRet; + }; + } + + if(!document.getElementsByClassName){ + DOM.getByClass = function(pClass, pElement){ + var lClass = '.' + pClass, + lResult; + + if(pElement) + lResult = $(pElement).find(lClass); + else lResult = $.find(lClass); + + return lResult; + }; + } + + DOM.scrollByPages = Util.retFalse; + /* function polyfill webkit standart function */ + DOM.scrollIntoViewIfNeeded = function(pElement, centerIfNeeded){ + if(!window.getComputedStyle) + return; + /* + https://gist.github.com/2581101 + */ + centerIfNeeded = arguments.length === 0 ? true : !!centerIfNeeded; + + var parent = pElement.parentNode, + parentComputedStyle = window.getComputedStyle(parent, null), + parentBorderTopWidth = + parseInt(parentComputedStyle.getPropertyValue('border-top-width'), 10), + + parentBorderLeftWidth = + parseInt(parentComputedStyle.getPropertyValue('border-left-width'), 10), + + overTop = pElement.offsetTop - parent.offsetTop < parent.scrollTop, + overBottom = + (pElement.offsetTop - + parent.offsetTop + + pElement.clientHeight - + parentBorderTopWidth) > + (parent.scrollTop + parent.clientHeight), + + overLeft = pElement.offsetLeft - + parent.offsetLeft < parent.scrollLeft, + + overRight = + (pElement.offsetLeft - + parent.offsetLeft + + pElement.clientWidth - + parentBorderLeftWidth) > + (parent.scrollLeft + parent.clientWidth), + + alignWithTop = overTop && !overBottom; + + if ((overTop || overBottom) && centerIfNeeded) + parent.scrollTop = + pElement.offsetTop - + parent.offsetTop - + parent.clientHeight / 2 - + parentBorderTopWidth + + pElement.clientHeight / 2; + + if ((overLeft || overRight) && centerIfNeeded) + parent.scrollLeft = + pElement.offsetLeft - + parent.offsetLeft - + parent.clientWidth / 2 - + parentBorderLeftWidth + + pElement.clientWidth / 2; + + if ( (overTop || overBottom || overLeft || overRight) && + !centerIfNeeded) + pElement.scrollIntoView(alignWithTop); + }; + + if(!document.body.classList){ + DOM.addClass = function(pElement, pClass){ + var lSpaceChar = '', + lClassName = pElement.className, + lRet_b = true; + + if(lClassName) lSpaceChar = ' '; + + if( lClassName.indexOf(pClass) < 0 ) + pElement.className += lSpaceChar + pClass; + else + lRet_b = false; + }; + + DOM.removeClass = function(pElement, pClass){ + var lClassName = pElement.className; + + if(lClassName.length > pClass.length) + pElement.className = lClassName.replace(pClass, ''); + }; + } + + if(!window.JSON){ + Util.parseJSON = $.parseJSON; + + /* https://gist.github.com/754454 */ + Util.stringifyJSON = function(pObj){ + var lRet; + + if (!Util.isObject(pObj) || pObj === null) { + // simple data type + if (Util.isString(pObj)) pObj = '"' + pObj + '"'; + lRet = String(pObj); + } else { + // recurse array or object + var n, v, json = [], isArray = Util.isArray(pObj); + + for (n in pObj) { + v = pObj[n]; + + if (pObj.hasOwnProperty(n)) { + if (Util.isString(v)) + v = '"' + v + '"'; + else if (v && Util.isObject(v)) + v = DOM.stringifyJSON(v); + + json.push((isArray ? "" : '"' + n + '":') + String(v)); + } + } + lRet = (isArray ? "[" : "{") + String(json) + (isArray ? "]" : "}"); + } + + return lRet; + }; + } + + if(!window.localStorage){ + var Cache = function(){ + /* приватный переключатель возможности работы с кэшем */ + var CacheAllowed, + Data = {}; + + /* функция проверяет возможно ли работать с кэшем каким-либо образом */ + this.isAllowed = function(){ + return CacheAllowed; + }; + + this.setAllowed = function(){ + CacheAllowed = true; + }; + + this.UnSetAllowed = function(){ + CacheAllowed = false; + }; + + /** remove element */ + this.remove = function(pItem){ + var lRet = this; + if(CacheAllowed) + delete Data[pItem]; + + return lRet; + }; + + /** если доступен localStorage и + * в нём есть нужная нам директория - + * записываем данные в него + */ + this.set = function(pName, pData){ + var lRet = this; + + if(CacheAllowed && pName && pData) + Data[pName] = pData; + + return lRet; + }, + + /** Если доступен Cache принимаем из него данные*/ + this.get = function(pName){ + var lRet = false; + + if(CacheAllowed) + lRet = Data[pName]; + + return lRet; + }, + + /** функция чистит весь кэш для всех каталогов*/ + this.clear = function(){ + var lRet = this; + + if(CacheAllowed) + Data = {}; + + return lRet; + }; + }; + + DOM.Cache = new Cache(); + } + + })(Util, DOM, jQuery); \ No newline at end of file diff --git a/lib/client/keyBinding.js b/lib/client/keyBinding.js index 32f86fed..df348264 100644 --- a/lib/client/keyBinding.js +++ b/lib/client/keyBinding.js @@ -1,308 +1,308 @@ -var CloudCommander, Util, DOM; -(function(CloudCmd, Util, DOM){ - "use strict"; - - DOM.Images.hideLoad(); - - /* private property set or set key binding */ - var keyBinded; - - /* Key constants*/ - CloudCmd.KEY = { - TAB : 9, - ENTER : 13, - ESC : 27, - - PAGE_UP : 33, - PAGE_DOWN : 34, - END : 35, - HOME : 36, - UP : 38, - DOWN : 40, - - Delete : 46, - - D : 68, - - G : 71, - - O : 79, - Q : 81, - R : 82, - S : 83, - T : 84, - - F2 : 113, - F3 : 114, - F4 : 115, - F10 : 121, - - TRA : 192 /* Typewritten Reverse Apostrophe (`) */ - }; - - var KEY = CloudCmd.KEY; - - CloudCmd.KeyBinding = {}; - - var KeyBinding = CloudCmd.KeyBinding; - - KeyBinding.get = function(){return keyBinded;}; - - KeyBinding.set = function(){keyBinded = true;}; - - KeyBinding.unSet = function(){keyBinded = false;}; - - KeyBinding.init = function(){ - /* saving state of tabs varibles */ - var lTabPanel = { - left : 0, - right : 0 - - }; - - var key_event = function(pEvent){ - /* получаем выдленный файл*/ - var lCurrentFile = DOM.getCurrentFile(), i; - /* если клавиши можно обрабатывать*/ - if(keyBinded && pEvent){ - var lKeyCode = pEvent.keyCode; - - /* open configuration window */ - if(lKeyCode === KEY.O && pEvent.altKey){ - console.log('openning config window...'); - - DOM.Images.showLoad({top: true}); - - Util.exec(CloudCmd.Config); - } - - else if(lKeyCode === KEY.G && pEvent.altKey) - Util.exec(CloudCmd.GitHub); - - else if(lKeyCode === KEY.D && pEvent.altKey){ - Util.exec(CloudCmd.DropBox); - DOM.preventDefault(pEvent); - } - - /* если нажали таб: - * переносим курсор на - * правую панель, если - * мы были на левой и - * наоборот - */ - else if(lKeyCode === KEY.TAB){ - console.log('Tab pressed'); - - Util.tryCatchLog(function(){ - /* changing parent panel of curent-file */ - var lPanel = DOM.getPanel(), - lId = lPanel.id; - - lTabPanel[lId] = lCurrentFile; - - lPanel = DOM.getPanel({active:false}); - lId = lPanel.id; - - if(lTabPanel[lId]) - DOM.setCurrentFile(lTabPanel[lId]); - else{ - var lFirstFileOnList = DOM.getByTag('li', lPanel)[2]; - - DOM.setCurrentFile(lFirstFileOnList); - } - }); - - DOM.preventDefault(pEvent);//запрет на дальнейшее действие - } - else if(lKeyCode === KEY.Delete) - DOM.promptRemoveCurrent(lCurrentFile); - - /* if f3 or shift+f3 or alt+f3 pressed */ - else if(lKeyCode === KEY.F3){ - var lEditor = CloudCmd[pEvent.shiftKey ? - 'Viewer' : 'Editor']; - - Util.exec(lEditor, true); - - DOM.preventDefault(pEvent); - } - - /* if f4 pressed */ - else if(lKeyCode === KEY.F4) { - DOM.Images.showLoad(); - - Util.exec(CloudCmd.Editor); - - DOM.preventDefault(pEvent); - } - else if(lKeyCode === KEY.F10 && pEvent.shiftKey){ - Util.exec(CloudCmd.Menu); - - DOM.preventDefault(pEvent); - } - - else if (lKeyCode === KEY.TRA){ - DOM.Images.showLoad({top: true}); - Util.exec(CloudCmd.Terminal); - } - /* навигация по таблице файлов * - * если нажали клавишу вверх * - * выделяем предыдущую строку */ - else if(lKeyCode === KEY.UP){ - DOM.setCurrentFile( lCurrentFile.previousSibling ); - DOM.preventDefault( pEvent ); - } - - /* если нажали клавишу в низ * - * выделяем следующую строку */ - else if(lKeyCode === KEY.DOWN){ - DOM.setCurrentFile( lCurrentFile.nextSibling ); - DOM.preventDefault( pEvent ); - } - - /* если нажали клавишу Home * - * переходим к самому верхнему * - * элементу */ - else if(lKeyCode === KEY.HOME){ - DOM.setCurrentFile( lCurrentFile.parentElement.firstChild ); - DOM.preventDefault(pEvent); - } - - /* если нажали клавишу End - * выделяем последний элемент - */ - else if(lKeyCode === KEY.END){ - DOM.setCurrentFile( lCurrentFile.parentElement.lastElementChild ); - DOM.preventDefault( pEvent ); - } - - /* если нажали клавишу page down - * проматываем экран - */ - else if(lKeyCode === KEY.PAGE_DOWN){ - DOM.getPanel().scrollByPages(1); - - for(i=0; i<30; i++){ - if(!lCurrentFile.nextSibling) break; - - lCurrentFile = lCurrentFile.nextSibling; - } - DOM.setCurrentFile(lCurrentFile); - DOM.preventDefault(pEvent); - } - - /* если нажали клавишу page up - * проматываем экран - */ - else if(lKeyCode === KEY.PAGE_UP){ - DOM.getPanel().scrollByPages(-1); - - var lC = lCurrentFile, - tryCatch = function(pCurrentFile){ - Util.tryCatch(function(){ - return pCurrentFile - .previousSibling - .previousSibling - .previousSibling - .previousSibling; - }); - }; - - for(i = 0; i < 30; i++){ - if(!lC.previousSibling || tryCatch(lC) ) break; - - lC = lC.previousSibling; - } - DOM.setCurrentFile(lC); - DOM.preventDefault(pEvent); - } - - /* если нажали Enter - открываем папку*/ - else if(lKeyCode === KEY.ENTER) - Util.exec(CloudCmd._loadDir()); - - /* если нажали +r - * обновляем страницу, - * загружаем содержимое каталога - * при этом данные берём всегда с - * сервера, а не из кэша - * (обновляем кэш) - */ - else if(lKeyCode === KEY.R && pEvent.ctrlKey){ - console.log('+r pressed\n' + - 'reloading page...\n' + - 'press +q to remove all key-handlers'); - - /* Программно нажимаем на кнопку перезагрузки - * содержимого каталога - */ - var lRefreshIcon = DOM.getRefreshButton(); - if(lRefreshIcon){ - /* получаем название файла*/ - var lSelectedName = DOM.getCurrentName(lCurrentFile); - - /* если нашли элемент нажимаем него - * а если не можем - нажимаем на - * ссылку, на которую повешен eventHandler - * onclick - */ - - Util.exec( DOM.getListener(lRefreshIcon) ); - CloudCmd._currentToParent(lSelectedName); - - DOM.preventDefault(); - } - } - - /* если нажали +d чистим кэш */ - else if(lKeyCode === KEY.D && pEvent.ctrlKey){ - Util.log('+d pressed\n' + - 'clearing cache...\n' + - 'press +q to remove all key-handlers'); - - DOM.Cache.clear(); - DOM.preventDefault(); - } - - /* если нажали +q - * убираем все обработчики - * нажатий клавиш - */ - else if(lKeyCode === KEY.Q && pEvent.altKey){ - console.log('+q pressed\n' + - '+r reload key-handerl - removed' + - '+s clear cache key-handler - removed'+ - 'press +s to to set them'); - - /* обработчик нажатий клавиш снят*/ - keyBinded = false; - - pEvent.preventDefault();//запрет на дальнейшее действие - } - } - - /* если нажали +s - * устанавливаем все обработчики - * нажатий клавиш - */ - else if(pEvent.keyCode === KEY.S && pEvent.altKey){ - /* обрабатываем нажатия на клавиши*/ - keyBinded = true; - - console.log('+s pressed\n' + - '+r reload key-handerl - set\n' + - '+s clear cache key-handler - set\n' + - 'press +q to remove them'); - - pEvent.preventDefault();//запрет на дальнейшее действие - } - }; - - /* добавляем обработчик клавишь */ - DOM.addKeyListener(key_event); - - /* клавиши назначены*/ - keyBinded = true; - }; - +var CloudCommander, Util, DOM; +(function(CloudCmd, Util, DOM){ + "use strict"; + + DOM.Images.hideLoad(); + + /* private property set or set key binding */ + var keyBinded; + + /* Key constants*/ + CloudCmd.KEY = { + TAB : 9, + ENTER : 13, + ESC : 27, + + PAGE_UP : 33, + PAGE_DOWN : 34, + END : 35, + HOME : 36, + UP : 38, + DOWN : 40, + + Delete : 46, + + D : 68, + + G : 71, + + O : 79, + Q : 81, + R : 82, + S : 83, + T : 84, + + F2 : 113, + F3 : 114, + F4 : 115, + F10 : 121, + + TRA : 192 /* Typewritten Reverse Apostrophe (`) */ + }; + + var KEY = CloudCmd.KEY; + + CloudCmd.KeyBinding = {}; + + var KeyBinding = CloudCmd.KeyBinding; + + KeyBinding.get = function(){return keyBinded;}; + + KeyBinding.set = function(){keyBinded = true;}; + + KeyBinding.unSet = function(){keyBinded = false;}; + + KeyBinding.init = function(){ + /* saving state of tabs varibles */ + var lTabPanel = { + left : 0, + right : 0 + + }; + + var key_event = function(pEvent){ + /* получаем выдленный файл*/ + var lCurrentFile = DOM.getCurrentFile(), i; + /* если клавиши можно обрабатывать*/ + if(keyBinded && pEvent){ + var lKeyCode = pEvent.keyCode; + + /* open configuration window */ + if(lKeyCode === KEY.O && pEvent.altKey){ + console.log('openning config window...'); + + DOM.Images.showLoad({top: true}); + + Util.exec(CloudCmd.Config); + } + + else if(lKeyCode === KEY.G && pEvent.altKey) + Util.exec(CloudCmd.GitHub); + + else if(lKeyCode === KEY.D && pEvent.altKey){ + Util.exec(CloudCmd.DropBox); + DOM.preventDefault(pEvent); + } + + /* если нажали таб: + * переносим курсор на + * правую панель, если + * мы были на левой и + * наоборот + */ + else if(lKeyCode === KEY.TAB){ + console.log('Tab pressed'); + + Util.tryCatchLog(function(){ + /* changing parent panel of curent-file */ + var lPanel = DOM.getPanel(), + lId = lPanel.id; + + lTabPanel[lId] = lCurrentFile; + + lPanel = DOM.getPanel({active:false}); + lId = lPanel.id; + + if(lTabPanel[lId]) + DOM.setCurrentFile(lTabPanel[lId]); + else{ + var lFirstFileOnList = DOM.getByTag('li', lPanel)[2]; + + DOM.setCurrentFile(lFirstFileOnList); + } + }); + + DOM.preventDefault(pEvent);//запрет на дальнейшее действие + } + else if(lKeyCode === KEY.Delete) + DOM.promptRemoveCurrent(lCurrentFile); + + /* if f3 or shift+f3 or alt+f3 pressed */ + else if(lKeyCode === KEY.F3){ + var lEditor = CloudCmd[pEvent.shiftKey ? + 'Viewer' : 'Editor']; + + Util.exec(lEditor, true); + + DOM.preventDefault(pEvent); + } + + /* if f4 pressed */ + else if(lKeyCode === KEY.F4) { + DOM.Images.showLoad(); + + Util.exec(CloudCmd.Editor); + + DOM.preventDefault(pEvent); + } + else if(lKeyCode === KEY.F10 && pEvent.shiftKey){ + Util.exec(CloudCmd.Menu); + + DOM.preventDefault(pEvent); + } + + else if (lKeyCode === KEY.TRA){ + DOM.Images.showLoad({top: true}); + Util.exec(CloudCmd.Terminal); + } + /* навигация по таблице файлов * + * если нажали клавишу вверх * + * выделяем предыдущую строку */ + else if(lKeyCode === KEY.UP){ + DOM.setCurrentFile( lCurrentFile.previousSibling ); + DOM.preventDefault( pEvent ); + } + + /* если нажали клавишу в низ * + * выделяем следующую строку */ + else if(lKeyCode === KEY.DOWN){ + DOM.setCurrentFile( lCurrentFile.nextSibling ); + DOM.preventDefault( pEvent ); + } + + /* если нажали клавишу Home * + * переходим к самому верхнему * + * элементу */ + else if(lKeyCode === KEY.HOME){ + DOM.setCurrentFile( lCurrentFile.parentElement.firstChild ); + DOM.preventDefault(pEvent); + } + + /* если нажали клавишу End + * выделяем последний элемент + */ + else if(lKeyCode === KEY.END){ + DOM.setCurrentFile( lCurrentFile.parentElement.lastElementChild ); + DOM.preventDefault( pEvent ); + } + + /* если нажали клавишу page down + * проматываем экран + */ + else if(lKeyCode === KEY.PAGE_DOWN){ + DOM.scrollByPages( DOM.getPanel(), 1 ); + + for(i=0; i<30; i++){ + if(!lCurrentFile.nextSibling) break; + + lCurrentFile = lCurrentFile.nextSibling; + } + DOM.setCurrentFile(lCurrentFile); + DOM.preventDefault(pEvent); + } + + /* если нажали клавишу page up + * проматываем экран + */ + else if(lKeyCode === KEY.PAGE_UP){ + DOM.scrollByPages( DOM.getPanel(), -1 ); + + var lC = lCurrentFile, + tryCatch = function(pCurrentFile){ + Util.tryCatch(function(){ + return pCurrentFile + .previousSibling + .previousSibling + .previousSibling + .previousSibling; + }); + }; + + for(i = 0; i < 30; i++){ + if(!lC.previousSibling || tryCatch(lC) ) break; + + lC = lC.previousSibling; + } + DOM.setCurrentFile(lC); + DOM.preventDefault(pEvent); + } + + /* если нажали Enter - открываем папку*/ + else if(lKeyCode === KEY.ENTER) + Util.exec(CloudCmd._loadDir()); + + /* если нажали +r + * обновляем страницу, + * загружаем содержимое каталога + * при этом данные берём всегда с + * сервера, а не из кэша + * (обновляем кэш) + */ + else if(lKeyCode === KEY.R && pEvent.ctrlKey){ + console.log('+r pressed\n' + + 'reloading page...\n' + + 'press +q to remove all key-handlers'); + + /* Программно нажимаем на кнопку перезагрузки + * содержимого каталога + */ + var lRefreshIcon = DOM.getRefreshButton(); + if(lRefreshIcon){ + /* получаем название файла*/ + var lSelectedName = DOM.getCurrentName(lCurrentFile); + + /* если нашли элемент нажимаем него + * а если не можем - нажимаем на + * ссылку, на которую повешен eventHandler + * onclick + */ + + Util.exec( DOM.getListener(lRefreshIcon) ); + CloudCmd._currentToParent(lSelectedName); + + DOM.preventDefault(); + } + } + + /* если нажали +d чистим кэш */ + else if(lKeyCode === KEY.D && pEvent.ctrlKey){ + Util.log('+d pressed\n' + + 'clearing cache...\n' + + 'press +q to remove all key-handlers'); + + DOM.Cache.clear(); + DOM.preventDefault(); + } + + /* если нажали +q + * убираем все обработчики + * нажатий клавиш + */ + else if(lKeyCode === KEY.Q && pEvent.altKey){ + console.log('+q pressed\n' + + '+r reload key-handerl - removed' + + '+s clear cache key-handler - removed'+ + 'press +s to to set them'); + + /* обработчик нажатий клавиш снят*/ + keyBinded = false; + + pEvent.preventDefault();//запрет на дальнейшее действие + } + } + + /* если нажали +s + * устанавливаем все обработчики + * нажатий клавиш + */ + else if(pEvent.keyCode === KEY.S && pEvent.altKey){ + /* обрабатываем нажатия на клавиши*/ + keyBinded = true; + + console.log('+s pressed\n' + + '+r reload key-handerl - set\n' + + '+s clear cache key-handler - set\n' + + 'press +q to remove them'); + + pEvent.preventDefault();//запрет на дальнейшее действие + } + }; + + /* добавляем обработчик клавишь */ + DOM.addKeyListener(key_event); + + /* клавиши назначены*/ + keyBinded = true; + }; + })(CloudCommander, Util, DOM); \ No newline at end of file