implemented dispatcher commands

This commit is contained in:
Borys Levytskyi
2015-04-03 18:55:39 +03:00
parent d301d0c317
commit 8e5be22fe3
6 changed files with 136 additions and 54 deletions

View File

@@ -1,8 +1,11 @@
(function() {
var twoOperandsRegex = /^(\d+)(<<|>>|\||\&|\^)(\d+)$/;
var twoOperandsRegex = /^(\d+)\s*(<<|>>|\||\&|\^)\s*(\d+)$/;
var numbersList = /^((\d*)+\s?)+$/;
app.service('expression', {
canParse: function(string) {
return twoOperandsRegex.test(string) || numbersList.test(string);
},
parse: function(string) {
var trimmed = string.replace(/^\s+|\s+$/, '');
var matches = twoOperandsRegex.exec(trimmed);

View File

@@ -1,4 +1,4 @@
(function(app){
(function(app, is){
app.controller('expressionInputCtrl', {
$dispatcher:null,
@@ -25,9 +25,8 @@
onViewAttached: function(el) {
var r = 1;
},
display: function (input, model) {
var result = new app.models.DisplayResult(input, model);
var view = app.buildViewFor(result);
display: function ( model) {
var view = app.buildViewFor(model);
var vw = this.viewElement;
if(vw.childNodes.length == 0) {
@@ -41,4 +40,4 @@
app.controller('resultViewCtrl', app.service('resultView'));
})(window.app);
})(window.app, window.is);

View File

@@ -1,11 +1,88 @@
(function(app){
(function(app, is){
var handlers = [];
var dispatcher = {
dispatch: function(input) {
app.command('dispatchInput').execute({input:input});
$resultView:null,
debug:true,
dispatch: function(rawInput) {
var input = rawInput.trim();
var handler = this.findHandler(input);
if(handler != null) {
if(this.debug) {
this.invokeHandler(input, handler);
} else {
try {
this.invokeHandler(input, handler);
} catch (e) {
this.displayCommandError(input, "Error: " + e);
}
}
}
else {
this.displayCommandError(input, "Unknown expression: " + input.trim());
}
// app.command('dispatchInput').execute({input:input});
},
command: function(cmd, handler) {
var h = this.createHandler(cmd, handler);
if(h == null){
console.warn('unexpected set of arguments: ', Array.prototype.splice.call(arguments));
return;
}
if(!is.aFunction(h.canHandle)) {
console.warn('handler is missing "canHandle" function. registration denied.');
return;
}
if(!is.aFunction(h.handle)) {
console.warn('handler is missing "handle" function. registration denied.');
return;
}
app.di.resolveProperties(h);
handlers.push(h);
},
createHandler: function(cmd, handler) {
if(is.plainObject(cmd)) {
return cmd;
}
if(is.string(cmd)) {
return { canHandle: function (input) { return input === cmd; }, handle: handler };
}
return null;
},
findHandler: function (input) {
var i= 0, h;
for(i;i<handlers.length; i++) {
if(handlers[i].canHandle(input)) {
return handlers[i];
}
}
},
invokeHandler: function (input, handler) {
var cmdResult = handler.handle(input);
if(cmdResult != null) {
var r = new app.models.DisplayResult(input, cmdResult);
this.$resultView.display(r);
}
},
displayCommandError: function (input, message) {
var error = new app.models.ErrorResult(message);
this.$resultView.display(new app.models.DisplayResult(input, error));
}
};
dispatcher.command('clear', function() {
app.get('resultView').clear();
});
app.service('dispatcher', dispatcher);
})(window.app);
})(window.app, window.is);

View File

@@ -39,6 +39,9 @@
};
HtmlBuilder.createElement = function(template, model) {
should.beString(template, "template")
var regex = /(?:{([^}]+)})/g, html;
if(model == null){
@@ -70,6 +73,12 @@
}
HtmlBuilder.escapeHtml = function(html) {
if(html == null) {
return html;
}
should.beString(html);
return html
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")

27
components/is.js Normal file
View File

@@ -0,0 +1,27 @@
(function(){
window.is = {
plainObject: function(obj) {
return typeof obj == "object" && obj instanceof Object;
},
aFunction: function (obj) {
return typeof obj == "function";
},
string: function (obj) {
return typeof obj == "string";
},
regex: function (obj) {
return typeof obj == "object" && this.constructedFrom(RegExp);
},
constructedFrom: function (obj, ctor) {
return obj instanceof ctor;
},
htmlElement: function(obj) {
return obj instanceof HtmlElement;
}
};
})();

View File

@@ -7,6 +7,7 @@
<script type="text/javascript" src="components/bindr.js"></script>
<script type="text/javascript" src="components/commandr.js"></script>
<script type="text/javascript" src="components/is.js"></script>
<script type="text/javascript" src="components/should.js"></script>
<script type="text/javascript" src="components/htmlBuilder.js"></script>
<script type="text/javascript" src="components/container.js"></script>
@@ -38,58 +39,24 @@
(function(){
var app = window.app;
var html = app.service('html');
var resultView = app.service('resultView');
// Expression
app.command('dispatchInput', {
$expression: null,
$resultView: null,
execute:function(cmdArgs) {
var expr = this.$expression.parse(cmdArgs.input);
if(expr == null) {
return;
}
this.$resultView.display(cmdArgs.input, expr);
cmdArgs.commandHandled = true;
}
});
// Help
app.command('dispatchInput', function(cmdArgs){
if(cmdArgs.input.toLowerCase() !== 'help') {
return;
}
var dispatcher = app.get('dispatcher');
dispatcher.command('help', function() {
var commands = [
{ name: '1>>2', description: 'Displays result of expression'},
{ name: 'help', description: 'Displays help'},
{ name: 'clear', description: 'Clears console'}
];
var model = new app.models.HelpResult(commands);
resultView.display(cmdArgs.input, model);
cmdArgs.commandHandled = true;
return new app.models.HelpResult(commands);
});
// Clear
app.command('dispatchInput', function(cmdArgs){
if(cmdArgs.input.toLowerCase() !== 'clear') {
return;
}
resultView.clear();
cmdArgs.commandHandled = true;
});
// Unknown Expression
app.command('dispatchInput', function(cmdArgs){
cmdArgs.commandHandled = true;
resultView.display(cmdArgs.input, new app.models.ErrorResult("Unknown expression: " + cmdArgs.input))
dispatcher.command({
$expression:null,
canHandle: function(input) { return this.$expression.canParse(input); },
handle: function(input) {
return this.$expression.parse(input);
}
});
app.bootstrap(document.getElementById('rootView'));