Bug Tracker

Ticket #9400 (closed enhancement: fixed)

Opened 3 years ago

Last modified 10 months ago

Deprecate :text, :radio, :checkbox, etc. selector extensions

Reported by: gnarf Owned by:
Priority: blocker Milestone: 1.8
Component: selector Version: 1.6.1
Keywords: 1.7-discuss Cc:
Blocking: Blocked by:

Description

Deprecate (for eventual removal) the input type selectors: :file :image :password :radio :reset :submit :text -- They are basically aliases to [type="file"] [type="image"] but can't use querySelectorAll - I think having these selectors around in the long term future is entirely unnecessary and confusing.

Change History

comment:1 Changed 3 years ago by john

  • Keywords 1.7-discuss added

Nominating ticket for 1.7 discussion.

comment:2 Changed 3 years ago by rwaldron

+0, Perhaps just map these to the qSA compat attr selectors

comment:3 Changed 3 years ago by john

+1, Yes, they should not exist in their current format - however I think that the selectors should be mapped to the associated CSS strings (e.g. :submit -> [type=submit]).

comment:4 Changed 3 years ago by gnarf

Do we already have the ability to map selectors pre-qSA? I'm not sure it would be worth building this feature, it will likely only cause MORE confusion, not LESS.

If not - why not just take these selectors and make them into a jQuery.formSelectors.js that the end user can include to keep them if they need them?

The actual implentation of some of these is not a simple search / replace, especially since they force nodeName==="input" as well, some of them search for multiple types (button/input submits for instance) and etc.

I think keeping the selectors but doing some sort of replacement strings would be more than needed, especially when we can just provide a shim to add the functionality back / give REALLY DETAILED explanations of the better alternatives.

Last edited 3 years ago by gnarf (previous) (diff)

comment:5 Changed 3 years ago by jaubourg

+1,

comment:6 Changed 3 years ago by timmywil

-1, I'm not sure removing will be realistic.

comment:7 Changed 3 years ago by timmywil

  • Priority changed from undecided to low
  • Status changed from new to open
  • Component changed from unfiled to selector

comment:8 Changed 3 years ago by dmethvin

+1, Deprecate in docs immediately, remove totally in the future. Remapping in code forever won't remove the bloat.

comment:9 Changed 3 years ago by timmywil

+1 I change my vote. Just checked and I didn't realize these weren't css3 selectors.

comment:10 Changed 3 years ago by ajpiano

+1, But if we remove this, we have to doc the hell out of it and make it fail obtrusively, kind of like when @ got deprecated - and we have to make the case that just like dropping @, it's a simple code change and it makes your code go faster. And also provide a shim. These shortcuts are really popular.

comment:11 Changed 3 years ago by danheberden

+1

comment:12 Changed 3 years ago by scott.gonzalez

+0, we should be able to pre-process selectors and convert them to standard selectors, then we should move these to a core plugin

comment:13 Changed 3 years ago by dmethvin

  • Keywords needsdocs added
  • Priority changed from low to blocker
  • Milestone changed from 1.next to 1.7

comment:14 Changed 3 years ago by espressive

+1 for removing the non CSS3 selectors, updating documentation and clearly communicating change to the community.

comment:15 Changed 3 years ago by john

  • Milestone changed from 1.7 to 1.8

Will tackle when we do the Sizzle rewrite.

comment:16 Changed 2 years ago by dmethvin

  • Summary changed from Remove :input Selectors to Deprecate :text, :radio, :checkbox, etc. selector extensions

comment:17 Changed 2 years ago by dmethvin

  • Keywords needsdocs removed
  • Status changed from open to closed
  • Resolution set to fixed

Docs updated. Again, this does not obligate us to remove them but I think it's clear they're not best practice.

comment:18 Changed 2 years ago by scott.gonzalez

Might as well mention here that not using :text is painful for many users since [type=text] doesn't match <input>.

comment:19 follow-up: ↓ 22 Changed 2 years ago by dmethvin

How do they get into that situation? Is there a common reason to not specify a type?

comment:20 Changed 2 years ago by scott.gonzalez

I never specify type for text inputs, just like I never specify type for script or style tags. It's pretty common for developers to not specify the type attribute when creating text inputs.

comment:21 Changed 2 years ago by dmethvin

I see your point but leaving off the type also makes it hard for CSS to select so it can't be styled. That doesn't seem like good practice.

I'm using "deprecated" to mean the stuff  here (things like: not best practice, unpopular, confusing, inefficient, ineffective, impractical to fix) and it doesn't obligate us to remove it. Conversely, we *can't* remove something until we've deprecated it for a version so I'd rather be aggressive on this.

comment:22 in reply to: ↑ 19 Changed 2 years ago by jsumners

Replying to dmethvin:

How do they get into that situation? Is there a common reason to not specify a type?

From  http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#the-input-element regarding the presence of the type attribute:

"The missing value default is the Text state."

Thus, if you're writing "HTML5", it is perfectly valid markup, according to the spec, to not include a type attribute for basic text inputs.

comment:23 Changed 2 years ago by dmethvin

Right, I agree it *can* be done in HTML; the question is whether it *should* be done. Give me the standard CSS to select only <input /> and not <input type=checkbox> in order to style it, for example. Whatever that is, you can use it in jQuery as well. If it turns out to be difficult, then perhaps inputs without a type are possible, but not advisable. Therefore the deprecation. It doesn't mean you cannot do it, just that it is not a good idea.

comment:24 follow-up: ↓ 26 Changed 2 years ago by csicky@…

I use :text all the time, please do not set it as deprecated. You can translate it if you wish behind the scenes to [type=text] and use that to select the elements, but I want to be able to write less.

Fantastic... I use jQuery to type less :|

JUST COUNT THE DAMN CHARACTERS!!!!

:text 5

[type=text] 11

comment:25 Changed 2 years ago by rwaldron

csicky@… -

Try to stay calm - there will be a supported back-compat plugin.

comment:26 in reply to: ↑ 24 Changed 2 years ago by mikesherov

Replying to csicky@…:

I use :text all the time, please do not set it as deprecated. You can translate it if you wish behind the scenes to [type=text] and use that to select the elements, but I want to be able to write less.

Fantastic... I use jQuery to type less :|

JUST COUNT THE DAMN CHARACTERS!!!!

:text 5

[type=text] 11

I can't tell if this is a real complaint or a troll trolling us.

comment:27 Changed 2 years ago by csicky@…

sorry, I am calm now :)

anyway in my opinion this should not be deprecated because it is less typing than the other selector

remember, the "write less" part in the logo...

comment:28 Changed 2 years ago by jamietre

I see this deprecation is part of 1.8 release - the point about the value of ":text" because "text" is the default for "type" in HTML5 seems very relevant.

The discussion kind of died out and suddenly it's official, just wondering what the proposed "correct" way to select text inputs is now. Is it expected that the "type" element should be included no matter what, even though it's not required in HTML5, or would we be expected to use a selector that chooses type="text" or type is missing to properly select all text inputs from a valid HTML5 document? Honestly I can't even figure out a CSS selector that would work inline. You could say:

input[type="text"], input[type!=""]

.. but that doesn't work inline (it would have to be it's own selector, since it depends on grouping for an "or" condition). And it's ugly as sin. And even that requires the jQuery "attribute not equals" extension!

This seems a very useful, and probably very widely used, feature to deprecate, without providing a clear path for an alternative.

comment:29 Changed 2 years ago by dmethvin

I think the best approach is to specify the type in the markup. Otherwise it can't be selected with CSS either. As with methods like .live() there is no set time for removing these, and some or all of them may not ever be removed. By deprecating them we are making it clear these are non-standard and not advisable.

comment:30 Changed 2 years ago by jamietre

The fact that it can't be done with CSS doesn't seem like a good reason to remove a feature. Quite the opposite, it seems like an excellent reason for the inclusion of a feature.

":selected" does something that can't be done at all with CSS. So does ":input" (at least not inline). So does attribute !=. Aren't these useful features for that very reason? This seems like a step backwards. I like the fact that jQuery solves shortcomings of the browser & CSS. I realize that this isn't going to break anything today, or for some time, but whenever that feature is removed it sure will. This seems like something that's way too common, and involves a requirement to make changes to 100% valid HTML, to be removed.

comment:31 Changed 2 years ago by dmethvin

The fact that it can't be done with CSS doesn't seem like a good reason to remove a feature.

It's not removed. It's discouraged via deprecation, and the fact that it can't be done with CSS is a good reason to discourage it. Eventually you may want to select text elements with CSS and be unable to do it.

comment:32 Changed 2 years ago by jamietre

Sure, I understand - but it's kinda the same thing. The goal of deprecating something is to remove it, and I wouldn't want to code against a deprecated feature if I could help it.

If the rationale is ensuring that whatever works with jQuery can also be done directly with CSS, does that mean that all other non-CSS pseudoclass selectors are likely to be deprecated in the future? Like :has(), :parent, :selected, and so on?

I'm just trying to understand the direction and rationale here. If the eventual target is to no longer support any non-true-CSS selectors (e.g. removing all jQuery extensions, in favor of only supporting the CSS4 spec) then that's fine, but that seems like a pretty big philosophical change to jQuery. CSS4 does deal with some stuff that jQuery extensions covered, but not everything, like this one and :selected, but probably others too.

comment:33 Changed 2 years ago by gnarf

It is VERY easy to implement these selectors - and once they are deprecated, we can provide a plugin for the re-inclusion of these selectors. Deprecation is about removing the size from the core library for the large number of people who don't even use these selectors... Those that do, can inject the selectors they need/use themselves.

comment:34 Changed 2 years ago by gnarf

Basically - we just need to take this chunk  https://github.com/jquery/sizzle/blob/feb5de3f8fed345190bf5ae86eb37ace1150f35b/sizzle.js#L622-653 and put it into a plugin.

comment:35 Changed 2 years ago by jamietre

@gnarf, totally understand the rationale for removing features in general. I'm just a bit confused by the decision to remove this one. The fact that something is easy to implement could be used as an argument for removing almost any single function of jQuery's. It's not a reason in and of itself.

I fully support jQuery moving towards a more plugin type approach in general. I hardly use 90% of its functionality. But this is the core of jQuery: a selector engine, a DOM traversal and manipulation tool, making it easier to do common tasks. Targeting text inputs for styling or other purposes is a very common task.

Last edited 2 years ago by jamietre (previous) (diff)

comment:36 Changed 2 years ago by kitsune

Having :text match both <input> and <input type="text"> is a really useful feature; and selecting elements seems to be a pretty core part of jQuery.

I wanted to add that Google's mod_pagespeed also removes type="text" for the purposes of reducing HTML size  https://developers.google.com/speed/docs/mod_pagespeed/filter-attribute-elide

so dmethvin's proposal that everyone rewrite all their HTML to use type="text" seems to have real costs, and doesn't really seem to be appropriate for all use cases (e.g. people who are speed geeks)

comment:37 Changed 2 years ago by dmethvin

so dmethvin's proposal that everyone rewrite all their HTML to use type="text"

For the sake of people who scroll to the bottom to spew, I did not propose that. If you have any doubt, you can Ctrl-F "dmethvin" on this page to see what I did write.

comment:38 Changed 2 years ago by kitsune

I read:

Right, I agree it *can* be done in HTML; the question is whether it *should* be done. Give me the standard CSS to select only <input /> and not <input type=checkbox> in order to style it, for example. Whatever that is, you can use it in jQuery as well. If it turns out to be difficult, then perhaps inputs without a type are possible, but not advisable. Therefore the deprecation. It doesn't mean you cannot do it, just that it is not a good idea.

as advising people not to use inputs without a type. If I misunderstood, I did not mean to "spew". I meant to refer to your posts to say that I disagree and think that people should be able leave out the type attribute on input elements.

We have an internal library that is used to read from form inputs, and ran into a bug where all of a sudden text inputs where not being selected properly. This was due to turning on the elide attributes optimization. We put in a fix to use the :text pseudo-selector instead, and found that to be a nicely elegant fix. While I agree that some of the other pseudo selectors, like :checkbox and :radio don't really do much useful "work", :text seems to do a very valuable normalization.

We also ended up implementing a filter that looked for all text-like inputs at once. This one then selected HTML5 variants like [type=search],[type=email],[type=tel], etc. I wonder if maybe a :text-like pseudo-selector might be useful to put in as a feature.

comment:39 Changed 2 years ago by Joe T.

i'm not seeing any effective, efficient alternatives for losing this selector. The other input selectors i can understand, but this one is usefully generic & applies to multiple HTML tags.

":input" matches any form input, correct? INPUT, SELECT, TEXTAREA, BUTTON...

"input" matches INPUT tags only.

Thus: $(":input") is much simpler to write AND remember than $("input, select, textarea, button") if i want a collection of all (or some combination) of the inputs in a form.

i'm not about to throw a fit over typing a few more characters, but in the interest of code efficiency & cleanliness...

Perhaps an inputs() method that will shortcut the long selector list above? If an argument is provided, it filters for the matching elements?

$('#myForm').inputs() /* All inputs in the form */

$('#myForm').inputs('[type=checkbox], select') /* Checks & SELECTs etc... */

comment:40 follow-ups: ↓ 41 ↓ 43 Changed 2 years ago by dmethvin

in the interest of code efficiency & cleanliness

Since :input is a non-standard selector extension, it is not efficient. It's also easy for later maintainers to overlook the leading colon, thinking that you meant input instead, so it's not good for readability or maintainability either.

The .elements property of the form element contains a list of all the inputs inside the form, and that is the fastest way to get all the inputs without any searching at all.

A plugin like the one you describe might help people who prefer not to use the standard selectors or form.elements but given there are already at least two good options I don't think a third method is needed in core.

comment:41 in reply to: ↑ 40 Changed 2 years ago by anonymous

Replying to dmethvin:

The .elements property of the form element contains a list of all the inputs inside the form, and that is the fastest way to get all the inputs without any searching at all.

My efficiency reference was for the programmer, not necessarily for performance, but the point is moot. i was unaware of .elements. It may be useful to note that as an alternative on the :input API page.

On that note, is that property a jQuery object, or just the DOM elements? It would seem just as performance-inefficient to do $($("#myForm").elements) in order to get the inputs into a jQuery object. Now, i give you there are many ways to skin a cat, i'm just taking a basic example. Also, does .elements apply to ALL inputs within ALL forms passed to jQuery? $('form').elements == all inputs on the page?

You mention a second option for getting all elements in a form, but only discuss the .elements property. Did i miss something?

comment:42 Changed 2 years ago by timmywil

I'm not sure I'd recommend using form.elements in IE6/7. I don't know where I stand on the convenience of these selectors, but I don't think we will realistically be able to remove them in 1.9 or 2.0.

comment:43 in reply to: ↑ 40 Changed 2 years ago by Joe T.

Replying to dmethvin:

The .elements property of the form element contains a list of all the inputs inside the form, and that is the fastest way to get all the inputs without any searching at all.

Sorry, i noticed now that you were referring to the DOM form.elements property, not a jQuery property. While that may address the issue on a small scale:

$(form.elements)

it still doesn't help make an efficient jQuery collection when you're already using a jQuery chain:

$("#myForm").[something i want to to do the form]().elements == jQuery dead-end (just like .context most of the time)

nor specify whether the .elements property applies to all forms in a collection.

comment:44 follow-up: ↓ 45 Changed 2 years ago by dmethvin

What's wrong with .filter()? Actually, nevermind, this thread is definitely off topic because we're not talking about a bug or a feature removal at this point. To get help with traversal, filtering, or writing a plugin, ask a question on our forum or StackOverflow.

comment:45 in reply to: ↑ 44 Changed 2 years ago by Joe T.

Replying to dmethvin:

What's wrong with .filter()? Actually, nevermind, this thread is definitely off topic because we're not talking about a bug or a feature removal at this point. To get help with traversal, filtering, or writing a plugin, ask a question on our forum or StackOverflow.

i disagree.

The purpose of my comments was to pose an argument against deprecating this particular selector until/unless an equally effective & simple-to-use alternative is offered. So far, i'm not convinced the suggestions match those requirements, which are fundamental qualities of jQuery.

.filter() doesn't help unless the INPUT/etc. elements are already in the collection, in which case you're in the same boat as above: using a long selector to get them or wrapping the DOM form.elements which someone suggested may cause problems in old IE. If you meant .find(), you still start from the FORM and feed a long selector to get the full list of elements.

So it goes back to: This selector provides an EASY way to get all the inputs of a form, regardless of tag, but it hurts performance. On the other hand, the alternatives are either inconvenient or perform as badly as this selector. Weighed against each other, i say the ease of use wins and the selector should be kept.

i personally feel adding a method to replace this wouldn't be that harmful. It would use .find(), but would handle the long selector internally. Optionally, if a selector is passed to it, that would filter .find()'s results. The resulting executions should wash:

Let's assume a requirement to obtain all inputs of a form, no immediate filters (which is what this selector does in the first place).

/* Current (lack-of) alternative */
$("#myForm").find("input, select, textarea, button")
==
$("#myForm").inputs() /* inputs() handles the above selector */

/* Optional filtering argument */
$("#myForm").find("input, select, textarea, button").filter("[name^=foo]")
==
$("#myForm").inputs("[name^=foo]") /* inputs() handles the selector & filters */

So to emphasize the point: this feature impacts performance but keeps code simple. If it's removed, the alternatives offered improve performance, but do not retain simplicity.

comment:46 follow-up: ↓ 47 Changed 2 years ago by ajpiano

Keep in mind "deprecation" doesn't necessarily mean we are going to remove something - we often can't because of backcompat. It is a denotation that we want to strongly discourage the use of a particular practise - in this case, these nonstandard form pseudoselectors.

Adding a new method to replace it wouldn't be "harmful," per se, unless we consider adding new API surface and filesize harmful - which we do. The best way to prove the demand is to release a plugin and then there's an implementation with its pros and cons we can evaluate, as well as the plugin's level of adoption. This isn't the first time someone's wanted a traversal/filtering method that would make life easier, and it likely won't be the last. However, something like this to core right now, especially when it could be fraught with issues in oldIE, isn't something we want to take on. And again, :input isn't going anywhere, we just want to make the point that just because something is a little faster to type, it doesn't make it the best choice for your application.

comment:47 in reply to: ↑ 46 Changed 2 years ago by Joe T.

Replying to ajpiano:

Keep in mind "deprecation" doesn't necessarily mean we are going to remove something - we often can't because of backcompat. It is a denotation that we want to strongly discourage the use of a particular practise - in this case, these nonstandard form pseudoselectors.

i understand deprecation isn't immediate removal, but it does imply an intent somewhere down the road. In any case, while i completely agree the non-standard type selectors should go, :input will be hard to get rid of without a suitable replacement. In the meantime, the whole block of code that deals with these selectors is stuck in the core, so i figured a replacement method might ease its removal. :)

Thanks for the feedback.

comment:48 Changed 2 years ago by anonymous

It's worth mentioning, this means changes to more than just your own code that you write, but also to all the plugins you use, one of the biggest assets to Jquery are the plugins.

I was searching for NEW HTML 5 types, e.g. :email for type="email" and came across this changeset.

comment:49 Changed 10 months ago by anonymous

After it's so widely used, jQuery becomes so smug these days. Every change require hunting and fixing bugs in plugins.

So what if I'm trolling? It's just feedback. Appreciate it while you get it!

Note: See TracTickets for help on using tickets.