diff options
Diffstat (limited to 'sources/plugins/clipboard/plugin.js')
-rw-r--r-- | sources/plugins/clipboard/plugin.js | 332 |
1 files changed, 170 insertions, 162 deletions
diff --git a/sources/plugins/clipboard/plugin.js b/sources/plugins/clipboard/plugin.js index 5c387b3..433f547 100644 --- a/sources/plugins/clipboard/plugin.js +++ b/sources/plugins/clipboard/plugin.js | |||
@@ -44,7 +44,6 @@ | |||
44 | // -- Paste command | 44 | // -- Paste command |
45 | // * fire 'paste' on editable ('beforepaste' for IE) | 45 | // * fire 'paste' on editable ('beforepaste' for IE) |
46 | // * !canceled && execCommand 'paste' | 46 | // * !canceled && execCommand 'paste' |
47 | // * !success && fire 'pasteDialog' on editor | ||
48 | // -- Paste from native context menu & menubar | 47 | // -- Paste from native context menu & menubar |
49 | // (Fx & Webkits are handled in 'paste' default listener. | 48 | // (Fx & Webkits are handled in 'paste' default listener. |
50 | // Opera cannot be handled at all because it doesn't fire any events | 49 | // Opera cannot be handled at all because it doesn't fire any events |
@@ -117,9 +116,9 @@ | |||
117 | ( function() { | 116 | ( function() { |
118 | // Register the plugin. | 117 | // Register the plugin. |
119 | CKEDITOR.plugins.add( 'clipboard', { | 118 | CKEDITOR.plugins.add( 'clipboard', { |
120 | requires: 'dialog', | 119 | requires: 'notification,toolbar', |
121 | // jscs:disable maximumLineLength | 120 | // jscs:disable maximumLineLength |
122 | lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE% | 121 | lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE% |
123 | // jscs:enable maximumLineLength | 122 | // jscs:enable maximumLineLength |
124 | icons: 'copy,copy-rtl,cut,cut-rtl,paste,paste-rtl', // %REMOVE_LINE_CORE% | 123 | icons: 'copy,copy-rtl,cut,cut-rtl,paste,paste-rtl', // %REMOVE_LINE_CORE% |
125 | hidpi: true, // %REMOVE_LINE_CORE% | 124 | hidpi: true, // %REMOVE_LINE_CORE% |
@@ -143,8 +142,6 @@ | |||
143 | initPasteClipboard( editor ); | 142 | initPasteClipboard( editor ); |
144 | initDragDrop( editor ); | 143 | initDragDrop( editor ); |
145 | 144 | ||
146 | CKEDITOR.dialog.add( 'paste', CKEDITOR.getUrl( this.path + 'dialogs/paste.js' ) ); | ||
147 | |||
148 | // Convert image file (if present) to base64 string for Firefox. Do it as the first | 145 | // Convert image file (if present) to base64 string for Firefox. Do it as the first |
149 | // step as the conversion is asynchronous and should hold all further paste processing. | 146 | // step as the conversion is asynchronous and should hold all further paste processing. |
150 | if ( CKEDITOR.env.gecko ) { | 147 | if ( CKEDITOR.env.gecko ) { |
@@ -156,7 +153,7 @@ | |||
156 | data = dataObj.dataValue, | 153 | data = dataObj.dataValue, |
157 | dataTransfer = dataObj.dataTransfer; | 154 | dataTransfer = dataObj.dataTransfer; |
158 | 155 | ||
159 | // If data empty check for image content inside data transfer. #16705 | 156 | // If data empty check for image content inside data transfer. http://dev.ckeditor.com/ticket/16705 |
160 | if ( !data && dataObj.method == 'paste' && dataTransfer && dataTransfer.getFilesCount() == 1 && latestId != dataTransfer.id ) { | 157 | if ( !data && dataObj.method == 'paste' && dataTransfer && dataTransfer.getFilesCount() == 1 && latestId != dataTransfer.id ) { |
161 | var file = dataTransfer.getFile( 0 ); | 158 | var file = dataTransfer.getFile( 0 ); |
162 | 159 | ||
@@ -250,14 +247,14 @@ | |||
250 | data = data.replace( /(<[^>]+) class="Apple-[^"]*"/gi, '$1' ); | 247 | data = data.replace( /(<[^>]+) class="Apple-[^"]*"/gi, '$1' ); |
251 | } | 248 | } |
252 | 249 | ||
253 | // Strip editable that was copied from inside. (#9534) | 250 | // Strip editable that was copied from inside. (http://dev.ckeditor.com/ticket/9534) |
254 | if ( data.match( /^<[^<]+cke_(editable|contents)/i ) ) { | 251 | if ( data.match( /^<[^<]+cke_(editable|contents)/i ) ) { |
255 | var tmp, | 252 | var tmp, |
256 | editable_wrapper, | 253 | editable_wrapper, |
257 | wrapper = new CKEDITOR.dom.element( 'div' ); | 254 | wrapper = new CKEDITOR.dom.element( 'div' ); |
258 | 255 | ||
259 | wrapper.setHtml( data ); | 256 | wrapper.setHtml( data ); |
260 | // Verify for sure and check for nested editor UI parts. (#9675) | 257 | // Verify for sure and check for nested editor UI parts. (http://dev.ckeditor.com/ticket/9675) |
261 | while ( wrapper.getChildCount() == 1 && | 258 | while ( wrapper.getChildCount() == 1 && |
262 | ( tmp = wrapper.getFirst() ) && | 259 | ( tmp = wrapper.getFirst() ) && |
263 | tmp.type == CKEDITOR.NODE_ELEMENT && // Make sure first-child is element. | 260 | tmp.type == CKEDITOR.NODE_ELEMENT && // Make sure first-child is element. |
@@ -299,7 +296,7 @@ | |||
299 | 296 | ||
300 | editor.on( 'paste', function( evt ) { | 297 | editor.on( 'paste', function( evt ) { |
301 | var dataObj = evt.data, | 298 | var dataObj = evt.data, |
302 | type = dataObj.type, | 299 | type = editor._.nextPasteType || dataObj.type, |
303 | data = dataObj.dataValue, | 300 | data = dataObj.dataValue, |
304 | trueType, | 301 | trueType, |
305 | // Default is 'html'. | 302 | // Default is 'html'. |
@@ -313,13 +310,15 @@ | |||
313 | trueType = recogniseContentType( data ); | 310 | trueType = recogniseContentType( data ); |
314 | } | 311 | } |
315 | 312 | ||
313 | delete editor._.nextPasteType; | ||
314 | |||
316 | // Unify text markup. | 315 | // Unify text markup. |
317 | if ( trueType == 'htmlifiedtext' ) { | 316 | if ( trueType == 'htmlifiedtext' ) { |
318 | data = htmlifiedTextHtmlification( editor.config, data ); | 317 | data = htmlifiedTextHtmlification( editor.config, data ); |
319 | } | 318 | } |
320 | 319 | ||
321 | // Strip presentational markup & unify text markup. | 320 | // Strip presentational markup & unify text markup. |
322 | // Forced plain text (dialog or forcePAPT). | 321 | // Forced plain text. |
323 | // Note: we do not check dontFilter option in this case, because forcePAPT was implemented | 322 | // Note: we do not check dontFilter option in this case, because forcePAPT was implemented |
324 | // before pasteFilter and pasteFilter is automatically used on Webkit&Blink since 4.5, so | 323 | // before pasteFilter and pasteFilter is automatically used on Webkit&Blink since 4.5, so |
325 | // forcePAPT should have priority as it had before 4.5. | 324 | // forcePAPT should have priority as it had before 4.5. |
@@ -364,17 +363,6 @@ | |||
364 | }, 0 ); | 363 | }, 0 ); |
365 | } | 364 | } |
366 | }, null, null, 1000 ); | 365 | }, null, null, 1000 ); |
367 | |||
368 | editor.on( 'pasteDialog', function( evt ) { | ||
369 | // TODO it's possible that this setTimeout is not needed any more, | ||
370 | // because of changes introduced in the same commit as this comment. | ||
371 | // Editor.getClipboardData adds listener to the dialog's events which are | ||
372 | // fired after a while (not like 'showDialog'). | ||
373 | setTimeout( function() { | ||
374 | // Open default paste dialog. | ||
375 | editor.openDialog( 'paste', evt.data ); | ||
376 | }, 0 ); | ||
377 | } ); | ||
378 | } | 366 | } |
379 | } ); | 367 | } ); |
380 | 368 | ||
@@ -402,8 +390,8 @@ | |||
402 | } | 390 | } |
403 | 391 | ||
404 | // Because of FF bug we need to use this hack, otherwise cursor is hidden | 392 | // Because of FF bug we need to use this hack, otherwise cursor is hidden |
405 | // or it is not possible to move it (#12420). | 393 | // or it is not possible to move it (http://dev.ckeditor.com/ticket/12420). |
406 | // Also, check that editor.toolbox exists, because the toolbar plugin might not be loaded (#13305). | 394 | // Also, check that editor.toolbox exists, because the toolbar plugin might not be loaded (http://dev.ckeditor.com/ticket/13305). |
407 | if ( CKEDITOR.env.gecko && data.method == 'drop' && editor.toolbox ) { | 395 | if ( CKEDITOR.env.gecko && data.method == 'drop' && editor.toolbox ) { |
408 | editor.once( 'afterPaste', function() { | 396 | editor.once( 'afterPaste', function() { |
409 | editor.toolbox.focus(); | 397 | editor.toolbox.focus(); |
@@ -423,28 +411,25 @@ | |||
423 | addButtonsCommands(); | 411 | addButtonsCommands(); |
424 | 412 | ||
425 | /** | 413 | /** |
426 | * Gets clipboard data by directly accessing the clipboard (IE only) or opening the paste dialog window. | 414 | * Gets clipboard data by directly accessing the clipboard (IE only). |
427 | * | 415 | * |
428 | * editor.getClipboardData( { title: 'Get my data' }, function( data ) { | 416 | * editor.getClipboardData( function( data ) { |
429 | * if ( data ) | 417 | * if ( data ) |
430 | * alert( data.type + ' ' + data.dataValue ); | 418 | * alert( data.type + ' ' + data.dataValue ); |
431 | * } ); | 419 | * } ); |
432 | * | 420 | * |
433 | * @member CKEDITOR.editor | 421 | * @member CKEDITOR.editor |
434 | * @param {Object} options | 422 | * @param {Function/Object} callbackOrOptions For function, see the `callback` parameter documentation. The object was used before 4.7.0 with the `title` property, to set the paste dialog's title. |
435 | * @param {String} [options.title] The title of the paste dialog window. | 423 | * @param {Function} callback A function that will be executed with the `data` property of the |
436 | * @param {Function} callback A function that will be executed with `data.type` and `data.dataValue` | 424 | * {@link CKEDITOR.editor#event-paste paste event} or `null` if none of the capturing methods succeeded. |
437 | * or `null` if none of the capturing methods succeeded. | 425 | * Since 4.7.0 the `callback` should be provided as a first argument, just like in the example above. This parameter will be removed in |
426 | * an upcoming major release. | ||
438 | */ | 427 | */ |
439 | editor.getClipboardData = function( options, callback ) { | 428 | editor.getClipboardData = function( callbackOrOptions, callback ) { |
440 | var beforePasteNotCanceled = false, | ||
441 | dataType = 'auto', | ||
442 | dialogCommited = false; | ||
443 | |||
444 | // Options are optional - args shift. | 429 | // Options are optional - args shift. |
445 | if ( !callback ) { | 430 | if ( !callback ) { |
446 | callback = options; | 431 | callback = callbackOrOptions; |
447 | options = null; | 432 | callbackOrOptions = null; |
448 | } | 433 | } |
449 | 434 | ||
450 | // Listen with maximum priority to handle content before everyone else. | 435 | // Listen with maximum priority to handle content before everyone else. |
@@ -452,39 +437,13 @@ | |||
452 | // access to the clipboard succeed in IE. | 437 | // access to the clipboard succeed in IE. |
453 | editor.on( 'paste', onPaste, null, null, 0 ); | 438 | editor.on( 'paste', onPaste, null, null, 0 ); |
454 | 439 | ||
455 | // Listen at the end of listeners chain to see if event wasn't canceled | ||
456 | // and to retrieve modified data.type. | ||
457 | editor.on( 'beforePaste', onBeforePaste, null, null, 1000 ); | ||
458 | |||
459 | // getClipboardDataDirectly() will fire 'beforePaste' synchronously, so we can | ||
460 | // check if it was canceled and if any listener modified data.type. | ||
461 | |||
462 | // If command didn't succeed (only IE allows to access clipboard and only if | 440 | // If command didn't succeed (only IE allows to access clipboard and only if |
463 | // user agrees) open and handle paste dialog. | 441 | // user agrees) invoke callback with null, meaning that paste is not blocked. |
464 | if ( getClipboardDataDirectly() === false ) { | 442 | if ( getClipboardDataDirectly() === false ) { |
465 | // Direct access to the clipboard wasn't successful so remove listener. | 443 | // Direct access to the clipboard wasn't successful so remove listener. |
466 | editor.removeListener( 'paste', onPaste ); | 444 | editor.removeListener( 'paste', onPaste ); |
467 | 445 | ||
468 | // If beforePaste was canceled do not open dialog. | 446 | callback( null ); |
469 | // Add listeners only if dialog really opened. 'pasteDialog' can be canceled. | ||
470 | if ( beforePasteNotCanceled && editor.fire( 'pasteDialog', onDialogOpen ) ) { | ||
471 | editor.on( 'pasteDialogCommit', onDialogCommit ); | ||
472 | |||
473 | // 'dialogHide' will be fired after 'pasteDialogCommit'. | ||
474 | editor.on( 'dialogHide', function( evt ) { | ||
475 | evt.removeListener(); | ||
476 | evt.data.removeListener( 'pasteDialogCommit', onDialogCommit ); | ||
477 | |||
478 | // Because Opera has to wait a while in pasteDialog we have to wait here. | ||
479 | setTimeout( function() { | ||
480 | // Notify even if user canceled dialog (clicked 'cancel', ESC, etc). | ||
481 | if ( !dialogCommited ) | ||
482 | callback( null ); | ||
483 | }, 10 ); | ||
484 | } ); | ||
485 | } else { | ||
486 | callback( null ); | ||
487 | } | ||
488 | } | 447 | } |
489 | 448 | ||
490 | function onPaste( evt ) { | 449 | function onPaste( evt ) { |
@@ -492,30 +451,6 @@ | |||
492 | evt.cancel(); | 451 | evt.cancel(); |
493 | callback( evt.data ); | 452 | callback( evt.data ); |
494 | } | 453 | } |
495 | |||
496 | function onBeforePaste( evt ) { | ||
497 | evt.removeListener(); | ||
498 | beforePasteNotCanceled = true; | ||
499 | dataType = evt.data.type; | ||
500 | } | ||
501 | |||
502 | function onDialogCommit( evt ) { | ||
503 | evt.removeListener(); | ||
504 | // Cancel pasteDialogCommit so paste dialog won't automatically fire | ||
505 | // 'paste' evt by itself. | ||
506 | evt.cancel(); | ||
507 | dialogCommited = true; | ||
508 | callback( { | ||
509 | type: dataType, | ||
510 | dataValue: evt.data.dataValue, | ||
511 | dataTransfer: evt.data.dataTransfer, | ||
512 | method: 'paste' | ||
513 | } ); | ||
514 | } | ||
515 | |||
516 | function onDialogOpen() { | ||
517 | this.customTitle = ( options && options.title ); | ||
518 | } | ||
519 | }; | 454 | }; |
520 | 455 | ||
521 | function addButtonsCommands() { | 456 | function addButtonsCommands() { |
@@ -574,7 +509,7 @@ | |||
574 | 509 | ||
575 | if ( CKEDITOR.plugins.clipboard.isCustomCopyCutSupported ) { | 510 | if ( CKEDITOR.plugins.clipboard.isCustomCopyCutSupported ) { |
576 | var initOnCopyCut = function( evt ) { | 511 | var initOnCopyCut = function( evt ) { |
577 | // If user tries to cut in read-only editor, we must prevent default action. (#13872) | 512 | // If user tries to cut in read-only editor, we must prevent default action. (http://dev.ckeditor.com/ticket/13872) |
578 | if ( !editor.readOnly || evt.name != 'cut' ) { | 513 | if ( !editor.readOnly || evt.name != 'cut' ) { |
579 | clipboard.initPasteDataTransfer( evt, editor ); | 514 | clipboard.initPasteDataTransfer( evt, editor ); |
580 | } | 515 | } |
@@ -586,7 +521,7 @@ | |||
586 | 521 | ||
587 | // Delete content with the low priority so one can overwrite cut data. | 522 | // Delete content with the low priority so one can overwrite cut data. |
588 | editable.on( 'cut', function() { | 523 | editable.on( 'cut', function() { |
589 | // If user tries to cut in read-only editor, we must prevent default action. (#13872) | 524 | // If user tries to cut in read-only editor, we must prevent default action. (http://dev.ckeditor.com/ticket/13872) |
590 | if ( !editor.readOnly ) { | 525 | if ( !editor.readOnly ) { |
591 | editor.extractSelectedHtml(); | 526 | editor.extractSelectedHtml(); |
592 | } | 527 | } |
@@ -663,17 +598,15 @@ | |||
663 | pasteDataFromClipboard( evt ); | 598 | pasteDataFromClipboard( evt ); |
664 | 599 | ||
665 | // Force IE to paste content into pastebin so pasteDataFromClipboard will work. | 600 | // Force IE to paste content into pastebin so pasteDataFromClipboard will work. |
666 | if ( !execIECommand( 'paste' ) ) { | 601 | execIECommand( 'paste' ); |
667 | editor.openDialog( 'paste' ); | ||
668 | } | ||
669 | } ); | 602 | } ); |
670 | 603 | ||
671 | // If mainPasteEvent is 'beforePaste' (IE before Edge), | 604 | // If mainPasteEvent is 'beforePaste' (IE before Edge), |
672 | // dismiss the (wrong) 'beforepaste' event fired on context/toolbar menu open. (#7953) | 605 | // dismiss the (wrong) 'beforepaste' event fired on context/toolbar menu open. (http://dev.ckeditor.com/ticket/7953) |
673 | editable.on( 'contextmenu', preventBeforePasteEventNow, null, null, 0 ); | 606 | editable.on( 'contextmenu', preventBeforePasteEventNow, null, null, 0 ); |
674 | 607 | ||
675 | editable.on( 'beforepaste', function( evt ) { | 608 | editable.on( 'beforepaste', function( evt ) { |
676 | // Do not prevent event on CTRL+V and SHIFT+INS because it blocks paste (#11970). | 609 | // Do not prevent event on CTRL+V and SHIFT+INS because it blocks paste (http://dev.ckeditor.com/ticket/11970). |
677 | if ( evt.data && !evt.data.$.ctrlKey && !evt.data.$.shiftKey ) | 610 | if ( evt.data && !evt.data.$.ctrlKey && !evt.data.$.shiftKey ) |
678 | preventBeforePasteEventNow(); | 611 | preventBeforePasteEventNow(); |
679 | }, null, null, 0 ); | 612 | }, null, null, 0 ); |
@@ -687,7 +620,7 @@ | |||
687 | 620 | ||
688 | // Use editor.document instead of editable in non-IEs for observing mouseup | 621 | // Use editor.document instead of editable in non-IEs for observing mouseup |
689 | // since editable won't fire the event if selection process started within | 622 | // since editable won't fire the event if selection process started within |
690 | // iframe and ended out of the editor (#9851). | 623 | // iframe and ended out of the editor (http://dev.ckeditor.com/ticket/9851). |
691 | editable.attachListener( CKEDITOR.env.ie ? editable : editor.document.getDocumentElement(), 'mouseup', function() { | 624 | editable.attachListener( CKEDITOR.env.ie ? editable : editor.document.getDocumentElement(), 'mouseup', function() { |
692 | mouseupTimeout = setTimeout( function() { | 625 | mouseupTimeout = setTimeout( function() { |
693 | setToolbarStates(); | 626 | setToolbarStates(); |
@@ -696,7 +629,7 @@ | |||
696 | 629 | ||
697 | // Make sure that deferred mouseup callback isn't executed after editor instance | 630 | // Make sure that deferred mouseup callback isn't executed after editor instance |
698 | // had been destroyed. This may happen when editor.destroy() is called in parallel | 631 | // had been destroyed. This may happen when editor.destroy() is called in parallel |
699 | // with mouseup event (i.e. a button with onclick callback) (#10219). | 632 | // with mouseup event (i.e. a button with onclick callback) (http://dev.ckeditor.com/ticket/10219). |
700 | editor.on( 'destroy', function() { | 633 | editor.on( 'destroy', function() { |
701 | clearTimeout( mouseupTimeout ); | 634 | clearTimeout( mouseupTimeout ); |
702 | } ); | 635 | } ); |
@@ -746,27 +679,73 @@ | |||
746 | canUndo: false, | 679 | canUndo: false, |
747 | async: true, | 680 | async: true, |
748 | fakeKeystroke: CKEDITOR.CTRL + 86 /*V*/, | 681 | fakeKeystroke: CKEDITOR.CTRL + 86 /*V*/, |
682 | |||
683 | /** | ||
684 | * The default implementation of the paste command. | ||
685 | * | ||
686 | * @private | ||
687 | * @param {CKEDITOR.editor} editor An instance of the editor where the command is being executed. | ||
688 | * @param {Object/String} data If `data` is a string, then it is considered content that is being pasted. | ||
689 | * Otherwise it is treated as an object with options. | ||
690 | * @param {Boolean/String} [data.notification=true] Content for a notification shown after an unsuccessful | ||
691 | * paste attempt. If `false`, the notification will not be displayed. This parameter was added in 4.7.0. | ||
692 | * @param {String} [data.type='html'] The type of pasted content. There are two allowed values: | ||
693 | * * 'html' | ||
694 | * * 'text' | ||
695 | * @param {String/Object} data.dataValue Content being pasted. If this parameter is an object, it | ||
696 | * is supposed to be a `data` property of the {@link CKEDITOR.editor#paste} event. | ||
697 | * @param {CKEDITOR.plugins.clipboard.dataTransfer} data.dataTransfer Data transfer instance connected | ||
698 | * with the current paste action. | ||
699 | * @member CKEDITOR.editor.commands.paste | ||
700 | */ | ||
749 | exec: function( editor, data ) { | 701 | exec: function( editor, data ) { |
702 | data = typeof data !== 'undefined' && data !== null ? data : {}; | ||
703 | |||
750 | var cmd = this, | 704 | var cmd = this, |
751 | fire = function( data, withBeforePaste ) { | 705 | notification = typeof data.notification !== 'undefined' ? data.notification : true, |
752 | data && firePasteEvents( editor, data, !!withBeforePaste ); | 706 | forcedType = data.type, |
753 | 707 | keystroke = CKEDITOR.tools.keystrokeToString( editor.lang.common.keyboard, | |
754 | editor.fire( 'afterCommandExec', { | 708 | editor.getCommandKeystroke( this ) ), |
755 | name: 'paste', | 709 | msg = typeof notification === 'string' ? notification : editor.lang.clipboard.pasteNotification |
756 | command: cmd, | 710 | .replace( /%1/, '<kbd aria-label="' + keystroke.aria + '">' + keystroke.display + '</kbd>' ), |
757 | returnValue: !!data | 711 | pastedContent = typeof data === 'string' ? data : data.dataValue; |
758 | } ); | 712 | |
759 | }; | 713 | function callback( data, withBeforePaste ) { |
760 | 714 | withBeforePaste = typeof withBeforePaste !== 'undefined' ? withBeforePaste : true; | |
761 | // Check data precisely - don't open dialog on empty string. | 715 | |
762 | if ( typeof data == 'string' ) | 716 | if ( data ) { |
763 | fire( { | 717 | data.method = 'paste'; |
764 | dataValue: data, | 718 | |
765 | method: 'paste', | 719 | if ( !data.dataTransfer ) { |
766 | dataTransfer: clipboard.initPasteDataTransfer() | 720 | data.dataTransfer = clipboard.initPasteDataTransfer(); |
767 | }, 1 ); | 721 | } |
768 | else | 722 | |
769 | editor.getClipboardData( fire ); | 723 | firePasteEvents( editor, data, withBeforePaste ); |
724 | } else if ( notification ) { | ||
725 | editor.showNotification( msg, 'info', editor.config.clipboard_notificationDuration ); | ||
726 | } | ||
727 | |||
728 | editor.fire( 'afterCommandExec', { | ||
729 | name: 'paste', | ||
730 | command: cmd, | ||
731 | returnValue: !!data | ||
732 | } ); | ||
733 | } | ||
734 | |||
735 | // Force type for the next paste. | ||
736 | if ( forcedType ) { | ||
737 | editor._.nextPasteType = forcedType; | ||
738 | } else { | ||
739 | delete editor._.nextPasteType; | ||
740 | } | ||
741 | |||
742 | if ( typeof pastedContent === 'string' ) { | ||
743 | callback( { | ||
744 | dataValue: pastedContent | ||
745 | } ); | ||
746 | } else { | ||
747 | editor.getClipboardData( callback ); | ||
748 | } | ||
770 | } | 749 | } |
771 | }; | 750 | }; |
772 | } | 751 | } |
@@ -820,7 +799,7 @@ | |||
820 | return enabled; | 799 | return enabled; |
821 | } | 800 | } |
822 | 801 | ||
823 | // Cutting off control type element in IE standards breaks the selection entirely. (#4881) | 802 | // Cutting off control type element in IE standards breaks the selection entirely. (http://dev.ckeditor.com/ticket/4881) |
824 | function fixCut() { | 803 | function fixCut() { |
825 | if ( !CKEDITOR.env.ie || CKEDITOR.env.quirks ) | 804 | if ( !CKEDITOR.env.ie || CKEDITOR.env.quirks ) |
826 | return; | 805 | return; |
@@ -857,14 +836,14 @@ | |||
857 | }, | 836 | }, |
858 | blurListener; | 837 | blurListener; |
859 | 838 | ||
860 | // Avoid recursions on 'paste' event or consequent paste too fast. (#5730) | 839 | // Avoid recursions on 'paste' event or consequent paste too fast. (http://dev.ckeditor.com/ticket/5730) |
861 | if ( doc.getById( 'cke_pastebin' ) ) | 840 | if ( doc.getById( 'cke_pastebin' ) ) |
862 | return; | 841 | return; |
863 | 842 | ||
864 | var sel = editor.getSelection(); | 843 | var sel = editor.getSelection(); |
865 | var bms = sel.createBookmarks(); | 844 | var bms = sel.createBookmarks(); |
866 | 845 | ||
867 | // #11384. On IE9+ we use native selectionchange (i.e. editor#selectionCheck) to cache the most | 846 | // http://dev.ckeditor.com/ticket/11384. On IE9+ we use native selectionchange (i.e. editor#selectionCheck) to cache the most |
868 | // recent selection which we then lock on editable blur. See selection.js for more info. | 847 | // recent selection which we then lock on editable blur. See selection.js for more info. |
869 | // selectionchange fired before getClipboardDataByPastebin() cached selection | 848 | // selectionchange fired before getClipboardDataByPastebin() cached selection |
870 | // before creating bookmark (cached selection will be invalid, because bookmarks modified the DOM), | 849 | // before creating bookmark (cached selection will be invalid, because bookmarks modified the DOM), |
@@ -898,7 +877,7 @@ | |||
898 | // It's better to paste close to the real paste destination, so inherited styles | 877 | // It's better to paste close to the real paste destination, so inherited styles |
899 | // (which Webkits will try to compensate by styling span) differs less from the destination's one. | 878 | // (which Webkits will try to compensate by styling span) differs less from the destination's one. |
900 | editable.append( pastebin ); | 879 | editable.append( pastebin ); |
901 | // Style pastebin like .cke_editable, to minimize differences between origin and destination. (#9754) | 880 | // Style pastebin like .cke_editable, to minimize differences between origin and destination. (http://dev.ckeditor.com/ticket/9754) |
902 | pastebin.addClass( 'cke_editable' ); | 881 | pastebin.addClass( 'cke_editable' ); |
903 | 882 | ||
904 | // Compensate position of offsetParent. | 883 | // Compensate position of offsetParent. |
@@ -932,7 +911,7 @@ | |||
932 | padding: 0 | 911 | padding: 0 |
933 | } ); | 912 | } ); |
934 | 913 | ||
935 | // Paste fails in Safari when the body tag has 'user-select: none'. (#12506) | 914 | // Paste fails in Safari when the body tag has 'user-select: none'. (http://dev.ckeditor.com/ticket/12506) |
936 | if ( CKEDITOR.env.safari ) | 915 | if ( CKEDITOR.env.safari ) |
937 | pastebin.setStyles( CKEDITOR.tools.cssVendorPrefix( 'user-select', 'text' ) ); | 916 | pastebin.setStyles( CKEDITOR.tools.cssVendorPrefix( 'user-select', 'text' ) ); |
938 | 917 | ||
@@ -955,8 +934,8 @@ | |||
955 | 934 | ||
956 | // Webkit fill fire blur on editable when moving selection to | 935 | // Webkit fill fire blur on editable when moving selection to |
957 | // pastebin (if body is used). Cancel it because it causes incorrect | 936 | // pastebin (if body is used). Cancel it because it causes incorrect |
958 | // selection lock in case of inline editor (#10644). | 937 | // selection lock in case of inline editor (http://dev.ckeditor.com/ticket/10644). |
959 | // The same seems to apply to Firefox (#10787). | 938 | // The same seems to apply to Firefox (http://dev.ckeditor.com/ticket/10787). |
960 | if ( CKEDITOR.env.webkit || CKEDITOR.env.gecko ) | 939 | if ( CKEDITOR.env.webkit || CKEDITOR.env.gecko ) |
961 | blurListener = editable.once( 'blur', cancel, null, null, -100 ); | 940 | blurListener = editable.once( 'blur', cancel, null, null, -100 ); |
962 | 941 | ||
@@ -969,7 +948,7 @@ | |||
969 | // If non-native paste is executed, IE will open security alert and blur editable. | 948 | // If non-native paste is executed, IE will open security alert and blur editable. |
970 | // Editable will then lock selection inside itself and after accepting security alert | 949 | // Editable will then lock selection inside itself and after accepting security alert |
971 | // this selection will be restored. We overwrite stored selection, so it's restored | 950 | // this selection will be restored. We overwrite stored selection, so it's restored |
972 | // in pastebin. (#9552) | 951 | // in pastebin. (http://dev.ckeditor.com/ticket/9552) |
973 | if ( CKEDITOR.env.ie ) { | 952 | if ( CKEDITOR.env.ie ) { |
974 | blurListener = editable.once( 'blur', function() { | 953 | blurListener = editable.once( 'blur', function() { |
975 | editor.lockSelection( selPastebin ); | 954 | editor.lockSelection( selPastebin ); |
@@ -981,18 +960,18 @@ | |||
981 | // Wait a while and grab the pasted contents. | 960 | // Wait a while and grab the pasted contents. |
982 | setTimeout( function() { | 961 | setTimeout( function() { |
983 | // Restore main window's scroll position which could have been changed | 962 | // Restore main window's scroll position which could have been changed |
984 | // by browser in cases described in #9771. | 963 | // by browser in cases described in http://dev.ckeditor.com/ticket/9771. |
985 | if ( CKEDITOR.env.webkit ) | 964 | if ( CKEDITOR.env.webkit ) |
986 | CKEDITOR.document.getBody().$.scrollTop = scrollTop; | 965 | CKEDITOR.document.getBody().$.scrollTop = scrollTop; |
987 | 966 | ||
988 | // Blur will be fired only on non-native paste. In other case manually remove listener. | 967 | // Blur will be fired only on non-native paste. In other case manually remove listener. |
989 | blurListener && blurListener.removeListener(); | 968 | blurListener && blurListener.removeListener(); |
990 | 969 | ||
991 | // Restore properly the document focus. (#8849) | 970 | // Restore properly the document focus. (http://dev.ckeditor.com/ticket/8849) |
992 | if ( CKEDITOR.env.ie ) | 971 | if ( CKEDITOR.env.ie ) |
993 | editable.focus(); | 972 | editable.focus(); |
994 | 973 | ||
995 | // IE7: selection must go before removing pastebin. (#8691) | 974 | // IE7: selection must go before removing pastebin. (http://dev.ckeditor.com/ticket/8691) |
996 | sel.selectBookmarks( bms ); | 975 | sel.selectBookmarks( bms ); |
997 | pastebin.remove(); | 976 | pastebin.remove(); |
998 | 977 | ||
@@ -1018,7 +997,6 @@ | |||
1018 | // On other browsers we should fire beforePaste event and return false. | 997 | // On other browsers we should fire beforePaste event and return false. |
1019 | function getClipboardDataDirectly() { | 998 | function getClipboardDataDirectly() { |
1020 | if ( clipboard.mainPasteEvent == 'paste' ) { | 999 | if ( clipboard.mainPasteEvent == 'paste' ) { |
1021 | // beforePaste should be fired when dialog open so it can be canceled. | ||
1022 | editor.fire( 'beforePaste', { type: 'auto', method: 'paste' } ); | 1000 | editor.fire( 'beforePaste', { type: 'auto', method: 'paste' } ); |
1023 | return false; | 1001 | return false; |
1024 | } | 1002 | } |
@@ -1031,7 +1009,7 @@ | |||
1031 | // we're canceling it. | 1009 | // we're canceling it. |
1032 | preventPasteEventNow(); | 1010 | preventPasteEventNow(); |
1033 | 1011 | ||
1034 | // #9247: Lock focus to prevent IE from hiding toolbar for inline editor. | 1012 | // http://dev.ckeditor.com/ticket/9247: Lock focus to prevent IE from hiding toolbar for inline editor. |
1035 | var focusManager = editor.focusManager; | 1013 | var focusManager = editor.focusManager; |
1036 | focusManager.lock(); | 1014 | focusManager.lock(); |
1037 | 1015 | ||
@@ -1074,7 +1052,7 @@ | |||
1074 | editor.fire( 'saveSnapshot' ); // Save before cut | 1052 | editor.fire( 'saveSnapshot' ); // Save before cut |
1075 | setTimeout( function() { | 1053 | setTimeout( function() { |
1076 | editor.fire( 'saveSnapshot' ); // Save after cut | 1054 | editor.fire( 'saveSnapshot' ); // Save after cut |
1077 | }, 50 ); // OSX is slow (#11416). | 1055 | }, 50 ); // OSX is slow (http://dev.ckeditor.com/ticket/11416). |
1078 | } | 1056 | } |
1079 | } | 1057 | } |
1080 | 1058 | ||
@@ -1327,7 +1305,7 @@ | |||
1327 | 1305 | ||
1328 | // -------------- DRAGOVER TOP & BOTTOM -------------- | 1306 | // -------------- DRAGOVER TOP & BOTTOM -------------- |
1329 | 1307 | ||
1330 | // Not allowing dragging on toolbar and bottom (#12613). | 1308 | // Not allowing dragging on toolbar and bottom (http://dev.ckeditor.com/ticket/12613). |
1331 | clipboard.preventDefaultDropOnElement( top ); | 1309 | clipboard.preventDefaultDropOnElement( top ); |
1332 | clipboard.preventDefaultDropOnElement( bottom ); | 1310 | clipboard.preventDefaultDropOnElement( bottom ); |
1333 | 1311 | ||
@@ -1349,7 +1327,7 @@ | |||
1349 | // Save drag range globally for cross editor D&D. | 1327 | // Save drag range globally for cross editor D&D. |
1350 | var dragRange = clipboard.dragRange = editor.getSelection().getRanges()[ 0 ]; | 1328 | var dragRange = clipboard.dragRange = editor.getSelection().getRanges()[ 0 ]; |
1351 | 1329 | ||
1352 | // Store number of children, so we can later tell if any text node was split on drop. (#13011, #13447) | 1330 | // Store number of children, so we can later tell if any text node was split on drop. (http://dev.ckeditor.com/ticket/13011, http://dev.ckeditor.com/ticket/13447) |
1353 | if ( CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) { | 1331 | if ( CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) { |
1354 | clipboard.dragStartContainerChildCount = dragRange ? getContainerChildCount( dragRange.startContainer ) : null; | 1332 | clipboard.dragStartContainerChildCount = dragRange ? getContainerChildCount( dragRange.startContainer ) : null; |
1355 | clipboard.dragEndContainerChildCount = dragRange ? getContainerChildCount( dragRange.endContainer ) : null; | 1333 | clipboard.dragEndContainerChildCount = dragRange ? getContainerChildCount( dragRange.endContainer ) : null; |
@@ -1373,9 +1351,15 @@ | |||
1373 | // we drop image it will overwrite document. | 1351 | // we drop image it will overwrite document. |
1374 | 1352 | ||
1375 | editable.attachListener( dropTarget, 'dragover', function( evt ) { | 1353 | editable.attachListener( dropTarget, 'dragover', function( evt ) { |
1354 | // Edge requires this handler to have `preventDefault()` regardless of the situation. | ||
1355 | if ( CKEDITOR.env.edge ) { | ||
1356 | evt.data.preventDefault(); | ||
1357 | return; | ||
1358 | } | ||
1359 | |||
1376 | var target = evt.data.getTarget(); | 1360 | var target = evt.data.getTarget(); |
1377 | 1361 | ||
1378 | // Prevent reloading page when dragging image on empty document (#12619). | 1362 | // Prevent reloading page when dragging image on empty document (http://dev.ckeditor.com/ticket/12619). |
1379 | if ( target && target.is && target.is( 'html' ) ) { | 1363 | if ( target && target.is && target.is( 'html' ) ) { |
1380 | evt.data.preventDefault(); | 1364 | evt.data.preventDefault(); |
1381 | return; | 1365 | return; |
@@ -1396,7 +1380,7 @@ | |||
1396 | // -------------- DROP -------------- | 1380 | // -------------- DROP -------------- |
1397 | 1381 | ||
1398 | editable.attachListener( dropTarget, 'drop', function( evt ) { | 1382 | editable.attachListener( dropTarget, 'drop', function( evt ) { |
1399 | // Do nothing if event was already prevented. (#13879) | 1383 | // Do nothing if event was already prevented. (http://dev.ckeditor.com/ticket/13879) |
1400 | if ( evt.data.$.defaultPrevented ) { | 1384 | if ( evt.data.$.defaultPrevented ) { |
1401 | return; | 1385 | return; |
1402 | } | 1386 | } |
@@ -1407,7 +1391,7 @@ | |||
1407 | var target = evt.data.getTarget(), | 1391 | var target = evt.data.getTarget(), |
1408 | readOnly = target.isReadOnly(); | 1392 | readOnly = target.isReadOnly(); |
1409 | 1393 | ||
1410 | // Do nothing if drop on non editable element (#13015). | 1394 | // Do nothing if drop on non editable element (http://dev.ckeditor.com/ticket/13015). |
1411 | // The <html> tag isn't editable (body is), but we want to allow drop on it | 1395 | // The <html> tag isn't editable (body is), but we want to allow drop on it |
1412 | // (so it is possible to drop below editor contents). | 1396 | // (so it is possible to drop below editor contents). |
1413 | if ( readOnly && !( target.type == CKEDITOR.NODE_ELEMENT && target.is( 'html' ) ) ) { | 1397 | if ( readOnly && !( target.type == CKEDITOR.NODE_ELEMENT && target.is( 'html' ) ) ) { |
@@ -1582,18 +1566,24 @@ | |||
1582 | } | 1566 | } |
1583 | 1567 | ||
1584 | // In Chrome we can trust Clipboard API, with the exception of Chrome on Android (in both - mobile and desktop modes), where | 1568 | // In Chrome we can trust Clipboard API, with the exception of Chrome on Android (in both - mobile and desktop modes), where |
1585 | // clipboard API is not available so we need to check it (#13187). | 1569 | // clipboard API is not available so we need to check it (http://dev.ckeditor.com/ticket/13187). |
1586 | if ( CKEDITOR.env.chrome && !dataTransfer.isEmpty() ) { | 1570 | if ( CKEDITOR.env.chrome && !dataTransfer.isEmpty() ) { |
1587 | return true; | 1571 | return true; |
1588 | } | 1572 | } |
1589 | 1573 | ||
1590 | // Because of a Firefox bug HTML data are not available in some cases (e.g. paste from Word), in such cases we | 1574 | // Because of a Firefox bug HTML data are not available in some cases (e.g. paste from Word), in such cases we |
1591 | // need to use the pastebin (#13528, https://bugzilla.mozilla.org/show_bug.cgi?id=1183686). | 1575 | // need to use the pastebin (http://dev.ckeditor.com/ticket/13528, https://bugzilla.mozilla.org/show_bug.cgi?id=1183686). |
1592 | if ( CKEDITOR.env.gecko && ( dataTransfer.getData( 'text/html' ) || dataTransfer.getFilesCount() ) ) { | 1576 | if ( CKEDITOR.env.gecko && ( dataTransfer.getData( 'text/html' ) || dataTransfer.getFilesCount() ) ) { |
1593 | return true; | 1577 | return true; |
1594 | } | 1578 | } |
1595 | 1579 | ||
1596 | // In Safari and IE HTML data is not available though the Clipboard API. | 1580 | // Safari fixed clipboard in 10.1 (https://bugs.webkit.org/show_bug.cgi?id=19893) (http://dev.ckeditor.com/ticket/16982). |
1581 | // However iOS version still doesn't work well enough (https://bugs.webkit.org/show_bug.cgi?id=19893#c34). | ||
1582 | if ( CKEDITOR.env.safari && CKEDITOR.env.version >= 603 && !CKEDITOR.env.iOS ) { | ||
1583 | return true; | ||
1584 | } | ||
1585 | |||
1586 | // In older Safari and IE HTML data is not available though the Clipboard API. | ||
1597 | // In Edge things are a bit messy at the moment - | 1587 | // In Edge things are a bit messy at the moment - |
1598 | // https://connect.microsoft.com/IE/feedback/details/1572456/edge-clipboard-api-text-html-content-messed-up-in-event-clipboarddata | 1588 | // https://connect.microsoft.com/IE/feedback/details/1572456/edge-clipboard-api-text-html-content-messed-up-in-event-clipboarddata |
1599 | // It is safer to use the paste bin in unknown cases. | 1589 | // It is safer to use the paste bin in unknown cases. |
@@ -1610,8 +1600,8 @@ | |||
1610 | getDropTarget: function( editor ) { | 1600 | getDropTarget: function( editor ) { |
1611 | var editable = editor.editable(); | 1601 | var editable = editor.editable(); |
1612 | 1602 | ||
1613 | // #11123 Firefox needs to listen on document, because otherwise event won't be fired. | 1603 | // http://dev.ckeditor.com/ticket/11123 Firefox needs to listen on document, because otherwise event won't be fired. |
1614 | // #11086 IE8 cannot listen on document. | 1604 | // http://dev.ckeditor.com/ticket/11086 IE8 cannot listen on document. |
1615 | if ( ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) || editable.isInline() ) { | 1605 | if ( ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) || editable.isInline() ) { |
1616 | return editable; | 1606 | return editable; |
1617 | } else { | 1607 | } else { |
@@ -1809,7 +1799,7 @@ | |||
1809 | // Check if drop range is inside range. | 1799 | // Check if drop range is inside range. |
1810 | // This is an edge case when we drop something on editable's margin/padding. | 1800 | // This is an edge case when we drop something on editable's margin/padding. |
1811 | // That space is not treated as a part of the range we drag, so it is possible to drop there. | 1801 | // That space is not treated as a part of the range we drag, so it is possible to drop there. |
1812 | // When we drop, browser tries to find closest drop position and it finds it inside drag range. (#13453) | 1802 | // When we drop, browser tries to find closest drop position and it finds it inside drag range. (http://dev.ckeditor.com/ticket/13453) |
1813 | var startNode = dragBookmark.startNode, | 1803 | var startNode = dragBookmark.startNode, |
1814 | endNode = dragBookmark.endNode, | 1804 | endNode = dragBookmark.endNode, |
1815 | dropNode = dropBookmark.startNode, | 1805 | dropNode = dropBookmark.startNode, |
@@ -1863,7 +1853,7 @@ | |||
1863 | return dropEvt.data.testRange; | 1853 | return dropEvt.data.testRange; |
1864 | 1854 | ||
1865 | // Webkits. | 1855 | // Webkits. |
1866 | if ( document.caretRangeFromPoint ) { | 1856 | if ( document.caretRangeFromPoint && editor.document.$.caretRangeFromPoint( x, y ) ) { |
1867 | $range = editor.document.$.caretRangeFromPoint( x, y ); | 1857 | $range = editor.document.$.caretRangeFromPoint( x, y ); |
1868 | range.setStart( CKEDITOR.dom.node( $range.startContainer ), $range.startOffset ); | 1858 | range.setStart( CKEDITOR.dom.node( $range.startContainer ), $range.startOffset ); |
1869 | range.collapse( true ); | 1859 | range.collapse( true ); |
@@ -2089,7 +2079,7 @@ | |||
2089 | */ | 2079 | */ |
2090 | initPasteDataTransfer: function( evt, sourceEditor ) { | 2080 | initPasteDataTransfer: function( evt, sourceEditor ) { |
2091 | if ( !this.isCustomCopyCutSupported ) { | 2081 | if ( !this.isCustomCopyCutSupported ) { |
2092 | // Edge does not support custom copy/cut, but it have some useful data in the clipboardData (#13755). | 2082 | // Edge does not support custom copy/cut, but it have some useful data in the clipboardData (http://dev.ckeditor.com/ticket/13755). |
2093 | return new this.dataTransfer( ( CKEDITOR.env.edge && evt && evt.data.$ && evt.data.$.clipboardData ) || null, sourceEditor ); | 2083 | return new this.dataTransfer( ( CKEDITOR.env.edge && evt && evt.data.$ && evt.data.$.clipboardData ) || null, sourceEditor ); |
2094 | } else if ( evt && evt.data && evt.data.$ ) { | 2084 | } else if ( evt && evt.data && evt.data.$ ) { |
2095 | var dataTransfer = new this.dataTransfer( evt.data.$.clipboardData, sourceEditor ); | 2085 | var dataTransfer = new this.dataTransfer( evt.data.$.clipboardData, sourceEditor ); |
@@ -2270,13 +2260,31 @@ | |||
2270 | * Facade for the native `getData` method. | 2260 | * Facade for the native `getData` method. |
2271 | * | 2261 | * |
2272 | * @param {String} type The type of data to retrieve. | 2262 | * @param {String} type The type of data to retrieve. |
2263 | * @param {Boolean} [getNative=false] Indicates if the whole, original content of the dataTransfer should be returned. | ||
2264 | * Introduced in CKEditor 4.7.0. | ||
2273 | * @returns {String} type Stored data for the given type or an empty string if the data for that type does not exist. | 2265 | * @returns {String} type Stored data for the given type or an empty string if the data for that type does not exist. |
2274 | */ | 2266 | */ |
2275 | getData: function( type ) { | 2267 | getData: function( type, getNative ) { |
2276 | function isEmpty( data ) { | 2268 | function isEmpty( data ) { |
2277 | return data === undefined || data === null || data === ''; | 2269 | return data === undefined || data === null || data === ''; |
2278 | } | 2270 | } |
2279 | 2271 | ||
2272 | function filterUnwantedCharacters( data ) { | ||
2273 | if ( typeof data !== 'string' ) { | ||
2274 | return data; | ||
2275 | } | ||
2276 | |||
2277 | var htmlEnd = data.indexOf( '</html>' ); | ||
2278 | |||
2279 | if ( htmlEnd !== -1 ) { | ||
2280 | // Just cut everything after `</html>`, so everything after htmlEnd index + length of `</html>`. | ||
2281 | // Required to workaround bug: https://bugs.chromium.org/p/chromium/issues/detail?id=696978 | ||
2282 | return data.substring( 0, htmlEnd + 7 ); | ||
2283 | } | ||
2284 | |||
2285 | return data; | ||
2286 | } | ||
2287 | |||
2280 | type = this._.normalizeType( type ); | 2288 | type = this._.normalizeType( type ); |
2281 | 2289 | ||
2282 | var data = this._.data[ type ], | 2290 | var data = this._.data[ type ], |
@@ -2297,8 +2305,9 @@ | |||
2297 | // This code removes meta tags and returns only the contents of the <body> element if found. Note that | 2305 | // This code removes meta tags and returns only the contents of the <body> element if found. Note that |
2298 | // some significant content may be placed outside Start/EndFragment comments so it's kept. | 2306 | // some significant content may be placed outside Start/EndFragment comments so it's kept. |
2299 | // | 2307 | // |
2300 | // See #13583 for more details. | 2308 | // See http://dev.ckeditor.com/ticket/13583 for more details. |
2301 | if ( type == 'text/html' ) { | 2309 | // Additionally http://dev.ckeditor.com/ticket/16847 adds a flag allowing to get the whole, original content. |
2310 | if ( type == 'text/html' && !getNative ) { | ||
2302 | data = data.replace( this._.metaRegExp, '' ); | 2311 | data = data.replace( this._.metaRegExp, '' ); |
2303 | 2312 | ||
2304 | // Keep only contents of the <body> element | 2313 | // Keep only contents of the <body> element |
@@ -2318,7 +2327,7 @@ | |||
2318 | data = ''; | 2327 | data = ''; |
2319 | } | 2328 | } |
2320 | 2329 | ||
2321 | return data; | 2330 | return filterUnwantedCharacters( data ); |
2322 | }, | 2331 | }, |
2323 | 2332 | ||
2324 | /** | 2333 | /** |
@@ -2339,7 +2348,7 @@ | |||
2339 | } | 2348 | } |
2340 | 2349 | ||
2341 | // If we use the text type to bind the ID, then if someone tries to set the text, we must also | 2350 | // If we use the text type to bind the ID, then if someone tries to set the text, we must also |
2342 | // update ID accordingly. #13468. | 2351 | // update ID accordingly. http://dev.ckeditor.com/ticket/13468. |
2343 | if ( clipboardIdDataType == 'Text' && type == 'Text' ) { | 2352 | if ( clipboardIdDataType == 'Text' && type == 'Text' ) { |
2344 | this.id = value; | 2353 | this.id = value; |
2345 | } | 2354 | } |
@@ -2384,7 +2393,7 @@ | |||
2384 | function getAndSetData( type ) { | 2393 | function getAndSetData( type ) { |
2385 | type = that._.normalizeType( type ); | 2394 | type = that._.normalizeType( type ); |
2386 | 2395 | ||
2387 | var data = that.getData( type ); | 2396 | var data = that.getData( type, true ); |
2388 | if ( data ) { | 2397 | if ( data ) { |
2389 | that._.data[ type ] = data; | 2398 | that._.data[ type ] = data; |
2390 | } | 2399 | } |
@@ -2407,7 +2416,7 @@ | |||
2407 | if ( ( this.$ && this.$.files ) || file ) { | 2416 | if ( ( this.$ && this.$.files ) || file ) { |
2408 | this._.files = []; | 2417 | this._.files = []; |
2409 | 2418 | ||
2410 | // Edge have empty files property with no length (#13755). | 2419 | // Edge have empty files property with no length (http://dev.ckeditor.com/ticket/13755). |
2411 | if ( this.$.files && this.$.files.length ) { | 2420 | if ( this.$.files && this.$.files.length ) { |
2412 | for ( i = 0; i < this.$.files.length; i++ ) { | 2421 | for ( i = 0; i < this.$.files.length; i++ ) { |
2413 | this._.files.push( this.$.files[ i ] ); | 2422 | this._.files.push( this.$.files[ i ] ); |
@@ -2507,7 +2516,7 @@ | |||
2507 | 2516 | ||
2508 | /** | 2517 | /** |
2509 | * When the content of the clipboard is pasted in Chrome, the clipboard data object has an empty `files` property, | 2518 | * When the content of the clipboard is pasted in Chrome, the clipboard data object has an empty `files` property, |
2510 | * but it is possible to get the file as `items[0].getAsFile();` (#12961). | 2519 | * but it is possible to get the file as `items[0].getAsFile();` (http://dev.ckeditor.com/ticket/12961). |
2511 | * | 2520 | * |
2512 | * @private | 2521 | * @private |
2513 | * @returns {File} File instance or `null` if not found. | 2522 | * @returns {File} File instance or `null` if not found. |
@@ -2593,7 +2602,7 @@ | |||
2593 | * @member CKEDITOR.editor | 2602 | * @member CKEDITOR.editor |
2594 | */ | 2603 | */ |
2595 | 2604 | ||
2596 | /** | 2605 | /** |
2597 | * Fired after the {@link #paste} event if content was modified. Note that if the paste | 2606 | * Fired after the {@link #paste} event if content was modified. Note that if the paste |
2598 | * event does not insert any data, the `afterPaste` event will not be fired. | 2607 | * event does not insert any data, the `afterPaste` event will not be fired. |
2599 | * | 2608 | * |
@@ -2602,16 +2611,6 @@ | |||
2602 | */ | 2611 | */ |
2603 | 2612 | ||
2604 | /** | 2613 | /** |
2605 | * Internal event to open the Paste dialog window. | ||
2606 | * | ||
2607 | * @private | ||
2608 | * @event pasteDialog | ||
2609 | * @member CKEDITOR.editor | ||
2610 | * @param {CKEDITOR.editor} editor This editor instance. | ||
2611 | * @param {Function} [data] Callback that will be passed to {@link CKEDITOR.editor#openDialog}. | ||
2612 | */ | ||
2613 | |||
2614 | /** | ||
2615 | * Facade for the native `drop` event. Fired when the native `drop` event occurs. | 2614 | * Facade for the native `drop` event. Fired when the native `drop` event occurs. |
2616 | * | 2615 | * |
2617 | * **Note:** To manipulate dropped data, use the {@link CKEDITOR.editor#paste} event. | 2616 | * **Note:** To manipulate dropped data, use the {@link CKEDITOR.editor#paste} event. |
@@ -2770,3 +2769,12 @@ | |||
2770 | * @property {CKEDITOR.filter} [pasteFilter] | 2769 | * @property {CKEDITOR.filter} [pasteFilter] |
2771 | * @member CKEDITOR.editor | 2770 | * @member CKEDITOR.editor |
2772 | */ | 2771 | */ |
2772 | |||
2773 | /** | ||
2774 | * Duration of the notification displayed after pasting was blocked by the browser. | ||
2775 | * | ||
2776 | * @since 4.7.0 | ||
2777 | * @cfg {Number} [clipboard_notificationDuration=10000] | ||
2778 | * @member CKEDITOR.config | ||
2779 | */ | ||
2780 | CKEDITOR.config.clipboard_notificationDuration = 10000; | ||