custom touch functions

Workarounds and usability notes.

custom touch functions

Postby John Robin Dove » Fri May 21, 2021 10:31 am

Hi Clifton,
I am doing my best to make my program compatible with touchscreen devices. It's not simple but things are slowly getting better. I have opted for a non-Toolbook login page containing a form as this seemed to be the only sure way of getting the browser to react immediately by asking to save the username and password which is what I want. A TB Powerpac password field was more hit and miss in my experience but I may have been doing something wrong. Conversely, although there are other (TB Powerpac) password fields in the program I don't want these to trigger the save password routine because in a school one computer will often be used by more than one student or teacher. Of course just to be ornery they sometimes do but not when you'd expect them to. Sometimes a long time after their use. Movement from one iframe to another seems to be the trigger. Anyway I have solved the problem by making my own password field system which works well and looks exactly like the real thing. I have included an 'eye feature' that allows the user to see the password which looks just like toggling between password/text with Powerpac. The login is here https://www.mediacours.com/login/ I had to use a form input button. I tried an image at first but that kept asking if the image should be downloaded. The button works better. It works on a desktop computer but equally well on a tablet with this code:
//Surprisingly it seems that touchstart, touchend,mousedown and mouseup can coexist.
//At least they can on an Android tablet. What about an I-pad I wonder?


document.getElementById('eye').addEventListener("touchstart", function(event){
showTxt();
}, true);

document.getElementById('eye').addEventListener("touchend", function(event){
showPwd();
}, true);

document.getElementById('eye').addEventListener("mousedown", function(event){
showTxt();
}, true);

document.getElementById('eye').addEventListener("mouseup", function(event){
showPwd();
}, true);

I'm wondering if it is possible to incorporate this into ceratin other parts of the program where password fields are used. What do you think? If it's too complicated, don't bother. I already have a workaround that uses a click which is recognised by the touchscreen but this means two clicks instaed of mousedown/mouseup touchstart/touchend. If you want to see the login in action try username AR-1 password K2rPc8lf. Later on I'll give a better guided tour in English if you have time but as yet I still need to finish a number of things.
John
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am

Re: custom touch functions

Postby Clifton » Fri May 21, 2021 2:29 pm

The PowerPac functions support touch events natively.
However, you can still use the ones you have mentioned in your post.
In order to have touch events work on both mousedown and touchstart, just use this undocumented PowerPac event listener setup function:
    pgAddEvent( [object literal], "mouseDown", [obj].[function] );
    To remove the event:
    pgRemoveEvent( [object literal], "mouseDown", [obj].[function] );
On touch devices, the correct event will be handled just by assigning "mouseDown" event functions using pgAddEvent(). This makes checking for events on any device a lot easier. A lot of this kind of thing is happening automatically for ToolBook objects as the PowerPac is managing all supported devices with its own engine. So technically, you don't have to design your application around desktop and touch devices separately. Just design for a desktop device and pgAddEvent() will manage things for you.

When creating listeners, remember to make the listener function a method of the object it is designed for (e.g., obj.myMouseDown() where myMouseDown() is a a method of [obj]). Otherwise you will have a hard time removing these events when they are no longer needed if they are based on anonymous functions. In addition, you can easily end up with listeners that fire multiple times which is usually undesirable and hard to troubleshoot.
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Re: custom touch functions

Postby John Robin Dove » Sat May 22, 2021 8:25 am

Thanks for your reply.
After several hours I have not made any progress. Could you give me another example using a real object name please? At the moment my code is like this:
Code: Select all
  <toggler>
  <userProperty>
  <![CDATA[
  { tbName : "toggler",
  prop  : "mouseEvents",
  val : true,
  get_set : "set" }
  ]]>
  </userProperty>
 
  <pgStyleObject>
  <![CDATA[
  { theStyle : "backgroundImage, cursor",
  propVal  : "url(../media/eye.gif), pointer" }
  ]]>
  </pgStyleObject>
 
   
  <function name="myUser" event="user" params="evt,value,target" useTB="true">
  <![CDATA[
  if (sharedActions.mouse == true)
  { 
  var n = value.indexOf("mousedown");
    if (n > -1)
    {
    tbfunction_pgTBObjSet("response", "text", sharedActions.holdCode);
    tbfunction_pgTBObjSet("cache", "visible", false);
    return;
    }
  n = value.indexOf("mouseup");
    if (n > -1)
    {
    var L = sharedActions.holdCode.length;
    var txt = ""
    var i;
      for (i = 0; i < L; i++)
      {
      txt = txt + "  ";
      }
    tbfunction_pgTBObjSet("response", "text", txt);
    tbfunction_pgTBObjSet("cache", "visible", true);
    tbfunction_caretPosition("response", "end" );
    }
  }
  ]]> 
  </function>   
  </toggler>

This works with a mouse but not with a touchscreen.
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am

Re: custom touch functions

Postby Clifton » Sat May 22, 2021 10:50 am

Hi John,
I think you may be over-complicating things here.
All you really need is a mouse handler for the "toggler" object:
    <toggler>
    <function name="myMouse" event="mousedown,mouseup" params="evt">
    <![CDATA[
    var n = /down/i.test(evt.type); //Regular expression sets n to true or false if evt.type is "mousedown"
    if (n) {
    //Mouse is down ... do some stuff
    } else {
    //Mouse is up ... do some other stuff
    }
    ]]>
    </function>
    </toggler>

I tested this in a sample page and it seems to do what you need on both desktop and touch devices runing the page in a browser.
 
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Re: custom touch functions

Postby John Robin Dove » Sat May 22, 2021 11:12 am

Thank you very much indeed. I'm afraid there's quite a bit of this 'over-complication' elsewhere. There are also examples of the uncomplicated version but I guess you wrote those for me. :)
So I don't need to bother with touchstart and touchend. Powerpac takes care of this for me?
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am

Re: custom touch functions

Postby Clifton » Sat May 22, 2021 11:57 am

You are correct, the mousedown and up messages are handled internally when the XML engine sets up the events on your object. Generally, probably not in absolutely every case, the PowerPac internal handlers are all that you need. I haven't come across a situation where I needed additional code. But ... you never know?
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Re: custom touch functions

Postby John Robin Dove » Sun May 23, 2021 7:57 am

Hi Clifton,
I am still having trouble making things function with a touchscreen. Can you confirm that mouseover and mouseout are not usable without a mouse? What about keypress? I use keypress in my ''fake enter password' system. I can't get this to work on the tablet. If you have time, perhaps could you take a look at it please? I have put a small example 9.1 tbk here https://www.mediacours.com/tb_examples/requestEtc.zip I tried to make it as small as possible but there's still quite a lot of stuff.
Thanks
John
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am

Re: custom touch functions

Postby Clifton » Sun May 23, 2021 9:17 am

Mouseover and mouseout are very difficult to support on touch devices. Generally, mousedown is a good substitute for mouseover and mouseup for mouseout when using touch devices.

Keydown is more reliable than keypress and works everywhere.

There are separate Javascript libraries that can be used to support other events. You can evaluate these by searching "mouseover on touch devices". I have not explored these directly.

NOTE: The challenge with touch devices is that browser developers have also installed delay mechanisms on these devices to detect other touch-related events (e.g., two-finger pinch to zoom, or whether to begin a text selection).
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Re: custom touch functions

Postby John Robin Dove » Thu Jun 17, 2021 8:34 am

Hi Clifton,
I'm still struggling with the touchscreen functions. Some of my original features like a drag and drop system are just not possible with a touchscreen so I have added a special 'tool' group to do these tasks in another way. This seems to work as planned. I am now stuck on entering the password with a touchscreen. As I mentioned before, I do not want to use a password type input because this triggers the browser to save the password again (often at a later and inappropriate stage in the program). And apparently and more importantly you can only save one password per site. So I am using this
Code: Select all
  <response>
  <pgStyleObject>
  <![CDATA[
  { theStyle : "font-size",
  propVal  : "19px" }
  ]]>
  </pgStyleObject>
   
  <function name="myKeyDown" event="keydown" params="e">
  <![CDATA[
    if (sharedActions.isPwd == true)
    {
      if (e.keyCode == 8)  //backspace
      {
      var txt = sharedActions.holdCode;
      var L = txt.length;
        if (L < 3)
        {
        tbfunction_pgTBObjSet("response", "text", "");
        sharedActions.holdCode = "";
        return;
        }
      L -= 1;
      var newTxt = "";
      var i;
        for (i = 0; i < L; i ++)
        {
        newTxt = newTxt + txt[i];
        }
      sharedActions.holdCode = newTxt;
      L = newTxt.length;
      sharedActions.showDots(L); 
       
      }
      else if (e.keyCode == 13)  //enter
      {
        var fct = function()
        {
        sharedActions.getResult();
        return;
        }
      setTimeout(fct, 750);
      }
      else if (e.keyCode == 46)  //delete
      {
      e.preventDefault();
      sharedActions.holdCode = "";
      sharedActions.showDots(0);
      }
      else if (e.keyCode == 16 || e.keyCode == 20)  //Shift or Caps lock
      {
      return;
      }
 
      if (sharedActions.mouse == 0) //Touchscreen
      {
        var fct = function()
        {
        var txt = tbfunction_pgTBObjGet("response", "text");
          if (txt)
          {
          var L = txt.length;
          L -= 1;
          var dot = '\u2022';
          var char = txt[L];
            if (char == dot)
            {
            return;
            }
          sharedActions.holdCode = sharedActions.holdCode + char;
          L = sharedActions.holdCode.length;
          sharedActions.showDots(L);
          }
        }
      setTimeout(fct, 100);
      }
    }
  ]]>
  </function> 
 
  <function name="showDots" event="" params="charNo">
  <![CDATA[
  //var dot = '\u26ab';
  var dot = '\u2022';
  var txt = "";
  var i;
    for(i = 0; i < charNo; i++)
    {
    txt = txt + dot;
    }
  tbfunction_pgTBObjSet("response", "text", txt);
  ]]>
  </function>   


This works on the pc but on the tablet it uses autocomplete and makes a complete mess of my system. I need to turn off the autocomplete. I tried to do this by using getHTMLContent / setHTMLContent and pgReplace to change input type to input autocomplete="false" type in the parent object of the input like this:

var result = tbfunction_getHTMLContent("mover");
result = tbfunction_pgReplace("input type", "input autocomplete=" + String.fromCharCode(34) + false + String.fromCharCode(34) +" type", result);
tbfunction_setHTMLContent("mover", result);
in the HTML content below.
Code: Select all
<span id="sys228" style="background: transparent none repeat scroll 0% 0%; height: 172px; width: 427px; visibility: inherit; z-index: 32813; color: rgb(0, 0, 0); font-family: &quot;MS Sans Serif&quot;; font-size: 11px; font-style: normal; position: absolute; left: 21px; top: 24px; overflow: hidden;"><div style="position: absolute; overflow: hidden; left: 0px; top: 0px; width: 427px; height: 172px; background: transparent url(&quot;../dialog/BG-UL.png&quot;) no-repeat scroll left top;"></div><div style="position: absolute; overflow: hidden; left: 0px; top: 0px; width: 427px; height: 172px; background: transparent url(&quot;../dialog/BG-BL.png&quot;) no-repeat scroll left bottom;"></div><div style="position: absolute; overflow: hidden; left: 0px; top: 0px; width: 427px; height: 172px; background: transparent url(&quot;../dialog/BG-UR.png&quot;) no-repeat scroll right top;"></div><div style="position: absolute; overflow: hidden; left: 0px; top: 0px; width: 427px; height: 172px; background: transparent url(&quot;../dialog/BG-BR.png&quot;) no-repeat scroll right bottom;"></div><div style="position: absolute; overflow: hidden; left: 12px; top: 0px; width: 403px; height: 172px; background: transparent url(&quot;../dialog/BG-BOT.png&quot;) repeat-x scroll left bottom;"></div><div style="position: absolute; overflow: hidden; left: 12px; top: 0px; width: 403px; height: 172px; background: transparent url(&quot;../dialog/BG-UPPER.png&quot;) repeat-x scroll left top;"></div><div style="position: absolute; overflow: hidden; left: 0px; top: 12px; width: 427px; height: 148px; background: transparent url(&quot;../dialog/BG-LEFT.png&quot;) repeat-y scroll left top;"></div><div style="position: absolute; overflow: hidden; left: 0px; top: 12px; width: 427px; height: 148px; background: transparent url(&quot;../dialog/BG-RIGHT.png&quot;) repeat-y scroll right top;"></div><div style="position: absolute; overflow: hidden; left: 12px; top: 12px; width: 403px; height: 148px; background-color: black; opacity: 0.65;"></div></span><span id="sys229" style="background-color: rgb(255, 255, 255); border: 1px solid rgb(0, 0, 0); height: auto; width: 429px; visibility: inherit; z-index: 32814; color: rgb(0, 0, 0); font-family: &quot;MS Sans Serif&quot;; font-size: 16px; font-style: normal; position: absolute; left: 6px; top: 29px; padding: 42px 40px 70px; overflow: hidden;">Importante. ¿Utiliza un ratón o una pantalla táctil?</span><span id="sys225" style="background-color: rgb(240, 240, 240); height: 66px; width: 428px; visibility: inherit; z-index: 32815; position: absolute; left: 7px; top: 9px; cursor: default; pointer-events: auto; touch-action: none;">
<span id="sys230" class="syshidden">
<img id="sys227" src="../media/14.gif" width="428" height="66" border="0">
</span>
<span id="sys231" style="position: absolute; left: 0px; top: 0px; width: 428px; height: 66px; visibility: inherit;">
<img id="sys226" src="../media/15.gif" width="428" height="66" border="0" align="top">
</span>
<span id="sys232" style="position: absolute; left: 0px; top: 0px; text-align: center; visibility: hidden; color: rgb(0, 0, 0); font-family: MS Sans Serif; font-size: 11px; font-style: normal; opacity: 1;">
</span>
</span><span id="sys233" style="background-color: rgb(192, 192, 192); border: 2px outset rgb(255, 255, 255); height: 33px; width: auto; visibility: inherit; z-index: 32816; color: rgb(0, 0, 0); font-family: &quot;Arial&quot;; text-align: center; font-size: 19px; font-style: normal; position: absolute; left: 119px; top: 132px; overflow: hidden; padding-top: 3px; padding-left: 14px; padding-right: 14px; cursor: pointer; touch-action: none;">Ratón</span><span id="sys234" style="background-color: rgb(192, 192, 192); border: 2px outset rgb(255, 255, 255); height: 33px; width: auto; visibility: hidden; z-index: 32817; color: rgb(0, 0, 0); font-family: &quot;Arial&quot;; text-align: center; font-size: 19px; font-style: normal; position: absolute; left: 190px; top: 132px; overflow: hidden; padding-top: 3px; padding-left: 14px; padding-right: 14px; cursor: pointer; touch-action: none;">OK</span><span id="sys235" style="background-color: rgb(192, 192, 192); border: 2px outset rgb(255, 255, 255); height: 33px; width: auto; visibility: inherit; z-index: 32818; color: rgb(0, 0, 0); font-family: &quot;Arial&quot;; text-align: center; font-size: 19px; font-style: normal; position: absolute; left: 261px; top: 132px; overflow: hidden; padding-top: 3px; padding-left: 14px; padding-right: 14px; cursor: pointer; touch-action: none;">Pantalla</span><span id="sys236" style="background-color: rgb(255, 255, 255); height: 27px; width: 51px; visibility: hidden; z-index: 32819; color: rgb(0, 0, 0); font-family: &quot;Arial&quot;; font-size: 21px; font-style: normal; position: absolute; left: 352px; top: 158px; overflow: hidden; background-image: url(&quot;../media/eye.gif&quot;); cursor: pointer; touch-action: none;"></span><input  type="text" value="" onfocus="TBK._Ffocus(p0.o139,true);" onblur="TBK._Ffocus(p0.o139,false);" id="sys237" style="border: 1px solid rgb(0, 0, 0); height: 30px; width: 362px; visibility: hidden; z-index: 32820; color: rgb(0, 0, 0); font-family: &quot;MS Sans Serif&quot;; font-size: 19px; font-style: normal; position: absolute; left: 37px; top: 122px; overflow: hidden; background-color: transparent; margin: 0px; padding-bottom: 2px;" name="response">
but this did not work. Can you help please?
John

UPDATE I have now actually got it to work on the tablet. Apparently autocomplete is a tricky subject in Chrome see https://stackoverflow.com/questions/30053167/autocomplete-off-vs-false I used this to do it:
Code: Select all
<function name="getObj2" event="" params="">
  <![CDATA[
  var iframe = document.getElementById('syspageFrame');
  var innerDoc = (iframe.contentDocument);
  this.obj2 = innerDoc.getElementById("sys237");
  this.obj2.autocomplete="chrome-off"; // chrome-off was suggeted by someone on Stack-Overflow
  ]]>
  </function>

It's still not as I'd like because the autocomplete field still appeared but this time it did not interfere with my system.

UPDATE 2
Clifton don't waste any time on this. It's driving me nuts! Just to make one or two things clear: Chrome autofill was not filling in the text but it was providing unhelpful prompts in a field just below. I decided to change the field in the tbk to wordwrap. In this way a textarea is created instead of an input. This made no difference. I have two users on my test site. Bill BlOGGS and John Robin DOVE. Their passwords are bloggs and dove. I have been using bloggs's account most of the time and stuff like bl blo or even bloggsbloggs kept appearing. Finally this evening I used The other account with dove as the password. This time Chrome made no unhelpful suggestions not even the second time I entered the password. I can only think that the bl blo stuff must be hidden away somewhere in Chrome and it keeps on using it even though I emptied the Chrome cache on the tablet every time. The last change I made was this: this.obj2.autocomplete = "new-password"
So it seems the problem is solved but I'll test it again tomorrow.
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am

Re: custom touch functions

Postby Clifton » Thu Jun 17, 2021 4:01 pm

I am really have a hard time trying to figure out the flow of of your design. It seems overly complicated.

I worked up an alternative that uses a normal input password field. It does not trigger password saving in Firefox. In Chrome the password saving drop down box shows only when the field is empty, but there is nothing that can be saved. As soon as you begin typing in the password box, the dropdown goes away.

You can play around with this. The code is a lot simpler and not as many objects are needed to make it work. My example checks to make sure at least 4 characters are entered before allowing the OK button to be enabled. It also will not display the password unless something has been entered. I also cleaned up the dialog window you are using to make things a bit simpler by using native CSS3 styling. In the long run this is a good area for just using a stylesheet. I converted the gif to a png with alph-transparency.

The following is an active export of my attempt at this:
Attachments
source.zip
Source files for above example. (ToolBook v9.01)
(56.99 KiB) Downloaded 196 times
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Next

Return to General Discussion

Who is online

Users browsing this forum: No registered users and 1 guest

cron