Return cursor position for query object (fixes #228)

Change-Id: I8a7e872dfcce38d2f525d07c1bb3fc84f25250c3
diff --git a/Changes b/Changes
index 6c60dae..e9d0a5a 100644
--- a/Changes
+++ b/Changes
@@ -1,4 +1,4 @@
-0.59 2024-11-18
+0.59 2024-11-21
         - Improve appearance of title-addon on logo. (uyen-nhu)
         - Create and style new item on top navbar for 'News'. (uyen-nhu)
         - Change settings link in logout.html.ep to dynamic link. (uyen-nhu)
@@ -18,6 +18,7 @@
           change navbar size and input fields, improve positionings of
           logo and icons, fix animation of navbar when scrolling on
           small devices. (uyen-nhu)
+        - Return cursor position for query object (fixes #228; diewald)
 
 0.58 2024-11-15
         - Cookie path is settable now (hebasta)
diff --git a/dev/js/spec/hintSpec.js b/dev/js/spec/hintSpec.js
index cefd428..e98b92a 100644
--- a/dev/js/spec/hintSpec.js
+++ b/dev/js/spec/hintSpec.js
@@ -139,6 +139,8 @@
       expect(input.style.left).toEqual("30px");
       expect(inputField.mirror().style.left.match(/^(\d+)px$/)[1]).toBeGreaterThan(29);
       expect(inputField.mirror().style.top.match(/^(\d+)px$/)[1]).toBeGreaterThan(20);
+      expect(inputField.selectionRange()[0]).toEqual(5);
+      expect(inputField.selectionRange()[1]).toEqual(5);
     });
 
     it('should have a correct context', function () {
diff --git a/dev/js/src/hint.js b/dev/js/src/hint.js
index 80262cc..de9c09b 100644
--- a/dev/js/src/hint.js
+++ b/dev/js/src/hint.js
@@ -153,6 +153,14 @@
 
 
     /**
+     * Return selection range of the input field.
+     */
+    selectionRange : function () {
+      return this._inputField.selectionRange();
+    },
+
+
+    /**
      * Alert at a specific character position.
      */
     alert : function (charPos, msg) {
diff --git a/dev/js/src/hint/input.js b/dev/js/src/hint/input.js
index cabaa84..520b9e4 100644
--- a/dev/js/src/hint/input.js
+++ b/dev/js/src/hint/input.js
@@ -40,6 +40,16 @@
       window.addEventListener('resize', re);
       this._el.addEventListener('onfocus', re);
       this.reposition();
+
+      // Prevent multiselections
+      this._el.addEventListener("select", () => {
+        const start = this._el.selectionStart;
+        const end = this._el.selectionEnd;
+        if (start !== null && end !== null && start !== end) {
+          this._el.setSelectionRange(start, end);
+        }
+      });
+
       return this;
     },
 
@@ -198,6 +208,13 @@
         value.substring(0, start),
         value.substring(start, value.length)
       );
+    },
+
+    /**
+     * Return the cursor character offsets
+     */
+    selectionRange : function () {
+      return [this._el.selectionStart, this._el.selectionEnd];
     }
   }
 });
diff --git a/dev/js/src/plugin/server.js b/dev/js/src/plugin/server.js
index 76d1a0e..b95d830 100644
--- a/dev/js/src/plugin/server.js
+++ b/dev/js/src/plugin/server.js
@@ -514,6 +514,9 @@
           if (el = KorAP.vc) {
             v["cq"] = el.toQuery();
           };
+          if (el = KorAP.Hint) {
+            v["selection"] = KorAP.Hint.selectionRange();
+          };
         }
 
         // Get text sigle from match
diff --git a/package.json b/package.json
index 755b1af..204bd0c 100644
--- a/package.json
+++ b/package.json
@@ -2,8 +2,8 @@
   "name": "Kalamar",
   "description": "Mojolicious-based Frontend for KorAP",
   "license": "BSD-2-Clause",
-  "version": "0.59.0",
-  "pluginVersion": "0.2.2",
+  "version": "0.59.1",
+  "pluginVersion": "0.2.3",
   "engines": {
     "node": ">=6.0.0"
   },