Improve RegEx button in vc builder

Change-Id: Iea748a41b78e4112a1e884b9b0ca6be05c5332e8
diff --git a/Changes b/Changes
index 411a21b..5b5a855 100755
--- a/Changes
+++ b/Changes
@@ -1,4 +1,4 @@
-0.40 2020-12-02
+0.40 2020-12-03
         - Modernize ES and fix in-loops.
         - add roll() method to state object.
         - Fix wrong hint-mirror behaviour in Firefox.
@@ -14,6 +14,7 @@
           or no longer supported by LDAP) (#99).
         - Fix requirement of KorAP.vc in docgroupref
           (which broke the vc demo).
+        - Improve RegEx-Button in vc builder.
 
 0.39 2020-10-07
         - Add information on secret file to Readme.
diff --git a/dev/js/spec/vcSpec.js b/dev/js/spec/vcSpec.js
index 83ee822..bfdf9fa 100644
--- a/dev/js/spec/vcSpec.js
+++ b/dev/js/spec/vcSpec.js
@@ -2824,10 +2824,17 @@
     });
 
     it('should have a classed element', function () {
-      var sv = stringValClass.create();
+      const sv = stringValClass.create();
       expect(sv.element().classList.contains('regex')).toBe(false);
       expect(sv.regex()).toBe(false);
-      sv.toggleRegex();
+
+      const re = sv.element().children[1];
+      expect(re.textContent).toEqual('RegEx');
+      expect(re.getAttribute("title")).toEqual('Use as regular expression');
+
+      // Run event instead toggleRegex()
+      re.click();
+
       expect(sv.element().classList.contains('regex')).toBe(true);
     });
 
diff --git a/dev/js/src/loc/de.js b/dev/js/src/loc/de.js
index 21bf629..6daed13 100644
--- a/dev/js/src/loc/de.js
+++ b/dev/js/src/loc/de.js
@@ -10,6 +10,9 @@
   loc.VC_allCorpora = 'allen Korpora';
   loc.VC_oneCollection = 'einem virtuellen Korpus';
 
+  // Regex:
+  loc.REGEX_DESC = loc.REGEX_DESC || 'Regulären Ausdruck verwenden';
+
   // Date picker:
   loc.WDAY = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'];
   loc.MONTH = [
diff --git a/dev/js/src/vc/stringval.js b/dev/js/src/vc/stringval.js
index 54f92ec..fde86ad 100644
--- a/dev/js/src/vc/stringval.js
+++ b/dev/js/src/vc/stringval.js
@@ -3,216 +3,223 @@
  */
 "use strict";
 
-define(['util'], {
+define(['util'], function () {
 
-  /**
-   * Create new string value helper.
-   */
-  create : function () {
-    const a = arguments;
-    let regexOp = true,
-        regex = false,
-        value = '';
+  const loc = KorAP.Locale;
+  loc.REGEX      = loc.REGEX      || 'RegEx';
+  loc.REGEX_DESC = loc.REGEX_DESC || 'Use a regular expression';
 
-    // Set value
-    if (a.length >= 1) {
-      if (a[0] !== undefined)
-        value = a[0];
-    };
+  return {
+    /**
+     * Create new string value helper.
+     */
+    create : function () {
+      const a = arguments;
+      let regexOp = true,
+          regex = false,
+          value = '';
 
-    // Set regex
-    if (a.length >= 2) {
-      if (a[1] !== undefined)
-        regex = a[1];
-    };
+      // Set value
+      if (a.length >= 1) {
+        if (a[0] !== undefined)
+          value = a[0];
+      };
 
-    // Set regexOp
-    if (a.length >= 3) {
-      regexOp = a[2];
-      if (regexOp === false) {
-        regex = false;
-      }
-    };
-    return Object.create(this)._init(value, regex, regexOp);
-  },
-  
+      // Set regex
+      if (a.length >= 2) {
+        if (a[1] !== undefined)
+          regex = a[1];
+      };
 
-  // Initialize the string value
-  _init : function (value, regex, regexOp) {
-    this.value(value);
-    this.regex(regex);
-    this._regexOp(regexOp);
-    return this;
-  },
-
-
-  /**
-   * Get or set the regex boolean value.
-   *
-   * @param bool Either true or false
-   */
-  regex : function (bool) {
-    if (arguments.length === 1) {
-	    this._regex = bool ? true : false;
-      this._update();
-    };
-    return this._regex;
-  },
-
-
-  _regexOp : function (regexOp) {
-    if (arguments.length === 1) {
-      this.__regexOp = regexOp ? true : false;
-      this._update();
-    };
-    return this.__regexOp;
-  },
-
-
-  /**
-   * Toggle the regex, make it either true,
-   * if it is false, or make it false, if it is true.
-   */
-  toggleRegex : function () {
-    this.regex(this._regex === false ? true : false);
-  },
-  
-
-  /**
-   * Get or set the string value.
-   */
-  value : function (val) {
-    if (arguments.length === 1) {
-      this._value = val;
-      // this._input.value = val;
-      this._update();
-    };
-    return this._value;
-  },
-
-
-  // Update dom element
-  _update : function () {
-    if (this._el === undefined)
-      return;
- 
-    this._value = this._input.value;
-
-    const cl = this._el.classList;
-
-    if (this._regexOp() && this._regex) {
-      cl.add('regex');
-    }
-    else {
-      cl.remove('regex');
-    };
-  },
-  
-
-  /**
-   * Store the string value.
-   * This method should be overwritten.
-   * The method receives the value and the regex.
-   */
-  store : function (v,r) {},
-
-
-  /**
-   * Put focus on element
-   */
-  focus : function () {
-    this._el.children[0].focus();
-  },
-
-
-  /**
-   * Get the associated dom element.
-   */
-  element : function () {
-    if (this._el !== undefined)
-      return this._el;
-
-    // Create element
-    const e = this._el = document.createElement('div');
-    e.setAttribute('tabindex', 0);
-    e.style.outline = 0;
-
-    const cl = e.classList;
-    cl.add('value');
-    if (this.regex() === true)
-      cl.add('regex');
+      // Set regexOp
+      if (a.length >= 3) {
+        regexOp = a[2];
+        if (regexOp === false) {
+          regex = false;
+        }
+      };
+      return Object.create(this)._init(value, regex, regexOp);
+    },
     
-    // Add input field
-    this._input = e.addE('input');
 
-    if (this.value() !== undefined) {
-      this._input.value = this.value();
-    };
+    // Initialize the string value
+    _init : function (value, regex, regexOp) {
+      this.value(value);
+      this.regex(regex);
+      this._regexOp(regexOp);
+      return this;
+    },
 
-    // Add regex button
-    if (this._regexOp()) {
-      const re = e.addE('div');
-      re.addEventListener(
-        'click',
-        function () {
-	        this.toggleRegex();
-          // ev.halt();
-        }.bind(this),
-        true
+
+    /**
+     * Get or set the regex boolean value.
+     *
+     * @param bool Either true or false
+     */
+    regex : function (bool) {
+      if (arguments.length === 1) {
+	      this._regex = bool ? true : false;
+        this._update();
+      };
+      return this._regex;
+    },
+
+
+    _regexOp : function (regexOp) {
+      if (arguments.length === 1) {
+        this.__regexOp = regexOp ? true : false;
+        this._update();
+      };
+      return this.__regexOp;
+    },
+
+
+    /**
+     * Toggle the regex, make it either true,
+     * if it is false, or make it false, if it is true.
+     */
+    toggleRegex : function () {
+      this.regex(this._regex === false ? true : false);
+    },
+    
+
+    /**
+     * Get or set the string value.
+     */
+    value : function (val) {
+      if (arguments.length === 1) {
+        this._value = val;
+        // this._input.value = val;
+        this._update();
+      };
+      return this._value;
+    },
+
+
+    // Update dom element
+    _update : function () {
+      if (this._el === undefined)
+        return;
+      
+      this._value = this._input.value;
+
+      const cl = this._el.classList;
+
+      if (this._regexOp() && this._regex) {
+        cl.add('regex');
+      }
+      else {
+        cl.remove('regex');
+      };
+    },
+    
+
+    /**
+     * Store the string value.
+     * This method should be overwritten.
+     * The method receives the value and the regex.
+     */
+    store : function (v,r) {},
+
+
+    /**
+     * Put focus on element
+     */
+    focus : function () {
+      this._el.children[0].focus();
+    },
+
+
+    /**
+     * Get the associated dom element.
+     */
+    element : function () {
+      if (this._el !== undefined)
+        return this._el;
+
+      // Create element
+      const e = this._el = document.createElement('div');
+      e.setAttribute('tabindex', 0);
+      e.style.outline = 0;
+
+      const cl = e.classList;
+      cl.add('value');
+      if (this.regex() === true)
+        cl.add('regex');
+      
+      // Add input field
+      this._input = e.addE('input');
+
+      if (this.value() !== undefined) {
+        this._input.value = this.value();
+      };
+
+      // Add regex button
+      if (this._regexOp()) {
+        const re = e.addE('div');
+        re.addEventListener(
+          'click',
+          function () {
+	          this.toggleRegex();
+            // ev.halt();
+          }.bind(this),
+          true
+        );
+        re.setAttribute("title", "Use as regular expression");
+        re.addT('RegEx');
+      };
+
+      // If the focus is not on the text field anymore,
+      // delegate focus to
+      this._input.addEventListener(
+        'blur',
+        function (ev) {
+          const t = this;
+          if (!t._inField) {
+	          t.value(t._input.value);
+            t.store(t.value(), t.regex());
+          };
+          ev.halt();
+        }.bind(this)
       );
-      re.addT('RE');
-    };
 
-    // If the focus is not on the text field anymore,
-    // delegate focus to
-    this._input.addEventListener(
-      'blur',
-      function () {
-        const t = this;
-        if (!t._inField) {
-	        t.value(t._input.value);
-          t.store(t.value(), t.regex());
-        };
-        ev.halt();
-      }.bind(this)
-    );
+      // Workaround to check the click is in the field
+      e.addEventListener(
+        'mousedown',
+        function () {
+          this._inField = true;
+        }.bind(this)
+      );
 
-    // Workaround to check the click is in the field
-    e.addEventListener(
-      'mousedown',
-      function () {
-        this._inField = true;
-      }.bind(this)
-    );
+      e.addEventListener(
+        'mouseup',
+        function () {
+          this._inField = false;
+          this._input.focus();
+        }.bind(this)
+      );
 
-    e.addEventListener(
-      'mouseup',
-      function () {
-        this._inField = false;
-        this._input.focus();
-      }.bind(this)
-    );
+      this._input.addEventListener(
+        'keypress',
+        function (ev) {
+          const t = this;
+	        if (ev.keyCode == 13) {
+	          t.value(t._input.value);
+	          t.store(t.value(), t.regex());
+            return false;
+	        };
+        }.bind(this)
+      );
 
-    this._input.addEventListener(
-      'keypress',
-      function (ev) {
-        const t = this;
-	      if (ev.keyCode == 13) {
-	        t.value(t._input.value);
-	        t.store(t.value(), t.regex());
-          return false;
-	      };
-      }.bind(this)
-    );
-
-    // Add store button
-    /*
-    e.appendChild(
-      document.createElement('div')
-    ).addEventListener('click', function () {
-      this.store(this.value(), this.regex());
-    }.bind(this));
-    */
-    return e;
-  }
+      // Add store button
+      /*
+        e.appendChild(
+        document.createElement('div')
+        ).addEventListener('click', function () {
+        this.store(this.value(), this.regex());
+        }.bind(this));
+      */
+      return e;
+    }
+  };
 });
diff --git a/dev/scss/header/vc.scss b/dev/scss/header/vc.scss
index 4ecd4f8..edd83e9 100644
--- a/dev/scss/header/vc.scss
+++ b/dev/scss/header/vc.scss
@@ -212,6 +212,7 @@
   div.value {
     position:   absolute;
     display:    inline-block;
+    min-width:  max-content;
     z-index:    8000;
     padding:    4pt;
     margin-top: -6pt;
@@ -224,12 +225,14 @@
 
     input {
       border-width: 0;
+      outline-width: 0;
     }
 
     > div {
       @include choose-item;
       display: inline-block;
-      padding: 2pt;
+      padding: 0 4pt;
+      margin-left: 4pt;
 
       font: {
         size:  80%;