title: Javascript, Datatables, jmhighlight and multiple searches
body: <p>I'm working with <a href="https://www.datatables.net" rel="nofollow noreferrer">DataTables plugin</a> and I've made multiple search boxes searching inside each column of the table.</p>
  
  <p>Then I've applied the <a href="https://github.com/julmot/jmHighlight" rel="nofollow noreferrer">jmHighlight plugin</a> to obtain highlighting of search results.</p>
  
  <p>Now I would have an advice from you on how modify jmHighlight code in order to obtain:</p>
  
  <ul>
  <li>different span and colors for highlight;</li>
  <li>and obtain that highlighted words don't return normal without highlight.</li>
  </ul>
  
  <p>When I call the <code>jmhighlight()</code> function I uses:</p>
  
  <pre><code> function hlCountry (e) {   //"e" is the number of col activated for search
       var $keyword = $('#col'+e+'_filter').val(); //this recover word inserted
       console.log($keyword); //this is just for test
  
       $("#example tbody #Col"+e+"_tab").jmRemoveHighlight(); //here I call jmRemoveHighlight function restricting search in specify col of table
       $("#example tbody #Col"+e+"_tab").jmHighlight($keyword);  //here I call jmHighlight function restricting search in specify col of table
   }
  </code></pre>
  
  <p>I have tried to search <code>jmRemoveHighlight()</code> and <code>jmHighlight()</code> inside <code>jquery.jmHighlight.min.js</code> (file included in page).
  Follows code:</p>
  
  <pre><code>  /*!***************************************************
    * jmHighlight
    * Version 3.1.0
    * Copyright (c) 2014–2016, Julian Motz
    *****************************************************/
    ! function(a, b) {
       "use strict";
       "function" == typeof define &amp;&amp; define.amd ? define(["jquery"], function(a, c) {
       return b(a, c)
    }) : "object" == typeof exports ? b(require("jquery"), a) : b(a.jQuery, a)
    }(this, function(a, b) {
       "use strict";
  
  function c(a, c, e) {
      return this.options = d.extend({}, {
          debug: !1,
          log: b.console,
          element: "span",
         // className: "highlight2",
          className: "highlight",
          filter: [],
          separateWordSearch: !1,
          diacritics: !0,
          synonyms: {}
      }, e), "object" != typeof this.options.log &amp;&amp; (this.options.log = {
          debug: function() {}
      }), this.keyword = "string" == typeof c ? c : "", this.$elements = d(), a instanceof d &amp;&amp; a.length &gt; 0 &amp;&amp; (this.$elements = a.add(a.find("*")), this.$elements = this.getFilteredElements()), this
  }
  var d = a;
  c.prototype.diacritics = ["aÀÁÂÃÄÅàáâãäåĀāąĄ", "cÇçćĆčČ", "dđĐďĎ", "eÈÉÊËèéêëěĚĒēęĘ", "iÌÍÎÏìíîïĪī", "lłŁ", "nÑñňŇńŃ", "oÒÓÔÕÕÖØòóôõöøŌō", "rřŘ", "sŠšśŚ", "tťŤ", "uÙÚÛÜùúûüůŮŪū", "yŸÿýÝ", "zŽžżŻźŹ"], c.prototype.getFilteredElements = function() {
      var a = this.$elements,
          b = this.options.filter;
      return "object" != typeof b || a instanceof d == !1 || "[object Array]" !== Object.prototype.toString.call(b) ? a : a = a.filter(function() {
          for (var a = d(this), c = !1, e = 0, f = b.length; f &gt; e; e++) {
              var g = b[e];
              a.is(g) &amp;&amp; (c = !0)
          }
          return c ? !1 : !0
      })
  }, c.prototype.getTextNodes = function(a) {
      var b = [];
      return a instanceof d == !1 || 0 === a.length ? b : (a.each(function() {
          var a = d(this),
              c = a.contents().filter(function() {
                  return 3 === this.nodeType ? !0 : !1
              });
          c.each(function() {
              b.push(this)
          })
      }), b)
  }, c.prototype.getKeywordRegexp = function(a) {
      var b = "string" != typeof a ? this.keyword : a;
      if ("string" != typeof b || "" === b) return b;
      var c = b;
      return d.isEmptyObject(this.options.synonyms) || (c = this.getSynonymsRegex(c)), this.options.diacritics &amp;&amp; (c = this.getDiacriticRegex(c)), c
  }, c.prototype.getSynonymsRegex = function(a) {
      var b = a;
      return "string" != typeof b ? b : (d.each(this.options.synonyms, function(a, c) {
          var d = a,
              e = c;
          b = b.replace(new RegExp("(" + d + "|" + e + ")", "gmi"), "(" + d + "|" + e + ")")
      }), b)
  }, c.prototype.getDiacriticRegex = function(a) {
      var b = a;
      if ("string" != typeof b) return b;
      for (var c = b.split(""), d = [], e = 0, f = c.length; f &gt; e; e++)
          for (var g = c[e], h = 0, i = this.diacritics.length; i &gt; h; h++) {
              var j = this.diacritics[h];
              if (-1 !== j.indexOf(g)) {
                  if (d.indexOf(j) &gt; -1) continue;
                  b = b.replace(new RegExp("[" + j + "]", "gmi"), "[" + j + "]"), d.push(j)
              }
          }
      return b
  }, c.prototype.highlight = function(a) {
      var b = "string" != typeof a ? this.keyword : a;
      if ("" === b) return !0;
      if (0 === this.$elements.length) return this.options.debug &amp;&amp; this.options.log.debug("No search context provided"), !1;
      this.$elements = this.$elements.filter("*:not([data-jmHighlight])");
      var c = this.options.separateWordSearch;
      if ("boolean" == typeof c &amp;&amp; c) {
          var d = b.split(" ");
          if (d.length &gt; 1) {
              this.options.debug &amp;&amp; this.options.log.debug("Highlighting keywords separately");
              for (var e = 0, f = d.length; f &gt; e; e++)
                  if (!this.highlight(d[e])) return !1;
              return !0
          }
      }
      this.options.debug &amp;&amp; (this.options.log.debug("Highlighting keyword '" + b + "' in elements:"), this.options.log.debug(this.$elements));
      for (var g = this.getKeywordRegexp(b), h = new RegExp(g, "mi"), i = this.getTextNodes(this.$elements), j = 0, k = i.length; k &gt; j; j++) {
          var l = i[j];
          if ("object" == typeof l &amp;&amp; "string" == typeof l.nodeValue &amp;&amp; "" !== l.nodeValue.trim() &amp;&amp; h.test(l.nodeValue) !== !1 &amp;&amp; (this.options.debug &amp;&amp; this.options.log.debug("Regex: '" + g + "'. Node value: '" + l.nodeValue + "'"), null != l.parentNode)) {
              var m = new RegExp("((?![^&lt;]*&gt;)" + g + ")", "gim");
              l.parentNode.innerHTML = l.parentNode.innerHTML.replace(m, this.getHighlightTag("$1"))
          }
      }
      return !0
  }, c.prototype.getHighlightTag = function(a) {
      var b = "&lt;" + this.options.element + " class='" + this.options.className + "' data-jmHighlight='true'&gt;",
          c = "&lt;/" + this.options.element + "&gt;";
      return "string" != typeof a &amp;&amp; (a = ""), b + a + c
  }, c.prototype.removeHighlight = function() {
      if (0 === this.$elements.length) return this.options.debug &amp;&amp; this.options.log.debug("No search context provided"), !1;
      this.options.debug &amp;&amp; ("string" == typeof this.keyword &amp;&amp; "" !== this.keyword ? this.options.log.debug("Removing highlighting with keyword: '" + this.keyword + "'") : this.options.log.debug("Removing highlighting"));
      var a = new RegExp(this.getKeywordRegexp(), "mi"),
          b = this.options.element + "[data-jmHighlight]." + this.options.className,
          c = this,
          e = this.$elements.filter(b);
      return this.options.debug &amp;&amp; (this.options.log.debug(b), this.options.log.debug(e)), e.each(function() {
          var b = d(this);
          return a.test(b.text()) ? void c.appendTextNodes(b, e) : !0
      }), !0
  }, c.prototype.appendTextNodes = function(a, b) {
      if (a instanceof d == !1 || 0 === a.length) return !1;
      var c = a.first()[0],
          e = c.previousSibling,
          f = c.nextSibling,
          g = d(e),
          h = d(f),
          i = !1;
      return g.length &gt; 0 &amp;&amp; (3 === e.nodeType ? (e.nodeValue = e.nodeValue + a.text(), a.remove()) : b instanceof d &amp;&amp; b.length &gt; 0 &amp;&amp; b.is(g) ? (g.replaceWith(a.text() + g.text()), a.remove()) : a.replaceWith(a.text()), i = !0), h.length &gt; 0 &amp;&amp; (3 === f.nodeType ? 0 === g.length ? (f.nodeValue = a.text() + f.nodeValue, a.remove()) : (f.nodeValue = g.text() + f.nodeValue, g.remove()) : b instanceof d &amp;&amp; b.length &gt; 0 &amp;&amp; b.is(h) ? 0 === g.length ? (h.replaceWith(h.text() + a.text()), a.remove()) : (h.replaceWith(g.text() + h.text()), g.remove()) : 0 === g.length &amp;&amp; a.replaceWith(a.text()), i = !0), i === !1 &amp;&amp; a.replaceWith(a.text()), !0
  }, d.fn.jmHighlight = function(a, b) {
      var e = new c(d(this), a, b);
      return e.highlight()
  }, d.fn.jmRemoveHighlight = function(a, b) {
      var e = new c(d(this), b, a);
      return e.removeHighlight()
  }
  });
  </code></pre>
  
  <p>This code is really complex to me. I thought I would have found <code>jmRemoveHighlight()</code> and <code>jmHighlight()</code> inside code, but there wasn't.</p>
  
  <p>For sure I should work on <code>&lt;span&gt;</code> and <code>&lt;class name&gt;</code> but I don't know exactly how.</p>
  
  <p>The dev of plugin written:</p>
  
  <blockquote>
    <p>You can also highlight multiple keywords/phrases with different classes in the context. Just clone this code below for each keyword. Pass an array <code>filter</code> in the option-object. The filter-array should contain all selectors that should be ignored.</p>
  </blockquote>
  
  <p>But I was unable to do it. Could please show me the direction to take in order to solve this problem?</p>