Reference
STEP 1. Download CK Editor
We have to options
CKEditor5
The first option is to use online builder at Option 1) Download through CK Editor online builder: https://ckeditor.com/ckeditor-5/online-builder/You can select features what you want to have.
- The benefit of the online-builder is that you
...
- do not need to install NPM and all other necessary binaries to get what you want.
- The below is the one I acquired at the online builder that does not include premium libraries that have to pay by the cases.
ckeditor5-40.1.0_2023_12_09.zip
ckeditor5-40.2.0-2023_12_22i.zip (Excluding Markdown, General HTML Support, Text part language, Style, Word Count, Watchdog)
By the model there are some options basically included as below:
Reference link: https://ckeditor.com/docs/ckeditor5/latest/installation/getting-started/predefined-builds.html
STEP 2. Implement Code
Below is the simple test code. Note that you should change <the_folder_where_you_saved> to the correct location.
Unfortunately this does not gave me the correct result.
Option 2) Download through NPM
Below is my script to download the necessary assets
Code Block |
---|
#!/bin/bash
npm install --save @ckeditor/ckeditor5-build-classic |
STEP 2.
Example of the simple editor from CDN
Code Block |
---|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>CKEditor 5 – Classic editor</title> <script src="https://cdn.ckeditor.com/ckeditor5/40.1.0/classic/ckeditor.js"></script> </<the_folder_where_you_saved>/ckeditor.js"></script> </head> <body> <h1>Classic editor</h1> <div id="editor"> <p>This is some sample content.</p> </div> <script> ClassicEditor .create( document.querySelector( '#editor' ) ) .catch( error => { console.error( error ); } ); </script> </body> </html> |
Example of the full-featured editor from CDN
Below is including file uploading feature.
Code Block | ||||
---|---|---|---|---|
| ||||
<html>
<head>
<title>CKEditor 5 ClassicEditor build</title>
| ||||
Code Block | ||||
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" href="styles.css"> </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
<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 | ||||
| ||||
<!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 | ||||
| ||||
<?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); } ?> |