返回介绍

Toolbar buttons

发布于 2019-05-06 06:49:47 字数 20023 浏览 1035 评论 0 收藏 0

Use cases

  • Create a shortcut for an action or a series of actions that the user repeatedly does.
  • Create a button for custom behavior.

How to create custom toolbar buttons

The methods for adding custom toolbar buttons are in the UI Registry part of the editor API editor.ui.registry. The API has four methods for adding toolbar buttons, one for each type of toolbar button:

  • editor.ui.registry.addButton(identifier, configuration)
  • editor.ui.registry.addToggleButton(identifier, configuration)
  • editor.ui.registry.addSplitButton(identifier, configuration)
  • editor.ui.registry.addMenuButton(identifier, configuration)

The two arguments these methods take are:

  • identifier - a unique name for the button
  • configuration - an object containing your configuration for that button.

Note: Some configuration options are common to all types of toolbar buttons, but some toolbar button types also have custom configuration options. Review the relevant documentation for each type of button for more information.

To create a custom toolbar button, define and register the button within the setup callback of the TinyMCE configuration. This callback is invoked automatically for every initialized editor instance. UI components must be defined within the setup callback because the callback receives a reference to the editor instance as its argument, which is used to access the UI registry API. Once registered, the button can be added to the editor by adding the identifier string it was registered with to the toolbar configuration option.

Example of adding a basic button that triggers an alert when clicked:

tinymce.init({
  selector: '#editor',
  toolbar: 'myCustomToolbarButton',
  setup: (editor) => {
    editor.ui.registry.addButton('myCustomToolbarButton', {
      text: 'My Custom Button',
      onAction: () => alert('Button clicked!')
    });
  }
});

Example

The following example creates different types of toolbar buttons.

TinyMCE HTML JS Edit on CodePen

<textarea id="toolbar-button">
  <p>Hello world</p>
</textarea>



tinymce.init({
  selector: 'textarea#toolbar-button',
  toolbar: 'basicDateButton selectiveDateButton toggleDateButton splitDateButton menuDateButton',
  setup: function (editor) {

    /* Helper functions */
    var toDateHtml = function (date) {
      return '<time datetime="' + date.toString() + '">' + date.toDateString() + '</time>';
    };
    var toGmtHtml = function (date) {
      return '<time datetime="' + date.toString() + '">' + date.toGMTString() + '</time>';
    };
    var toIsoHtml = function (date) {
      return '<time datetime="' + date.toString() + '">' + date.toISOString() + '</time>';
    };

    /* Basic button that just inserts the date */
    editor.ui.registry.addButton('basicDateButton', {
      text: 'Insert Date',
      tooltip: 'Insert Current Date',
      onAction: function (_) {
        editor.insertContent(toDateHtml(new Date()));
      }
    });

    /* Basic button that inserts the date, but only if the cursor isn't currently in a "time" element */
    editor.ui.registry.addButton('selectiveDateButton', {
      icon: 'insert-time',
      tooltip: 'Insert Current Date',
      disabled: true,
      onAction: function (_) {
        editor.insertContent(toDateHtml(new Date()));
      },
      onSetup: function (buttonApi) {
        var editorEventCallback = function (eventApi) {
          buttonApi.setDisabled(eventApi.element.nodeName.toLowerCase() === 'time');
        };
        editor.on('NodeChange', editorEventCallback);
        return function (buttonApi) {
          editor.off('NodeChange', editorEventCallback);
        }
      }
    });

    /* Toggle button that inserts the date, but becomes inactive when the cursor is in a "time" element */
    /* so you can't insert a "time" element inside another one. Also gives visual feedback. */
    editor.ui.registry.addToggleButton('toggleDateButton', {
      icon: 'insert-time',
      tooltip: 'Insert Current Date',
      onAction: function (_) {
        editor.insertContent(toDateHtml(new Date()));
      },
      onSetup: function (buttonApi) {
        var editorEventCallback = function (eventApi) {
          buttonApi.setActive(eventApi.element.nodeName.toLowerCase() === 'time');
        };
        editor.on('NodeChange', editorEventCallback);
        return function (buttonApi) {
          editor.off('NodeChange', editorEventCallback);
        }
      }
    });

    /* Split button that lists 3 formats, and inserts the date in the selected format when clicked */
    editor.ui.registry.addSplitButton('splitDateButton', {
      text: 'Insert Date',
      onAction: function (_) {
        editor.insertContent('<p>Its Friday!</p>')
      },
      onItemAction: function (buttonApi, value) {
        editor.insertContent(value);
      },
      fetch: function (callback) {
        var items = [
          {
            type: 'choiceitem',
            text: 'Insert Date',
            value: toDateHtml(new Date())
          },
          {
            type: 'choiceitem',
            text: 'Insert GMT Date',
            value: toGmtHtml(new Date())
          },
          {
            type: 'choiceitem',
            text: 'Insert ISO Date',
            value: toIsoHtml(new Date())
          }
        ];
        callback(items);
      }
    });

    /* Menu button that has a simple "insert date" menu item, and a submenu containing other formats. */
    /* Clicking the first menu item or one of the submenu items inserts the date in the selected format. */
    editor.ui.registry.addMenuButton('menuDateButton', {
      text: 'Date',
      fetch: function (callback) {
        var items = [
          {
            type: 'menuitem',
            text: 'Insert Date',
            onAction: function (_) {
              editor.insertContent(toDateHtml(new Date()));
            }
          },
          {
            type: 'nestedmenuitem',
            text: 'Other formats',
            getSubmenuItems: function () {
              return [
                {
                  type: 'menuitem',
                  text: 'GMT',
                  onAction: function (_) {
                    editor.insertContent(toGmtHtml(new Date()));
                  }
                },
                {
                  type: 'menuitem',
                  text: 'ISO',
                  onAction: function (_) {
                    editor.insertContent(toIsoHtml(new Date()));
                  }
                }
              ];
            }
          }
        ];
        callback(items);
      }
    });
  }
});


(function() { var isIE = !!window.MSInputMethodContext && !!document.documentMode; if (isIE && document.getElementsByClassName("ie11_optional")[0] !== undefined) { document.getElementsByClassName("ie11_optional")[0].style.display = 'none'; } })(); (function() { tinymce.init({ selector: 'textarea#toolbar-button', toolbar: 'basicDateButton selectiveDateButton toggleDateButton splitDateButton menuDateButton', setup: function (editor) { /* Helper functions */ var toDateHtml = function (date) { return '' + date.toDateString() + ''; }; var toGmtHtml = function (date) { return '' + date.toGMTString() + ''; }; var toIsoHtml = function (date) { return '' + date.toISOString() + ''; }; /* Basic button that just inserts the date */ editor.ui.registry.addButton('basicDateButton', { text: 'Insert Date', tooltip: 'Insert Current Date', onAction: function (_) { editor.insertContent(toDateHtml(new Date())); } }); /* Basic button that inserts the date, but only if the cursor isn't currently in a "time" element */ editor.ui.registry.addButton('selectiveDateButton', { icon: 'insert-time', tooltip: 'Insert Current Date', disabled: true, onAction: function (_) { editor.insertContent(toDateHtml(new Date())); }, onSetup: function (buttonApi) { var editorEventCallback = function (eventApi) { buttonApi.setDisabled(eventApi.element.nodeName.toLowerCase() === 'time'); }; editor.on('NodeChange', editorEventCallback); return function (buttonApi) { editor.off('NodeChange', editorEventCallback); } } }); /* Toggle button that inserts the date, but becomes inactive when the cursor is in a "time" element */ /* so you can't insert a "time" element inside another one. Also gives visual feedback. */ editor.ui.registry.addToggleButton('toggleDateButton', { icon: 'insert-time', tooltip: 'Insert Current Date', onAction: function (_) { editor.insertContent(toDateHtml(new Date())); }, onSetup: function (buttonApi) { var editorEventCallback = function (eventApi) { buttonApi.setActive(eventApi.element.nodeName.toLowerCase() === 'time'); }; editor.on('NodeChange', editorEventCallback); return function (buttonApi) { editor.off('NodeChange', editorEventCallback); } } }); /* Split button that lists 3 formats, and inserts the date in the selected format when clicked */ editor.ui.registry.addSplitButton('splitDateButton', { text: 'Insert Date', onAction: function (_) { editor.insertContent('

Its Friday!

') }, onItemAction: function (buttonApi, value) { editor.insertContent(value); }, fetch: function (callback) { var items = [ { type: 'choiceitem', text: 'Insert Date', value: toDateHtml(new Date()) }, { type: 'choiceitem', text: 'Insert GMT Date', value: toGmtHtml(new Date()) }, { type: 'choiceitem', text: 'Insert ISO Date', value: toIsoHtml(new Date()) } ]; callback(items); } }); /* Menu button that has a simple "insert date" menu item, and a submenu containing other formats. */ /* Clicking the first menu item or one of the submenu items inserts the date in the selected format. */ editor.ui.registry.addMenuButton('menuDateButton', { text: 'Date', fetch: function (callback) { var items = [ { type: 'menuitem', text: 'Insert Date', onAction: function (_) { editor.insertContent(toDateHtml(new Date())); } }, { type: 'nestedmenuitem', text: 'Other formats', getSubmenuItems: function () { return [ { type: 'menuitem', text: 'GMT', onAction: function (_) { editor.insertContent(toGmtHtml(new Date())); } }, { type: 'menuitem', text: 'ISO', onAction: function (_) { editor.insertContent(toIsoHtml(new Date())); } } ]; } } ]; callback(items); } }); } }); })(); (function() { /* TODO: more js, less jekyll */ var id = "toolbar-button"; var html = decodeURIComponent("%0A%3Ctextarea%20id=%22toolbar-button%22%3E%0A%20%20%3Cp%3EHello%20world%3C/p%3E%0A%3C/textarea%3E%0A%0A"); var js = decodeURIComponent("%0Atinymce.init(%7B%0A%20%20selector:%20'textarea#toolbar-button',%0A%20%20toolbar:%20'basicDateButton%20selectiveDateButton%20toggleDateButton%20splitDateButton%20menuDateButton',%0A%20%20setup:%20function%20(editor)%20%7B%0A%0A%20%20%20%20/*%20Helper%20functions%20*/%0A%20%20%20%20var%20toDateHtml%20=%20function%20(date)%20%7B%0A%20%20%20%20%20%20return%20'%3Ctime%20datetime=%22'%20+%20date.toString()%20+%20'%22%3E'%20+%20date.toDateString()%20+%20'%3C/time%3E';%0A%20%20%20%20%7D;%0A%20%20%20%20var%20toGmtHtml%20=%20function%20(date)%20%7B%0A%20%20%20%20%20%20return%20'%3Ctime%20datetime=%22'%20+%20date.toString()%20+%20'%22%3E'%20+%20date.toGMTString()%20+%20'%3C/time%3E';%0A%20%20%20%20%7D;%0A%20%20%20%20var%20toIsoHtml%20=%20function%20(date)%20%7B%0A%20%20%20%20%20%20return%20'%3Ctime%20datetime=%22'%20+%20date.toString()%20+%20'%22%3E'%20+%20date.toISOString()%20+%20'%3C/time%3E';%0A%20%20%20%20%7D;%0A%0A%20%20%20%20/*%20Basic%20button%20that%20just%20inserts%20the%20date%20*/%0A%20%20%20%20editor.ui.registry.addButton('basicDateButton',%20%7B%0A%20%20%20%20%20%20text:%20'Insert%20Date',%0A%20%20%20%20%20%20tooltip:%20'Insert%20Current%20Date',%0A%20%20%20%20%20%20onAction:%20function%20(_)%20%7B%0A%20%20%20%20%20%20%20%20editor.insertContent(toDateHtml(new%20Date()));%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D);%0A%0A%20%20%20%20/*%20Basic%20button%20that%20inserts%20the%20date,%20but%20only%20if%20the%20cursor%20isn't%20currently%20in%20a%20%22time%22%20element%20*/%0A%20%20%20%20editor.ui.registry.addButton('selectiveDateButton',%20%7B%0A%20%20%20%20%20%20icon:%20'insert-time',%0A%20%20%20%20%20%20tooltip:%20'Insert%20Current%20Date',%0A%20%20%20%20%20%20disabled:%20true,%0A%20%20%20%20%20%20onAction:%20function%20(_)%20%7B%0A%20%20%20%20%20%20%20%20editor.insertContent(toDateHtml(new%20Date()));%0A%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20onSetup:%20function%20(buttonApi)%20%7B%0A%20%20%20%20%20%20%20%20var%20editorEventCallback%20=%20function%20(eventApi)%20%7B%0A%20%20%20%20%20%20%20%20%20%20buttonApi.setDisabled(eventApi.element.nodeName.toLowerCase()%20===%20'time');%0A%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20editor.on('NodeChange',%20editorEventCallback);%0A%20%20%20%20%20%20%20%20return%20function%20(buttonApi)%20%7B%0A%20%20%20%20%20%20%20%20%20%20editor.off('NodeChange',%20editorEventCallback);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D);%0A%0A%20%20%20%20/*%20Toggle%20button%20that%20inserts%20the%20date,%20but%20becomes%20inactive%20when%20the%20cursor%20is%20in%20a%20%22time%22%20element%20*/%0A%20%20%20%20/*%20so%20you%20can't%20insert%20a%20%22time%22%20element%20inside%20another%20one.%20Also%20gives%20visual%20feedback.%20*/%0A%20%20%20%20editor.ui.registry.addToggleButton('toggleDateButton',%20%7B%0A%20%20%20%20%20%20icon:%20'insert-time',%0A%20%20%20%20%20%20tooltip:%20'Insert%20Current%20Date',%0A%20%20%20%20%20%20onAction:%20function%20(_)%20%7B%0A%20%20%20%20%20%20%20%20editor.insertContent(toDateHtml(new%20Date()));%0A%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20onSetup:%20function%20(buttonApi)%20%7B%0A%20%20%20%20%20%20%20%20var%20editorEventCallback%20=%20function%20(eventApi)%20%7B%0A%20%20%20%20%20%20%20%20%20%20buttonApi.setActive(eventApi.element.nodeName.toLowerCase()%20===%20'time');%0A%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20editor.on('NodeChange',%20editorEventCallback);%0A%20%20%20%20%20%20%20%20return%20function%20(buttonApi)%20%7B%0A%20%20%20%20%20%20%20%20%20%20editor.off('NodeChange',%20editorEventCallback);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D);%0A%0A%20%20%20%20/*%20Split%20button%20that%20lists%203%20formats,%20and%20inserts%20the%20date%20in%20the%20selected%20format%20when%20clicked%20*/%0A%20%20%20%20editor.ui.registry.addSplitButton('splitDateButton',%20%7B%0A%20%20%20%20%20%20text:%20'Insert%20Date',%0A%20%20%20%20%20%20onAction:%20function%20(_)%20%7B%0A%20%20%20%20%20%20%20%20editor.insertContent('%3Cp%3EIts%20Friday!%3C/p%3E')%0A%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20onItemAction:%20function%20(buttonApi,%20value)%20%7B%0A%20%20%20%20%20%20%20%20editor.insertContent(value);%0A%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20fetch:%20function%20(callback)%20%7B%0A%20%20%20%20%20%20%20%20var%20items%20=%20[%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20type:%20'choiceitem',%0A%20%20%20%20%20%20%20%20%20%20%20%20text:%20'Insert%20Date',%0A%20%20%20%20%20%20%20%20%20%20%20%20value:%20toDateHtml(new%20Date())%0A%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20type:%20'choiceitem',%0A%20%20%20%20%20%20%20%20%20%20%20%20text:%20'Insert%20GMT%20Date',%0A%20%20%20%20%20%20%20%20%20%20%20%20value:%20toGmtHtml(new%20Date())%0A%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20type:%20'choiceitem',%0A%20%20%20%20%20%20%20%20%20%20%20%20text:%20'Insert%20ISO%20Date',%0A%20%20%20%20%20%20%20%20%20%20%20%20value:%20toIsoHtml(new%20Date())%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20];%0A%20%20%20%20%20%20%20%20callback(items);%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D);%0A%0A%20%20%20%20/*%20Menu%20button%20that%20has%20a%20simple%20%22insert%20date%22%20menu%20item,%20and%20a%20submenu%20containing%20other%20formats.%20*/%0A%20%20%20%20/*%20Clicking%20the%20first%20menu%20item%20or%20one%20of%20the%20submenu%20items%20inserts%20the%20date%20in%20the%20selected%20format.%20*/%0A%20%20%20%20editor.ui.registry.addMenuButton('menuDateButton',%20%7B%0A%20%20%20%20%20%20text:%20'Date',%0A%20%20%20%20%20%20fetch:%20function%20(callback)%20%7B%0A%20%20%20%20%20%20%20%20var%20items%20=%20[%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20type:%20'menuitem',%0A%20%20%20%20%20%20%20%20%20%20%20%20text:%20'Insert%20Date',%0A%20%20%20%20%20%20%20%20%20%20%20%20onAction:%20function%20(_)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20editor.insertContent(toDateHtml(new%20Date()));%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20type:%20'nestedmenuitem',%0A%20%20%20%20%20%20%20%20%20%20%20%20text:%20'Other%20formats',%0A%20%20%20%20%20%20%20%20%20%20%20%20getSubmenuItems:%20function%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20[%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'menuitem',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20text:%20'GMT',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20onAction:%20function%20(_)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20editor.insertContent(toGmtHtml(new%20Date()));%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'menuitem',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20text:%20'ISO',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20onAction:%20function%20(_)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20editor.insertContent(toIsoHtml(new%20Date()));%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20];%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20];%0A%20%20%20%20%20%20%20%20callback(items);%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D);%0A%20%20%7D%0A%7D);%0A%0A"); var css = ""; var tabNames = ["run","html","js"]; /* Note: there are some other fields we could populate here to polish this. */ /* See: https://blog.codepen.io/documentation/api/prefill/ */ var data = { title: "TinyMCE Example", description: '', html: html, css: css, css_external: 'https://www.tiny.cloud/css/codepen.min.css', js: js, js_external: 'https://cloud.tinymce.com/5/tinymce.min.js?apiKey=qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc' }; document.getElementById("codepen_data_toolbar-button").value = JSON.stringify(data); /* TODO: */ var tabs = tabNames.map(function(t) { return { tab: document.getElementById("codepen_tab_" + t + "_" + id), pane: document.getElementById("codepen_pane_" + t + "_" + id) }; }); tabs.forEach(function(t) { t.tab.onclick = function(e) { tabs.forEach(function(tt) { tt.pane.style.display = t === tt ? 'block' : 'none'; tt.tab.className = t === tt ? 'codepen_tab_selected' : 'codepen_tab_deselected'; }); e.preventDefault(); }; }); if (document.getElementById("codepen_tab_codepen_" + id) !== null) { document.getElementById("codepen_tab_codepen_" + id).onclick = function() { document.getElementById("codepen_form_" + id).submit(); }; } })();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文