Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Below is including file uploading feature.

Code Block
<!DOCTYPE html>
<html lang="en">
    <head>
        <html>
	<head>
		<title>CKEditor 5 ClassicEditor build</title>
		<meta charset="UTF-8">
		<meta name="viewport"   </head>
    <body>
        <style>
            #container {
                width: 1000px;
                margin: 20px auto;
            }
            .ck-editor__editable[role="textbox"] {
                /* editing area */
                min-height: 200px;
            }
            .ck-content .image {
                /* block images */
                max-width: 80%;
                margin: 20px auto;
            }
        </style>
        <div id="container">
            <div id="editor">
            </div>
        </div>
        <!--
            The "super-build" of CKEditor 5 served via CDN contains a large set of plugins and multiple editor types.
            See https://ckeditor.com/docs/ckeditor5/latest/installation/getting-started/quick-start.html#running-a-full-featured-editor-from-cdn
        -->
        <script src="https://cdn.ckeditor.com/ckeditor5/40.1.0/super-build/ckeditor.js"></script>
        <!--
            Uncomment to load the Spanish translation
            <script src="https://cdn.ckeditor.com/ckeditor5/40.1.0/super-build/translations/es.js"></script>
        -->
        <script>
            // This sample still does not showcase all CKEditor 5 features (!)
            // Visit https://ckeditor.com/docs/ckeditor5/latest/features/index.html to browse all the features.
            CKEDITOR.ClassicEditor.create(document.getElementById("editor"), {
                // https://ckeditor.com/docs/ckeditor5/latest/features/toolbar/toolbar.html#extended-toolbar-configuration-format
                toolbar: {
                    items: [
                        'exportPDF','exportWord', '|',
                        'findAndReplace', 'selectAll', '|',
                        'heading', '|',
                        'bold', 'italic', 'strikethrough', 'underline', 'code', 'subscript', 'superscript', 'removeFormat', '|',
                        'bulletedList', 'numberedList', 'todoList', '|',
                        'outdent', 'indent', '|',
                        'undo', 'redo',
                        '-',
                        'fontSize', 'fontFamily', 'fontColor', 'fontBackgroundColor', 'highlight', '|',
                        'alignment', '|',
                        'link', 'insertImage', 'blockQuote', 'insertTable', 'mediaEmbed', 'codeBlock', 'htmlEmbed', '|',
                        'specialCharacters', 'horizontalLine', 'pageBreak', '|',
                        'textPartLanguage', '|',
                        'sourceEditing'
                    ],
                    shouldNotGroupWhenFull: true
                },
                // Changing the language of the interface requires loading the language file using the <script> tag.
                // language: 'es',
                list: {
                    properties: {
                        styles: true,
                        startIndex: true,
                        reversed: true
                    }
                },
                // https://ckeditor.com/docs/ckeditor5/latest/features/headings.html#configuration
                heading: {
                    options: [
                        { model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
                        { model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' },
                        { model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' },
                        { model: 'heading3', view: 'h3', title: 'Heading 3', class: 'ck-heading_heading3' },
                        { model: 'heading4', view: 'h4', title: 'Heading 4', class: 'ck-heading_heading4' },
                        { model: 'heading5', view: 'h5', title: 'Heading 5', class: 'ck-heading_heading5' },
                        { model: 'heading6', view: 'h6', title: 'Heading 6', class: 'ck-heading_heading6' }
                    ]
                },
                // https://ckeditor.com/docs/ckeditor5/latest/features/editor-placeholder.html#using-the-editor-configuration
                placeholder: 'Welcome to CKEditor 5!',
                // https://ckeditor.com/docs/ckeditor5/latest/features/font.html#configuring-the-font-family-feature
                fontFamily: {
                    options: [
                        'default',
                        'Arial, Helvetica, sans-serif',
                        'Courier New, Courier, monospace',
                        'Georgia, serif',
                        'Lucida Sans Unicode, Lucida Grande, sans-serif',
                        'Tahoma, Geneva, sans-serif',
                        'Times New Roman, Times, serif',
                        'Trebuchet MS, Helvetica, sans-serif',
                        'Verdana, Geneva, sans-serif'
                    ],
                    supportAllValues: true
                },
                // https://ckeditor.com/docs/ckeditor5/latest/features/font.html#configuring-the-font-size-feature
                fontSize: {
                    options: [ 10, 12, 14, 'default', 18, 20, 22 ],
                    supportAllValues: true
                },
                // Be careful with the setting below. It instructs CKEditor to accept ALL HTML markup.
                // https://ckeditor.com/docs/ckeditor5/latest/features/general-html-support.html#enabling-all-html-features
                htmlSupport: {
                    allow: [
                        {
                            name: /.*/,
                            attributes: true,
                            classes: true,
                            styles: true
                        }
                    ]
                },
                // Be careful with enabling previews
                // https://ckeditor.com/docs/ckeditor5/latest/features/html-embed.html#content-previews
                htmlEmbed: {
                    showPreviews: true
                },
                // https://ckeditor.com/docs/ckeditor5/latest/features/link.html#custom-link-attributes-decorators
                link: {
                    decorators: {
                        addTargetToExternalLinks: true,
                        defaultProtocol: 'https://',
                        toggleDownloadable: {
                            mode: 'manual',
                            label: 'Downloadable',
                            attributes: {
                                download: 'file'
                            }
                        }
                    }
                },
                // https://ckeditor.com/docs/ckeditor5/latest/features/mentions.html#configuration
                mention: {
                    feeds: [
                        {
                            marker: '@',
                            feed: [
                                '@apple', '@bears', '@brownie', '@cake', '@cake', '@candy', '@canes', '@chocolate', '@cookie', '@cotton', '@cream',
                                '@cupcake', '@danish', '@donut', '@dragée', '@fruitcake', '@gingerbread', '@gummi', '@ice', '@jelly-o',
                                '@liquorice', '@macaroon', '@marzipan', '@oat', '@pie', '@plum', '@pudding', '@sesame', '@snaps', '@soufflé',
                                '@sugar', '@sweet', '@topping', '@wafer'
                            ],
                            minimumCharacters: 1
                        }
                    ]
                },
                // The "super-build" contains more premium features that require additional configuration, disable them below.
                // Do not turn them on unless you read the documentation and know how to configure them and setup the editor.
                removePlugins: [
                    // These two are commercial, but you can try them out without registering to a trial.
                    // 'ExportPdf',
                    // 'ExportWord',
                    'AIAssistant',
                    'CKBox',
                    'CKFinder',
                    'EasyImage',
                    // This sample uses the Base64UploadAdapter to handle image uploads as it requires no configuration.
                    // https://ckeditor.com/docs/ckeditor5/latest/features/images/image-upload/base64-upload-adapter.html
                    // Storing images as Base64 is usually a very bad idea.
                    // Replace it on production website with other solutions:
                    // https://ckeditor.com/docs/ckeditor5/latest/features/images/image-upload/image-upload.html
                    // 'Base64UploadAdapter',
                    'RealTimeCollaborativeComments',
                    'RealTimeCollaborativeTrackChanges',
                    'RealTimeCollaborativeRevisionHistory',
                    'PresenceList',
                    'Comments',
                    'TrackChanges',
                    'TrackChangesData',
                    'RevisionHistory',
                    'Pagination',
                    'WProofreader',
                    // Careful, with the Mathtype plugin CKEditor will not load when loading this sample
                    // from a local file system (file://) - load this site via HTTP server if you enable MathType.
                    'MathType',
                    // The following features are part of the Productivity Pack and require additional license.
                    'SlashCommand',
                    'Template',
                    'DocumentOutline',
                    'FormatPainter',
                    'TableOfContents',
                    'PasteFromOfficeEnhanced'
                ]
            });
        </script>
    </body>
</html>

Implementing upload feature with CKEditor 5

content="width=device-width, initial-scale=1">
		<link rel="stylesheet" type="text/css" href="styles.css">
	</head>
	<body>
		<div id="editor">
			
		</div>
		<script src="ck/ckeditor.js"></script>
		<script>
			ClassicEditor
				.create( document.querySelector( '#editor' ), {
					simpleUpload: {
						// The URL that the images are uploaded to.
						uploadUrl: 'upload.php',
					}
				} )
				.then( editor => {
					window.editor = editor;
				} )
				.catch( err => {
					console.error( err.stack );
				} );
		</script>
	</body>
</html>

You will need to have following upload.php to save the necessary files as planned.

Code Block
<?php
// Define file upload path 
$upload_dir = array( 
    'img'=> './', 
); 
 
// Allowed image properties  
$imgset = array( 
    'maxsize' => 5000, 
    'maxwidth' => 4096, 
    'maxheight' => 3000, 
    'minwidth' => 10, 
    'minheight' => 10, 
    'type' => array('bmp', 'gif', 'jpg', 'jpeg', 'png'), 
); 
 
// If 0, will OVERWRITE the existing file 
define('RENAME_F', 1); 
 
$site = ''; 
 
/** 
 * Set filename 
 * If the file exists, and RENAME_F is 1, set "img_name_1" 
 * 
 * $p = dir-path, $fn=filename to check, $ex=extension $i=index to rename 
 */ 
function setFName($p, $fn, $ex, $i){ 
    if(RENAME_F ==1 && file_exists($p .$fn .$ex)){ 
        return setFName($p, F_NAME .'_'. ($i +1), $ex, ($i +1)); 
    }else{ 
        return $fn .$ex; 
    } 
} 
 
$re = ''; 
if(isset($_FILES['upload']) && strlen($_FILES['upload']['name']) > 1) { 
 
    define('F_NAME', preg_replace('/\.(.+?)$/i', '', basename($_FILES['upload']['name'])));   
 
    // Get filename without extension 
    $sepext = explode('.', strtolower($_FILES['upload']['name'])); 
    $type = end($sepext);    /** gets extension **/ 
     
    // Upload directory 
    $upload_dir = in_array($type, $imgset['type']) ? $upload_dir['img'] : $upload_dir['audio']; 
    $upload_dir = trim($upload_dir, '/') .'/'; 
 
    // Validate file type 
    if(in_array($type, $imgset['type'])){ 
        // Image width and height 
        list($width, $height) = getimagesize($_FILES['upload']['tmp_name']); 
 
        if(isset($width) && isset($height)) { 
            if($width > $imgset['maxwidth'] || $height > $imgset['maxheight']){ 
                $re .= ' Width x Height = '. $width .' x '. $height .' >>> The maximum Width x Height must be: '. $imgset['maxwidth']. ' x '. $imgset['maxheight']; 
 
Code Block
languagexml
titleindex.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CKEditor 5 File Upload</title>
    <script src="https://cdn.ckeditor.com/ckeditor5/44.0.0/classic/ckeditor.js"></script>
    <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
</head>
<body>
    <textarea id="editor"></textarea>

    <script>
        ClassicEditor
            .create(document.querySelector('#editor'), {
           } 
 
   // CKEditor configuration options
      if($width < $imgset['minwidth'] || $height  })< $imgset['minheight']){ 
            .catch(error => {
   $re .= ' Width x Height = '. $width .' x '. $height console.error(error);
            });

.' >>> The minimum Width x Height must be: '. $imgset['minwidth']. ' x '. $imgset['minheight']; 
           function uploadFile(file)} {
 
           const formData = new FormData();
 if($_FILES['upload']['size'] > $imgset['maxsize']*1000){ 
             formData.append('file', file);

            $.ajax({   $re .= ' >>> Maximum file size must be: '. $imgset['maxsize']. ' KB.'; 
            } 
   url: 'upload.php', // Your PHP script for handling} uploads
    }else{ 
        $re .= 'The typefile: 'POST',
                data: formData,'. $_FILES['upload']['name']. ' has not the allowed extension type.'; 
    } 
     
    // File upload processData:path false,
    $f_name = setFName($_SERVER['DOCUMENT_ROOT'] .'/'. $upload_dir, F_NAME, ".$type", 0); 
    $uploadpath contentType: false,
    = $upload_dir . $f_name; 
 
    // If no errors, upload the image, else, success:output functionthe (data)errors {
    if($re == ''){ 
             console.log('File uploaded successfully:', data);
  if(move_uploaded_file($_FILES['upload']['tmp_name'], $uploadpath)) { 
            $url  },
   = $upload_dir . $f_name; 
            $msg error: function (error) {
                    console.error('Error uploading file:', error);= F_NAME .'.'. $type .' successfully uploaded! >>> Size: '. number_format($_FILES['upload']['size']/1024, 2, '.', '') .' KB'; 
            $response = [ 
 }
            });
   'url' => $url 
  }

        // Listen for]; the
 'change' event on the file input in the}else{ editor
        document.querySelector('#editor input[type="file"]').addEventListener('change', (event) => {
$response = [ 
         const file = event.target.files[0];
    'error' => [ 
     if (file) {
             'message' =>  uploadFile(file);
   'Unable to upload the file!' 
         }
       ] });
    </script>
</body>
</html>
Code Block
languagephp
titleupload.php
<?php
// Check if the file was uploaded without errors
if ($_FILES['file']['error'] === UPLOAD_ERR_OK) {
]; 
       $uploadDir = 'uploads/'; // Adjust the upload directory} 
    }else{ 
    $uploadFile   = $uploadDir$response .= basename($_FILES['file']['name']);

[ 
       // Move the uploaded file to the desired directory'error' => [ 
    if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadFile)) {
        echo json_encode(['successmessage' => true,'Error: 'url' => $uploadFile]);
    } else {
.$re 
         echo json_encode(['success' => false, 'error' => 'Failed to move the uploaded file.']);   ] 
        ]; 
    } 
} else
 {
// Return response in JSON format 
echo json_encode(['success' => false, 'error' => 'File upload failed.']$response); 
}
?>