Problem/Motivation

Dreditor currently uses the TAB key to do autocompletion. For example, type "<block" + TAB to get "<blockquote></blockquote>", with the cursor positioned in between. The problem is that the TAB key already has a function before Dreditor: it moves the focus out of the textarea to the next link or control that can accept the focus.

Dreditor hijacks the TAB key if (and only if) the cursor sits at the end of a shortcut, e.g. at the end of "<block", but not at the end of "<bloc", "<blockq", or "<bloxk" or anywhere else. This means that if you intend to type "<block" + TAB but you mistype "<bloxk", then the TAB throws you out of your context (typically out of the textarea to the next link). You have to refocus your attention away from your train of thought towards how to get your cursor back to where you're typing.

There are different kinds of typists who may experience this in different ways:

  • The fingers-are-faster-than-the-brain type types furiously and may not notice typos until a few keystrokes later, or his fingers may feel the difference and backspace automatically to correct the error. For this type it's extremely important that key behavior is predictable and that the backspace sequence is preserved, i.e. typing a wrong character and two more should be undoable by hitting BACKSPACE three times, because the fingers do this automatically. Most every software works that way and the fingers have learned that behavior. Breaking the backspace sequence is a usability problem, and that's what Dreditor does: if you type "<bloxk" + TAB, you're thrown out of the textarea and you cannot use the BACKSPACE to correct your typo. (*)
  • The hunt-and-peck type...
  • ... (I can only describe my own subjective experience — please add your own if you're of a different type.)

(*) This has turned into a HUGE usability issue with the deployment of BUEditor on d.o. Due to a bug in the old jQuery version that we use on d.o, if you hit BACKSPACE anyway in this situation, you've lost your entire input. The fingers-are-faster-than-the-brain type's fingers will do that and we lose hours of work (and confidence in the reliability of d.o) due to this issue. This is not Dreditor's fault, and it could be fixed by updating jQuery or BUEditor (the current version has a work-around), but neither of these are going to happen on d.o anytime soon. Fixing this issue here will mitigate the jQuery/BUEditor issue, and this adds some urgency to this issue.

Proposed resolution

There are several at this point:

Disable tabbing out of the textarea

Advantage: auto-complete key remains the TAB.
Disadvantage: tabbing out will not work anymore.

Use SPACE instead of TAB

Advantage: tabbing out continues to work, SPACE works naturally and will not cause any conflicts.
Disadvantage: users need to learn a new auto-complete key.

Remaining tasks

  • Understand the problem.
  • Look for possible solutions.
  • Evaluate the alternatives.
  • Implement the best one.

User interface changes

(See Proposed resolution above.)

API changes

N/A

Original report by salvis

As described in #1351642: Major UX issue: BUEditor clears the text area the combination of BUEditor and Dreditor creates a considerable risk of losing the text that you type into textareas on d.o.

Dreditor's use of the Tab key to expand tags gets you into the habit of hitting the Tab key in textareas, which you wouldn't normally do otherwise. Sometimes, for example if I mistype <block and hit Tab before I notice the typo, then my fingers automatically hit the Backspace key to backtrack to the error. Whenever this happens, you've lost your text, because the browser pages back, and when you page forward again, BUEditor clears the textarea.

This is a severe misbehavior of BUEditor that should be fixed IMO, which will reduce the severity of this issue, but even then I think Dreditor breaks usability if it causes the Tab key to behave in two completely different ways (expanding a tag or jumping out of the textarea to the next link) depending on whether the cursor happens to be on an expandable start-of-tag or not.

To make Dreditor's behavior consistent it should really insert a tab character when it cannot expand a tag, so that the natural flow of typing (hitting the Backspace to undo the Tab in this case) is preserved.

Comments

clemens.tolboom’s picture

As reported by ufku in #1351642: Major UX issue: BUEditor clears the text area his comment in https://bugzilla.mozilla.org/show_bug.cgi?id=209292#c32 this is a jQuery [<=1.3.2] bug.

His testcase on https://bug209292.bugzilla.mozilla.org/attachment.cgi?id=566289 is pretty good.

@salvis: Do you know of a bug report @ jQuery about this?

jQuery @ drupal.org == 1.2.6

salvis’s picture

@salvis: Do you know of a bug report @ jQuery about this?

No, I don't. And it doesn't matter. jQuery is at v1.7.1. Version 1.4 was released over 20 months ago and apparently has it fixed, so what should we expect from having a bug report against an old, old version of jQuery?

IMO, Dreditor's behavior is bad either way: An "expand" key should not do something completely different and throw you out of your context just because there's nothing to expand.

clemens.tolboom’s picture

Dreditor auto suggest is not dad as it just runs out of suggestions.

Drupal.dreditor.syntaxAutocomplete = function (element) {

But dreditor could try to remember it ran out of suggestions by the previous key press and thus insert a tab as @salvis suggested.

I thought sometime like this would solve it but not quite :( .

diff --git a/dreditor.user.js b/dreditor.user.js
index cc913c3..178c983 100644
--- a/dreditor.user.js
+++ b/dreditor.user.js
@@ -2696,6 +2696,11 @@ Drupal.dreditor.syntaxAutocomplete.prototype.keypressHandler = function (event)
     event.stopPropagation();
     return false;
   }
+  else if (self.outOfSuggestion) {
+    self.outOfSuggestion = false;
+    event.preventDefault();
+    event.stopPropagation();
+  }
 };
 
 /**
@@ -2722,9 +2727,11 @@ Drupal.dreditor.syntaxAutocomplete.prototype.keyupHandler = function (event) {
     var suggestion;
     if (suggestion = self.checkSuggestion(self.needle)) {
       self.setSuggestion(suggestion);
+      self.outOfSuggestion = false;
     }
     // Otherwise, ensure a possibly existing last suggestion is removed.
     else {
+      self.outOfSuggestion = true;
       self.delSuggestion();
     }
   }
salvis’s picture

Do we ever have more than one suggestion? I don't think so, at least the hint only pops up at an exact match, no prefix matching or anything like that. So, maybe just an else rather than an else if? (Just a wild guess, I don't know how this works.)

Thank you for looking into it!

clemens.tolboom’s picture

@salvis: I lost some issue work as well :p

This dreditor code doing the suggestions is tricky code to me too. So I hope others join.

sun’s picture

Title: Always eat the Tab keystrokes » Prevent tabbing out of the comment textarea
Category: bug » feature
Priority: Major » Normal

I considered this at the beginning, but didn't want to break the normal user experience for users operating with keyboard only.

clemens.tolboom’s picture

Category: feature » bug

@sun I think you're missing the point.

_only_ when having active autocomplete which ran out of suggestions dreditor should consume the next tab keypress. I tried this with #3 but failed :(

I consider this a dreditor bug as people may loose work as both @salvis and @clemens.tolboom did :(

sun’s picture

Indeed, I don't think I understand the desired behavior then. The summary could be clarified a bit.

Either way, I'm also not sure whether what you want is technically possible. Technically, Dreditor invokes the syntaxAutocompletion event handlers on every single keypress, and technically, there's an autocomplete needle at any point in time.

This also explains why there is a very very small lag in response time during typing. The syntaxAutocompletion implementation is not trivial exactly because of this - I had to rewrite it a couple of times to make it as performant as possible.

salvis’s picture

@sun: Dreditor is part of the chain that makes losing your work all too easy. That's what makes this issue a major one.

You have two groups of users with conflicting needs:

  • those who want to tab out of textareas (you have to tab a couple of times to actually get to a useful tabstop) and
  • those who depend more and more on Dreditor and blindly type the keyword expansions, and get bitten badly by its peculiarities.

Which of these are your "core customers"?

If you feel that you must support the Tabbers, then how about using the Space to expand the shortcuts?

helmo’s picture

@salvis: using just Space would probably introduce other problems.

What about ctrl + space?

clemens.tolboom’s picture

@sun
You are right about always having a needle. But can we go for 'press tab twice' for exiting the text area?

@salvis
Could you spend some time on the issue summary as sun asked ;-)

@helmo
ctrl+space sounds great but

- on my mac shows a context menu
- taken by Windows Vista IME according to http://www.dotnetmonster.com/Uwe/Forum.aspx/vs-setup/1815/Ctrl-Space-alw...

So not sure whether that could work.

salvis’s picture

@salvis: using just Space would probably introduce other problems.

"Probably" is not good enough — please give this some thought.

@salvis
Could you spend some time on the issue summary as sun asked ;-)

Well, I did. I wrote the original version and spent my best effort, but I'll take the template and try again...

What about ctrl + space?

Aside of potential conflicts (#11), Ctrl-Space is not ideal for typing either. I type on a number of keyboards (desktop, notebook, etc.) and Ctrl-combinations don't come as easily as single-key TAB or SPACE, because the Ctrl key is in different positions on different keyboards.

AFAICS there are several types of shortcuts. Typical representatives are:

  • <block
  • <img
  • Issue URLs: Paste http://drupal.org/node/123456 and hit TAB to get #123456: Drupal website oupedia.com with imported joomla template — hitting SPACE instead is completely natural and will work perfectly.
  • Usernames: Type @s to get @sun, @sl to get @slantview, etc. Only usernames contained on the current page are available. — This could seem like a bit of a problem for the SPACE key. HOWEVER: the @ shortcuts work in a different way than the other types: they depend on the context (the usernames in the issue at hand), and you'll never type "@sTAB" blindly, because your fingers can't know whether you'll get the desired expansion, or even any at all. This means the user always has to observe the hint before he can hit the expansion key.

    Dreditor doesn't match just any prefix, but it allocates them uniquely instead: if we have @sun and @sunny in the same thread, then @sEXPAND would turn into @sun, and @suEXPAND would turn into @sunny, but @sun would not expand at all. Thus, with the SPACE as the expansion key, we can happily type @sunSPACE and get "@sun " — exactly what we expect, even in the presence of @sunny.

Remain "<block" and "<img": Both of these work quite nicely with the SPACE: You'd never type a space after <block, so it works great, and you'd always type a space after <img, so it works great, too. The only problematic cases would be those where you might or might not want to type a space. I don't think we have any of those, so the SPACE would work just fine.

What's more: the SPACE never ever has any special functionality. Inserting a space is fine in every situation, and hitting BACKSPACE will remove it gracefully.

Please don't dismiss the SPACE without seriously considering it!

helmo’s picture

@salvis: Your reasoning about using SPACE makes sense. I had the idea that users would end up with extra white space.
E.g. when an expected completion does not exist "@gEXPAND". But even if... that is as you say quickly removed with backspace.

Issue URLs: Paste http://drupal.org/node/123456 and hit TAB to get #123456: Drupal website oupedia.com with imported joomla template

In my experience pasting often does not provide the expansion hit, as I usually do that with ctrl+v or shift+INS, and the special keys are excluded from the event handling.
I assume teh code below in Drupal.dreditor.syntaxAutocomplete.prototype.keyupHandler does that:

  // Skip special keystrokes.
  if (event.shiftKey || event.ctrlKey || event.altKey || event.metaKey) {
    return;
  }
clemens.tolboom’s picture

@salvis thanks for #12 and the summary :-)

I'll try the space for a while with my sandbox version when finding time.

salvis’s picture

Thanks for giving the SPACE a chance!

@helmo: I didn't even know about the issue number thing before I read up on it! But it does work for me, both with Ctrl-V and Shift-Ins, and it is really handy.

Dreditor does not seem to care at all how you get the shortcut into the textarea. It'll even work for shortcuts that have been there all along and you use the mouse to position the cursor in the right spot.

salvis’s picture

Issue summary: View changes

Create an initial "summary" as requested by #8.