Merge branch 'dev'

This commit is contained in:
coderaiser 2012-07-19 06:06:39 -04:00
commit 0fd6f42008
13 changed files with 351 additions and 149 deletions

3
.gitignore vendored
View file

@ -40,3 +40,6 @@ node_modules/*
#hashes file
hashes.json
#hiding git modules for travis work out
.gitignore

View file

@ -1,3 +1,36 @@
2012.07.*, Version 0.1.3
* Fixed bug with nodester (jitsu env.HOME make him go done).
* Fixed bug: gzip do not working out, becouse accessible flag settet
up to _controller object.
* To every panel added scroll bars which is hiding if do not needed.
* Fixed bug with setting up flag in config.json: do not minimize js.
* Fixed bugs many bugs in _anyload function (client.js).
* Added function cssLoad to client.js
* Added Client Side CodeMirror library with name Cloud Editor.
* Fixed bug with building file table from json data, when we go around
and come back to root dir.
If name of a file or directory is more then 16 charactes it shows
like 'VERY-LONG-NAME..', so becaouse of on first came we load page
like no js, so json building from file table thet was genereted on
server. So if file to long we should take it's name from title
parameter of <a> tag, it's wasn't, so folder navigation not every
time was possible.
* Fixed bug with undefined size on root directory of Cloud Commander.
Now Cloud Commander writes size 0, if can't get size, and besides will
setted b char: "0b".
* Added supporting of Russian language in directory names.
2012.07.14, Version 0.1.2
* Added suport of jitsu.

View file

@ -42,9 +42,14 @@ There is a short list:
Installing
---------------
**Cloud Commander** installing is very easy. All you need it's just clone
repository from github. Install and start, just 3 commands:
repository from github. Just 2 commands:
git clone git://github.com/coderaiser/cloudcmd.git --recursive
git clone git://github.com/coderaiser/cloudcmd.git
cd cloudcmd
or
npm i cloudcmd
mv node_modules/cloudcmd ./cloudcmd
Starting
---------------
@ -75,8 +80,7 @@ assingned (and installed) module: [Minify] (https://github.com/coderaiser/minify
Install addtitional modules:
git submodule init
git submodule update
npm i
**Cloud Commander's Client Side** use module jquery for ajaxing.
We could not use this module, but this way is fast:
@ -94,4 +98,12 @@ If you would like to contribute - send pull request to dev branch.
Getting dev version of **Cloud Commander**:
git clone cloudcmd --recursive
git checkout dev
It is possible thet dev version Cloud Commander will needed dev version of Minify,
so to get it you should type a couple more commands:
cd node_modules
rm -rf minify
git clone git://github.com/coderaiser/minify
git checkout dev

127
client.js
View file

@ -17,6 +17,7 @@ var CloudClient={
init :function(){},
keyBinding :function(){},/* функция нажатий обработки клавишь */
Editor :function(){},/* function loads and shows editor */
keyBinded :false,/* оброботка нажатий клавишь установлена*/
_loadDir :function(){},
/*
@ -137,7 +138,15 @@ CloudClient.keyBinding=(function(){
});
});
/* function loads and shows editor */
CloudClient.Editor = (function(){
/* loading CloudMirror plagin */
CloudClient.jsload(CloudClient.LIBDIRCLIENT + 'editor.js',{
onload:(function(){
CloudCommander.Editor.Keys();
})
});
});
/*
* Функция привязываеться ко всем ссылкам и
* загружает содержимое каталогов
@ -330,7 +339,20 @@ CloudClient.init=(function()
/* устанавливаем размер высоты таблицы файлов
* исходя из размеров разрешения экрана
*/
/* выделяем строку с первым файлом */
var lFmHeader=document.getElementsByClassName('fm_header');
if(lFmHeader && lFmHeader[0].nextSibling)
lFmHeader[0].nextSibling.className=CloudClient.CURRENT_FILE;
/* показываем элементы, которые будут работать только, если есть js */
var lFM=document.getElementById('fm');
if(lFM)lFM.className='localstorage';
/* если есть js - показываем правую панель*/
var lRight=document.getElementById('right');
if(lRight)lRight.className=lRight.className.replace('hidden','');
/* формируем и округляем высоту экрана
* при разрешениии 1024x1280:
* 658 -> 700
@ -339,28 +361,11 @@ CloudClient.init=(function()
var lHeight=window.screen.height - (window.screen.height/3).toFixed();
lHeight=(lHeight/100).toFixed()*100;
var lFm=document.getElementById('fm');
if(lFm)lFm.style.cssText='height:' +
lHeight +
'px';
/* выделяем строку с первым файлом */
var lFmHeader=document.getElementsByClassName('fm_header');
if(lFmHeader && lFmHeader[0].nextSibling)
lFmHeader[0].nextSibling.className=CloudClient.CURRENT_FILE;
/* показываем элементы, которые будут работать только, если есть js */
var lFM=document.getElementById('fm');
if(lFM)lFm.className='localstorage';
/* если есть js - показываем правую панель*/
var lRight=document.getElementById('right');
if(lRight)lRight.className=lRight.className.replace('hidden','');
CloudClient.cssSet({id:'show_2panels',
element:document.head,
inner:'#left{width:46%;}'
});
inner:'#left{width:46%;}' +
'.panel{height:' + lHeight +'px'
});
});
/* функция меняет ссыки на ajax-овые */
@ -432,9 +437,10 @@ CloudClient._changeLinks = function(pPanelID)
* @pNeedRefresh - необходимость обновить данные о каталоге
*/
CloudClient._ajaxLoad=function(path, pNeedRefresh)
{
/* Отображаем красивые пути */
var lPath=path;
{
/* Отображаем красивые пути */
/* added supporting of russian language */
var lPath=decodeURI(path);
var lFS_s=CloudFunc.FS;
if(lPath.indexOf(lFS_s)===0){
lPath=lPath.replace(lFS_s,'');
@ -586,24 +592,31 @@ CloudClient._anyload = function(pName,pSrc,pFunc,pStyle,pId,pElement)
if(!document.getElementById(lID))
{
var element = document.createElement(pName);
element.src = pSrc;
/* if working with external css
* using href in any other case
* using src
*/
pName === 'link' ?
element.href = pSrc
: element.src = pSrc;
element.id=lID;
if(arguments.length>=3){
/* if passed arguments function
* then it's onload by default
*/
if(typeof pFunc === 'function'){
element.onload=pFunc;
/* if object - then onload or onerror */
}else if (typeof pFunc === 'object'){
if(pFunc.onload)element.onload = pFunc.onload;
if(pFunc.onerror)element.onerror=pFunc.onerror;
}
if(arguments.length>=4){
if(pFunc)
if(typeof pFunc === 'function'){
element.onload=pFunc;
/* if object - then onload or onerror */
}else if (typeof pFunc === 'object'){
if(pFunc.onload)element.onload = pFunc.onload;
if(pFunc.onerror)element.onerror=pFunc.onerror;
}
if(arguments.length >= 4 && pStyle){
element.style.cssText=pStyle;
}
}
pElement.appendChild(element);
(pElement || document.body).appendChild(element);
return element;
}
/* если js-файл уже загружен
@ -632,9 +645,31 @@ CloudClient.cssSet = function(pParams_o){
pParams_o.func,
pParams_o.style,
pParams_o.id,
pParams_o.element?pParams_o.element:document.body);
lElem.innerHTML=pParams_o.inner;
pParams_o.element || document.head);
pParams_o.inner &&
(lElem.innerHTML = pParams_o.inner);
};
/* Function loads external css files
* @pParams_o - структура параметров, заполняеться таким
* образом: {src: ' ',func: '', id: '', element: '', inner: ''}
* все параметры опциональны
*/
CloudClient.cssLoad = function(pParams_o){
var lElem=CloudClient._anyload('link',
pParams_o.src,
pParams_o.func,
pParams_o.style,
pParams_o.id,
pParams_o.element || document.head);
lElem.rel = "stylesheet";
pParams_o.inner &&
(lElem.innerHTML = pParams_o.inner);
};
/*
* Функция генерирует JSON из html-таблицы файлов
@ -663,7 +698,22 @@ CloudClient._getJSONfromFileTable=function()
var lIsDir=lLI[i].getElementsByClassName('mini-icon')[0]
.className.replace('mini-icon ','')==='directory'?true:false;
var lName=lLI[i].getElementsByClassName('name')[0].textContent;
var lName=lLI[i].getElementsByClassName('name')[0];
lName &&
(lName = lName.getElementsByTagName('a'));
/* if found link to folder
* cheking is it a full name
* or short
*/
/* if short we got title
* if full - getting textConent
*/
lName.length &&
(lName = lName[0]);
lName.title &&
(lName = lName.title) ||
(lName = lName.textContent);
/* если это папка - выводим слово dir вместо размера*/
var lSize=lIsDir?'dir':lLI[i].getElementsByClassName('size')[0].textContent;
var lMode=lLI[i].getElementsByClassName('mode')[0].textContent;
@ -716,6 +766,7 @@ try{
CloudCommander.init();
/* привязываем клавиши к функциям */
CloudCommander.keyBinding();
CloudCommander.Editor();
};
}
catch(err){}

View file

@ -137,8 +137,7 @@ background:url(/img/panel_refresh.png) 0 -15px no-repeat;
background-position: 0 0;
}
#fm{
height:90%;
overflow-y: scroll;
height:90%;
}
.fm_header{
font-weight: bold;
@ -162,7 +161,7 @@ background:url(/img/panel_refresh.png) 0 -15px no-repeat;
float:right;
}
.panel{
display: table;
overflow-y: auto;
width:46%;
}
#keyspanel{

6
install-dev Normal file
View file

@ -0,0 +1,6 @@
git checkout dev
cd node_modules
git clone git://github.com/coderaiser/minify
cd minify
git checkout dev
cd ../../

130
lib/client/editor.js Normal file
View file

@ -0,0 +1,130 @@
var CloudCommander, CodeMirror;
CloudCommander.Editor = {};
CloudCommander.Editor.CloudMirror = {
load: (function(){
CloudCommander.jsload('http://codemirror.net/lib/codemirror.js', load_all(this));
function load_all(pParent) {
return function(){
CloudCommander.cssLoad({
src : 'http://codemirror.net/lib/codemirror.css',
element : document.head
});
CloudCommander.cssLoad({
src : 'http://codemirror.net/theme/night.css',
element : document.head
});
CloudCommander.cssSet({id:'editor',
inner : '.CodeMirror{' +
'font-family:\'Droid Sans Mono\';' +
'font-size:15px;' +
'resize:vertical;' +
'padding:20px;' +
'}' +
'.CodeMirror-scroll{' +
'height: 660px;' +
'}' +
'.CodeMirror-scrollbar{' +
'overflow-y:auto' +
'}'
});
var lShowEditor_f = function (){
if (!document.getElementById('CloudEditor')) {
var lEditor=document.createElement('div');
lEditor.id ='CloudEditor';
lEditor.className = 'hidden';
var lFM = document.getElementById('fm');
if(lFM){
lFM.appendChild(lEditor);
CodeMirror(lEditor,{
mode : "xml",
htmlMode : true,
theme : 'night',
lineNumbers : true,
//переносим длинные строки
lineWrapping: true,
extraKeys: {
//Сохранение
"Esc": pParent.hide(pParent)
}
});
}else console.log('Error. Something went wrong FM not found');
}
};
CloudCommander.jsload('http://codemirror.net/mode/xml/xml.js', lShowEditor_f);
};
}
}),
show : (function(){
/* if CloudEditor is not loaded - loading him */
document.getElementById('CloudEditor') ||
this.load();
/* removing keyBinding if set */
CloudCommander.keyBinded = false;
var lLeft = this.getById('left');
var lCloudEditor = this.getById('CloudEditor');
lLeft &&
(lLeft.className = 'panel hidden');
lCloudEditor &&
(lCloudEditor.className = '');
}),
hide : (function(pParent) {
return function(){
CloudCommander.keyBinded = true;
var lLeft = pParent.getById('left');
var lCloudEditor = pParent.getById('CloudEditor');
lCloudEditor &&
(lCloudEditor.className = 'hidden');
lLeft &&
(lLeft.className = 'panel');
};
}),
getById: function(pId){return document.getElementById(pId);},
getPanel: function(){
var lCurrent = document.getElementsByClassName('current-file');
lCurrent.length &&
(lCurrent = lCurrent[0].parentElement);
return lCurrent && lCurrent.id;
}
};
CloudCommander.Editor.Keys = (function(){
"use strict";
/* loading js and css of CodeMirror */
CloudCommander.Editor.CloudMirror.load();
var key_event=function(event){
/* если клавиши можно обрабатывать */
if(CloudCommander.keyBinded){
/* if f4 pressed */
if(event.keyCode===115){
CloudCommander.Editor.CloudMirror.show();
}
}
};
/* добавляем обработчик клавишь */
if (document.addEventListener)
document.addEventListener('keydown', key_event,false);
else
document.onkeypress=key_event;
/* клавиши назначены*/
CloudCommander.keyBinded=true;
});

View file

@ -14,8 +14,7 @@ CloudCommander.keyBinding=(function(){
* контент снова (js,css) в готовой версии нет
* необходимости.
*
*/
//console.log(event.keyCode);
*/
var lCurrentFile;
var lName;
/* если клавиши можно обрабатывать*/
@ -108,17 +107,6 @@ CloudCommander.keyBinding=(function(){
var lATag=lName[0].getElementsByTagName('a');
/* если нету - выходим */
if(!lATag)return false;
/* получаем ссылку на каталог,
* что на уровень выше
*/
/* получаем имя каталога в котором находимся*/
var lHref;
try{
lHref=lCurrentFile.parentElement.getElementsByClassName('path')[0].textContent;
}catch(error){console.log('error');}
lHref=CloudFunc.removeLastSlash(lHref);
var lSubstr=lHref.substr(lHref,lHref.lastIndexOf('/'));
lHref=lHref.replace(lSubstr+'/','');
/* вызываем ajaxload привязанный через changelinks
* пробулем нажать на ссылку, если не получиться

View file

@ -32,19 +32,6 @@ CloudFunc.removeLastSlash = function(pPath){
pPath.substr(pPath, pPath.length-1):pPath;
else return pPath;
};
/*
* Функция меняет код символа пробела на пробел
* в переданной строке
* @pPath - строка
*/
CloudFunc.replaceSpaces = function(pPath){
if(pPath.indexOf('%20')>0){
do{
pPath=pPath.replace('%20',' ');
}while(pPath.indexOf('%20')>0);
}
return pPath;
};
/* Функция возвращает заголовок веб страницы */
CloudFunc.setTitle = function(){
@ -159,7 +146,7 @@ CloudFunc.convertPermissionsToNumberic= function(pPerm_s){
*/
CloudFunc.getShortedSize=function(pSize){
/* if pSize=0 - return it */
if(!pSize)return pSize;
if (pSize != pSize-0) return pSize;
/* Константы размеров, что используются
* внутри функции

View file

@ -81,10 +81,7 @@ exports.Minify={
*/
setAllowed :(function(pAllowed){
if(pAllowed){
this._allowed.css=pAllowed.css;
this._allowed.js=pAllowed.js;
this._allowed.html=pAllowed.html;
this._allowed.img=pAllowed.img;
this._allowed=pAllowed;
}
}),
@ -101,7 +98,7 @@ exports.Minify={
lMinify = require('minify');
}catch(pError){
this._allowed={js:false,css:false,html:false};
return console.log('Could not minify' +
return console.log('Could not minify ' +
'withou minify module\n' +
'for fixing type:\n' +
'git submodule init\n' +
@ -140,21 +137,23 @@ exports.Minify={
'client.js' +
' changed. size:',
(pFinalCode = pFinalCode
.replace('cloudfunc.js','cloudfunc.min.js')
.replace('keyBinding.js','keyBinding.min.js')
.replace('/lib/', lMinFolder)
.replace('/lib/client/',
lMinFolder)).length);
.replace('editor.js','editor.min.js')
.replace('cloudfunc.js','cloudfunc.min.js')
.replace('keyBinding.js','keyBinding.min.js')
.replace('/lib/', lMinFolder)
.replace('/lib/client/',
lMinFolder)).length);
return pFinalCode;
};
var lOptimizeParams;
var lOptimizeParams = [];
if (this._allowed.js) {
lOptimizeParams=[{
'client.js': lPostProcessing_f},
'lib/cloudfunc.js',
'lib/client/keyBinding.js'];
'lib/client/keyBinding.js',
'lib/client/editor.js'];
}
if (this._allowed.html)

2
node_modules/minify generated vendored

@ -1 +1 @@
Subproject commit d08b97db461c5e0227df178a699c376c963d48ee
Subproject commit 8d386766868e176add3772365e277e501b0a37dd

View file

@ -1,6 +1,6 @@
{
"name": "cloudcmd",
"version": "0.1.2",
"version": "0.1.3",
"author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
"description": "Two-panels file manager, totally writed on js.",
"homepage": "https://github.com/coderaiser/cloudcmd",
@ -15,7 +15,7 @@
"node": "0.6.17",
"subdomain": "cloudcmd",
"dependencies": {
"minify": "0.1.2"
"minify": "0.1.3"
},
"devDependencies": {},
"engines": {

118
server.js
View file

@ -3,92 +3,91 @@
/* Обьект содержащий все функции и переменные
* серверной части Cloud Commander'а
*/
var CloudServer={
var CloudServer = {
/* main Cloud Commander configuration
* readed from config.json if it's
* exist
*/
Config : {
"cache" : {"allowed" : true},
"minification" : {
"js" : false,
"css" : false,
"html" : true,
"img" : false
},
"server" : true
Config : {
"cache" : {"allowed" : true},
"minification" : {
"js" : false,
"css" : false,
"html" : true,
"img" : false
},
"server" : true
},
/* функция, которая генерирует заголовки
* файлов, отправляемые сервером клиенту
*/
generateHeaders :function(){},
generateHeaders : function () {},
/* функция высылает
* данные клиенту
*/
sendResponse :function(){},
sendResponse : function () {},
/* Структура содержащая функции,
* и переменные, в которых
* говориться о поддерживаемых
* браузером технологиях
*/
BrowserSuport :{},
BrowserSuport : {},
/* Обьект для работы с кэшем */
Cashe :{},
Cashe : {},
/* Обьект через который
* выполняеться сжатие
* скриптов и стилей
*/
Minify :{},
Minify : {},
/* Асоциативный масив обьектов для
* работы с ответами сервера
* высылаемыми на запрос о файле и
* хранащий информацию в виде
* Responces[name]=responce;
*/
Responses :{},
Responses : {},
/* ПЕРЕМЕННЫЕ */
/* Поддержка браузером JS*/
NoJS :true,
NoJS : true,
/* Поддержка gzip-сжатия
* браузером
*/
Gzip :undefined,
Gzip : undefined,
/* КОНСТАНТЫ */
/* index.html */
INDEX :'index.html',
LIBDIR :'./lib',
LIBDIRSERVER :'./lib/server',
INDEX : 'index.html',
LIBDIR : './lib',
LIBDIRSERVER : './lib/server',
Port :31337, /* server port */
IP :'127.0.0.1'
Port : 31337, /* server port */
IP : '127.0.0.1'
};
var LeftDir='/';
var RightDir=LeftDir;
var LeftDir = '/';
var RightDir = LeftDir;
/* модуль для работы с путями*/
var Path = require('path');
var Path = require('path');
var Fs = require('fs'); /* модуль для работы с файловой системой*/
var Querystring = require('querystring');
var Zlib;
/* node v0.4 not contains zlib
*/
try{
try {
Zlib = require('zlib'); /* модуль для сжатия данных gzip-ом*/
}catch(error){
Zlib=undefined;
} catch (error) {
Zlib = undefined;
console.log('to use gzip-commpression' +
'you should install zlib module\n' +
'npm install zlib');
}
/* добавляем модуль с функциями */
var CloudFunc;
try{
try {
CloudFunc = require(CloudServer.LIBDIR +
'/cloudfunc');
@ -125,22 +124,22 @@ CloudServer.init=(function(){
* not created, just init and
* all logs writed to screen
*/
if(process.argv[2]==='test'){
if (process.argv[2] === 'test') {
console.log(process.argv);
this.Config.server=false;
this.Config.logs=false;
this.Config.server = false;
this.Config.logs = false;
}
if(this.Config.logs){
if (this.Config.logs) {
console.log('log param setted up in config.json\n' +
'from now all logs will be writed to log.txt');
this.writeLogsToFile();
}
}catch(pError){
} catch (pError) {
console.log('warning: configureation file config.json not found...\n' +
'using default values...\n' +
JSON.stringify(CloudServer.Config));
}
}
/* Переменная в которой храниться кэш*/
this.Cache.setAllowed(CloudServer.Config.cache.allowed);
@ -154,8 +153,7 @@ CloudServer.init=(function(){
/* создаём сервер на порту 31337 */
CloudServer.start=function()
{
CloudServer.start = function () {
this.init();
this.Port = process.env.PORT || /* c9 */
@ -167,17 +165,17 @@ CloudServer.start=function()
CloudServer.IP;
/* if Cloud Server started on jitsu */
if(!process.env.HOME.indexOf('/opt/haibu')){
this.IP = '0.0.0.0';
if(process.env.HOME &&
!process.env.HOME.indexOf('/opt/haibu')) {
this.IP = '0.0.0.0';
}
/* server mode or testing mode */
if(!process.argv[2] && this.Config.server){
/* server mode or testing mode */
if (!process.argv[2] && this.Config.server) {
var http = require('http');
try{
try {
http.createServer(this._controller).listen(
this.Port,
this.IP);
this.Port, this.IP);
console.log('Cloud Commander server running at http://' +
this.IP +
@ -252,7 +250,10 @@ CloudServer._controller=function(pReq, pRes)
*/
var url = require("url");
var pathname = url.parse(pReq.url).pathname;
console.log('pathname: '+pathname);
/* added supporting of Russian language in directory names */
pathname = Querystring.unescape(pathname);
console.log('pathname: ' + pathname);
/* получаем поддерживаемые браузером кодировки*/
var lAcceptEncoding = pReq.headers['accept-encoding'];
@ -263,9 +264,8 @@ CloudServer._controller=function(pReq, pRes)
if (lAcceptEncoding &&
lAcceptEncoding.match(/\bgzip\b/) &&
Zlib){
this.Gzip=true;
}else
this.Gzip=false;
CloudServer.Gzip=true;
}
/* путь в ссылке, который говорит
* что js отключен
*/
@ -369,17 +369,11 @@ CloudServer._controller=function(pReq, pRes)
/* если в итоге путь пустой
* делаем его корневым
*/
if(pathname==='')pathname='/';
RightDir=pathname;
LeftDir=pathname;
/* если встретиться пробел -
* меня код символа пробела на пробел
*/
LeftDir=CloudFunc.replaceSpaces(LeftDir);
RightDir=CloudFunc.replaceSpaces(RightDir);
if (pathname==='')
pathname = '/';
LeftDir = pathname;
RightDir = LeftDir;
/* Проверяем с папкой ли мы имеем дело */