Every time I've needed faceted search capabilities, I've had to rewrite the JavaScript to do it. This plugin hopes to do away with that. I tried looking for an existing plugin that did what jQuery Facets does, but surprisingly I couldn't find any that offered the functionality that I wanted. Hopefully others will find this plugin useful too.
A demo can be found here. A few things to notice about this demo:
Below is the proper way to include the plugin on your page:
<script type='text/javascript' src='jquery.deserialize.js'></script>
<script type='text/javascript' src='jquery.facets.js'></script>
The jQuery Deserialize plugin is necessary if you plan on using the hashtag features of jQuery Facets.
The simplest way to use jQuery Facets is like so:
var facetsPlugin = $("form#facets").facets();
However, this assumes some defaults which are listed below.
Below are all of the options that can be set with jQuery Facets and all of their default values. All defaults can be changed like so:
$("form#facets").facets({
'option1':'value1',
'option2':'value2'
});
'searchCont' : '#searchCont'
This is a selector for the container that will hold the filtered search results after the ajax request.
'ajaxURL' : $(location).attr('href')
URL to make ajax requests to for filtered results. Defaults to current URL of the page.
'URLParams' : new Array()
Extra params for the ajaxURL, such as the original search query. Takes an array in jQuery's serializeArray() format.
'ajaxMethod' : 'GET'
The method of the ajax request. Default is GET.
'bindType' : 'change'
This is the way to bind to facet elements (i.e. checkboxes). The default is onchange. So whenever an element changes (or whichever bindType you select), this is when a call to ajaxReq will be made to filter the search results. To select a bindType for individual elements see bindTypes. A bindType can be any eventType that jQuery's bind function takes. In hindsight, perhaps I should've just named bindType eventType, but I already have this code in production so I have to stick with the naming scheme now :)
'bindTypes' : new Array()
With bindTypes you can specify specific bindTypes for elements matching jQuery selectors. This can be useful if you want your default bindType to be change, but say that you want the bindType for an input of type text to be blur. You can specify that like so:
'bindTypes' : [{
'selector' : 'input[type="text"]',
'bindType' : 'blur'
}],
bindTypes takes in an array of hashes with the keys selector and bindType, where selector specifies the jQuery selector for the elements you want to have the corresponding bindType.
'excludeBindTypes' : new Array()
excludeBindTypes can be used to specify any elements that you would not like to make ajax calls by being bound to an event (i.e. blur, change). To specify which elements should not be bound to any bindType, you simply pass in their jQuery selectors in an array. This can be useful if you have an element for which you would like to manually trigger the ajax call. For instance, to exclude all inputs of type text from being bound to a bindType, you simply do the following:
'excludeBindTypes' : [
'input[type="text"]'
],
Or if you would like to manually trigger all ajax calls, you could do so like this:
'excludeBindTypes' : [
'*'
],
Where '*
' would match all elements. However, this is not recommended.
'generateData' : function () {
var settings = this.data("settings");
var dataArr = remove_empty(this.serializeArray());
//push on any user added params
for(var k = 0; k < settings.URLParams.length; k++) {
dataArr.push(settings.URLParams[k]);
}
return dataArr;
}
generateData takes in a function reference and must return the data to be sent server-side by ajaxReq during the ajax request. Acceptable input is anything that is acceptable for the data setting of jQuery's jQuery.ajax method. If you feel the need to generate the data to be sent server-side yourself, this will allow you to do it. The generateData function will be passed in the jQuery Facets plugin object as this
. However, any user added params set in URLParams will not be added with a user defined generateData function, since the data setting can take in so many formats. Thus, if there are any values you want added, you need to add them yourself in generateData. The default is to return the form serialized using jQuery's serializeArray() function and to remove any elements where the value is empty, while also adding on any user defined params in URLParams.
preAJAX
'preAJAX' : function () { return true }
preAJAX takes in a function reference and will be called prior to making the ajax request for the filtered data. It must return either true or false (true and jQuery Facets will make the ajax request, false it will not). This function is mostly useful if you want to validate the users input for any facets before sending the data server-side. For example, lets say this was a facet in your facets form:
<input type="text" name="zip" id="zip" value="" ⁄>
Where you allowed the user to filter search results by zip code. By having a preAJAX function defined you could appropriately validate the user's input and then return true if the input is okay, and return false otherwise allowing the user to fix their input.
'postAJAX' : function (data) { $(plugin.data("settings").searchCont).html(data) }
postAJAX takes in a function reference and will be called after making the ajax request for the filtered data. The default is to fill whatever element you put for searchCont with the data returned by the ajax request. However, by being able to specify your own postAJAX method you could return the data in whatever format you like (i.e. JSON, XML, etc.) and then you can parse it however you want and display it however you want.
'preHash' : function () { }
preHash takes in a function reference and will be called before the hashURL method is called. This is mainly useful for modifying the hashOptions before hashURL method is called.
'postHash' : function () { }
postHash takes in a function reference and will be called after the hashURL method is called. To be honest I'm not really sure what I would use this for, but maybe someone else can figure out a use for it :)
'hashOptions' : new Array()
hashOptions can be used to specify extra key value pairs that will be put after the hashtag when the hashURL method is called. Takes an array in jQuery's serializeArray() format.
'hash' : true
hash takes in a true or false value to determine whether the hashURL method should be called. If set to false, your preHash and postHash methods will not be called.
'shouldSubmit' : false
shouldSubmit takes in a true or false value to determine whether the facets form should be able to be submitted or not. I'm not really sure why you would want the facets form to be able to be submitted, so the default is false. This way if someone pressed enter on a input of type text, the form won't submit, etc.
Listed below are the methods that you may have a reason to call manually. Any methods that you need to call yourself can be called like so:
$("form#facets").facets('methodName',optionalArgs);
facetsPlugin.facets('methodName',optionalArgs);
hashURL is only called when the hash option is set to true. It is called after making the ajax request in the ajaxReq method. It takes all key value pairs in your facets form and puts them after the hashtag in the URL. This is beneficial for a number of reasons. First, if your user reloads the page or bookmarks it, then jQuery Facets will on page load (using hashInit) check to see if there are any values after the hashtag in the URL, and if there are it will make an ajax request with those key value pairs to get the appropriate filtered data. It will also fill in all facets with the appropriate values (or check checkboxes, etc.) so that the user's page is in the same state it was before. Also, this can be very useful for users sending links to one another. hashURL returns the resulting hash that follows after the hashtag.
ajaxReq is called by default when any element triggers its bindType. ajaxReq makes an ajax request to ajaxURL and then leaves it up to postAJAX to handle the returned data. A situation in which you might want to call this explicitly would be if you wanted to have an element in your facets form that did not call ajaxReq via a bindType, but instead by having the user click a submit button or something like this. ajaxReq returns a method call to hashURL if hash is true.
Most options should just be set when creating the jQuery Facets plugin object. However, if you do find a need to get or set a value, it can be done like so:
var optionValue = $("form#facets").facets('get','optionName');
Or if you have a handle on the plugin:
var optionValue = facetsPlugin.facets('get','optionName');
$("form#facets").facets("set",'optionName','optionValue');
Or if you have a handle on the plugin:
facetsPlugin.facets("set",'optionName','optionValue');
I definitely haven't thought of everything, and if there's a feature you think would be good or something that's lacking, shoot me an email and I'll see what I can do about it :)
If anything is unclear in the documentation or you feel something could be explained better, please let me know! I'm far from the best writer in the world and I'm always open to suggestions :)
comments powered by Disqus