1. trendymoniker
  2. django-selectable

Commits

Mark Lavin  committed 0306986

Patch django formset js to work with dynamic inlines.

  • Participants
  • Parent commits ffa8bbd
  • Branches admin-inlines

Comments (0)

Files changed (3)

File example/core/admin.py

View file
     model = Farm
     form = FarmAdminForm
 
-    class Media(object):
-        js = ('%sjs/inlines.js' % MEDIA_PREFIX, )
-
 
 class NewUserAdmin(UserAdmin):
     inlines = [

File selectable/static/js/inlines.js

-/**
- * Django admin inlines
- *
- * Based on jQuery Formset 1.1
- * @author Stanislaus Madueke (stan DOT madueke AT gmail DOT com)
- * @requires jQuery 1.2.6 or later
- *
- * Copyright (c) 2009, Stanislaus Madueke
- * All rights reserved.
- *
- * Spiced up with Code from Zain Memon's GSoC project 2009
- * and modified for Django by Jannis Leidel
- *
- * Licensed under the New BSD License
- * See: http://www.opensource.org/licenses/bsd-license.php
- */
-(function($) {
-	$.fn.formset = function(opts) {
-		var options = $.extend({}, $.fn.formset.defaults, opts);
-		var updateElementIndex = function(el, prefix, ndx) {
-			var id_regex = new RegExp("(" + prefix + "-(\\d+|__prefix__))");
-			var replacement = prefix + "-" + ndx;
-			if ($(el).attr("for")) {
-				$(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
-			}
-			if (el.id) {
-				el.id = el.id.replace(id_regex, replacement);
-			}
-			if (el.name) {
-				el.name = el.name.replace(id_regex, replacement);
-			}
-		};
-		var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").attr("autocomplete", "off");
-		var nextIndex = parseInt(totalForms.val());
-		var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").attr("autocomplete", "off");
-		// only 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);
-		});
-		if ($(this).length && showAddButton) {
-			var addButton;
-			if ($(this).attr("tagName") == "TR") {
-				// If forms are laid out as table rows, insert the
-				// "add" button in a new table row:
-				var numCols = this.eq(0).children().length;
-				$(this).parent().append('<tr class="' + options.addCssClass + '"><td colspan="' + numCols + '"><a href="javascript:void(0)">' + options.addText + "</a></tr>");
-				addButton = $(this).parent().find("tr:last a");
-			} else {
-				// Otherwise, insert it immediately after the last form:
-				$(this).filter(":last").after('<div class="' + options.addCssClass + '"><a href="javascript:void(0)">' + options.addText + "</a></div>");
-				addButton = $(this).filter(":last").next().find("a");
-			}
-			addButton.click(function() {
-				var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS");
-				var template = $("#" + options.prefix + "-empty");
-				var row = template.clone(true);
-				row.removeClass(options.emptyCssClass)
-				    .addClass(options.formCssClass)
-				    .attr("id", options.prefix + "-" + nextIndex);
-				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="javascript:void(0)">' + 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="javascript:void(0)">' + 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="javascript:void(0)">' + 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()) + 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).click(function() {
-					// Remove the parent form containing this button:
-					var row = $(this).parents("." + options.formCssClass);
-					row.remove();
-					nextIndex -= 1;
-					// If a post-delete callback was provided, call it with the deleted form:
-					if (options.removed) {
-						options.removed(row);
-					}
-					// 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:
-					for (var i=0, formCount=forms.length; i<formCount; i++)
-					{
-						updateElementIndex($(forms).get(i), options.prefix, i);
-						$(forms.get(i)).find("*").each(function() {
-							updateElementIndex(this, options.prefix, i);
-						});
-					}
-                    $(this).trigger('formsetdelete', row);
-					return false;
-				});
-				// If a post-add callback was supplied, call it with the added form:
-				if (options.added) {
-					options.added(row);
-				}
-                $(this).trigger('formsetadd', row);
-				return false;
-			});
-		}
-		return this;
-	}
-	/* Setup plugin defaults */
-	$.fn.formset.defaults = {
-		prefix: "form",					// The form prefix for your django formset
-		addText: "add another",			// Text for the add link
-		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
-		emptyCssClass: "empty-row",		// CSS class applied to the empty row
-		formCssClass: "dynamic-form",	// CSS class applied to each form in a formset
-		added: null,					// Function called each time a new form is added
-		removed: null					// Function called each time a form is deleted
-	}
-})(django.jQuery);

File selectable/static/js/jquery.dj.selectable.js

View file
 
 if (typeof(django) != "undefined" && typeof(django.jQuery) != "undefined") {
     if (django.jQuery.fn.formset) {
-        django.jQuery('.add-row a').live('formsetadd', function(e, row) {
-            bindSelectables($(row));
-        });
+        var oldformset = django.jQuery.fn.formset;
+	    django.jQuery.fn.formset = function(opts) {
+            var options = $.extend({}, opts);
+            var addedevent = function(row) {
+                bindSelectables($(row));
+            };
+            var added = null;
+            if (options.added) {
+                var oldadded = options.added;
+                added = function(row) { oldadded(row); addedevent(row); };
+            }
+            options.added = added || addedevent;
+            return oldformset.call(this, options);
+        }
     }
 }