title: How should I crop an image at client side using jcrop and upload it?
body: <p>I am working on a component in which there is file-upload HTML control, upon selecting an image using the file-upload element, the image would be rendered on the HTML5 Canvas element.</p>
  <p>Here is JSFiddle with sample code:  <a href="https://jsfiddle.net/govi20/spmc7ymp/" rel="nofollow noreferrer">https://jsfiddle.net/govi20/spmc7ymp/</a></p>
  <p><strong>id=target</strong> =&gt;  selector for jcrop element<br />
  <strong>id=photograph</strong> =&gt;  selector for fileupload element <br />
  <strong>id=preview</strong> =&gt; selector for canvas element<br />
  <strong>id=clear_selection</strong>  =&gt; selector for a button which would clear the canvas</p>
  <p>Third-party JS libraries used:</p>
  <pre><code>&lt;script src=&quot;./js/jquery.min.js&quot;&gt;&lt;/script&gt;
  &lt;script src=&quot;./js/jquery.Jcrop.js&quot;&gt;&lt;/script&gt;
  &lt;script src=&quot;./js/jquery.color.js&quot;&gt;&lt;/script&gt;
  </code></pre>
  <p>Setting up the JCrop:</p>
  <pre><code>&lt;script type=&quot;text/javascript&quot;&gt;
  
  jQuery(function($){
   
  var api;
  
  $('#target').Jcrop({
    // start off with jcrop-light class
    bgOpacity: 0.5,
    keySupport: false,
    bgColor: 'black',
    minSize:[240,320],
    maxSize:[480,640],
    onChange : updatePreview,
    onSelect : updatePreview, 
    height:160,
    width:120,
    addClass: 'jcrop-normal'
  },function(){
    api = this;
    api.setSelect([0,0,240,320]);
    api.setOptions({ bgFade: true });
    api.ui.selection.addClass('jcrop-selection');
    });
  
  });
  </code></pre>
  <p>clear canvas event which will be triggered on clear button click event:</p>
  <pre><code>jQuery('#clear_selection').click(function(){
    $('#target').Jcrop({    
        
        setSelect: [0,0,0,0],
      });
  });
  </code></pre>
  <p>code that renders image on HTML5 Canvas:</p>
  <pre><code>function readURL(input) {
      
      if (input.files &amp;&amp; input.files[0]) {
          var reader = new FileReader();
          reader.onload = function (e) {
              $('#target').attr('src', e.target.result);
              setProperties();       
          }
          reader.readAsDataURL(input.files[0]);
      }
  }
  
  function setProperties(){
     $('#target').Jcrop({         
                setSelect: [0,0,240,320]
          }); 
  }
  $(&quot;#photograph&quot;).change(function(){
      readURL(this);     
  });
  </code></pre>
  <p>code to crop and render an image on the canvas:</p>
  <pre><code>    var canvas = document.getElementById('preview'),
      context = canvas.getContext('2d');
  
      make_base();
      function updatePreview(c) {
          console.log(&quot;called&quot;);
          if(parseInt(c.w) &gt; 0) {
              // Show image preview
              var imageObj = $(&quot;#target&quot;)[0];
              var canvas = $(&quot;#preview&quot;)[0];
              var context = canvas.getContext(&quot;2d&quot;);
              context.drawImage(imageObj, c.x, c.y, c.w, c.h, 0, 0, canvas.width, canvas.height);
          }
      };
  
      function make_base() {
          console.log(&quot;make_base called&quot;);
          var base_image = new Image();
          base_image.src = '';
          base_image.onload = function () {
              context.drawImage(base_image, 0, 0);
          }
      }
  </code></pre>
  <p>Here are a bunch of issues I am facing with the above setup:</p>
  <ol>
  <li>updatePreview function is not getting called on selection, hence the canvas is not getting rendered.</li>
  <li>crop selection box is not draggable (I am using bootstrap CSS, I suspect it is due to missing/mismatching dependency).</li>
  <li>Canvas is <code>HTML5</code> element, which means the end-user must have an <code>HTML5</code> compatible browser, I am working on an app that has millions of users. Forcing users to use the latest browser is not a feasible option. What should be the fallback mechanism here?</li>
  </ol>