Skip to content

Instantly share code, notes, and snippets.

@tkaemming
Created June 17, 2009 19:53
Show Gist options
  • Save tkaemming/131455 to your computer and use it in GitHub Desktop.
Save tkaemming/131455 to your computer and use it in GitHub Desktop.
Simple inlineformset plugin for jQuery and Django. This is a work in progress and not ready for a production environment, but a good starting point for forks to add additional functionality.
;(function($){
$.inlineformset = {
defaults: {
extra: 3,
formSelector: '.form',
formsetSelector: '.formset',
hideOnDeletion: true,
},
};
$.fn.inlineformset = function(options)
{
if ($(this).data('inlineformset-instance'))
{
return $(this).data('inlineformset-instance');
}
else
{
function InlineFormSet(container, options)
{
var container = container;
var settings = $.extend($.inlineformset.defaults, options);
var formset = $(container).find(settings.formsetSelector).get(0);
var totalForms = $(container).find('input[name$="TOTAL_FORMS"]').get(0);
var initialForms = $(container).find('input[name$="INITIAL_FORMS"]').get(0);
var prototypeForm = $(container).find(settings.formSelector + ':last').clone(true);
var initialize = function(self)
{
$(formset).find(settings.formSelector).each(function(i){
// Delete each form that does not have an ID or parent object associated with it.
if(!$(this).find('input[name$="-id"]').val() && !$(this).find('input[name$="_ptr"]').val())
{
$(this).remove();
}
else
{
// Add the deletion handler to the form if necessary.
if (settings.hideOnDeletion) {
addDeletionHandler($(this));
}
}
});
$(initialForms).val($(formset).find(settings.formSelector).length);
// Add the extra forms as neccessary.
for (var i = 0; i < settings.extra; i++)
{
self.addForm(false);
}
refreshFormset();
}
var addDeletionHandler = function(form)
{
$(form).find('input[name$="DELETE"]').bind('change', {'settings': settings}, function(event){
var settings = event.data.settings;
$(this).closest(settings.formSelector).addClass('deleted').hide();
});
}
var getFormset = function()
{
return formset;
}
var getPrototypeForm = function()
{
var form = $(prototypeForm).clone(true);
if (settings.hideOnDeletion) { addDeletionHandler(form); }
return form;
}
var refreshFormset = function()
{
var forms = {}
var fieldname_regex = new RegExp('^([a-zA-Z0-9_-]+)-([0-9]+)-([a-zA-Z0-9_]+)$');
$(container).find(settings.formSelector).each(function(i){
var prefix = null;
$(this).find('input, select').each(function(i){
var matches = $(this).attr('name').match(fieldname_regex);
if (matches)
{
prefix = matches[1];
return false;
}
});
if (prefix)
{
if (typeof forms[prefix] == "number")
{
forms[prefix] = forms[prefix] + 1;
}
else
{
forms[prefix] = 0;
}
}
$(this).find('input, select').each(function(i){
var matches = $(this).attr('name').match(fieldname_regex);
if (matches)
{
var new_field_name = prefix + '-' + forms[prefix] + '-' + matches[3];
$(this).attr('id', 'id_' + new_field_name);
$(this).attr('name', new_field_name);
}
});
$(this).find('label').each(function(i){
var matches = $(this).attr('for').match(fieldname_regex);
if (matches)
{
var new_field_name = prefix + '-' + forms[prefix] + '-' + matches[3];
$(this).attr('for', 'id_' + new_field_name);
}
});
});
$(totalForms).val($(container).find(settings.formSelector).length);
}
this.addForm = function(refresh)
{
// Default the value of the refresh argument to "true".
if (refresh == undefined) { refresh = true; }
form = getPrototypeForm();
formset = getFormset();
$(formset).append(form);
if (refresh) { refreshFormset(); }
};
initialize(this);
return this;
};
$(this).data('inlineformset-instance', new InlineFormSet(this, options));
return $(this).data('inlineformset-instance');
}
}
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment