Filterable Opens Matching Collapsibles


The jQuery Mobile  (jQM) library includes a filterable widget which can be applied to any container element by setting data-filer=”true”.  The user can then start typing in the search input box and any child elements with matching text are shown while the rest are hidden from view. The widget also provides a callback for after the filtering is complete, and in this article we shall exploit this callback to make matching collapsibles expand instead of hiding non-matching elements.

As of jQM version 1.4, we can provide the search box markup and associate its ID with the filterable widget. Because the widget will be expanding and collapsing a list of collapsibles, I have decided to provide buttons for ‘expand all’ and ‘collapse all’ as a convenience to the user. The markup for the buttons and search box looks like this:

<div class="ui-grid-a">
  <div class="ui-block-a"><a id="btnExpand" class="ui-btn ui-corner-all collapseExpand">Expand All</a>
  </div>
  <div class="ui-block-b"><a id="btnCollapse" class="ui-btn ui-corner-all collapseExpand">Collapse All</a>
  </div>
</div>
<form class="ui-filterable">
  <input id="filterBasic-input" data-type="search" placeholder="Open matching collapsibles..." />
</form>

The list of collapsibles is just a container DIV with many standard jQM collapsibles as its direct children. The container has data-filter=”true” and the data-input attribute points at the ID of our search box:

<div id="filterList" data-filter="true" data-input="#filterBasic-input">
  <div data-role="collapsible" data-inset="false" data-mini="true">
    <h4>Aaron</h4>
    <p>Aaron is a great employee</p>
  </div>
  <div data-role="collapsible" data-inset="false" data-mini="true">
    <h4>Adam</h4>
    <p>Adam is a great employee</p>
  </div>
  <div data-role="collapsible" data-inset="false" data-mini="true">
    <h4>Benjamin</h4>
    <p>Benjamin is a great employee</p>
  </div>
  <!-- etc. -->
</div>

Now for the button click events for the  ‘expand all’ and ‘collapse all’ buttons I have one handler on the common class they share. In the handler I determine if we are collapsing or expanding based on the ID of the button clicked, and finally I apply the collapsed option to all collapsibles in the container:

$(document).on("click", ".collapseExpand", function(){
    var collapseAll = this.id == "btnCollapse";
    $('#filterList [data-role="collapsible"]').collapsible("option", "collapsed", collapseAll);
});

The last thing we have to do is bind to the filterable widget’s filter event. All items that do not match the filter criteria are assigned a class of ui-screen-hidden, so we can iterate through all the collapsible items (available in the handler’s second paramter) and expand the ones that don’t have the ui-screen-hidden class and collapse the ones that do. We also need to remove the ui-screen-hidden class after collapsing so that the collapsible won’t be hidden from view:

$("#filterList").on("filterablefilter", function (event, ui) {
    ui.items.each(function (index) {
        $(this).collapsible("option", "collapsed", $(this).hasClass("ui-screen-hidden")).removeClass("ui-screen-hidden");
    });
});

I have created a jsFiddle that demonstrates this simple trick of applying a filter to collapsibles:

jQM 1.4 Filterable Expands Collapsibles

As you type in the search box, any collapsibles that contain matching text in either the header or the content expand while the rest collapse.

Buy Me A Coffee :) @ ko-fi.com

Advertisements

4 thoughts on “Filterable Opens Matching Collapsibles

  1. Wojtek, Omar has given you a good solution, but it depends what you want to happen when you click the button and some elements are expanded and some are collapsed. At that point, do you want to always expand (like Omar’s solution), or do you just want to do the opposite of the last time you clicked? Then you can save previous action in a data element like this: http://jsfiddle.net/ezanker/3zzuxdfy/1/

  2. Something like this?

    $(document).on(“pagecreate”, “#punktyKontrolne”, function () {
    $(document).on(“click”, “.collapseExpand”, function(){
    if ($(‘#listviewContent’).hasClass(“ui-collapsible-collapsed”)){
    $(‘#listviewContent [data-role=”collapsible”]’).collapsible(“option”, “collapsed”, false);
    }
    else {
    var collapseAll = this.id == “ZwinRozwinWszystko”;
    $(‘#listviewContent [data-role=”collapsible”]’).collapsible(“option”, “collapsed”, collapseAll);
    }

              });
          });
    

Drop me a line or two ;)

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s