From 8b578243e8c0b09d026a40ac6a2f6ac17fcc4f5e Mon Sep 17 00:00:00 2001 From: Jared Hancock <jared@osticket.com> Date: Tue, 28 Apr 2015 22:12:30 -0500 Subject: [PATCH] redactor: Fix image paste+upload in Chrome --- include/ajax.draft.php | 4 +++ js/redactor-plugins.js | 73 +++++++++++++++++++++++++++++++----------- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/include/ajax.draft.php b/include/ajax.draft.php index e963605ad..5f36b4704 100644 --- a/include/ajax.draft.php +++ b/include/ajax.draft.php @@ -94,6 +94,10 @@ class DraftAjaxAPI extends AjaxController { )) ); + // Paste uploads in Chrome will have a name of 'blob' + if ($file[0]['name'] == 'blob') + $file[0]['name'] = 'screenshot-'.Misc::randcode(4); + if (isset($file[0]['tmp_name'])) { $ids = $draft->attachments->upload($file); } diff --git a/js/redactor-plugins.js b/js/redactor-plugins.js index 6aaeea3bd..19544786b 100644 --- a/js/redactor-plugins.js +++ b/js/redactor-plugins.js @@ -790,16 +790,35 @@ RedactorPlugins.imagepaste = function() { return true; this.$editor.on('paste.imagepaste', $.proxy(this.imagepaste.buildEventPaste, this)); + + // Capture the selection position every so often as Redactor seems to + // drop it when attempting an image paste before `paste` browser event + // fires + var that = this, + plugin = this.imagepaste; + setInterval(function() { + if (plugin.inpaste) + return; + plugin.offset = that.caret.getOffset() || plugin.offset; + }, 300); }, + offset: 0, + inpaste: false, buildEventPaste: function(e) { var event = e.originalEvent || e, fileUpload = false, files = [], i, file, - cd = event.clipboardData; + plugin = this.imagepaste, + cd = event.clipboardData, + self = this, node, + bail = function() { + plugin.inpaste = false; + }; + plugin.inpaste = true; - if (typeof(cd) === 'undefined') return; + if (typeof(cd) === 'undefined') return bail(); if (cd.items && cd.items.length) { @@ -824,23 +843,41 @@ RedactorPlugins.imagepaste = function() { } } } - var self = this, node; - this.opts.imageUploadCallback = function(image, json) { - // Redactor just has a bloody hard time inserting for some dumb - // reason. - }; - if (files.length) { - // clipboard upload - var I = setInterval(function() { - if (!self.focus.isFocused()) - return; - clearInterval(I); - self.clean.singleLine = false; - for (i = 0, k = files.length; i < k; i++) - self.upload.directUpload(files[i], e); - }, 5); - } + if (!files.length) + return bail(); + + // Clipboard upload + + setTimeout(function() { + // We need to allow the paste operation to settle, so we can set + // self.clean.singleLine and not have to cleared by some other running + // code + + var oldIUC = self.opts.imageUploadCallback; + self.opts.imageUploadCallback = function(image, json) { + self.$editor.find('.-image-upload-placeholder').remove(); + self.opts.imageUploadCallback = oldIUC; + // Add a zero-width space so that the caret:getOffset will find + // locations after pictures if only <br> tags exist otherwise. In + // other words, ensure there is at least one character after the + // image for text character counting. Additionally, Redactor will + // strip the zero-width space when saving + $(document.createTextNode("\u200b")).insertAfter($(image)); + bail(); + }; + + // Place the cursor back in the box! + self.caret.setOffset(plugin.offset); + + // Add cool wait cursor + self.insert.htmlWithoutClean('<span class="-image-upload-placeholder icon-stack"><i class="icon-circle icon-stack-base"></i><i class="icon-picture icon-light icon-spin"></i></span>'); + + // Upload clipboard files + self.clean.singleLine = false; + for (i = 0, k = files.length; i < k; i++) + self.upload.directUpload(files[i], e); + }, 1); } }; }; -- GitLab