diff --git a/.eslintrc b/.eslintrc index ec705d2257..cfe7f53010 100644 --- a/.eslintrc +++ b/.eslintrc @@ -14,7 +14,7 @@ "no-octal-escape": [2], "no-underscore-dangle": [2], "no-unused-vars": [2, {"vars": "local", "args": "none"}], - "no-script-url": [1], + "no-script-url": [2], "no-shadow": [2, {"hoist": "functions"}], "quotes": [0, "single"], "linebreak-style": [2, "unix"], diff --git a/django/contrib/admin/actions.py b/django/contrib/admin/actions.py index c4cccfd990..80b0ac83d6 100644 --- a/django/contrib/admin/actions.py +++ b/django/contrib/admin/actions.py @@ -74,6 +74,7 @@ def delete_selected(modeladmin, request, queryset): protected=protected, opts=opts, action_checkbox_name=helpers.ACTION_CHECKBOX_NAME, + media=modeladmin.media, ) request.current_app = modeladmin.admin_site.name diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py index 2c712f6e93..775fb1b5d3 100644 --- a/django/contrib/admin/helpers.py +++ b/django/contrib/admin/helpers.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals +import json import warnings from django import forms @@ -18,7 +19,7 @@ from django.utils.deprecation import RemovedInDjango20Warning from django.utils.encoding import force_text, smart_text from django.utils.html import conditional_escape, format_html from django.utils.safestring import mark_safe -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import ugettext, ugettext_lazy as _ ACTION_CHECKBOX_NAME = '_selected_action' @@ -276,6 +277,19 @@ class InlineAdminFormSet(object): 'help_text': form_field.help_text, } + def inline_formset_data(self): + verbose_name = self.opts.verbose_name + return json.dumps({ + 'name': '#%s' % self.formset.prefix, + 'options': { + 'prefix': self.formset.prefix, + 'addText': ugettext('Add another %(verbose_name)s') % { + 'verbose_name': capfirst(verbose_name), + }, + 'deleteText': ugettext('Remove'), + } + }) + def _media(self): media = self.opts.media + self.formset.media for fs in self: diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index f6ed33b5ee..24d698f540 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals import copy +import json import operator from collections import OrderedDict from functools import partial, reduce, update_wrapper @@ -40,7 +41,7 @@ from django.template.response import SimpleTemplateResponse, TemplateResponse from django.utils import six from django.utils.decorators import method_decorator from django.utils.encoding import force_text, python_2_unicode_compatible -from django.utils.html import escape, escapejs, format_html +from django.utils.html import escape, format_html from django.utils.http import urlencode, urlquote from django.utils.safestring import mark_safe from django.utils.text import capfirst, get_text_list @@ -568,9 +569,9 @@ class ModelAdmin(BaseModelAdmin): extra = '' if settings.DEBUG else '.min' js = [ 'core.js', - 'admin/RelatedObjectLookups.js', 'vendor/jquery/jquery%s.js' % extra, 'jquery.init.js', + 'admin/RelatedObjectLookups.js', 'actions%s.js' % extra, 'urlify.js', 'prepopulate%s.js' % extra, @@ -1084,9 +1085,12 @@ class ModelAdmin(BaseModelAdmin): else: attr = obj._meta.pk.attname value = obj.serializable_value(attr) - return SimpleTemplateResponse('admin/popup_response.html', { + popup_response_data = json.dumps({ 'value': value, - 'obj': obj, + 'obj': six.text_type(obj), + }) + return SimpleTemplateResponse('admin/popup_response.html', { + 'popup_response_data': popup_response_data, }) elif "_continue" in request.POST: @@ -1132,11 +1136,14 @@ class ModelAdmin(BaseModelAdmin): # Retrieve the `object_id` from the resolved pattern arguments. value = request.resolver_match.args[0] new_value = obj.serializable_value(attr) - return SimpleTemplateResponse('admin/popup_response.html', { + popup_response_data = json.dumps({ 'action': 'change', - 'value': escape(value), - 'obj': escapejs(obj), - 'new_value': escape(new_value), + 'value': value, + 'obj': six.text_type(obj), + 'new_value': new_value, + }) + return SimpleTemplateResponse('admin/popup_response.html', { + 'popup_response_data': popup_response_data, }) opts = self.model._meta @@ -1300,9 +1307,12 @@ class ModelAdmin(BaseModelAdmin): opts = self.model._meta if IS_POPUP_VAR in request.POST: - return SimpleTemplateResponse('admin/popup_response.html', { + popup_response_data = json.dumps({ 'action': 'delete', - 'value': escape(obj_id), + 'value': obj_id, + }) + return SimpleTemplateResponse('admin/popup_response.html', { + 'popup_response_data': popup_response_data, }) self.message_user(request, @@ -1332,6 +1342,7 @@ class ModelAdmin(BaseModelAdmin): context.update( to_field_var=TO_FIELD_VAR, is_popup_var=IS_POPUP_VAR, + media=self.media, ) return TemplateResponse(request, diff --git a/django/contrib/admin/static/admin/js/SelectFilter2.js b/django/contrib/admin/static/admin/js/SelectFilter2.js index acf3996c38..e73f8a50ff 100644 --- a/django/contrib/admin/static/admin/js/SelectFilter2.js +++ b/django/contrib/admin/static/admin/js/SelectFilter2.js @@ -75,15 +75,15 @@ Requires core.js, SelectBox.js and addevent.js. filter_input.id = field_id + '_input'; selector_available.appendChild(from_box); - var choose_all = quickElement('a', selector_available, gettext('Choose all'), 'title', interpolate(gettext('Click to choose all %s at once.'), [field_name]), 'href', 'javascript:void(0);', 'id', field_id + '_add_all_link'); + var choose_all = quickElement('a', selector_available, gettext('Choose all'), 'title', interpolate(gettext('Click to choose all %s at once.'), [field_name]), 'href', '#', 'id', field_id + '_add_all_link'); choose_all.className = 'selector-chooseall'; //