views:

7268

answers:

9

I'm looking for a way to sanitize input that I paste into the browser, is this possible to do with jQuery?

I've managed to come up with this so far:

$(this).live(pasteEventName, function(e) {
 // this is where i would like to sanitize my input
 return false;
}

Unfortunately my development has come to a screeching hold because of this "minor" issue. I would really make me a happy camper if someone could point me to the right direction.

Thanks in advance.

+1  A: 

Hmm... I think you can use e.clipboardData to catch the data being pasted. If it doesn't pan out, have a look here.

$(this).live("paste", function(e) {
    alert(e.clipboardData); // [object Clipboard]
});
moff
When I run this in Safari I get 'undefined' :(
Christoffer Winterkvist
A: 

See this example: http://www.p2e.dk/diverse/detectPaste.htm

It essentialy tracks every change with oninput event and then checks if it’s a paste by string comparison. Oh, and in IE there’s an onpaste event. So:

$ (something).bind ("input paste", function (e) {
    // check for paste as in example above and
    // do something
})
Ilya Birman
So it is impossible just to get the paste text when the event occurs?
Christoffer Winterkvist
Well, I guess you will have to deal with it yourself, like, compare the before and after. It has to be rather easy. But why don’t you just revalidate the whole input? Slow?
Ilya Birman
I just thought that would be possible to do but I guess not, Right now I'm trying another method by pasting it into a textarea and then transfering it to its final destination. I'm hoping that will work.
Christoffer Winterkvist
You just have to find the maximum matching fragment in the beginning of two strings (before and after). Everything from there and up to the lengths difference is the pasted text.
Ilya Birman
+3  A: 

This is getting closer to what you might want.

function sanitize(s) {
  return s.replace(/\bfoo\b/g, "~"); 
};

$(function() {
 $(":text, textarea").bind("input paste", function(e) {
   try {
     clipboardData.setData("text",
       sanitize(clipboardData.getData("text"))
     );
   } catch (e) {
     $(this).val( sanitize( $(this).val() ) );
   }
 });
});

Please note that when clipboardData object is not found (on browsers other then IE) you are currently getting the element's full value + the clipboard'ed value.

You can probably do some extra steps to dif the two values, before an input & after the input, if you really are only after what data was truly pasted into the element.

Mister Lucky
+1  A: 

I sort of fixed it by using the following code:

$("#editor").live('input paste',function(e){
    if(e.target.id == 'editor') {
     $('<textarea></textarea>').attr('id', 'paste').appendTo('#editMode');
     $("#paste").focus();
     setTimeout($(this).paste, 250);
    }
});

Now I just need to store the caret location and append to that position then I'm all set... I think :)

Christoffer Winterkvist
A: 

This proved to be quite illusive. The value of the input is not updated prior to the execution of the code inside the paste event function. I tried calling other events from within the paste event function but the input value is still not updated with the pasted text inside the function of any events. That is all events apart from keyup. If you call keyup from within the paste event function you can sanitize the pasted text from within the keyup event function. like so...

$(':input').live
(
    'input paste',
    function(e)
    {
        $(this).keyup();
    }
);

$(':input').live
(
    'keyup',
    function(e)
    {
        // sanitize pasted text here
    }
);

There is one caveat here. In Firefox, if you reset the input text on every keyup, if the text is longer than the viewable area allowed by the input width, then resetting the value on every keyup breaks the browser functionality that auto scrolls the text to the caret position at the end of the text. Instead the text scrolls back to the beginning leaving the caret out of view.

+6  A: 

OK, just bumped into the same issue.. I went around the gipsy way (as my collegue is always making fun of me heheh..)

$(".inputTextArea").bind('paste', function(e) {
 var el = $(this);
 setTimeout(function() {
     var text = $(el).val();
     alert(text);
 }, 100);
});

Just a small timeout till .val() func can get populated.

E.

Evgeni Dimov
A: 

There is one caveat here. In Firefox, if you reset the input text on every keyup, if the text is longer than the viewable area allowed by the input width, then resetting the value on every keyup breaks the browser functionality that auto scrolls the text to the caret position at the end of the text. Instead the text scrolls back to the beginning leaving the caret out of view.

function scroll(elementToBeScrolled) 
{
     //this will reset the scroll to the bottom of the viewable area. 
     elementToBeScrolled.topscroll = elementToBeScrolled.scrollheight;
}
lordcheeto
A: 

I'd like to add a small piece of information for you guys out there using setTimeout(code,250). A small trick I have learned is to use a setTimeout delay of 0, this sends the function to the bottom of the rendering stack, allows the text to be added to the textbox then executes the code. (If you need this functionality) I have tested this in ie 7/8 and firefox and seems to work for both.It avoids having to use arbitrary timeout delays

Sharif
+1  A: 

Listen for the paste event and set a keyup event listener. On keyup, capture the value and remove the keyup event listener.

$('.inputTextArea').bind('paste', function (e){
    $(e.target).keyup(getInput);
});
function getInput(e){
    var inputText = $(e.target).val();
    $(e.target).unbind('keyup');
}
Eric