-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Paste extension and images #1120
Comments
Is your paste handler a medium-editor extension, or something else externally? Can you provide how your implementing this paste handler? It might be possible to implement a custom paste-handler that extends medium-editor's built-in paste handler, and override the |
My paste handler is not medium-editor extension. It is just my code. //paste image
document.getElementById(content_id).addEventListener("paste", function(e) {
if(e && e.clipboardData && e.clipboardData.items && $.inArray( 'Files', e.clipboardData.types )>-1){
for (var i = 0; i < e.clipboardData.items.length; i++) {
if (e.clipboardData.items[i].kind == "file" && e.clipboardData.items[i].type == "image/png") {
var imageFile = e.clipboardData.items[i].getAsFile(); // get the blob
var key = sysname+'/tasks/'+$('#t_id').text()+'/'+tm_id+'/embedded/' +
Date.now()+Math.floor(Math.random() * 1000)+'.png';
// create an image
var image = document.createElement("IMG");
image.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
image.setAttribute('class', 'loading');
image.setAttribute('key', key);
image.setAttribute('width', 50);
image.id = key.slice(0, -4).replace(/\//g,'');
// insert the image
var range = window.getSelection().getRangeAt(0);
$('#'+content_id).attr('waiting', true);
$('#'+content_id).removeClass('medium-editor-placeholder');
range.insertNode(image);
range.collapse(false);
// set the selection to after the image
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
new s3uploaderObject({
sysname: sysname,
file: imageFile,
content_type: 'image/png',
content_disposition: '',
key: key,
policy: $('#tm_wrap_'+tm_id+'>.content-wrap>.s3-policy').text(),
signature: $('#tm_wrap_'+tm_id+'>.content-wrap>.s3-signature').text(),
onload: function(e, key) {
$.post( "ajax_get_s3_url.php", {
t_id: $('#t_id').text(),
key: key
})
.done(function( data ) {
image.src = data;
image.onload = function() {
var svg = '<svg xmlns="http://www.w3.org/2000/svg" width="'+image.naturalWidth+'" height="'+image.naturalHeight+'"/>';
image.setAttribute('class', '');
image.setAttribute('width', image.naturalWidth);
image.setAttribute('data-dump-image', 'data:image/svg+xml;base64,'+btoa(svg));
$('#'+content_id).attr('waiting', false);
};
});
}
});
break;
}
}
e.preventDefault();
}
return false;
}); My code create dump img with loading animation. Then it uploads the image to s3. When upload finished, src of the img is changed to the url from s3 and uctual image is shown. For now I have to just disable extentions for my code to work:
|
@gnemtsov I think you could get this to work by implementing your own paste extension and overriding the 1st, break your custom paste handler code into 2 helper functions, one to detect if it's a custom paste, and one to actually handle the logic // Helper method containing your logic on detecting your special case for paste
var isFilePaste = function (event) {
return event &&
event.clipboardData &&
event.clipboardData.items &&
$.inArray( 'Files', event.clipboardData.types )>-1;
}
var handleFilePaste = function (event) {
// ...
// All your logic for handling your special paste
} Next, define the custom paste handler and override the 2 methods which handle paste today, allowing you to call into your custom logic, or fallback to the default behavior: // Define your custom paste handler and override:
// cleanPastedHTML -> true (to enable html cleaning)
// handlePaste -> method which is called for handling paste from the context menu
// handlePasteBinPaste -> method which is called for handling paste from the keyboard
var CustomPasteHandler = MediumEditor.extensions.paste.extend({
cleanPastedHTML: true,
handlePaste: function (event) {
if (isFilePaste(event)) {
handleFilePaste(event);
return;
}
// If it's not a file paste, fallback to the default paste handler logic
MediumEditor.extensions.paste.prototype.handlePaste.apply(this, arguments);
},
handlePasteBinPaste: function (event) {
if (isFilePaste(event)) {
handleFilePaste(event);
return;
}
// If it's not a file paste, fallback to the default paste handler logic
MediumEditor.extensions.paste.prototype.handlePaste.apply(this, arguments);
}
}); Finally, pass your custom paste handler into the editor when instantiating. // Define editor and pass the custom paste handler
var editor = new MediumEditor('.editable', {
// other options
extensions: {
'imageDragging': {},
'paste': new CustomPasteHandler(),
'table': new MediumEditorTable()
}
}); If I understand everything correctly, I think that will work. |
Thanks a lot for help! Really appreciate. This code works in general. But there are some problems.. var CustomPasteHandler = MediumEditor.extensions.paste.extend({
cleanPastedHTML: true,
handlePaste: function (event) {
if (isFilePaste(event)) {
handleFilePaste($(this.base.elements[0]).attr('tm_id'), event);
return;
}
// If it's not a file paste, fallback to the default paste handler logic
MediumEditor.extensions.paste.prototype.handlePaste.apply(this, arguments);
},
handlePasteBinPaste: function (event) {
if (isFilePaste(event)) {
handleFilePaste($(this.base.elements[0]).attr('tm_id'), event);
return;
}
// If it's not a file paste, fallback to the default paste handler logic
MediumEditor.extensions.paste.prototype.handlePaste.apply(this, arguments);
}
}); So here are the problems
// insert the image
var range = window.getSelection().getRangeAt(0);
console.log(range);
$('#'+content_id).attr('waiting', true);
$('#'+content_id).removeClass('medium-editor-placeholder');
range.insertNode(image);
range.collapse(false);
// set the selection to after the image
var selection = window.getSelection(); I suppose selection range is not in my div. It is in some div#medium-editor-pastebin-.. div. |
For CTRL + V paste, try calling handlePasteBinPaste: function (event) {
if (isFilePaste(event)) {
this.removePasteBin(); // <-- Try Calling This
handleFilePaste($(this.base.elements[0]).attr('tm_id'), event);
return;
}
// If it's not a file paste, fallback to the default paste handler logic
MediumEditor.extensions.paste.prototype.handlePaste.apply(this, arguments);
}
As for your issue with paste from the context menu, I would try debugging to ensure that your |
Ah, this is related to 8bd8f8f. Since we use a You can work around this though by overriding the Original
|
Well, thanks @nmielnik, it is almost done. All previous problems were solved! But one new has appeared. My current code looks like this var AbtaskPasteHandler = MediumEditor.extensions.paste.extend({
forcePlainText: true,
cleanPastedHTML: true,
cleanAttrs: ['class', 'style', 'dir'],
cleanTags: ['meta'],
init: function () {
MediumEditor.Extension.prototype.init.apply(this, arguments);
if (this.forcePlainText || this.cleanPastedHTML) {
this.subscribe('editableKeydown', this.handleKeydown.bind(this));
this.getEditorElements().forEach(function (element) {
this.on(element, 'paste', this.handlePaste.bind(this));
}, this);
}
},
handlePaste: function (event) {
if (isFilePaste(event)) {
this.removePasteBin();
handleImagePaste($(this.document.activeElement).attr("tm_id"), event);
return;
}
MediumEditor.extensions.paste.prototype.handlePaste.apply(this, arguments);
ProcessPastedImages($(this.document.activeElement).attr("tm_id"));
},
handlePasteBinPaste: function (event) {
if (isFilePaste(event)) {
this.removePasteBin();
handleImagePaste($(this.document.activeElement).attr("tm_id"), event);
return;
}
MediumEditor.extensions.paste.prototype.handlePasteBinPaste.apply(this, arguments);
ProcessPastedImages($(this.document.activeElement).attr("tm_id"));
}
}); It works in all situations. But... I add elements dynamically and attach medium editor: |
@gnemtsov if you're not maintaining a fork, just update to the latest version of medium-editor (5.21.0) which has the updates to the paste extension you need. |
Sorry for my silence. |
I want to use fantastic extension "paste" to clean user's HTML pasted.
But I have my own paste handler which handles image paste. I upload image to S3 and insert img tag by javascript. If I enable paste extension, then my handler never fires and image is just ignored with error in console (see attachemnt).
What I need is to use my handler, when image is pasted (I can detect it with something like this $.inArray( 'Files', e.clipboardData.types )>-1). And to use medium handler to clean HTML, when 'text/html' content is pasted. Is that possible?
![default](https://cloud.githubusercontent.com/assets/6842497/15991635/184d5688-30c1-11e6-9492-8fdc29698f1a.PNG)
The text was updated successfully, but these errors were encountered: