mirror of
https://github.com/coderaiser/cloudcmd.git
synced 2026-01-23 02:35:49 +00:00
feature(cloudcmd) add --html-dialogs
This commit is contained in:
parent
d9c67255a3
commit
a7933b755c
37 changed files with 1271 additions and 141 deletions
3
HELP.md
3
HELP.md
|
|
@ -71,11 +71,13 @@ Cloud Commander supports command line parameters:
|
|||
| `--port` | set port number
|
||||
| `--minify` | enable minification
|
||||
| `--progress` | show progress of file operations
|
||||
| `--html-dialogs` | show html dialogs
|
||||
| `--no-server` | do not start server
|
||||
| `--no-auth` | disable authorization
|
||||
| `--no-online` | load scripts from local server
|
||||
| `--no-minify` | disable minification
|
||||
| `--no-progress` | do not show progress of file operations
|
||||
| `--no-html-dialogs` | do not use html dialogs
|
||||
|
||||
If no parameters given Cloud Commander reads information from `~/.cloudcmd.json` and use
|
||||
port from it (`8000` default). if port variables `PORT` or `VCAP_APP_PORT` isn't exist.
|
||||
|
|
@ -218,6 +220,7 @@ Here is description of options:
|
|||
"root" : "/", /* root directory */
|
||||
"prefix" : "", /* url prefix */
|
||||
"progress" : true /* show progress of file operations */
|
||||
"htmlDialogs" : false /* show html dialogs */
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@
|
|||
'online',
|
||||
'minify',
|
||||
'progress',
|
||||
'progress-of-copying'
|
||||
'progress-of-copying',
|
||||
'html-dialogs'
|
||||
],
|
||||
default: {
|
||||
server : true,
|
||||
|
|
@ -45,6 +46,8 @@
|
|||
root : config('root') || '/',
|
||||
prefix : config('prefix') || '',
|
||||
progress : config('progress') || config('progressOfCopying'),
|
||||
|
||||
'html-dialogs' : config('htmlDialogs')
|
||||
},
|
||||
alias: {
|
||||
v: 'version',
|
||||
|
|
@ -80,6 +83,7 @@
|
|||
config('progress', args.progress);
|
||||
config('prefix', args.prefix);
|
||||
config('root', args.root);
|
||||
config('htmlDialogs', args['html-dialogs']);
|
||||
|
||||
deprecate('progress-of-copying', 'progress');
|
||||
|
||||
|
|
|
|||
17
bower.json
17
bower.json
|
|
@ -21,16 +21,17 @@
|
|||
"test"
|
||||
],
|
||||
"dependencies": {
|
||||
"fancybox": "~2.1.5",
|
||||
"jquery": "~2.1.4",
|
||||
"format-io": "~0.9.6",
|
||||
"rendy": "~1.1.0",
|
||||
"github": "~0.10.6",
|
||||
"vk-openapi": "~0.0.1",
|
||||
"domtokenlist-shim": "~1.1.0",
|
||||
"promise-polyfill": "~2.1.0",
|
||||
"emitify": "~1.2.0",
|
||||
"fancybox": "~2.1.5",
|
||||
"format-io": "~0.9.6",
|
||||
"github": "~0.10.6",
|
||||
"jquery": "~2.1.4",
|
||||
"menu": "~0.7.9",
|
||||
"philip": "~1.3.0",
|
||||
"menu": "~0.7.9"
|
||||
"promise-polyfill": "~2.1.0",
|
||||
"rendy": "~1.1.0",
|
||||
"vk-openapi": "~0.0.1",
|
||||
"smalltalk": "~1.5.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 62 KiB |
|
|
@ -13,9 +13,11 @@
|
|||
"--port ": "set port number",
|
||||
"--minify ": "enable minification",
|
||||
"--progress ": "show progress of file operations",
|
||||
"--html-dialogs ": "use html dialogs",
|
||||
"--no-server ": "do not start server",
|
||||
"--no-auth ": "disable authorization",
|
||||
"--no-online ": "load scripts from local server",
|
||||
"--no-minify ": "disable minification",
|
||||
"--no-progress ": "do not show progress of file operations"
|
||||
"--no-progress ": "do not show progress of file operations",
|
||||
"--no-html-dialogs ": "do not use html dialogs"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,5 +18,6 @@
|
|||
"ip": null,
|
||||
"root": "/",
|
||||
"prefix": "",
|
||||
"progress": true
|
||||
"progress": true,
|
||||
"htmlDialogs":false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ var Util, DOM, CloudFunc, join;
|
|||
console.log(str);
|
||||
},
|
||||
|
||||
TITLE,
|
||||
Listeners,
|
||||
Files = DOM.Files,
|
||||
Images = DOM.Images,
|
||||
|
|
@ -29,6 +30,10 @@ var Util, DOM, CloudFunc, join;
|
|||
this.HOST = location.origin ||
|
||||
location.protocol + '//' + location.host;
|
||||
|
||||
this.TITLE = 'Cloud Commander';
|
||||
|
||||
TITLE = this.TITLE;
|
||||
|
||||
log.enable = function() {
|
||||
Debug = true;
|
||||
};
|
||||
|
|
@ -171,6 +176,17 @@ var Util, DOM, CloudFunc, join;
|
|||
CloudCmd.LIBDIR = prefix + '/lib/';
|
||||
CloudCmd.LIBDIRCLIENT = prefix + '/lib/client/';
|
||||
|
||||
DOM.Files.get('config', function(error, config) {
|
||||
var options = {
|
||||
htmlDialogs: !error && config.htmlDialogs
|
||||
};
|
||||
|
||||
if (error)
|
||||
CloudCmd.log(error);
|
||||
|
||||
DOM.Dialog = new DOM.Dialog(prefix, options);
|
||||
});
|
||||
|
||||
Util.exec.if(document.body.scrollIntoViewIfNeeded, func, funcBefore);
|
||||
};
|
||||
|
||||
|
|
@ -385,13 +401,14 @@ var Util, DOM, CloudFunc, join;
|
|||
CloudCmd.log('reading dir: "' + path + '";');
|
||||
|
||||
Files.get('config', function(error, config) {
|
||||
var dirStorage;
|
||||
var dirStorage,
|
||||
Dialog = DOM.Dialog;
|
||||
|
||||
if (error)
|
||||
alert(error);
|
||||
Dialog.alert(TITLE, error);
|
||||
else
|
||||
dirStorage = config.dirStorage;
|
||||
|
||||
|
||||
if (dirStorage)
|
||||
Storage.get(path, create);
|
||||
else
|
||||
|
|
@ -421,7 +438,7 @@ var Util, DOM, CloudFunc, join;
|
|||
name = Info.name;
|
||||
|
||||
if (error) {
|
||||
Dialog.alert(error.responseText);
|
||||
Dialog.alert(TITLE, error.responseText);
|
||||
} else {
|
||||
childNodes = panel.childNodes;
|
||||
i = childNodes.length;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
COPY = 'copy',
|
||||
CUT = 'cut',
|
||||
|
||||
TITLE = 'Buffer',
|
||||
|
||||
Buffer = {
|
||||
cut : callIfEnabled.bind(null, cut),
|
||||
copy : callIfEnabled.bind(null, copy),
|
||||
|
|
@ -56,7 +58,7 @@
|
|||
function isEnabled(callback) {
|
||||
Files.get('config', function(error, config) {
|
||||
if (error)
|
||||
Dialog.alert(error);
|
||||
Dialog.alert(TITLE, error);
|
||||
else
|
||||
callback(config.buffer);
|
||||
});
|
||||
|
|
@ -67,7 +69,7 @@
|
|||
if (is)
|
||||
callback();
|
||||
else
|
||||
Dialog.alert('Buffer disabled in config!');
|
||||
Dialog.alert(TITLE, 'Buffer disabled in config!');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -127,13 +129,13 @@
|
|||
error = 'Buffer is empty!';
|
||||
|
||||
if (error) {
|
||||
DOM.Dialog.alert(error);
|
||||
Dialog.alert(TITLE, error);
|
||||
} else {
|
||||
data = json.parse(opData);
|
||||
data.to = path;
|
||||
|
||||
if (data.from === path) {
|
||||
Dialog.alert(msg);
|
||||
Dialog.alert(TITLE, msg);
|
||||
} else {
|
||||
Operation.show(opStr, data);
|
||||
clear();
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ var CloudCmd;
|
|||
client + 'notify',
|
||||
client + 'storage',
|
||||
client + 'files',
|
||||
client + 'dialog',
|
||||
'client',
|
||||
client + 'buffer',
|
||||
client + 'listeners',
|
||||
|
|
@ -30,11 +31,13 @@ var CloudCmd;
|
|||
}),
|
||||
|
||||
moduleFiles = [
|
||||
'promise-polyfill/Promise.min',
|
||||
window.Promise ? '' : 'promise-polyfill/Promise.min',
|
||||
'format-io/lib/format',
|
||||
'rendy/lib/rendy',
|
||||
'emitify/lib/emitify'
|
||||
].map(function(name) {
|
||||
].filter(function(name) {
|
||||
return name;
|
||||
}).map(function(name) {
|
||||
return modules + name;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,12 @@ var CloudCmd, Util, DOM, io;
|
|||
showLoad = function() {
|
||||
Images.show.load('top');
|
||||
},
|
||||
|
||||
Element,
|
||||
Template,
|
||||
|
||||
TITLE = 'Config',
|
||||
|
||||
Notify = DOM.Notify,
|
||||
Config = this;
|
||||
|
||||
|
|
@ -79,7 +83,7 @@ var CloudCmd, Util, DOM, io;
|
|||
});
|
||||
|
||||
socket.on('err', function(error) {
|
||||
Dialog.alert(error);
|
||||
Dialog.alert(TITLE, error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -112,7 +116,7 @@ var CloudCmd, Util, DOM, io;
|
|||
focus, obj;
|
||||
|
||||
if (error)
|
||||
return Dialog.alert('Could not load config!');
|
||||
return Dialog.alert(TITLE, 'Could not load config!');
|
||||
|
||||
obj = input.convert(config);
|
||||
|
||||
|
|
@ -221,7 +225,7 @@ var CloudCmd, Util, DOM, io;
|
|||
});
|
||||
|
||||
if (isChecked && !el.localStorage.checked) {
|
||||
Dialog.alert(msg);
|
||||
Dialog.alert(TITLE, msg);
|
||||
|
||||
elements.forEach(function(element) {
|
||||
if (element.checked) {
|
||||
|
|
@ -241,7 +245,7 @@ var CloudCmd, Util, DOM, io;
|
|||
msg = name + ' depends on localStorage';
|
||||
|
||||
if (data && !elLocalStorage.checked) {
|
||||
Dialog.alert(msg);
|
||||
Dialog.alert(TITLE, msg);
|
||||
elLocalStorage.checked = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
54
lib/client/dialog.js
Normal file
54
lib/client/dialog.js
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* global DOM */
|
||||
/* global smalltalk */
|
||||
|
||||
(function(DOM) {
|
||||
'use strict';
|
||||
|
||||
DOM.Dialog = Dialog;
|
||||
|
||||
function Dialog(prefix, config) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Dialog))
|
||||
return new Dialog(config);
|
||||
|
||||
load(config.htmlDialogs);
|
||||
|
||||
function load(htmlDialogs) {
|
||||
var names,
|
||||
name = 'smalltalk',
|
||||
is = window.Promise,
|
||||
js = '.min.js',
|
||||
jsName = is ? js : '.poly' + js,
|
||||
dir = '/modules/' + name + '/dist/';
|
||||
|
||||
if (!htmlDialogs)
|
||||
jsName = '.native' + jsName;
|
||||
|
||||
names = [jsName, '.min.css'].map(function(ext) {
|
||||
return prefix + dir + name + ext;
|
||||
});
|
||||
|
||||
DOM.load.parallel(names, function() {});
|
||||
}
|
||||
|
||||
this.alert = function(title, message) {
|
||||
return smalltalk.alert(title, message, {
|
||||
cancel: false
|
||||
});
|
||||
};
|
||||
|
||||
this.prompt = function(title, message, value, options) {
|
||||
return smalltalk.prompt(title, message, value, options);
|
||||
};
|
||||
|
||||
this.confirm = function(title, message, options) {
|
||||
return smalltalk.confirm(title, message, options);
|
||||
};
|
||||
|
||||
this.alert.noFiles = function(title) {
|
||||
return self.alert(title, 'No files selected!');
|
||||
};
|
||||
}
|
||||
|
||||
})(DOM);
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
var CloudCmd, Util, DOM, CloudFunc, Dialog;
|
||||
var CloudCmd, Util, DOM, CloudFunc;
|
||||
|
||||
(function(Util, window) {
|
||||
'use strict';
|
||||
|
|
@ -8,18 +8,6 @@ var CloudCmd, Util, DOM, CloudFunc, Dialog;
|
|||
var DOMFunc = function() {},
|
||||
DOMProto,
|
||||
|
||||
DialogProto = function() {
|
||||
var self = this;
|
||||
|
||||
this.alert = alert.bind(window);
|
||||
this.prompt = prompt.bind(window);
|
||||
this.confirm = confirm.bind(window);
|
||||
|
||||
this.alert.noFiles = function() {
|
||||
self.alert('No files selected!');
|
||||
};
|
||||
},
|
||||
|
||||
ImagesProto = function() {
|
||||
var Images,
|
||||
ImageElementProto = function() {
|
||||
|
|
@ -167,7 +155,7 @@ var CloudCmd, Util, DOM, CloudFunc, Dialog;
|
|||
},
|
||||
|
||||
DOMTreeProto = function() {
|
||||
var DOM = this;
|
||||
var DOM = this;
|
||||
|
||||
/**
|
||||
* check class of element
|
||||
|
|
@ -280,7 +268,8 @@ var CloudCmd, Util, DOM, CloudFunc, Dialog;
|
|||
CURRENT_FILE = 'current-file',
|
||||
SELECTED_FILE = 'selected-file',
|
||||
SelectType = '*.*',
|
||||
Title,
|
||||
TITLE = 'Cloud Commander',
|
||||
Title,
|
||||
TabPanel = {
|
||||
'js-left' : null,
|
||||
'js-right' : null
|
||||
|
|
@ -468,6 +457,7 @@ var CloudCmd, Util, DOM, CloudFunc, Dialog;
|
|||
|
||||
function promptNew(typeName, type) {
|
||||
var RESTful = DOM.RESTful,
|
||||
Dialog = DOM.Dialog,
|
||||
path = '',
|
||||
name = Cmd.getCurrentName(),
|
||||
dir = Cmd.getCurrentDirPath(),
|
||||
|
|
@ -476,20 +466,21 @@ var CloudCmd, Util, DOM, CloudFunc, Dialog;
|
|||
if (name === '..')
|
||||
name = '';
|
||||
|
||||
name = Dialog.prompt(msg, name);
|
||||
path = dir + name;
|
||||
|
||||
if (type)
|
||||
path += type;
|
||||
Dialog.prompt(TITLE, msg, name, {cancel: false}).then(function(name) {
|
||||
path = dir + name;
|
||||
|
||||
if (name)
|
||||
RESTful.write(path, function(error) {
|
||||
!error && CloudCmd.refresh(null, function() {
|
||||
var current = DOM.getCurrentByName(name);
|
||||
|
||||
DOM.setCurrentFile(current);
|
||||
if (type)
|
||||
path += type;
|
||||
|
||||
if (name)
|
||||
RESTful.write(path, function(error) {
|
||||
!error && CloudCmd.refresh(null, function() {
|
||||
var current = DOM.getCurrentByName(name);
|
||||
|
||||
DOM.setCurrentFile(current);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -729,6 +720,7 @@ var CloudCmd, Util, DOM, CloudFunc, Dialog;
|
|||
this.getCurrentData = function(callback, currentFile) {
|
||||
var hash,
|
||||
RESTful = DOM.RESTful,
|
||||
Dialog = DOM.Dialog,
|
||||
Info = DOM.CurrentInfo,
|
||||
current = currentFile || DOM.getCurrentFile(),
|
||||
path = DOM.getCurrentPath(current),
|
||||
|
|
@ -752,7 +744,7 @@ var CloudCmd, Util, DOM, CloudFunc, Dialog;
|
|||
};
|
||||
|
||||
if (Info.name === '..') {
|
||||
Dialog.alert.noFiles();
|
||||
Dialog.alert.noFiles(TITLE);
|
||||
callback(Error('No files selected!'));
|
||||
} else if (isDir) {
|
||||
RESTful.read(path, func);
|
||||
|
|
@ -913,18 +905,16 @@ var CloudCmd, Util, DOM, CloudFunc, Dialog;
|
|||
|
||||
function selectByPattern(msg, files) {
|
||||
var n, regExp,
|
||||
Dialog = DOM.Dialog,
|
||||
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) {
|
||||
Dialog.prompt(TITLE, allMsg, SelectType, {cancel: false}).then(function(type) {
|
||||
SelectType = type;
|
||||
|
||||
regExp = Util.getRegExp(type);
|
||||
|
|
@ -952,8 +942,8 @@ var CloudCmd, Util, DOM, CloudFunc, Dialog;
|
|||
}
|
||||
|
||||
if (!matches)
|
||||
Dialog.alert('No matches found!');
|
||||
}
|
||||
Dialog.alert('Select Files', 'No matches found!');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1334,7 +1324,7 @@ var CloudCmd, Util, DOM, CloudFunc, Dialog;
|
|||
wnd = window.open(url, 'Cloud Commander Auth', options);
|
||||
|
||||
if (!wnd)
|
||||
Dialog.alert('Please disable your popup blocker and try again.');
|
||||
Dialog.alert(TITLE, 'Please disable your popup blocker and try again.');
|
||||
|
||||
return wnd;
|
||||
};
|
||||
|
|
@ -1411,42 +1401,42 @@ var CloudCmd, Util, DOM, CloudFunc, Dialog;
|
|||
* @currentFile
|
||||
*/
|
||||
this.renameCurrent = function(current) {
|
||||
var from, to, dirPath, files, isExist,
|
||||
RESTful = DOM.RESTful;
|
||||
var from, dirPath, files, isExist,
|
||||
RESTful = DOM.RESTful,
|
||||
Dialog = DOM.Dialog;
|
||||
|
||||
if (!Cmd.isCurrentFile(current))
|
||||
current = Cmd.getCurrentFile();
|
||||
|
||||
from = Cmd.getCurrentName(current);
|
||||
|
||||
if (from === '..') {
|
||||
Dialog.alert.noFiles();
|
||||
} else {
|
||||
to = Dialog.prompt('Rename', from) || from;
|
||||
isExist = !!DOM.getCurrentByName(to);
|
||||
|
||||
dirPath = Cmd.getCurrentDirPath();
|
||||
|
||||
if (from !== to) {
|
||||
files = {
|
||||
from : dirPath + from,
|
||||
to : dirPath + to
|
||||
};
|
||||
if (from === '..')
|
||||
Dialog.alert.noFiles(TITLE);
|
||||
else
|
||||
Dialog.prompt(TITLE, 'Rename', from, {cancel: false}).then(function(to) {
|
||||
isExist = !!DOM.getCurrentByName(to);
|
||||
dirPath = Cmd.getCurrentDirPath();
|
||||
|
||||
RESTful.mv(files, function(error) {
|
||||
var Storage = DOM.Storage;
|
||||
if (from !== to) {
|
||||
files = {
|
||||
from : dirPath + from,
|
||||
to : dirPath + to
|
||||
};
|
||||
|
||||
if (!error) {
|
||||
DOM.setCurrentName(to, current);
|
||||
Cmd.updateCurrentInfo();
|
||||
Storage.remove(dirPath);
|
||||
RESTful.mv(files, function(error) {
|
||||
var Storage = DOM.Storage;
|
||||
|
||||
if (isExist)
|
||||
CloudCmd.refresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!error) {
|
||||
DOM.setCurrentName(to, current);
|
||||
Cmd.updateCurrentInfo();
|
||||
Storage.remove(dirPath);
|
||||
|
||||
if (isExist)
|
||||
CloudCmd.refresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1523,12 +1513,13 @@ var CloudCmd, Util, DOM, CloudFunc, Dialog;
|
|||
|
||||
this.goToDirectory = function() {
|
||||
var msg = 'Go to directory:',
|
||||
path = CurrentInfo.dirPath;
|
||||
path = CurrentInfo.dirPath,
|
||||
Dialog = DOM.Dialog;
|
||||
|
||||
path = prompt(msg, path);
|
||||
|
||||
path && CloudCmd.loadDir({
|
||||
path: path
|
||||
Dialog.prompt(TITLE, msg, path, {cancel: false}).then(function(path) {
|
||||
CloudCmd.loadDir({
|
||||
path: path
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -1627,12 +1618,9 @@ var CloudCmd, Util, DOM, CloudFunc, Dialog;
|
|||
|
||||
DOMProto = DOMFunc.prototype = new CmdProto();
|
||||
|
||||
Dialog = new DialogProto();
|
||||
|
||||
Util.extend(DOMProto, [
|
||||
DOMTree, {
|
||||
Images : Images,
|
||||
Dialog : Dialog
|
||||
Images : Images
|
||||
}
|
||||
]);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,14 +9,17 @@ var CloudCmd, Util, DOM, CloudFunc, MenuIO, Format, edward;
|
|||
Loading = true,
|
||||
|
||||
Info = DOM.CurrentInfo,
|
||||
Dialog = DOM.Dialog,
|
||||
|
||||
exec = Util.exec,
|
||||
Edit = this,
|
||||
|
||||
Menu,
|
||||
Dialog = DOM.Dialog,
|
||||
|
||||
Editor = 'edward',
|
||||
|
||||
TITLE = 'Edit',
|
||||
|
||||
Images = DOM.Images,
|
||||
MSG_CHANGED,
|
||||
Element,
|
||||
|
|
@ -126,7 +129,7 @@ var CloudCmd, Util, DOM, CloudFunc, MenuIO, Format, edward;
|
|||
function getConfig(callback) {
|
||||
DOM.Files.get('config', function(error, config) {
|
||||
if (error)
|
||||
Dialog.alert(error);
|
||||
Dialog.alert(TITLE, error);
|
||||
else if (config.editor)
|
||||
Editor = config.editor;
|
||||
|
||||
|
|
@ -199,7 +202,7 @@ var CloudCmd, Util, DOM, CloudFunc, MenuIO, Format, edward;
|
|||
};
|
||||
|
||||
if (error) {
|
||||
Dialog.alert(error);
|
||||
Dialog.alert(TITLE, error);
|
||||
} else if (!Menu && MenuIO) {
|
||||
Menu = new MenuIO(Element, options, menuData);
|
||||
Menu.show(position.x, position.y);
|
||||
|
|
|
|||
|
|
@ -262,10 +262,12 @@ var CloudCmd, Util, DOM;
|
|||
|
||||
case Key.PLUS:
|
||||
DOM.expandSelection();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.MINUS:
|
||||
DOM.shrinkSelection();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.F1:
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
function ConsoleProto() {
|
||||
var Name = 'Konsole',
|
||||
TITLE = 'Console',
|
||||
|
||||
Element,
|
||||
Loaded,
|
||||
Images = DOM.Images,
|
||||
|
|
@ -79,7 +81,7 @@
|
|||
|
||||
DOM.load.js(url, function(error) {
|
||||
if (error) {
|
||||
Dialog.alert(error.message);
|
||||
Dialog.alert(TITLE, error.message);
|
||||
} else {
|
||||
Loaded = true;
|
||||
Util.timeEnd(Name + ' load');
|
||||
|
|
|
|||
|
|
@ -6,13 +6,16 @@ var CloudCmd, Util, DOM, CloudFunc, MenuIO;
|
|||
CloudCmd.Menu = MenuProto;
|
||||
|
||||
function MenuProto(position) {
|
||||
var Buffer = DOM.Buffer,
|
||||
Info = DOM.CurrentInfo,
|
||||
Loading = true,
|
||||
Key = CloudCmd.Key,
|
||||
Events = DOM.Events,
|
||||
Menu = this,
|
||||
Images = DOM.Images,
|
||||
var Buffer = DOM.Buffer,
|
||||
Info = DOM.CurrentInfo,
|
||||
Loading = true,
|
||||
Key = CloudCmd.Key,
|
||||
Events = DOM.Events,
|
||||
Dialog = DOM.Dialog,
|
||||
Images = DOM.Images,
|
||||
Menu = this,
|
||||
TITLE = 'Menu',
|
||||
|
||||
MenuShowedName,
|
||||
MenuContext,
|
||||
MenuContextFile;
|
||||
|
|
@ -48,7 +51,7 @@ var CloudCmd, Util, DOM, CloudFunc, MenuIO;
|
|||
Util.exec.if(MenuIO, showFunc, function() {
|
||||
DOM.loadMenu(function(error) {
|
||||
if (error)
|
||||
DOM.Dialog.alert(error);
|
||||
Dialog.alert(TITLE, error);
|
||||
else
|
||||
showFunc();
|
||||
});
|
||||
|
|
@ -107,7 +110,7 @@ var CloudCmd, Util, DOM, CloudFunc, MenuIO;
|
|||
var is = config.auth;
|
||||
|
||||
if (error)
|
||||
DOM.alert(error);
|
||||
DOM.alert(TITLE, error);
|
||||
|
||||
callback(is);
|
||||
});
|
||||
|
|
@ -187,10 +190,14 @@ var CloudCmd, Util, DOM, CloudFunc, MenuIO;
|
|||
'Download' : download,
|
||||
'Upload To Cloud': curry(uploadTo, 'Cloud'),
|
||||
'Cut' : function() {
|
||||
isCurrent(Buffer.cut, Dialog.alert.noFiles);
|
||||
isCurrent(Buffer.cut, function() {
|
||||
Dialog.alert.noFiles(TITLE);
|
||||
});
|
||||
},
|
||||
'Copy' : function() {
|
||||
isCurrent(Buffer.copy, Dialog.alert.noFiles);
|
||||
isCurrent(Buffer.copy, function() {
|
||||
Dialog.alert.noFiles(TITLE);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
function OperationProto(operation, data) {
|
||||
var Name = 'Operation',
|
||||
TITLE = Name,
|
||||
Loaded,
|
||||
RESTful = DOM.RESTful,
|
||||
|
||||
|
|
@ -41,7 +42,7 @@
|
|||
|
||||
Files.get('config', function(error, config) {
|
||||
if (error)
|
||||
alert(error);
|
||||
Dialog.alert('Config', error);
|
||||
else if (config.progress)
|
||||
load(create);
|
||||
|
||||
|
|
@ -144,21 +145,27 @@
|
|||
},
|
||||
|
||||
error: function(error) {
|
||||
var is;
|
||||
var msg,
|
||||
messageBox;
|
||||
|
||||
wasError = true;
|
||||
|
||||
if (done)
|
||||
Dialog.alert(error);
|
||||
else
|
||||
is = Dialog.confirm(error + '\n Continue?');
|
||||
if (done) {
|
||||
msg = error;
|
||||
messageBox = Dialog.alert;
|
||||
} else {
|
||||
msg = error + '\n Continue?';
|
||||
messageBox = Dialog.confirm;
|
||||
}
|
||||
|
||||
if (is)
|
||||
messageBox(TITLE, msg).then(function() {
|
||||
emitter.continue();
|
||||
else
|
||||
}, function() {
|
||||
emitter.abort();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
events = Object.keys(listeners);
|
||||
|
||||
events.forEach(function(name) {
|
||||
|
|
@ -263,13 +270,12 @@
|
|||
msg = msgAsk + msgSel + type + name + '?';
|
||||
}
|
||||
|
||||
if (name !== '..')
|
||||
ret = Dialog.confirm(msg);
|
||||
if (name === '..')
|
||||
Dialog.alert.noFiles(TITLE);
|
||||
else
|
||||
Dialog.alert.noFiles();
|
||||
|
||||
if (ret)
|
||||
deleteSilent(files);
|
||||
Dialog.confirm(TITLE, msg, {cancel: false}).then(function() {
|
||||
deleteSilent(files);
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -354,19 +360,28 @@
|
|||
sameName = !!DOM.getCurrentByName(name, panel);
|
||||
|
||||
if (name === '..') {
|
||||
Dialog.alert.noFiles();
|
||||
Dialog.alert.noFiles(TITLE);
|
||||
} else {
|
||||
if (shouldAsk)
|
||||
to = message(to, names);
|
||||
|
||||
message(to, names).then(ask);
|
||||
else
|
||||
ask(to);
|
||||
}
|
||||
|
||||
function ask(to) {
|
||||
ok = from !== to && to;
|
||||
|
||||
if (ok && shouldAsk && sameName)
|
||||
ok = Dialog.confirm(rendy(tmpl, {
|
||||
name: name
|
||||
}));
|
||||
if (ok)
|
||||
if (shouldAsk && sameName)
|
||||
Dialog.confirm(TITLE, rendy(tmpl, {
|
||||
name: name
|
||||
}), {cancel: false}).then(function() {
|
||||
go();
|
||||
});
|
||||
else
|
||||
go();
|
||||
|
||||
if (ok) {
|
||||
function go() {
|
||||
showLoad();
|
||||
|
||||
files = {
|
||||
|
|
@ -415,7 +430,7 @@
|
|||
Util.check(arguments, ['operation']);
|
||||
|
||||
if (!names.length) {
|
||||
Dialog.alert.noFiles();
|
||||
Dialog.alert.noFiles(TITLE);
|
||||
} else {
|
||||
switch(operation) {
|
||||
case 'extract':
|
||||
|
|
@ -460,7 +475,7 @@
|
|||
|
||||
function message(msg) {
|
||||
return function(to, names) {
|
||||
var ret,
|
||||
var promise,
|
||||
n = names.length,
|
||||
name = names[0];
|
||||
|
||||
|
|
@ -473,9 +488,9 @@
|
|||
|
||||
msg += ' to';
|
||||
|
||||
ret = Dialog.prompt(msg, to);
|
||||
promise = Dialog.prompt(TITLE, msg, to, {cancel: false});
|
||||
|
||||
return ret;
|
||||
return promise;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -491,7 +506,7 @@
|
|||
|
||||
DOM.load.parallel(files, function(error) {
|
||||
if (error) {
|
||||
Dialog.alert(error.message);
|
||||
Dialog.alert(TITLE, error.message);
|
||||
} else {
|
||||
Loaded = true;
|
||||
Util.timeEnd(Name + ' load');
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ var Util, DOM, CloudFunc, CloudCmd;
|
|||
|
||||
Images.show.error(text);
|
||||
setTimeout(function() {
|
||||
DOM.Dialog.alert(text);
|
||||
DOM.Dialog.alert(CloudCmd.TITLE, text);
|
||||
}, 100);
|
||||
|
||||
p.callback(Error(text));
|
||||
|
|
|
|||
|
|
@ -34,13 +34,15 @@ programs in browser from any computer, mobile or tablet device.
|
|||
--root set root directory
|
||||
--prefix set url prefix
|
||||
--port set port number
|
||||
--minify enable minification
|
||||
--progress show progress of file operations
|
||||
--html-dialogs use html dialogs
|
||||
--no-auth disable authorization
|
||||
--no-server do not start server
|
||||
--no-online load scripts from local server
|
||||
--minify enable minification
|
||||
--no-minify disable minification
|
||||
--progress show progress of file operations
|
||||
--no-progress do not show progress of file operations
|
||||
--no-html-dialogs do not use html dialogs
|
||||
|
||||
.SH RESOURCES AND DOCUMENTATION
|
||||
|
||||
|
|
|
|||
41
modules/smalltalk/.bower.json
Normal file
41
modules/smalltalk/.bower.json
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"name": "smalltalk",
|
||||
"version": "1.5.0",
|
||||
"homepage": "https://github.com/coderaiser/smalltalk",
|
||||
"authors": [
|
||||
"coderaiser <mnemonic.enemy@gmail.com>"
|
||||
],
|
||||
"description": "Promise-based Alert, Confirm and Prompt replacement",
|
||||
"main": "dist/smalltalk.min.js",
|
||||
"moduleType": [
|
||||
"globals",
|
||||
"node"
|
||||
],
|
||||
"keywords": [
|
||||
"modal",
|
||||
"alert",
|
||||
"prompt",
|
||||
"confirm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"modules",
|
||||
"test",
|
||||
"tests",
|
||||
"screen"
|
||||
],
|
||||
"dependencies": {},
|
||||
"_release": "1.5.0",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v1.5.0",
|
||||
"commit": "04b5b3474dde87c4bdcb57b1040006050511f79b"
|
||||
},
|
||||
"_source": "git://github.com/coderaiser/smalltalk.git",
|
||||
"_target": "~1.5.0",
|
||||
"_originalSource": "smalltalk",
|
||||
"_direct": true
|
||||
}
|
||||
67
modules/smalltalk/ChangeLog
Normal file
67
modules/smalltalk/ChangeLog
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
2015.09.28, v1.5.0
|
||||
|
||||
feature:
|
||||
- (smalltalk) add native
|
||||
|
||||
|
||||
2015.09.26, v1.4.1
|
||||
|
||||
feature:
|
||||
- (bower) rm promise-polyfill
|
||||
|
||||
|
||||
2015.09.26, v1.4.0
|
||||
|
||||
feature:
|
||||
- (smalltalk) Cancel, OK -> OK, Cancel
|
||||
|
||||
|
||||
2015.09.26, v1.3.4
|
||||
|
||||
fix:
|
||||
- (smalltalk) keyDown enter: prevent pass next
|
||||
|
||||
feature:
|
||||
- (package) add jscs
|
||||
- (package) add jshint support
|
||||
|
||||
|
||||
2015.09.24, v1.3.3
|
||||
|
||||
feature:
|
||||
- (smalltalk) header: add font-weight
|
||||
|
||||
|
||||
2015.09.24, v1.3.2
|
||||
|
||||
feature:
|
||||
- (smalltalk) h1 -> header
|
||||
- (smalltalk) .content-area: add max-width
|
||||
|
||||
|
||||
2015.09.23, v1.3.1
|
||||
|
||||
fix:
|
||||
- (smalltalk) changeButtonFocus: left, right, up, down do not work with confirm
|
||||
|
||||
|
||||
2015.09.23, v1.3.0
|
||||
|
||||
feature:
|
||||
- (smalltalk) add handling of keys: left, right, up, down
|
||||
|
||||
|
||||
2015.09.23, v1.2.0
|
||||
|
||||
feature:
|
||||
- (smalltalk) keyDown: add stopPropogation
|
||||
- (smalltalk) .smalltalk: rm background-color
|
||||
|
||||
|
||||
2015.09.22, v1.1.0
|
||||
|
||||
feature:
|
||||
- (package) scripts build: add build-poly
|
||||
- (smalltalk) add options {cancel}
|
||||
- (screen) add
|
||||
|
||||
21
modules/smalltalk/LICENSE
Normal file
21
modules/smalltalk/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 coderaiser
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
76
modules/smalltalk/README.md
Normal file
76
modules/smalltalk/README.md
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
Smalltalk [![License][LicenseIMGURL]][LicenseURL] [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL]
|
||||
====
|
||||
|
||||
Simple [Promise](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise)-based replacement of native Alert, Confirm and Prompt.
|
||||
|
||||
# Install
|
||||
With help of [bower](http://bower.io "Bower").
|
||||
|
||||
```
|
||||
bower install smalltalk
|
||||
```
|
||||
|
||||
Or npm:
|
||||
|
||||
```
|
||||
npm i smalltalk
|
||||
```
|
||||
|
||||
# API
|
||||
|
||||
In every method of `smalltalk` last parameter *options* is optional and could be used
|
||||
for preventing of handling cancel event.
|
||||
|
||||
```js
|
||||
{
|
||||
cancel: true /* default */
|
||||
}
|
||||
```
|
||||
|
||||
## smalltalk.alert(title, message [, options])
|
||||
|
||||

|
||||
|
||||
```js
|
||||
smalltalk.alert('Error', 'There was an error!').then(function() {
|
||||
console.log('ok');
|
||||
}, function() {
|
||||
console.log('cancel');
|
||||
});
|
||||
```
|
||||
|
||||
## smalltalk.confirm(title, message [, options])
|
||||
|
||||

|
||||
|
||||
```js
|
||||
smalltalk.confirm('Question', 'Are you sure?').then(function() {
|
||||
console.log('yes');
|
||||
}, function() {
|
||||
console.log('no');
|
||||
});
|
||||
```
|
||||
|
||||
## smalltalk.prompt(title, message, value [, options])
|
||||
|
||||

|
||||
|
||||
```js
|
||||
smalltalk.prompt('Question', 'How old are you?', '10').then(function(value) {
|
||||
console.log(value);
|
||||
}, function() {
|
||||
console.log('cancel');
|
||||
});
|
||||
```
|
||||
|
||||
#License
|
||||
MIT
|
||||
|
||||
[NPMIMGURL]: https://img.shields.io/npm/v/smalltalk.svg?style=flat
|
||||
[BuildStatusIMGURL]: https://img.shields.io/travis/coderaiser/smalltalk/master.svg?style=flat
|
||||
[DependencyStatusIMGURL]: https://img.shields.io/gemnasium/coderaiser/smalltalk.svg?style=flat
|
||||
[LicenseIMGURL]: https://img.shields.io/badge/license-MIT-317BF9.svg?style=flat
|
||||
[NPMURL]: https://npmjs.org/package/smalltalk "npm"
|
||||
[BuildStatusURL]: https://travis-ci.org/coderaiser/smalltalk "Build Status"
|
||||
[DependencyStatusURL]: https://gemnasium.com/coderaiser/smalltalk "Dependency Status"
|
||||
[LicenseURL]: https://tldrlegal.com/license/mit-license "MIT License"
|
||||
31
modules/smalltalk/bower.json
Normal file
31
modules/smalltalk/bower.json
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "smalltalk",
|
||||
"version": "1.5.0",
|
||||
"homepage": "https://github.com/coderaiser/smalltalk",
|
||||
"authors": [
|
||||
"coderaiser <mnemonic.enemy@gmail.com>"
|
||||
],
|
||||
"description": "Promise-based Alert, Confirm and Prompt replacement",
|
||||
"main": "dist/smalltalk.min.js",
|
||||
"moduleType": [
|
||||
"globals",
|
||||
"node"
|
||||
],
|
||||
"keywords": [
|
||||
"modal",
|
||||
"alert",
|
||||
"prompt",
|
||||
"confirm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"modules",
|
||||
"test",
|
||||
"tests",
|
||||
"screen"
|
||||
],
|
||||
"dependencies": {}
|
||||
}
|
||||
181
modules/smalltalk/css/smalltalk.css
Normal file
181
modules/smalltalk/css/smalltalk.css
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
.smalltalk {
|
||||
display: -webkit-flex;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
-webkit-transition: 200ms opacity;
|
||||
-moz-transition: 200ms opacity;
|
||||
-ms-transition: 200ms opacity;
|
||||
-o-transition: 200ms opacity;
|
||||
transition: 200ms opacity;
|
||||
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow: auto;
|
||||
padding: 20px;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.smalltalk .page {
|
||||
border-radius: 3px;
|
||||
background: white;
|
||||
box-shadow: 0 4px 23px 5px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0,0,0,0.15);
|
||||
color: #333;
|
||||
min-width: 400px;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 500px) {
|
||||
.smalltalk .page {
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.smalltalk .page > .close-button {
|
||||
background-image: url(../img/IDR_CLOSE_DIALOG.png);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
height: 14px;
|
||||
position: absolute;
|
||||
right: 7px;
|
||||
top: 7px;
|
||||
width: 14px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.smalltalk .page > .close-button:hover {
|
||||
background-image: url(../img/IDR_CLOSE_DIALOG_H.png);
|
||||
}
|
||||
|
||||
.smalltalk .page header {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
color: #333;
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 14px 17px 14px;
|
||||
text-shadow: white 0 1px 2px;
|
||||
}
|
||||
|
||||
.smalltalk .page .content-area {
|
||||
overflow: auto;
|
||||
padding: 6px 17px 6px;
|
||||
position: relative;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.smalltalk .page .action-area {
|
||||
padding: 14px 17px;
|
||||
}
|
||||
|
||||
.smalltalk .page .button-strip {
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display:flex;
|
||||
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.smalltalk .page .button-strip > button {
|
||||
-webkit-margin-start: 10px;
|
||||
-moz-margin-start: 10px;
|
||||
-ms-margin-start: 10px;
|
||||
}
|
||||
|
||||
.smalltalk button:enabled:focus, .smalltalk input:enabled:focus {
|
||||
-webkit-transition: border-color 200ms;
|
||||
-moz-transition: border-color 200ms;
|
||||
-ms-transition: border-color 200ms;
|
||||
-o-transition: border-color 200ms;
|
||||
transition: border-color 200ms;
|
||||
border-color: rgb(77, 144, 254);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.smalltalk button:enabled:active {
|
||||
background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);
|
||||
background-image: -moz-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);
|
||||
background-image: -ms-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);
|
||||
background-image: linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);
|
||||
|
||||
box-shadow: none;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.smalltalk button, .smalltalk .smalltalk {
|
||||
min-height: 2em;
|
||||
min-width: 4em;
|
||||
}
|
||||
|
||||
.smalltalk button::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.smalltalk button {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
-ms-appearance: none;
|
||||
appearance: none;
|
||||
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);
|
||||
background-image: -moz-linear-gradient(#ededed, #ededed 38%, #dedede);
|
||||
background-image: -ms-linear-gradient(#ededed, #ededed 38%, #dedede);
|
||||
background-image: linear-gradient(#ededed, #ededed 38%, #dedede);
|
||||
|
||||
border: 1px solid rgb(0, 0, 0);
|
||||
border: 1px solid rgba(0, 0, 0, 0.25);
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75);
|
||||
color: #444;
|
||||
font: inherit;
|
||||
margin: 0 1px 0 0;
|
||||
outline: none;
|
||||
text-shadow: 0 1px 0 rgb(240, 240, 240);
|
||||
}
|
||||
|
||||
.smalltalk button:enabled:focus, .smalltalk input:enabled:focus {
|
||||
-webkit-transition: border-color 200ms;
|
||||
-moz-transition: border-color 200ms;
|
||||
-ms-transition: border-color 200ms;
|
||||
-o-transition: border-color 200ms;
|
||||
transition: border-color 200ms;
|
||||
border-color: rgb(77, 144, 254);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.smalltalk input {
|
||||
width: 100%;
|
||||
border: 1px solid #bfbfbf;
|
||||
border-radius: 2px;
|
||||
box-sizing: border-box;
|
||||
color: #444;
|
||||
font: inherit;
|
||||
margin: 0;
|
||||
min-height: 2em;
|
||||
padding: 3px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
|
||||
button {
|
||||
font-family: Ubuntu, Arial, sans-serif;
|
||||
}
|
||||
1
modules/smalltalk/dist/smalltalk.min.css
vendored
Normal file
1
modules/smalltalk/dist/smalltalk.min.css
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.smalltalk{display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;align-items:center;flex-direction:column;justify-content:center;-webkit-transition:.2s opacity;-moz-transition:.2s opacity;-ms-transition:.2s opacity;-o-transition:.2s opacity;transition:.2s opacity;bottom:0;left:0;overflow:auto;padding:20px;position:fixed;right:0;top:0}.smalltalk .page{border-radius:3px;background:#fff;box-shadow:0 4px 23px 5px rgba(0,0,0,.2),0 2px 6px rgba(0,0,0,.15);color:#333;min-width:400px;padding:0;position:relative;z-index:0}@media only screen and (max-width:500px){.smalltalk .page{min-width:0}}.smalltalk .page>.close-button{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAQAAAC1QeVaAAAAUklEQVR4XqXPYQrAIAhAYW/gXd8NJxTopVqsGEhtf+L9/ERU2k/HSMFQpKcYJeNFI9Be0LCMij8cYyjj5EHIivGBkwLfrbX3IF8PqumVmnDpEG+eDsKibPG2JwAAAABJRU5ErkJggg==);background-position:center;background-repeat:no-repeat;height:14px;position:absolute;right:7px;top:7px;width:14px;z-index:1}.smalltalk .page>.close-button:hover{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAQAAAC1QeVaAAAAnUlEQVR4XoWQQQ6CQAxFewjkJkMCyXgJPMk7AiYczyBeZEAX6AKctGIaN+bt+trk9wtGQc/IkhnoKGxqqiWxOSZalapWFZ6VrIUDExsN0a5JRBq9LoVOR0eEQMoEhKizXhhsn0p1sCWVo7CwOf1RytPL8CPvwuBUoHL6ugeK30CVD1TqK7V/hdpe+VNChhOzV8xWny/+xosHF8578W/Hmc1OOC3wmwAAAABJRU5ErkJggg==)}.smalltalk .page header{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#333;font-size:120%;font-weight:700;margin:0;padding:14px 17px;text-shadow:#fff 0 1px 2px}.smalltalk .page .content-area{overflow:auto;padding:6px 17px;position:relative;max-width:500px}.smalltalk .page .action-area{padding:14px 17px}.smalltalk .page .button-strip{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:flex;flex-direction:row;justify-content:flex-end}.smalltalk .page .button-strip>button{-webkit-margin-start:10px;-moz-margin-start:10px;-ms-margin-start:10px}.smalltalk button:enabled:active{background-image:-webkit-linear-gradient(#e7e7e7,#e7e7e7 38%,#d7d7d7);background-image:-moz-linear-gradient(#e7e7e7,#e7e7e7 38%,#d7d7d7);background-image:-ms-linear-gradient(#e7e7e7,#e7e7e7 38%,#d7d7d7);background-image:linear-gradient(#e7e7e7,#e7e7e7 38%,#d7d7d7);box-shadow:none;text-shadow:none}.smalltalk .smalltalk,.smalltalk button{min-height:2em;min-width:4em}.smalltalk button::-moz-focus-inner{border:0}.smalltalk button{-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:-webkit-linear-gradient(#ededed,#ededed 38%,#dedede);background-image:-moz-linear-gradient(#ededed,#ededed 38%,#dedede);background-image:-ms-linear-gradient(#ededed,#ededed 38%,#dedede);background-image:linear-gradient(#ededed,#ededed 38%,#dedede);border:1px solid #000;border:1px solid rgba(0,0,0,.25);border-radius:2px;box-shadow:0 1px 0 rgba(0,0,0,.08),inset 0 1px 2px rgba(255,255,255,.75);color:#444;font:inherit;margin:0 1px 0 0;outline:0;text-shadow:0 1px 0 #f0f0f0}.smalltalk button:enabled:focus,.smalltalk input:enabled:focus{-webkit-transition:border-color .2s;-moz-transition:border-color .2s;-ms-transition:border-color .2s;-o-transition:border-color .2s;transition:border-color .2s;border-color:#4d90fe;outline:0}.smalltalk input{width:100%;border:1px solid #bfbfbf;border-radius:2px;box-sizing:border-box;color:#444;font:inherit;margin:0;min-height:2em;padding:3px;outline:0}button{font-family:Ubuntu,Arial,sans-serif}
|
||||
1
modules/smalltalk/dist/smalltalk.min.js
vendored
Normal file
1
modules/smalltalk/dist/smalltalk.min.js
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
"use strict";!function(n){function t(n){function e(n,t,e,r){if(!Array.isArray(r))throw Error("buttons should be array!");return'<div class="page">\n <div data-name="js-close" class="close-button"></div>\n <header>'+n+'</header>\n <div class="content-area">\n '+t+"\n "+e+'\n </div>\n <div class="action-area">\n <div class="button-strip"> '+r.map(function(n,t){return"<button tabindex="+t+' data-name="js-'+n.toLowerCase()+'">'+n+"</button>"}).join("")+"\n </div>\n </div>\n </div>"}function r(n,t,r,o,u){var c=document.createElement("div"),s=["cancel","close","ok"],d=void 0,v=void 0,m=new Promise(function(n,t){var e=u&&!u.cancel,r=function(){};d=n,v=t,e&&(v=r)}),p=e(n,t,r,o);return c.innerHTML=p,c.className="smalltalk",document.body.appendChild(c),l(c,["ok"]).forEach(function(n){return n.focus()}),l(c,["input"]).forEach(function(n){return n.setSelectionRange(0,r.length)}),f("click",c,s,function(n){return i(n.target,c,d,v)}),["click","contextmenu"].forEach(function(n){return c.addEventListener(n,function(){return l(c,["ok","input"]).forEach(function(n){return n.focus()})})}),c.addEventListener("keydown",a(c,d,v)),m}function a(n,t,e){return function(r){var a={ENTER:13,ESC:27,TAB:9,LEFT:37,UP:38,RIGHT:39,DOWN:40},f=r.keyCode,s=r.target,d=["ok","cancel","input"],m=l(n,d).map(function(n){return o(n)});switch(f){case a.ENTER:i(s,n,t,e),r.preventDefault();break;case a.ESC:v(),e();break;case a.TAB:r.shiftKey&&c(n,m),c(n,m),r.preventDefault();break;default:var p=["left","right","up","down"].some(function(n){return f===a[n.toUpperCase()]});p&&u(n,m)}r.stopPropagation()}}function o(n){return n.getAttribute("data-name").replace("js-","")}function u(n,t){var e="",r=document.activeElement,a=o(r),u=/ok|cancel/.test(a),c=t.length-1;c&&u&&(e="cancel"===a?"ok":"cancel",l(n,[e]).forEach(function(n){return n.focus()}))}function c(n,t){var e=document.activeElement,r=o(e),a=t.length-1,u=t.indexOf(r);u===a?u=0:a>u&&++u;var c=t[u];l(n,[c]).forEach(function(n){return n.focus()})}function i(n,t,e,r){var a=void 0,o=n.getAttribute("data-name").replace("js-","");/close|cancel/.test(o)?r():(a=l(t,["input"]).reduce(function(n,t){return t.value},null),e(a)),v()}function l(n,t){var e=t.map(function(t){return n.querySelector('[data-name="js-'+t+'"]')}).filter(function(n){return n});return e}function f(n,t,e,r){l(t,e).forEach(function(t){return t.addEventListener(n,function(n){return r(n)})})}function s(n){var t=document.querySelector(n);t.parentElement.removeChild(t)}function d(n){var t=[].slice.call(arguments,1);return n.bind(null,t)}if(!(this instanceof t))return new t(n);var v=d(s,".smalltalk"),m=["OK"],p=["OK","Cancel"];this.alert=function(n,t,e){return r(n,t,"",m,e)},this.prompt=function(n,t,e,a){var o=e||"",u='<input type="text" value="'+o+'" data-name="js-input">';return r(n,t,u,p,a)},this.confirm=function(n,t,e){return r(n,t,"",p,e)}}"undefined"!=typeof module&&module.exports?module.exports=t():n.smalltalk=t()}("undefined"!=typeof window&&window);
|
||||
1
modules/smalltalk/dist/smalltalk.native.min.js
vendored
Normal file
1
modules/smalltalk/dist/smalltalk.native.min.js
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
!function(n){"use strict";function t(){return this instanceof t?(this.alert=function(n,t){var e=new Promise(function(n){alert(t),n()});return e},this.prompt=function(n,t,e,r){var o=r,i=new Promise(function(n,r){var i=o&&!o.cancel,u=prompt(t,e);null!==u?n(u):i||r()});return i},void(this.confirm=function(n,t,e){var r=e,o=r&&!r.noCancel,i=new Promise(function(n,e){var r=confirm(t);r?n():o||e()});return i})):new t}"undefined"!=typeof module&&module.exports?module.exports=t():n.smalltalk=t()}(this);
|
||||
2
modules/smalltalk/dist/smalltalk.poly.min.js
vendored
Normal file
2
modules/smalltalk/dist/smalltalk.poly.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
15
modules/smalltalk/example/index.html
Normal file
15
modules/smalltalk/example/index.html
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<link rel="stylesheet" href="../css/smalltalk.css">
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport">
|
||||
|
||||
<script src="../src/smalltalk.js"></script>
|
||||
<script>
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
smalltalk.prompt('hello', 'world', '2+2').then(function(value) {
|
||||
console.log(value);
|
||||
}, function() {
|
||||
console.log('close');
|
||||
})
|
||||
});
|
||||
|
||||
</script>
|
||||
BIN
modules/smalltalk/img/IDR_CLOSE_DIALOG.png
Normal file
BIN
modules/smalltalk/img/IDR_CLOSE_DIALOG.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 139 B |
BIN
modules/smalltalk/img/IDR_CLOSE_DIALOG_H.png
Normal file
BIN
modules/smalltalk/img/IDR_CLOSE_DIALOG_H.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 214 B |
219
modules/smalltalk/lib/smalltalk.js
Normal file
219
modules/smalltalk/lib/smalltalk.js
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
'use strict';
|
||||
|
||||
(function (global) {
|
||||
'use strict';
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) module.exports = SmallTalk();else global.smalltalk = SmallTalk();
|
||||
|
||||
function SmallTalk(callback) {
|
||||
if (!(this instanceof SmallTalk)) return new SmallTalk(callback);
|
||||
|
||||
var remove = bind(removeEl, '.smalltalk');
|
||||
|
||||
var BUTTON_OK = ['OK'];
|
||||
var BUTTON_OK_CANCEL = ['OK', 'Cancel'];
|
||||
|
||||
this.alert = function (title, msg, options) {
|
||||
return showDialog(title, msg, '', BUTTON_OK, options);
|
||||
};
|
||||
|
||||
this.prompt = function (title, msg, value, options) {
|
||||
var val = value || '';
|
||||
var valueStr = '<input type="text" value="' + val + '" data-name="js-input">';
|
||||
|
||||
return showDialog(title, msg, valueStr, BUTTON_OK_CANCEL, options);
|
||||
};
|
||||
|
||||
this.confirm = function (title, msg, options) {
|
||||
return showDialog(title, msg, '', BUTTON_OK_CANCEL, options);
|
||||
};
|
||||
|
||||
function getTemplate(title, msg, value, buttons) {
|
||||
if (!Array.isArray(buttons)) throw Error('buttons should be array!');
|
||||
|
||||
return '<div class="page">\n <div data-name="js-close" class="close-button"></div>\n <header>' + title + '</header>\n <div class="content-area">\n ' + msg + '\n ' + value + '\n </div>\n <div class="action-area">\n <div class="button-strip"> ' + buttons.map(function (name, i) {
|
||||
return '<button tabindex=' + i + ' data-name="js-' + name.toLowerCase() + '">' + name + '</button>';
|
||||
}).join('') + '\n </div>\n </div>\n </div>';
|
||||
}
|
||||
|
||||
function showDialog(title, msg, value, buttons, options) {
|
||||
var dialog = document.createElement('div'),
|
||||
closeButtons = ['cancel', 'close', 'ok'],
|
||||
ok = undefined,
|
||||
cancel = undefined,
|
||||
promise = new Promise(function (resolve, reject) {
|
||||
var noCancel = options && !options.cancel;
|
||||
var empty = function empty() {};
|
||||
|
||||
ok = resolve;
|
||||
cancel = reject;
|
||||
|
||||
if (noCancel) cancel = empty;
|
||||
}),
|
||||
tmpl = getTemplate(title, msg, value, buttons);
|
||||
|
||||
dialog.innerHTML = tmpl;
|
||||
dialog.className = 'smalltalk';
|
||||
|
||||
document.body.appendChild(dialog);
|
||||
|
||||
find(dialog, ['ok']).forEach(function (el) {
|
||||
return el.focus();
|
||||
});
|
||||
|
||||
find(dialog, ['input']).forEach(function (el) {
|
||||
return el.setSelectionRange(0, value.length);
|
||||
});
|
||||
|
||||
addListeterAll('click', dialog, closeButtons, function (event) {
|
||||
return closeDialog(event.target, dialog, ok, cancel);
|
||||
});
|
||||
|
||||
['click', 'contextmenu'].forEach(function (event) {
|
||||
return dialog.addEventListener(event, function () {
|
||||
return find(dialog, ['ok', 'input']).forEach(function (el) {
|
||||
return el.focus();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
dialog.addEventListener('keydown', keyDown(dialog, ok, cancel));
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function keyDown(dialog, ok, cancel) {
|
||||
return function (event) {
|
||||
var KEY = {
|
||||
ENTER: 13,
|
||||
ESC: 27,
|
||||
TAB: 9,
|
||||
LEFT: 37,
|
||||
UP: 38,
|
||||
RIGHT: 39,
|
||||
DOWN: 40
|
||||
};
|
||||
|
||||
var keyCode = event.keyCode,
|
||||
el = event.target;
|
||||
|
||||
var namesAll = ['ok', 'cancel', 'input'],
|
||||
names = find(dialog, namesAll).map(function (el) {
|
||||
return getDataName(el);
|
||||
});
|
||||
|
||||
switch (keyCode) {
|
||||
case KEY.ENTER:
|
||||
closeDialog(el, dialog, ok, cancel);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.ESC:
|
||||
remove();
|
||||
cancel();
|
||||
break;
|
||||
|
||||
case KEY.TAB:
|
||||
if (event.shiftKey) tab(dialog, names);
|
||||
|
||||
tab(dialog, names);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
default:
|
||||
var is = ['left', 'right', 'up', 'down'].some(function (name) {
|
||||
return keyCode === KEY[name.toUpperCase()];
|
||||
});
|
||||
|
||||
if (is) changeButtonFocus(dialog, names);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
};
|
||||
}
|
||||
|
||||
function getDataName(el) {
|
||||
return el.getAttribute('data-name').replace('js-', '');
|
||||
}
|
||||
|
||||
function changeButtonFocus(dialog, names) {
|
||||
var name = '',
|
||||
active = document.activeElement,
|
||||
activeName = getDataName(active),
|
||||
isButton = /ok|cancel/.test(activeName),
|
||||
count = names.length - 1;
|
||||
|
||||
if (count && isButton) {
|
||||
if (activeName === 'cancel') name = 'ok';else name = 'cancel';
|
||||
|
||||
find(dialog, [name]).forEach(function (el) {
|
||||
return el.focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function tab(dialog, names) {
|
||||
var active = document.activeElement,
|
||||
activeName = getDataName(active),
|
||||
count = names.length - 1,
|
||||
index = names.indexOf(activeName);
|
||||
|
||||
if (index === count) index = 0;else if (index < count) ++index;
|
||||
|
||||
var name = names[index];
|
||||
|
||||
find(dialog, [name]).forEach(function (el) {
|
||||
return el.focus();
|
||||
});
|
||||
}
|
||||
|
||||
function closeDialog(el, dialog, ok, cancel) {
|
||||
var value = undefined,
|
||||
name = el.getAttribute('data-name').replace('js-', '');
|
||||
|
||||
if (/close|cancel/.test(name)) {
|
||||
cancel();
|
||||
} else {
|
||||
value = find(dialog, ['input']).reduce(function (value, el) {
|
||||
return el.value;
|
||||
}, null);
|
||||
|
||||
ok(value);
|
||||
}
|
||||
|
||||
remove();
|
||||
}
|
||||
|
||||
function find(element, names) {
|
||||
var elements = names.map(function (name) {
|
||||
return element.querySelector('[data-name="js-' + name + '"]');
|
||||
}).filter(function (el) {
|
||||
return el;
|
||||
});
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
function addListeterAll(event, parent, elements, fn) {
|
||||
find(parent, elements).forEach(function (el) {
|
||||
return el.addEventListener(event, function (event) {
|
||||
return fn(event);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function removeEl(name) {
|
||||
var el = document.querySelector(name);
|
||||
|
||||
el.parentElement.removeChild(el);
|
||||
}
|
||||
|
||||
function bind(fn) {
|
||||
var args = [].slice.call(arguments, 1);
|
||||
|
||||
return fn.bind(null, args);
|
||||
}
|
||||
}
|
||||
})(typeof window !== 'undefined' && window);
|
||||
54
modules/smalltalk/lib/smalltalk.native.js
Normal file
54
modules/smalltalk/lib/smalltalk.native.js
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
(function(global) {
|
||||
'use strict';
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports)
|
||||
module.exports = Smalltalk();
|
||||
else
|
||||
global.smalltalk = Smalltalk();
|
||||
|
||||
|
||||
function Smalltalk() {
|
||||
if (!(this instanceof Smalltalk))
|
||||
return new Smalltalk();
|
||||
|
||||
this.alert = function(title, message) {
|
||||
var promise = new Promise(function(resolve) {
|
||||
alert(message);
|
||||
resolve();
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
this.prompt = function(title, message, value, options) {
|
||||
var o = options,
|
||||
promise = new Promise(function(resolve, reject) {
|
||||
var noCancel = o && !o.cancel,
|
||||
result = prompt(message, value);
|
||||
|
||||
if (result !== null)
|
||||
resolve(result);
|
||||
else if (!noCancel)
|
||||
reject();
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
this.confirm = function(title, message, options) {
|
||||
var o = options,
|
||||
noCancel = o && !o.noCancel,
|
||||
promise = new Promise(function(resolve, reject) {
|
||||
var is = confirm(message);
|
||||
|
||||
if (is)
|
||||
resolve();
|
||||
else if (!noCancel)
|
||||
reject();
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
}
|
||||
|
||||
})(this);
|
||||
47
modules/smalltalk/package.json
Normal file
47
modules/smalltalk/package.json
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"name": "smalltalk",
|
||||
"version": "1.5.0",
|
||||
"description": "Promise-based Alert, Confirm and Prompt replacement",
|
||||
"homepage": "http://github.com/coderaiser/smalltalk",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/coderaiser/smalltalk.git"
|
||||
},
|
||||
"main": "dist/smalltalk.min.js",
|
||||
"scripts": {
|
||||
"watch": "watch 'npm run 6to5' dist",
|
||||
"6to5": "babel -d lib src",
|
||||
"build-css": "minify css/smalltalk.css > dist/smalltalk.min.css",
|
||||
"build-js": "npm run 6to5 && minify lib/smalltalk.js > dist/smalltalk.min.js",
|
||||
"build-js-native": "minify lib/smalltalk.native.js > dist/smalltalk.native.min.js",
|
||||
"build-poly": "cat node_modules/promise-polyfill/Promise.min.js dist/smalltalk.min.js > dist/smalltalk.poly.min.js",
|
||||
"build-poly-native": "cat node_modules/promise-polyfill/Promise.min.js dist/smalltalk.native.min.js > dist/smalltalk.native.poly.min.js",
|
||||
"build-js-full": "npm run build-js && npm run build-poly",
|
||||
"build-native-full": "npm run build-js-native && npm run build-js-native",
|
||||
"build": "npm run build-css && npm run build-js-full && npm run build-native-full",
|
||||
"bower": "bower",
|
||||
"babel": "babel",
|
||||
"minify": "minify",
|
||||
"wisdom": "npm run build",
|
||||
"test": "jshint src && jscs --esnext src"
|
||||
},
|
||||
"keywords": [
|
||||
"modal",
|
||||
"alert",
|
||||
"confirm",
|
||||
"prompt"
|
||||
],
|
||||
"author": "coderaiser <mnemonic.enemy@gmail.com> (http://coderaiser.github.io/)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/coderaiser/smalltalk/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "~5.8.23",
|
||||
"jscs": "~2.1.1",
|
||||
"jshint": "~2.8.0",
|
||||
"minify": "~1.4.20",
|
||||
"promise-polyfill": "^2.1.0",
|
||||
"watch": "~0.16.0"
|
||||
}
|
||||
}
|
||||
257
modules/smalltalk/src/smalltalk.js
Normal file
257
modules/smalltalk/src/smalltalk.js
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
(function(global) {
|
||||
'use strict';
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports)
|
||||
module.exports = SmallTalk();
|
||||
else
|
||||
global.smalltalk = SmallTalk();
|
||||
|
||||
function SmallTalk(callback) {
|
||||
if (!(this instanceof SmallTalk))
|
||||
return new SmallTalk(callback);
|
||||
|
||||
let remove = bind(removeEl, '.smalltalk');
|
||||
|
||||
const BUTTON_OK = ['OK'];
|
||||
const BUTTON_OK_CANCEL = ['OK', 'Cancel'];
|
||||
|
||||
this.alert = (title, msg, options) => {
|
||||
return showDialog(title, msg, '', BUTTON_OK, options);
|
||||
};
|
||||
|
||||
this.prompt = (title, msg, value, options) => {
|
||||
let val = value || '';
|
||||
let valueStr = `<input type="text" value="${ val }" data-name="js-input">`;
|
||||
|
||||
return showDialog(title, msg, valueStr, BUTTON_OK_CANCEL, options);
|
||||
};
|
||||
|
||||
this.confirm = (title, msg, options) => {
|
||||
return showDialog(title, msg, '', BUTTON_OK_CANCEL, options);
|
||||
};
|
||||
|
||||
function getTemplate(title, msg, value, buttons) {
|
||||
if (!Array.isArray(buttons))
|
||||
throw Error('buttons should be array!');
|
||||
|
||||
return `<div class="page">
|
||||
<div data-name="js-close" class="close-button"></div>
|
||||
<header>${ title }</header>
|
||||
<div class="content-area">
|
||||
${ msg }
|
||||
${ value }
|
||||
</div>
|
||||
<div class="action-area">
|
||||
<div class="button-strip"> ${
|
||||
buttons.map((name, i) =>
|
||||
`<button tabindex=${ i } data-name="js-${ name.toLowerCase() }">${ name }</button>`
|
||||
).join('')
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function showDialog(title, msg, value, buttons, options) {
|
||||
let dialog = document.createElement('div'),
|
||||
|
||||
closeButtons = [
|
||||
'cancel',
|
||||
'close',
|
||||
'ok'
|
||||
],
|
||||
|
||||
ok, cancel,
|
||||
|
||||
promise = new Promise((resolve, reject) => {
|
||||
let noCancel = options && !options.cancel;
|
||||
let empty = () => {};
|
||||
|
||||
ok = resolve;
|
||||
cancel = reject;
|
||||
|
||||
if (noCancel)
|
||||
cancel = empty;
|
||||
}),
|
||||
|
||||
tmpl = getTemplate(title, msg, value, buttons);
|
||||
|
||||
dialog.innerHTML = tmpl;
|
||||
dialog.className = 'smalltalk';
|
||||
|
||||
document.body.appendChild(dialog);
|
||||
|
||||
find(dialog, ['ok']).forEach(el =>
|
||||
el.focus()
|
||||
);
|
||||
|
||||
find(dialog, ['input']).forEach(el =>
|
||||
el.setSelectionRange(0, value.length)
|
||||
);
|
||||
|
||||
addListeterAll('click', dialog, closeButtons, event =>
|
||||
closeDialog(event.target, dialog, ok, cancel)
|
||||
);
|
||||
|
||||
['click', 'contextmenu'].forEach(event =>
|
||||
dialog.addEventListener(event, () =>
|
||||
find(dialog, ['ok', 'input']).forEach(el =>
|
||||
el.focus()
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
dialog.addEventListener('keydown', keyDown(dialog, ok, cancel));
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function keyDown(dialog, ok, cancel) {
|
||||
return event => {
|
||||
const KEY = {
|
||||
ENTER : 13,
|
||||
ESC : 27,
|
||||
TAB : 9,
|
||||
LEFT : 37,
|
||||
UP : 38,
|
||||
RIGHT : 39,
|
||||
DOWN : 40
|
||||
};
|
||||
|
||||
let keyCode = event.keyCode,
|
||||
el = event.target;
|
||||
|
||||
let namesAll = ['ok', 'cancel', 'input'],
|
||||
names = find(dialog, namesAll).map(el =>
|
||||
getDataName(el)
|
||||
);
|
||||
|
||||
switch(keyCode) {
|
||||
case KEY.ENTER:
|
||||
closeDialog(el, dialog, ok, cancel);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.ESC:
|
||||
remove();
|
||||
cancel();
|
||||
break;
|
||||
|
||||
case KEY.TAB:
|
||||
if (event.shiftKey)
|
||||
tab(dialog, names);
|
||||
|
||||
tab(dialog, names);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
default:
|
||||
let is = ['left', 'right', 'up', 'down'].some(name =>
|
||||
keyCode === KEY[name.toUpperCase()]
|
||||
);
|
||||
|
||||
if (is)
|
||||
changeButtonFocus(dialog, names);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
};
|
||||
}
|
||||
|
||||
function getDataName(el) {
|
||||
return el
|
||||
.getAttribute('data-name')
|
||||
.replace('js-', '');
|
||||
}
|
||||
|
||||
function changeButtonFocus(dialog, names) {
|
||||
let name = '',
|
||||
active = document.activeElement,
|
||||
activeName = getDataName(active),
|
||||
isButton = /ok|cancel/.test(activeName),
|
||||
count = names.length - 1;
|
||||
|
||||
if (count && isButton) {
|
||||
if (activeName === 'cancel')
|
||||
name = 'ok';
|
||||
else
|
||||
name = 'cancel';
|
||||
|
||||
find(dialog, [name]).forEach(el =>
|
||||
el.focus()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function tab(dialog, names) {
|
||||
let active = document.activeElement,
|
||||
activeName = getDataName(active),
|
||||
|
||||
count = names.length - 1,
|
||||
index = names.indexOf(activeName);
|
||||
|
||||
if (index === count)
|
||||
index = 0;
|
||||
else if (index < count)
|
||||
++index;
|
||||
|
||||
let name = names[index];
|
||||
|
||||
find(dialog, [name]).forEach(el =>
|
||||
el.focus()
|
||||
);
|
||||
}
|
||||
|
||||
function closeDialog(el, dialog, ok, cancel) {
|
||||
let value,
|
||||
name = el
|
||||
.getAttribute('data-name')
|
||||
.replace('js-', '');
|
||||
|
||||
if (/close|cancel/.test(name)) {
|
||||
cancel();
|
||||
} else {
|
||||
value = find(dialog, ['input']).reduce((value, el) => {
|
||||
return el.value;
|
||||
}, null);
|
||||
|
||||
ok(value);
|
||||
}
|
||||
|
||||
remove();
|
||||
}
|
||||
|
||||
function find(element, names) {
|
||||
let elements = names.map(name =>
|
||||
element.querySelector(`[data-name="js-${ name }"]`)
|
||||
).filter(el =>
|
||||
el
|
||||
);
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
function addListeterAll(event, parent, elements, fn) {
|
||||
find(parent, elements).forEach(el =>
|
||||
el.addEventListener(event, event =>
|
||||
fn(event)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function removeEl(name) {
|
||||
var el = document.querySelector(name);
|
||||
|
||||
el.parentElement.removeChild(el);
|
||||
}
|
||||
|
||||
function bind(fn) {
|
||||
var args = [].slice.call(arguments, 1);
|
||||
|
||||
return fn.bind(null, args);
|
||||
}
|
||||
}
|
||||
|
||||
})(typeof window !== 'undefined' && window);
|
||||
|
|
@ -127,4 +127,10 @@
|
|||
Progress
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label>
|
||||
<input data-name="js-htmlDialogs" type="checkbox" {{ htmlDialogs }}>
|
||||
HTML Dialogs
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue