The problem here is that the image loading for firefox needs typically have the correct size already before moving on to the next step. And the modal needs to exist for the canvas to be attached to that.
https://jsfiddle.net/a0e5dt98/
$(document).on("change", "#photograph", function() {
$(this).replaceWith('<input id="photograph" type="file" class="form-control">');
$("#picCrop").modal('show');
loadImage(this);
});
$('#picCrop').on('shown.bs.modal', function(e) {
validateImage();
})
Then it calls loadImage from the selection of the image. Then validates that image on the loading of the modal which will affix it to the now existing div. This does assume that the imageLoad takes less time than the modal loading. In theory you might be able to load a large enough image locally that it can't validate the unloaded image.
Then dividing up the validate and the affix again, so that firefox can get the sizes correctly.
function validateImage() {
console.log("validateimage.")
if (canvas != null) {
image = new Image();
image.onload = affixJcrop;
image.src = canvas.toDataURL('image/png');
} else affixJcrop();
}
function affixJcrop() {
console.log("affixJcrop")
if (jcrop_api != null) {
jcrop_api.destroy();
}
$("#views").empty();
$("#views").append("<canvas id=\"canvas\">");
canvas = $("#canvas")[0];
context = canvas.getContext("2d");
console.log(image.width);
console.log(image.height);
canvas.width = image.width;
canvas.height = image.height;
context.drawImage(image, 0, 0);
$("#canvas").Jcrop({
onSelect: selectcanvas,
onRelease: clearcanvas,
boxWidth: crop_max_width,
boxHeight: crop_max_height,
minSize: [100, 100],
setSelect: [0, 0, 100, 100]
}, function() {
jcrop_api = this;
});
clearcanvas();
}