#16630 closed New feature (fixed)
Support for HTML5 input types
Reported by: | Jonas H. | Owned by: | Claude Paroz |
---|---|---|---|
Component: | Forms | Version: | dev |
Severity: | Normal | Keywords: | html5 |
Cc: | riccardo.magliocchetti@…, tgecho, Paul Oswald, dharris+django@…, Danilo Bargen, buggystick, philipe.rp@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I attached a patch that adds support for HTML5 input types (URL, e-mail, number).
New widgets:
IntegerInput
-- HTML5type="number"
URLInput
-- HTML5type="url"
EmailInput
-- HTML5type="email"
Changes to fields:
EmailField
: UsesEmailInput
URLField
: UsesURLInput
IntegerField
: UsesIntegerInput
, adds themax="..."
andmin="..."
HTML5attrs
ifmax_value
/min_value
are specifiedFloatField
: inherits behaviour fromIntegerField
and addsstep="any"
DecimalFields
: Now based onIntegerField
because they share code; alsomaxlength="..."
andstep="..."
are set accordingly
The second patch that is attached adapts the tests accordingly. (Some HTML attribute reordering was neccessary because of Python's dict ordering behaviour.)
Attachments (9)
Change History (55)
by , 13 years ago
Attachment: | html5-input-types-take1.patch added |
---|
by , 13 years ago
Attachment: | html5-input-types-tests-take1.patch added |
---|
comment:1 by , 13 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 13 years ago
Yep should be backwards compatible because of HTML5's strong backwards compatibility. Of course I can't guarantee anything; I'll do some IE testing though.
comment:3 by , 13 years ago
Input types unknown to browsers (including IE7 and IE8 which I just tested) are interpreted as type="text"
so this is backwards compatible as far as browsers are concerned.
comment:5 by , 13 years ago
comment:6 by , 13 years ago
Cc: | added |
---|
comment:7 by , 13 years ago
Cc: | added |
---|
Is there anything I can do to help this move forward? The patches doesn't seem to apply cleanly any more... would it be worthwhile for me to take a stab at fixing them up? Document the changes?
comment:9 by , 13 years ago
jonash, bumping a ticket without adding extra information isn't going to make it go faster :-)
If you think you've already answered all the questions/remarks mentioned here so far, you think the patch is ready, and you'd like to receive more feedback, then please take it to the mailing list or to #django-dev.
comment:10 by , 13 years ago
Needs documentation: | set |
---|
comment:11 by , 13 years ago
Paul Oswald raised some concerns about backwards-compatibility when localization is active (copy/paste from django-developers):
I have a concern regarding this.. A few times I have tried to
integrate django-floppyforms which takes a similar approach to what
the html5 widgets offer (input types are specified by default) and it
often causes pain. The reason is that while browsers say they support
html5 input types sometimes that support is lacking or very badly
implemented. As an example, if you say <input type="date"
value="2011-12-28"> the only officially supported date format is an
RFC-3339 'full-date' format (YYYY-MM-DD) according to the spec:
http://dev.w3.org/html5/markup/input.date.html#input.date.attrs.value
http://tools.ietf.org/html/rfc3339
This means that you cannot have any other format of date string in
that form field.
Now, this ticket 16630 doesn't change the date field specifically but
it does change the number field. (Is there a similar ticket for
changing the date field?) I've run into a similar problem with the
type='number' that this ticket does change. The problem I ran into was
that forms cannot easily use the THOUSANDS_SEPARATOR because it is not
a valid number. It has to be a 'float' to be valid. This means
technically you need to use the text widget for that.
http://dev.w3.org/html5/markup/datatypes.html#common.data.float
So by my thinking this patch (and by extension the thinking of
browsers and the w3) is non-backwards compatible with the way that
django formats numbers when USE_THOUSANDS_SEPARATOR is True or when
localization is turned on.
https://docs.djangoproject.com/en/dev/ref/settings/#use-thousand-separator
Maybe there is something I'm missing here? I just want to flag this as
a concern and make sure that developers know what they are getting
into by enabling that. I would be for this being the default if it
could be disabled. That way, I can use modernizr.js and turn only
certain marked fields into type="number" or type="date". At the
minimum, we would need to document that the default behavior is
changing.
comment:12 by , 13 years ago
Cc: | added |
---|
I have found that wether or not a developer will want the html5 input type="date" or type="number" feature on a given form input depends on several things:
- the type of the data
- the usage of the data (for example an id number might never be humanized with commas whereas an amount will be)
- if the data needs to be localized in a way not allowed by the html5 spec
- the capabilities of the user's browser's built-in widgets (iPad and iPod give input type="number" nice numeric keyboards)
- if the user's browser's built-in widgets are 'better' than a javascript polyfill widget (type='date' in Safari is currently a simple up/down arrow, hardly enough for most uses)
Because the last two of these need to be determined on a per-user or per-request basis the only real solution that solves all of these is a client-side Javascript library. Unfortunately, the last one even rules out a tool like Modernizr since it reports support even when the support is terrible. That being said, some widgets (like input type='search' ) are clear wins today. For some developers, the above won't be issues and they will want html5 input type support right away.
If you're going to try to tackle it server-side, the absolutely ideal situation would be a way to allow the developer to switch date and number types on and off on a per-request basis. Second best would be switching them on and off on a per-widget basis which is what you have in this patch. For those troublesome types, the default just needs to be off with a way to switch them on for select data. Perhaps the best approach is to allow the form to pass in the type to override the default of 'text'? Something like this:
class MyForm(forms.ModelForm): date = forms.DateField(label=_('Date'), type='date') num = forms.IntegerField(label=_('Number'), type='number')
This way, when browsers get better support for these data types, it is a simple matter of changing the default but developers can still manually override defaults.
comment:13 by , 13 years ago
How about adding a input_type
parameter to class Input(Widget)
so that you can override the input type if it doesn't fit your needs?
class MyForm(forms.ModelForm): class Meta: ... # Use "type=date" despite the pathetic browser support: widgets = {'date': forms.Input(input_type='date')}
comment:15 by , 13 years ago
Cc: | added |
---|
comment:16 by , 12 years ago
Cc: | added |
---|
comment:17 by , 12 years ago
I think that a way to go forward on this ticket would be first to factor out the new input_type parameter (code/test/docs). One question that comes to mind is if the input_type should be set on Input (then it should also be supported on Input subclasses) or on TextInput.
comment:18 by , 12 years ago
Cc: | added |
---|
follow-up: 21 comment:19 by , 12 years ago
Following my comment:17, I've factored out the input_type customizability of TextInput-based widgets from the existing patches, with tests and docs.
comment:20 by , 12 years ago
I think we should really default to type="number"
and type="email"
for number and email fields, respectively. It's much easier to type on mobile devices and doesn't really hurt in other browsers.
The main issue with date and floating point input is that it's not properly localized in most browsers. That doesn't apply to integers and emails, though.
comment:21 by , 12 years ago
Replying to claudep:
Following my comment:17, I've factored out the input_type customizability of TextInput-based widgets from the existing patches, with tests and docs.
... and then I realized it's already possible to customize the type attribute using the attr dict, without requiring to a new input_type parameter. I may commit some test adjustments soon, then we can polish the latest patches from jonash.
comment:23 by , 12 years ago
Needs documentation: | unset |
---|
After my previous commit, I updated the patch from jonash and added minimal documentation. I renamed IntegerInput to NumberInput. Final reviews welcome.
comment:24 by , 12 years ago
That would be hugely backwards incompatible, right? I'm -1 on this and support #15667 instead.
Also just for the record, the DecimalField in the latest patch uses manual format localization instead of the system in django.utils.formats.
comment:25 by , 12 years ago
Backwards incompatible in what way?
I don't think #15667 and this ticket are mutually exclusive. Plus I think it doesn't make sense to postpone features that *might* be superseded by another feature in remote future...
comment:26 by , 12 years ago
This is not backwards-incompatible in any way that I can see. As was previously mentioned, old browsers will interpret these HTML5 types as text fields. As for localization - the HTML inputs will no longer accept values that use THOUSANDS_SEPARATOR on the client side. As far as I know, that's not a backwards-compatibility issue; users will get a clear error message and be able to fix the issue without submitting the form. And on the python side, if THOUSANDS-separated text *does* get through (for example from an old browser) it will still be handled correctly.
Also this doesn't seem mutually exclusive with #15667, but it does seem more likely to be finished soon.
comment:27 by , 12 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Tests pass, docs look good to me, marking RFC.
comment:28 by , 12 years ago
Triage Stage: | Ready for checkin → Accepted |
---|
AFAIK, the compatibility issues are for CSS and JS:
input[type="text"]
CSS selector will suddenly not apply any more for the new types (url, email, number).- If you access an input in Javascript based on the type property, e.g.
if (form.elements[0].type=='text') { ... }
, your script might be broken.
My personal view is that these incompatibilities are not so serious (mainly visual for CSS and in JS, it is not so frequent to test on input types), but you need to convince other core developers, too.
comment:30 by , 12 years ago
Triage Stage: | Accepted → Design decision needed |
---|
comment:31 by , 12 years ago
Cc: | added |
---|
comment:32 by , 12 years ago
Triage Stage: | Design decision needed → Accepted |
---|
IMO this is a change we simply need to make at some point in order to stay up to date, and waiting won't make the (minor) CSS/JS backwards-incompatibilities any less incompatible. We could do something more complex like a settings-flag to enable the change, but I really don't think the compatibility issues are worth that; we've never made any backwards-compatibility promises regarding form HTML output.
#15667 is not really relevant, as it's not clear if that can even happen, due to performance issues with the template engine. And in any case, this doesn't prevent that. So I think we should just go ahead and do this. Though we definitely do need to note the output changes in the "backwards incompatibilities" section of the release notes, so the patch is still lacking that.
comment:33 by , 12 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
Thanks Carl for your input. I'll take care of the commit.
comment:34 by , 12 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Latest version of the patch: https://github.com/django/django/pull/679
comment:35 by , 12 years ago
Triage Stage: | Ready for checkin → Accepted |
---|
The patch should take into account localized fields.
i.e. To keep the fix simple, localized IntegerField
, FloatField
and DecimalField
should be rendered as text inputs with no additional attributes.
We could add pattern and maxlength generation based on the locale's settings latter on.
comment:36 by , 12 years ago
Simon, you pointed out a valid issue on the pull request with maxlength
on DecimalField
. But maxlength
is not used on IntegerField
and FloatField
, so I don't see how localization affects those fields in this patch. Could you elaborate?
comment:37 by , 12 years ago
Say you have a localized IntegerField(initial=1000)
with NUMBER_GROUPING = ' '
then it would be rendered as <input type="number" value="1 000" />
which is an invalid value for such HTML input type. Take a look at this fiddle in chrome, the value is totally stripped.
I'll add additional notes on the PR.
comment:38 by , 12 years ago
I've split the pull request in three parts: EmailInput
, URLInput
and NumberInput
. If first two are undisputed, we could commit this part and concentrate on the localization issue of NumberInput
.
comment:41 by , 12 years ago
The number input implementation seems to be a bit unstable at the moment.
Chrome implemented it quickly and attempted to localize the input value to the useragent's locale while submitting it the document (or closest parent with a lang attribute) locale. It raised some issues and it's quite hard to work with.
Firefox halted development because many questions arose concerning the decimal mark, group size and separator.
comment:42 by , 12 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
I'm closing this ticket in favour of #19686 which will discuss the specific issue of number input type. Thanks for all involved contributors until now!
comment:47 by , 11 years ago
I don't think so. Specialized input types should be left to third-party apps.
comment:48 by , 5 months ago
Tickets #35598, #35599, #35600 and #35601 were raised for other HTML5 input types. Forum discussion.
This is a consistent subset of #15924 which was closed because it was too broad.
The backwards compatibility concerns expressed over there still apply. Is it guaranteed that this won't cause regressions in supported browsers (especially IE >=7) ?