diff --git a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js index ffba7cdf24..4a577c4187 100644 --- a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js +++ b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js @@ -27,14 +27,16 @@ function windowname_to_id(text) { return text; } -function showAdminPopup(triggeringLink, name_regexp) { +function showAdminPopup(triggeringLink, name_regexp, add_popup) { var name = triggeringLink.id.replace(name_regexp, ''); name = id_to_windowname(name); var href = triggeringLink.href; - if (href.indexOf('?') == -1) { - href += '?_popup=1'; - } else { - href += '&_popup=1'; + if (add_popup) { + if (href.indexOf('?') == -1) { + href += '?_popup=1'; + } else { + href += '&_popup=1'; + } } var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); win.focus(); @@ -42,7 +44,7 @@ function showAdminPopup(triggeringLink, name_regexp) { } function showRelatedObjectLookupPopup(triggeringLink) { - return showAdminPopup(triggeringLink, /^lookup_/); + return showAdminPopup(triggeringLink, /^lookup_/, true); } function dismissRelatedLookupPopup(win, chosenId) { @@ -57,12 +59,22 @@ function dismissRelatedLookupPopup(win, chosenId) { } function showRelatedObjectPopup(triggeringLink) { - var name = triggeringLink.id.replace(/^(change|add|delete)_/, ''); - name = id_to_windowname(name); - var href = triggeringLink.href; - var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); - win.focus(); - return false; + return showAdminPopup(triggeringLink, /^(change|add|delete)_/, false); +} + +function updateRelatedObjectLinks(triggeringLink) { + var $this = django.jQuery(triggeringLink); + var siblings = $this.nextAll('.change-related, .delete-related'); + if (!siblings.length) return; + var value = $this.val(); + if (value) { + siblings.each(function() { + var elm = django.jQuery(this); + elm.attr('href', elm.attr('data-href-template').replace('__fk__', value)); + }); + } else { + siblings.removeAttr('href'); + } } function dismissAddRelatedObjectPopup(win, newId, newRepr) { @@ -72,13 +84,10 @@ function dismissAddRelatedObjectPopup(win, newId, newRepr) { newRepr = html_unescape(newRepr); var name = windowname_to_id(win.name); var elem = document.getElementById(name); - var o; if (elem) { var elemName = elem.nodeName.toUpperCase(); if (elemName == 'SELECT') { - o = new Option(newRepr, newId); - elem.options[elem.options.length] = o; - o.selected = true; + elem.options[elem.options.length] = new Option(newRepr, newId, true, true); } else if (elemName == 'INPUT') { if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) { elem.value += ',' + newId; @@ -90,7 +99,7 @@ function dismissAddRelatedObjectPopup(win, newId, newRepr) { django.jQuery(elem).trigger('change'); } else { var toId = name + "_to"; - o = new Option(newRepr, newId); + var o = new Option(newRepr, newId); SelectBox.add_to_cache(toId, o); SelectBox.redisplay(toId); } diff --git a/django/contrib/admin/static/admin/js/related-widget-wrapper.js b/django/contrib/admin/static/admin/js/related-widget-wrapper.js deleted file mode 100644 index dbb1f58c8c..0000000000 --- a/django/contrib/admin/static/admin/js/related-widget-wrapper.js +++ /dev/null @@ -1,23 +0,0 @@ -django.jQuery(function($){ - function updateLinks() { - var $this = $(this); - var siblings = $this.nextAll('.change-related, .delete-related'); - if (!siblings.length) return; - var value = $this.val(); - if (value) { - siblings.each(function(){ - var elm = $(this); - elm.attr('href', elm.attr('data-href-template').replace('__fk__', value)); - }); - } else siblings.removeAttr('href'); - } - var container = $(document); - container.on('change', '.related-widget-wrapper select', updateLinks); - container.find('.related-widget-wrapper select').each(updateLinks); - container.on('click', '.related-widget-wrapper-link', function(event){ - if (this.href) { - showRelatedObjectPopup(this); - } - event.preventDefault(); - }); -}); diff --git a/django/contrib/admin/templates/admin/change_form.html b/django/contrib/admin/templates/admin/change_form.html index 5e6c0c6321..0e2255f6ec 100644 --- a/django/contrib/admin/templates/admin/change_form.html +++ b/django/contrib/admin/templates/admin/change_form.html @@ -73,12 +73,39 @@ $(document).ready(function() { $('.add-another').click(function(e) { e.preventDefault(); - showAddAnotherPopup(this); + var event = $.Event('django:add-another-related'); + $(this).trigger(event); + if (!event.isDefaultPrevented()) { + showAddAnotherPopup(this); + } }); $('.related-lookup').click(function(e) { e.preventDefault(); - showRelatedObjectLookupPopup(this); + var event = $.Event('django:lookup-related'); + $(this).trigger(event); + if (!event.isDefaultPrevented()) { + showRelatedObjectLookupPopup(this); + } }); + $('body').on('click', '.related-widget-wrapper-link', function(e) { + e.preventDefault(); + if (this.href) { + var event = $.Event('django:show-related', {href: this.href}); + $(this).trigger(event); + if (!event.isDefaultPrevented()) { + showRelatedObjectPopup(this); + } + } + }); + $('body').on('change', '.related-widget-wrapper select', function(e) { + var event = $.Event('django:update-related'); + $(this).trigger(event); + if (!event.isDefaultPrevented()) { + updateRelatedObjectLinks(this); + } + }); + $('.related-widget-wrapper select').trigger('change'); + {% if adminform and add %} $('form#{{ opts.model_name }}_form :input:visible:enabled:first').focus() {% endif %} diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py index 2e88e930bd..251cc0ef1c 100644 --- a/django/contrib/admin/widgets.py +++ b/django/contrib/admin/widgets.py @@ -10,7 +10,7 @@ from django.contrib.admin.templatetags.admin_static import static from django.core.urlresolvers import reverse from django.db.models.deletion import CASCADE from django.forms.utils import flatatt -from django.forms.widgets import Media, RadioFieldRenderer +from django.forms.widgets import RadioFieldRenderer from django.template.loader import render_to_string from django.utils import six from django.utils.encoding import force_text @@ -272,8 +272,7 @@ class RelatedFieldWidgetWrapper(forms.Widget): @property def media(self): - media = Media(js=['admin/js/related-widget-wrapper.js']) - return self.widget.media + media + return self.widget.media def get_related_url(self, info, action, *args): return reverse("admin:%s_%s_%s" % (info + (action,)),