Repository: cbouy/mols2grid (language: python)

Issue:
Searching CAS numbers
Hello,

I have a dataframe with two columns, 'SMILES', and 'CAS', with both containing their obvious entities. One issue I am having is that the search tool, when 'text' searching for CAS number, doesn't seem to work with the built in dashes in CAS numbers, (e.g., 50-00-0). For example, if I were to start typing in '50' it would find all the text with '50' somewhere in it, but as soon as i type '50-' it doesn't find anything.

Obviously I could just remove all the dashes from the CAS numbers and just instruct users of my app to do the same, but I'd like to keep the original number present if possible.

I'm surprised this issue hasn't come up before. Any suggestions?


Discussion / hints:
It's a known problem in the underlying library that I use to create the paginated grid, but there hasn't been any answer from the maintainer of the lib in a while now.
Basically if you have a regex character (`[-[\]{}()*+?.,\\^$|#`) in your search it will fail.

I'll see if I can somehow patch it, but apart from removing the dashes as you suggested I don't see any other quick workaround at the moment...

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index aacbf54..0ddb972 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
   specifying a callback.
 
 ### Fixed
+- Issue #34: text searches containing any of the following regex characters
+  `-[]{}()*+?.,\^$|#` would automatically return an empty grid, preventing searching
+  for CAS numbers and any other identifier or text containing the above characters. This
+  has been temporarily patched until a proper fix is released in the underlying
+  `list.js` library.
 - The link to the KNIME component on the corresponding badges has been fixed.
 
 ---
diff --git a/mols2grid/templates/js/search.js b/mols2grid/templates/js/search.js
index 5b5f7f0..24787a3 100644
--- a/mols2grid/templates/js/search.js
+++ b/mols2grid/templates/js/search.js
@@ -37,11 +37,32 @@ function SmartsSearch(query, columns) {
     qmol.delete();
 }
 var search_type = "Text";
+// Temporary fix for regex characters being escaped by list.js
+// This extends String.replace to ignore the regex pattern used by list.js and returns
+// the string unmodified. Other calls should not be affected, unless they use the exact
+// same pattern and replacement value.
+// TODO: remove once the issue is fixed in list.js and released
+String.prototype.replace = (function(_super) {
+    return function() {
+        if (
+            (arguments[0].toString() === '/[-[\\]{}()*+?.,\\\\^$|#]/g')
+            && (arguments[1] === '\\$&')
+        ) {
+            if (this.length === 0) {
+                return ''
+            }
+            return this
+        }
+        return _super.apply(this, arguments);
+    };         
+})(String.prototype.replace);
+// Switch search type (Text or SMARTS)
 $('#mols2grid .search-btn').click(function() {
     search_type = $(this).text();
     $('#mols2grid button.search-btn.active').removeClass("active");
     $(this).addClass("active");
 });
+// Searchbar update event handler
 $('#mols2grid #searchbar').on("keyup", function(e) {
     var query = e.target.value;
     if (search_type === "Text") {


Test patch:
diff --git a/tests/test_interface.py b/tests/test_interface.py
index e600a33..ccc2744 100644
--- a/tests/test_interface.py
+++ b/tests/test_interface.py
@@ -216,6 +216,13 @@ def test_text_search(driver: FirefoxDriver, html_doc):
     el = driver.find_by_css_selector("#mols2grid .cell .data-SMILES")
     assert el.get_attribute("innerHTML") == "CC(I)C"
 
+def test_text_search_regex_chars(driver: FirefoxDriver, html_doc):
+    driver.get(html_doc)
+    driver.wait_for_img_load()
+    driver.text_search("1-pentene")
+    el = driver.find_by_css_selector("#mols2grid .cell .data-SMILES")
+    assert el.get_attribute("innerHTML") == "CCCC=C"
+
 @flaky(max_runs=3, min_passes=1)
 def test_smarts_search(driver: FirefoxDriver, html_doc):
     driver.get(html_doc)