Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

Filterable and Sortable Memberlist for Jcink, using isotope
   (0 reviews)

Kit the Human
  • A few weeks ago, the editable templates for Jcink's memberlist went live on all sites. This is a fantastic opportunity for admins to create a memberlist that can be filtered by factions, or sorted on playby, without having to update and maintain a list.


    I'm going to show you how you can do this using isotope and custom profile fields. This code can be used by any software (just substitute your variables and templates) but I am targeting administrators of jcink sites in particular.

    Type: Javascript Software: Jcink 183,99

To get started, set up a couple of custom profile fields. For the purposes of this exercise, we're going to use the following:

  • Character Faction
  • Character Age
  • Character's Playby

I strongly recommend that Character Faction is a drop down selection, the script relies on everyone using the same spelling and capitalisation. Example:




Character Age and Playby does not need any special settings.


Save your custom profile fields and take note of their numbers. In my case they will be:

  • Character Faction - <!-- |field_21| -->
  • Character Age - <!-- |field_2| -->
  • Character Playby - <!-- |field_17| -->


Go to your HTML templates. We need to edit the following:


Member List Header - HTML and Javascript

Paste the following:

<!-- START SORT BY -->
<h3>Sort by:</h3>
<div id="sorts" class="button-group">
	<button class="button is-checked" data-sort-by="original-order">original order</button>
	<button class="button" data-sort-by="face">Face Claim</button>
  	<button class="button" data-sort-by="age">Character Age</button>
<!-- END SORT BY -->

<div class="filters">

<div class="ui-group">
<h3>Filter by Character Faction</h3>
<div class="button-group js-radio-button-group" data-filter-group="species">
  <button class="button is-checked" data-filter="*">show all</button>
  <button class="button" data-filter=".Good">The Good Guys</button>
  <button class="button" data-filter=".Evil">The Bad Guys</button>



<div class="ui-group">
<h3>Filter by YOUR STUFF HERE</h3>
<div class="button-group js-radio-button-group" data-filter-group="UNIQUE-DATA-FILTER-GROUP">
  <button class="button is-checked" data-filter="*">show all</button>
  <button class="button" data-filter=".YOUR_WORD_HERE">DISPLAYED WORDS</button>
  <button class="button" data-filter=".YOUR_WORD_HERE">DISPLAYED WORDS</button>


<!-- END FILTERS -->

<p class="resetme"><button class="button button--reset">Reset filters</button></p>

<!-- END FILTERS -->

<div class='grid'>

<!-- |pages| -->

<script src="https://unpkg.com/isotope-layout@3/dist/isotope.pkgd.js"></script>
$(document).ready(function() {

var $grid = $('.grid').isotope({
  itemSelector: '.grid-item',
  layoutMode: 'fitRows',
  getSortData: {
    age: '.age parseInt',
    face: '.face',
    category: '[data-category]',
    weight: function( itemElem ) { // function
      var weight = $( itemElem ).find('.weight').text();
      return parseFloat( weight.replace( /[\(\)]/g, '') );

// store filter for each group
var filters = {};

$('.filters').on( 'click', '.button', function() {
  var $this = $(this);
  // get group key
  var $buttonGroup = $this.parents('.button-group');
  var filterGroup = $buttonGroup.attr('data-filter-group');
  // set filter for group
  filters[ filterGroup ] = $this.attr('data-filter');
  // combine filters
  var filterValue = concatValues( filters );
  $grid.isotope({ filter: filterValue });

// bind sort button click
$('#sorts').on( 'click', 'button', function() {
  var sortByValue = $(this).attr('data-sort-by');
  $grid.isotope({ sortBy: sortByValue });

// change is-checked class on buttons
$('.button-group').each( function( i, buttonGroup ) {
  var $buttonGroup = $( buttonGroup );
  $buttonGroup.on( 'click', 'button', function() {
    $( this ).addClass('is-checked');

var $anyButtons = $('.filters').find('button[data-filter=""]');
  var $buttons = $('.filters button');

  $('.button--reset').on( 'click', function() {
    // reset filters
    filters = {};
    $grid.isotope({ filter: '*' });
    // reset buttons

// flatten object by concatting values
function concatValues( obj ) {
  var value = '';
  for ( var prop in obj ) {
    value += obj[ prop ];
  return value;

  1. The first section is the sort by buttons. These are what will rearrange the order in which member's are displayed. The most important thing here is data-sort-by="face" take note of the word used in the data-sort-by attribute.
  2. The second section is the filter buttons. These are what will make users vanish from view (filtered out) when they do not meet the filter requirements. The most important thing here is  data-filter=".Good" take note of the word used in the data-filter attribute.
  3. The third section has a handy reset button, allowing your users to put all characters back into view.
  4. The fourth section contains the actual members and the container that they will sit within. The div class is important here because it is referred to by the script.
  5. Fifth section is the pages button and this is sadly the memberlist's biggest weakness. You can only display so many users on a page and the script will not load more that for you. All the script does is sort information that is already there, it doesn't retrieve any additional data. Infinite scroll is also not doable on Jcink due to the way it needs to be set up. I would love to be proven wrong though. I'll address a work around for that later in this guide.
  6. The Sixth and final section is the script.


The following script source links directly to isotope's website, I strongly recommend downloading a version yourself and uploading it to your site. Use your site link for the script source.

<script src="https://unpkg.com/isotope-layout@3/dist/isotope.pkgd.js"></script>

You must have this (or the version on your site) linked before the script in order for it to run properly. I recommend just putting it on the member header template just because you don't need to run the script anywhere else. If you prefer, you can add it to your global wrapper in the usual spot.


The magic is between <script> and </script>


The first line is telling the script to not execute until the entire page has loaded. The next bit is telling what div to act execute the isotope on. If you have changed any of the class names in your HTML, you will need to read through the script and change to the appropriate class. If you want to save yourself the hassle, just use the same class names I use. I'll go into the script in more detail when I describe how to add more sort by buttons.


Member List Row - HTML

Paste the following into your member list row

<div class="grid-item member <!-- |field_21| -->">
	<div class='avatar'>
		<!-- |avatar| -->
	<div class="name">
		<!-- |name| -->
		<li class='age'>
			<!-- |field_2| -->
			Faction: <!-- |field_21| -->
		<li class='face'>
			Face Claim: <!-- |field_17| -->

Substitute your custom profile field numbers as necessary. If you save the templates now and check out your member list, you'll see that it's now working!


It also looks like pants, but you can fix that with a bit of CSS magic 🙂


How to Add More Filters

To add a filter, do the following:

  • Go to the member list row
  • Add the appropriate variable to grid-item member <!-- |field_21| --> so, if you want to add another filter and it's variable is 22, you should have div class="grid-item member <!-- |field_21| --> <!-- |field_22| -->" Make sure that there are spaces between each variable!
  • Save
  • Go to the member list header
  • Add the following before </div>
    <!-- END FILTERS --> 
    <div class="ui-group">
    <h3>Filter by YOUR STUFF HERE</h3>
    <div class="button-group js-radio-button-group" data-filter-group="UNIQUE-DATA-FILTER-GROUP">
      <button class="button is-checked" data-filter="*">show all</button>
      <button class="button" data-filter=".YOUR_WORD_HERE">DISPLAYED WORDS</button>
      <button class="button" data-filter=".YOUR_WORD_HERE">DISPLAYED WORDS</button>
  • Substitute .YOUR_WORD_HERE with what the potential input for that variable might be. For example, the Faction variable I created earlier had two potential inputs, Good and Evil (capitalisation IS important). So WORD is replaced with .Good and the next button has .Evil after data-filter= You should also rename the data-filter-group (where it says UNIQUE-DATA-FILTER-GROUP)
  • Save!
  • Done!

How to Add More Sorts

  • Go to the member list row
  • Add the custom field variable to where you want it to appear, and then wrap it in an element with an unique class name. For example, if you want to add player names to the sort button, you could put them in a h3 class like so: <h3 class="playername"><!-- |field_XX| --></h3>
  • Memorise what the class name is
  • Save
  • Go to member list header
  • Add this <button class="button" data-sort-by="CLASS-NAME">WORDS TO DISPLAY</button> before </div>
    <!-- END SORT BY -->
    • Using the player name example would mean you would put in: <button class="button" data-sort-by="playername">Player</button>
  • Scroll down to the script and find the following: getSortData: {
  • Press enter and add the following after the curly bracket 
    • Take note that there is a comma at the end of the line. Leave it off? Script stops working.
    • Using the player name example would mean you would end up with the following: 
      getSortData: {
        playername: '.playername',
        // rest of the stuff here


  • Save
  • Done!

Note: use the age sort as your guide on how to set up any other sort by numbers in the sort by. If you want to sort by height, make your users use metres (1.7 rather than 5'5 because the apostrophe will spoil your script) and change parseInt to parseFloat. In saying that, making your user's type 5\'5 ought to save your script, if someone makes a mistake however you will need them to correct it in order for the script to continue functioning. Safest just to use decimal points.


How to add a label to numbers

  • If you want to sort by a number, your class to sort can only contain a number. For example, age looks like this: 
    		<li class='age'>
    			<!-- |field_2| -->


  • We will use CSS to fix this: 
    .age::before {
      content: 'Age: ';
      display: inline


  • Save and Done!


A Cheat to Display More Members

  • As noted, the biggest disadvantage of using the sort and filter script is that it can not retrieve data from another page. So when a user clicks on the member list, we want them to automatically see as many characters as possible. The most allowable by Jcink is 50. So, make your own link to the member list and make it the following URL:
  • YOUR_BOARD_URL_HERE/index.php?&act=Members&photoonly=&name=&name_box=all&max_results=50&filter=ALL&sort_order=asc&sort_key=name&st=0
  • Done!

Another thing to consider is using the Hide this group from the member list? option in the user group settings to your advantage. For example, consider only having accepted and active character accounts displayed on your member list, rather than having inactive and unaccepted character accounts clogging up the list.


I wish there was a more elegant solution to this! If anyone has found a solution that works for them, I would love to hear about it.


Even if this isn't the member list code for you, I hope that it's given you some ideas on what you can do with the member list template!


Visit the isotope website to find out what else you can do with the script!

  • Thank you 2
  • Cheers 1

Related Guides

  • Morrigan

    Jcink Themeing: What you Need

    By Morrigan, By Morrigan, in Coding,

    This guide is the precursor guide to how to create a theme, step by step on Jcink. This will start from how do you even start a new theme on Jcink to exporting/importing it to s site. This particular guide is the expectations that I have for a member to follow guides in order to be successful.


User Feedback

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.


  • Create New...

Important Information

By using this site, you agree to our Terms of Use, Guidelines and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.