cannot capture paste event from window or document

RESOLVED FIXED

Status

()

Core
DOM: Events
RESOLVED FIXED
4 years ago
3 months ago

People

(Reporter: Jens Mönig, Unassigned)

Tracking

19 Branch
x86
Mac OS X
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(1 attachment)

(Reporter)

Description

4 years ago
Created attachment 719868 [details]
pasteCapture.html

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:19.0) Gecko/20100101 Firefox/19.0
Build ID: 20130215130331

Steps to reproduce:

add an event listener for "paste" to either the window or the document. Copy some text to the clipboard elsewhere, try to paste it into the document using cmd-v.

Source of the test page:

<!DOCTYPE html>
<html>
    <head>
        <title>Paste!</title>
        <script type="text/javascript">            
            window.onload = function () {
                document.addEventListener(
                    "paste",
                    function (event) {
                        alert(event.clipboardData.getData("text"));
                    },
                    false
                );
            };
        </script>
    </head>
    <body>
        <p>Copy some text elsewhere, then paste it here.</p>
    </body>
</html>



Actual results:

nothing


Expected results:

the "paste" event should be captured. This works in Chrome.

Updated

4 years ago
Attachment #719868 - Attachment mime type: text/plain → text/html

Comment 1

4 years ago
Dupe of bug 407983, I guess.

Comment 2

4 years ago
I am not sure if bug 407983 is really a duplicate as that bug asks for support of the clipboardData object on the paste event. Yet, this present bug asks the paste  event to be triggered in the first place whether with or without clibpoardData.

I actually found that paste is triggered but only with document.designMode = 'On'. I have changed the above code and with document.designMode = 'On' it works:

<!DOCTYPE html>
<html>
    <head>
        <title>Paste!</title>
        <script type="text/javascript">            
            window.onload = function () {
				document.designMode = 'On';
                document.addEventListener(
                    "paste",
                    function (event) {
                        alert(event.clipboardData.getData('text'));
                    },
                    false
                );
            };
        </script>
    </head>
    <body>
        <p>Copy some text elsewhere, then paste it here.</p>
    </body>
</html>

Follow the steps by Jens Mönig to make it work.

According to section "4.1.3 paste event" of the Clipboard API spec (http://www.w3.org/TR/clipboard-apis/#paste-event) the paste event should be triggered even with non-editable content, but without default behavior:

It says: "The paste event has no default action in a non-editable context, but the event fires regardless."

I guess that all other clipboard events are also not working in a non-editable context whether on document or any other element. Should I file a general bug report for this?

I have tested Firefox nightly build.

Comment 3

3 years ago
I confirm this bug is still present.

The spec is remarkably clear as jupiter mentioned: "The paste event has no default action in a non-editable context, but the event fires regardless."

In firefox, the paste event is fired only on an editable content. This behavior is in direct violation of the standard. See here: http://www.w3.org/TR/clipboard-apis/#paste-event

See the test case below:

<html>
<body>
<div id="editable" width="100%" contenteditable>
  CAN PASTE
</div>
<div id="noteditable" width="100%" >
  CANNOT PASTE
</div>

<script type="text/javascript">
document.getElementById('editable').addEventListener('paste', function(){
  console.log('Ive been pasted');
});
document.getElementById('noteditable').addEventListener('paste', function(){
  console.log('Ive been pasted');
});
</script>
</body>
</html>

Updated

3 years ago
Component: Untriaged → DOM: Core & HTML
Product: Firefox → Core
> This behavior is in direct violation of the standard

You mean of the draft?  What you linked to is not a standard; it's not even close to one.  It's not even at the "we're asking feedback on whether this makes any sense" stage....

Olli, have you been following the clipboard API spec?
Component: DOM: Core & HTML → DOM: Events
Flags: needinfo?(bugs)
One other note: nothing in the draft says whether the paste event bubbles.  So it's not actually defined whether a bubbling listener on the document or window will see the event.  Not that we're firing the event anyway, mind you (as you can tell by using a capturing listener), but there is nothing in the spec that says the actual testcases in this bug should work.  Or not work.  The behavior is simply not defined.
And while http://dev.w3.org/2006/webapi/clipops/clipops.html is a bit better for the other events, it still doesn't define whether the "paste" event bubbles.

Comment 7

3 years ago
I haven't followed the spec work too closely, but as far as I know, it is not very close
to reality yet, and it needs changes. (Apparently some behavior there effectively requires use of 
sync XHR on the main thread, that is a rather major bug
http://lists.w3.org/Archives/Public/public-webapps/2014JanMar/0247.html)
Flags: needinfo?(bugs)

Comment 8

3 years ago
Ok, it is a draft. What did you follow to implement the current behavior ?

I don't see what the test case I presented has to do with the bubbling nature of the event: the event does not fire at all on an element which is not in an editable context. So, maybe the first presented test case is not defined, but the simple, second one I presented should work according to the draft.

Since these are two separate issues (bubbling nature of the event vs which elements can be the source of a paste event), maybe I should open a separate issue ?
> the event does not fire at all on an element which is not in an editable context. 

Oh, sorry, I didn't read the comment 3 testcase carefully enough.

Note that per the current draft, the event shouldn't fire on that non-editable element, unless that non-editable element has focus.  Which it can't in that testcase, since it's not focusable.  See http://www.w3.org/TR/clipboard-apis/#fire-a-clipboard-event step 5.
And the bubbling issue is a spec issue (it not specifying the behavior), not an implementation issue.  Our paste events do in fact bubble, as they should.
(In reply to Boris Zbarsky [:bz] from comment #4)
> What you linked to is not a standard; it's not even
> close to one.  It's not even at the "we're asking feedback on whether this
> makes any sense" stage....

Well, the editor's draft is at that stage now :) http://lists.w3.org/Archives/Public/public-webapps/2014JanMar/0570.html

I should apologise that the TR/clipboard-apis is one year old though.

(In reply to Olli Pettay [:smaug] from comment #7)
> I haven't followed the spec work too closely, but as far as I know, it is
> not very close to reality yet

With the editor's hat on, I hope that anything currently not close to reality is on purpose. In other words: some things in the current editor's draft are not implemented or not consistent across browsers, but those should be powerful and usable bits that we want to do. (One example is being able to create event instances with a ClipboardEvent constructor and a property dictionary - new ClipboardEvent('paste', {'dataType':'text/plain', 'data':'Hello'}) - it's not "close to reality" but it's how we want things to be working AFAIK and more usable than the initFooEvent() convention with the sometimes insane number of arguments.)

> (Apparently some behavior there effectively requires use of 
> sync XHR on the main thread, that is a rather major bug

This point was brought up and most likely needs a small tweak to the "semi-trusted events" text. It is however entirely unrelated to the issues in this report, and I'm holding back because I think the whole "semi-trusted event" concept should be moved to the DOM Events spec eventually.

(In reply to Boris Zbarsky [:bz] from comment #5)
> nothing in the draft says whether the paste event bubbles
<X>
> The behavior is simply not defined.

Heh. I'm pretty sure it used to say "the event bubbles and is cancelable" all over the place until Hixie and Anne told me to drop those section because a Processing Model - style description would be so much clearer than plain fuzzy English. ;) They were right, though - simply writing the processing model turned my attention to several corner cases I would never have thought of otherwise. Anyway, I also kept most of the plain English prose, just labelling it as a "high-level description" ( http://dev.w3.org/2006/webapi/clipops/clipops.html#events ). I'll restore those missing bubbly sentences.

(In reply to rdunklau+firefox from comment #3)
> In firefox, the paste event is fired only on an editable content.

This is indeed a bug in Firefox (and since this works in Chrome it is, if I may borrow Olli's terminology, a case where the spec *is* aligned with reality, just not our reality.)

(In reply to Boris Zbarsky [:bz] from comment #9)
> Note that per the current draft, the event shouldn't fire on that
> non-editable element, unless that non-editable element has focus.  Which it
> can't in that testcase, since it's not focusable.  See
> http://www.w3.org/TR/clipboard-apis/#fire-a-clipboard-event step 5.

Step 5 there (or step 7 in the current editor's draft) specifies what node event.target should refer to if there is no focus. It doesn't (and shouldn't) say that the event doesn't fire if there is no focus.

I'm afraid Gecko has some work to do to beef up our clipboard events. I hope the spec is clear and mature enough to support this work.
Status: UNCONFIRMED → NEW
Ever confirmed: true
> It doesn't (and shouldn't) say that the event doesn't fire if there is no focus.

Sure.  It just won't fire on the node the listener is attached to in comment 3, nor any of its descendants.
In fact, the Paste command isn't enabled in Firefox. It appears to work in Chrome because Chrome doesn't update the enabled state of the Paste item and just keeps it enabled all the time.

The spec seems to have added the 'before' versions of the events which could be used to solve this, but I don't care too much for that as it would require us to fire all three before events on every focus/blur.
I added the before* events because they were requested, but it's not a terribly pretty solution. We don't handle ctrl-v with before* events, for example.

I've been considering something like

navigator.setCommandState('paste', 'enabled')
// paste command now enabled in this window

navigator.setCommandState('paste', 'automatic')
// now state depends on focus/editable context again, as usual

But then again, Opera (Presto) simply enabled 'paste' command if there was an event listener for paste events, same for copy and cut.. Does it need to be more complicated?
> navigator.setCommandState('paste', 'enabled')
> // paste command now enabled in this window
> 
> navigator.setCommandState('paste', 'automatic')
> // now state depends on focus/editable context again, as usual

That's generally what I had been thinking as well, although we maintain the state per top level window, so I would use window.setCommandState(...) instead.

However, you would still need access to the type of data on the clipboard to properly determine if a paste could be performed. For example, you'd want to disable the paste command if there was an image on the clipboard and you wanted to paste into a text-only field.
So we already support document.queryCommandEnabled() which is supposed to return true if a command is enabled, so we should keep that in mind when designing an API to set this value.  But because of what Neil mentioned in comment 15, I don't think we should just let the web page set the state of the paste command.

Could we not just fire this event irrespective of whether Gecko's paste command is enabled and modify the default action of the event to do nothing if it's disabled?  This way, content can use queryCommandEnabled if it wants to in order to figure out whether the paste event will do something, or they can just choose to implement it all themselves, for use cases such as CodeMirror where the content is technically not interested in the paste happening anyway.
(In reply to :Ehsan Akhgari (lagging on bugmail, needinfo? me!) from comment #16)
> Could we not just fire this event irrespective of whether Gecko's paste
> command is enabled and modify the default action of the event to do nothing
> if it's disabled?  

If the paste command is disabled, you can't trigger a paste from which to fire the paste event.
(In reply to comment #17)
> (In reply to :Ehsan Akhgari (lagging on bugmail, needinfo? me!) from comment
> #16)
> > Could we not just fire this event irrespective of whether Gecko's paste
> > command is enabled and modify the default action of the event to do nothing
> > if it's disabled?  
> 
> If the paste command is disabled, you can't trigger a paste from which to fire
> the paste event.

What do you mean by triggering a paste?  Ctrl+V/middleclick for example?
Any of the ways in which you can trigger a paste: menu command, toolbar button, key shortcut, etc.
(In reply to Neil Deakin from comment #15)
> However, you would still need access to the type of data on the clipboard to
> properly determine if a paste could be performed.

Hm.. In IE, beforepaste handles this with window.clipboardData (if user permits the site to access the clipboard).

Classic dilemma: is it better with a more limited API we can allow everywhere, or a more advanced API we'll have to guard with permissions?
(In reply to comment #19)
> Any of the ways in which you can trigger a paste: menu command, toolbar button,
> key shortcut, etc.

Right.  I'm proposing to change our behavior there.
I guess this is a needinfo on Enn?
Flags: needinfo?(enndeakin)
What info are you asking for?

The user can't trigger a paste from the menu unless that menu is enabled. On Mac, you can't trigger a keyboard shortcut associated with a disabled menu command either. You can't fire a paste event unless the user triggers the paste.

The options are to take the Chrome approach and enable the commands all the time, or have something similar to what was proposed in command 14/15.
Flags: needinfo?(enndeakin)
To be explicit, options are:

1) Always enable cut/copy/paste commands. (Precedent: Chrome)

2) Enable these commands if and only if there is an event listener for the corresponding event (Opera Presto)

3) Implement beforecut/beforecopy/beforepaste events and let JS enable otherwise disabled commands from corresponding event listeners (IE)

4) Come up with a new API for setting command state (f.ex. document.setCommandEnabled() to go with the somewhat related execCommand stuff) (nobody)

Of these options, only #3 might handle the use case Neil mentioned earlier, where a script may want to check if there is content it wants to handle on the clipboard before actually enabling the command. (It's not spec'ed that way at the moment, but if we want to handle that use case we can give that some thought.. Reported https://www.w3.org/Bugs/Public/show_bug.cgi?id=27010 on that.)

I think I'm leaning towards #3 because #4 will add new API but probably not bring major benefits compared to #3. So it seems like adding more "stuff" to the platform for a pretty minor benefit.

(#3 does however require us to sort of do #1 too, at least do something to make ctrl-V work.)
> I think I'm leaning towards #3 because #4 will add new API but probably not
> bring major benefits compared to #3. So it seems like adding more "stuff" to
> the platform for a pretty minor benefit.
> 

The main issue with #3 is that it requires firing all three events every time the focus/selection changes.

> (#3 does however require us to sort of do #1 too, at least do something to
> make ctrl-V work.)

It should just do the same thing as the other methods of invoking the commands, so there shouldn't be any difference here.
(In reply to Neil Deakin from comment #25)
> The main issue with #3 is that it requires firing all three events every
> time the focus/selection changes.

Hm.. As far as I know it's not what IE does, and the way it's spec'ed doesn't seem to require this:
http://dev.w3.org/2006/webapi/clipops/clipops.html#beforecopy-event

Now, if you have copy/cut/paste buttons in the UI (for example on a toolbar) I suppose it follows that to set their state correctly you'll have to fire lots of events. But few if any browsers have such toolbars these days, so we get away with firing the events every time we open a menu that contains copy, cut or paste commands. (I think it would apply to "Edit" menu, main program menu, right-click menu, and the long tap-menu on some devices).
(But then again, the shortcut key case is not really covered by this functionality per the current spec. I guess the shortcuts should trigger an internal "check if clipboard event is desired" command which fires the before* event.)
> Now, if you have copy/cut/paste buttons in the UI (for example on a toolbar)
> I suppose it follows that to set their state correctly you'll have to fire
> lots of events. But few if any browsers have such toolbars these days, so we
> get away with firing the events every time we open a menu that contains
> copy, cut or paste commands.

Firefox does have such buttons that you can customize to be on the toolbar.

Firing three events that a web page could use to potentially pause the browser for some time while opening the Edit menu isn't acceptable in my opinion. This is one reason I prefer something more like method 4.
(In reply to Neil Deakin from comment #28)
> Firing three events that a web page could use to potentially pause the
> browser for some time while opening the Edit menu isn't acceptable in my
> opinion.

I may still class it as "acceptable" based on the following arguments:

1) Websites that cause poor browser performance or behaviour will loose users. 

2) If we're truly concerned it should also be fine to put a low time limit on these events - say, no more than 5ms each or something should handle all concerns. (Not suggesting "slow script" dialogs though - just kill the slow listener's thread and move on).

3) If we have an implementation that doesn't do script execution and UI on the same thread, we could also draw the menu anyway, and just enable those commands if and when the script concludes. (Keep in mind that JS can not *disable* commands the browser thinks should be enabled, like copy if there is a selection - so there's no nuisance potential).

I'm not against suggesting a new API if it's clearly better than the existing stuff, but I think we need more reasons than just "prevent a clumsy or malicious website from subtly harming browser UX while we're still using a mostly single-threadedish generation of browsers".
(In reply to Neil Deakin from comment #28)
> Firefox does have such buttons that you can customize to be on the toolbar.

I wonder if it would be good enough to fire these events when the page is loaded. An app that wishes to handle clipboard events can listen for the before events fired right after the load event to enable them..? Given that a "web app" can (and often does) fake "focus" handling through styling elements, it's really going to be inconsistent if we rely on firing events when we think focus changes..

On the other hand, it's not a great leap to propose document.setCommandState() to go with document.queryCommandState()..

Updated

3 years ago
Duplicate of this bug: 953389
Duplicate of this bug: 920405

Comment 33

3 years ago
For a more advanced app framework like Cappuccino, solution #3 would be the best solution. Whether Edit > Paste should be enabled or not is a dynamic state that changes throughout the life-time of the app and as the clipboard changes. Paste should be enabled if, and only if, something that can accept the type of data that is on the clipboard is the first responder and editable (Cocoa/Cappuccino terminology for 'being focused').

So for example, maybe there's a collection view showing images (imagine iPhoto for the web). When the collection view is the first responder (has focus), and is editable, and image data is on the clipboard, then we'd like the Edit > Paste menu item to be enabled.

Note that it is not sufficient to check for paste-ability when input focus changes, at least not for any definition of focus Firefox might be aware of -- a "Collection View" in Cappuccino is just a div. It doesn't "have focus" in an HTML sense. It's not content-editable.

Cappuccino could use setCommandState but this wouldn't be a perfect solution without the ability to react to clipboard mime-type changes too. As they change the app needs an opportunity to change its stance on paste-ability. Again, taking the iPhoto-web example, a text only clipboard would ideally disable pasting, but as soon as an image comes onto the clipboard, pasting should be enabled again.

So in the end the simplest solution is probably to just always ask the app for paste-ability when it looks like there's a chance of paste (Edit menu is opened, Cmd-V is pressed), through the beforePaste handler, which is existing technology.

Comment 34

3 years ago
This is what I've said from a bug that was closed as a dupe of this one:

It doesn't matter if the UA has got a button for pasting and it's disabled. Do you think lynx worries about that? The spec is pretty clear - fire the event. The concerns of things like toolbars are concerns of the UA and the UA alone.
I think you and others are getting confused into thinking that you can invoke that paste command with Ctrl+V all the time, and that the event should then fire. You cannot do that. When the paste command is disabled, there is presently no means to invoke it at all by any means, and it certainly shouldn't have different behaviour depending on how to the user invokes the paste (keyboard, middle click, menu,...) The spec doesn't mention how the user can invoke a paste, nor should it.

This is more clearer on Mac, where pressing Command+V when pasting is enabled will flash the Edit menu once, and pressing Command+V when pasting is disabled does not.

Fixing this bug requires either enabling the command all of time, or creating a means to indicate that the command needs to be enabled/disabled; this would be used for all ways that the command can be triggered.
(In reply to Neil Deakin from comment #35)
> I think you and others are getting confused into thinking that you can
> invoke that paste command with Ctrl+V all the time, and that the event
> should then fire. You cannot do that.

Indeed, and fixing this bug requires changing exactly this.

> Fixing this bug requires either enabling the command all of time, or
> creating a means to indicate that the command needs to be enabled/disabled;
> this would be used for all ways that the command can be triggered.

For menus, onbefore* events (with suitable event.clipboardData access to let you check data types on clipboard (but not actually read data)) takes care of it. So the problem is shortcut keys.

Do you think pressing ctrl-V in a non-editable context can/should be rigged to fire an onbeforepaste event, followed by a paste event only if the onbeforepaste event was cancelled?
If the beforepaste event is supported, then it needs to fire before the paste event. It should fire when the browser needs to determine that that pasting is enabled or disabled. Chrome and Safari fire beforepaste when the Paste menu command is selected and when the keyboard shortcut is pressed.

In Firefox, we assume that this state will need to be updated whenever the focus changes, the selection changes, or the clipboard changes. We don't support the before events, but our equivalent mechanism is checked at these three points. Some hackery is performed on Windows/Linux to lazily check this state only when the clipboard toolbar items are visible, a menu opens or the keyboard shortcut is pressed, and perform the 'before' checks only then.
 
Whether the content is editable has no bearing on the events.

Comment 38

a year ago
This is one of the most glaring bikeshedding threads I ever read. Yes, when a user presses Ctrl+V, you should fire an event - as long as there's anything in clipboard at all. Just the same as now you show active "Paste" in a context menu as long as there's anything in clipboard at all - for user to click it, and nothing to happen. Because your broken browser doesn't fire an event.

Well, what to do if a page doesn't expect a context type currently in the clipboard? Or my god, nobody knows - let's call a pundit committee to sit on that for next couple of years! No wait, it's crystal clear what do do - a handler should check type of the content and - unbelievable! - not do anything on content it doesn't expect. Of course, in a real programming environment, one might want to do better than that. But there's no real programming environment - there's that proverbial "web". There's no real programming language - only "javascript". People got used that this stuff stays broken for years, it's slow, it crashes, and it all gets worse year after year. So they certainly will forgive you for saving them from bunch of pre-, post-, instead-, and uturn- events to be fired with.
Nice rant, Sir :)

You're quite right though: decision making is taking too long here.

Shall we apply the 80/20 rule and simply say always enabling the commands likely handles 80% of the use cases, then decide on and implement some finer controls later if there's web developer demand for it? 

Due to pushback I'm considering dropping onbefore* events from the spec anyway. If we ship always-enabled without onbefore* and web developers don't demand this functionality it's a good simplification and one "wart" less..
Enabling paste (and cut and copy) all the time would be fine from the Cappuccino point of view. 

If we had the onbefore* events we could use them to provide proper UI feedback such as Edit > Paste greying out, if what you have in the clipboard can't be pasted in the current UI state of the web app (which is opaque to the web browser). It's a "nice to have" and would bring web apps one step closer to parity with desktop apps in UI fidelity.

If we don't have the events, we'd  be grateful and happy for an "always on" behaviour. It'd be a big step forward.

(It would need to be literally always - focus, editability and so on as the browser understands would need to be immaterial.)
What about cut and copy - should these always be enabled too?
Depends on: 1249759
Cut and copy were made always on for html documents in bug 1012662. There may have been some reason to not to do this for paste. Let's ask.
Flags: needinfo?(michael)
Duplicate of this bug: 1208217
Per https://bugzilla.mozilla.org/show_bug.cgi?id=1159490 and https://bugzilla.mozilla.org/show_bug.cgi?id=1208217 it seems like Michael just didn't get to it..
(In reply to Hallvord R. M. Steen [:hallvors] from comment #41)
> What about cut and copy - should these always be enabled too?

For Cappuccino's purposes yes, for the same reason: the user might want to copy things Firefox doesn't know can be copied. 

For example the user might select a few rows from a table to copy, but as far as Firefox can tell there is nothing selected -- the concept of selected table rows is an application level one, not HTML/DOM level.

Updated

a year ago
Depends on: 1208217
(In reply to Hallvord R. M. Steen [:hallvors] from comment #44)
> Per https://bugzilla.mozilla.org/show_bug.cgi?id=1159490 and
> https://bugzilla.mozilla.org/show_bug.cgi?id=1208217 it seems like Michael
> just didn't get to it..

Yup - that seems about right. I believe that this was my first patch, and I was very focused cut/copy and tried to not change paste.
Flags: needinfo?(michael)

Comment 47

7 months ago
Hi, any news on this?

I still experience the issue of middle-click paste not working with Sourceforge (which uses CodeMirror as the rich text editor for the issue tracker) and Firefox 49.

Should there be changes in CodeMirror after this has been fixed in Firefox?

Thanks,
   Antonio

Comment 48

3 months ago
Using Jira 7.x as my test case, the issue happened in FF 47.., but is no longer happening in FF 51.0.1 32 bit on Windows 7 Pro x64.

Comment 49

3 months ago
This bug has been fixed by Bug 1208217:
https://hg.mozilla.org/integration/mozilla-inbound/pushloghtml?fromchange=abddf7ccee3b92751cc133a231d81dd7f01684e0&tochange=0d5cc353d9e014cba6dcc90cff10b7c2c17df5ea


Coud we close it as fixed?
Flags: needinfo?(michael)
It looks to me like we can :).
Status: NEW → RESOLVED
Last Resolved: 3 months ago
Flags: needinfo?(michael)
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.