Skip to content

Commit 18df284

Browse files
committed
Shows add button even with no forms
This allows to add a form when the formset is empty. It requires the option addContainerClass to be set.
1 parent 5e2c95c commit 18df284

File tree

1 file changed

+71
-73
lines changed

1 file changed

+71
-73
lines changed

src/jquery.formset.js

Lines changed: 71 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -143,82 +143,80 @@
143143
}
144144
});
145145

146-
if ($$.length) {
147-
var hideAddButton = !showAddButton(),
148-
addButton, template;
149-
if (options.formTemplate) {
150-
// If a form template was specified, we'll clone it to generate new form instances:
151-
template = (options.formTemplate instanceof $) ? options.formTemplate : $(options.formTemplate);
152-
template.removeAttr('id').addClass(options.formCssClass + ' formset-custom-template');
153-
template.find(childElementSelector).each(function() {
154-
updateElementIndex($(this), options.prefix, '__prefix__');
155-
});
156-
insertDeleteLink(template);
157-
} else {
158-
// Otherwise, use the last form in the formset; this works much better if you've got
159-
// extra (>= 1) forms (thnaks to justhamade for pointing this out):
160-
if (options.hideLastAddForm) $('.' + options.formCssClass + ':last').hide();
161-
template = $('.' + options.formCssClass + ':last').clone(true).removeAttr('id');
162-
template.find('input:hidden[id $= "-DELETE"]').remove();
163-
// Clear all cloned fields, except those the user wants to keep (thanks to brunogola for the suggestion):
164-
template.find(childElementSelector).not(options.keepFieldValues).each(function() {
165-
var elem = $(this);
166-
// If this is a checkbox or radiobutton, uncheck it.
167-
// This fixes Issue 1, reported by Wilson.Andrew.J:
168-
if (elem.is('input:checkbox') || elem.is('input:radio')) {
169-
elem.attr('checked', false);
170-
} else {
171-
elem.val('');
172-
}
173-
});
174-
}
175-
// FIXME: Perhaps using $.data would be a better idea?
176-
options.formTemplate = template;
177-
178-
var addButtonHTML = '<a class="' + options.addCssClass + '" href="javascript:void(0);">' + options.addText + '</a>';
179-
if (options.addContainerClass) {
180-
// If we have a specific container for the "add" button,
181-
// place it as the last child of that container:
182-
var addContainer = $('[class*="' + options.addContainerClass + '"');
183-
addContainer.append(addButtonHTML);
184-
addButton = addContainer.find('[class="' + options.addCssClass + '"]');
185-
} else if ($$.is('TR')) {
186-
// If forms are laid out as table rows, insert the
187-
// "add" button in a new table row:
188-
var numCols = $$.eq(0).children().length, // This is a bit of an assumption :|
189-
buttonRow = $('<tr><td colspan="' + numCols + '">' + addButtonHTML + '</tr>').addClass(options.formCssClass + '-add');
190-
$$.parent().append(buttonRow);
191-
addButton = buttonRow.find('a');
192-
} else {
193-
// Otherwise, insert it immediately after the last form:
194-
$$.filter(':last').after(addButtonHTML);
195-
addButton = $$.filter(':last').next();
196-
}
197-
198-
if (hideAddButton) addButton.hide();
199-
200-
addButton.click(function() {
201-
var formCount = parseInt(totalForms.val()),
202-
row = options.formTemplate.clone(true).removeClass('formset-custom-template'),
203-
buttonRow = $($(this).parents('tr.' + options.formCssClass + '-add').get(0) || this),
204-
delCssSelector = $.trim(options.deleteCssClass).replace(/\s+/g, '.');
205-
applyExtraClasses(row, formCount);
206-
row.insertBefore(buttonRow).show();
207-
row.find(childElementSelector).each(function() {
208-
updateElementIndex($(this), options.prefix, formCount);
209-
});
210-
totalForms.val(formCount + 1);
211-
// Check if we're above the minimum allowed number of forms -> show all delete link(s)
212-
if (showDeleteLinks()){
213-
$('a.' + delCssSelector).each(function(){$(this).show();});
146+
var hideAddButton = !showAddButton(),
147+
addButton, template;
148+
if (options.formTemplate) {
149+
// If a form template was specified, we'll clone it to generate new form instances:
150+
template = (options.formTemplate instanceof $) ? options.formTemplate : $(options.formTemplate);
151+
template.removeAttr('id').addClass(options.formCssClass + ' formset-custom-template');
152+
template.find(childElementSelector).each(function() {
153+
updateElementIndex($(this), options.prefix, '__prefix__');
154+
});
155+
insertDeleteLink(template);
156+
} else {
157+
// Otherwise, use the last form in the formset; this works much better if you've got
158+
// extra (>= 1) forms (thnaks to justhamade for pointing this out):
159+
if (options.hideLastAddForm) $('.' + options.formCssClass + ':last').hide();
160+
template = $('.' + options.formCssClass + ':last').clone(true).removeAttr('id');
161+
template.find('input:hidden[id $= "-DELETE"]').remove();
162+
// Clear all cloned fields, except those the user wants to keep (thanks to brunogola for the suggestion):
163+
template.find(childElementSelector).not(options.keepFieldValues).each(function() {
164+
var elem = $(this);
165+
// If this is a checkbox or radiobutton, uncheck it.
166+
// This fixes Issue 1, reported by Wilson.Andrew.J:
167+
if (elem.is('input:checkbox') || elem.is('input:radio')) {
168+
elem.attr('checked', false);
169+
} else {
170+
elem.val('');
214171
}
215-
// Check if we've exceeded the maximum allowed number of forms:
216-
if (!showAddButton()) buttonRow.hide();
217-
// If a post-add callback was supplied, call it with the added form:
218-
if (options.added) options.added(row);
219-
return false;
220172
});
221173
}
174+
// FIXME: Perhaps using $.data would be a better idea?
175+
options.formTemplate = template;
176+
177+
var addButtonHTML = '<a class="' + options.addCssClass + '" href="javascript:void(0);">' + options.addText + '</a>';
178+
if (options.addContainerClass) {
179+
// If we have a specific container for the "add" button,
180+
// place it as the last child of that container:
181+
var addContainer = $('[class*="' + options.addContainerClass + '"');
182+
addContainer.append(addButtonHTML);
183+
addButton = addContainer.find('[class="' + options.addCssClass + '"]');
184+
} else if ($$.is('TR')) {
185+
// If forms are laid out as table rows, insert the
186+
// "add" button in a new table row:
187+
var numCols = $$.eq(0).children().length, // This is a bit of an assumption :|
188+
buttonRow = $('<tr><td colspan="' + numCols + '">' + addButtonHTML + '</tr>').addClass(options.formCssClass + '-add');
189+
$$.parent().append(buttonRow);
190+
addButton = buttonRow.find('a');
191+
} else {
192+
// Otherwise, insert it immediately after the last form:
193+
$$.filter(':last').after(addButtonHTML);
194+
addButton = $$.filter(':last').next();
195+
}
196+
197+
if (hideAddButton) addButton.hide();
198+
199+
addButton.click(function() {
200+
var formCount = parseInt(totalForms.val()),
201+
row = options.formTemplate.clone(true).removeClass('formset-custom-template'),
202+
buttonRow = $($(this).parents('tr.' + options.formCssClass + '-add').get(0) || this),
203+
delCssSelector = $.trim(options.deleteCssClass).replace(/\s+/g, '.');
204+
applyExtraClasses(row, formCount);
205+
row.insertBefore(buttonRow).show();
206+
row.find(childElementSelector).each(function() {
207+
updateElementIndex($(this), options.prefix, formCount);
208+
});
209+
totalForms.val(formCount + 1);
210+
// Check if we're above the minimum allowed number of forms -> show all delete link(s)
211+
if (showDeleteLinks()){
212+
$('a.' + delCssSelector).each(function(){$(this).show();});
213+
}
214+
// Check if we've exceeded the maximum allowed number of forms:
215+
if (!showAddButton()) buttonRow.hide();
216+
// If a post-add callback was supplied, call it with the added form:
217+
if (options.added) options.added(row);
218+
return false;
219+
});
222220

223221
return $$;
224222
};

0 commit comments

Comments
 (0)