Defining menu items

Char count, Button groups, toolbar container

Iframe, fullPage and use CodeMirror (^5.0.0)

User Functions

Toolbar : Responsive and more buttons

1200px

ExploreEditor.create('responsive_Toolbar', {
  templates: [
      {
          name: 'Template-1',
          html: '<p>HTML source1</p>'
      },
      {
          name: 'Template-2',
          html: '<p>HTML source2</p>'
      }
  ],
  codeMirror: CodeMirror,
  katex: katex,
  toolbarItem: [
      // 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 = ExploreEditor.create('imageResize', {
  toolbarItem: [
      ['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

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 = ExploreEditor.create('imageManagement', {
        toolbarItem: [
            ['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 &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;
      }
      
      // 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 = []
      }
      
      /** --- 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]();
      }