Fixed #15569 -- Corrected the numbering updates to inlines when rows are added and deleted. Thanks to sbaechler for the report, to Arthur de Jong and mk for the work on the patch, and to Karen Tracey for the last minute testing help.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15862 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2011-03-17 00:44:12 +00:00
parent 274849c873
commit c2ae6b2af7
2 changed files with 11 additions and 34 deletions

View File

@ -18,7 +18,7 @@
$.fn.formset = function(opts) { $.fn.formset = function(opts) {
var options = $.extend({}, $.fn.formset.defaults, opts); var options = $.extend({}, $.fn.formset.defaults, opts);
var updateElementIndex = function(el, prefix, ndx) { var updateElementIndex = function(el, prefix, ndx) {
var id_regex = new RegExp("(" + prefix + "-\\d+)"); var id_regex = new RegExp("(" + prefix + "-(\\d+|__prefix__))");
var replacement = prefix + "-" + ndx; var replacement = prefix + "-" + ndx;
if ($(el).attr("for")) { if ($(el).attr("for")) {
$(el).attr("for", $(el).attr("for").replace(id_regex, replacement)); $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
@ -59,31 +59,6 @@
row.removeClass(options.emptyCssClass) row.removeClass(options.emptyCssClass)
.addClass(options.formCssClass) .addClass(options.formCssClass)
.attr("id", options.prefix + "-" + nextIndex); .attr("id", options.prefix + "-" + nextIndex);
nextIndex += 1;
row.find("*")
.filter(function() {
var el = $(this);
return el.attr("id") && el.attr("id").search(/__prefix__/) >= 0;
}).each(function() {
var el = $(this);
el.attr("id", el.attr("id").replace(/__prefix__/g, nextIndex));
})
.end()
.filter(function() {
var el = $(this);
return el.attr("name") && el.attr("name").search(/__prefix__/) >= 0;
}).each(function() {
var el = $(this);
el.attr("name", el.attr("name").replace(/__prefix__/g, nextIndex));
})
.end()
.filter(function() {
var el = $(this);
return el.attr("for") && el.attr("for").search(/__prefix__/) >= 0;
}).each(function() {
var el = $(this);
el.attr("for", el.attr("for").replace(/__prefix__/g, nextIndex));
});
if (row.is("tr")) { if (row.is("tr")) {
// If the forms are laid out in table rows, insert // If the forms are laid out in table rows, insert
// the remove button into the last table cell: // the remove button into the last table cell:
@ -97,13 +72,14 @@
// last child element of the form's container: // last child element of the form's container:
row.children(":first").append('<span><a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + options.deleteText + "</a></span>"); row.children(":first").append('<span><a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + options.deleteText + "</a></span>");
} }
row.find("input,select,textarea,label,a").each(function() { row.find("*").each(function() {
updateElementIndex(this, options.prefix, totalForms.val()); updateElementIndex(this, options.prefix, totalForms.val());
}); });
// Insert the new form when it has been fully edited // Insert the new form when it has been fully edited
row.insertBefore($(template)); row.insertBefore($(template));
// Update number of total forms // Update number of total forms
$(totalForms).val(parseInt(totalForms.val()) + 1); $(totalForms).val(parseInt(totalForms.val()) + 1);
nextIndex += 1;
// Hide add button in case we've hit the max, except we want to add infinitely // Hide add button in case we've hit the max, except we want to add infinitely
if ((maxForms.val() != '') && (maxForms.val()-totalForms.val()) <= 0) { if ((maxForms.val() != '') && (maxForms.val()-totalForms.val()) <= 0) {
addButton.parent().hide(); addButton.parent().hide();
@ -113,6 +89,7 @@
// Remove the parent form containing this button: // Remove the parent form containing this button:
var row = $(this).parents("." + options.formCssClass); var row = $(this).parents("." + options.formCssClass);
row.remove(); row.remove();
nextIndex -= 1;
// If a post-delete callback was provided, call it with the deleted form: // If a post-delete callback was provided, call it with the deleted form:
if (options.removed) { if (options.removed) {
options.removed(row); options.removed(row);
@ -128,7 +105,8 @@
// so they remain in sequence: // so they remain in sequence:
for (var i=0, formCount=forms.length; i<formCount; i++) for (var i=0, formCount=forms.length; i<formCount; i++)
{ {
$(forms.get(i)).find("input,select,textarea,label,a").each(function() { updateElementIndex($(forms).get(i), options.prefix, i);
$(forms.get(i)).find("*").each(function() {
updateElementIndex(this, options.prefix, i); updateElementIndex(this, options.prefix, i);
}); });
} }

View File

@ -1,6 +1,5 @@
(function(a){a.fn.formset=function(g){var b=a.extend({},a.fn.formset.defaults,g),l=function(d,f,e){var c=RegExp("("+f+"-\\d+)");f=f+"-"+e;a(d).attr("for")&&a(d).attr("for",a(d).attr("for").replace(c,f));if(d.id)d.id=d.id.replace(c,f);if(d.name)d.name=d.name.replace(c,f)};g=a("#id_"+b.prefix+"-TOTAL_FORMS").attr("autocomplete","off");var i=parseInt(g.val()),h=a("#id_"+b.prefix+"-MAX_NUM_FORMS").attr("autocomplete","off");g=h.val()==""||h.val()-g.val()>0;a(this).each(function(){a(this).not("."+b.emptyCssClass).addClass(b.formCssClass)}); (function(b){b.fn.formset=function(g){var a=b.extend({},b.fn.formset.defaults,g),k=function(c,f,d){var e=new RegExp("("+f+"-(\\d+|__prefix__))");f=f+"-"+d;b(c).attr("for")&&b(c).attr("for",b(c).attr("for").replace(e,f));if(c.id)c.id=c.id.replace(e,f);if(c.name)c.name=c.name.replace(e,f)};g=b("#id_"+a.prefix+"-TOTAL_FORMS").attr("autocomplete","off");var l=parseInt(g.val()),h=b("#id_"+a.prefix+"-MAX_NUM_FORMS").attr("autocomplete","off");g=h.val()==""||h.val()-g.val()>0;b(this).each(function(){b(this).not("."+
if(a(this).length&&g){var j;if(a(this).attr("tagName")=="TR"){g=this.eq(0).children().length;a(this).parent().append('<tr class="'+b.addCssClass+'"><td colspan="'+g+'"><a href="javascript:void(0)">'+b.addText+"</a></tr>");j=a(this).parent().find("tr:last a")}else{a(this).filter(":last").after('<div class="'+b.addCssClass+'"><a href="javascript:void(0)">'+b.addText+"</a></div>");j=a(this).filter(":last").next().find("a")}j.click(function(){var d=a("#id_"+b.prefix+"-TOTAL_FORMS"),f=a("#"+b.prefix+"-empty"), a.emptyCssClass).addClass(a.formCssClass)});if(b(this).length&&g){var j;if(b(this).attr("tagName")=="TR"){g=this.eq(0).children().length;b(this).parent().append('<tr class="'+a.addCssClass+'"><td colspan="'+g+'"><a href="javascript:void(0)">'+a.addText+"</a></tr>");j=b(this).parent().find("tr:last a")}else{b(this).filter(":last").after('<div class="'+a.addCssClass+'"><a href="javascript:void(0)">'+a.addText+"</a></div>");j=b(this).filter(":last").next().find("a")}j.click(function(){var c=b("#id_"+
e=f.clone(true);e.removeClass(b.emptyCssClass).addClass(b.formCssClass).attr("id",b.prefix+"-"+i);i+=1;e.find("*").filter(function(){var c=a(this);return c.attr("id")&&c.attr("id").search(/__prefix__/)>=0}).each(function(){var c=a(this);c.attr("id",c.attr("id").replace(/__prefix__/g,i))}).end().filter(function(){var c=a(this);return c.attr("name")&&c.attr("name").search(/__prefix__/)>=0}).each(function(){var c=a(this);c.attr("name",c.attr("name").replace(/__prefix__/g,i))}).end().filter(function(){var c= a.prefix+"-TOTAL_FORMS"),f=b("#"+a.prefix+"-empty"),d=f.clone(true);d.removeClass(a.emptyCssClass).addClass(a.formCssClass).attr("id",a.prefix+"-"+l);if(d.is("tr"))d.children(":last").append('<div><a class="'+a.deleteCssClass+'" href="javascript:void(0)">'+a.deleteText+"</a></div>");else d.is("ul")||d.is("ol")?d.append('<li><a class="'+a.deleteCssClass+'" href="javascript:void(0)">'+a.deleteText+"</a></li>"):d.children(":first").append('<span><a class="'+a.deleteCssClass+'" href="javascript:void(0)">'+
a(this);return c.attr("for")&&c.attr("for").search(/__prefix__/)>=0}).each(function(){var c=a(this);c.attr("for",c.attr("for").replace(/__prefix__/g,i))});if(e.is("tr"))e.children(":last").append('<div><a class="'+b.deleteCssClass+'" href="javascript:void(0)">'+b.deleteText+"</a></div>");else e.is("ul")||e.is("ol")?e.append('<li><a class="'+b.deleteCssClass+'" href="javascript:void(0)">'+b.deleteText+"</a></li>"):e.children(":first").append('<span><a class="'+b.deleteCssClass+'" href="javascript:void(0)">'+ a.deleteText+"</a></span>");d.find("*").each(function(){k(this,a.prefix,c.val())});d.insertBefore(b(f));b(c).val(parseInt(c.val())+1);l+=1;h.val()!=""&&h.val()-c.val()<=0&&j.parent().hide();d.find("a."+a.deleteCssClass).click(function(){var e=b(this).parents("."+a.formCssClass);e.remove();l-=1;a.removed&&a.removed(e);e=b("."+a.formCssClass);b("#id_"+a.prefix+"-TOTAL_FORMS").val(e.length);if(h.val()==""||h.val()-e.length>0)j.parent().show();for(var i=0,m=e.length;i<m;i++){k(b(e).get(i),a.prefix,i);
b.deleteText+"</a></span>");e.find("input,select,textarea,label,a").each(function(){l(this,b.prefix,d.val())});e.insertBefore(a(f));a(d).val(parseInt(d.val())+1);h.val()!=""&&h.val()-d.val()<=0&&j.parent().hide();e.find("a."+b.deleteCssClass).click(function(){var c=a(this).parents("."+b.formCssClass);c.remove();b.removed&&b.removed(c);c=a("."+b.formCssClass);a("#id_"+b.prefix+"-TOTAL_FORMS").val(c.length);if(h.val()==""||h.val()-c.length>0)j.parent().show();for(var k=0,m=c.length;k<m;k++)a(c.get(k)).find("input,select,textarea,label,a").each(function(){l(this, b(e.get(i)).find("*").each(function(){k(this,a.prefix,i)})}return false});a.added&&a.added(d);return false})}return this};b.fn.formset.defaults={prefix:"form",addText:"add another",deleteText:"remove",addCssClass:"add-row",deleteCssClass:"delete-row",emptyCssClass:"empty-row",formCssClass:"dynamic-form",added:null,removed:null}})(django.jQuery);
b.prefix,k)});return false});b.added&&b.added(e);return false})}return this};a.fn.formset.defaults={prefix:"form",addText:"add another",deleteText:"remove",addCssClass:"add-row",deleteCssClass:"delete-row",emptyCssClass:"empty-row",formCssClass:"dynamic-form",added:null,removed:null}})(django.jQuery);