3
$('#sometextarea')
    .change(function(){console.log($(this).val());})
    [0].onpaste=function(){
        var self=$(this);
        var intr=setInterval(function(){
            if(self.val().length) {
                clearInterval(intr);
                self.blur();                                                                    
            }
        },10);                          
    }

onpaste doesn't work in Opera.

Can someone suggest better solution for this task?

Because I don't like that I have to use setInterval/setTimeout and emulate change event. Because if using triggerHandler('change') causes second event triggering on user blur, don't know why actually, it shouldn't by idea, because data isn't changed after first triggerHandler('change')

Need a solution to capture val() before user exits textarea, mouse paste should be captured as well.

Marcel Korpel
  • 21,536
  • 6
  • 60
  • 80
Somebody
  • 9,316
  • 26
  • 94
  • 142
  • Yea i guess it's the only workaround. Could you post it as an answer to this topic so i could accept it? – Somebody Jun 10 '11 at 12:37

2 Answers2

2

I know this is little late to the party, but I've been working on capturing paste events in the browser. I'm still working on the code but what I have so far is at http://jsfiddle.net/JgU37/42/.

the gist of the code is below:

$(document).ready(function() {
    // Fake paste
    var doFakePaste = false;
    $(document).on('keydown', function(e) {
        $('#status').html('metaKey: ' + e.metaKey + 
                          ' ctrlKey: ' + e.ctrlKey + 
                          ' which: ' + e.which);

        // These browser work with the real paste event
        if ($.client.browser === "Chrome")
            return;
        if ($.client.os === "Windows" && $.client.browser === "Safari")
            return;

        // Check for patse keydown event
        if (!doFakePaste &&
            ($.client.os === "Mac" && e.which == 86 && e.metaKey) ||
            ($.client.os !== "Mac" && e.which == 86 && e.ctrlKey)) {
            doFakePaste = true;
            // got a paste
            if (!$("*:focus").is("input") &&
                !$("*:focus").is("textarea")) {
                $('#status').html('fake paste');

                // Focus the offscreen editable
                $('#TribblePaste').focus();

                // Opera doesn't support onPaste events so we have
                // to use a timeout to get the paste
                if ($.client.browser === "Opera")
                {
                    setTimeout(function() {
                        doFakePaste = false;
                        var html = $('#TribblePaste').html();
                        var text = $('#TribblePaste').text();
                        if (text == '') text = $('#TribblePaste').val();
                        $('#resultA').text('[o] '+html);
                        $('#resultB').text('[o] '+text);
                        $('#TribblePaste').val('');
                        $('#TribblePaste').text('');
                        $('#TribblePaste').blur();
                    }, 1);
                }
            }
        }
    }).on('paste', function (e) {
        // Firefox is not supported - they don't
        // expose the real clipboard
        if ($.client.browser === 'Firefox')
            return;

        $('#status').html('paste event');

        // real pasteing
        var html = '';
        var text = '';
        if (window.clipboardData) // IE
        {  
            text = window.clipboardData.getData("Text");
        }
        if (e.clipboardData && e.clipboardData.getData) // Standard
        {
            text = e.clipboardData.getData('text/plain');
            text = e.clipboardData.getData('text/html');
        }
        if (e.originalEvent.clipboardData &&
            e.originalEvent.clipboardData.getData) // jQuery
        {
            text = e.originalEvent.clipboardData.getData('text/plain');
            html = e.originalEvent.clipboardData.getData('text/html');
        }
        $('#resultA').text(html);
        $('#resultB').text(text);
    });

    // Setup the offscreen paste capture area
    $('<textarea contenteditable id="TribblePaste"></textarea>').css({
        'position': 'absolute',
        'top': '-100000px',
        'width': '100px',
        'height': '100px'
    }).on('paste', function(e) {
        setTimeout(function() {
            doFakePaste = false;
            var html = $('#TribblePaste').html();
            var text = $('#TribblePaste').text();
            if (text == '') text = $('#TribblePaste').val();
            $('#resultA').text(html);
            $('#resultB').text(text);
            $('#TribblePaste').val('');
            $('#TribblePaste').text('');
            $('#TribblePaste').blur();
        }, 1);
    }).appendTo('body');

    $('#data').html('os: ' + $.client.os + ' browser: ' + $.client.browser);
});
Justin808
  • 20,859
  • 46
  • 160
  • 265
1

You can't, it's simply not supported. The only workaround I can think of, is using setInterval to detect these kind of changes.

Marcel Korpel
  • 21,536
  • 6
  • 60
  • 80