Created | ![]() |
Favourites | Opened | Upvotes | Comments |
4. Oct 2019 | 2 | 0 | 380 | 0 | 0 |
CK5 Screenshot is a commercial CKEditor 5 plugin that allows you to add screenshots as popovers to your text - this allows heavy use of images to support your text without using real screen estate.
Index :
If you are already experienced with building a CKEditor 5, here is a condensed usage documentation to get you up an running fast (otherwise go to the Detailed Usage Documentation)
// app.js
import ClassicEditorBase from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
import Heading from '@ckeditor/ckeditor5-heading/src/heading';
import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
import Link from '@ckeditor/ckeditor5-link/src/link';
import List from '@ckeditor/ckeditor5-list/src/list';
import Screenshot from '@ckpro/ckeditor5-screenshot'; // ADD THIS (1/4)
export default class ClassicEditor extends ClassicEditorBase { }
ClassicEditor
.create(document.querySelector('#editor'), {
plugins: [
Heading, // should always be loaded (otherwise among others paragraphs cannot be modelled)
Essentials, // should always be loaded (otherwise among others the editor cannot recieve keyboard input)
Bold,
List,
Screenshot // ADD THIS (2/4)
],
toolbar: [
'heading', // even though the Heading plugin should be loaded, it is not strictly necessary to add it to the toolbar (though most often you want)
'bold',
'bulletedList',
'numberedList',
'screenshot' // ADD THIS (3/4)
],
// ADD THIS (4/4)
screenshot: {
uploadUrl: '/Images/ImageUpload',
uploadParamName: 'upload' // the param name at the http endpoint (above /Images/ImageUpload)
}
})
.then(editor => {
window.editor = editor;
})
.catch(error => {
console.error(error.stack);
});
If you are relatively new to building CKEditor 5 from source, this detailed usage documentation will hold your hand - how to build a CKEditor 5 with CKPro Screenshot support (if you are fully new to CKEditor 5, you should read the tutorial Building CKEditor 5 From Source first).
Ok, let's hold hands :
{
"dependencies": {
"@ckeditor/ckeditor5-editor-classic": "x",
"@ckeditor/ckeditor5-essentials": "x",
"@ckeditor/ckeditor5-heading": "x",
"@ckeditor/ckeditor5-basic-styles": "x",
"@ckeditor/ckeditor5-link": "x",
"@ckeditor/ckeditor5-list": "x",
"@ckeditor/ckeditor5-theme-lark": "x",
"@ckpro/ckeditor5-screenshot": "x"
},
"devDependencies": {
"@ckeditor/ckeditor5-dev-utils": "x",
"postcss-loader": "3.0.0",
"raw-loader": "4.0.1",
"style-loader": "1.2.1",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12"
}
}
// app.js
import ClassicEditorBase from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
import Heading from '@ckeditor/ckeditor5-heading/src/heading';
import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
import Link from '@ckeditor/ckeditor5-link/src/link';
import List from '@ckeditor/ckeditor5-list/src/list';
import Screenshot from '@ckpro/ckeditor5-screenshot'; // ADD THIS (1/4)
export default class ClassicEditor extends ClassicEditorBase { }
ClassicEditor
.create(document.querySelector('#editor'), {
plugins: [
Heading, // should always be loaded (otherwise among others paragraphs cannot be modelled)
Essentials, // should always be loaded (otherwise among others the editor cannot recieve keyboard input)
Bold,
List,
Screenshot // ADD THIS (2/4)
],
toolbar: [
'heading', // even though the Heading plugin should be loaded, it is not strictly necessary to add it to the toolbar (though most often you want)
'bold',
'bulletedList',
'numberedList',
'screenshot' // ADD THIS (3/4)
],
// ADD THIS (4/4)
screenshot: {
uploadUrl: '/Images/ImageUpload',
uploadParamName: 'upload' // the param name at the http endpoint (above /Images/ImageUpload)
}
})
.then(editor => {
window.editor = editor;
})
.catch(error => {
console.error(error.stack);
});
<!-- edit.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CKEditor 5 - with CKPro Screenshot Plugin</title>
</head>
<body>
<!-- ADD THIS (1/2) -->
<div id="editor">
<h2>Sourdough Bread Recipe</h2>
<ul>
<li>40g Sourdough starter</li>
<li>280g Water</li>
<li>400g Bread Flour</li>
<li>7g salt</li>
</ul>
</div>
<script src="dist/bundle.js"></script> <!-- ADD THIS (2/2) -->
</body>
</html>
The CKEditor 5 Screenshot Plugin will send an image to your server of choice as specified in the Screenshot configuration of your build file, typically app.js or the .html client file. In the code below the http endpoint is set to '/Images/ImageUpload' and the endpoint should take a parameter 'upload' :
// app.js
import ...
export default class ClassicEditor extends ClassicEditorBase { }
ClassicEditor
.create(document.querySelector('#editor'), {
plugins: [
...
],
toolbar: [
....
],
screenshot: {
uploadUrl: '/Images/ImageUpload', // http endpoint
uploadParamName: 'upload' // the param name at the http endpoint (above /Images/ImageUpload)
}
})
.then(editor => {
window.editor = editor;
})
.catch(error => {
console.error(error.stack);
});
public class ImagesController : Controller
{
private readonly IWebHostEnvironment _hostingEnvironment;
public ImagesController(IWebHostEnvironment hostingEnvironment)
{
_hostingEnvironment = hostingEnvironment;
}
[HttpPost]
[IgnoreAntiforgeryToken] // if you have CSRF global prevention enabled you must disable it here (CKPro Screenshot will support CSRF prevention in major semver 2)
public async Task<JsonResult> ImageUpload(IFormFile upload)
{
var headers = Request.Headers;
var contentType = upload.ContentType;
var contentDisposition = upload.ContentDisposition;
var filelength = upload.Length;
if (filelength == 0)
{
return Json(new
{
uploaded = false,
error = "Image file have no length."
});
}
var filename = upload.FileName;
var filetype = ""; if (filename.IndexOf('.') != -1) { filetype = filename.Substring(filename.LastIndexOf('.')); }
if (filetype == "")
{
return Json(new
{
uploaded = false,
error = "Image file extension is not valid."
});
}
var targetFilename = Guid.NewGuid().ToString().Replace("-", "") + filetype;
var imgTempPath = TempFolderPath(_hostingEnvironment, targetFilename);
if (upload.Length > 0)
{
using (var fileStream = new FileStream(imgTempPath, FileMode.Create))
{
await upload.CopyToAsync(fileStream);
}
}
var imageTempUrl = TempFolderUrl + targetFilename;
return Json(new
{
uploaded = true,
url = imageTempUrl
});
}
public static string TempFolderPath(IWebHostEnvironment hostingEnvironment, string imageNameOrUrl = "")
{
var pathWebroot = hostingEnvironment.WebRootPath;
var pathUploads = Path.Combine(pathWebroot, "uploads");
if (!pathUploads.EndsWith('\\')) { pathUploads += '\\'; }
var imageName = imageNameOrUrl;
var indexOfLastSlash = imageNameOrUrl.LastIndexOf('/');
if (indexOfLastSlash > 0 && imageNameOrUrl.Length > indexOfLastSlash)
{
imageName = imageNameOrUrl.Substring(indexOfLastSlash + 1);
}
return pathUploads + imageName;
}
public static string TempFolderUrl
{
get { return "/uploads/"; }
}
}
}
One thing is for a content creator to add a screenshot to the text in CKEditor 5, however another thing is to actual display that screenshot then publishing the content client-side.
To create the screenshot popover client-side, you need some javascript code. While it is possible to use Bootstrap popover, I have created a more relevant CKPro Screenshot Popover Script, which have icons and pre-loader embedded - I will show how to use the CKPro Screenshot Popover Script here.
document.addEventListener("DOMContentLoaded", function () {
CKPro.Screenshot.initialize({
popupZIndex: 1000,
popupActivation: 'click',
placement: CKPro.Screenshot.PlacementEnum.corner_bottom_right, // using an enum to set the popover placement
//placement: "corner_bottom_right", // also possible to use a string to set the popover placement
offset: { // fine tune placement
horizontal: 2,
vertical: -12
},
//iconPopupRegular: '/Images/view_screenshot_reg.png', // if you don't like the builtin screenshot icon, you can supply your own
//iconPopupHover: '/Images/view_screenshot_hot.png',
//imageUrlPrefix: '/FileServer/ContentImages/', // exported CKEditor 5 data contains only the screenshot name, therefore it is necessary to specify the folder to find the image in
maxImageWidth: 500,
maxImageHeight: 400,
//loaderUrl: '/Images/spinner.png' // if you don't like the builtin loader grafic, you can set your own
});
});
That's all.
CKPro Popover is protected by a commercial license and must be purchased before use.
There are 3 licenses :
For all licenses you are allowed to use the plugin or a derivative as part of a projekt that you sell or sell access to, it does not matter if you have 1 user or a million users of your projekt.
For all licenses you are allowed to change the source code, however if the source code change you forfeit CKPro ALL support on that particular plugin.
For all licenses any number of developers can work with the plugin.
Please contact Rasmus Rummel on email : rasmusrummel@gmail.com to obtain a license.