Added image paste from clipboard
authorAlexander Ebert <ebert@woltlab.com>
Mon, 12 Sep 2016 11:17:23 +0000 (13:17 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 12 Sep 2016 11:17:29 +0000 (13:17 +0200)
com.woltlab.wcf/templates/wysiwyg.tpl
wcfsetup/install/files/js/3rdParty/redactor2/plugins/WoltLabAttachment.js
wcfsetup/install/files/js/3rdParty/redactor2/plugins/WoltLabModal.js
wcfsetup/install/files/js/3rdParty/redactor2/plugins/WoltLabPaste.js
wcfsetup/install/files/js/WCF.Attachment.js
wcfsetup/install/files/js/WCF.Message.js
wcfsetup/install/files/style/ui/redactor.scss

index 3b1d51de449d31803409aa401e72350d86330bc1..181f88eb9f002bdc732691066363ab120ec734df 100644 (file)
                        
                        var config = {
                                buttons: buttons,
-                               clipboardImageUpload: false,
+                               clipboardImageUpload: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('img')}true{else}false{/if},
                                formatting: ['p', 'h2', 'h3', 'h4'],
                                imageCaption: false,
+                               imageUpload: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('img')}true{else}false{/if},
                                lang: 'wsc', // fake language to offload phrases
                                langs: {
                                        wsc: {
                                linkify: false,
                                linkSize: 0xBADC0DED, // some random value to disable truncating
                                minHeight: 200,
-                               pasteImages: false,
+                               pasteImages: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('img')}true{else}false{/if},
                                plugins: [
                                        // Imperavi
                                        'alignment',
index 79fd1e700f862af5ca21d3bf8c045650bd9a6015..8930abf2b5bd3ab04cb72f97a63cd91c47d1efe9 100644 (file)
@@ -4,8 +4,9 @@ $.Redactor.prototype.WoltLabAttachment = function() {
        return {
                init: function() {
                        require(['EventHandler'], (function(EventHandler) {
-                               EventHandler.add('com.woltlab.wcf.redactor2', 'insertAttachment_' + this.$element[0].id, this.WoltLabAttachment._insert.bind(this))
-                               EventHandler.add('com.woltlab.wcf.redactor2', 'deleteAttachment_' + this.$element[0].id, this.WoltLabAttachment._delete.bind(this))
+                               EventHandler.add('com.woltlab.wcf.redactor2', 'insertAttachment_' + this.$element[0].id, this.WoltLabAttachment._insert.bind(this));
+                               EventHandler.add('com.woltlab.wcf.redactor2', 'deleteAttachment_' + this.$element[0].id, this.WoltLabAttachment._delete.bind(this));
+                               EventHandler.add('com.woltlab.wcf.redactor2', 'replaceAttachment_' + this.$element[0].id, this.WoltLabAttachment._replaceAttachment.bind(this));
                        }).bind(this));
                },
                
@@ -21,6 +22,18 @@ $.Redactor.prototype.WoltLabAttachment = function() {
                                // non-image attachment
                                this.insert.text('[attach=' + attachmentId + '][/attach]');
                        }
+                       
+                       this.buffer.set();
+               },
+               
+               _replaceAttachment: function (data) {
+                       var img = elCreate('img');
+                       img.className = 'woltlabAttachment';
+                       img.src = data.src;
+                       elData(img, 'attachment-id', data.attachmentId);
+                       
+                       data.img.parentNode.insertBefore(img, data.img);
+                       elRemove(data.img);
                },
                
                _delete: function(data) {
index df78cd349b53ff59f20c4e431c08f51502466007..db2f9b7971965b37183afa8de73ddafc7abf5944 100644 (file)
@@ -12,7 +12,10 @@ $.Redactor.prototype.WoltLabModal = function() {
                close: function() {
                        this.selection.restore();
                        
-                       _uiDialog.close(this);
+                       // avoid calling `close()` without any dialogs opened before
+                       if (_uiDialog.getDialog(this)) {
+                               _uiDialog.close(this);
+                       }
                },
                
                load: function(templateName, title) {
index c4027eae5093d68a9850c8a815732b0725fa7fd7..52285e2a288e95018ebdd7f0f9e2610999030272 100644 (file)
@@ -36,6 +36,97 @@ $.Redactor.prototype.WoltLabPaste = function() {
                        
                        // rebind paste event
                        this.core.editor().off('paste.redactor').on('paste.redactor', this.paste.init.bind(this));
+                       
+                       this.paste.detectClipboardUpload = (function (e) {
+                               e = e.originalEvent || e;
+                               
+                               var clipboard = e.clipboardData;
+                               
+                               // WoltLab modification: allow Edge
+                               if (this.detect.isIe() && (this.detect.isIe() !== 'edge' || document.documentMode))
+                               {
+                                       return true;
+                               }
+                               
+                               if (this.detect.isFirefox())
+                               {
+                                       return false;
+                               }
+                               
+                               // prevent safari fake url
+                               var types = clipboard.types;
+                               // WoltLab modification: `DataTransfer.types` is a `DOMStringList` in Edge
+                               if (Array.isArray(types) && types.indexOf('public.tiff') !== -1)
+                               {
+                                       e.preventDefault();
+                                       return false;
+                               }
+                               
+                               
+                               if (!clipboard.items || !clipboard.items.length)
+                               {
+                                       return;
+                               }
+                               
+                               var file = clipboard.items[0].getAsFile();
+                               if (file === null)
+                               {
+                                       return false;
+                               }
+                               
+                               var reader = new FileReader();
+                               reader.readAsDataURL(file);
+                               reader.onload = $.proxy(this.paste.insertFromClipboard, this);
+                               
+                               return true;
+                       }).bind(this);
+                       
+                       this.paste.insertFromClipboard = (function (e) {
+                               if (!window.FormData) {
+                                       return;
+                               }
+                               
+                               this.buffer.set();
+                               
+                               WCF.System.Event.fireEvent('com.woltlab.wcf.redactor2', 'pasteFromClipboard_' + this.$element[0].id, {
+                                       blob: this.utils.dataURItoBlob(e.target.result)
+                               });
+                       }).bind(this);
+                       
+                       this.paste.clipboardUpload = (function () {
+                               elBySelAll('img', this.$editor[0], (function (img) {
+                                       if (!window.FormData || img.src.indexOf('data:image') !== 0) {
+                                               return;
+                                       }
+                                       
+                                       this.buffer.set();
+                                       
+                                       elHide(img);
+                                       
+                                       WCF.System.Event.fireEvent('com.woltlab.wcf.redactor2', 'pasteFromClipboard_' + this.$element[0].id, {
+                                               blob: this.utils.dataURItoBlob(img.src),
+                                               replace: img
+                                       });
+                               }).bind(this));
+                       }).bind(this);
+                       
+                       var mpInsert = this.paste.insert;
+                       this.paste.insert = (function(html, data) {
+                               if (!data.pre && !data.text) {
+                                       var div = elCreate('div');
+                                       div.innerHTML = html;
+                                       
+                                       elBySelAll('img', this.$editor[0], function (img) {
+                                               if (img.src.indexOf('data:image') === 0) {
+                                                       elHide(img);
+                                               }
+                                       });
+                                       
+                                       html = div.innerHTML;
+                               }
+                               
+                               mpInsert.call(this, html, data);
+                       }).bind(this);
                }
        };
 };
index 5d3ad7c120428da6ce8f5c7c9f8fb6abedf189cf..63f14bc21cde1485c485d8738957b9a398b284f9 100644 (file)
@@ -53,6 +53,12 @@ WCF.Attachment.Upload = WCF.Upload.extend({
         */
        _editorId: '',
        
+       /**
+        * replace img element on load
+        * @var Object
+        */
+       _replaceOnLoad: {},
+       
        /**
         * @see WCF.Upload.init()
         */
@@ -87,6 +93,7 @@ WCF.Attachment.Upload = WCF.Upload.extend({
                        WCF.System.Event.addListener('com.woltlab.wcf.redactor2', 'submit_' + this._editorId, this._submitInline.bind(this));
                        WCF.System.Event.addListener('com.woltlab.wcf.redactor2', 'reset_' + this._editorId, this._reset.bind(this));
                        WCF.System.Event.addListener('com.woltlab.wcf.redactor2', 'dragAndDrop_' + this._editorId, this._editorUpload.bind(this));
+                       WCF.System.Event.addListener('com.woltlab.wcf.redactor2', 'pasteFromClipboard_' + this._editorId, this._editorUpload.bind(this));
                        
                        var metacodeAttachUuid = WCF.System.Event.addListener('com.woltlab.wcf.redactor2', 'metacode_attach', (function(data) {
                                var images = this._getImageAttachments();
@@ -117,6 +124,7 @@ WCF.Attachment.Upload = WCF.Upload.extend({
                                WCF.System.Event.removeAllListeners('com.woltlab.wcf.redactor2', 'reset_' + this._editorId);
                                WCF.System.Event.removeAllListeners('com.woltlab.wcf.redactor2', 'insertAttachment_' + this._editorId);
                                WCF.System.Event.removeAllListeners('com.woltlab.wcf.redactor2', 'dragAndDrop_' + this._editorId);
+                               WCF.System.Event.removeAllListeners('com.woltlab.wcf.redactor2', 'pasteFromClipboard_' + this._editorId);
                                
                                WCF.System.Event.removeListener('com.woltlab.wcf.redactor2', 'metacode_attach', metacodeAttachUuid);
                        }).bind(this));
@@ -129,7 +137,7 @@ WCF.Attachment.Upload = WCF.Upload.extend({
         * @param       object          data
         */
        _editorUpload: function(data) {
-               var $uploadID;
+               var $uploadID, replace = null;
                
                // show tab
                this._fileListSelector.closest('.messageTabMenu').messageTabMenu('showTab', 'attachments', true);
@@ -139,9 +147,16 @@ WCF.Attachment.Upload = WCF.Upload.extend({
                }
                else {
                        $uploadID = this._upload(undefined, undefined, data.blob);
+                       replace = data.replace || null;
+               }
+               
+               if (replace === null) {
+                       this._autoInsert.push($uploadID);
+               }
+               else {
+                       this._replaceOnLoad[$uploadID] = replace;
                }
                
-               this._autoInsert.push($uploadID);
                data.uploadID = $uploadID;
        },
        
@@ -227,9 +242,7 @@ WCF.Attachment.Upload = WCF.Upload.extend({
                }
                
                if (!$listItems.length) {
-                       setTimeout((function() {
-                               this._fileListSelector.wcfBlindOut();
-                       }).bind(this), 250);
+                       this._fileListSelector.hide();
                }
                
                if (this._editorId && data.button) {
@@ -374,6 +387,21 @@ WCF.Attachment.Upload = WCF.Upload.extend({
                                                $insertPlain.appendTo($buttonList).children('span.button').click($.proxy(this._insert, this));
                                        }
                                }
+                               
+                               if (this._replaceOnLoad.hasOwnProperty(uploadID)) {
+                                       if (!$li.hasClass('uploadFailed')) {
+                                               var img = this._replaceOnLoad[uploadID];
+                                               if (img && img.parentNode) {
+                                                       WCF.System.Event.fireEvent('com.woltlab.wcf.redactor2', 'replaceAttachment_' + this._editorId, {
+                                                               attachmentId: attachmentData.attachmentID,
+                                                               img: img,
+                                                               src: (attachmentData.thumbnailURL) ? attachmentData.thumbnailURL : attachmentData.url
+                                                       });
+                                               }
+                                       }
+                                       
+                                       this._replaceOnLoad[uploadID] = null;
+                               }
                        }
                        else {
                                // upload icon
@@ -400,10 +428,10 @@ WCF.Attachment.Upload = WCF.Upload.extend({
                                this._autoInsert.splice(this._autoInsert.indexOf(uploadID), 1);
                                
                                if (!$li.hasClass('uploadFailed')) {
-                                       WCF.System.Event.fireEvent('com.woltlab.wcf.attachment', 'autoInsert_' + this._editorId, {
-                                               attachment: '[attach=' + data.returnValues.attachments[$internalFileID].attachmentID + '][/attach]',
-                                               uploadID: uploadID
-                                       });
+                                       var btn = $li.find('.jsButtonAttachmentInsertThumbnail');
+                                       if (!btn.length) btn = $li.find('.jsButtonAttachmentInsertFull');
+                                       
+                                       btn.trigger('click');
                                }
                        }
                }
index 9077830e3256a14b4d434da9579cd155325ff0de..4a041c2cb75384dd45cf4c885a1ca266eeaa28ec 100644 (file)
@@ -2153,12 +2153,6 @@ WCF.Message.UserMention = Class.extend({
  * Provides a specialized tab menu used for message options, integrates better into the editor.
  */
 $.widget('wcf.messageTabMenu', {
-       /**
-        * pointer span
-        * @var jQuery
-        */
-       _span: null,
-       
        /**
         * list of existing tabs and their containers
         * @var array<object>
@@ -2192,9 +2186,6 @@ $.widget('wcf.messageTabMenu', {
                        return;
                }
                
-               // pointer span
-               this._span = $('<span />').appendTo($nav);
-               
                var $preselect = this.element.data('preselect');
                
                // check for tabs containing '.innerError' and select the first matching one instead
@@ -2302,11 +2293,6 @@ $.widget('wcf.messageTabMenu', {
                        });
                }
                
-               this._span.css({
-                       transform: 'translateX(' + $target.tab[0].offsetLeft + 'px)', 
-                       width: $target.tab[0].clientWidth + 'px'
-               });
-               
                $(window).trigger('resize');
        },
        
index df7c19fe16945bce1324266be0758ecef5387c41..78750924eee1b1ef5a47d538c40e2bb8309b54b3 100644 (file)
                        // show cursor to indicate editing capability excluding smilies
                        cursor: pointer;
                }
+               
+               /* prevent flicker from pasted images */
+               &[src^="data:image"] {
+                       display: none !important;
+               }
        }
        
        // TODO: this is somewhat out of sync