# CKEditor5 使用說明 ## 1.安裝說明 [官方下載連結](https://ckeditor.com/ckeditor-5/download/) 1.選擇經典版下載 ![](https://i.imgur.com/dlJs8gt.png) 2.選擇Zip package下載 ![](https://i.imgur.com/8qo9hfA.png) 3.將其解壓縮結構長成這樣 ![](https://i.imgur.com/aY5FJDz.png) ## 2.CKEditor5與MVC搭配使用 1.將專案放進wwwroot/lib/底下 ![](https://i.imgur.com/u802513.png) 2.在view/Shared/_Layout.cshtml引入ckeditor.js ![](https://i.imgur.com/O6a6ROE.png) ``` <script src="~/lib/ckeditor5/build/ckeditor.js"></script> ``` 3.在index.cshtml加入textarea id="editor" 用意是把texttarea轉成CKEditor編輯器 ``` <div class="row"> <div class="col"> <div class="form-group"> <label class="control-label"></label> <textarea class="form-control editor" id="editor"></textarea> <span class="text-danger"></span> </div> </div> <button id=getdata>Print data</button> </div> ``` 4.在js引入初始化CKEditor程式碼 ``` window.addEventListener("load", (e) => { ClassicEditor .create(document.querySelector('.editor'), { extraPlugins: [MyCustomUploadAdapterPlugin], toolbar: { items: [ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', '|', 'alignment', 'outdent', 'indent', '|', 'fontSize', 'fontColor', '|', 'imageUpload', 'blockQuote', 'insertTable', 'mediaEmbed', 'undo', 'redo' ] }, language: 'en', image: { toolbar: [ 'imageTextAlternative', 'imageStyle:inline', 'imageStyle:block', 'imageStyle:side' ] }, table: { contentToolbar: [ 'tableColumn', 'tableRow', 'mergeTableCells' ] }, licenseKey: '', }) .then(editor => { window.editor = editor; }) .catch(error => { console.error('Oops, something went wrong!'); console.error(error); }); }); ``` 5.專案跑起來畫面 ![](https://i.imgur.com/l9Ymp6G.png) ## 3.CKEditor5圖片上傳 base64儲存方式將以下程式碼放入js即可使用 ``` class MyUploadAdapter { constructor(loader) { // The file loader instance to use during the upload. this.loader = loader; } // Starts the upload process. upload() { var reader = new FileReader(); return new Promise((resolve, reject) => { reader.addEventListener('load', () => { resolve({ default: reader.result }); }); reader.addEventListener('error', err => { reject(err); }); reader.addEventListener('abort', () => { reject(); }); this.loader.file.then(file => { reader.readAsDataURL(file); }); }) } // Aborts the upload process. abort() { if (this.xhr) { this.xhr.abort(); } } // Initializes the XMLHttpRequest object using the URL passed to the constructor. _initRequest() { const xhr = (this.xhr = new XMLHttpRequest()); // Note that your request may look different. It is up to you and your editor // integration to choose the right communication channel. This example uses // a POST request with JSON as a data structure but your configuration // could be different. xhr.open("POST", "/Home/ImageTest", true); xhr.responseType = "json"; } // Initializes XMLHttpRequest listeners. _initListeners(resolve, reject, file) { const xhr = this.xhr; const loader = this.loader; const genericErrorText = `無法上傳檔案: ${file.name}.`; xhr.addEventListener("error", () => reject(genericErrorText)); xhr.addEventListener("abort", () => reject()); xhr.addEventListener("load", () => { const response = xhr.response; console.log('response', response); // This example assumes the XHR server's "response" object will come with // an "error" which has its own "message" that can be passed to reject() // in the upload promise. // // Your integration may handle upload errors in a different way so make sure // it is done properly. The reject() function must be called when the upload fails. if (!response || response.error) { return reject(response && response.error ? response.error.message : genericErrorText); } // If the upload is successful, resolve the upload promise with an object containing // at least the "default" URL, pointing to the image on the server. // This URL will be used to display the image in the content. Learn more in the // UploadAdapter#upload documentation. resolve({ default: response.url, }); }); // Upload progress when it is supported. The file loader has the #uploadTotal and #uploaded // properties which are used e.g. to display the upload progress bar in the editor // user interface. if (xhr.upload) { xhr.upload.addEventListener("progress", evt => { if (evt.lengthComputable) { loader.uploadTotal = evt.total; loader.uploaded = evt.loaded; } }); } } // Prepares the data and sends the request. _sendRequest(file) { // Prepare the form data. const data = new FormData(); data.append("Files", file); console.log('file:', file); // Important note: This is the right place to implement security mechanisms // like authentication and CSRF protection. For instance, you can use // XMLHttpRequest.setRequestHeader() to set the request headers containing // the CSRF token generated earlier by your application. // Send the request. this.xhr.send(data); } } // ... function MyCustomUploadAdapterPlugin(editor) { editor.plugins.get("FileRepository").createUploadAdapter = loader => { // Configure the URL to the upload script in your back-end here! return new MyUploadAdapter(loader); }; } ``` 取得CKEdiotr html 主要是getDataFromTheEditor() ``` function getDataFromTheEditor() { return window.editor.getData(); } document.getElementById('getdata').addEventListener('click', () => { alert(getDataFromTheEditor()); //document.getElementById('test').value = getDataFromTheEditor(); }); ``` 取得範例如下,將該html儲存到db,到前端只要輸入@Html.Raw(@Model.Content)就能將編輯畫面整個顯示 ![](https://i.imgur.com/t4ykOHN.png) ## 4.特殊技巧 如果要編輯CKEditor畫面可以將儲存的html利用setData()塞入編輯畫面中 ``` window.editor.setData() ``` [github下載連結](https://github.com/hungho0208/CKEditor5)