-
• #2
Here the code - about to be a module -with usage example:
// SBTouchCtrl.js // 2020v1210_ao by allObjects // Simple Bangle Touch Controller (module to be) // Easy to use bangle touch controler by allObjects. // Provides events for left, right, and both touch // lifecycle w/ timings incl. on error and recovery. /* ` ` ` var l = function() { console.log.apply(console,arguments); }; , sbtcMod = require("SBTouchCtrl"); , sbtc; // instance of simple bangle touch controler function onInit() { sbtc = new SBTouchCtrl( // provide callback obj w/ named cbs for some events { L:(ts,tt,et)=>l("Left touch for",et,"[sec] at",tt) , E:()=>console.log("Error - recovered") }).watch(); // activate button touch button watching g.clear(); } setTimeout(onInit,999); ` ` ` */ var SBTouchCtrl=function(cbs) { var _=0||this; _.cbs=cbs||{}; // obj w/ callbacks named after touchSignature // l: left touch down (touchSign,touchTime,elapsedTime,sbtctl) // r: right touch down // b: 2nd both touch down // p: 1st untouch of both touch // e: error in sequncing (no recovery other than untouch all // L: untouch of left button and completion of left touch // R: untouch of right button and completion of right touch // B: untouch of both buttons and completion of both touch // E: end of error sequencing - all untouched - ready to cont _.tt=0; // touch time _.bt=0; // both touch time(+/-=L/R) _.pt=0; // both untouch time(+/-=L/R) _.ut=0; // untouch time _.et=0; // elapsed time _.st=0; // signature time _.ts=""; // touch signature _.sb=0; // status bits (for error resolution) _.s="s"; // status, s (start) _.wl=_.wr=_.wL=_.wR=null; // touch button watchers } , p=SBTouchCtrl.prototype; p.sl=(_,t,e)=>{_.ts=_.s=e;_.tt=t;return _.cbs[e];}; p.sr=(_,t,e)=>{_.ts=_.s=e;_.tt=t;return _.cbs[e];}; p.lL=(_,t,e)=>{_.ts=e;_.s="s";_.et=(_.ut=t)-_.tt;return _.cbs[e];}; p.rR=(_,t,e)=>{_.ts=e;_.s="s";_.et=(_.ut=t)-_.tt;return _.cbs[e];}; p.lr=(_,t,e)=>{_.ts=_.s="b";_.bt=t-_.tt; return _.cbs.b;}; p.rl=(_,t,e)=>{_.ts=_.s="b";_.bt=_.tt-t; return _.cbs.b;}; p.bL=(_,t,e)=>{_.ts="p";_.pt=t-_.tt; return _.cbs.p;}; p.bR=(_,t,e)=>{_.ts="p";_.pt=_.tt-t; return _.cbs.p;}; p.bLR=(_,t,e)=>{_.ts="B";_.s="s";_.et=(_.ut=t)-_.tt;return _.cbs.B;}; p.bRL=(_,t,e)=>{_.ts="B";_.s="s";_.et=(_.ut=t)-_.tt;return _.cbs.B;}; p.ign=(_,t,e,c,b)=>{ // p - s ignore from 1st err: evt already in _.s if ((c=((s=_.s).charAt(0)))=="b") { // 1st time here switch to e(rr) _.sb=3; _.ts=c="e"; _.s=c+s; } else { if ((_.sb=(_.sb^("RL".indexOf(e)+1))||("rl".indexOf(e)+1))) { _.ts="e"; _.s="e.."+e; } else { _.ts="E"; _.s="s"; } } return _.cbs[c]; }; p.ns=(_,e,b,f,t,cb)=>{ // dispatcher to state transitioners if ((cb=((f=_[_.s+=e])?f:_.ign).apply(_,[_,_.st=t=getTime(),e,b])) )cb(_.ts,t,_.et,_);}; // touchSignCharlrbpeLRBE,time,elapsed,BTouch p.el=function(){this.ns(this,"l");}; // l touch event handler p.er=function(){this.ns(this,"r");}; // r ... p.eL=function(){this.ns(this,"L");}; // L untouch event handler p.eR=function(){this.ns(this,"R");}; // R .. p.watch=function(){var _=0||this,o;_.unwatch();// set watch on t btns _.wl=setWatch(_.el.bind(_),BTN4,o={repeat:true,edge:"rising"}); _.wr=setWatch(_.er.bind(_),BTN5,o); _.wL=setWatch(_.eL.bind(_),BTN4,o={repeat:true,edge:"falling"}); _.wR=setWatch(_.eR.bind(_),BTN5,o); return _; }; p.unwatch=function() { var _=0||this,o; // clear watches touch btns if(_.wl)_.wl=clearWatch(_.wl); if(_.wr)_.wr=clearWatch(_.wr); if(_.wL)_.wL=clearWatch(_.Wr); if(_.wR)_.wR=clearWatch(_.wR); return _; }; // exports=SBTouchCtrl; // ---------- end of SBTouchCtrl module // slim logging function var l = function(){console.log.apply(console,arguments); }; // var SBTouchCtrl = require("SBTouchCtrl"); var sbtc; // instance of simple bangle touch controler function onInit() { sbtc = new SBTouchCtrl( // provide callback obj w/ named cbs for some events { L:(ts,tt,et)=>l("Left touch for",et,"[sec] at",tt) , R:(ts,tt,et)=>l("Right touch for",et,"[sec]") , B:(ts,tt,et,ctl)=>{ var d=new Date(tt*1000); l(ts // touch sign ,"Both w/ details abt 2nd btn touch and 1st btn untouch" ,"\nat" ,d.getHours()+":"+d.getMinutes()+":"+d.getSeconds() ,"\nfor",et // elapsed in [s] from 1st touch to last untouch ,"\n2nd touch after 1st t",ctl.bt // +/- R/L[s] touched appart ,"\n1st untouch aft 1st t",ctl.pt // +/- R/L[s] before elapsed ,"\n2nd untouch aft 1st u",et-ctl.pt // +/- R/L[s]unt'd appart ,"\n2nd untouch aft 1st t",et,"=elapsed");} // +/- R/L[s]unt'd , e:(ts,tt,et,ctl)=>console.log("err",ts,ctl.sb) , E:()=>console.log("Error - recovered") }).watch(); // activate button touch button watching g.clear(); } setTimeout(onInit,999);
Among others, the conversation about 2 questions regarding Button and touch event stirred me to take yet another - 3rd - stab at that subject of a Bangle Touch Controller. The first one was in the Bangle emulator when a Bangle was not yet available to me.
First and second failed because the nested condition checking and tracking of state became unbearable: lots of code, slow, and still a lot of unresolved (corner) cases, brittle and of limited functions.
This 3rd time, I use a state machine with direct addressed / called functions for the state and transitions. It consists of 2 implementations:
In this conversations it's about the simple controller. Main design goal was to enable easy exchange of the application callbacks to reuse the one-time setup of the controller. Therefore, the callbacks are passed as object properties in an object. The property names map to the events, states and transitions of he state machine of the controller and are called Touch Signatures. They can have these values:
Right touch for 0.17495727539 [sec] Left touch for 0.11331176757 [sec] at 1607677068.38404655456 Right touch for 0.83169555664 [sec] Left touch for 1.75540161132 [sec] at 1607677075.57887077331 B Both w/ details abt 2nd btn touch and 1st btn untouch at 0:58:0 for 1.31875610351 2nd touch after 1st t 0.02020263671 1st untouch aft 1st t 1.31472778320 2nd untouch aft 1st u 0.00402832031 2nd untouch aft 1st t 1.31875610351 =elapsed ign: bRr r 0 err e 3 ign: ebRrR R 3 err e 2 ign: e..Rr r 2 err e 2 ign: e..rR R 2 err e 3 ign: e..Rr r 3 err e 3 ign: e..rL L 3 err e 1 ign: e..LR R 1 err E 0
.sb=(.sb^("RL".indexOf(e)+1))||("rl".indexOf(e)+1)```
A suitable application of the Simple Bangle Touch Controller will be a BangleJS Soft Keyboard as outlined in post #14 of above mentioned conversation about touch buttons and events, but without the issues of the (integrated) touch controller implementation. It will be presented in a separate conversation.