diff options
| -rw-r--r-- | django/contrib/admin/media/js/admin/DateTimeShortcuts.js | 12 | ||||
| -rw-r--r-- | django/contrib/admin/media/js/inlines.js | 41 | ||||
| -rw-r--r-- | django/contrib/admin/media/js/inlines.min.js | 11 | ||||
| -rw-r--r-- | django/contrib/admin/media/js/prepopulate.js | 34 | ||||
| -rw-r--r-- | django/contrib/admin/options.py | 2 | ||||
| -rw-r--r-- | django/contrib/admin/templates/admin/edit_inline/stacked.html | 12 | ||||
| -rw-r--r-- | django/contrib/admin/templates/admin/edit_inline/tabular.html | 12 | ||||
| -rw-r--r-- | django/contrib/admin/templates/admin/prepopulated_fields_js.html | 22 |
8 files changed, 123 insertions, 23 deletions
diff --git a/django/contrib/admin/media/js/admin/DateTimeShortcuts.js b/django/contrib/admin/media/js/admin/DateTimeShortcuts.js index fbaa599c7a..d840f78729 100644 --- a/django/contrib/admin/media/js/admin/DateTimeShortcuts.js +++ b/django/contrib/admin/media/js/admin/DateTimeShortcuts.js @@ -120,6 +120,7 @@ var DateTimeShortcuts = { }, handleClockQuicklink: function(num, val) { DateTimeShortcuts.clockInputs[num].value = val; + DateTimeShortcuts.clockInputs[num].focus(); DateTimeShortcuts.dismissClock(num); }, // Add calendar widget to a given field. @@ -247,12 +248,21 @@ var DateTimeShortcuts = { format = format.replace('\n', '\\n'); format = format.replace('\t', '\\t'); format = format.replace("'", "\\'"); - return "function(y, m, d) { DateTimeShortcuts.calendarInputs["+num+"].value = new Date(y, m-1, d).strftime('"+format+"');document.getElementById(DateTimeShortcuts.calendarDivName1+"+num+").style.display='none';}"; + return ["function(y, m, d) { DateTimeShortcuts.calendarInputs[", + num, + "].value = new Date(y, m-1, d).strftime('", + format, + "');DateTimeShortcuts.calendarInputs[", + num, + "].focus();document.getElementById(DateTimeShortcuts.calendarDivName1+", + num, + ").style.display='none';}"].join(''); }, handleCalendarQuickLink: function(num, offset) { var d = new Date(); d.setDate(d.getDate() + offset) DateTimeShortcuts.calendarInputs[num].value = d.strftime(get_format('DATE_INPUT_FORMATS')[0]); + DateTimeShortcuts.calendarInputs[num].focus(); DateTimeShortcuts.dismissCalendar(num); }, cancelEventPropagation: function(e) { diff --git a/django/contrib/admin/media/js/inlines.js b/django/contrib/admin/media/js/inlines.js index 55118dfc4b..9decaae444 100644 --- a/django/contrib/admin/media/js/inlines.js +++ b/django/contrib/admin/media/js/inlines.js @@ -55,24 +55,41 @@ var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS"); var nextIndex = parseInt(totalForms.val()); var template = $("#" + options.prefix + "-empty"); - var row = template.clone(true).get(0); - $(row).removeClass(options.emptyCssClass).removeAttr("id").insertBefore($(template)); - $(row).html($(row).html().replace(/__prefix__/g, nextIndex)); - $(row).addClass(options.formCssClass).attr("id", options.prefix + (nextIndex + 1)); - if ($(row).is("TR")) { + var row = template.clone(true); + row.removeClass(options.emptyCssClass) + .addClass(options.formCssClass) + .attr("id", options.prefix + nextIndex) + .insertBefore($(template)); + 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)); + }); + 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")) { + 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>"); + 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.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("input,select,textarea,label,a").each(function() { updateElementIndex(this, options.prefix, totalForms.val()); }); // Update number of total forms @@ -82,7 +99,7 @@ addButton.parent().hide(); } // The delete button of each row triggers a bunch of other things - $(row).find("a." + options.deleteCssClass).click(function() { + row.find("a." + options.deleteCssClass).click(function() { // Remove the parent form containing this button: var row = $(this).parents("." + options.formCssClass); row.remove(); @@ -109,7 +126,7 @@ }); // If a post-add callback was supplied, call it with the added form: if (options.added) { - options.added($(row)); + options.added(row); } return false; }); diff --git a/django/contrib/admin/media/js/inlines.min.js b/django/contrib/admin/media/js/inlines.min.js index 29e048df54..891cc3fca5 100644 --- a/django/contrib/admin/media/js/inlines.min.js +++ b/django/contrib/admin/media/js/inlines.min.js @@ -1,5 +1,6 @@ -(function(a){a.fn.formset=function(f){var b=a.extend({},a.fn.formset.defaults,f),l=function(d,e,j){var c=new RegExp("("+e+"-\\d+)");e=e+"-"+j;a(d).attr("for")&&a(d).attr("for",a(d).attr("for").replace(c,e));if(d.id)d.id=d.id.replace(c,e);if(d.name)d.name=d.name.replace(c,e)};f=a("#id_"+b.prefix+"-TOTAL_FORMS").attr("autocomplete","off");var h=a("#id_"+b.prefix+"-MAX_NUM_FORMS").attr("autocomplete","off");f=h.val()==""||h.val()-f.val()>0;a(this).each(function(){a(this).not("."+b.emptyCssClass).addClass(b.formCssClass)}); -if(a(this).length&&f){var i;if(a(this).attr("tagName")=="TR"){f=this.eq(0).children().length;a(this).parent().append('<tr class="'+b.addCssClass+'"><td colspan="'+f+'"><a href="javascript:void(0)">'+b.addText+"</a></tr>");i=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>");i=a(this).filter(":last").next().find("a")}i.click(function(){var d=a("#id_"+b.prefix+"-TOTAL_FORMS"),e=parseInt(d.val()), -j=a("#"+b.prefix+"-empty"),c=j.clone(true).get(0);a(c).removeClass(b.emptyCssClass).removeAttr("id").insertBefore(a(j));a(c).html(a(c).html().replace(/__prefix__/g,e));a(c).addClass(b.formCssClass).attr("id",b.prefix+(e+1));if(a(c).is("TR"))a(c).children(":last").append('<div><a class="'+b.deleteCssClass+'" href="javascript:void(0)">'+b.deleteText+"</a></div>");else a(c).is("UL")||a(c).is("OL")?a(c).append('<li><a class="'+b.deleteCssClass+'" href="javascript:void(0)">'+b.deleteText+"</a></li>"): -a(c).children(":first").append('<span><a class="'+b.deleteCssClass+'" href="javascript:void(0)">'+b.deleteText+"</a></span>");a(c).find("input,select,textarea,label,a").each(function(){l(this,b.prefix,d.val())});a(d).val(e+1);h.val()!=""&&h.val()<=d.val()&&i.parent().hide();a(c).find("a."+b.deleteCssClass).click(function(){var g=a(this).parents("."+b.formCssClass);g.remove();b.removed&&b.removed(g);g=a("."+b.formCssClass);a("#id_"+b.prefix+"-TOTAL_FORMS").val(g.length);if(h.val()==""||h.val()>=g.length)i.parent().show(); -for(var k=0,m=g.length;k<m;k++)a(g.get(k)).find("input,select,textarea,label,a").each(function(){l(this,b.prefix,k)});return false});b.added&&b.added(a(c));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}})(jQuery); +(function(a){a.fn.formset=function(g){var b=a.extend({},a.fn.formset.defaults,g),l=function(e,f,j){var d=new RegExp("("+f+"-\\d+)");f=f+"-"+j;a(e).attr("for")&&a(e).attr("for",a(e).attr("for").replace(d,f));if(e.id)e.id=e.id.replace(d,f);if(e.name)e.name=e.name.replace(d,f)};g=a("#id_"+b.prefix+"-TOTAL_FORMS").attr("autocomplete","off");var 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)}); +if(a(this).length&&g){var i;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>");i=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>");i=a(this).filter(":last").next().find("a")}i.click(function(){var e=a("#id_"+b.prefix+"-TOTAL_FORMS"),f=parseInt(e.val()), +j=a("#"+b.prefix+"-empty"),d=j.clone(true);d.removeClass(b.emptyCssClass).addClass(b.formCssClass).attr("id",b.prefix+f).insertBefore(a(j));d.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,f))}).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, +f))});if(d.is("tr"))d.children(":last").append('<div><a class="'+b.deleteCssClass+'" href="javascript:void(0)">'+b.deleteText+"</a></div>");else d.is("ul")||d.is("ol")?d.append('<li><a class="'+b.deleteCssClass+'" href="javascript:void(0)">'+b.deleteText+"</a></li>"):d.children(":first").append('<span><a class="'+b.deleteCssClass+'" href="javascript:void(0)">'+b.deleteText+"</a></span>");d.find("input,select,textarea,label,a").each(function(){l(this,b.prefix,e.val())});a(e).val(f+1);h.val()!=""&& +h.val()<=e.val()&&i.parent().hide();d.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)i.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.prefix,k)});return false});b.added&&b.added(d);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}})(jQuery); diff --git a/django/contrib/admin/media/js/prepopulate.js b/django/contrib/admin/media/js/prepopulate.js new file mode 100644 index 0000000000..27375d4cd2 --- /dev/null +++ b/django/contrib/admin/media/js/prepopulate.js @@ -0,0 +1,34 @@ +(function($) { + $.fn.prepopulate = function(dependencies, maxLength) { + /* + Depends on urlify.js + Populates a selected field with the values of the dependent fields, + URLifies and shortens the string. + dependencies - selected jQuery object of dependent fields + maxLength - maximum length of the URLify'd string + */ + return this.each(function() { + var field = $(this); + + field.data('_changed', false); + field.change(function() { + field.data('_changed', true); + }); + + var populate = function () { + // Bail if the fields value has changed + if (field.data('_changed') == true) return; + + var values = []; + dependencies.each(function() { + if ($(this).val().length > 0) { + values.push($(this).val()); + } + }); + field.val(URLify(values.join(' '), maxLength)); + }; + + dependencies.keyup(populate).change(populate).focus(populate); + }); + }; +})(jQuery.noConflict()); diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 6f66893c26..ae90bce067 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -274,6 +274,7 @@ class ModelAdmin(BaseModelAdmin): js.extend(['js/jquery.min.js', 'js/actions.min.js']) if self.prepopulated_fields: js.append('js/urlify.js') + js.append('js/prepopulate.js') if self.opts.get_ordered_objects(): js.extend(['js/getElementsBySelector.js', 'js/dom-drag.js' , 'js/admin/ordering.js']) @@ -1201,6 +1202,7 @@ class InlineModelAdmin(BaseModelAdmin): js = ['js/jquery.min.js', 'js/inlines.min.js'] if self.prepopulated_fields: js.append('js/urlify.js') + js.append('js/prepopulate.js') if self.filter_vertical or self.filter_horizontal: js.extend(['js/SelectBox.js' , 'js/SelectFilter2.js']) return forms.Media(js=['%s%s' % (settings.ADMIN_MEDIA_PREFIX, url) for url in js]) diff --git a/django/contrib/admin/templates/admin/edit_inline/stacked.html b/django/contrib/admin/templates/admin/edit_inline/stacked.html index fb112a0166..6eb4492e49 100644 --- a/django/contrib/admin/templates/admin/edit_inline/stacked.html +++ b/django/contrib/admin/templates/admin/edit_inline/stacked.html @@ -48,6 +48,17 @@ }) } } + var initPrepopulatedFields = function(row) { + row.find('.prepopulated_field').each(function() { + var field = $(this); + var input = field.find('input, select, textarea'); + var dependency_list = input.data('dependency_list') || []; + var dependencies = row.find(dependency_list.join(',')).find('input, select, textarea'); + if (dependencies.length) { + input.prepopulate(dependencies, input.attr('maxlength')); + } + }); + } $(rows).formset({ prefix: "{{ inline_admin_formset.formset.prefix }}", addText: "{% blocktrans with inline_admin_formset.opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}", @@ -57,6 +68,7 @@ emptyCssClass: "empty-form", removed: updateInlineLabel, added: (function(row) { + initPrepopulatedFields(row); reinitDateTimeShortCuts(); updateSelectFilter(); updateInlineLabel(row); diff --git a/django/contrib/admin/templates/admin/edit_inline/tabular.html b/django/contrib/admin/templates/admin/edit_inline/tabular.html index dc9552f454..48be38db5d 100644 --- a/django/contrib/admin/templates/admin/edit_inline/tabular.html +++ b/django/contrib/admin/templates/admin/edit_inline/tabular.html @@ -94,6 +94,17 @@ }) } } + var initPrepopulatedFields = function(row) { + row.find('.prepopulated_field').each(function() { + var field = $(this); + var input = field.find('input, select, textarea'); + var dependency_list = input.data('dependency_list') || []; + var dependencies = row.find(dependency_list.join(',')).find('input, select, textarea'); + if (dependencies.length) { + input.prepopulate(dependencies, input.attr('maxlength')); + } + }); + } $(rows).formset({ prefix: "{{ inline_admin_formset.formset.prefix }}", addText: "{% blocktrans with inline_admin_formset.opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}", @@ -103,6 +114,7 @@ emptyCssClass: "empty-form", removed: alternatingRows, added: (function(row) { + initPrepopulatedFields(row); reinitDateTimeShortCuts(); updateSelectFilter(); alternatingRows(row); diff --git a/django/contrib/admin/templates/admin/prepopulated_fields_js.html b/django/contrib/admin/templates/admin/prepopulated_fields_js.html index e1cdb9614e..f0eb471dfb 100644 --- a/django/contrib/admin/templates/admin/prepopulated_fields_js.html +++ b/django/contrib/admin/templates/admin/prepopulated_fields_js.html @@ -1,11 +1,23 @@ <script type="text/javascript"> +(function($) { + var field = null; + {% for field in prepopulated_fields %} - document.getElementById("{{ field.field.auto_id }}").onchange = function() { this._changed = true; }; + field = { + id: '#{{ field.field.auto_id }}', + dependency_ids: [], + dependency_list: [], + maxLength: {{ field.field.field.max_length|default_if_none:"50" }} + }; + {% for dependency in field.dependencies %} - document.getElementById("{{ dependency.auto_id }}").onkeyup = function() { - var e = document.getElementById("{{ field.field.auto_id }}"); - if (!e._changed) { e.value = URLify({% for innerdep in field.dependencies %}document.getElementById("{{ innerdep.auto_id }}").value{% if not forloop.last %} + ' ' + {% endif %}{% endfor %}, {{ field.field.field.max_length|default_if_none:"50" }}); } - } + field['dependency_ids'].push('#{{ dependency.auto_id }}'); + field['dependency_list'].push('.{{ dependency.name }}'); {% endfor %} + + $('.empty-form .{{ field.field.name }}').addClass('prepopulated_field'); + $(field.id).data('dependency_list', field['dependency_list']) + .prepopulate($(field['dependency_ids'].join(',')), field.maxLength); {% endfor %} +})(jQuery.noConflict()); </script> |
