Source code for superdjango.forms.widgets
# Imports
from datetime import timedelta
from django import forms
from django.utils.translation import ugettext_lazy as _
from json import dumps as json_dumps
import os
from superdjango.assets import JavaScript, StyleSheet
# Exports
__all__ = (
"AjaxUploadWidget",
"ChooserWidget",
"CodeEditorWidget",
"ColorPickerWidget",
"MarkdownWidget",
"ReadOnlyWidget",
"SlugFromWidget",
)
# Widgets
[docs]class AjaxUploadWidget(forms.ClearableFileInput):
"""A file widget that provides support for AJAX uploads."""
[docs] def render(self, name, value, attrs=None, renderer=None):
"""Get the HTML that supports AJAX upload."""
if attrs is None:
attrs = dict()
# attrs['style'] = 'display: none;'
html = super().render(name, value, attrs=attrs, renderer=renderer)
context = {
'message': _("Please enable JavaScript to use the file uploader."),
'name': name,
}
html += '<div id="file-uploader-%(name)s"><noscript><p>%(message)s</p></noscript></div>' % context
# html += '<input type="hidden" name="%s" value="%s" id="file-uploader-%s-field">' % (
# name,
# value or "",
# name
# )
return html
[docs]class ChooserWidget(forms.Select):
"""A widget that may be used to transform a select into a chooser."""
pass
[docs]class CodeEditorWidget(forms.widgets.Textarea):
"""A widget for producing a code editor."""
template_name = "html/forms/widgets/code_editor.html"
[docs] def render(self, name, value, attrs=None, renderer=None):
"""Get the HTML for the code editor."""
context = self.get_context(name, value, attrs)
template = os.path.join("html", "forms", "widgets", "code_editor.html")
return self._render(template, context, renderer)
[docs]class ColorPickerWidget(forms.TextInput):
"""A widget that supports a color picker."""
@property
def media(self):
"""Return the form media for the color picker resource."""
return forms.Media(
css={
'all': [
"bundled/wcp/css/wheelcolorpicker.css",
]
},
js=[
"bundled/wcp/jquery.wheelcolorpicker.js",
"superdjango/ui/js/color_picker.js",
]
)
class HumanFriendlyDurationWidget(forms.TextInput):
"""Allows human-friendly durations."""
def format_value(self, value):
"""Format the value."""
tokens = list()
if value.days:
tokens.append("%sd" % value.days)
if value.hours:
tokens.append("%sh" % value.hours)
if value.minutes:
tokens.append("%sm" % value.minutes)
if value.seconds:
tokens.append("%ss" % value.seconds)
return " ".join(tokens)
@staticmethod
def to_python(value):
"""Convert the duration to Python timedelta."""
days = None
hours = None
minutes = None
seconds = None
tokens = value.split(" ")
for t in tokens:
t = t.strip()
if t.endswith("d"):
days = int(t.replace("d", "").strip())
elif t.endswith("h"):
hours = int(t.replace("h", "").strip())
elif t.endswith("m"):
minutes = int(t.replace("m", "").strip())
elif t.endswith("s"):
seconds = int(t.replace("s", "").strip())
else:
pass
return timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds)
[docs]class MarkdownWidget(forms.widgets.Textarea):
"""A widget for creating a Markdown editor.
Base on `SimpleMDE`_.
.. _SimpleMDE: https://github.com/sparksuite/simplemde-markdown-editor
"""
template_name = "html/forms/widgets/markdown.html"
[docs] def __init__(self, attrs=None, options=None):
"""Initialize the widget. The ``options`` parameter is for SimpleMDE options."""
super().__init__(attrs=attrs)
self._widget_options = options or dict()
# noinspection PyUnusedLocal
# @classmethod
# def get_css(cls, field_name=None):
# """Get the CSS for the editor. Works with SuperDjango UI.
#
# :param field_name: The name of the field. NOT USED, but included to maintain the standard signature.
# :type field_name: str
#
# :rtype: StyleSheet
#
# """
# css = StyleSheet()
#
# css.append("simplemde", url="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css")
#
# return css
#
# # noinspection PyUnusedLocal
# @classmethod
# def get_js(cls, field_name=None):
# """Get the JavaScript for the editor. Works with SuperDjango UI.
#
# :param field_name: The name of the field.
# :type field_name: str
#
# :rtype: JavaScript
#
# """
# js = JavaScript()
#
# js.append("simplemde", url="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js")
# js.append("simplemde-fields", url="superdjango/forms/js/simplemde.js")
#
# return js
@property
def media(self):
"""Support for standard Django implementation."""
return forms.Media(
css={
'all': [
"https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css",
]
},
js=[
"https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js",
"superdjango/forms/js/simplemde.js",
]
)
[docs] def render(self, name, value, attrs=None, renderer=None):
"""Add class and options to output."""
# markdown class now exists in the template.
# if "class" not in attrs:
# attrs['class'] = ""
#
# attrs['class'] += " markdown"
attrs['data-simplemde-options'] = json_dumps(self._widget_options)
# insert this style tag to fix the label from breaking into the toolbar
# html = super().render(name, value, attrs, renderer=renderer)
# html += "<style>.field-%s label { float: none; }</style>" % name
# return mark_safe(html)
context = self.get_context(name, value, attrs)
# template = os.path.join("html", "forms", "widgets", "markdown.html")
return self._render(self.template_name, context, renderer)
[docs]class ReadOnlyWidget(forms.widgets.Input):
"""Display only the value of the field."""
template_name = "html/forms/widgets/readonly.html"
[docs] def __init__(self, attrs=None):
"""Initialize with ``disabled`` as ``True``."""
if attrs is None:
attrs = {'disabled': True}
super().__init__(attrs=attrs)
[docs] def render(self, name, value, attrs=None, renderer=None):
"""Set the initial value."""
if hasattr(self, "initial"):
value = self.initial
return value
[docs]class SlugFromWidget(forms.widgets.TextInput):
"""Supports real-time slug generation from another field."""
template_name = "html/forms/widgets/slug.html"
[docs] def __init__(self, attrs=None, from_field="title"):
"""Initialize with ``data-from-field`` in attributes."""
self.from_field = from_field
_attrs = attrs or dict()
_attrs['data-from-field'] = from_field
super().__init__(attrs=_attrs)
@property
def media(self):
"""Get the form media for creating the slug in real-time."""
return forms.Media(
js=[
"superdjango/ui/js/slugify.js",
]
)