VPKR is a filterable, hierarchical data table. It combines the functionality of a data table, an accordion, and an autocomplete.
Apparel | Edit |
Men's Apparel | Edit |
Women's Apparel | Edit |
Footwear | Edit |
Men's Shoes | Edit |
Women's Shoes | Edit |
Decor | Edit |
Tasteless | Edit |
Tasteful | Edit |
Housewares | Edit |
Tools | Edit |
Pet Supplies | Edit |
Iguana Supplies | Edit |
Cat Supplies | Edit |
Dog Supplies | Edit |
Electronics | Edit |
Yard Maintenance | Edit |
Auto Care | Edit |
<table class="vpkr tree expandable clickToExpand">
<tr id="vpkr0-node-0001">
<td class="searchable item-name">
Apparel
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr class="child-of-vpkr0-node-0001" id="vpkr0-node-0102">
<td class="searchable item-name">
Men's Apparel
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr class="child-of-vpkr0-node-0001" id="vpkr0-node-0101">
<td class="searchable item-name">
Women's Apparel
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr id="vpkr0-node-0002">
<td class="searchable item-name">
Footwear
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr class="child-of-vpkr0-node-0002" id="vpkr0-node-0202">
<td class="searchable item-name">
Men's Shoes
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr class="child-of-vpkr0-node-0002" id="vpkr0-node-0201">
<td class="searchable item-name">
Women's Shoes
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr id="vpkr0-node-0003">
<td class="searchable item-name">
Decor
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr class="child-of-vpkr0-node-0003" id="vpkr0-node-0302">
<td class="searchable item-name">
Tasteless
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr class="child-of-vpkr0-node-0003" id="vpkr0-node-0301">
<td class="searchable item-name">
Tasteful
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr id="vpkr0-node-0004">
<td class="searchable item-name">
Housewares
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr id="vpkr0-node-0005">
<td class="searchable item-name">
Tools
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr id="vpkr0-node-0006">
<td class="searchable item-name">
Pet Supplies
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr class="child-of-vpkr0-node-0006" id="vpkr0-node-0603">
<td class="searchable item-name">
Iguana Supplies
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr class="child-of-vpkr0-node-0006" id="vpkr0-node-0602">
<td class="searchable item-name">
Cat Supplies
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr class="child-of-vpkr0-node-0006" id="vpkr0-node-0601">
<td class="searchable item-name">
Dog Supplies
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr id="vpkr0-node-0007">
<td class="searchable item-name">
Electronics
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr id="vpkr0-node-0008">
<td class="searchable item-name">
Yard Maintenance
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr id="vpkr0-node-0009">
<td class="searchable item-name">
Auto Care
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
</table>
$('#hardcoded .vpkr').vpkr({
name: "hardcoded",
actions: {
"Edit": function(e) {
alert('Editing ' + $.trim( $(this)
.closest('tr')
.children('.item-name')
.text()) + '!');
}
},
dataSource: 'html'
});
<table class="vpkr tree checkable">
</table>
$('#dynamic .vpkr').vpkr({
name: "dynamic",
dataSource: function(callback){
$.getJSON('./resources/categories.json',
function(data){
callback(data.categories);
});
},
searchText: "Start typing..."
});
<table class="vpkr">
</table>
$('#dynamic2 .vpkr').vpkr({
name: "dynamic2",
dataSource: function(callback){
$.getJSON('./resources/categories.json',function(data){
callback(data.categories);
})
},
searchBox: false,
actions: {
"Edit": function(e,data) {
var row = $(this);
row.children('.item-name')
.html('<input type="text" value="' + data.name + '" />')
.children('input')
.bind('keyup.vpkr',function(e){
if (e.which===13) {
row.data('vpkr-data',$.extend(row.data('vpkr-data'),{name:this.value}));
$(this).parent().text(this.value);
}
});
},
"Flash": function(e,data) {
$(this).effect('highlight')
},
"Delete": function(e,data) {
$(this).remove();
}
}
});
At minimum, VPKR needs a table tag.
<table></table>
You can attach a VPKR to this table in one simple command:
$('table').vpkr();
Of course, this table will be empty. If you don't provide VPKR with a data source, it will attempt to populate from the table itself. It will only be successful at this if your HTML follows the VPKR Markup Structure.
You can specify boolean options for your VPKR in your HTML, by adding those boolean options as classnames.
<table id="foo" class="tree expandable clickToExpand"></table>
<script type="text/javascript">
$(function(){
$("#foo").vpkr({dataSource:someObj});
})
</script>
is equivalent to
<table id="foo"></table>
<script type="text/javascript">
$(function(){
$("#foo").vpkr({tree: true, expandable: true, clickToExpand: true, dataSource:someObj});
})
</script>
VPKR is more powerful if you provide it with external data. The data must follow the VPKR JSON Structure, and it can be delivered either synchronously, by setting the dataSource option to the JSON itself, or asynchronously, by setting dataSource to a function that takes a single parameter. The examples above use a jQuery AJAX call to a JSON file.
dataSource: function(callback){
$.getJSON('./resources/categories.json',
function(data){
callback(data.categories);
});
}
Note that the function argued to dataSource must take a "callback" argument; VPKR will send its own callback method to the function, which the function must then execute with the JSON.
It's also possible to update the VPKR with external JSON, using the .vpkr('update') method:
$('#some_table').ajaxComplete(function(e,xhr){
$(this).vpkr('update',$.parseJSON(xhr.responseText));
})
With no argument, the .vpkr('update') method will reload from the original data source.
Key | Type | Default | Description |
---|---|---|---|
actions | object (function map) | None | An optional object map of functions. The keys of this object, e.g. "Edit", will display as text links on each row. The functions will be executed in the context of the <tr /> DOM element, and receive two arguments: the jQuery event object, and, if there was an external data source, the data row associated with that table. |
tree | boolean | false | Displays the table data hierarchically, based on the "childOf" value in the data set. |
expandable | boolean | false | Creates buttons to expand and collapse subtrees. Requires "tree". |
clickToExpand | boolean | false | Makes the row names clickable to expand and collapse subtrees. Requires "tree", "expandable". |
initialState | string | "collapsed" | If set to "expanded", expands all trees upon population. |
checkable | string | None | Adds form controls to the table rows. Argue "checkbox" or "radio". |
name | string | None | For usage as an identifier and in forms, to name your checkboxes. |
dataSource | function, JSON object | None | Accepts an external data source. If left blank, will attempt to populate from HTML already inside the table. If JSON, will populate with that JSON. Arguing a function can make table population asynchronous. The function must take a callback parameter and execute that callback with one argument--the data returned from the asynchronous function. |
searchBox | jQuery object | None | Optionally accepts an external input element to serve as a search box. If this option is not used, VPKR will create a search box on the top border of the table. |
showAllButton | jQuery object | None | Optionally accepts an external element to serve as a "show all" or "clear search" button. |
searchText | string | "Search..." | Sets the default prompt in the autogenerated search box. |
indent | integer | 20 | Sets the indent, in pixels, for each subtree. |
wrap | boolean | true | If true, wraps the initial table in container elements. Set "false" only if the VPKR renders poorly otherwise. |
width | integer | 500 | Width of the VPKR table. |
height | integer | 200 | Height of the VPKR table (not counting search box). |
Name | Arguments | Description |
---|---|---|
collapse | .vpkr('collapse',$tr) | Collapse an expanded row, recursively. Requires a jQuery-wrapped <tr> element. |
expand | .vpkr('expand',$tr) | Expand a collapsed row. Requires a jQuery-wrapped <tr> element. |
clearSearch | .vpkr('clearSearch') | Clear any filter characters from the search box and display all uncollapsed rows. |
filter | .vpkr('filter',string) | Filter the list by a string. The searchbox uses this method. |
update | .vpkr('update', [json]) | Update and repopulate the table. If you pass a parameter, it must be a JSON object. If you pass no parameter, it will update from the original data source. |
If you are generating your VPKR using external data, then first of all, good for you. This is the way to do things. Secondly, this external data must conform to an existing format. It must be an an array of data objects, with each object having at minimum an "id", "name", and, if the record has a parent record, a "childOf" property. The "id" and "name" properties must be strings, and the "childOf" property, if present, must contain the ID of the parent record, e.g.:
[
{
"id": "0001",
"name": "Apparel"
},
{
"id": "0101",
"name": "Women's Apparel",
"childOf": "0001"
},
{
"id": "0102",
"name": "Men's Apparel",
"childOf": "0001"
},
{
"id": "0002",
"name": "Footwear"
},
(...)
}
Note that the JSON structure provides its hierarchy by reference, instead of actually storing data records beneath other records. The HTML structure that VPKR creates reflects this as well. This has show to dramatically increase performance.
If you'll be parsing inline HTML in the table, instead of using an external data source, then first allow me to register my mild disapproval, and then check out the Markup Structure.
Notes:
In order for VPKR to read a table into its data store, your application will have to render HTML that VPKR would have rendered itself. Fortunately, VPKR's HTML is relatively simple!
<table class="vpkr tree expandable clickToExpand">
<tr id="vpkr0-node-0001">
<td class="searchable item-name">
Apparel
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr class="child-of-vpkr0-node-0001" id="vpkr0-node-0102">
<td class="searchable item-name">
Men's Apparel
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr class="child-of-vpkr0-node-0001" id="vpkr0-node-0101">
<td class="searchable item-name">
Women's Apparel
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
<tr id="vpkr0-node-0002">
<td class="searchable item-name">
Footwear
</td>
<td align="right">
<a href="#" class="vpkr-action-edit">Edit</a>
</td>
</tr>
(...)
</table>
First, you must create a unique prefix for all of your table rows. The above example uses
Identify certain text nodes as containing searchable text using the "searchable" class. The filter function will only examine these nodes.
Any actions you have configured in your VPKR constructor must have their links hardcoded into this table, as in the example above. The functions you put in the actions array will run when you click those links, even though VPKR did not generate them itself.
Notes: