Defining menu items

Char count, Button groups

Iframe, fullPage and use CodeMirror (^5.0.0)

Image management

Attached files Attach image 0KB
<div id="image_wrapper" class="image-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>
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 editorImageSample = SUNEDITOR.create('imageManagement', {
    buttonList: [
        ['undo', 'redo'],
        ['formatBlock'],
        ['horizontalRule', 'list', 'table'],
        ['image', 'video'],
        ['showBlocks', 'fullScreen', 'preview', 'print']
    ],
})

editorImageSample.onImageUpload = function (targetImgElement, index, state, imageInfo, remainingFilesCount) {
    if (state === 'delete') {
        imageList.splice(findIndex(imageList, index), 1)
    } else {
        if (state === 'create') {
            const image = editorImageSample.getImagesInfo()[findIndex(editorImageSample.getImagesInfo(), index)]
            imageList.push(image)
        } 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 &lt; imageList.length; i++) {
        image = imageList[i];
        fixSize = (image.size / 1000).toFixed(1) * 1
            
        list += '&lt;li id="img_' + image.index + '"&gt;' +
                    '&lt;div onclick="checkImage(' + image.index + ')"&gt;' +
                        '&lt;div class="image-wrapper"&gt;&lt;img src="' + image.src + '"&gt;&lt;/div&gt;' +
                    '&lt;/div&gt;' +
                    '&lt;a href="javascript:void(0)" onclick="selectImage(\'select\',' + image.index + ')" class="image-size"&gt;' + fixSize + 'KB&lt;/a&gt;' +
                    '&lt;div class="image-check"&gt;&lt;svg aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" data-fa-i2svg=""&gt;&lt;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"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;' +
                '&lt;/li&gt;';
        
        size += fixSize;
    }

    imageSize.innerText = size.toFixed(1) + 'KB';
    imageTable.innerHTML = list;
}

// Array.prototype.findIndex
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;
}

// 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 &gt; -1) {
        selectedImages.splice(currentImageIdx, 1)
        li.className = '';
    } else {
        selectedImages.push(index)
        li.className = 'checked';
    }

    if (selectedImages.length &gt; 0) {
        imageRemove.removeAttribute('disabled');
    } else {
        imageRemove.setAttribute('disabled', true);
    }
}

// Click the remove button
function deleteCheckedImages() {
    const iamgesInfo = editorImageSample.getImagesInfo();

    for (let i = 0; i &lt; iamgesInfo.length; i++) {
        if (selectedImages.indexOf(iamgesInfo[i].index) &gt; -1) {
            iamgesInfo[i].delete();
            i--;
        }
    }

    selectedImages = []
}

User Functions

function sun_setOptions() {
    suneditor.setOptions({
        mode: 'inline',
        minHeight: '300px',
        colorList: [
            ['#ccc', '#dedede', 'OrangeRed', 'Orange', 'RoyalBlue', 'SaddleBrown']
        ],
        buttonList: [
            ['fontColor', 'hiliteColor']
        ]
    });

    opt1.style.display = 'none';
    opt2.style.display = 'inline-block';
}

function sun_replaceOptions() {
    suneditor.setOptions({
        mode: 'classic',
        minHeight: null,
        colorList: null,
        buttonList: [
            ['undo', 'redo'],
            ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'],
            ['removeFormat'],
            ['outdent', 'indent'],
            ['fullScreen', 'showBlocks', 'codeView'],
            ['preview', 'print'],
            ['image']
        ],
    });

    opt1.style.display = 'inline-block';
    opt2.style.display = 'none';
}
import suneditor from 'suneditor'

const editor = suneditor.create('example');

// Add or reset option property
editor.setOptions({
    minHeight: '300px',
    buttonList: [
        ['fontColor', 'hiliteColor']
    ],
    colorList: [
        ['#ccc', '#dedede', 'OrangeRed', 'Orange', 'RoyalBlue', 'SaddleBrown']
    ]
});

// Open a notice area
editor.noticeOpen('test notice');

// Close a notice area
editor.noticeClose();

// Copies the contents of the suneditor into a [textarea]
editor.save();

// Gets the suneditor's context object. Contains settings, plugins, and cached element objects
editor.getContext();

// Gets the contents of the suneditor
editor.getContents();

// Gets a list of images uploaded to the editor
/** 
 * {
 *  src: imgage src
 *  index: data index
 *  name: file name
 *  size: file size
 *  select: select function
 *  delete: delete function
 * }
 **/
editor.getImagesInfo();

// Upload images using image plugin
// document.getElementById('example_files_input').files
editor.insertImage(FileList);

// Inserts an HTML element or HTML string or plain string at the current cursor position
editor.insertHTML('<img src="http://suneditor.com/sample/img/sunset.jpg">');

// Change the contents of the suneditor
editor.setContents('set contents');

// Add content to the suneditor
editor.appendContents('append contents');

// Disable the suneditor
editor.disabled();

// Enabled the suneditor
editor.enabled();

// Hide the suneditor
editor.hide();

// Show the suneditor
editor.show();
    
// Destroy the suneditor
editor.destroy();
editor = null;

// Event functions
// It can be redefined by receiving event object as parameter.
// It is not called in exceptional cases and is called after the default event function has finished.
editor.onScroll = function (e) { console.log('onScroll', e) }

editor.onClick = function (e) { console.log('onClick', e) }

editor.onKeyDown = function (e) { console.log('onKeyDown', e) }

editor.onKeyUp = function (e) { console.log('onKeyUp', e) }

editor.onDrop = function (e) { console.log('onDrop', e) }

editor.onChange = function (contents) { console.log('onChange', contents) }

// Paste event.
// Called before the editor's default event action.
// If it returns false, it stops without executing the rest of the action.
/**
 * cleanData : HTML string modified for editor format
 * maxCharCount : maxChartCount option (true if max character is exceeded)
*/
editor.onPaste = function (e, cleanData, maxCharCount) { console.log('onPaste', e, cleanData, maxCharCount) }

// Called when the image is uploaded or the uploaded image is deleted.
/**
 * targetImgElement: Current img element
 * index: Uploaded index (key value)
 * state: Upload status ('create', 'update', 'delete')
 * imageInfo: {
 * * index: data index
 * * name: file name
 * * size: file size
 * * select: select function
 * * delete: delete function
 * }
 * remainingFilesCount: Count of remaining image files
*/
editor.onImageUpload = function (targetImgElement, index, state, imageInfo, remainingFilesCount) {
    console.log(`targetImgElement:${targetImgElement}, index:${index}, state('create', 'update', 'delete'):${state}`)
    console.log(`imageInfo:${imageInfo}, remainingFilesCount:${remainingFilesCount}`)
}

// Called when the image is upload failed.
// If you return false, the default notices are not called.
/**
 * errorMessage: Error message to show
 * result: Result object 
*/
editor.onImageUploadError = function (errorMessage, result) {
    alert(errorMessage)
}

// Paste event.
// Called before the editor's default event action.
// If it returns false, it stops without executing the rest of the action.
/**
 * toolbar: Toolbar Element
 * context: The editor's context object (editor.getContext())
*/
editor.showInline = function (toolbar, context) {
    console.log('toolbar', toolbar);
    console.log('context', context);
}