build
[semainetech_django.git] / project / media / django / js / inlines.js
1 /**
2 * Django admin inlines
3 *
4 * Based on jQuery Formset 1.1
5 * @author Stanislaus Madueke (stan DOT madueke AT gmail DOT com)
6 * @requires jQuery 1.2.6 or later
7 *
8 * Copyright (c) 2009, Stanislaus Madueke
9 * All rights reserved.
10 *
11 * Spiced up with Code from Zain Memon's GSoC project 2009
12 * and modified for Django by Jannis Leidel
13 *
14 * Licensed under the New BSD License
15 * See: http://www.opensource.org/licenses/bsd-license.php
16 */
17 (function($) {
18 $.fn.formset = function(opts) {
19 var options = $.extend({}, $.fn.formset.defaults, opts);
20 var updateElementIndex = function(el, prefix, ndx) {
21 var id_regex = new RegExp("(" + prefix + "-\\d+)");
22 var replacement = prefix + "-" + ndx;
23 if ($(el).attr("for")) {
24 $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
25 }
26 if (el.id) {
27 el.id = el.id.replace(id_regex, replacement);
28 }
29 if (el.name) {
30 el.name = el.name.replace(id_regex, replacement);
31 }
32 };
33 var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").attr("autocomplete", "off");
34 var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").attr("autocomplete", "off");
35 // only show the add button if we are allowed to add more items,
36 // note that max_num = None translates to a blank string.
37 var showAddButton = maxForms.val() == '' || (maxForms.val()-totalForms.val()) > 0;
38 $(this).each(function(i) {
39 $(this).not("." + options.emptyCssClass).addClass(options.formCssClass);
40 });
41 if ($(this).length && showAddButton) {
42 var addButton;
43 if ($(this).attr("tagName") == "TR") {
44 // If forms are laid out as table rows, insert the
45 // "add" button in a new table row:
46 var numCols = this.eq(0).children().length;
47 $(this).parent().append('<tr class="' + options.addCssClass + '"><td colspan="' + numCols + '"><a href="javascript:void(0)">' + options.addText + "</a></tr>");
48 addButton = $(this).parent().find("tr:last a");
49 } else {
50 // Otherwise, insert it immediately after the last form:
51 $(this).filter(":last").after('<div class="' + options.addCssClass + '"><a href="javascript:void(0)">' + options.addText + "</a></div>");
52 addButton = $(this).filter(":last").next().find("a");
53 }
54 addButton.click(function() {
55 var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS");
56 var nextIndex = parseInt(totalForms.val());
57 var template = $("#" + options.prefix + "-empty");
58 var row = template.clone(true);
59 row.removeClass(options.emptyCssClass)
60 .addClass(options.formCssClass)
61 .attr("id", options.prefix + "-" + nextIndex)
62 .insertBefore($(template));
63 row.find("*")
64 .filter(function() {
65 var el = $(this);
66 return el.attr("id") && el.attr("id").search(/__prefix__/) >= 0;
67 }).each(function() {
68 var el = $(this);
69 el.attr("id", el.attr("id").replace(/__prefix__/g, nextIndex));
70 })
71 .end()
72 .filter(function() {
73 var el = $(this);
74 return el.attr("name") && el.attr("name").search(/__prefix__/) >= 0;
75 }).each(function() {
76 var el = $(this);
77 el.attr("name", el.attr("name").replace(/__prefix__/g, nextIndex));
78 });
79 if (row.is("tr")) {
80 // If the forms are laid out in table rows, insert
81 // the remove button into the last table cell:
82 row.children(":last").append('<div><a class="' + options.deleteCssClass +'" href="javascript:void(0)">' + options.deleteText + "</a></div>");
83 } else if (row.is("ul") || row.is("ol")) {
84 // If they're laid out as an ordered/unordered list,
85 // insert an <li> after the last list item:
86 row.append('<li><a class="' + options.deleteCssClass +'" href="javascript:void(0)">' + options.deleteText + "</a></li>");
87 } else {
88 // Otherwise, just insert the remove button as the
89 // last child element of the form's container:
90 row.children(":first").append('<span><a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + options.deleteText + "</a></span>");
91 }
92 row.find("input,select,textarea,label,a").each(function() {
93 updateElementIndex(this, options.prefix, totalForms.val());
94 });
95 // Update number of total forms
96 $(totalForms).val(nextIndex + 1);
97 // Hide add button in case we've hit the max, except we want to add infinitely
98 if ((maxForms.val() != '') && (maxForms.val()-totalForms.val()) <= 0) {
99 addButton.parent().hide();
100 }
101 // The delete button of each row triggers a bunch of other things
102 row.find("a." + options.deleteCssClass).click(function() {
103 // Remove the parent form containing this button:
104 var row = $(this).parents("." + options.formCssClass);
105 row.remove();
106 // If a post-delete callback was provided, call it with the deleted form:
107 if (options.removed) {
108 options.removed(row);
109 }
110 // Update the TOTAL_FORMS form count.
111 var forms = $("." + options.formCssClass);
112 $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length);
113 // Show add button again once we drop below max
114 if ((maxForms.val() == '') || (maxForms.val()-forms.length) > 0) {
115 addButton.parent().show();
116 }
117 // Also, update names and ids for all remaining form controls
118 // so they remain in sequence:
119 for (var i=0, formCount=forms.length; i<formCount; i++)
120 {
121 $(forms.get(i)).find("input,select,textarea,label,a").each(function() {
122 updateElementIndex(this, options.prefix, i);
123 });
124 }
125 return false;
126 });
127 // If a post-add callback was supplied, call it with the added form:
128 if (options.added) {
129 options.added(row);
130 }
131 return false;
132 });
133 }
134 return this;
135 }
136 /* Setup plugin defaults */
137 $.fn.formset.defaults = {
138 prefix: "form", // The form prefix for your django formset
139 addText: "add another", // Text for the add link
140 deleteText: "remove", // Text for the delete link
141 addCssClass: "add-row", // CSS class applied to the add link
142 deleteCssClass: "delete-row", // CSS class applied to the delete link
143 emptyCssClass: "empty-row", // CSS class applied to the empty row
144 formCssClass: "dynamic-form", // CSS class applied to each form in a formset
145 added: null, // Function called each time a new form is added
146 removed: null // Function called each time a form is deleted
147 }
148 })(django.jQuery);