var CloudCmd, Util, DOM, CloudFunc, Dialog; (function(Util) { 'use strict'; var DOMFunc = function() {}, DOMProto, DialogProto = function() { this.alert = alert.bind(window); this.prompt = prompt.bind(window); this.confirm = confirm.bind(window); }, ImagesProto = function() { var Images, ImageElementProto = function() { var LOADING = 'loading', LoadingImage, HIDDEN = 'hidden', ERROR = 'error'; function init() { var is; if (!LoadingImage) { LoadingImage = LOADING; is = DOM.isSVG(); if (is) LoadingImage += '-svg'; else LoadingImage += '-gif'; } } function getElement() { var element; init(); element = DOM.load({ name : 'span', id : 'js-status-image', className : 'icon', attribute : 'data-progress', notAppend : true }); return element; } this.get = getElement; /* Функция создаёт картинку загрузки */ this.loading = function() { var element = getElement(); DOM.addClass(element, LOADING) .addClass(element, LoadingImage) .removeClass(element, ERROR) .removeClass(element, HIDDEN); return element; }; /* Функция создаёт картинку ошибки загрузки */ this.error = function() { var element = getElement(); DOM.addClass(element, ERROR) .removeClass(element, LOADING) .removeClass(element, LoadingImage) .removeClass(element, HIDDEN); return element; }; }; Images = new ImageElementProto(); /** * Function shows loading spinner * pPosition = {top: true}; */ this.showLoad = function(position) { var top = position && position.top, current, image = Images.loading(), parent = image.parentElement; if (top) current = DOM.getRefreshButton().parentElement; else { current = DOM.getCurrentFile(); current = DOM.getByClass('name', current); } if (!parent || (parent && parent !== current)) current.appendChild(image); DOM.show(image); return image; }; /** * hide load image */ this.hide = function() { var element = Images.get(); DOM.hide(element); }; /** * show error image (usualy after error on ajax request) */ this.showError = function(jqXHR, isQuiet) { var isStr = Util.isString(jqXHR), image = Images.error(), response = '', statusText = '', status = 0, text = ''; if (jqXHR) if (isStr) { text = jqXHR; } else { response = jqXHR.responseText; statusText = jqXHR.statusText; status = jqXHR.status; text = status === 404 ? response : statusText; } DOM.show(image); image.title = text; if (text) setTimeout(function() { if (!isQuiet) Dialog.alert(text); Util.log(text); }, 100); return image; }; this.setProgress = function(value, title) { var DATA = 'data-progress', element = Images.get(); if (element) { element.setAttribute(DATA, value + '%'); if (title) element.title = title; } }; this.clearProgress = function() { var DATA = 'data-progress', element = Images.get(); if (element) { element.setAttribute(DATA, ''); element.title = ''; } }; }, DOMTreeProto = function() { var DOM = this; /** * add class to element * * @param element * @param pClass */ this.addClass = function(element, pClass) { var ret = element && pClass; if (ret) element.classList.add(pClass); return this; }; /** * remove class pClass from element element * @param element * @param pClass */ this.removeClass = function(element, pClass) { var ret = element && pClass; if (ret) element.classList.remove(pClass); return this; }; this.toggleClass = function(element, pClass) { var ret = element && pClass; if (ret) element.classList.toggle(pClass); return this; }; /** * check class of element * * @param element * @param pClass */ this.isContainClass = function(element, pClass) { var ret, lClassList = element && element.classList; if (lClassList ) ret = lClassList.contains(pClass); return ret; }; /** * Function search element by tag * @param pTag - className * @param element - element */ this.getByTag = function(pTag, element) { return (element || document).getElementsByTagName(pTag); }; /** * Function search element by id * @param Id - id */ this.getById = function(pId) { return document.getElementById(pId); }; /** * Function search first element by class name * @param pClass - className * @param element - element */ this.getByClass = function(pClass, elementParam) { var element = elementParam || document, ret = this.getByClassAll(pClass, element)[0]; return ret; }; this.getByDataName = function(attribute, element) { var ret, selector = '[' + 'data-name="' + attribute + '"]'; if (!element) element = document; ret = element.querySelector(selector); return ret; }; /** * Function search element by class name * @param pClass - className * @param element - element */ this.getByClassAll = function(pClass, element) { return (element || document).getElementsByClassName(pClass); }; /** * check SVG SMIL animation support */ this.isSVG = function() { var ret, svgNode, name, create = document.createElementNS, SVG_URL = 'http://www.w3.org/2000/svg'; if (create) { create = create.bind(document); svgNode = create(SVG_URL, 'animate'); name = svgNode.toString(); ret = /SVGAnimate/.test(name); } return ret; }; /** * add class=hidden to element * * @param element */ this.hide = function(element) { return DOM.addClass(element, 'hidden'); }; this.show = function(element) { return DOM.removeClass(element, 'hidden'); }; }, CmdProto = function() { var Cmd = this, CurrentInfo = {}, CURRENT_FILE = 'current-file', SELECTED_FILE = 'selected-file', SelectType = '*.*', Title, TabPanel = { 'js-left' : null, 'js-right' : null }; /** * private function thet unset currentfile * * @currentFile */ function unsetCurrentFile(currentFile) { var ret = DOM.isCurrentFile(currentFile); if (ret) DOM.removeClass(currentFile, CURRENT_FILE); return ret; } this.loadRemote = function(name, callback) { var Files = DOM.Files; Files.get(['config', 'modules'], function(error, config, modules) { var remoteTmpls, local, remote, load = DOM.load, online = config.online && navigator.onLine, remoteObj = Util.findObjByNameInArr(modules, 'remote'), module = Util.findObjByNameInArr(remoteObj, name), version = module.version, isArray = Util.isArray(module.local), funcON = function() { load.parallel(remote, function(error) { if (error) funcOFF(); else callback(); }); }, funcOFF = function() { load.parallel(local, callback); }; if (isArray) { remoteTmpls = module.remote; local = module.local; } else { remoteTmpls = [module.remote]; local = [module.local]; } remote = remoteTmpls.map(function(item) { return Util.render(item, { version: version }); }); Util.exec.if(online, funcON, funcOFF); }); return DOM; }; /** * load jquery from google cdn or local copy * @param callback */ this.loadJquery = function(callback) { var ret = DOM.loadRemote('jquery', callback); return ret; }; this.loadSocket = function(callback) { var ret = DOM.loadRemote('socket', callback); return ret; }; /** function loads css and js of Menu * @param callback */ this.loadMenu = function(callback) { var Images = DOM.Images, dir = CloudCmd.LIBDIRCLIENT + 'menu/', files = [ dir + 'menu-io.js', dir + 'menu-io.css' ]; Images.showLoad(); DOM.load.parallel(files, function(error) { Images.hide(); Util.exec(callback, error); }); }; /** * create new folder * */ this.promptNewDir = function() { promptNew('directory', '?dir'); }; /** * create new file * * @typeName * @type */ this.promptNewFile = function() { promptNew('file'); }; function promptNew(typeName, type) { var RESTful = DOM.RESTful, lName = Cmd.getCurrentName(), lDir = Cmd.getCurrentDirPath(), lMsg = 'New ' + typeName || 'File', lType = Util.isString(type) ? type : ''; if (lName === '..') lName = ''; lName = Dialog.prompt(lMsg, lName); if (lName) RESTful.write(lDir + lName + lType, null, CloudCmd.refresh); } /** * zip file * */ this.zipFile = function() { var RESTful = DOM.RESTful, name = Cmd.getCurrentName(), dir = Cmd.getCurrentDirPath(), path = dir + name, fileFrom = { from : path }; if (name && name !== '..') RESTful.zip(fileFrom, CloudCmd.refresh); }; /** * unzip file * */ this.unzipFile = function() { var RESTful = DOM.RESTful, name = Cmd.getCurrentName(), dir = Cmd.getCurrentDirPath(), path = dir + name, fileFrom = { from : path }; if (name && name !== '..') RESTful.unzip(fileFrom, CloudCmd.refresh); }; /** * prompt and delete current file or selected files * * @currentFile */ this.promptDelete = function(currentFile) { var ret, type, isDir, msg, current, name = '', msgAsk = 'Do you really want to delete the ', msgSel = 'selected ', files = Cmd.getSelectedFiles(), names = Cmd.getSelectedNames(files), i, n = names && names.length; if (!Cmd.isCurrentFile(currentFile)) current = DOM.getCurrentFile(); if (n) { for (i = 0; i < 5 && i < n; i++) name += '\n' + names[i]; if (n >= 5) name += '\n...'; msg = msgAsk + msgSel + n + ' files/directoris?\n' + name ; } else { isDir = Cmd.isCurrentIsDir(current); if (isDir) type ='directory'; else type = 'file'; type += ' '; name = Cmd.getCurrentName(current); msg = msgAsk + msgSel + type + name + '?'; } if (name !== '..') ret = Dialog.confirm(msg); else Dialog.alert('No files selected!'); if (ret) DOM.sendDelete(files); return ret; }; /** * delete current or selected files * * @files */ this.sendDelete = function(files) { var n, names, path, query = '', RESTful = DOM.RESTful, current = CurrentInfo.element; if (!files) files = Cmd.getSelectedFiles(); names = DOM.getSelectedNames(files), n = names && names.length; if (n) { path = Cmd.getCurrentDirPath(); query = '?files'; } else { path = Cmd.getCurrentPath(current); } RESTful.delete(path + query, names, function() { var Storage = DOM.Storage, dirPath = CurrentInfo.dirPath, dir = CloudFunc.rmLastSlash(dirPath); if (n > 1) DOM.deleteSelected(files); else DOM.deleteCurrent(current); Storage.removeMatch(dir); }); }; /** * get current direcotory name */ this.getCurrentDirName = function() { var ret, lSubstr, /* получаем имя каталога в котором находимся */ lHref = this.getCurrentDirPath(); lHref = CloudFunc.rmLastSlash(lHref); lSubstr = lHref.substr(lHref , lHref.lastIndexOf('/')); ret = Util.rmStrOnce(lHref, lSubstr + '/') || '/'; return ret; }; /** * get current direcotory path */ this.getCurrentDirPath = function(panel) { var ret, path; if (!panel) panel = this.getPanel(); path = this.getByDataName('js-path', panel); ret = path && path.textContent; return ret; }; /** * get current direcotory path */ this.getParentDirPath = function(panel) { var path = DOM.getCurrentDirPath(panel), dirName = DOM.getCurrentDirName() + '/', ret = '/'; if (path !== '/') ret = Util.rmStr(path, dirName); return ret; }; /** * get not current direcotory path */ this.getNotCurrentDirPath = function() { var panel = this.getPanel(true), path = this.getCurrentDirPath(panel); return path; }; /** * unified way to get current file * * @currentFile */ this.getCurrentFile = function() { var ret = this.getByClass(CURRENT_FILE); return ret; }; /** * get current file by name */ this.getCurrentFileByName = function(name) { var element, panel = DOM.getPanel(); name = 'js-file-' + name; element = DOM.getByDataName(name, panel); return element; }; /** * unified way to get current file * * @currentFile */ this.getSelectedFiles = function() { var panel = DOM.getPanel(), selected = this.getByClassAll(SELECTED_FILE, panel), ret = Util.slice(selected); return ret; }; /** * get size * @currentFile */ this.getCurrentSize = function(currentFile) { var ret, current = currentFile || Cmd.getCurrentFile(), size = this.getByClass('size', current); size = size.textContent; /* если это папка - возвращаем слово dir вместо размера*/ ret = Util.rmStrOnce(size, ['<', '>']); return ret; }; /** * get size * @currentFile */ this.loadCurrentSize = function(callback, currentFile) { var RESTful = DOM.RESTful, Images = DOM.Images, current = currentFile || this.getCurrentFile(), query = '?size', link = this.getCurrentPath(current); Images.showLoad(); if (name !== '..') RESTful.read(link + query, function(size) { DOM.setCurrentSize(size, current); Util.exec(callback, current); Images.hide(); }); }; /** * load hash * @callback * @currentFile */ this.loadCurrentHash = function(callback, currentFile) { var RESTful = DOM.RESTful, current = currentFile || DOM.getCurrentFile(), query = '?hash', link = DOM.getCurrentPath(current); RESTful.read(link + query, function(data) { callback(null, data); }); }; /** * load current modification time of file * @callback * @currentFile */ this.loadCurrentTime = function(callback, currentFile) { var RESTful = DOM.RESTful, current = currentFile || this.getCurrentFile(), query = '?time', link = this.getCurrentPath(current); RESTful.read(link + query, callback); }; /** * set size * @currentFile */ this.setCurrentSize = function(size, currentFile) { var current = currentFile || this.getCurrentFile(), sizeElement = this.getByClass('size', current); sizeElement.textContent = size; }; /** * @currentFile */ this.getCurrentMode = function(currentFile) { var ret, current = currentFile || this.getCurrentFile(), lMode = this.getByClass('mode', current); ret = lMode.textContent; return ret; }; /** * @currentFile */ this.getCurrentOwner = function(currentFile) { var ret, current = currentFile || this.getCurrentFile(), owner = this.getByClass('owner', current); ret = owner.textContent; return ret; }; /** * unified way to get current file content * * @param callback * @param currentFile */ this.getCurrentData = function(callback, currentFile) { var hash, RESTful = DOM.RESTful, current = currentFile || DOM.getCurrentFile(), path = DOM.getCurrentPath(current), isDir = DOM.isCurrentIsDir(current), func = function(data) { var length, ONE_MEGABYTE = 1024 * 1024 * 1024; if (Util.isObject(data)) data = Util.stringifyJSON(data); length = data.length; if (hash && length < ONE_MEGABYTE) DOM.saveDataToStorage(path, data, hash); Util.exec(callback, null, data); }; if (isDir) RESTful.read(path, func); else DOM.checkStorageHash(path, function(error, equal, hashNew) { Util.exec.if(!error && equal, function() { DOM.getDataFromStorage(path, callback); }, function() { hash = hashNew; RESTful.read(path, func); }); }); }; /** * unified way to save current file content * * @callback - function({data, name}) {} * @currentFile */ this.saveCurrentData = function(url, data, callback, query) { if (!query) query = ''; DOM.RESTful.write(url + query, data, function() { DOM.saveDataToStorage(url, data); }); }; /** * unified way to get RefreshButton */ this.getRefreshButton = function() { var panel = this.getPanel(), refresh = this.getByDataName('js-refresh', panel); return refresh; }; /** * unified way to set current file */ this.setCurrentFile = function(currentFile, options) { var ret, path, pathWas, title, o = options, FS = CloudFunc.FS, CENTER = true, currentFileWas = this.getCurrentFile(); if (currentFile) { if (currentFileWas) { pathWas = DOM.getCurrentDirPath(); unsetCurrentFile(currentFileWas); } this.addClass(currentFile, CURRENT_FILE); path = DOM.getCurrentDirPath(); if (path !== pathWas) { title = CloudFunc.getTitle(path); this.setTitle(title); /* history could be present * but it should be false * to prevent default behavior */ if (!o || o.history !== false) { if (path !== '/') path = FS + path; DOM.setHistory(path, null, path); } } /* scrolling to current file */ this.scrollIntoViewIfNeeded(currentFile, CENTER); ret = true; Cmd.updateCurrentInfo(); } return this; }; /* * set current file by position * * @param layer - element * @param - position {x, y} */ this.getCurrentByPosition = function(position) { var element, tag, isChild, x = position.x, y = position.y; element = document.elementFromPoint(x, y), tag = element.tagName; isChild = Util.strCmp(tag, ['A', 'SPAN', 'LI']); if (!isChild) { element = null; } else { switch (tag) { case 'A': element = element.parentElement.parentElement; break; case 'SPAN': element = element.parentElement; break; } } return element; }; /** * select current file * @param currentFile */ this.toggleSelectedFile = function(currentFile) { var current = currentFile || this.getCurrentFile(), ret = this.toggleClass(current, SELECTED_FILE); return ret; }; this.toggleAllSelectedFiles = function() { var i, n, panel = DOM.getPanel(), files = DOM.getFiles(panel), name = DOM.getCurrentName(files[0]); if (name === '..') i = 1; else i = 0; n = files.length; for (;i < n; i++) DOM.toggleSelectedFile(files[i]); return Cmd; }; function selectByPattern(msg, files) { var n, allMsg = 'Specify file type for ' + msg + ' selection', i = 0, type, matches = 0, name, shouldSel = msg === 'expand', isSelected, isMatch, current; type = Dialog.prompt(allMsg, SelectType); if (type !== null) { SelectType = type; type = Util.getRegExp(type); n = files && files.length; for (i = 0; i < n; i++) { current = files[i]; name = DOM.getCurrentName(current); if (name !== '..') { isMatch = name.match(new RegExp(type)); if (isMatch) { ++matches; isSelected = DOM.isSelected(current); if (shouldSel) isSelected = !isSelected; if (isSelected) DOM.toggleSelectedFile(current); } else if (!shouldSel) ++i; } } if (!matches) Dialog.alert('No matches found!'); } } /* * open dialog with expand selection */ this.expandSelection = function() { var msg = 'expand', files = CurrentInfo.files; selectByPattern(msg, files); }; /* * open dialog with shrink selection */ this.shrinkSelection = function() { var msg = 'shrink', files = DOM.getSelectedFiles(); selectByPattern(msg, files); }; /** * setting history wrapper */ this.setHistory = function(data, pTitle, url) { var ret = window.history; if (ret) history.pushState(data, pTitle, url); return ret; }; /** * set title or create title element * * @param name */ this.setTitle = function(name) { if (!Title) Title = DOM.getByTag('title')[0] || DOM.load({ name :'title', innerHTML : name, parentElement : document.head }); Title.textContent = name; return this; }; /** * current file check * * @param currentFile */ this.isCurrentFile = function(currentFile) { var ret; if (currentFile ) ret = this.isContainClass(currentFile, CURRENT_FILE); return ret; }; /** * selected file check * * @param currentFile */ this.isSelected = function(pSelected) { var ret; if (pSelected ) ret = this.isContainClass(pSelected, SELECTED_FILE); return ret; }; /** * check is current file is a directory * * @param currentFile */ this.isCurrentIsDir = function(currentFile) { var current = currentFile || this.getCurrentFile(), lFileType = this.getByClass('mini-icon', current), ret = this.isContainClass(lFileType, 'directory'); return ret; }; /** * get link from current (or param) file * * @param currentFile - current file by default */ this.getCurrentLink = function(currentFile) { var lLink = this.getByTag( 'a', currentFile || this.getCurrentFile()), ret = lLink.length > 0 ? lLink[0] : -1; return ret; }; /** * get link from current (or param) file * * @param currentFile - current file by default */ this.getCurrentPath = function(currentFile) { var current = currentFile || DOM.getCurrentFile(), element = DOM.getByTag('a', current)[0], path = element.getAttribute('href'); path = Util.rmStrOnce(path, CloudFunc.FS); return path; }; /** * get name from current (or param) file * * @param currentFile */ this.getCurrentName = function(currentFile) { var name = '', current = currentFile || this.getCurrentFile(), link = this.getCurrentLink(current); if (link) name = link.title || link.textContent; return name; }; this.getSelectedNames = function(selected) { var current, first, name, i, n, isSelected, ret = []; if (!selected) selected = this.getSelectedFiles() || []; first = selected[0]; if (first) { name = this.getCurrentName(first); } else { first = this.getCurrentFile(); name = this.getCurrentName(first); } isSelected = this.isSelected(first); if (name === '..' && isSelected) { selected.shift(); this.toggleSelectedFile(first); } n = selected.length; for (i = 0; i < n;i++) { current = selected[i]; ret[i] = this.getCurrentName(current); } return ret; }; /** * set name from current (or param) file * * @param name * @param current */ this.setCurrentName = function(name, current) { var Info = CurrentInfo, link = Info.link, FS = CloudFunc.FS, dir = FS + Info.dirPath; link.title = link.textContent = name; link.href = dir + name; current.setAttribute('data-name', 'js-file-' + name); return link; }; /** * check storage hash */ this.checkStorageHash = function(name, callback) { var Storage = DOM.Storage, parallel = Util.exec.parallel, loadHash = DOM.loadCurrentHash, nameHash = name + '-hash', getStoreHash = Util.exec.with(Storage.get, nameHash); Util.checkArgs(arguments, ['name', 'callback']); parallel([loadHash, getStoreHash], function(error, loadHash, storeHash) { var equal, isContain = Util.isContainStr(loadHash, 'error'); if (isContain) error = loadHash; else if (loadHash === storeHash) equal = true; callback(error, equal, loadHash); }); }; /** * save data to storage * * @param name * @param data * @param callback */ this.saveDataToStorage = function(name, data, hash, callback) { DOM.Files.get('config', function(error, config) { var allowed = config.localStorage, isDir = DOM.isCurrentIsDir(), nameHash = name + '-hash', nameData = name + '-data'; if (!allowed || isDir) Util.exec(callback); else Util.exec.if(hash, function() { var Storage = DOM.Storage; Storage.set(nameHash, hash); Storage.set(nameData, data); Util.exec(callback, hash); }, function(callback) { DOM.loadCurrentHash(function(error, loadHash) { hash = loadHash; callback(); }); }); }); }; /** * save data to storage * * @param name * @param data * @param callback */ this.getDataFromStorage = function(name, callback) { DOM.Files.get('config', function(error, config) { var Storage = DOM.Storage, nameHash = name + '-hash', nameData = name + '-data', allowed = config.localStorage, isDir = DOM.isCurrentIsDir(); if (!allowed || isDir) Util.exec(callback); else { Util.exec.parallel([ function(callback) { Storage.get(nameData, callback); }, function(callback) { Storage.get(nameHash, callback); } ], callback); } }); }; /** 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 id = 'js-', current = this.getCurrentFile(), files = current.parentElement, panel = files.parentElement, isLeft = panel.id === 'js-left'; /* if {active : false} getting passive panel */ if (pActive && !pActive.active) { id += isLeft ? 'right' : 'left'; panel = this.getById(id); } /* if two panels showed * then always work with passive * panel */ if (window.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH) panel = this.getById('js-left'); if (!panel) Util.log('Error can not find Active Panel'); return panel; }; this.getFiles = function(element) { var files = DOM.getByDataName('js-files', element), ret = files.children || []; return ret; }; /** * shows panel right or left (or active) */ this.showPanel = function(pActive) { var ret = true, lPanel = this.getPanel(pActive); if (lPanel) this.show(lPanel); else ret = false; return ret; }; /** * hides panel right or left (or active) */ this.hidePanel = function(pActive) { var ret = false, lPanel = this.getPanel(pActive); if (lPanel) ret = this.hide(lPanel); return ret; }; /** * open window with URL * @param url */ this.openWindow = function(url) { var left = 140, top = 187, width = 1000, height = 650, options = 'left=' + left + ',top=' + top + ',width=' + width + ',height=' + height + ',personalbar=0,toolbar=0' + ',scrollbars=1,resizable=1', wnd = window.open(url, 'Cloud Commander Auth', options); if (!wnd) Dialog.alert('Please disable your popup blocker and try again.'); }; /** * remove child of element * @param pChild * @param element */ this.remove = function(child, element) { var parent = element || document.body; parent.removeChild(child); return DOM; }; /** * remove current file from file table * @param current * */ this.deleteCurrent = function(current) { var name, next, prev, parent, currentNew; if (!current) Cmd.getCurrentFile(); parent = current && current.parentElement; name = Cmd.getCurrentName(current); if (current && name !== '..') { next = current.nextSibling, prev = current.previousSibling; if (next) currentNew = next; else if (prev) currentNew = prev; this.setCurrentFile(currentNew); parent.removeChild(current); } return currentNew; }; /** * remove selected files from file table * @Selected */ this.deleteSelected = function(selected) { var i, n, current; if (!selected) selected = this.getSelectedFiles(); if (selected) { n = selected.length; for (i = 0; i < n; i++) { current = selected[i]; this.deleteCurrent(current); } } return selected; }; /** * rename current file * * @currentFile */ this.renameCurrent = function(current) { var from, to, dirPath, cmp, files, RESTful = DOM.RESTful; if (!Cmd.isCurrentFile(current)) current = Cmd.getCurrentFile(); from = Cmd.getCurrentName(current), to = Dialog.prompt('Rename', from) || from, dirPath = Cmd.getCurrentDirPath(); cmp = Util.strCmp(from, to); if (!cmp) { files = { from : dirPath + from, to : dirPath + to }; RESTful.mv(files, function() { var Storage = DOM.Storage, path = CloudFunc.rmLastSlash(dirPath); DOM.setCurrentName(to, current); Cmd.updateCurrentInfo(); Storage.remove(path); }); } }; /* * process files (copy or move) * @param operation */ function processFiles(operation) { var n, name, from, to, files, cmp, msg, opFunc, path = CurrentInfo.dirPath, RESTful = DOM.RESTful, names = Cmd.getSelectedNames(), length = names && names.length; if (operation.copy) { opFunc = RESTful.cp; msg = 'Copy '; } else if (operation.move) { opFunc = RESTful.mv; msg = 'Rename/Move '; } if (!length) { name = DOM.getCurrentName(); names.push(name); } else if (length === 1) { name = names[0]; } n = names.length; if (n > 1) msg += n + ' file(s)'; else msg += '"' + name + '"'; msg += ' to'; from = path; to = DOM.getNotCurrentDirPath(); if (name === '..') { Dialog.alert('No files selected!'); } else { to = Dialog.prompt(msg, to); cmp = Util.strCmp(from, to); if (!cmp && to) { files = { from : from, names : names, to : to }; opFunc(files, function() { var panel = DOM.getPanel(), panelPassive = DOM.getPanel(true), id = panelPassive.id, dotDot = DOM.getById( '..(' + id + ')'); if (operation.move) CloudCmd.refresh(dotDot, panel); DOM.setCurrentFile(dotDot); CloudCmd.refresh(dotDot, panelPassive); DOM.Storage.remove(path); }); } } } this.copyFiles = function() { processFiles({ copy: true }); }; this.moveFiles = function() { processFiles({ move: true }); }; /** * unified way to scrollIntoViewIfNeeded * (native suporte by webkit only) * @param element * @param pCenter */ this.scrollIntoViewIfNeeded = function(element, center) { var ret = element && element.scrollIntoViewIfNeeded; /* for scroll as small as possible * param should be false */ if (arguments.length === 1) center = false; if (ret) element.scrollIntoViewIfNeeded(center); return ret; }; /* scroll on one page*/ this.scrollByPages = function(element, pPages) { var ret = element && element.scrollByPages && pPages; if (ret) element.scrollByPages(pPages); return ret; }; this.getType = function(name, callback) { DOM.Files.get('ext', function(error, extensions) { var index, ext = Util.getExt(name); ext = extensions[ext]; if (ext) { index = ext.indexOf('/') + 1; ext = ext.substr(index); } Util.exec(callback, ext); }); }; this.changePanel = function() { var id, files, Info = CurrentInfo, current = Info.element, panel = Info.panel, filesPassive = Info.filesPassive; id = panel.id; TabPanel[id] = current; panel = Info.panelPassive; id = panel.id; current = TabPanel[id]; if (current) files = current.parentElement; if (!files || !files.parentElement) current = filesPassive[0]; DOM.setCurrentFile(current, { history: true }); return this; }; this.CurrentInfo = CurrentInfo, this.updateCurrentInfo = function(currentFile) { var info = Cmd.CurrentInfo, current = currentFile || Cmd.getCurrentFile(), files = current.parentElement, panel = files.parentElement, panelPassive = Cmd.getPanel({active:false}), filesPassive = DOM.getFiles(panelPassive), name = Cmd.getCurrentName(current); info.dir = Cmd.getCurrentDirName(); info.dirPath = Cmd.getCurrentDirPath(); info.parentDirPath = Cmd.getParentDirPath(); info.element = current; info.ext = Util.getExt(name); info.files = files.children, info.filesPassive = filesPassive, info.first = files.firstChild; info.getData = Cmd.getCurrentData; info.last = files.lastChild; info.link = Cmd.getCurrentLink(current); info.mode = Cmd.getCurrentMode(current); info.name = name; info.path = Cmd.getCurrentPath(current); info.panel = panel; info.panelPassive = panelPassive; info.size = Cmd.getCurrentSize(current); info.isDir = Cmd.isCurrentIsDir(); info.isSelected = Cmd.isSelected(current); }; }, DOMTree = Util.extendProto(DOMTreeProto), Images = Util.extendProto(ImagesProto); DOMProto = DOMFunc.prototype = new CmdProto(); Dialog = new DialogProto(); Util.extend(DOMProto, [ DOMTree, { Images : Images, Dialog : Dialog } ]); DOM = new DOMFunc(); })(Util);