#22266 closed defect (bug) (fixed)
onbeforeunload alert always triggers with attachments
| Reported by: |
|
Owned by: |
|
|---|---|---|---|
| Priority: | low | Milestone: | 3.5 |
| Component: | Media | Version: | 3.5 |
| Severity: | blocker | Keywords: | |
| Cc: |
Description
Steps
- Create a post with attachments in it
- Visit the post's edit screen
- Navigate away without modification and see an alert about "The changes you made will be lost..."
Trying to press "Update" and then leaving gives the same result.
Cause
tinymce.activeEditor.isDirty() is always returning true because attachments are lazy loaded with individual XHRs and so the editor's startContent property doesn't contain the full HTML for an attachment. Once an attachment model has been loaded then it's re-rendered and the editor content is different even though the user hasn't made any modifications.
Attachments (1)
Change History (13)
comment:2
SergeyBiryukov — 7 months ago
Related/duplicate: #22048
comment:3
SergeyBiryukov — 7 months ago
#22048 was marked as a duplicate.
- Priority changed from normal to high
- Severity changed from normal to blocker
Discussed this with @koopersmith in IRC. Only happens when the user opens an existing post for editing but doesn't edit anything, caused by the replacement of the shortcodes with "views" when the editor loads the initial content.
There is a way to tell TinyMCE the content wasn't modified which will cancel the beforeunload event. We need a bit more logic to make sure the user hasn't started typing before all shortcodes were replaced with views. Patch coming soon.
Replying to azaozz:
There is a way to tell TinyMCE the content wasn't modified which will cancel the beforeunload event. We need a bit more logic to make sure the user hasn't started typing before all shortcodes were replaced with views. Patch coming soon.
We're not going to block the user, right? But rather, once all views are loaded, we should only set dirty to false if the user hasn't started typing by then.
Replying to nacin:
Right. Tested attaching an one-time-only callback to the keydown and paste events so we know when the user has started typing. If that occurs before all views are loaded, we leave the editor state as "dirty" (i.e. onbeforeunload will trigger). If the user hasn't started typing when all views are loaded, we set the editor state to "clean".
The other thing to think about is what happens when they try to leave a post before all of the views are loaded. If the one-time-only callbacks have yet to fire, we'll want to consider it to be clean.
Yeah, the logic is pretty simple: there's a var isClean = true; that is changed to false onpaste and onkeydown. Both callbacks are removed if any of them runs or when all views are loaded. After all views are loaded we check that var and set ed.isNotDirty = true if isClean is true.
It's a bit tricky to sync this with ed.isNotDirty while the views are loading, trying to figure out the best way (the onbeforeunload event in the browsers is a "special" one and doesn't behave as a standard event).
comment:10
nacin — 6 months ago
- Priority changed from high to low
Removing views, see #21813 (comment 30), should resolve this for 3.5.
comment:11
koopersmith — 6 months ago
- Owner set to koopersmith
- Resolution set to fixed
- Status changed from new to closed
In 22567:
comment:12
koopersmith — 6 months ago
Another method we could use here is to avoid editor.isDirty() entirely, and compare processed versions of the content. Attaching a patch as an example.

A couple of options:
Option 2. has the potential issue of a slow loading image updating the startContent after a user has made some actual modifications and stopping the navigation warning from appearing.