View Issue Details

IDProjectCategoryView StatusLast Update
0004103SOGoGUIpublic2018-02-13 10:45
Reporteralaniyatm Assigned To 
PriorityhighSeverityminorReproducibilityalways
Status newResolutionopen 
Summary0004103: email input termination by coma button shortcut
Description

When you start typing a user name in the "TO" field, the search for the address book starts, at the same time, if the name of the user has a symbol that is located on the "," key, the search completion is triggered. This behavior leads to the impossibility of selecting users with the Russian letter B in the name, because it is placed on the same button as the "," symbol in the English keyboard layout. Thus, it is not possible to write a letter to the user with the letter B.

TagsNo tags attached.

Relationships

duplicate of 0003513 resolvedfrancis "To" field automatically add address when "@" is writed into field on Chrome and Safari 
has duplicate 0004109 new Address book search fails 

Activities

alaniyatm

alaniyatm

2017-03-23 20:47

reporter  

screen.png (82,489 bytes)   
screen.png (82,489 bytes)   
alaniyatm

alaniyatm

2017-03-27 19:07

reporter   ~0011597

So.
Basically, i found that keycode 188 triggers autocomplete function.

In file UIxMailEditor.wox (line 70,104,137) for fileds 'To,CC,BCC' are used md-separator-keys="editor.recipientSeparatorKeys".

i resolved this (on lab) by deleting the 188 code from angular-material.js (line: 409) and angular-material.min (line: ...KEY_CODE:{COMMA:188...)

also my colleague found the function that overrides entered COMMA to the $mdConstant.KEY_CODE.ENTER

https://github.com/angular/material/blob/e06284aa4745dd7323a872a0a9290fd026747e30/src/components/chips/chips.spec.js#L883

What should i do next? Make a custom fix for me?

francis

francis

2017-03-27 22:16

administrator   ~0011598

Check my comments in ticket 0003513.

Ivan Zakharyaschev

Ivan Zakharyaschev

2018-02-06 22:52

reporter   ~0012573

I've found a patch by Volker Braun for the old angular-material which might be helpful to solve this problem: allow chars as chips separators (besides keycodes).

It's in https://github.com/vbraun/material , branch chips-separator-keys; more links:

https://github.com/angular/material/pull/8321
https://github.com/angular/material/issues/8319

https://github.com/vbraun/material/commit/50e929cba57b4b5197fcc2c12cb4d8e317f57758

I've rebased it onto the commit of angular-material checked-in as a submodule in SOGo-3.2.10 -- https://github.com/imz/material/tree/chips-separator-keys .

I've committed the changes to the SOGo code relying on this feature: http://git.altlinux.org/people/imz/packages/sogo3.git?p=sogo3.git;a=shortlog;h=refs/heads/chips-separator-keys .

But I didn't manage to make the SOGo build system recompile the JS so that the changes take effect --

So, I haven't yet tested whether this feature would actually work. I need help from the developers of SOGo in this.

Can you please tell me how to change UI/WebServerResources/angular-material/ sources and then recompile so that the changes take effect?

Example of what I did to try out some changes (an attempt to fix a problem reported several times like https://sogo.nu/bugs/view.php?id=4103 and test the new code) and it didn't work, i.e. they didn't take effect:

Updated the submodule UI/WebServerResources/angular-material and committed the new changes -- https://github.com/imz/material/tree/chips-separator-keys .

Committed the new submodule state -- the second top commit 0d8ef8fca38e4df3f202c2d05f980e678076f57e in http://git.altlinux.org/people/imz/packages/sogo3.git?p=sogo3.git;a=shortlog;h=refs/heads/chips-separator-keys .
Read Documentation/SOGoDevelopersGuide.asciidoc (section: Building frontend), did all the commands (npm etc.)

Run make -C UI/WebServerResources prod .

The result: it regenerated and committed some JS files -- in cdf0a77f681bcb9006217e2971e025251dfecefd , second top in http://git.altlinux.org/people/imz/packages/sogo3.git?p=sogo3.git;a=shortlog;h=refs/heads/altM/80P .

But the changed angular-material code didn't get into the result. To check:

$ cd UI/WebServerResources/angular-material/
$ git --no-pager grep -iFe inputKeypress
src/components/chips/js/chipsController.js:MdChipsCtrl.prototype.inputKeypress = function(event) {
src/components/chips/js/chipsController.js: * Common code for both inputKeydown and inputKeypress
src/components/chips/js/chipsController.js: .on('keypress', function(event) { scopeApplyFn(event, ctrl.inputKeypress) })
src/components/chips/js/chipsDirective.js: ng-keypress="$mdChipsCtrl.inputKeypress($event)"\
$ cd ..
$ git --no-pager grep -iFe inputKeypress | wc -l
0
$

Compare that to the old code:

$ cd UI/WebServerResources/angular-material/
$ git --no-pager grep -iFe inputKeydown
src/components/chips/chips.spec.js: ctrl.inputKeydown(event);
src/components/chips/js/chipsController.js:MdChipsCtrl.prototype.inputKeydown = function(event) {
src/components/chips/js/chipsController.js: * Common code for both inputKeydown and inputKeypress
src/components/chips/js/chipsController.js: .on('keydown', function(event) { scopeApplyFn(event, ctrl.inputKeydown) })
src/components/chips/js/chipsDirective.js: ng-keydown="$mdChipsCtrl.inputKeydown($event)">';
$ cd ..
$ git --no-pager grep -iFe inputKeydown | wc -l
4
$

Ivan Zakharyaschev

Ivan Zakharyaschev

2018-02-06 22:55

reporter  

0001-fix-chips-keypress-handler-for-chips-separator-keys.patch (9,603 bytes)   
From 662f0c6d4fa0f8719467bb35eb6da02a64bad8a6 Mon Sep 17 00:00:00 2001
From: Volker Braun <vbraun.name@gmail.com>
Date: Tue, 3 May 2016 16:47:53 +0200
Subject: [PATCH] fix(chips): keypress handler for chips separator keys

Chips separator keys can now either be numeric (and matched in the
keydown handler) or string (and matched in the keypress handler).

Closes #8319
---
 src/components/chips/chips.spec.js                 | 64 ++++++++++++++++++++--
 .../chips/demoCustomSeparatorKeys/script.js        | 13 +++--
 src/components/chips/js/chipsController.js         | 25 ++++++++-
 src/components/chips/js/chipsDirective.js          |  5 +-
 4 files changed, 96 insertions(+), 11 deletions(-)

diff --git a/src/components/chips/chips.spec.js b/src/components/chips/chips.spec.js
index 217fb14..2912a6d 100755
--- a/src/components/chips/chips.spec.js
+++ b/src/components/chips/chips.spec.js
@@ -892,26 +892,80 @@ describe('<md-chips>', function() {
           '<md-chips ng-model="items" md-separator-keys="keys"></md-chips>';
 
         it('should create a new chip when a comma is entered', inject(function($mdConstant) {
-          scope.keys = [$mdConstant.KEY_CODE.ENTER, $mdConstant.KEY_CODE.COMMA];
+          scope.keys = [$mdConstant.KEY_CODE.ENTER, ','];
           var element = buildChips(SEPARATOR_KEYS_CHIP_TEMPLATE);
           var ctrl = element.controller('mdChips');
 
-          var commaInput = {
+          // Event sequence when pressing the comma key: first commaKeydown, then commaKeypress
+          var commaAscii = ','.charCodeAt(0);
+          var commaKeydown = {
             type: 'keydown',
             keyCode: $mdConstant.KEY_CODE.COMMA,
+            charCode: 0,
             which: $mdConstant.KEY_CODE.COMMA,
             preventDefault: jasmine.createSpy('preventDefault')
           };
+          var commaKeypress = {
+            type: 'keypress',
+            keyCode: commaAscii,
+            charCode: commaAscii,
+            which: commaAscii,
+            preventDefault: jasmine.createSpy('preventDefault')
+          };
+
+          ctrl.chipBuffer = 'Test';
+          element.find('input').triggerHandler(commaKeydown);
+          element.find('input').triggerHandler(commaKeypress);
+
+          expect(commaKeydown.preventDefault).not.toHaveBeenCalled();
+          expect(commaKeypress.preventDefault).toHaveBeenCalled();
+        }));
+
+        it('should not create a new chip when shift+comma is pressed', inject(function($mdConstant) {
+          scope.keys = [$mdConstant.KEY_CODE.ENTER, ','];
+          var element = buildChips(SEPARATOR_KEYS_CHIP_TEMPLATE);
+          var ctrl = element.controller('mdChips');
+
+          // Event sequence when pressing the comma key:
+          // first shiftKeydown, then commaKeydown, then shiftCommaKeypress
+          var shiftKeyCode = 16;
+          var commaAscii = ','.charCodeAt(0);
+          var shiftCommaAscii = '<'.charCodeAt(0);  // depends on keyboard, example is dvorak
+          var shiftKeydown = {
+            type: 'keydown',
+            keyCode: shiftKeyCode,
+            charCode: 0,
+            which: shiftKeyCode,
+            preventDefault: jasmine.createSpy('preventDefault')
+          };
+          var commaKeydown = {
+            type: 'keydown',
+            keyCode: $mdConstant.KEY_CODE.COMMA,
+            charCode: 0,
+            which: $mdConstant.KEY_CODE.COMMA,
+            preventDefault: jasmine.createSpy('preventDefault')
+          };
+          var shiftCommaKeypress = {
+            type: 'keypress',
+            keyCode: shiftCommaAscii,
+            charCode: shiftCommaAscii,
+            which: shiftCommaAscii,
+            preventDefault: jasmine.createSpy('preventDefault')
+          };
 
           ctrl.chipBuffer = 'Test';
-          element.find('input').triggerHandler(commaInput);
+          element.find('input').triggerHandler(shiftKeydown);
+          element.find('input').triggerHandler(commaKeydown);
+          element.find('input').triggerHandler(shiftCommaKeypress);
 
-          expect(commaInput.preventDefault).toHaveBeenCalled();
+          expect(shiftKeydown.preventDefault).not.toHaveBeenCalled();
+          expect(commaKeydown.preventDefault).not.toHaveBeenCalled();
+          expect(shiftCommaKeypress.preventDefault).not.toHaveBeenCalled();
         }));
 
         it('supports custom separator key codes', inject(function($mdConstant) {
           var semicolon = 186;
-          scope.keys = [$mdConstant.KEY_CODE.ENTER, $mdConstant.KEY_CODE.COMMA, semicolon];
+          scope.keys = [$mdConstant.KEY_CODE.ENTER, ',', semicolon];
 
           var element = buildChips(SEPARATOR_KEYS_CHIP_TEMPLATE);
           var ctrl = element.controller('mdChips');
diff --git a/src/components/chips/demoCustomSeparatorKeys/script.js b/src/components/chips/demoCustomSeparatorKeys/script.js
index a389b22..38fb923 100644
--- a/src/components/chips/demoCustomSeparatorKeys/script.js
+++ b/src/components/chips/demoCustomSeparatorKeys/script.js
@@ -5,13 +5,18 @@
       .controller('CustomSeparatorCtrl', DemoCtrl);
 
   function DemoCtrl ($mdConstant) {
-    // Use common key codes found in $mdConstant.KEY_CODE...
-    this.keys = [$mdConstant.KEY_CODE.ENTER, $mdConstant.KEY_CODE.COMMA];
+    // Use common numeric key codes found in $mdConstant.KEY_CODE or
+    // length-one strings for characters
+    this.keys = [$mdConstant.KEY_CODE.ENTER, ','];
     this.tags = [];
 
-    // Any key code can be used to create a custom separator
+    // Any key code can be used to create a custom separator. Note
+    // that key codes ignore modifiers, so this makes shift+semicolon
+    // a separator, too
     var semicolon = 186;
-    this.customKeys = [$mdConstant.KEY_CODE.ENTER, $mdConstant.KEY_CODE.COMMA, semicolon];
+    // Use this instead if you only want semicolon as separator
+    // var semicolon = ';';
+    this.customKeys = [$mdConstant.KEY_CODE.ENTER, ',', semicolon];
     this.contacts = ['test@example.com'];
   }
 })();
diff --git a/src/components/chips/js/chipsController.js b/src/components/chips/js/chipsController.js
index 9f34dcf..fe83d46 100644
--- a/src/components/chips/js/chipsController.js
+++ b/src/components/chips/js/chipsController.js
@@ -232,6 +232,7 @@ MdChipsCtrl.prototype.setupWrapperAria = function() {
  * @param event
  */
 MdChipsCtrl.prototype.inputKeydown = function(event) {
+  console.log('keydown', event);
   var chipBuffer = this.getChipBuffer();
 
   // If we have an autocomplete, and it handled the event, we have nothing to do
@@ -256,13 +257,34 @@ MdChipsCtrl.prototype.inputKeydown = function(event) {
     return;
   }
 
+  this.inputKey(event.keyCode, event);
+}
+
+/**
+ * Handles the keypress event on the input element: Search for special
+ * separator keys.
+ * @param event
+ */
+MdChipsCtrl.prototype.inputKeypress = function(event) {
+  console.log('keypress', event);
+  this.inputKey(String.fromCharCode(event.charCode), event);
+}
+
+/**
+ * Common code for both inputKeydown and inputKeypress
+ * @param key Either a numeric keyCode (keydown) or a length-one string (keypress)
+ * @param event
+ */
+MdChipsCtrl.prototype.inputKey = function(key, event) {
+  var chipBuffer = this.getChipBuffer();
+
   // By default <enter> appends the buffer to the chip list.
   if (!this.separatorKeys || this.separatorKeys.length < 1) {
     this.separatorKeys = [this.$mdConstant.KEY_CODE.ENTER];
   }
 
   // Support additional separator key codes in an array of `md-separator-keys`.
-  if (this.separatorKeys.indexOf(event.keyCode) !== -1) {
+  if (this.separatorKeys.indexOf(key) !== -1) {
     if ((this.autocompleteCtrl && this.requireMatch) || !chipBuffer) return;
     event.preventDefault();
 
@@ -742,6 +764,7 @@ MdChipsCtrl.prototype.configureUserInput = function(inputElement) {
   inputElement
       .attr({ tabindex: 0 })
       .on('keydown', function(event) { scopeApplyFn(event, ctrl.inputKeydown) })
+      .on('keypress', function(event) { scopeApplyFn(event, ctrl.inputKeypress) })
       .on('focus', function(event) { scopeApplyFn(event, ctrl.onInputFocus) })
       .on('blur', function(event) { scopeApplyFn(event, ctrl.onInputBlur) })
 };
diff --git a/src/components/chips/js/chipsDirective.js b/src/components/chips/js/chipsDirective.js
index 428bba0..94079d0 100644
--- a/src/components/chips/js/chipsDirective.js
+++ b/src/components/chips/js/chipsDirective.js
@@ -133,7 +133,9 @@
    *    the delete key will remove the chip.
    * @param {string=} delete-button-label A label for the delete button. Also hidden and read by
    *    screen readers.
-   * @param {expression=} md-separator-keys An array of key codes used to separate chips.
+   * @param {expression=} md-separator-keys An array of keys used to separate chips. Each entry is
+   *     either a numeric key code (triggering on keydown, ignoring modifiers) or a length-one
+   *     string (matching that keypress).
    * @param {string=} md-chip-append-delay The number of milliseconds that the component will select
    *    a newly appended chip before allowing a user to type into the input. This is **necessary**
    *    for keyboard accessibility for screen readers. It defaults to 300ms and any number less than
@@ -221,6 +223,7 @@
             ng-model="$mdChipsCtrl.chipBuffer"\
             ng-focus="$mdChipsCtrl.onInputFocus()"\
             ng-blur="$mdChipsCtrl.onInputBlur()"\
+            ng-keypress="$mdChipsCtrl.inputKeypress($event)"\
             ng-keydown="$mdChipsCtrl.inputKeydown($event)">';
 
   var CHIP_DEFAULT_TEMPLATE = '\
-- 
2.10.2

Ivan Zakharyaschev

Ivan Zakharyaschev

2018-02-06 22:57

reporter  

0001-MessageEditorController.js-use-comma-and-semicolon-c.patch (1,695 bytes)   
From 6903c19ff6c57b74ecd24264e35ba8826f30fc60 Mon Sep 17 00:00:00 2001
From: Ivan Zakharyaschev <imz@altlinux.org>
Date: Thu, 25 Jan 2018 14:58:37 +0300
Subject: [PATCH] MessageEditorController.js: use comma and semicolon *chars*
 rather than *keycodes* as separators

This fixes entering some letters (for example, Cyrillic Be or Zhe) in the
address fields (like To:) of the message editor so that they do not act as
"separator" keys (like comma or semicolon) any more; this error's cause
was that these letters and the separators are on the same physical keys.

(Thanks Volker Braun for implementing the underlying feature
for this fix in the old unsupported angular-material.)

Fixes:

* https://sogo.nu/bugs/view.php?id=4103
* https://sogo.nu/bugs/view.php?id=3573
* https://sogo.nu/bugs/view.php?id=3513
* https://lists.inverse.ca/sogo/arc/users/2016-07/msg00032.html
* https://sogo.nu/bugs/view.php?id=4109 (probably, too,
  although the bug report is not clear enough)
---
 UI/WebServerResources/js/Mailer/MessageEditorController.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/UI/WebServerResources/js/Mailer/MessageEditorController.js b/UI/WebServerResources/js/Mailer/MessageEditorController.js
index 7c5524d..b39c922 100644
--- a/UI/WebServerResources/js/Mailer/MessageEditorController.js
+++ b/UI/WebServerResources/js/Mailer/MessageEditorController.js
@@ -24,8 +24,8 @@
     vm.recipientSeparatorKeys = [
       $mdConstant.KEY_CODE.ENTER,
       $mdConstant.KEY_CODE.TAB,
-      $mdConstant.KEY_CODE.COMMA,
-      $mdConstant.KEY_CODE.SEMICOLON
+      ',',
+      ';'
     ];
     vm.removeAttachment = removeAttachment;
     vm.save = save;
-- 
2.10.2

francis

francis

2018-02-07 01:29

administrator   ~0012575

We use the source code of Material only to build the CSS. The pre-build JavaScript library is retrieved through bower.

If you modify the JavaScript of ng-material, you must follow their procedure:

https://github.com/angular/material/tree/v1.1.6#building

Ivan Zakharyaschev

Ivan Zakharyaschev

2018-02-07 10:14

reporter   ~0012579

We use the source code of Material only to build the CSS. The pre-build JavaScript library is retrieved through bower.

Thanks for the clarification! I'll try the bower way to test whether this patch helps.

Isn't that strange/Doesn't that add some inconsistency to the project: one source of angular-material is used for one purpose, but another revision -- for the other purpose? Can't they get too much different so that the CSS wouldn't match the other components?

francis

francis

2018-02-07 11:41

administrator   ~0012580

No. We make sure the versioning matches between the two sources.

We could eventually rely exclusively on the source code but there's no advantage for now.

Ivan Zakharyaschev

Ivan Zakharyaschev

2018-02-13 10:45

reporter   ~0012594

Well, I've determined how to compile my own version of the bower-material/ tree (with my changes). Like this (a draft of a rule in UI/WebServerResources/GNUmakefile):

js-dev:
cd angular-material && npm install
cd angular-material && ./scripts/bower-material-release.sh \
--git_push_dryrun=true --verbose=true --version=1.1.4

TODO: Then make bower use a copy of the result in

# angular-material/bower-material/ as bower_components/bower-material/
# (Either copy directly or play with bower.json.)

Issue History

Date Modified Username Field Change
2017-03-23 20:47 alaniyatm New Issue
2017-03-23 20:47 alaniyatm File Added: screen.png
2017-03-27 08:52 Christian Mack Relationship added has duplicate 0004109
2017-03-27 10:26 francis Relationship added duplicate of 0003513
2017-03-27 19:07 alaniyatm Note Added: 0011597
2017-03-27 22:16 francis Note Added: 0011598
2017-03-29 12:55 ludovic Severity major => minor
2018-02-06 22:52 Ivan Zakharyaschev Note Added: 0012573
2018-02-06 22:55 Ivan Zakharyaschev File Added: 0001-fix-chips-keypress-handler-for-chips-separator-keys.patch
2018-02-06 22:57 Ivan Zakharyaschev File Added: 0001-MessageEditorController.js-use-comma-and-semicolon-c.patch
2018-02-07 01:29 francis Note Added: 0012575
2018-02-07 10:14 Ivan Zakharyaschev Note Added: 0012579
2018-02-07 11:41 francis Note Added: 0012580
2018-02-13 10:45 Ivan Zakharyaschev Note Added: 0012594