wagtail/wagtail/wagtailadmin/widgets.py
Tim Heap 385564afe5 Refactor edit handler JavaScript integration
Edit handler panels which required JavaScript provided the JavaScript in
a `render_js` function, the output of which was collected together and
inserted after the `<script>` tags in the footer. Now that the
`<script>` tags are at the top of the `<body>`, these collected
initialisations were failing when they could not find the elements.

A new set of widgets have been created: `AdminPageChooser`,
`AdminImageChooser`, `AdminSnippetChooser`, `AdminDocumentChooser`.
These widgets output the initialisation JavaScript in a `<script>` tag
immediately following the widget itself, assuming that the required
external libraries and scripts are now included further up in the page.
This is how the GeoDjango fields from Django work, as well as many other
third party widgets. It makes writing integrations for arbitary widgets
easy, as they do not have to know anything about Wagtail edit handlers.

This also removes the need for the `fixPrefix()` JavaScript function
wrapping all field initialisers. As the fields are initialised as they
are inserted in to the page, any scripts included with them are inserted
at the same time. Additionally, the `__prefix__` placeholder in empty
form fields is also present in the initialisation scripts, and is fixed
at the same time. A template tag `escapescript` has been added to help
with this, to prevent `<script>` initialisation blocks from prematurely
closing the `<script type='text/django-form-template'>` tags.
2014-10-08 17:24:48 +11:00

55 lines
1.9 KiB
Python

from __future__ import absolute_import, unicode_literals
import json
from django.core.urlresolvers import reverse
from django.forms import widgets
from wagtail.utils.widgets import WidgetWithScript
from wagtail.wagtailcore.models import Page
from taggit.forms import TagWidget
class AdminDateInput(WidgetWithScript, widgets.DateInput):
def render_js_init(self, id_, name, value):
return 'initDateChooser({});'.format(json.dumps(id_))
class AdminTimeInput(WidgetWithScript, widgets.TimeInput):
def render_js_init(self, id_, name, value):
return 'initTimeChooser({});'.format(json.dumps(id_))
class AdminDateTimeInput(WidgetWithScript, widgets.DateTimeInput):
def render_js_init(self, id_, name, value):
return 'initDateTimeChooser({});'.format(json.dumps(id_))
class AdminTagWidget(WidgetWithScript, TagWidget):
def render_js_init(self, id_, name, value):
return "initTagField({0}, {1});".format(
json.dumps(id_),
json.dumps(reverse('wagtailadmin_tag_autocomplete')))
class AdminPageChooser(WidgetWithScript, widgets.Input):
input_type = 'hidden'
target_content_type = None
def __init__(self, content_type=None, **kwargs):
super(AdminPageChooser, self).__init__(**kwargs)
if content_type is not None:
self.target_content_type = content_type
def render_js_init(self, id_, name, value):
page = Page.objects.get(pk=value) if value else None
parent = page.get_parent() if page else None
content_type = self.target_content_type
return "createPageChooser({id}, {content_type}, {parent});".format(
id=json.dumps(id_),
content_type=json.dumps('{app}.{model}'.format(
app=content_type.app_label,
model=content_type.model)),
parent=json.dumps(parent.id if parent else None))