Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,14 @@ complete list of available options is shown below::
This means you can also pass in DOM elements, or a function (in newer
versions of jQuery) as your selector.

``addImage``
Use the specified image instead of text for the add button. This should
be a URL that will be automatically wrapped in an <img> tag.

``deleteImage``
Use the specified image instead of text for the delete button. This should
be a URL that will be automatically wrapped in an <img> tag.

.. note:: The ``addCssClass`` and ``deleteCssClass`` options must be unique.
Internally, the plugin uses the class names to target the add and delete
links. Any other elements with the same class applied to them will also
Expand Down
26 changes: 21 additions & 5 deletions src/jquery.formset.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,22 +55,30 @@
insertDeleteLink = function(row) {
var delCssSelector = $.trim(options.deleteCssClass).replace(/\s+/g, '.'),
addCssSelector = $.trim(options.addCssClass).replace(/\s+/g, '.');

if (options.deleteImage) {
deleteElement = '<img src="' + options.deleteImage + '" />';
} else {
deleteElement = options.deleteText;
}

if (row.is('TR')) {
// If the forms are laid out in table rows, insert
// the remove button into the last table cell:
row.children(':last').append('<a class="' + options.deleteCssClass +'" href="javascript:void(0)">' + options.deleteText + '</a>');
row.children(':last').append('<a class="' + options.deleteCssClass +'" href="javascript:void(0)">' + deleteElement + '</a>');
} else if (row.is('UL') || row.is('OL')) {
// If they're laid out as an ordered/unordered list,
// insert an <li> after the last list item:
row.append('<li><a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + options.deleteText +'</a></li>');
row.append('<li><a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + deleteElement +'</a></li>');
} else {
// Otherwise, just insert the remove button as the
// last child element of the form's container:
row.append('<a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + options.deleteText +'</a>');
row.append('<a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + deleteElement +'</a>');
}
// Check if we're under the minimum number of forms - not to display delete link at rendering
if (!showDeleteLinks()){
row.find('a.' + delCssSelector).hide();
} else {
}

row.find('a.' + delCssSelector).click(function() {
Expand Down Expand Up @@ -172,19 +180,25 @@
}
// FIXME: Perhaps using $.data would be a better idea?
options.formTemplate = template;

if (options.addImage) {
addElement = '<img src="' + options.addImage + '" />';
} else {
addElement = options.addText;
}

if ($$.is('TR')) {
// If forms are laid out as table rows, insert the
// "add" button in a new table row:
var numCols = $$.eq(0).children().length, // This is a bit of an assumption :|
buttonRow = $('<tr><td colspan="' + numCols + '"><a class="' + options.addCssClass + '" href="javascript:void(0)">' + options.addText + '</a></tr>')
buttonRow = $('<tr><td colspan="' + numCols + '"><a class="' + options.addCssClass + '" href="javascript:void(0)">' + addElement + '</a></tr>')
.addClass(options.formCssClass + '-add');
$$.parent().append(buttonRow);
if (hideAddButton) buttonRow.hide();
addButton = buttonRow.find('a');
} else {
// Otherwise, insert it immediately after the last form:
$$.filter(':last').after('<a class="' + options.addCssClass + '" href="javascript:void(0)">' + options.addText + '</a>');
$$.filter(':last').after('<a class="' + options.addCssClass + '" href="javascript:void(0)">' + addElement + '</a>');
addButton = $$.filter(':last').next();
if (hideAddButton) addButton.hide();
}
Expand Down Expand Up @@ -218,7 +232,9 @@
$.fn.formset.defaults = {
prefix: 'form', // The form prefix for your django formset
formTemplate: null, // The jQuery selection cloned to generate new form instances
addImage: null, // Image for the add link (overrides text)
addText: 'add another', // Text for the add link
deleteImage: null, // Image for the delete link (overrides text)
deleteText: 'remove', // Text for the delete link
addCssClass: 'add-row', // CSS class applied to the add link
deleteCssClass: 'delete-row', // CSS class applied to the delete link
Expand Down
30 changes: 30 additions & 0 deletions tests/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
assert.equal($.fn.formset.defaults.keepFieldValues, '', 'keepFieldValues: ');
assert.equal($.fn.formset.defaults.added, null, 'added callback: null');
assert.equal($.fn.formset.defaults.removed, null, 'removed callback: null');
assert.equal($.fn.formset.defaults.addImage, null, 'addImage: null');
assert.equal($.fn.formset.defaults.deleteImage, null, 'deleteImage: null');
});

module('Basic Formset Tests', {
Expand All @@ -26,7 +28,9 @@
test('Test Formset Creation', function (assert) {
assert.equal($('#stacked-form div').size(), 1, 'Default form is present.');
assert.equal($('#stacked-form .delete-row').size(), 1, 'Delete button created.');
assert.equal($('#stacked-form .delete-row').text(), 'remove', 'Delete text created.');
assert.equal($('#stacked-form .add-row').size(), 1, 'Add button created.');
assert.equal($('#stacked-form .add-row').text(), 'add another', 'Add text created.');
assert.ok($('#stacked-form div:first').hasClass('dynamic-form'), 'FormCssClass added to forms.');
});

Expand Down Expand Up @@ -205,4 +209,30 @@
assert.equal($totalForms.val(), $minForms.val(), 'Form count is now equal to min allowed.');
assert.ok($del.first().is(':hidden'), 'Delete button is hidden again.');
});

module('Basic Formset Tests', {
setup: function () {
$('#stacked-form div').formset({
'addImage': 'add.png',
'deleteImage': 'delete.png'
});
}
});

test('Test Formset Creation with Images', function (assert) {
assert.equal($('#stacked-form div').size(), 1, 'Default form is present.');
assert.equal($('#stacked-form .delete-row').size(), 1, 'Delete button created.');
assert.equal(
$('#stacked-form .delete-row').html(),
"<img src=\"delete.png\">",
'Delete image created.'
);
assert.equal($('#stacked-form .add-row').size(), 1, 'Add button created.');
assert.equal(
$('#stacked-form .add-row').html(),
"<img src=\"add.png\">",
'Add image created.'
);
assert.ok($('#stacked-form div:first').hasClass('dynamic-form'), 'FormCssClass added to forms.');
});
}(jQuery));