Firefox ONPASTE: Get the text to be pasted?

781 views
Skip to first unread message

Jim Douglas

unread,
Feb 12, 2010, 2:38:15 PM2/12/10
to Google Web Toolkit
I'm in the process of implementing a text control from Swing
(JFormattedTextField) to GWT. One of the requirements is that when
the user pastes in a block of text, I can't just let the default
action occur; I have to filter the text through a mask. Given that
requirement, I need to be able to intercept the text the user is about
to paste into a TextBox.

I've got a solution that seems to be working perfectly in IE and
WebKit (Chrome/Safari). There's an open Mozilla bug requesting this
feature (https://bugzilla.mozilla.org/show_bug.cgi?id=407983), but
it's not clear when it will be resolved.

Here's what I have so far, plugged in to the StockWatcher sample app
for ease of testing. Does anyone know of a reliable way to make this
work in Firefox?

(1) Create the nameField TextBox like this:

final TextBox nameField = new TextBox()
{
@Override
public void onBrowserEvent(Event event)
{
super.onBrowserEvent(event);
switch (event.getTypeInt())
{
case Event.ONPASTE:
{
event.preventDefault();
String text = getPastedText(event);
if (text.length() > 0)
{
Window.alert("Pasted: "+text);
}
break;
}
}
}
};
nameField.sinkEvents(Event.ONPASTE);

(2) Add this methodt:

public static native String getPastedText(Event event)
/*-{

var text = "";

if (event.clipboardData) // WebKit/Chrome/Safari
{
try
{
text = event.clipboardData.getData("Text");
return text;
}
catch (e)
{
// Hmm, that didn't work.
}
}

if ($wnd.clipboardData) // IE
{
try
{
text = $wnd.clipboardData.getData("Text");
return text;
}
catch (e)
{
// Hmm, that didn't work.
}
}

// Ok, last chance. Firefox refuses to make this easy:
// https://bugzilla.mozilla.org/show_bug.cgi?id=407983
// And this ridiculous approach is unlikely to work.
// But try it anyway; we have nothing to lose.
// We can ignore Opera; it doesn't even fire ONPASTE.

try
{
if (netscape.security.PrivilegeManager.enablePrivilege)
{

netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
}
else
{
return "";
}
}
catch (ex)
{
return "";
}

var clip = Components.classes["@mozilla.org/widget/clipboard;
1"].getService(Components.interfaces.nsIClipboard);
if (!clip) return "";

var trans = Components.classes["@mozilla.org/widget/
transferable;
1"].createInstance(Components.interfaces.nsITransferable);
if (!trans) return "";

trans.addDataFlavor("text/unicode");
clip.getData(trans, clip.kGlobalClipboard);

var str = new Object();
var strLength = new Object();

trans.getTransferData("text/unicode", str, strLength);
if (str) str =
str.value.QueryInterface(Components.interfaces.nsISupportsString);
if (str) text = str.data.substring(0, strLength.value / 2);

return text;

}-*/;

mike b

unread,
Jan 31, 2011, 3:18:08 PM1/31/11
to google-we...@googlegroups.com
Thanks for posting this!  Very helpful!  I did variation on the theme. 

I created a class called XTextBox (and XTextArea) which catches the ONPASTE and then fires the ValueChangedEvent. This is useful because all I need to do is call the textBox.addValueChangeHandler(aHandler)  in my presenter class. 

public class XTextBox extends TextBox  {

    public XTextBox() {
        super();
       
        this.sinkEvents(Event.ONPASTE);
    }
   
   
    /**
     * Catch ONPASTE and re-throw it as a ValueChangeEvent
     *
     */

   
    @Override
    public void onBrowserEvent(Event event) {
        super.onBrowserEvent(event);
        switch (event.getTypeInt()) {
            case Event.ONPASTE: {
                String newValue = null;  // get the pasted value here!!!
                this.setValue(newValue, true);
                break;
            }
        }
    }

}

mike b

unread,
Feb 3, 2011, 4:40:08 PM2/3/11
to google-we...@googlegroups.com
On second thought...

Change this line -> this.setValue(newValue, true);

To this -->  ValueChangeEvent.fireIfNotEqual(this, this.getValue(), newValue);


Reply all
Reply to author
Forward
0 new messages