From 77600d3dde3257ee4f3a46694d2ec7085d8cee4b Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Tue, 14 Apr 2015 00:19:14 -0600 Subject: [PATCH] * Fix EtherTerm backspace key * Better WIP apply art / module * Better WIP 'enter' and 'leave' events from VC --- core/ansi_term.js | 26 ++++++--- core/view.js | 41 +++++++++---- core/view_controller.js | 26 +++++++-- mods/apply.js | 73 ++++++++++++++---------- mods/art/themes/NU-MAYA/APPLY1.ANS | Bin 0 -> 3954 bytes mods/art/themes/NU-MAYA/theme_info.json | 5 +- mods/login.js | 2 +- mods/matrix.js | 2 +- mods/menu.json | 33 ++++++++++- mods/standard_menu.js | 2 +- 10 files changed, 150 insertions(+), 60 deletions(-) create mode 100644 mods/art/themes/NU-MAYA/APPLY1.ANS diff --git a/core/ansi_term.js b/core/ansi_term.js index d69cf1e1..671f041c 100644 --- a/core/ansi_term.js +++ b/core/ansi_term.js @@ -14,6 +14,8 @@ var assert = require('assert'); var binary = require('binary'); var miscUtil = require('./misc_util.js'); +exports.getFGColorValue = getFGColorValue; +exports.getBGColorValue = getBGColorValue; exports.sgr = sgr; exports.clearScreen = clearScreen; exports.resetScreen = resetScreen; @@ -69,7 +71,7 @@ var CONTROL = { // Select Graphics Rendition // See http://cvs.synchro.net/cgi-bin/viewcvs.cgi/*checkout*/src/conio/cterm.txt // -var SGR = { +var SGRValues = { reset : 0, bold : 1, dim : 2, @@ -96,11 +98,21 @@ var SGR = { greenBG : 42, yellowBG : 43, blueBG : 44, - magentaBG : 45, + cyanBG : 47, whiteBG : 47, }; +function getFGColorValue(name) { + return SGRValues[name]; +} + +function getBGColorValue(name) { + return SGRValues[name + 'BG']; +} + + + // See http://cvs.synchro.net/cgi-bin/viewcvs.cgi/*checkout*/src/conio/cterm.txt // :TODO: document var SYNC_TERM_FONTS = [ @@ -162,8 +174,8 @@ Object.keys(CONTROL).forEach(function onControlName(name) { }); // Create various color methods such as white(), yellowBG(), reset(), ... -Object.keys(SGR).forEach(function onSgrName(name) { - var code = SGR[name]; +Object.keys(SGRValues).forEach(function onSgrName(name) { + var code = SGRValues[name]; exports[name] = function() { return ESC_CSI + code + 'm'; @@ -173,7 +185,7 @@ Object.keys(SGR).forEach(function onSgrName(name) { function sgr() { // // - Allow an single array or variable number of arguments - // - Each element can be either a integer or string found in SGR + // - Each element can be either a integer or string found in SGRValues // which in turn maps to a integer // if(arguments.length <= 0) { @@ -187,11 +199,11 @@ function sgr() { var args = Array.isArray(arguments[0]) ? arguments[0] : arguments; for(var i = 0; i < args.length; i++) { if(typeof args[i] === 'string') { - if(args[i] in SGR) { + if(args[i] in SGRValues) { if(result.length > 0) { result += ';'; } - result += SGR[args[i]]; + result += SGRValues[args[i]]; } } else if(typeof args[i] === 'number') { if(result.length > 0) { diff --git a/core/view.js b/core/view.js index 71d9c556..d4d5c7bc 100644 --- a/core/view.js +++ b/core/view.js @@ -13,7 +13,7 @@ exports.VIEW_SPECIAL_KEY_MAP_DEFAULT = VIEW_SPECIAL_KEY_MAP_DEFAULT; var VIEW_SPECIAL_KEY_MAP_DEFAULT = { accept : [ 'enter' ], exit : [ 'esc' ], - backspace : [ 'backspace' ], + backspace : [ 'backspace', 'del' ], del : [ 'del' ], next : [ 'tab' ], up : [ 'up arrow' ], @@ -89,6 +89,10 @@ View.prototype.setId = function(id) { this.id = id; }; +View.prototype.getId = function() { + return this.id; +}; + View.prototype.setPosition = function(pos) { // // We allow [x, y], { x : x, y : y }, or (x, y) @@ -116,18 +120,35 @@ View.prototype.setPosition = function(pos) { 'Y position ' + this.position.y + ' out of terminal range ' + this.client.term.termWidth); }; -View.prototype.setColor = function(fg, bg, flags) { - if(fg) { - this.color.fg = fg; +View.prototype.setColor = function(color, bgColor, flags) { + if(_.isObject(color)) { + assert(_.has(color, 'fg')); + assert(_.has(color, 'bg')); + assert(_.has(color, 'flags')); + + this.color = color; + } else { + if(color) { + this.color.fg = color; + } + + if(bgColor) { + this.color.bg = bgColor; + } + + if(_.isNumber(flags)) { + this.color.flags = flags; + } } - if(bg) { - this.color.bg = bg; + // allow strings such as 'red', 'black', etc. to be passed + if(_.isString(this.color.fg)) { + this.color.fg = ansi.getFGColorValue(this.color.fg); } - if('undefined' !== typeof flags) { - this.color.flags = flags; - } + if(_.isString(this.color.bg)) { + this.color.bg = ansi.getBGColorValue(this.color.bg); + } }; View.prototype.getColor = function() { @@ -147,8 +168,6 @@ View.prototype.setFocus = function(focused) { this.hasFocus = focused; this.client.term.write('show' === this.cursor ? ansi.showCursor() : ansi.hideCursor()); - - this.emit(focused ? 'enter' : 'leave'); }; View.prototype.onKeyPress = function(key, isSpecial) { diff --git a/core/view_controller.js b/core/view_controller.js index 43fe8fd6..d4671bf8 100644 --- a/core/view_controller.js +++ b/core/view_controller.js @@ -15,14 +15,17 @@ var _ = require('lodash'); exports.ViewController = ViewController; -function ViewController(client, formId) { +function ViewController(options) { + assert(_.isObject(options)); + assert(_.isObject(options.client)); + events.EventEmitter.call(this); var self = this; - this.client = client; + this.client = options.client; this.views = {}; // map of ID -> view - this.formId = formId || 0; + this.formId = options.formId || 0; this.onClientKeyPress = function(key, isSpecial) { if(isSpecial) { @@ -95,6 +98,16 @@ function ViewController(client, formId) { self.emit('submit', formData); }; + this.switchFocusEvent = function(event, view) { + if(self.emitSwitchFocus) { + return; + } + + self.emitSwitchFocus = true; + self.emit(event, view); + self.emitSwitchFocus = false; + }; + this.attachClientEvents(); } @@ -146,16 +159,17 @@ ViewController.prototype.getFocusedView = function() { ViewController.prototype.switchFocus = function(id) { if(this.focusedView && this.focusedView.acceptsFocus) { + this.switchFocusEvent('leave', this.focusedView); this.focusedView.setFocus(false); } var view = this.getView(id); if(view && view.acceptsFocus) { + this.switchFocusEvent('enter', view); + this.focusedView = view; this.focusedView.setFocus(true); } - - // :TODO: Probably log here }; ViewController.prototype.nextFocus = function() { @@ -234,7 +248,7 @@ ViewController.prototype.loadFromMCIMapAndConfig = function(options, cb) { if(err) { // :TODO: fix logging of err here: Log.warn( - { err : err, mci : Object.keys(options.mciMap), formIdKey : formIdKey } , + { err : err.toString(), mci : Object.keys(options.mciMap), formIdKey : formIdKey } , 'Unable to load menu configuration'); } diff --git a/mods/apply.js b/mods/apply.js index d834cca5..96c26c47 100644 --- a/mods/apply.js +++ b/mods/apply.js @@ -27,10 +27,8 @@ function ApplyModule(menuConfig) { var self = this; - this.clearForm = function() { - [ 1, 2, ].forEach(function onId(id) { - self.viewController.getView(id).clearText(); - }); + this.menuMethods.submitApplication = function(args) { + console.log('do submit') }; } @@ -49,46 +47,63 @@ ApplyModule.prototype.mciReady = function(mciMap) { var self = this; - self.viewController = self.addViewController(new ViewController(self.client)); + self.viewController = self.addViewController(new ViewController({ client : self.client } )); self.viewController.loadFromMCIMapAndConfig( { mciMap : mciMap, menuConfig : self.menuConfig }, function onViewReady(err) { var usernameView = self.viewController.getView(1); - var userExistsView = self.viewController.getView(10); - usernameView.on('leave', function leave() { + var passwordView = self.viewController.getView(9); + var pwConfirmView = self.viewController.getView(10); + var statusView = self.viewController.getView(11); + + self.viewController.on('leave', function leaveView(view) { + switch(view.getId()) { + case 1 : + user.getUserIdAndName(view.getViewData(), function userIdAndName(err) { + var alreadyExists = !err; + if(alreadyExists) { + statusView.setText('Username unavailable!'); + self.viewController.switchFocus(1); // don't allow to leave + } else { + statusView.setText(''); + self.viewController.switchFocus(2); + } + }); + break; + } + }); +/* + usernameView.on('leave', function leaveUsername() { user.getUserIdAndName(usernameView.getViewData(), function userIdAndName(err) { - if(!err) { - userExistsView.setText('That username already exists!'); + var alreadyExists = !err; + if(alreadyExists) { + statusView.setText('Username unavailable!'); + self.viewController.switchFocus(1); // don't allow to leave } else { - userExistsView.setText(''); + statusView.setText(''); + self.viewController.switchFocus(2); } - //if(11 !== self.viewController.getFocusedView()) { - self.viewController.switchFocus(2); - //} }); }); - var pwView = self.viewController.getView(8); - var pwConfirmView = self.viewController.getView(9); - var pwSecureView = self.viewController.getView(11); - var pwConfirmNoticeView = self.viewController.getView(12); - - // :TODO: show a secure meter here instead - pwView.on('leave', function pwLeave() { - if(pwView.getViewData().length > 3) { - pwSecureView.setColor(32); - pwSecureView.setText('Secure'); + passwordView.on('leave', function leavePw() { + if(passwordView.getViewData().length < 3) { + statusView.setText('Password too short!'); + self.viewController.switchFocus(9); } else { - pwSecureView.setColor(31); - pwSecureView.setText('Insecure!'); + statusView.setText(''); } }); - pwConfirmView.on('leave', function confirmPwLeave() { - if(pwView.getViewData() !== pwConfirmView.getViewData()) { - pwConfirmNoticeView.setText('Passwords must match!'); + pwConfirmView.on('leave', function leavePwConfirm() { + if(passwordView.getViewData() !== pwConfirmView.getViewData()) { + statusView.setText('Passwords must match!'); + self.viewController.switchFocus(9); } else { - pwConfirmNoticeView.setText(''); + statusView.setText(''); } }); +*/ + + }); }; \ No newline at end of file diff --git a/mods/art/themes/NU-MAYA/APPLY1.ANS b/mods/art/themes/NU-MAYA/APPLY1.ANS new file mode 100644 index 0000000000000000000000000000000000000000..ea1b3e496e0ffb8402ee79aa98fe809d9276a176 GIT binary patch literal 3954 zcmb`K!EW0|5Qd#=f%ei%QC--B0T&1gQj{edJ~=_q7Dxl5N!o)>YGW4$OdE(>w2wvd zbx4EH&^PG+|1-N>N|tl!2BFB^;qEv8%+AuYb$+(U&&pLbTOSuMXX~=8dbDn)LeLL)Wxz%jXq?Qx@XpLxPXtJwA^7 z4ea+ZQP+u&K?n0=s+IXNY94LIwW3x}&7=3GQYKR=gH|TfUX>D^y1H(fEuE;BRQt4l zBfBxkJ%dAs;+(*R`J(NPpNbzhA#Nt=DD~pRp1pY8tdM8QdL}n4eK<}cQI?++h0`so z46^myzyqc<9h5ygs>Faw&IxUFkXvyI6_B|_BPpv+7~o=dkDpz|qGiTRmS@L_XZ4<- z!<4QyVK{viHA3A1HgY9Usv~>!Hxl1rPZ-YDib1TaWu;}E38l4F^~Ke3gxq(?2VPR- zIf{8Pr{7r5q?@f(9g^qm)#zng>#E#bvD|lvGWK`LLgiUM=^pA9U||f)bv0CMy0(j* zNOK$!mmI*35Xnk?43#qU)X|o=xI`}M3m4!xon*o5 zx~v{*P$5-D?*q@zvMQ>}%}w@ZQ;kTRA3XDfXU;xMQd%tGq%$#0JmM&vH1Q-ARUqoJ z2@<`)D}f0-;68VnKSmCT6Vxe>${TbyBdnD3OKb}Od z9qI1(&7aqIw<8x?>>a4aM zZnH_^Bzjj@*EjbgR8(r2U@aYsbwPQpjAp(vI^Ne?d4V{J9xtZb$b+P+y9X#1c6|sS zcwWh@sH)BNO^Oq;X_fG-wt0d$${G=xG}um(XnGle1c>~5gy&c1x%_QH6ZJVscut&W zOr&(dempwFhv+b`*;wh2ZPD5|Lf9`HVRL`~_ua=2BL|m5=9~iI`9;X)Q-e5-G4i*O zn;DkU1^Mlzm<$Y&M^Zo$0|zi;%gUuT#liw|;qLb8`XjTIRXVMT`Gl*;4NTuomdkOW z?VF(=Sa+~E1D9ou_;ePR{yuu}1)(9)CBVgxP2A4!ii zIVT!@6>wd9;=rE!G10gw`9G`#77KD`$;Sl~c^2A35X?N_>B~d)@Wq<~=L*g{yK(<8 znOZOdAPrFT%~I9hb@$Bo8sUE8ZC}c_E3{({KrrXS^Z18`9xMg6uS^&%@*|Up- UuMX6{{PD$4*)QLp+f%&$2Z2>R5C8xG literal 0 HcmV?d00001 diff --git a/mods/art/themes/NU-MAYA/theme_info.json b/mods/art/themes/NU-MAYA/theme_info.json index 75864b1c..e8ae536b 100644 --- a/mods/art/themes/NU-MAYA/theme_info.json +++ b/mods/art/themes/NU-MAYA/theme_info.json @@ -1,4 +1,7 @@ { "name" : "Nu Mayan", - "author" : "NuSkooler" + "author" : "NuSkooler", + "config" : { + "passwordChar" : "*" + } } \ No newline at end of file diff --git a/mods/login.js b/mods/login.js index 4cafbc14..a6c1ff4a 100644 --- a/mods/login.js +++ b/mods/login.js @@ -80,7 +80,7 @@ LoginModule.prototype.mciReady = function(mciMap) { var self = this; - self.viewController = self.addViewController(new ViewController(self.client)); + self.viewController = self.addViewController(new ViewController( { client : self.client } )); self.viewController.loadFromMCIMapAndConfig( { mciMap : mciMap, menuConfig : self.menuConfig }, function onViewReady(err) { }); }; \ No newline at end of file diff --git a/mods/matrix.js b/mods/matrix.js index b1af2804..2fc60df3 100644 --- a/mods/matrix.js +++ b/mods/matrix.js @@ -66,7 +66,7 @@ MatrixModule.prototype.mciReady = function(mciMap) { // 2 - Bye! // //var vc = new ViewController(client); - var vc = self.addViewController(new ViewController(self.client)); + var vc = self.addViewController(new ViewController({ client : self.client } )); vc.on('submit', function onSubmit(form) { console.log(form); diff --git a/mods/menu.json b/mods/menu.json index b161e1e2..554328b0 100644 --- a/mods/menu.json +++ b/mods/menu.json @@ -105,17 +105,44 @@ "module" : "apply", "form" : { "0" : { - "BN13BN14ET1ET2ET3ET4ET5ET6ET7ET8ET9TL10TL11TL12" : { + "BN12BN13ET1ET10ET2ET3ET4ET5ET6ET7ET8ET9TL11" : { "mci" : { "ET1" : { "focus" : true }, - "BN13" : { + "BN12" : { + "submit" : true, "text" : "Apply" }, - "BN14" : { + "BN13" : { + "submit" : true, "text" : "Cancel" } + }, + "submit" : { + "12" : [ // Apply + { + "value" : { "12" : null }, + "action" : "@method:submitApplication", + "args" : { + "username" : "{1}", + "realName" : "{2}", + "age" : "{3}", + "sex" : "{4}", + "location" : "{5}", + "affils" : "{6}", + "email" : "{7}", + "web" : "{8}", + "password" : "{9}" + } + } + ], + "13" : [ // Cancel + { + "value" : { "13" : null }, + "action" : "@menu:matrix" + } + ] } } } diff --git a/mods/standard_menu.js b/mods/standard_menu.js index 925fe1e5..bb02f155 100644 --- a/mods/standard_menu.js +++ b/mods/standard_menu.js @@ -34,7 +34,7 @@ StandardMenuModule.prototype.mciReady = function(mciMap) { var self = this; - var vc = self.addViewController(new ViewController(self.client)); + var vc = self.addViewController(new ViewController({ client : self.client } )); vc.loadFromMCIMapAndConfig( { mciMap : mciMap, menuConfig : self.menuConfig }, function onViewReady(err) { if(err) { console.log(err);