if disabled state is changed with javascript, the normal state doesn't return after refreshing the page

NEW
Unassigned

Status

()

Core
DOM: Core & HTML
6 years ago
3 months ago

People

(Reporter: aardmaat, Unassigned)

Tracking

(Blocks: 2 bugs, {testcase})

Trunk
testcase
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(Not tracked)

Details

(URL)

Attachments

(1 attachment)

(Reporter)

Description

6 years ago
User-Agent:       Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0a2) Gecko/20110501 Firefox/5.0a2
Build Identifier: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0a2) Gecko/20110501 Firefox/5.0a2

on a forum I helped with a script
when doing that it appeared that firefox was the only browser that didn't behave as expected with this script:

<html>
<head>
<script>
for(var i=0;i<20;i++)
setTimeout("foo('"+i+"')",(20-i)*2000);
function foo(n)
{
	document.getElementById('btn').value=n;
	if(n==0)
  {
	document.getElementById('btn').value='Download';
	document.getElementById('btn').disabled=false;
  }
}
</script>
</head>
<body bgcolor="#00CCCC">
<input style='width:150px' id='btn' type='button' value='20' disabled='disabled' onclick='window.location="mijndownloadbestand.rar"'>
</body>
</html>

(you might want to change the timer for testing, 20 seconds is long!)

after 20 seconds the button for downloading is enabled, that's just fine,
when you refresh though, the button starts counting again but isn't disabled at the beginning. all other tested browsers (opera, chrome, ie9) do disable the button after refreshing the page.
this flaw would cause developers to make patches for firefox.

Reproducible: Always

Steps to Reproduce:
1.make a html file with the script
2.open it in firefox and an other browser
3.waith till the timer enables the button
4.refresh the page
5.firefox doesn't disable the button, other browser does

Actual Results:  
firefox's behaviour was out of sync with the other browsers

Expected Results:  
it should have disabled the button again for 20 seconds

this also happened with the firefox browser used by the person who needed help (because of this bug) with the script. I don't know what version he/she uses but it probably isn't aurora (so the bug is probably in more different versions of firefox)
(Reporter)

Comment 1

6 years ago
Created attachment 529443 [details]
example of the code

an example of the script
Attachment #529443 - Attachment mime type: text/plain → text/html
I confirm the issue on Gecko 1.9.1, 1.9.2 and trunk.
I believe there is a dup somewhere.
Status: UNCONFIRMED → NEW
Ever confirmed: true
OS: Windows 7 → All
Hardware: x86 → All
Whiteboard: DUPEME
Version: unspecified → Trunk
Component: Layout: Form Controls → DOM: Core & HTML
QA Contact: layout.form-controls → general
(Reporter)

Comment 3

6 years ago
just realized it isn't css what I'm talking about, it's just html attribute,
sorry for my bad description
Modified disabled state is one of the form states that we preserve across history navigations and reloads, yes.  That's done quite explicitly.
(Reporter)

Comment 5

6 years ago
what's the reason for that?
shouldn't things like that be the same across al browsers?
> what's the reason for that?

I believe the idea was that a non-forced reload should be preserving all user-visible form state as much as possible (since it's a request to show again exactly what you're seeing, not to rerequest it all from the server).

> shouldn't things like that be the same across al browsers?

History operations are decidedly not the same across all browsers, and likely never will be....
Summary: if css is changed with javascript, the normal css doesn't return after refreshing the page → if disabled state is changed with javascript, the normal state doesn't return after refreshing the page

Comment 7

6 years ago
I think this is a bug and needs to be fixed. It's not consistent with other browsers. And if you ask me, the developers should take care of these things, not the browser itself. E.g. run validations on DOM load. There is just too many cases where this is not the desired behavior. Filling in values into input fields is ok, but not this. And it works "properly" in other major browsers.
Duplicate of this bug: 685657

Updated

6 years ago
Duplicate of this bug: 638609

Updated

6 years ago
Blocks: 592665

Updated

6 years ago
Duplicate of this bug: 587527

Updated

6 years ago
Blocks: 516920

Comment 11

6 years ago
Here's an old (resolved/invalid) bug about this: bug 293733.

from bz's comment 7 there:
> > why is disabled state of form elements persisted? 
> 
> I (or someone else) would have to go back and read the original bugs on
> that...  You're welcome to if you want to, of course.  It's about rock
> bottom low priority for me.
> 
> I wouldn't be opposed to changing the behavior if someone comes up with a
> consistent description of what form state restoration _should_ act like. 
> I'm opposed to random back-and-forth tweaking, though.

and for those interested in digging up the previous changes made in this area, the code is here: http://mxr.mozilla.org/mozilla-central/search?string=::SaveState
Keywords: testcase
Whiteboard: DUPEME

Comment 12

5 years ago
I'm throwing in my vote to fix this... I made a demo with a disabled button being added after the page loads: http://fiddle.jshell.net/Mottie/Adz9L/1/show/

Keep hitting the reload button without holding down the shift key and watch what happens.

Comment 13

5 years ago
(In reply to Boris Zbarsky (:bz) from comment #6)
> I believe the idea was that a non-forced reload should be preserving all
> user-visible form state as much as possible (since it's a request to show
> again exactly what you're seeing, not to rerequest it all from the server).

I agree that this is bad.  Form state should attempt to preserve *user-entered* information.  The disabled state of form elements isn't stuff the user typed in, it's stuff the page and scripts have set.  Preserving that does nothing but break pages; the disabled state is no more "form data" than class names and other arbitrary bits of DOM state.

I've hit this problem myself on EasyNews's search (a subscription service; can't usefully give a link), which disables the submit button when the form is submitted.  If I then reload the page before the submit completes, the form comes back unsubmittable.
You can't win there: disabled state is often set based on information the user entered (e.g. selecting one of a set of radios can enable/disable other controls), so restoring values but not disabled state will fix some pages but break others....

What we really need is some better way of restoring form data that informs the page about what exactly was restored or something.  Maybe we can make our restoration look like a user interacting with the page?

Comment 15

5 years ago
(In reply to Boris Zbarsky (:bz) from comment #14)
> You can't win there: disabled state is often set based on information the
> user entered (e.g. selecting one of a set of radios can enable/disable other
> controls), so restoring values but not disabled state will fix some pages
> but break others....

I think not restoring one select bit of DOM state as if it's form state is a step up, though.  Selecting that same set of radios might do any number of things, like hiding/showing arbitrary elements ("your password is weak"), or creating entirely new ones (Google Instant).

> What we really need is some better way of restoring form data that informs
> the page about what exactly was restored or something.  Maybe we can make
> our restoration look like a user interacting with the page?

That might be risky, since the page may react to the "user interactions" unexpectedly.  For example, if a user's authentication has expired, trying to enter data into a form might pop up an authentication overlay, when the page only meant  to do upon a real user interaction.

Comment 16

5 years ago
(In reply to Boris Zbarsky (:bz) from comment #6)
> > what's the reason for that?
> 
> I believe the idea was that a non-forced reload should be preserving all
> user-visible form state as much as possible (since it's a request to show
> again exactly what you're seeing, not to rerequest it all from the server).

A non-forced reload could be:
 1. A request to see again what you see now (as described above).
 2. A request to see what you saw when you first visited the page.
 3. A request to see what is on the server right now.

I would suggest that #1 is the least likely of these in the mind of the typical user and that #3 is beyond the technical understanding of the typical user (and already has its own, separate, invocation method), leaving #2 as the most useful implementation.

But the current implementation creates a 4th option:
 4. A request to see what you saw when you first visited the page, except for certain things, where 'some things' is defined in terms the typical user does not understand.  Moreover, if the 'some things' are logically related to other things, the user may see two kinds of data, that which is the same as when the page was first viewed and that which is not, in a relationship that no longer is consistent.

Example: http://stl.beallsprings.org/conservation%20easement.html

The checkbox toggles the display between two versions by modifying CSS.  The box is checked upon initial loading, which corresponds to what is displayed elsewhere on the page.  If you UNcheck the box, CSS is modified and the user sees a different view of the data (in this case a filtered view and a different background color).  The view of the data and the checkbox setting are in sync, as expected.  This synchronization remains as you check and uncheck the checkbox.

Now uncheck the checkbox, then reload the page.  The data has been restored to its original view, i.e. with annotations, but the checkbox remains unchecked, i.e. the two are now out of sync and the user is confused.

In this case, the problem results because the initial state of the checkbox, which is created by JavaScript with a specification of 'checked', is not restored when the page is reloaded.  This is apparently a direct result of the philosophy described above.

My symptoms are a possible dup of 693927, which also seems to be related to this philosophy.

A workaround, which I have implemented on page http://stl.beallsprings.org/Timeline.html, is to explicitly restore the initial state of the checkboxes using additional JavaScript driven by body onload=.  This is not necessary on any other browser that I have tested.

I continue to believe that interpretation #2 more closely matches the typical user expectation and thus is the best choice.
Chris, the most common reason for non-forced reloads are scripts running location.reload() and such, not users using the reload button.... and pages do it in all sorts of situations when they really mean #1.

I agree that the current situation is suboptimal; I'm just not sure how to actually make it better as opposed to trading off one set of problems (primarily biting website authors) for another (primarily biting users).

Comment 18

5 years ago
I'm disappointed that this hasn't been changed to match the behavior of every other browser.

Maybe I'm not seeing the big picture here, but how is this issue biting the users? The button itself says "reload the current page" not "refresh the current page". When would the user want to refresh a page? Why not make the form reset button do this? I guess we have to assume there are users with many different levels of experience, but I think they would be even more confused when the experience isn't consistent across different browsers.

Please don't make Firefox into the IE6 of browsers.
Comment 16 suggests not restoring form state at all.  How would that bite users?  Take a guess....
And for the rest, see comment 14.  Maybe pages are now expecting the other behavior and coding to it explicitly, in which case I agree that we should just stop saving/restoring disabled state.

Jonas, thoughts?

Comment 21

5 years ago
(In reply to Boris Zbarsky (:bz) from comment #19)
> Comment 16 suggests not restoring form state at all.  How would that bite
> users?  Take a guess....

Boris,

My guesser must not be working well.  How WOULD it impact users?  More specifically, how would it impact them if non-forced reload worked as it does on other browsers, but Back (i.e. the history) worked as it does today.  I see no logical reason for these things to be functionally linked, as they apparently are today.

I noticed something else.  I have browser.formfill.enable set to false.  It's one of the first things I do when setting up any browser.  I know many people like that capability, but I'm not one of them.  So why is MY checkbox state being 'preserved' when I reload a page?  (Note that this is a logical trap; if we were to agree that formfill.enable should alter the behavior of a non-forced reload, we'd have added even more complexity for the developer (or more confusion on the part of a user who encounters a page that didn't account for the added complexity...))

Which raises an OT question: Can a JavaScript developer dynamically determine the state of FIrefox options such as browser.formfill.enable?
> More specifically, how would it impact them if non-forced reload worked as it does on
> other browsers,

Other browsers preserve various bits of form control state on reload in various cases, last I tested (as well as scroll position and such).  They're not consistent with each other or with us, of course.  Also, web pages make reload() calls based on browser sniffing....

> So why is MY checkbox state being 'preserved' when I reload a page? 

Because that's not autofill.  Autofill is filling in controls when the page first loads based on previous values you put into them some other time when you visited the page.

Comment 23

5 years ago
firefox is "preserving" disabled="disabled" on inputs that _were not disabled_ prior to reload

<input id="foo1">
<input id="foo2" disabled="disabled">
<input id="foo3">

note, i have not determined the order of how this happens, so don't infer.  the order probably has a derterministic affect, but i haven't figured it out yet.

on reload, this happens:

<input id="foo1">
<input id="foo2" disabled="disabled">
<input id="foo3" disabled="disabled">

why is firefox applying attributes to elements that didn't previously have them?

reference page:  https://dragonstone-mill.com/pcf.html

Comment 24

5 years ago
(use firebug on my page and you'll see plenty of debug about wrongly applied disabled attribute)

Comment 25

5 years ago
That sounds like a different issue.  You may want to create a minimal test case and open a new ticket.

Comment 26

5 years ago
(In reply to Chris Beall from comment #21)
> My guesser must not be working well.  How WOULD it impact users?  More
> specifically, how would it impact them if non-forced reload worked as it
> does on other browsers, but Back (i.e. the history) worked as it does today.

Belatedly, I find it annoying in other browsers when I reload a form with data in it, and all of the fields get cleared on me.

Of course, if I have significant data then I always make a copy before refreshing even in Firefox, since it doesn't actually always work.  Since it's a dangerous, brittle feature--it's easy to get used to it, and then lose data when it doesn't happen--I think it should never have been introduced in the first place, but removing it now would probably cause riots.

(In reply to Boris Zbarsky (:bz) [In and out Aug 1 - 10, out Aug 11-20] from comment #14)
> You can't win there: disabled state is often set based on information the
> user entered (e.g. selecting one of a set of radios can enable/disable other
> controls), so restoring values but not disabled state will fix some pages
> but break others....

That's true, but this is a game of whack-a-mole that you can't win: sites often do many other things on user entry that can't possibly be restored, such as hiding and displaying elements and all kinds of style/class changes.  (Of course, this stuff is far more common today then it was when this feature was first introduced.)

It might simply break too many sites to be doable, but I really think this should only preserve direct user input, and leave it to sites to apply other changes during onload.
Duplicate of this bug: 681318

Comment 28

4 years ago
If you persist anything which is not directly changeable by the user, it will probably break the page:

 * If you refresh a page and a text field value is prefilled, user can change the value and carry on.
 * If you refresh a page and a text field is disabled, user can not do anything about it...

> It might simply break too many sites to be doable...

During my web developer and web user lifetime I did not come across any site which might rely on this feature (but I understand this is kind of subjective view).

Comment 29

4 years ago
I think what Pavel Horal said makes a lot of sense. One thing is filling text boxes, a whole other thing is disabling fields. The other problem is that no other browser exhibits this behavior, only Firefox.

Comment 30

3 years ago
We've encountered this misfeature over at Bootstrap (see https://github.com/twbs/bootstrap/issues/793 ) and ended up having to add a warning box to our docs specifically covering this ( http://getbootstrap.com/javascript/#buttons-usage ).
I am disappointed that Firefox required us to do that.

Comment 31

3 years ago
This weirdness is now documented on MDN:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input$compare?to=661055&from=641697
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button$compare?to=661057&from=660021

Updated

2 years ago
Severity: minor → normal

Comment 32

2 years ago
I'll add my 2 cents:  This is a BUG, not a feature.  It should be fixed.

Updated

a year ago
Blocks: 1230801

Comment 33

a year ago
There are lots of good points for either side of this debate but as it requires a work-around by the developer to fix it and not wanting the button to re-enable would seem to be an edge case I would label this as undesired behaviour and would also say it should be fixed.

Also, Bootstrap's suggestion of using autocomplete="off" as a work-around does not appear to work for me.

Comment 34

10 months ago
This is my preferred solution:

1. Don't restore states of form fields that can't be changed by user directly (e.g. disabled).

2. Restore later (e.g. after DOMContentLoaded), and fire "change" events on restored fields to simulate user inputs, so that the page can responed to the restoration and maintain the consistancy of the page. This should address https://bugzilla.mozilla.org/show_bug.cgi?id=654072#c14 . The tricky thing is that some pages may expect users to fill form fields in perticular order, e.g. reveal more fields according to previous inputs. Restoring in document order is probably OK for most cases.

3. Provide a way to opt-out form fields restoration. May be something like history.scrollRestoration="manual" ( https://developer.mozilla.org/zh-CN/docs/Web/API/History ). This needs a spec update.

Updated

5 months ago
Duplicate of this bug: 1299809

Updated

5 months ago
Duplicate of this bug: 1320419

Comment 37

3 months ago
(In reply to Duan Yao from comment #34)
> This is my preferred solution:
> 
> 1. Don't restore states of form fields that can't be changed by user
> directly (e.g. disabled).

Exactly. It was always a bad idea to restore disabled states on reload (or return visits). Restore user input only. Any states that change in response to user input are to be restored by the script, which will have every chance to do that as on load. Meddling by the browser in this area is just plain misguided.

> 
> 2. Restore later (e.g. after DOMContentLoaded), and fire "change" events on
> restored fields to simulate user inputs, so that the page can responed to
> the restoration and maintain the consistancy of the page.

No. This is just more "magical" meddling by the browser. Any script that responds to "change" events by changing disabled states should always do the same on load (or DOMContentLoaded) as there's always a chance that user data is persisted. This is not a new concept for browsers and they should not try to force the issue by firing bogus change events, which are strictly for indicating *user* changes as they occur (not when they are persisted between page loads).

> This should
> address https://bugzilla.mozilla.org/show_bug.cgi?id=654072#c14 . The tricky
> thing is that some pages may expect users to fill form fields in perticular
> order, e.g. reveal more fields according to previous inputs. Restoring in
> document order is probably OK for most cases.

There's nothing tricky about it and never has been. Scripts that hide or show elements in response to user input are responsible for synchronizing these states on load, just as when they disable elements in response to same. There's simply nothing for the browser to solve here, certainly not after two decades.

> 
> 3. Provide a way to opt-out form fields restoration. May be something like
> history.scrollRestoration="manual" (
> https://developer.mozilla.org/zh-CN/docs/Web/API/History ). This needs a
> spec update.

As far as persisting user *input* on revisiting a page? Fine, but realize that most users will never turn that off. Imagine the majority will never even find such a setting.

In any event, a properly designed script should never run into these issues as it would simply override all such meddling on load (or DOMContentLoaded). Of course, that depends on when such meddling occurs. Please do everyone a favor and make that a moot point.

Realize that no other browsers have such issues and properly designed scripts have managed for two decades without help in this area. Trying to prop up improperly designed scripts is just going to create more confusion and possibly trip up scripts that are trying to do their job properly.

HTH
You need to log in before you can comment on or make changes to this bug.