Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mark.js in Tablesorter #1243

Closed
airthomas opened this issue Jul 4, 2016 · 20 comments
Closed

mark.js in Tablesorter #1243

airthomas opened this issue Jul 4, 2016 · 20 comments

Comments

@airthomas
Copy link

airthomas commented Jul 4, 2016

Hi Mottie,

Sorry, it is a feature request, can mark.js or tablesorter self work word hgihlight in tablesorter after filter ?

Many thanks.

@Mottie
Copy link
Owner

Mottie commented Jul 4, 2016

Hi @airthomas!

I'll see what I can do!

@airthomas
Copy link
Author

many thanks.

@Mottie
Copy link
Owner

Mottie commented Jul 11, 2016

I forgot about this because you closed it LOL...

Here is a demo.

I basically copied the "official" mark.js demo code into the tablesorter playground.

@airthomas
Copy link
Author

The demo looks great, any method to unmark thead ? and how can implement it if "filter by column".
Thanks your help.

@Mottie
Copy link
Owner

Mottie commented Jul 12, 2016

Ok, how about this demo

It sets the marks per column using the filter widget, and the external input marks all columns.

HTML

Highlight: <input type="text" name="keyword" data-column="all">
<p>Options:</p>
<ul>
  <li><input type="checkbox" name="opt[]" value="separateWordSearch" checked> separate word search</li>
  <li><input type="checkbox" name="opt[]" value="diacritics" checked> diacritics</li>
  <li><input type="checkbox" name="opt[]" value="debug"> debug</li>
</ul>
<button type="button" class="reset">Reset</button>
<table class="tablesorter">
  <!-- ... -->
</table>

Script

$(function() {

  var $table = $('table');

  function mark() {
    // Read the keyword
    var keyword = $("input[name='keyword']").val();

    // Determine selected options
    var options = {};
    $("input[name='opt[]']").each(function() {
      options[$(this).val()] = $(this).is(":checked");
    });

    var $rows = $(".tablesorter tbody tr");
    $rows.unmark();
    var filters = $.tablesorter.getFilters($table);
    $.each(filters, function(indx, filter) {
      var col = indx === $table[0].config.columns ? '' : ':nth-child(' + (indx + 1) + ')';
      $rows.children(col).mark(filter, options);
    });
  }

  $("input[name='keyword']").on("input", mark);
  $("input[type='checkbox']").on("change", mark);

  $table
    .on('filterEnd', mark)
    .tablesorter({
      theme: 'blue',
      widgets: ['zebra', 'filter'],
      widgetOptions: {
        filter_external: 'input[name="keyword"]',
        filter_reset: '.reset'
      }
    });
});

There is also some extra css to change the color of the mark per column:

tr td:nth-child(1) mark {
  background: #aa0000;
  color: #fff;
}

tr td:nth-child(2) mark {
  background: #00aa00;
  color: #fff;
}

tr td:nth-child(3) mark {
  background: #0000aa;
  color: #fff;
}

@airthomas
Copy link
Author

It's really cool and awesome !!! many thanks Mottie.

@airthomas airthomas reopened this Jul 12, 2016
@TheSin-
Copy link
Collaborator

TheSin- commented Jul 12, 2016

bag and tag it, widget-mark.js ;)

@Mottie
Copy link
Owner

Mottie commented Jul 20, 2016

Actaully, I've been working on making a widget-mark.js. I've been trying to get it to work properly with regex - see https://github.com/julmot/mark.js/issues/55.

It should be ready for the next release.

Mottie added a commit that referenced this issue Jul 27, 2016
@julkue
Copy link

julkue commented Aug 2, 2016

@Mottie Fantastic 🍻

@LaRemond
Copy link

LaRemond commented Aug 2, 2016

Hello Mottie,

In my case version 2.7.1 works beautifully 👍 as long as I enter uppercase text in filter_external field.
When text is lowercase and longer than 2-3 characters, rows are filtered but but for some reason text is not highligthed.

I've got the impression that the mark_ settings - at least mark_diacritics : false in my case - are not being taken into account. Is that possible?

Here is my TableSorter definition (sorry it's a bit crowded...):

  var $table = $("#studiesList").tablesorter({
      widthFixed          : true,
      theme               : 'blue',
      cssChildRow         : "tablesorter-childRow",
      sortLocaleCompare   : true,                     // sort & filter diacritics
      debug               : true,                     // TODO normally false
      headers: {
          0: { sorter: false, filter: false },        
          1: { sorter: false, filter: false  },       
          2: { sorter: false, filter: false  },       
          3: { sorter: 'examen' },                    
          4: { sorter: 'date' },                      
          5: { sorter: false }                        
      },
      sortList: [[4,1]],                              // Sort on the 4th column (date of examination) in descending order
      widgets: ['zebra', 'scroller', 'filter', 'mark'],
      widgetOptions : {
          scroller_height         : 300,              // height of scroll window
          scroller_jumpToHeader   : true,             // header snap to browser top when scrolling the tbody
          scroller_upAfterSort    : true,             // scroll tbody to top after sorting (new in v2.26.6) - default = true
          scroller_fixedColumns   : 0,                // set number of fixed columns (new in v2.26.6)
          scroller_height         : 0,                // Set the height of the scroll window in pixels (new in v2.26.6); setting this option to an empty string or zero will make the scroller full height

          filter_cssFilter        : '',
          filter_childRows        : true,             // If true, non-XC images having XC somewhere in the child row will be selected and therefore displayed
                                                      // Needs to be set to false when XC only have to be displayed (see JS function setStudiesListFilterChildRows) 
          filter_hideFilters      : false,
          filter_ignoreCase       : true,
          filter_startsWith       : false,

          filter_liveSearch       : true,
          filter_searchDelay      : 300,

          filter_external         : "input[name='keyword']",      // jQuery selector (or object) pointing to an input to be used to match the contents of any column (v2.15)
          filter_columnFilters    : true,             // To display the internal table filters (could be omitted before v2.26.5)
          filter_saveFilters      : false,
          filter_reset            : '.reset',

          // mark.js default settings
          mark_accuracy           : 'partially',
          mark_className          : '',
          mark_debug              : true,             // TODO normally false
          mark_diacritics         : false,
          mark_element            : 'mark',
          mark_exclude            : [],
          mark_iframes            : true,             // TODO normally false
          mark_log                : console,
          mark_separateWordSearch : true,
          mark_synonyms           : {},
          // mark.js callback functions
          mark_done               : function(totalMatches) {},
          mark_each               : function(element) {},
          mark_filter             : function(node, term, counter, totalCounter) { return true; },
          mark_noMatch            : function(keyword) {}
      }
  });

I'm pretty sure I'm doing something wrong, only that I cannot figure out what.

Tracing function ts.mark.update in widget-mark.js seems to show that filters set immediately before the extract & save mark options from widgetOptions (prefixed with "mark_") contain the text being searched for rather than the widget options.

What am I missing ?

Thanks in advance for your help

@Mottie
Copy link
Owner

Mottie commented Aug 2, 2016

Hi @LaRemond!

It looks like I actually left out the code to transfer the mark widgetOptions into the mark plugin. I've updated the widget in the master branch for now.

@LaRemond
Copy link

LaRemond commented Aug 3, 2016

Well done @Mottie, now it works really well.
Awesome !!
👍 👍 👍 👍 👍

Thanks +++++

@julkue
Copy link

julkue commented Aug 3, 2016

@Mottie Aren't you using unit tests in tablesorter?

@Mottie
Copy link
Owner

Mottie commented Aug 3, 2016

LOL, yes, but I've gotten lazy about making unit tests for all the widgets.

@LaRemond
Copy link

LaRemond commented Aug 3, 2016

Tip for newbies like myself working on oldish projects:

jquery.mark.js and jquery.mark.min.js have UTF-8 as a character encoding.
Unless your default is UTF-8, the charset must be specified when embedding one of these files in your page header, as follows:

<script src="js/jquery.mark.min.js" charset="UTF-8" ></script>

If the charset is not specified and the default is not UTF-8, highlighting may just not work.
For example, search on upper case text may be marked, whereas lower case text longer than 2-3 characters is not.

As far as I can see, with a default charset other than UTF-8, strings used to match diacritics (such as "aÀÁÂÃÄÅàáâãäåĀāąĄ" , "cÇçćĆčČ", etc) are transformed into something completely unexpected, and therefore no match can be found.

Hope it helps
😅

julkue added a commit to julkue/mark.js that referenced this issue Aug 3, 2016
@Mottie
Copy link
Owner

Mottie commented Aug 3, 2016

It might help if we encoded the strings as unicode. For example:

"aÀÁÂÃÄÅàáâãäåĀāąĄ"

becomes

"a\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u0100\u0101\u0105\u0104"

@JamoCA
Copy link

JamoCA commented Aug 30, 2016

I wrote a hack to apply mark.js to tablesorter cells by parsing filter keywords and converting them to an array. This was before I learned that there was an official widget.

}).on('pagerChange pagerComplete pagerInitialized pageMoved', function(e, table){
    var q = [];
    $('div.TableWrapper').unmark();
    $('#myTable input.tablesorter-filter').each(function(i){
        if ($(this).val() !== ''){
            q.push($(this).val());
        }
    });
    if (q.length){
        q = q.toString().replace(/[,]/gi, " ").split(" "); /* convert to space-delim list & back to array */
        $('div.TableWrapper').mark(q);
        console.log('highlighted keywords', e, q, new Date);
    }           
})

I tried the widget (8/1/2016 v2.27.2) and it works fine with inline data, but doesn't seem to highlight table data using paginated ajax requests. Keywords are highlighted in realtime, but when the ajax results are performed and the table is updated, there aren't any highlights. I'm using the default Mark settings from the Mark Widget Demo. Am I doing it wrong or is this a potential bug?

I added this event listener and it forces a mark update after pager ajax updates. (I have a filter delay of 500ms, so the keywords are highlighted immediately, the ajax search is performed, data refresh occurs and then keywords are re-highlighted.)

}).on('pagerChange pagerComplete pagerInitialized pageMoved', function(e, table){
    $('#myTable').trigger('markUpdate');
})

@JamoCA
Copy link

JamoCA commented Aug 30, 2016

I wanted to exclude some columns from being highlighted. There's no option to do this, but the effect can be somewhat nullified by using CSS overrides:

tr td:nth-child(1) mark { background:inherit; color:inherit;}

@Mottie
Copy link
Owner

Mottie commented Aug 30, 2016

Thanks @JamoCA!

The mark widget is set up to only update after a "filterEnd" event, which should be firing after a "pagerComplete". I'll check it out.

I'll also look into add a column exception option in the mark widget.

@Mottie
Copy link
Owner

Mottie commented Aug 30, 2016

Ok @JamoCA!

Try the updated widget in the master branch.

Add a mark_tsIgnore widget option to ignore a column(s)

mark_tsIgnore: {
  1 : true // second column (zero-based index)
}

or add a "mark-ignore" class name to the header.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants