Appendo is a lightweight plugin to manage cloning form rows.
Appendo is less than 2000 bytes and is very easy to use.
|
|
Appendo aims to be a lightweight solution to duplicating form rows in a simple jQuery plugin format. The appendix includes some PHP example code for naming and reading rows.
Appendo also aims to be a succinct example of jQuery plugin design (see code).
It's very simple to attach Appendo.
In fact, it doesn't even require any Javascript.
If you've loaded jQuery and Appendo correctly, Appendo will automatically attach to tables with class="appendo". It's that easy!
A reference for the most common options:
| labelAdd | string | String value of "add" button (default: 'Add Row') |
|---|---|---|
| labelDel | string | String value of "remove" button (default: 'Remove') |
| maxRows | integer | Set to 0 for no limit (default) |
| allowDelete | boolean | Delete button will be shown if true (default:true) |
| copyHandlers | boolean | Set to true to copy event handlers (default: false) |
| focusFirst | boolean | Focus 'input:first' on added form rows (default: true) |
There are two methods for setting Appendo options. Global Appendo options can be set to override defaults on all Appendo instances created henceforth. This can be done by inserting inline Javascript like so:
$.appendo.opt.maxRows = 5; $.appendo.opt.labelAdd = 'Another'; jQuery.appendo.opt.copyHandlers = true; jQuery.appendo.opt.focusFirst = true;
Note that both syntaxes refer to the same set of global options. When setting options globally, just insert them inline, don't wrap with $(document).ready() or similar. This way, you'll ensure they're set before Appendo is invoked automatically (if this is how you're invoking it).
The other method for setting options is using jQuery plugin syntax.
Of course, Appendo can also be used as a typical jQuery plugin. You would usually do this if you wanted to set options on a per-instance basis, or if you have some other aversion to using a class name as per Appendo's automatic attachment method. It uses the same set of options listed above. An example invocation with options:
$(function() {
$('#objid').appendo({
maxRows: 4,
allowDelete: false,
labelAdd: 'Add Another Row'
});
});
In this example, the table with id="objid" will be used.
Appendo doesn't need any additional CSS files or settings, but some designers may wish to style the output to match their page. This information should help you do that. However, it can't teach you how CSS works; you'll need to understand at least the basics already.
If you are styling via CSS rules included inline or in an external stylesheet, the styles for Appendo might look like this:
.appendoButtons { border: 1px black solid; }
.appendoButtons button { background: white; font-size: 80%; }
This div is inserted directly after the selected element in the DOM. The wrapClass option can be set if you want to change the class given to this button wrapper div.
| wrapClass | string | Name of class to set on button wrapper div |
|---|
An alternative method to perform CSS styling is to set an object for wrapStyle and/or buttonStyle options. Object(s) will be passed directly to jQuery's .css() method.
| wrapStyle | object | jQuery CSS properties object to set on wrapper (default: { padding: '.4em .2em .5em' }) |
|---|---|---|
| buttonStyle | object | jQuery CSS properties object to set on buttons (default: { marginRight: '.5em' }) |
If you set either option, you will override the default margins and padding (so you may need to incorporate that into your properties). If you use "stylesheet" rules and want to override the default margins and padding you may need to use !important or set an empty object for wrapStyle and buttonStyle options.
Appendo supports two callback events, settable as options:
| onAdd | callback | Called when a row has been added |
|---|---|---|
| onDel | callback | Called before a row is removed (return true to delete) |
When a new row is added, the onAdd callback is fired. If set, the function is called and given a jQuery object referencing the added element (usually a table row). This function is called at the end of the addition, after it's in the DOM, so it's even safe to .remove() if your callback function sees fit. It goes without saying that you can subselect and tweak the object to your heart's content with jQuery.
When the "remove" button is clicked, the onDel callback is fired. If set, the function is called and given a jQuery object referencing the element that will be removed (usually a table row). This function is called before removal. Your callback may inspect the object, take action(s), and return true or false, signaling whether the removal should continue. If a non-true value is returned, the removal will not take place. In this way, you can implement a "do you really want to lose this data?" prompt, or any other sort of behavior.
Well, when you think about it, it's tabular data. If you absolutely hate tables, or you have another reason to use it somewhere else, there's an undocumented option called subSelect which is initially set to 'tr:last'. This way, the interface could be used to duplicate any selector within the outer selection.
<div id="outer"> <div class="inner"> Making copies... </div> </div>
So you could invoke Appendo like this:
$(function() {
$('#outer').appendo({ subSelect: '.inner' });
});
This could have interesting side effects if the subSelect were set to a selector that wasn't unique within the invoked selection.
The naming of form fields in the cloned rows is beyond the scope of the Appendo plugin. However, if you're using PHP, or a language with similar "form-to-array" features, this isn't a problem. Consider this table with Appendo rows added:
<table class="appendo">
<tr>
<td><input type="text" name="col1[]" /></td>
<td><input type="text" name="col2[]" /></td>
<td><input type="text" name="col2[]" /></td>
</tr>
</table>
To read these rows dynamically in PHP, you can do something like:
$rv = array();
foreach($_POST['col1'] as $k => $v)
$rv[] = array($v, $_POST['col2'][$k], $_POST['col3'][$k]);
This is possible because PHP reads form values named with [] as arrays. So by looping over the first column, you can associate those values with the other columns.
Note: This is only tested on select elements and input elements with type other than radio and checkbox. I suspect it will not work as intended with those types of input.