Refs #29087 -- Refactored admin inlines.js.
Split logic into separate functions to clarify and allow reuse.
This commit is contained in:
parent
daa9415f78
commit
6ea3aadd17
|
@ -37,19 +37,17 @@
|
||||||
var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").prop("autocomplete", "off");
|
var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").prop("autocomplete", "off");
|
||||||
var nextIndex = parseInt(totalForms.val(), 10);
|
var nextIndex = parseInt(totalForms.val(), 10);
|
||||||
var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").prop("autocomplete", "off");
|
var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").prop("autocomplete", "off");
|
||||||
// only show the add button if we are allowed to add more items,
|
var addButton;
|
||||||
// note that max_num = None translates to a blank string.
|
|
||||||
var showAddButton = maxForms.val() === '' || (maxForms.val() - totalForms.val()) > 0;
|
/**
|
||||||
$this.each(function(i) {
|
* The "Add another MyModel" button below the inline forms.
|
||||||
$(this).not("." + options.emptyCssClass).addClass(options.formCssClass);
|
*/
|
||||||
});
|
var addInlineAddButton = function() {
|
||||||
if ($this.length && showAddButton) {
|
|
||||||
var addButton = options.addButton;
|
|
||||||
if (addButton === null) {
|
if (addButton === null) {
|
||||||
if ($this.prop("tagName") === "TR") {
|
if ($this.prop("tagName") === "TR") {
|
||||||
// If forms are laid out as table rows, insert the
|
// If forms are laid out as table rows, insert the
|
||||||
// "add" button in a new table row:
|
// "add" button in a new table row:
|
||||||
var numCols = this.eq(-1).children().length;
|
var numCols = $this.eq(-1).children().length;
|
||||||
$parent.append('<tr class="' + options.addCssClass + '"><td colspan="' + numCols + '"><a href="#">' + options.addText + "</a></tr>");
|
$parent.append('<tr class="' + options.addCssClass + '"><td colspan="' + numCols + '"><a href="#">' + options.addText + "</a></tr>");
|
||||||
addButton = $parent.find("tr:last a");
|
addButton = $parent.find("tr:last a");
|
||||||
} else {
|
} else {
|
||||||
|
@ -58,73 +56,100 @@
|
||||||
addButton = $this.filter(":last").next().find("a");
|
addButton = $this.filter(":last").next().find("a");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addButton.on('click', function(e) {
|
addButton.on('click', addInlineClickHandler);
|
||||||
e.preventDefault();
|
};
|
||||||
var template = $("#" + options.prefix + "-empty");
|
|
||||||
var row = template.clone(true);
|
var addInlineClickHandler = function(e) {
|
||||||
row.removeClass(options.emptyCssClass)
|
e.preventDefault();
|
||||||
.addClass(options.formCssClass)
|
var template = $("#" + options.prefix + "-empty");
|
||||||
.attr("id", options.prefix + "-" + nextIndex);
|
var row = template.clone(true);
|
||||||
if (row.is("tr")) {
|
row.removeClass(options.emptyCssClass)
|
||||||
// If the forms are laid out in table rows, insert
|
.addClass(options.formCssClass)
|
||||||
// the remove button into the last table cell:
|
.attr("id", options.prefix + "-" + nextIndex);
|
||||||
row.children(":last").append('<div><a class="' + options.deleteCssClass + '" href="#">' + options.deleteText + "</a></div>");
|
addInlineDeleteButton(row);
|
||||||
} else if (row.is("ul") || row.is("ol")) {
|
row.find("*").each(function() {
|
||||||
// If they're laid out as an ordered/unordered list,
|
updateElementIndex(this, options.prefix, totalForms.val());
|
||||||
// insert an <li> after the last list item:
|
|
||||||
row.append('<li><a class="' + options.deleteCssClass + '" href="#">' + options.deleteText + "</a></li>");
|
|
||||||
} else {
|
|
||||||
// Otherwise, just insert the remove button as the
|
|
||||||
// last child element of the form's container:
|
|
||||||
row.children(":first").append('<span><a class="' + options.deleteCssClass + '" href="#">' + options.deleteText + "</a></span>");
|
|
||||||
}
|
|
||||||
row.find("*").each(function() {
|
|
||||||
updateElementIndex(this, options.prefix, totalForms.val());
|
|
||||||
});
|
|
||||||
// Insert the new form when it has been fully edited
|
|
||||||
row.insertBefore($(template));
|
|
||||||
// Update number of total forms
|
|
||||||
$(totalForms).val(parseInt(totalForms.val(), 10) + 1);
|
|
||||||
nextIndex += 1;
|
|
||||||
// Hide add button in case we've hit the max, except we want to add infinitely
|
|
||||||
if ((maxForms.val() !== '') && (maxForms.val() - totalForms.val()) <= 0) {
|
|
||||||
addButton.parent().hide();
|
|
||||||
}
|
|
||||||
// The delete button of each row triggers a bunch of other things
|
|
||||||
row.find("a." + options.deleteCssClass).on('click', function(e1) {
|
|
||||||
e1.preventDefault();
|
|
||||||
// Remove the parent form containing this button:
|
|
||||||
row.remove();
|
|
||||||
nextIndex -= 1;
|
|
||||||
// If a post-delete callback was provided, call it with the deleted form:
|
|
||||||
if (options.removed) {
|
|
||||||
options.removed(row);
|
|
||||||
}
|
|
||||||
$(document).trigger('formset:removed', [row, options.prefix]);
|
|
||||||
// Update the TOTAL_FORMS form count.
|
|
||||||
var forms = $("." + options.formCssClass);
|
|
||||||
$("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length);
|
|
||||||
// Show add button again once we drop below max
|
|
||||||
if ((maxForms.val() === '') || (maxForms.val() - forms.length) > 0) {
|
|
||||||
addButton.parent().show();
|
|
||||||
}
|
|
||||||
// Also, update names and ids for all remaining form controls
|
|
||||||
// so they remain in sequence:
|
|
||||||
var i, formCount;
|
|
||||||
var updateElementCallback = function() {
|
|
||||||
updateElementIndex(this, options.prefix, i);
|
|
||||||
};
|
|
||||||
for (i = 0, formCount = forms.length; i < formCount; i++) {
|
|
||||||
updateElementIndex($(forms).get(i), options.prefix, i);
|
|
||||||
$(forms.get(i)).find("*").each(updateElementCallback);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// If a post-add callback was supplied, call it with the added form:
|
|
||||||
if (options.added) {
|
|
||||||
options.added(row);
|
|
||||||
}
|
|
||||||
$(document).trigger('formset:added', [row, options.prefix]);
|
|
||||||
});
|
});
|
||||||
|
// Insert the new form when it has been fully edited.
|
||||||
|
row.insertBefore($(template));
|
||||||
|
// Update number of total forms.
|
||||||
|
$(totalForms).val(parseInt(totalForms.val(), 10) + 1);
|
||||||
|
nextIndex += 1;
|
||||||
|
// Hide the add button if there's a limit and it's been reached.
|
||||||
|
if ((maxForms.val() !== '') && (maxForms.val() - totalForms.val()) <= 0) {
|
||||||
|
addButton.parent().hide();
|
||||||
|
}
|
||||||
|
// Pass the new form to the post-add callback, if provided.
|
||||||
|
if (options.added) {
|
||||||
|
options.added(row);
|
||||||
|
}
|
||||||
|
$(document).trigger('formset:added', [row, options.prefix]);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "X" button that is part of every unsaved inline.
|
||||||
|
* (When saved, it is replaced with a "Delete" checkbox.)
|
||||||
|
*/
|
||||||
|
var addInlineDeleteButton = function(row) {
|
||||||
|
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('<div><a class="' + options.deleteCssClass + '" href="#">' + options.deleteText + "</a></div>");
|
||||||
|
} 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="#">' + options.deleteText + "</a></li>");
|
||||||
|
} else {
|
||||||
|
// Otherwise, just insert the remove button as the
|
||||||
|
// last child element of the form's container:
|
||||||
|
row.children(":first").append('<span><a class="' + options.deleteCssClass + '" href="#">' + options.deleteText + "</a></span>");
|
||||||
|
}
|
||||||
|
// Add delete handler for each row.
|
||||||
|
row.find("a." + options.deleteCssClass).on('click', inlineDeleteHandler.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
var inlineDeleteHandler = function(e1) {
|
||||||
|
e1.preventDefault();
|
||||||
|
var deleteButton = $(e1.target);
|
||||||
|
var row = deleteButton.closest('.' + options.formCssClass);
|
||||||
|
// Remove the parent form containing this button:
|
||||||
|
row.remove();
|
||||||
|
nextIndex -= 1;
|
||||||
|
// Pass the deleted form to the post-delete callback, if provided.
|
||||||
|
if (options.removed) {
|
||||||
|
options.removed(row);
|
||||||
|
}
|
||||||
|
$(document).trigger('formset:removed', [row, options.prefix]);
|
||||||
|
// Update the TOTAL_FORMS form count.
|
||||||
|
var forms = $("." + options.formCssClass);
|
||||||
|
$("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length);
|
||||||
|
// Show add button again once below maximum number.
|
||||||
|
if ((maxForms.val() === '') || (maxForms.val() - forms.length) > 0) {
|
||||||
|
addButton.parent().show();
|
||||||
|
}
|
||||||
|
// Also, update names and ids for all remaining form controls so
|
||||||
|
// they remain in sequence:
|
||||||
|
var i, formCount;
|
||||||
|
var updateElementCallback = function() {
|
||||||
|
updateElementIndex(this, options.prefix, i);
|
||||||
|
};
|
||||||
|
for (i = 0, formCount = forms.length; i < formCount; i++) {
|
||||||
|
updateElementIndex($(forms).get(i), options.prefix, i);
|
||||||
|
$(forms.get(i)).find("*").each(updateElementCallback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Show the add button if we are allowed to add more items.
|
||||||
|
// Note that max_num = None translates to a blank string.
|
||||||
|
var showAddButton = maxForms.val() === '' || (maxForms.val() - totalForms.val()) > 0;
|
||||||
|
$this.each(function(i) {
|
||||||
|
$(this).not("." + options.emptyCssClass).addClass(options.formCssClass);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create the add button.
|
||||||
|
addButton = options.addButton;
|
||||||
|
if ($this.length && showAddButton) {
|
||||||
|
addInlineAddButton();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
(function(b){b.fn.formset=function(c){var a=b.extend({},b.fn.formset.defaults,c),d=b(this);c=d.parent();var h=function(a,e,f){var c=new RegExp("("+e+"-(\\d+|__prefix__))");e=e+"-"+f;b(a).prop("for")&&b(a).prop("for",b(a).prop("for").replace(c,e));a.id&&(a.id=a.id.replace(c,e));a.name&&(a.name=a.name.replace(c,e))},g=b("#id_"+a.prefix+"-TOTAL_FORMS").prop("autocomplete","off"),k=parseInt(g.val(),10),e=b("#id_"+a.prefix+"-MAX_NUM_FORMS").prop("autocomplete","off"),f=""===e.val()||0<e.val()-g.val();
|
(function(b){b.fn.formset=function(c){var a=b.extend({},b.fn.formset.defaults,c),d=b(this),h=d.parent(),l=function(a,e,k){var f=new RegExp("("+e+"-(\\d+|__prefix__))");e=e+"-"+k;b(a).prop("for")&&b(a).prop("for",b(a).prop("for").replace(f,e));a.id&&(a.id=a.id.replace(f,e));a.name&&(a.name=a.name.replace(f,e))},g=b("#id_"+a.prefix+"-TOTAL_FORMS").prop("autocomplete","off"),e=parseInt(g.val(),10),k=b("#id_"+a.prefix+"-MAX_NUM_FORMS").prop("autocomplete","off");c=function(){if(null===m)if("TR"===d.prop("tagName")){var b=
|
||||||
d.each(function(e){b(this).not("."+a.emptyCssClass).addClass(a.formCssClass)});if(d.length&&f){var m=a.addButton;null===m&&("TR"===d.prop("tagName")?(d=this.eq(-1).children().length,c.append('<tr class="'+a.addCssClass+'"><td colspan="'+d+'"><a href="#">'+a.addText+"</a></tr>"),m=c.find("tr:last a")):(d.filter(":last").after('<div class="'+a.addCssClass+'"><a href="#">'+a.addText+"</a></div>"),m=d.filter(":last").next().find("a")));m.on("click",function(f){f.preventDefault();f=b("#"+a.prefix+"-empty");
|
d.eq(-1).children().length;h.append('<tr class="'+a.addCssClass+'"><td colspan="'+b+'"><a href="#">'+a.addText+"</a></tr>");m=h.find("tr:last a")}else d.filter(":last").after('<div class="'+a.addCssClass+'"><a href="#">'+a.addText+"</a></div>"),m=d.filter(":last").next().find("a");m.on("click",n)};var n=function(f){f.preventDefault();f=b("#"+a.prefix+"-empty");var c=f.clone(!0);c.removeClass(a.emptyCssClass).addClass(a.formCssClass).attr("id",a.prefix+"-"+e);p(c);c.find("*").each(function(){l(this,
|
||||||
var c=f.clone(!0);c.removeClass(a.emptyCssClass).addClass(a.formCssClass).attr("id",a.prefix+"-"+k);c.is("tr")?c.children(":last").append('<div><a class="'+a.deleteCssClass+'" href="#">'+a.deleteText+"</a></div>"):c.is("ul")||c.is("ol")?c.append('<li><a class="'+a.deleteCssClass+'" href="#">'+a.deleteText+"</a></li>"):c.children(":first").append('<span><a class="'+a.deleteCssClass+'" href="#">'+a.deleteText+"</a></span>");c.find("*").each(function(){h(this,a.prefix,g.val())});c.insertBefore(b(f));
|
a.prefix,g.val())});c.insertBefore(b(f));b(g).val(parseInt(g.val(),10)+1);e+=1;""!==k.val()&&0>=k.val()-g.val()&&m.parent().hide();a.added&&a.added(c);b(document).trigger("formset:added",[c,a.prefix])},p=function(b){b.is("tr")?b.children(":last").append('<div><a class="'+a.deleteCssClass+'" href="#">'+a.deleteText+"</a></div>"):b.is("ul")||b.is("ol")?b.append('<li><a class="'+a.deleteCssClass+'" href="#">'+a.deleteText+"</a></li>"):b.children(":first").append('<span><a class="'+a.deleteCssClass+'" href="#">'+
|
||||||
b(g).val(parseInt(g.val(),10)+1);k+=1;""!==e.val()&&0>=e.val()-g.val()&&m.parent().hide();c.find("a."+a.deleteCssClass).on("click",function(f){f.preventDefault();c.remove();--k;a.removed&&a.removed(c);b(document).trigger("formset:removed",[c,a.prefix]);f=b("."+a.formCssClass);b("#id_"+a.prefix+"-TOTAL_FORMS").val(f.length);(""===e.val()||0<e.val()-f.length)&&m.parent().show();var d,g=function(){h(this,a.prefix,l)};var l=0;for(d=f.length;l<d;l++)h(b(f).get(l),a.prefix,l),b(f.get(l)).find("*").each(g)});
|
a.deleteText+"</a></span>");b.find("a."+a.deleteCssClass).on("click",q.bind(this))},q=function(c){c.preventDefault();c=b(c.target).closest("."+a.formCssClass);c.remove();--e;a.removed&&a.removed(c);b(document).trigger("formset:removed",[c,a.prefix]);c=b("."+a.formCssClass);b("#id_"+a.prefix+"-TOTAL_FORMS").val(c.length);(""===k.val()||0<k.val()-c.length)&&m.parent().show();var d,g=function(){l(this,a.prefix,f)};var f=0;for(d=c.length;f<d;f++)l(b(c).get(f),a.prefix,f),b(c.get(f)).find("*").each(g)},
|
||||||
a.added&&a.added(c);b(document).trigger("formset:added",[c,a.prefix])})}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,addButton:null};b.fn.tabularFormset=function(c,a){var d=b(this),h=function(a){b(c).not(".add-row").removeClass("row1 row2").filter(":even").addClass("row1").end().filter(":odd").addClass("row2")},g=function(){"undefined"!==
|
r=""===k.val()||0<k.val()-g.val();d.each(function(e){b(this).not("."+a.emptyCssClass).addClass(a.formCssClass)});var m=a.addButton;d.length&&r&&c();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,addButton:null};b.fn.tabularFormset=function(c,a){var d=b(this),h=function(a){b(c).not(".add-row").removeClass("row1 row2").filter(":even").addClass("row1").end().filter(":odd").addClass("row2")},
|
||||||
typeof SelectFilter&&(b(".selectfilter").each(function(a,b){a=b.name.split("-");SelectFilter.init(b.id,a[a.length-1],!1)}),b(".selectfilterstacked").each(function(a,b){a=b.name.split("-");SelectFilter.init(b.id,a[a.length-1],!0)}))},k=function(a){a.find(".prepopulated_field").each(function(){var c=b(this).find("input, select, textarea"),e=c.data("dependency_list")||[],d=[];b.each(e,function(b,c){d.push("#"+a.find(".field-"+c).find("input, select, textarea").attr("id"))});d.length&&c.prepopulate(d,
|
l=function(){"undefined"!==typeof SelectFilter&&(b(".selectfilter").each(function(a,b){a=b.name.split("-");SelectFilter.init(b.id,a[a.length-1],!1)}),b(".selectfilterstacked").each(function(a,b){a=b.name.split("-");SelectFilter.init(b.id,a[a.length-1],!0)}))},g=function(a){a.find(".prepopulated_field").each(function(){var c=b(this).find("input, select, textarea"),e=c.data("dependency_list")||[],d=[];b.each(e,function(b,c){d.push("#"+a.find(".field-"+c).find("input, select, textarea").attr("id"))});
|
||||||
c.attr("maxlength"))})};d.formset({prefix:a.prefix,addText:a.addText,formCssClass:"dynamic-"+a.prefix,deleteCssClass:"inline-deletelink",deleteText:a.deleteText,emptyCssClass:"empty-form",removed:h,added:function(a){k(a);"undefined"!==typeof DateTimeShortcuts&&(b(".datetimeshortcuts").remove(),DateTimeShortcuts.init());g();h(a)},addButton:a.addButton});return d};b.fn.stackedFormset=function(c,a){var d=b(this),h=function(a){b(c).find(".inline_label").each(function(a){a+=1;b(this).html(b(this).html().replace(/(#\d+)/g,
|
d.length&&c.prepopulate(d,c.attr("maxlength"))})};d.formset({prefix:a.prefix,addText:a.addText,formCssClass:"dynamic-"+a.prefix,deleteCssClass:"inline-deletelink",deleteText:a.deleteText,emptyCssClass:"empty-form",removed:h,added:function(a){g(a);"undefined"!==typeof DateTimeShortcuts&&(b(".datetimeshortcuts").remove(),DateTimeShortcuts.init());l();h(a)},addButton:a.addButton});return d};b.fn.stackedFormset=function(c,a){var d=b(this),h=function(a){b(c).find(".inline_label").each(function(a){a+=1;
|
||||||
"#"+a))})},g=function(){"undefined"!==typeof SelectFilter&&(b(".selectfilter").each(function(a,b){a=b.name.split("-");SelectFilter.init(b.id,a[a.length-1],!1)}),b(".selectfilterstacked").each(function(a,b){a=b.name.split("-");SelectFilter.init(b.id,a[a.length-1],!0)}))},k=function(a){a.find(".prepopulated_field").each(function(){var c=b(this).find("input, select, textarea"),d=c.data("dependency_list")||[],e=[];b.each(d,function(b,c){e.push("#"+a.find(".form-row .field-"+c).find("input, select, textarea").attr("id"))});
|
b(this).html(b(this).html().replace(/(#\d+)/g,"#"+a))})},l=function(){"undefined"!==typeof SelectFilter&&(b(".selectfilter").each(function(a,b){a=b.name.split("-");SelectFilter.init(b.id,a[a.length-1],!1)}),b(".selectfilterstacked").each(function(a,b){a=b.name.split("-");SelectFilter.init(b.id,a[a.length-1],!0)}))},g=function(a){a.find(".prepopulated_field").each(function(){var c=b(this).find("input, select, textarea"),d=c.data("dependency_list")||[],e=[];b.each(d,function(b,c){e.push("#"+a.find(".form-row .field-"+
|
||||||
e.length&&c.prepopulate(e,c.attr("maxlength"))})};d.formset({prefix:a.prefix,addText:a.addText,formCssClass:"dynamic-"+a.prefix,deleteCssClass:"inline-deletelink",deleteText:a.deleteText,emptyCssClass:"empty-form",removed:h,added:function(a){k(a);"undefined"!==typeof DateTimeShortcuts&&(b(".datetimeshortcuts").remove(),DateTimeShortcuts.init());g();h(a)},addButton:a.addButton});return d};b(document).ready(function(){b(".js-inline-admin-formset").each(function(){var c=b(this).data(),a=c.inlineFormset;
|
c).find("input, select, textarea").attr("id"))});e.length&&c.prepopulate(e,c.attr("maxlength"))})};d.formset({prefix:a.prefix,addText:a.addText,formCssClass:"dynamic-"+a.prefix,deleteCssClass:"inline-deletelink",deleteText:a.deleteText,emptyCssClass:"empty-form",removed:h,added:function(a){g(a);"undefined"!==typeof DateTimeShortcuts&&(b(".datetimeshortcuts").remove(),DateTimeShortcuts.init());l();h(a)},addButton:a.addButton});return d};b(document).ready(function(){b(".js-inline-admin-formset").each(function(){var c=
|
||||||
switch(c.inlineType){case "stacked":c=a.name+"-group .inline-related";b(c).stackedFormset(c,a.options);break;case "tabular":c=a.name+"-group .tabular.inline-related tbody:first > tr",b(c).tabularFormset(c,a.options)}})})})(django.jQuery);
|
b(this).data(),a=c.inlineFormset;switch(c.inlineType){case "stacked":c=a.name+"-group .inline-related";b(c).stackedFormset(c,a.options);break;case "tabular":c=a.name+"-group .tabular.inline-related tbody:first > tr",b(c).tabularFormset(c,a.options)}})})})(django.jQuery);
|
||||||
|
|
Loading…
Reference in New Issue