30

Hi i am creating an web chat application in that i want user can copy paste the image from desktop or can paste directly the screen shot but i am unable to achieve it. I used following code:

$("#dummy").on("paste",function(event){

var items = (event.clipboardData ||   event.originalEvent.clipboardData).items;
console.log(JSON.stringify(items)); // will give you the mime types
for (index in items) {
    var item = items[index];
    if (item.kind === 'file') {
        var blob = item.getAsFile();
        var reader = new FileReader();
        reader.onload = function(event){
            console.log(event.target.result)}; // data url!
        reader.readAsDataURL(blob);
    }
}

})

using the above code in Chrome and Firefox i am getting Clipboarddata undefined in case of image. I tried lots of links on google but not able to reach the target. I also tried below link from stackoverflow: Paste an image from clipboard using JavaScript also the below link:

http://strd6.com/2011/09/html5-javascript-pasting-image-data-in-chrome/

http://codepen.io/netsi1964/pen/IoJbg

can any one help me with complete example how to achieve It?

Community
  • 1
  • 1
pareshm
  • 4,874
  • 5
  • 35
  • 53
  • Have you noticed, that you've missed a semicolon at the end? –  Feb 19 '16 at 06:59
  • If you use the divs id, your code works. – Sascha Feb 23 '16 at 06:05
  • Please can you add working fiddle or code pen the code only works with Printscreen coping the desktop image doesnot works – pareshm Feb 23 '16 at 08:32
  • A combined version, using the code from @pareshm for Chrome and my code for Firefox may be found in this updated fiddle https://jsfiddle.net/SaschaKluth/togafu5s/1/ (Tested with clipboard content created via system screendump by ctrl+print and copy image part from gimp) – Sascha Feb 23 '16 at 11:18

2 Answers2

24

Demo

Works on latest chrome/firefox. Chrome implementation is simple. Firefox has restrictions that user must give command to do paste like keyboard event and editable input must be focused, so we do tricks here - on ctrl down we focusthat input field, on release unfocus.

HTML:

<canvas style="border:1px solid grey;" id="my_canvas" width="300" height="300"></canvas>

JS:

var CLIPBOARD = new CLIPBOARD_CLASS("my_canvas", true);

/**
 * image pasting into canvas
 * 
 * @param string canvas_id canvas id
 * @param boolean autoresize if canvas will be resized
 */
function CLIPBOARD_CLASS(canvas_id, autoresize) {
    var _self = this;
    var canvas = document.getElementById(canvas_id);
    var ctx = document.getElementById(canvas_id).getContext("2d");
    var ctrl_pressed = false;
    var reading_dom = false;
    var text_top = 15;
    var pasteCatcher;
    var paste_mode;

    //handlers
    document.addEventListener('keydown', function (e) {
        _self.on_keyboard_action(e);
    }, false); //firefox fix
    document.addEventListener('keyup', function (e) {
        _self.on_keyboardup_action(e);
    }, false); //firefox fix
    document.addEventListener('paste', function (e) {
        _self.paste_auto(e);
    }, false); //official paste handler

    //constructor - prepare
    this.init = function () {
        //if using auto
        if (window.Clipboard)
            return true;

        pasteCatcher = document.createElement("div");
        pasteCatcher.setAttribute("id", "paste_ff");
        pasteCatcher.setAttribute("contenteditable", "");
        pasteCatcher.style.cssText = 'opacity:0;position:fixed;top:0px;left:0px;';
        pasteCatcher.style.marginLeft = "-20px";
        pasteCatcher.style.width = "10px";
        document.body.appendChild(pasteCatcher);
        document.getElementById('paste_ff').addEventListener('DOMSubtreeModified', function () {
            if (paste_mode == 'auto' || ctrl_pressed == false)
                return true;
            //if paste handle failed - capture pasted object manually
            if (pasteCatcher.children.length == 1) {
                if (pasteCatcher.firstElementChild.src != undefined) {
                    //image
                    _self.paste_createImage(pasteCatcher.firstElementChild.src);
                }
            }
            //register cleanup after some time.
            setTimeout(function () {
                pasteCatcher.innerHTML = '';
            }, 20);
        }, false);
    }();
    //default paste action
    this.paste_auto = function (e) {
        paste_mode = '';
        pasteCatcher.innerHTML = '';
        var plain_text_used = false;
        if (e.clipboardData) {
            var items = e.clipboardData.items;
            if (items) {
                paste_mode = 'auto';
                //access data directly
                for (var i = 0; i < items.length; i++) {
                    if (items[i].type.indexOf("image") !== -1) {
                        //image
                        var blob = items[i].getAsFile();
                        var URLObj = window.URL || window.webkitURL;
                        var source = URLObj.createObjectURL(blob);
                        this.paste_createImage(source);
                    }
                }
                e.preventDefault();
            }
            else {
                //wait for DOMSubtreeModified event
                //https://bugzilla.mozilla.org/show_bug.cgi?id=891247
            }
        }
    };
    //on keyboard press - 
    this.on_keyboard_action = function (event) {
        k = event.keyCode;
        //ctrl
        if (k == 17 || event.metaKey || event.ctrlKey) {
            if (ctrl_pressed == false)
                ctrl_pressed = true;
        }
        //c
        if (k == 86) {
            if (document.activeElement != undefined && document.activeElement.type == 'text') {
                //let user paste into some input
                return false;
            }

            if (ctrl_pressed == true && !window.Clipboard)
                pasteCatcher.focus();
        }
    };
    //on kaybord release
    this.on_keyboardup_action = function (event) {
        k = event.keyCode;
        //ctrl
        if (k == 17 || event.metaKey || event.ctrlKey || event.key == 'Meta')
            ctrl_pressed = false;
    };
    //draw image
    this.paste_createImage = function (source) {
        var pastedImage = new Image();
        pastedImage.onload = function () {
            if(autoresize == true){
                //resize canvas
                canvas.width = pastedImage.width;
                canvas.height = pastedImage.height;
            }
            else{
                //clear canvas
                ctx.clearRect(0, 0, canvas.width, canvas.height);
            }
            ctx.drawImage(pastedImage, 0, 0);
        };
        pastedImage.src = source;
    };
}

Safari doesn't implement DataTransfer.items, so there's no way to extract image data (i.e. a screenshot copied to the clipboard) in Javascript. You can get copied files, but not data.

[From stakeoverflow post]

Mayur Patel
  • 1,741
  • 15
  • 32
  • Its working with only Print screen its not working with the copying image from Desktop and pasting on canvas... :( – pareshm Feb 23 '16 at 14:38
  • Its working properly for me. I have tested it in Firefox by Copy from Desctop and paste. What is your firefox version? – Mayur Patel Feb 23 '16 at 14:43
  • @MayurPatel : It only works in Firefox but not on Chrome browser copy from Desktop and paste can you try on Chrome.... – pareshm Feb 24 '16 at 04:32
  • Nope i am working on it but still not getting exact solution that worked in chrome. May be google chrome is not allowing it to paste from desktop's clipboard data. But never give up!! :) If i get solution i will surely let you know – Mayur Patel Feb 29 '16 at 06:39
  • when i checked var items = e.clipboardData.items in firefox it works properly but same thing in chrome items[0] is getting Undefined in my latest chrome browser this is preventing it from paste – Mayur Patel Mar 01 '16 at 08:33
  • I think chrome is preventing clipboard data for security reason – Mayur Patel Mar 02 '16 at 11:05
  • how would this script be if jquery will be used for example –  Nov 13 '17 at 18:15
-3

Chrome

Add your code to he code from codepen and give an id to the div (line 50)

Include your script as posted above with the divs id

$("#one").on("paste", function (event) {

  var items = (event.clipboardData || event.originalEvent.clipboardData).items;
  console.log(JSON.stringify(items)); // will give you the mime types
  for (index in items) {
    var item = items[index];
    if (item.kind === 'file') {
      var blob = item.getAsFile();
      var reader = new FileReader();
      reader.onload = function (event) {
        console.log(event.target.result)
      }; // data url!
      reader.readAsDataURL(blob);
    }
  }

})

Make a screenshot, select the first div (that one with the id one), hit ctrl+v, the screenshot appears in the div and the imagedata is loged to console.

Firefox Use the code I prepeared you within this fiddle

fiddle

<html>
<head>
  <meta charset="utf-8">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
  <style>
    #one {
      border: 1px solid black;
      min-height: 100px;
      min-width: 100px;
    }
  </style>
</head>

<body>
  Copy image from clipboard in Firefox.
  <br /> Select the box below and paste a image from clipboard via ctrl+v
  <br /> Data printed at console
  <br />
  <div id="one" contenteditable="true"></div>

  <script>
    $(function () {
      $("#one").bind("input paste", function (ev) {
        window.setTimeout(function (ev) {
          var input = $("#one").children()[0].src;
          var s = input.split(',');
          var mime = s[0];
          var data = s[1];
          console.log(mime);
          console.log(data);
        }, 300);
      });
    });
  </script>
</body>

</html>

Chrome & Firefox combined

A combined version, using the code from @pareshm for Chrome and my code for Firefox may be found in this updated fiddle (Tested with clipboard content created via system screendump by ctrl+print and copy image part from gimp)

Sascha
  • 1,156
  • 9
  • 13
  • Uncomment/delet the snapshoot() call in line 137 to get rid of the undefined error – Sascha Feb 19 '16 at 09:41
  • But it will paste the screen shot I want to paste the image copied from desktop or any other computer location. – pareshm Feb 23 '16 at 05:56
  • The posted code of my answer works, execept that it will throw an error cause of the undefined snapshot function wich you'l have to add or remove its call to get rid of the error message – Sascha Feb 23 '16 at 06:04
  • I left the call in the code because it'll be the entrypoint for your extra funtionality – Sascha Feb 23 '16 at 06:08
  • It does not work with the image copied from Desktop and also fails to work in firefox gets undefined console.log(event.target.result) – pareshm Feb 23 '16 at 06:09