基础交互对话框

以下示例展示了数据如何通过对话框流动,以及按钮的配置方式。这是一个交互式对话框,提交时会将猫的名字插入到编辑器内容中。

HTML

<textarea id="dialog-pet-machine">
  <p>点击自定义 {;} 工具栏按钮</p>
</textarea>

JS

/* 示例对话框,将宠物的名字插入到编辑器内容中 */
const dialogConfig =  {
  title: 'Pet Name Machine',
  body: {
    type: 'panel',
    items: [
      {
        type: 'input',
        name: 'catdata',
        label: 'enter the name of a cat'
      },
      {
        type: 'checkbox',
        name: 'isdog',
        label: 'tick if cat is actually a dog'
      }
    ]
  },
  buttons: [
    {
      type: 'cancel',
      name: 'closeButton',
      text: 'Cancel'
    },
    {
      type: 'submit',
      name: 'submitButton',
      text: 'Do Cat Thing',
      buttonType: 'primary'
    }
  ],
  initialData: {
    catdata: 'initial Cat',
    isdog: false
  },
  onSubmit: (api) => {
    const data = api.getData();
    const pet = data.isdog ? 'dog' : 'cat';

    tinymce.activeEditor.execCommand('mceInsertContent', false, `<p>My ${pet}'s name is: <strong>${data.catdata}</strong></p>`);
    api.close();
  }
};

tinymce.init({
  selector: 'textarea#dialog-pet-machine',
  toolbar: 'dialog-example-btn',
  setup: (editor) => {
    editor.ui.registry.addButton('dialog-example-btn', {
      icon: 'code-sample',
      onAction: () => editor.windowManager.open(dialogConfig)
    })
  },
  content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }'
});

此示例中的对话框包含两个交互组件 - 一个名为 catdata 的输入组件和一个名为 isdog 的复选框组件。这些名称在 initialdata 配置属性中用于设置这些组件的初始值。在这种情况下,当对话框加载时,输入框将包含文本 initial Cat,复选框将不会被选中。

对话框还包含两个页脚按钮 - 一个 提交 类型的按钮和一个 取消 类型的按钮。由于对话框的配置不包含 onCancel 回调函数,因此点击取消类型按钮只会关闭对话框。但是,配置中确实包含一个 onSubmit 回调函数,当点击提交类型按钮时将触发该函数。

在 onSubmit 回调函数中,传递给回调函数的对话框实例API用于调用 getData()。此函数返回对话框的数据存储,我们可以从中获取 isdog 复选框的状态和 catadata 输入的值。此信息用于构造一个句子,然后插入到编辑器中。最后,调用 close() 手动关闭对话框。

使用Redial的交互示例

Redial可用于更改对话框中显示的信息,创建下一个按钮加载新表单页面的多页表单,或使用不同的组件或选项重新创建对话框。

以下示例展示了使用 redial() 方法实现多页表单对话框的一种方式。自定义按钮用于通过调用带有适当对话框配置的 redial() 在表单的两个页面之间切换。

要查看代码的输出,请点击下方 fiddle 中的 TinyMCE 标签页。

HTML

<textarea id="redial-demo">
  <p>点击自定义 {;} 工具栏按钮打开一个使用 Redial 渲染多页表单的对话框。</p>
</textarea>

JS

const page1Config = {
  title: 'Redial Demo',
  body: {
    type: 'panel',
    items: [{
      type: 'htmlpanel',
      html: '<p>Redial allows for the contents of a dialog to be replaced with new contents. This can be used to create multipage form dialogs.</p><br/><p>The Next button is initially disabled. When the <strong>checkbox</strong> is checked, the Next button should be enabled.</p>'
    }, {
      type: 'checkbox',
      name: 'anyterms',
      label: 'I agree to disagree'
    }, {
      type: 'htmlpanel',
      html: '<p>Pressing the Next button will call redial() to reload the dialog with the next page of the form.</p><br><p>Press Next to continue.</p>'
    }]
  },
  initialData: {
    anyterms: false
  },
  buttons: [
    {
      type: 'custom',
      name: 'doesnothing',
      text: 'Previous',
      enabled: false
    },
    {
      type: 'custom',
      name: 'uniquename',
      text: 'Next',
      enabled: false
    }
  ],
  onChange: (dialogApi, details) => {
    const data = dialogApi.getData();
    /* Example of enabling and disabling a button, based on the checkbox state. */
    dialogApi.setEnabled('uniquename', data.anyterms);
  },
  onAction: (dialogApi, details) => {
    if (details.name === 'uniquename') {
      dialogApi.redial(page2Config);
    } else if (details.name === 'doesnothing') {
      /* this case should never be met as the button is never enabled. */
    }
  }
};

const page2Config = {
  title: 'Redial Demo - Page 2',
  body: {
    type: 'panel',
    items: [
      {
        type: 'selectbox',
        name: 'choosydata',
        label: 'Choose a pet',
        items: [
          { value: 'meow', text: 'Cat' },
          { value: 'woof', text: 'Dog' },
          { value: 'thunk', text: 'Rock' }
        ]
      },
      {
        type: 'htmlpanel',
        html: '<p>Click done and the dialog will log a message to the console, insert a sentence into the editor and close.</p>'
      }
    ]
  },
  buttons: [
    {
      type: 'custom',
      name: 'lastpage',
      text: 'Done',
      enabled: true
    }
  ],
  initialData: {
    choosydata: ''
  },
  onAction: (dialogApi, details) => {
    const data = dialogApi.getData();

    const result = 'You chose wisely: ' + data.choosydata;
    console.log(result);
    tinymce.activeEditor.execCommand('mceInsertContent', false, `<p>${result}</p>`);

    dialogApi.close();
  }
};

tinymce.init({
  selector: 'textarea#redial-demo',
  toolbar: 'wizardExample',
  height: '900px',
  setup: (editor) => {
    editor.ui.registry.addButton('wizardExample', {
      icon: 'code-sample',
      onAction: () => editor.windowManager.open(page1Config)
    })
  },
  content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }'
});

此 JavaScript 代码示例包含两个对话框配置 - page1Config 和 page2Config。TinyMCE 初始化代码会向编辑器添加一个按钮,点击该按钮时会调用 editor.windowManager.open(page1Config) 以使用第一个配置打开一个对话框。

多页表单第一页的配置包含表单描述和一个复选框。该复选框通过对话框的 onChange() 回调函数来切换 next 按钮的禁用或启用状态。当点击 next 按钮时,会触发 onAction() 回调函数,该函数进而触发 redial(),将 page1Config 对话框替换为 page2Config 对话框。

更具体地说:

page1Config 中的 onChange() 回调函数在复选框状态切换时触发。它使用对话框实例 API 中的 setEnabled 来禁用和启用 Next 按钮。该代码使用对话框实例 API 中的 getData() 来获取名为 anyterms 的复选框的状态(勾选时为 true,未勾选时为 false),然后使用组件名称 uniquename 和复选框值调用 setEnabled 函数,以设置 Next 按钮的启用状态。

page1Config 中的 onAction() 回调函数在两个页脚按钮中的任何一个被点击时触发,因为它们都是自定义类型的页脚按钮。onAction() 会传入对话框实例 API 和一个包含有关更改事件的一些数据的对象,其中包括触发该事件的组件的 name。这一点很重要,因为相同的 onAction() 处理程序在所有兼容的对话框组件之间共享。该代码会检查触发 onAction() 的组件的 name,如果它是 uniquename(Next 按钮的名称),则会调用 redial(page2Config)。如果组件的 name 是 donothing,则代码不做任何操作。

在 page2Config 中,onAction() 回调函数使用 getData() 获取 selectbox 组件的值,具体来说是用户是否选择了 Cat、Dog 或 Rock。然后,它使用该值构造一个句子,将其插入到编辑器内容中,并调用 close() 来手动关闭对话框。