Opened 13 years ago

Closed 12 years ago

Last modified 4 months ago

#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 -- HTML5 type="number"
  • URLInput -- HTML5 type="url"
  • EmailInput -- HTML5 type="email"

Changes to fields:

  • EmailField: Uses EmailInput
  • URLField: Uses URLInput
  • IntegerField: Uses IntegerInput, adds the max="..." and min="..." HTML5 attrs if max_value/min_value are specified
  • FloatField: inherits behaviour from IntegerField and adds step="any"
  • DecimalFields: Now based on IntegerField because they share code; also maxlength="..." and step="..." 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)

html5-input-types-take1.patch (7.2 KB ) - added by Jonas H. 13 years ago.
html5-input-types-tests-take1.patch (40.9 KB ) - added by Jonas H. 13 years ago.
html5-input-types-take2.patch (7.8 KB ) - added by Jonas H. 13 years ago.
against [17281]
html5-input-types-tests-take2.patch (40.0 KB ) - added by Jonas H. 13 years ago.
against [17821]
html5-input-types-tests-take3.patch (40.8 KB ) - added by Jonas H. 13 years ago.
Against [17904]
html5-input-types-take3.patch (8.0 KB ) - added by Jonas H. 13 years ago.
Against [17904]
16630-input_type.diff (6.7 KB ) - added by Claude Paroz 12 years ago.
Made input_type customizable
html5-input-types-take4.patch (52.8 KB ) - added by Claude Paroz 12 years ago.
Patch, tests, docs
html5-input-types-take5.patch (52.8 KB ) - added by Stephen Burrows 12 years ago.
Updated patch to current master.

Download all attachments as: .zip

Change History (55)

by Jonas H., 13 years ago

by Jonas H., 13 years ago

comment:1 by Aymeric Augustin, 13 years ago

Triage Stage: UnreviewedAccepted

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) ?

comment:2 by Jonas H., 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 Jonas H., 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 Carl Meyer, 13 years ago

This patch would be superseded/fixed if #15667 is merged. That shouldn't block this patch, as it's not clear when (or even if, depending on performance issues) we can do #15667 - just making a note for reference.

comment:6 by rm_, 13 years ago

Cc: riccardo.magliocchetti@… added

comment:7 by tgecho, 13 years ago

Cc: tgecho 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 Julien Phalip, 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.

by Jonas H., 13 years ago

against [17281]

by Jonas H., 13 years ago

against [17821]

comment:10 by Aymeric Augustin, 13 years ago

Needs documentation: set

comment:11 by Aymeric Augustin, 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 Paul Oswald, 13 years ago

Cc: Paul Oswald 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 Jonas H., 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')}

by Jonas H., 13 years ago

Against [17904]

by Jonas H., 13 years ago

Against [17904]

comment:14 by Jonas H., 13 years ago

Added an implementation of my suggestion in comment 13.

comment:15 by Doug Harris, 13 years ago

Cc: dharris+django@… added

comment:16 by Danilo Bargen, 12 years ago

Cc: Danilo Bargen added

comment:17 by Claude Paroz, 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.

Last edited 12 years ago by Claude Paroz (previous) (diff)

comment:18 by buggystick, 12 years ago

Cc: buggystick added

by Claude Paroz, 12 years ago

Attachment: 16630-input_type.diff added

Made input_type customizable

comment:19 by Claude Paroz, 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 anonymous, 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.

in reply to:  19 comment:21 by Claude Paroz, 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:22 by Claude Paroz <claude@…>, 12 years ago

In [f1bdfbd24bcc76d21c4bf7442959bdf630ac4dec]:

Document and test 'type' usage in Widget attrs

Refs #16630.

by Claude Paroz, 12 years ago

Patch, tests, docs

comment:23 by Claude Paroz, 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 Jannis Leidel, 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 Jonas H., 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 Stephen Burrows, 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.

by Stephen Burrows, 12 years ago

Updated patch to current master.

comment:27 by Stephen Burrows, 12 years ago

Triage Stage: AcceptedReady for checkin

Tests pass, docs look good to me, marking RFC.

comment:28 by Claude Paroz, 12 years ago

Triage Stage: Ready for checkinAccepted

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:29 by Stephen Burrows, 12 years ago

If the issue is convincing core devs, shouldn't this be marked DDN?

comment:30 by Stephen Burrows, 12 years ago

Triage Stage: AcceptedDesign decision needed

comment:31 by Felipe 'chronos' Prenholato, 12 years ago

Cc: philipe.rp@… added

comment:32 by Carl Meyer, 12 years ago

Triage Stage: Design decision neededAccepted

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 Claude Paroz, 12 years ago

Owner: changed from nobody to Claude Paroz
Status: newassigned

Thanks Carl for your input. I'll take care of the commit.

comment:34 by Claude Paroz, 12 years ago

Triage Stage: AcceptedReady for checkin

Latest version of the patch: https://github.com/django/django/pull/679

comment:35 by Simon Charette, 12 years ago

Triage Stage: Ready for checkinAccepted

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 Claude Paroz, 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 Simon Charette, 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 Claude Paroz, 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:39 by Claude Paroz <claude@…>, 12 years ago

In 4f16376274a4e52074722c615fccef5fac5f009a:

Added HTML5 email input type

Refs #16630.

comment:40 by Claude Paroz <claude@…>, 12 years ago

In f7394d2c32b4b4717066f254adaa513d08ab32a4:

Added HTML5 url input type

Refs #16630.

comment:41 by Simon Charette, 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 Claude Paroz, 12 years ago

Resolution: fixed
Status: assignedclosed

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:43 by Claude Paroz <claude@…>, 12 years ago

In 7ec2a21be15af5b2c7513482c3bcfdd1e12782ed:

Fixed #19686 -- Added HTML5 number input type

Thanks Simon Charette for his help on the patch. Refs #16630.

comment:44 by Tim Graham <timograham@…>, 11 years ago

In 2a979d2a7bec485e4b90b7ae99ace0dd16faa948:

Updated contrib.admin to use Email/URLInputs; refs #16630

comment:45 by Tim Graham <timograham@…>, 11 years ago

In 5cc1ea4773f628f93dd2db9d353dc6b980e4a3ab:

[1.6.x] Updated contrib.admin to use Email/URLInputs; refs #16630

Backport of 2a979d2a7b from master

comment:46 by anonymous, 11 years ago

Is ColorInput available as a widget yet? Do you want a patch for it?

comment:47 by Claude Paroz, 11 years ago

I don't think so. Specialized input types should be left to third-party apps.

comment:48 by Natalia Bidart, 4 months ago

Tickets #35598, #35599, #35600 and #35601 were raised for other HTML5 input types. Forum discussion.

Note: See TracTickets for help on using tickets.
Back to Top