plugin.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /**
  2. * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  4. */
  5. 'use strict';
  6. ( function() {
  7. var uniqueNameCounter = 0,
  8. // Black rectangle which is shown before the image is loaded.
  9. loadingImage = 'data:image/gif;base64,R0lGODlhDgAOAIAAAAAAAP///yH5BAAAAAAALAAAAAAOAA4AAAIMhI+py+0Po5y02qsKADs=';
  10. // Returns number as a string. If a number has 1 digit only it returns it prefixed with an extra 0.
  11. function padNumber( input ) {
  12. if ( input <= 9 ) {
  13. input = '0' + input;
  14. }
  15. return String( input );
  16. }
  17. // Returns a unique image file name.
  18. function getUniqueImageFileName( type ) {
  19. var date = new Date(),
  20. dateParts = [ date.getFullYear(), date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds() ];
  21. uniqueNameCounter += 1;
  22. return 'image-' + CKEDITOR.tools.array.map( dateParts, padNumber ).join( '' ) + '-' + uniqueNameCounter + '.' + type;
  23. }
  24. CKEDITOR.plugins.add( 'uploadimage', {
  25. requires: 'uploadwidget',
  26. onLoad: function() {
  27. CKEDITOR.addCss(
  28. '.cke_upload_uploading img{' +
  29. 'opacity: 0.3' +
  30. '}'
  31. );
  32. },
  33. init: function( editor ) {
  34. // Do not execute this paste listener if it will not be possible to upload file.
  35. if ( !CKEDITOR.plugins.clipboard.isFileApiSupported ) {
  36. return;
  37. }
  38. var fileTools = CKEDITOR.fileTools,
  39. uploadUrl = fileTools.getUploadUrl( editor.config, 'image' );
  40. if ( !uploadUrl ) {
  41. return;
  42. }
  43. // Handle images which are available in the dataTransfer.
  44. fileTools.addUploadWidget( editor, 'uploadimage', {
  45. supportedTypes: /image\/(jpeg|png|gif|bmp)/,
  46. uploadUrl: uploadUrl,
  47. fileToElement: function() {
  48. var img = new CKEDITOR.dom.element( 'img' );
  49. img.setAttribute( 'src', loadingImage );
  50. return img;
  51. },
  52. parts: {
  53. img: 'img'
  54. },
  55. onUploading: function( upload ) {
  56. // Show the image during the upload.
  57. this.parts.img.setAttribute( 'src', upload.data );
  58. },
  59. onUploaded: function( upload ) {
  60. // Width and height could be returned by server (https://dev.ckeditor.com/ticket/13519).
  61. var $img = this.parts.img.$,
  62. width = upload.responseData.width || $img.naturalWidth,
  63. height = upload.responseData.height || $img.naturalHeight;
  64. // Set width and height to prevent blinking.
  65. this.replaceWith( '<img src="' + upload.url + '" ' +
  66. 'width="' + width + '" ' +
  67. 'height="' + height + '">' );
  68. }
  69. } );
  70. // Handle images which are not available in the dataTransfer.
  71. // This means that we need to read them from the <img src="data:..."> elements.
  72. editor.on( 'paste', function( evt ) {
  73. // For performance reason do not parse data if it does not contain img tag and data attribute.
  74. if ( !evt.data.dataValue.match( /<img[\s\S]+data:/i ) ) {
  75. return;
  76. }
  77. var data = evt.data,
  78. // Prevent XSS attacks.
  79. tempDoc = document.implementation.createHTMLDocument( '' ),
  80. temp = new CKEDITOR.dom.element( tempDoc.body ),
  81. imgs, img, i;
  82. // Without this isReadOnly will not works properly.
  83. temp.data( 'cke-editable', 1 );
  84. temp.appendHtml( data.dataValue );
  85. imgs = temp.find( 'img' );
  86. for ( i = 0; i < imgs.count(); i++ ) {
  87. img = imgs.getItem( i );
  88. // Assign src once, as it might be a big string, so there's no point in duplicating it all over the place.
  89. var imgSrc = img.getAttribute( 'src' ),
  90. // Image have to contain src=data:...
  91. isDataInSrc = imgSrc && imgSrc.substring( 0, 5 ) == 'data:',
  92. isRealObject = img.data( 'cke-realelement' ) === null;
  93. // We are not uploading images in non-editable blocs and fake objects (https://dev.ckeditor.com/ticket/13003).
  94. if ( isDataInSrc && isRealObject && !img.data( 'cke-upload-id' ) && !img.isReadOnly( 1 ) ) {
  95. // Note that normally we'd extract this logic into a separate function, but we should not duplicate this string, as it might
  96. // be large.
  97. var imgFormat = imgSrc.match( /image\/([a-z]+?);/i ),
  98. loader;
  99. imgFormat = ( imgFormat && imgFormat[ 1 ] ) || 'jpg';
  100. loader = editor.uploadRepository.create( imgSrc, getUniqueImageFileName( imgFormat ) );
  101. loader.upload( uploadUrl );
  102. fileTools.markElement( img, 'uploadimage', loader.id );
  103. fileTools.bindNotifications( editor, loader );
  104. }
  105. }
  106. data.dataValue = temp.getHtml();
  107. } );
  108. }
  109. } );
  110. /**
  111. * The URL where images should be uploaded.
  112. *
  113. * @since 4.5
  114. * @cfg {String} [imageUploadUrl='' (empty string = disabled)]
  115. * @member CKEDITOR.config
  116. */
  117. } )();