Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Imports
3from datetime import timedelta
4from django import forms
5from django.utils.translation import ugettext_lazy as _
6from json import dumps as json_dumps
7import os
8from superdjango.assets import JavaScript, StyleSheet
10# Exports
12__all__ = (
13 "AjaxUploadWidget",
14 "ChooserWidget",
15 "CodeEditorWidget",
16 "ColorPickerWidget",
17 "MarkdownWidget",
18 "ReadOnlyWidget",
19 "SlugFromWidget",
20)
22# Widgets
25class AjaxUploadWidget(forms.ClearableFileInput):
27 def render(self, name, value, attrs=None, renderer=None):
28 if attrs is None:
29 attrs = dict()
31 # attrs['style'] = 'display: none;'
32 html = super().render(name, value, attrs=attrs, renderer=renderer)
34 context = {
35 'message': _("Please enable JavaScript to use the file uploader."),
36 'name': name,
37 }
38 html += '<div id="file-uploader-%(name)s"><noscript><p>%(message)s</p></noscript></div>' % context
39 # html += '<input type="hidden" name="%s" value="%s" id="file-uploader-%s-field">' % (
40 # name,
41 # value or "",
42 # name
43 # )
44 return html
47class ChooserWidget(forms.Select):
48 pass
51class CodeEditorWidget(forms.widgets.Textarea):
52 template_name = "html/forms/widgets/code_editor.html"
54 def render(self, name, value, attrs=None, renderer=None):
55 context = self.get_context(name, value, attrs)
56 template = os.path.join("html", "forms", "widgets", "code_editor.html")
58 return self._render(template, context, renderer)
61class ColorPickerWidget(forms.TextInput):
63 @property
64 def media(self):
65 return forms.Media(
66 css={
67 'all': [
68 "bundled/wcp/css/wheelcolorpicker.css",
69 ]
70 },
71 js=[
72 "bundled/wcp/jquery.wheelcolorpicker.js",
73 "superdjango/ui/js/color_picker.js",
74 ]
75 )
78class HumanFriendlyDurationWidget(forms.TextInput):
79 """Allows human-friendly durations."""
81 def format_value(self, value):
82 tokens = list()
83 if value.days:
84 tokens.append("%sd" % value.days)
86 if value.hours:
87 tokens.append("%sh" % value.hours)
89 if value.minutes:
90 tokens.append("%sm" % value.minutes)
92 if value.seconds:
93 tokens.append("%ss" % value.seconds)
95 return " ".join(tokens)
97 @staticmethod
98 def to_python(value):
99 days = None
100 hours = None
101 minutes = None
102 seconds = None
104 tokens = value.split(" ")
105 for t in tokens:
106 t = t.strip()
107 if t.endswith("d"):
108 days = int(t.replace("d", "").strip())
109 elif t.endswith("h"):
110 hours = int(t.replace("h", "").strip())
111 elif t.endswith("m"):
112 minutes = int(t.replace("m", "").strip())
113 elif t.endswith("s"):
114 seconds = int(t.replace("s", "").strip())
115 else:
116 pass
118 return timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds)
121class MarkdownWidget(forms.widgets.Textarea):
122 """A widget for creating a Markdown editor.
124 Base on `SimpleMDE`_.
126 .. _SimpleMDE: https://github.com/sparksuite/simplemde-markdown-editor
128 """
130 template_name = "html/forms/widgets/markdown.html"
132 def __init__(self, attrs=None, options=None):
133 """Initialize the widget. The ``options`` parameter is for SimpleMDE options."""
134 super().__init__(attrs=attrs)
136 self._widget_options = options or dict()
138 # noinspection PyUnusedLocal
139 # @classmethod
140 # def get_css(cls, field_name=None):
141 # """Get the CSS for the editor. Works with SuperDjango UI.
142 #
143 # :param field_name: The name of the field. NOT USED, but included to maintain the standard signature.
144 # :type field_name: str
145 #
146 # :rtype: StyleSheet
147 #
148 # """
149 # css = StyleSheet()
150 #
151 # css.append("simplemde", url="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css")
152 #
153 # return css
154 #
155 # # noinspection PyUnusedLocal
156 # @classmethod
157 # def get_js(cls, field_name=None):
158 # """Get the JavaScript for the editor. Works with SuperDjango UI.
159 #
160 # :param field_name: The name of the field.
161 # :type field_name: str
162 #
163 # :rtype: JavaScript
164 #
165 # """
166 # js = JavaScript()
167 #
168 # js.append("simplemde", url="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js")
169 # js.append("simplemde-fields", url="superdjango/forms/js/simplemde.js")
170 #
171 # return js
173 @property
174 def media(self):
175 """Support for standard Django implementation."""
176 return forms.Media(
177 css={
178 'all': [
179 "https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css",
180 ]
181 },
182 js=[
183 "https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js",
184 "superdjango/forms/js/simplemde.js",
185 ]
186 )
188 def render(self, name, value, attrs=None, renderer=None):
189 """Add class and options to output."""
190 # markdown class now exists in the template.
191 # if "class" not in attrs:
192 # attrs['class'] = ""
193 #
194 # attrs['class'] += " markdown"
196 attrs['data-simplemde-options'] = json_dumps(self._widget_options)
198 # insert this style tag to fix the label from breaking into the toolbar
199 # html = super().render(name, value, attrs, renderer=renderer)
200 # html += "<style>.field-%s label { float: none; }</style>" % name
201 # return mark_safe(html)
203 context = self.get_context(name, value, attrs)
204 # template = os.path.join("html", "forms", "widgets", "markdown.html")
206 return self._render(self.template_name, context, renderer)
209class ReadOnlyWidget(forms.widgets.Input):
210 """Display only the value of the field."""
212 template_name = "html/forms/widgets/readonly.html"
214 def __init__(self, attrs=None):
215 if attrs is None:
216 attrs = {'disabled': True}
218 super().__init__(attrs=attrs)
220 def render(self, name, value, attrs=None, renderer=None):
221 if hasattr(self, "initial"):
222 value = self.initial
224 return value
227class SlugFromWidget(forms.widgets.TextInput):
228 """Supports real-time slug generation from another field."""
230 template_name = "html/forms/widgets/slug.html"
232 def __init__(self, attrs=None, from_field="title"):
233 self.from_field = from_field
235 _attrs = attrs or dict()
236 _attrs['data-from-field'] = from_field
238 super().__init__(attrs=_attrs)
240 @property
241 def media(self):
242 return forms.Media(
243 js=[
244 "superdjango/ui/js/slugify.js",
245 ]
246 )