0

In this website I'm building there's a page with a Views list of people, divided into categories. I've exposed a category filter and a name filter to visitors.

Since the list isn't long, I would like to show all the items on page load and use the exposed filters as "fake" filters. Those will not actually make a request to the database, but call a JavaScript function that will go through the list and hide the unwanted items using CSS.

I can create my own filters, but then the category filter will not auto update when a new category is created. I've seen that I can use MYTHEME_preprocess_views_exposed_form hook to change it to how I want, but then the page will still download and run auto-submit.js, which is the CTools JS file that Views module uses for auto submitting. I can remove it with MYTHEME_js_alter, but it seems like a lot of effort - and mostly wasted computational time slowing the page load - for a simple task.

Does anyone know a better way to accomplish this? Am I just overreacting over a few lines of code?

Thanks guys, hope everything is clear.

EDIT:

About 5 seconds after posting I've realized that I could use auto-submit.js with the JavaScript too. So all I need to do is remove the action of the form and add onSubmit that'll point to my script.

  • I'd be tempted to create a cached callback to populate the filter with your categories, it'd probably run to about 5 lines of code and has to be less heavy than views adding them. – bloke_zero Oct 6 '15 at 9:00
  • Actually, I looked for the quickest solution. I also like the fact that in case JavaScript is disabled, the filter fallbacks to the normal views' filter. – Neta Oct 6 '15 at 17:27
1

Here is the solution I used:

I created a new module named "My Views' Client Side Filters".

In the module's .module file I added:

<?php

function my_views_client_side_filters_form_views_exposed_form_alter(&$form, &$form_state, $form_id)
{
    $form['#attributes']['onsubmit'] = 'return exposedFilterOnSubmit();';
    drupal_add_js('sites/all/themes/MY_THEME/js/MY_JS_FILE.js');
}

Which resulted in the HTML:

<form onsubmit="return exposedFilterOnSubmit();" action="MY FORM DESTINATION" method="get">

And sites/all/themes/MY_THEME/js/MY_JS_FILE.js:

function isEmpty(str) {
    return (str.length === 0 || !str.trim());
}
var departmentAllShown = true;
var nameAllShown = true;
(function ($) {
    function reloadNames(name) {
        $('.views-row').each(function() {
            if($(this).find('.doctors_view_row_title').text().toLowerCase().indexOf(name.toLowerCase()) >= 0)
                $(this).css('display','block');
            else
                $(this).css('display','none');
        });
        nameAllShown = false;
    }
    jQuery.extend({
        exposedFilterHider: function()
        {
            //Handle url (JavaScript only now enabled)
            if(!isEmpty(window.location.search))
                location = "MY_SITE_LOCATION/FORM_PAGE";

            var department = $('#edit-field-department-value')[0].value;
            var departmentIndex = $('#edit-field-department-value')[0].selectedIndex;
            var name = $('#edit-title')[0].value;

            var nameIsEmpty = isEmpty(name);

            if (departmentIndex != 0)
            {
                $('.item-list').each(function() {
                    if ($(this).children().first().text() === department)
                    {
                        $(this).css('display','block');
                        if (!nameIsEmpty)
                            reloadNames(name);
                        else
                            if (!nameAllShown)
                            {
                                $('.views-row').css('display','block');
                                nameAllShown = true;
                            }
                    }
                    else
                        $(this).css('display','none');
                });
                departmentAllShown = false;
            }
            else
            {
                //Enable all categories if not already
                if (!departmentAllShown)
                {
                    $('.item-list').css('display','block');
                    departmentAllShown = true;
                }

                if (!nameIsEmpty)
                    reloadNames(name);
                else //Enable all names if not already
                    if (!nameAllShown)
                    {
                        $('.views-row').css('display','block');
                        nameAllShown = true;
                    }
            }
        }
    });
})(jQuery);

function exposedFilterOnSubmit()
{
    jQuery.exposedFilterHider();
    return false;
}

Sorry I don't explain any further, I'm kind of stressed in time. If someone asks a specific question I promise to answer.

Hope this helps anyone!

BTW, although the code is a bit long it works spectacularly and runs swiftly.

Remember to change the classes! You might need to change things a bit since my layout may not be the same as yours.

My classes:

.views-row - Entire "person" row (The name container is somewhere inside and there are a few of those in every category)

.doctors_view_row_title - Name container

.item-list - The category container

Good luck guys!

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.