Defining menu items
SunEditor.create('exampleOptions', {
font : [
'Arial',
'tohoma',
'Courier New,Courier'
],
fontSize : [
8, 10, 14, 18, 24, 36
],
colorList : [
['#ccc', '#dedede', 'OrangeRed', 'Orange', 'RoyalBlue', 'SaddleBrown'],
['SlateGray', 'BurlyWood', 'DeepPink', 'FireBrick', 'Gold', 'SeaGreen'],
],
paragraphStyles : [
'spaced',
'neon',
{
name: 'Custom'
class: '__se__customClass'
}
],
textStyles : [
'translucent',
{
name: 'Emphasis'
style: '-webkit-text-emphasis: filled;'
}
],
width : '100%',
maxWidth : '600px',
minWidth : '400px',
height : 'auto',
videoWidth : '80%',
youtubeQuery : 'autoplay=1&mute=1&enablejsapi=1',
popupDisplay : 'local',
resizingBar : false,
buttonList : [
'font', 'fontSize',
'fontColor', 'hiliteColor', 'video',
'fullScreen', 'codeView',
'preview', 'save']
],
callBackSave: function (contents, isChanged) {
alert(contents);
}
});
Char count, Button groups, toolbar container
SUNEDITOR.create('lineBreak', {
toolbarContainer : '#toolbar_container',
showPathLabel : false,
charCounter : true,
maxCharCount : 720,
width : 'auto',
maxWidth : '700px',
height : 'auto',
minHeight : '100px',
maxHeight: '250px',
buttonList : [
['undo', 'redo', 'font', 'fontSize', 'formatBlock'],
['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript', 'removeFormat'],
'/' // Line break
['fontColor', 'hiliteColor', 'outdent', 'indent', 'align', 'horizontalRule', 'list', 'table'],
['link', 'image', 'video', 'fullScreen', 'showBlocks', 'codeView', 'preview', 'print', 'save']
],
callBackSave : function (contents, isChanged) {
console.log(contents);
}
});
Iframe, fullPage and use CodeMirror (^5.0.0)
User Functions
User Function Test
Toolbar : Responsive and more buttons
1200px
SUNEDITOR.create('responsive_Toolbar', {
templates: [
{
name: 'Template-1',
html: '<p>HTML source1</p>'
},
{
name: 'Template-2',
html: '<p>HTML source2</p>'
}
],
codeMirror: CodeMirror,
katex: katex,
buttonList: [
// default
['undo', 'redo'],
[':p-More Paragraph-default.more_paragraph', 'font', 'fontSize', 'formatBlock', 'paragraphStyle', 'blockquote'],
['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'],
['fontColor', 'hiliteColor', 'textStyle'],
['removeFormat'],
['outdent', 'indent'],
['align', 'horizontalRule', 'list', 'lineHeight'],
['-right', ':i-More Misc-default.more_vertical', 'fullScreen', 'showBlocks', 'codeView', 'preview', 'print', 'save', 'template'],
['-right', ':r-More Rich-default.more_plus', 'table', 'math', 'imageGallery'],
['-right', 'image', 'video', 'audio', 'link'],
// (min-width: 992)
['%992', [
['undo', 'redo'],
[':p-More Paragraph-default.more_paragraph', 'font', 'fontSize', 'formatBlock', 'paragraphStyle', 'blockquote'],
['bold', 'underline', 'italic', 'strike'],
[':t-More Text-default.more_text', 'subscript', 'superscript', 'fontColor', 'hiliteColor', 'textStyle'],
['removeFormat'],
['outdent', 'indent'],
['align', 'horizontalRule', 'list', 'lineHeight'],
['-right', ':i-More Misc-default.more_vertical', 'fullScreen', 'showBlocks', 'codeView', 'preview', 'print', 'save', 'template'],
['-right', ':r-More Rich-default.more_plus', 'table', 'link', 'image', 'video', 'audio', 'math', 'imageGallery']
]],
// (min-width: 767)
['%767', [
['undo', 'redo'],
[':p-More Paragraph-default.more_paragraph', 'font', 'fontSize', 'formatBlock', 'paragraphStyle', 'blockquote'],
[':t-More Text-default.more_text', 'bold', 'underline', 'italic', 'strike', 'subscript', 'superscript', 'fontColor', 'hiliteColor', 'textStyle'],
['removeFormat'],
['outdent', 'indent'],
[':e-More Line-default.more_horizontal', 'align', 'horizontalRule', 'list', 'lineHeight'],
[':r-More Rich-default.more_plus', 'table', 'link', 'image', 'video', 'audio', 'math', 'imageGallery'],
['-right', ':i-More Misc-default.more_vertical', 'fullScreen', 'showBlocks', 'codeView', 'preview', 'print', 'save', 'template']
]],
// (min-width: 480)
['%480', [
['undo', 'redo'],
[':p-More Paragraph-default.more_paragraph', 'font', 'fontSize', 'formatBlock', 'paragraphStyle', 'blockquote'],
[':t-More Text-default.more_text', 'bold', 'underline', 'italic', 'strike', 'subscript', 'superscript', 'fontColor', 'hiliteColor', 'textStyle', 'removeFormat'],
[':e-More Line-default.more_horizontal', 'outdent', 'indent', 'align', 'horizontalRule', 'list', 'lineHeight'],
[':r-More Rich-default.more_plus', 'table', 'link', 'image', 'video', 'audio', 'math', 'imageGallery'],
['-right', ':i-More Misc-default.more_vertical', 'fullScreen', 'showBlocks', 'codeView', 'preview', 'print', 'save', 'template']
]]
]
})
Image file resize
var editorimageResize = SUNEDITOR.create('imageResize', {
buttonList: [
['undo', 'redo'],
['image']
],
})
/** UploadBefore event
If undefined is returned, it waits until "uploadHandler" is executed.
"uploadHandler" is an upload function with "core" and "info" bound. (plugin.upload.bind(core, info))
[upload files] : uploadHandler(files or [new File(...),])
[error] : uploadHandler("Error message")
[Just finish] : uploadHandler()
[directly register] : uploadHandler(response) // Same format as "imageUploadUrl" response
ex) {
// "errorMessage": "insert error message",
"result": [ { "url": "...", "name": "...", "size": "999" }, ]
}
*/
editorimageResize.onImageUploadBefore = function (files, info, core, uploadHandler) {
try {
ResizeImage(files, uploadHandler)
} catch (err) {
uploadHandler(err.toString())
}
};
// image resize
function ResizeImage (files, uploadHandler) {
const uploadFile = files[0];
const img = document.createElement('img');
const canvas = document.createElement('canvas');
const reader = new FileReader();
reader.onload = function (e) {
img.src = e.target.result
img.onload = function () {
let ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
const MAX_WIDTH = 200;
const MAX_HEIGHT = 100;
let width = img.width;
let height = img.height;
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
canvas.toBlob(function (blob) {
uploadHandler([new File([blob], uploadFile.name)])
}, uploadFile.type, 1);
}
}
reader.readAsDataURL(uploadFile);
}
Image management
cat

cat1

Insert description
Attached files
Attach image
0KB
Video list
<!-- image list -->
<div id="image_wrapper" class="component-list">
<div class="file-list-info">
<span>Attached files</span>
<span class="xefu-btn">
<span class="files-text">Attach image</span>
</span>
<input type="file" id="files_upload" accept="image/*" multiple="multiple" class="files-text files-input"/>
<span id="image_size" class="total-size text-small-2">0KB</span>
<button class="btn btn-md btn-danger" id="image_remove" disabled onclick="deleteCheckedImages()">Remove</button>
</div>
<div class="file-list">
<ul id="image_list">
</ul>
</div>
</div>
<!-- video list -->
<div class="component-list">
<div class="file-list-info">
<span>Video list</span>
</div>
<div class="component-file-list">
<ul id="video_list">
</ul>
</div>
</div>
const imageWrapper = document.getElementById('image_wrapper');
const imageSize = document.getElementById('image_size');
const imageRemove = document.getElementById('image_remove');
const imageTable = document.getElementById('image_list');
let imageList = [];
let selectedImages = [];
const videoTable = document.getElementById('video_list');
let videoList = [];
// Array.prototype.findIndex (IE)
function findIndex(arr, index) {
let idx = -1;
arr.some(function (a, i) {
if ((typeof a === 'number' ? a : a.index) === index) {
idx = i;
return true;
}
return false;
})
return idx;
}
/** event registration */
editorImageSample.onImageUpload = imageUpload;
editorImageSample.onVideoUpload = videoUpload;
/** --- image list --- */
const editorImageSample = SUNEDITOR.create('imageManagement', {
buttonList: [
['undo', 'redo'],
['formatBlock'],
['horizontalRule', 'list', 'table'],
['image', 'video'],
['showBlocks', 'fullScreen', 'preview', 'print']
],
})
editorImageSample.onImageUpload = function (targetElement, index, state, imageInfo, remainingFilesCount) {
if (state === 'delete') {
imageList.splice(findIndex(imageList, index), 1)
} else {
if (state === 'create') {
imageList.push(imageInfo)
} else { // update }
}
if (remainingFilesCount === 0) {
setImageList(imageList)
}
}
// Upload from outside the editor
document.getElementById('files_upload').addEventListener('change', function (e) {
if (e.target.files) {
editorImageSample.insertImage(e.target.files)
e.target.value = ''
}
})
// Edit image list
function setImageList () {
let list = '';
let size = 0;
for (let i = 0, image, fixSize; i < imageList.length; i++) {
image = imageList[i];
fixSize = (image.size / 1000).toFixed(1) * 1
list += '<li id="img_' + image.index + '">' +
'<div onclick="checkImage(' + image.index + ')">' +
'<div class="image-wrapper"><img src="' + image.src + '"></div>' +
'</div>' +
'<a href="javascript:void(0)" onclick="selectImage(\'select\',' + image.index + ')" class="image-size">' + fixSize + 'KB</a>' +
'<div class="image-check"><svg aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" data-fa-i2svg=""><path fill="currentColor" d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"></path></svg></div>' +
'</li>';
size += fixSize;
}
imageSize.innerText = size.toFixed(1) + 'KB';
imageTable.innerHTML = list;
}
// Click the file size
function selectImage (type, index) {
imageList[findIndex(imageList, index)][type]();
}
// Image check
function checkImage (index) {
const li = imageTable.querySelector('#img_' + index);
const currentImageIdx = findIndex(selectedImages, index)
if (currentImageIdx > -1) {
selectedImages.splice(currentImageIdx, 1)
li.className = '';
} else {
selectedImages.push(index)
li.className = 'checked';
}
if (selectedImages.length > 0) {
imageRemove.removeAttribute('disabled');
} else {
imageRemove.setAttribute('disabled', true);
}
}
// Click the remove button
function deleteCheckedImages() {
const iamgesInfo = editorImageSample.getImagesInfo();
for (let i = 0; i < iamgesInfo.length; i++) {
if (selectedImages.indexOf(iamgesInfo[i].index) > -1) {
iamgesInfo[i].delete();
i--;
}
}
selectedImages = []
}
/** --- video list --- */
function videoUpload (targetElement, index, state, videoInfo, remainingFilesCount) {
console.log('videoInfo', videoInfo);
if (state === 'delete') {
videoList.splice(findIndex(videoList, index), 1)
} else {
if (state === 'create') {
videoList.push(videoInfo)
} else { // update
//
}
}
if (remainingFilesCount === 0) {
console.log('videoList', videoList)
setVideoList(videoList)
}
}
function setVideoList () {
let list = '';
for (let i = 0, video; i < videoList.length; i++) {
video = videoList[i];
list += '<li>' +
'<button title="delete" onclick="selectVideo(\'delete\',' + video.index + ')">X</button>' +
'<a href="javascript:void(0)" onclick="selectVideo(\'select\',' + video.index + ')">' + video.src + '</a>' +
'</li>';
}
videoTable.innerHTML = list;
}
function selectVideo (type, index) {
videoList[findIndex(videoList, index)][type]();
}