Index: django/contrib/admin/media/js/admin/DateTimeShortcuts.js
===================================================================
--- django/contrib/admin/media/js/admin/DateTimeShortcuts.js (revision 12873)
+++ django/contrib/admin/media/js/admin/DateTimeShortcuts.js (working copy)
@@ -120,6 +120,7 @@
},
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 @@
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) {
Index: django/contrib/admin/media/js/prepopulate.js
===================================================================
--- django/contrib/admin/media/js/prepopulate.js (revision 0)
+++ django/contrib/admin/media/js/prepopulate.js (revision 0)
@@ -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());
Index: django/contrib/admin/media/js/inlines.js
===================================================================
--- django/contrib/admin/media/js/inlines.js (revision 12873)
+++ django/contrib/admin/media/js/inlines.js (working copy)
@@ -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('
");
- } else if ($(row).is("UL") || $(row).is("OL")) {
+ row.children(":last").append('");
+ } else if (row.is("ul") || row.is("ol")) {
// If they're laid out as an ordered/unordered list,
// insert an after the last list item:
- $(row).append('' + options.deleteText + "");
+ row.append('' + options.deleteText + "");
} else {
// Otherwise, just insert the remove button as the
// last child element of the form's container:
- $(row).children(":first").append('' + options.deleteText + "");
+ row.children(":first").append('' + options.deleteText + "");
}
- $(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;
});
Index: django/contrib/admin/options.py
===================================================================
--- django/contrib/admin/options.py (revision 12873)
+++ django/contrib/admin/options.py (working copy)
@@ -273,6 +273,7 @@
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'])
@@ -1197,9 +1198,10 @@
def _media(self):
from django.conf import settings
- js = ['js/jquery.min.js', 'js/inlines.min.js']
+ js = ['js/jquery.min.js', 'js/inlines.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])
Index: django/contrib/admin/templates/admin/edit_inline/stacked.html
===================================================================
--- django/contrib/admin/templates/admin/edit_inline/stacked.html (revision 12873)
+++ django/contrib/admin/templates/admin/edit_inline/stacked.html (working copy)
@@ -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);
Index: django/contrib/admin/templates/admin/edit_inline/tabular.html
===================================================================
--- django/contrib/admin/templates/admin/edit_inline/tabular.html (revision 12873)
+++ django/contrib/admin/templates/admin/edit_inline/tabular.html (working copy)
@@ -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);
Index: django/contrib/admin/templates/admin/prepopulated_fields_js.html
===================================================================
--- django/contrib/admin/templates/admin/prepopulated_fields_js.html (revision 12873)
+++ django/contrib/admin/templates/admin/prepopulated_fields_js.html (working copy)
@@ -1,11 +1,23 @@