/* * JavaScript Load Image Demo JS * https://github.com/blueimp/JavaScript-Load-Image * * Copyright 2013, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: * https://opensource.org/licenses/MIT */ /* global loadImage, $ */ $(function () { 'use strict' var resultNode = $('#result') var metaNode = $('#meta') var thumbNode = $('#thumbnail') var actionsNode = $('#actions') var orientationNode = $('#orientation') var imageSmoothingNode = $('#image-smoothing') var fileInputNode = $('#file-input') var urlNode = $('#url') var editNode = $('#edit') var cropNode = $('#crop') var cancelNode = $('#cancel') var coordinates var jcropAPI /** * Displays tag data * * @param {*} node jQuery node * @param {object} tags Tags map * @param {string} title Tags title */ function displayTagData(node, tags, title) { var table = $('
') var row = $('') var cell = $('') var headerCell = $('') var prop table.append(row.clone().append(headerCell.clone().text(title))) for (prop in tags) { if (Object.prototype.hasOwnProperty.call(tags, prop)) { if (typeof tags[prop] === 'object') { displayTagData(node, tags[prop], prop) continue } table.append( row .clone() .append(cell.clone().text(prop)) .append(cell.clone().text(tags[prop])) ) } } node.append(table).show() } /** * Displays the thumbnal image * * @param {*} node jQuery node * @param {string} thumbnail Thumbnail URL * @param {object} [options] Options object */ function displayThumbnailImage(node, thumbnail, options) { if (thumbnail) { var link = $('') .attr('href', loadImage.createObjectURL(thumbnail)) .attr('download', 'thumbnail.jpg') .appendTo(node) loadImage( thumbnail, function (img) { link.append(img) node.show() }, options ) } } /** * Displays metadata * * @param {object} [data] Metadata object */ function displayMetaData(data) { if (!data) return metaNode.data(data) var exif = data.exif var iptc = data.iptc if (exif) { var thumbnail = exif.get('Thumbnail') if (thumbnail) { displayThumbnailImage(thumbNode, thumbnail.get('Blob'), { orientation: exif.get('Orientation') }) } displayTagData(metaNode, exif.getAll(), 'TIFF') } if (iptc) { displayTagData(metaNode, iptc.getAll(), 'IPTC') } } /** * Removes meta data from the page */ function removeMetaData() { metaNode.hide().removeData().find('table').remove() thumbNode.hide().empty() } /** * Updates the results view * * @param {*} img Image or canvas element * @param {object} [data] Metadata object * @param {boolean} [keepMetaData] Keep meta data if true */ function updateResults(img, data, keepMetaData) { var isCanvas = window.HTMLCanvasElement && img instanceof HTMLCanvasElement if (!keepMetaData) { removeMetaData() if (data) { displayMetaData(data) } if (isCanvas) { actionsNode.show() } else { actionsNode.hide() } } if (!(isCanvas || img.src)) { resultNode .children() .replaceWith($('Loading image file failed')) return } var content = $('').append(img) resultNode.children().replaceWith(content) if (data.imageHead) { if (data.exif) { // Reset Exif Orientation data: loadImage.writeExifData(data.imageHead, data, 'Orientation', 1) } img.toBlob(function (blob) { if (!blob) return loadImage.replaceHead(blob, data.imageHead, function (newBlob) { content .attr('href', loadImage.createObjectURL(newBlob)) .attr('download', 'image.jpg') }) }, 'image/jpeg') } } /** * Displays the image * * @param {File|Blob|string} file File or Blob object or image URL */ function displayImage(file) { var options = { maxWidth: resultNode.width(), canvas: true, pixelRatio: window.devicePixelRatio, downsamplingRatio: 0.5, orientation: Number(orientationNode.val()) || true, imageSmoothingEnabled: imageSmoothingNode.is(':checked'), meta: true } if (!loadImage(file, updateResults, options)) { removeMetaData() resultNode .children() .replaceWith( $( '' + 'Your browser does not support the URL or FileReader API.' + '' ) ) } } /** * Handles drop and file selection change events * * @param {event} event Drop or file selection change event */ function fileChangeHandler(event) { event.preventDefault() var originalEvent = event.originalEvent var target = originalEvent.dataTransfer || originalEvent.target var file = target && target.files && target.files[0] if (!file) { return } displayImage(file) } /** * Handles URL change events */ function urlChangeHandler() { var url = $(this).val() if (url) displayImage(url) } // Show the URL/FileReader API requirement message if not supported: if ( window.createObjectURL || window.URL || window.webkitURL || window.FileReader ) { resultNode.children().hide() } else { resultNode.children().show() } $(document) .on('dragover', function (e) { e.preventDefault() if (event.dataTransfer) event.dataTransfer.dropEffect = 'copy' }) .on('drop', fileChangeHandler) fileInputNode.on('change', fileChangeHandler) urlNode.on('change paste input', urlChangeHandler) orientationNode.on('change', function () { var img = resultNode.find('img, canvas')[0] if (img) { updateResults( loadImage.scale(img, { maxWidth: resultNode.width() * (window.devicePixelRatio || 1), pixelRatio: window.devicePixelRatio, orientation: Number(orientationNode.val()) || true, imageSmoothingEnabled: imageSmoothingNode.is(':checked') }), metaNode.data(), true ) } }) editNode.on('click', function (event) { event.preventDefault() var imgNode = resultNode.find('img, canvas') var img = imgNode[0] var pixelRatio = window.devicePixelRatio || 1 var margin = img.width / pixelRatio >= 140 ? 40 : 0 imgNode // eslint-disable-next-line new-cap .Jcrop( { setSelect: [ margin, margin, img.width / pixelRatio - margin, img.height / pixelRatio - margin ], onSelect: function (coords) { coordinates = coords }, onRelease: function () { coordinates = null } }, function () { jcropAPI = this } ) .parent() .on('click', function (event) { event.preventDefault() }) }) cropNode.on('click', function (event) { event.preventDefault() var img = resultNode.find('img, canvas')[0] var pixelRatio = window.devicePixelRatio || 1 if (img && coordinates) { updateResults( loadImage.scale(img, { left: coordinates.x * pixelRatio, top: coordinates.y * pixelRatio, sourceWidth: coordinates.w * pixelRatio, sourceHeight: coordinates.h * pixelRatio, maxWidth: resultNode.width() * pixelRatio, contain: true, pixelRatio: pixelRatio, imageSmoothingEnabled: imageSmoothingNode.is(':checked') }), metaNode.data(), true ) coordinates = null } }) cancelNode.on('click', function (event) { event.preventDefault() if (jcropAPI) { jcropAPI.release() jcropAPI.disable() } }) })