From ccbfcf2e662a31f8de0c228e8d8c7b8e5e9dd6dd Mon Sep 17 00:00:00 2001 From: onli Date: Thu, 8 May 2014 22:37:44 +0200 Subject: [PATCH] Finish uplaod resize function (#137) configurable, some fixes, polyfill for chrome --- include/tpl/config_local.inc.php | 7 + templates/2k11/admin/js/canvas-toBlob.js | 120 ++++++++++++++ templates/2k11/admin/media_upload.tpl | 3 +- .../2k11/admin/serendipity_editor.js.tpl | 146 +++++++++++------- templates/2k11/config.inc.php | 7 +- 5 files changed, 221 insertions(+), 62 deletions(-) create mode 100644 templates/2k11/admin/js/canvas-toBlob.js diff --git a/include/tpl/config_local.inc.php b/include/tpl/config_local.inc.php index 101ffb751..3cb18c07c 100644 --- a/include/tpl/config_local.inc.php +++ b/include/tpl/config_local.inc.php @@ -594,6 +594,13 @@ 'permission' => 'blogConfiguration', 'default' => ''), + array('var' => 'uploadResize', + 'title' => MEDIA_UPLOAD_RESIZE, + 'description' => MEDIA_UPLOAD_RESIZE_DESC, + 'type' => 'bool', + 'permission' => 'siteConfiguration', + 'default' => false), + array('var' => 'onTheFlySynch', 'title' => ONTHEFLYSYNCH, 'description' => ONTHEFLYSYNCH_DESC, diff --git a/templates/2k11/admin/js/canvas-toBlob.js b/templates/2k11/admin/js/canvas-toBlob.js new file mode 100644 index 000000000..8a3a8f7a3 --- /dev/null +++ b/templates/2k11/admin/js/canvas-toBlob.js @@ -0,0 +1,120 @@ +/* canvas-toBlob.js + * A canvas.toBlob() implementation. + * 2013-12-27 + * + * By Eli Grey, http://eligrey.com and Devin Samarin, https://github.com/eboyjr + * License: X11/MIT + * See LICENSE.md + */ + +/*global self */ +/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, + plusplus: true */ + +/*! @source http://purl.eligrey.com/github/canvas-toBlob.js/blob/master/canvas-toBlob.js */ + +(function(view) { +"use strict"; +var + Uint8Array = view.Uint8Array + , HTMLCanvasElement = view.HTMLCanvasElement + , canvas_proto = HTMLCanvasElement && HTMLCanvasElement.prototype + , is_base64_regex = /\s*;\s*base64\s*(?:;|$)/i + , to_data_url = "toDataURL" + , base64_ranks + , decode_base64 = function(base64) { + var + len = base64.length + , buffer = new Uint8Array(len / 4 * 3 | 0) + , i = 0 + , outptr = 0 + , last = [0, 0] + , state = 0 + , save = 0 + , rank + , code + , undef + ; + while (len--) { + code = base64.charCodeAt(i++); + rank = base64_ranks[code-43]; + if (rank !== 255 && rank !== undef) { + last[1] = last[0]; + last[0] = code; + save = (save << 6) | rank; + state++; + if (state === 4) { + buffer[outptr++] = save >>> 16; + if (last[1] !== 61 /* padding character */) { + buffer[outptr++] = save >>> 8; + } + if (last[0] !== 61 /* padding character */) { + buffer[outptr++] = save; + } + state = 0; + } + } + } + // 2/3 chance there's going to be some null bytes at the end, but that + // doesn't really matter with most image formats. + // If it somehow matters for you, truncate the buffer up outptr. + return buffer; + } +; +if (Uint8Array) { + base64_ranks = new Uint8Array([ + 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1 + , -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + , 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 + , -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 + , 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 + ]); +} +if (HTMLCanvasElement && !canvas_proto.toBlob) { + canvas_proto.toBlob = function(callback, type /*, ...args*/) { + if (!type) { + type = "image/png"; + } if (this.mozGetAsFile) { + callback(this.mozGetAsFile("canvas", type)); + return; + } + var + args = Array.prototype.slice.call(arguments, 1) + , dataURI = this[to_data_url].apply(this, args) + , header_end = dataURI.indexOf(",") + , data = dataURI.substring(header_end + 1) + , is_base64 = is_base64_regex.test(dataURI.substring(0, header_end)) + , blob + ; + if (Blob.fake) { + // no reason to decode a data: URI that's just going to become a data URI again + blob = new Blob + if (is_base64) { + blob.encoding = "base64"; + } else { + blob.encoding = "URI"; + } + blob.data = data; + blob.size = data.length; + } else if (Uint8Array) { + if (is_base64) { + blob = new Blob([decode_base64(data)], {type: type}); + } else { + blob = new Blob([decodeURIComponent(data)], {type: type}); + } + } + callback(blob); + }; + + if (canvas_proto.toDataURLHD) { + canvas_proto.toBlobHD = function() { + to_data_url = "toDataURLHD"; + var blob = this.toBlob(); + to_data_url = "toDataURL"; + return blob; + } + } else { + canvas_proto.toBlobHD = canvas_proto.toBlob; + } +} +}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this)); diff --git a/templates/2k11/admin/media_upload.tpl b/templates/2k11/admin/media_upload.tpl index 50148fd7d..ef0488939 100644 --- a/templates/2k11/admin/media_upload.tpl +++ b/templates/2k11/admin/media_upload.tpl @@ -91,4 +91,5 @@ - \ No newline at end of file + + \ No newline at end of file diff --git a/templates/2k11/admin/serendipity_editor.js.tpl b/templates/2k11/admin/serendipity_editor.js.tpl index 4623bb41b..8ce6a7269 100644 --- a/templates/2k11/admin/serendipity_editor.js.tpl +++ b/templates/2k11/admin/serendipity_editor.js.tpl @@ -1304,66 +1304,92 @@ $(function() { } // minify images before upload, approach taken from https://github.com/joelvardy/javascript-image-upload/ - // if ($('#uploadform').length > 0) { - // $('#uploadform').submit(function(event) { - // event.preventDefault(); - // $('.uploadform_userfile').each(function() { - // var files = this.files; - // for (var i = 0; i < files.length; i++) { - // var reader = new FileReader(); - // var file = files[i]; - // reader.onload = function(readerEvent) { - // var image = new Image(); - // image.onload = function (imageEvent) { - // // Resize image - // var canvas = document.createElement('canvas'), - // max_size = 1200, - // width = image.width, - // height = image.height; - // if (width > height) { - // if (width > max_size) { - // height *= max_size / width; - // width = max_size; - // } - // } else { - // if (height > max_size) { - // width *= max_size / height; - // height = max_size; - // } - // } - // canvas.width = width; - // canvas.height = height; - // canvas.getContext('2d').drawImage(image, 0, 0, width, height); - // var data = new FormData(); - // data.append('serendipity[action]', 'admin'); - // data.append('serendipity[adminModule]', 'media'); - // data.append('serendipity[adminAction]', 'add'); - // data.append('serendipity[token]', $('input[name*="serendipity[token]"]').val()); - // data.append('serendipity[target_filename][1]', file.name); - // canvas.toBlob(function(blob) { - // data.append('serendipity[userfile][1]', blob, file.name); - // var jqxhr = $.ajax({ - // type: 'post', - // url: $('#uploadform').attr('action'), - // data: data, - // cache: false, - // processData: false, - // contentType: false - // }).done(function(data) { - // alert('success'); - // }).fail(function(data) { - // alert("fail:" + data.statusText); - // }); - - // }, file.type); - // } - // image.src = readerEvent.target.result; - // } - // reader.readAsDataURL(file); - // } - // }); - // }); - // } + {if $uploadResize && ($maxImgWidth > 0 || $maxImgHeight > 0)} + if ($('#uploadform').length > 0) { + $('input[name="go_properties"]').hide(); + var progressIcon = document.createElement('span'); + progressIcon.className = 'icon-info-circled' + $('#uploadform').submit(function(event) { + event.preventDefault(); + $('.uploadform_userfile').each(function() { + var files = this.files; + for (var i = 0; i < files.length; i++) { + var reader = new FileReader(); + reader.file = files[i]; + reader.onload = function(readerEvent) { + var image = new Image(); + var file = this.file; + image.onload = function (imageEvent) { + var canvas = document.createElement('canvas'), + max_width = {if $maxImgWidth}{$maxImgWidth}{else}0{/if}, + max_height = {if $maxImgHeight}{$maxImgHeight}{else}0{/if}, + width = image.width, + height = image.height; + + if (max_width > 0 && width > max_width) { + height *= max_width / width; + width = max_width; + } + if (max_height > 0 && height > max_height) { + width *= max_height / height; + height = max_height; + } + + canvas.width = width; + canvas.height = height; + canvas.getContext('2d').drawImage(image, 0, 0, width, height); + var data = new FormData(); + data.append('serendipity[action]', 'admin'); + data.append('serendipity[adminModule]', 'media'); + data.append('serendipity[adminAction]', 'add'); + data.append('serendipity[token]', $('input[name*="serendipity[token]"]').val()); + data.append('serendipity[target_filename][1]', file.name); + var type = file.type; + if (type == "image/bmp") { + {* bmp is not supported *} + type = "image/png"; + data.append('serendipity[target_filename][1]', file.name.replace('.bmp', '.png')); + } + canvas.toBlob(function(blob) { + data.append('serendipity[userfile][1]', blob, file.name); + var progress = document.createElement('progress'); + var progressContainer = document.createElement('span'); + progressContainer.className = 'msg_notice'; + progress.max = 100; + progress.value = 0; + $(progressContainer).append(progressIcon); + progressContainer.innerHTML += file.name + ": " + $(progressContainer).append(progress); + $('.form_buttons').append(progressContainer); + $.ajax({ + type: 'post', + url: $('#uploadform').attr('action'), + data: data, + cache: false, + processData: false, + contentType: false, + xhrFields: { + onprogress: function (e) { + if (e.lengthComputable) { + progress.value = e.loaded / e.total * 100; + } + } + } + }).done(function(data) { + progress.value = 100; + }).fail(function(data) { + alert("fail:" + data.statusText); + }) + }, type); + } + image.src = readerEvent.target.result; + } + reader.readAsDataURL(reader.file); + } + }); + }); + } + {/if} // reopen detail element after spamblock action if ($('#serendipity_comments_list').length > 0 && window.location.hash && $('#' + window.location.hash.replace('#', '')).length > 0) { diff --git a/templates/2k11/config.inc.php b/templates/2k11/config.inc.php index 3b93bdabc..061c42e3b 100644 --- a/templates/2k11/config.inc.php +++ b/templates/2k11/config.inc.php @@ -112,7 +112,12 @@ function serendipity_plugin_api_pre_event_hook($event, &$bag, &$eventData, &$add switch ($eventData) { case 'admin/serendipity_editor.js': header('Content-Type: application/javascript'); - $data = array('token_url' => serendipity_setFormToken("url")); + global $serendipity; + $data = array( 'token_url' => serendipity_setFormToken("url"), + 'uploadResize' => $serendipity['uploadResize'], + 'maxImgWidth' => $serendipity['maxImgWidth'], + 'maxImgHeight' => $serendipity['maxImgHeight'] + ); echo serendipity_smarty_show('admin/serendipity_editor.js.tpl', $data); break; }