Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ You can download and run these demos locally. Some demos uses premium plugins so

## License
The files in this repository are licensed under an MIT license.
TinyMCE is licensed under a LGPL or commercial license.
TinyMCE is available under a commercial license and a subset of the features are open source under the GNU General Public License Version 2 or later.
56 changes: 32 additions & 24 deletions cool-demos/conditional-blocks.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,52 +15,61 @@
<meta charset="utf-8">
<title>Conditional blocks</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.tiny.cloud/1/qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc/tinymce/5-dev/tinymce.min.js" referrerpolicy="origin"></script>
<script src="https://cdn.tiny.cloud/1/qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc/tinymce/8/tinymce.min.js" referrerpolicy="origin"></script>

<script>
tinymce.init({
selector: '#editor',

// Tip! To make TinyMCE leaner, only include the plugins you actually need.
plugins: 'autoresize advcode link lists noneditable',
plugins: 'autoresize advcode link lists mergetags',

// We have put our custom insert conditional block button last.
toolbar: 'bold italic strikethrough backcolor | bullist numlist link | conditionalblock | code',
// We have put our custom insert conditional block button second to last.
toolbar: 'bold italic strikethrough backcolor | bullist numlist link mergetags | conditionalblock | code',

// "Thin" is a premium icon pack you get wth the cloud essential plan.
// See https://www.tiny.cloud for more details and purchasing options
// You can also create your own icon packs for TinyMCE
// https://www.tiny.cloud/docs/advanced/creating-an-icon-pack/
// https://www.tiny.cloud/docs/tinymce/latest/enhanced-skins-and-icon-packs/
// https://www.tiny.cloud/docs/tinymce/latest/creating-an-icon-pack/
icons: 'thin',

// "Naked" is a premium icon pack you get wth the cloud essential plan
// "Naked" is a premium icon pack you get with the cloud essential plan
// See https://www.tiny.cloud for more details and purchasing options
// You can also create your own skins for TinyMCE
// https://www.tiny.cloud/docs/advanced/creating-a-skin/
// https://www.tiny.cloud/docs/tinymce/latest/creating-a-skin/
skin: 'naked',

// If we don't need the menubar we can hide it
// https://www.tiny.cloud/docs/configure/editor-appearance/#menubar
// https://www.tiny.cloud/docs/tinymce/latest/menus-configuration-options/#menubar
menubar: false,

// Easily configure replacement values using merge tags plugin
// https://www.tiny.cloud/docs/tinymce/latest/mergetags/
mergetags_list: [
{ title: "first_name", value: "first_name" },
{ title: "number_of_people", value: "number_of_people" },
{ title: "agent_first_name", value: "agent_first_name" },
],

// Tell TinyMCE that conditional-block is a valid element.
// https://www.tiny.cloud/docs/configure/content-filtering/#custom_elements
// https://www.tiny.cloud/docs/tinymce/latest/content-filtering/#custom_elements
custom_elements: 'conditional-block',

setup: (editor) => {
// Instead of defining a custom icon pack, we can register individual
// icons using the API.
// https://www.tiny.cloud/docs/api/tinymce.editor.ui/tinymce.editor.ui.registry/#addicon
// https://www.tiny.cloud/docs/tinymce/latest/apis/tinymce.editor.ui.registry/#addicon
editor.ui.registry.addIcon('conditional-block', '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M19 4a2 2 0 1 1-1.854 2.751L15 6.75c-1.239 0-1.85.61-2.586 2.31l-.3.724c-.42 1.014-.795 1.738-1.246 2.217.406.43.751 1.06 1.12 1.92l.426 1.018c.704 1.626 1.294 2.256 2.428 2.307l.158.004h2.145a2 2 0 1 1 0 1.501L15 18.75l-.219-.004c-1.863-.072-2.821-1.086-3.742-3.208l-.49-1.17c-.513-1.163-.87-1.57-1.44-1.614L9 12.75l-2.146.001a2 2 0 1 1 0-1.501H9c.636 0 1.004-.383 1.548-1.619l.385-.92c.955-2.291 1.913-3.382 3.848-3.457L15 5.25h2.145A2 2 0 0 1 19 4z" fill-rule="evenodd"/></svg>');

// The preinit event is fired after the editor is loaded but before
// the content is loaded
// https://www.tiny.cloud/docs/advanced/events/#editorcoreevents
// https://www.tiny.cloud/docs/tinymce/latest/events/
editor.on('PreInit', () => {
// Get the iframe window object and the iframes document object
// and call our setup function that creates the web component
// https://www.tiny.cloud/docs/api/tinymce/tinymce.editor/#getwin
// https://www.tiny.cloud/docs/api/tinymce/tinymce.editor/#getdoc
// https://www.tiny.cloud/docs/tinymce/latest/apis/tinymce.editor/#getWin
// https://www.tiny.cloud/docs/tinymce/latest/apis/tinymce.editor/#getDoc
const win = editor.getWin();
const doc = editor.getDoc();
setupWebComponent(win, doc, editor);
Expand All @@ -69,9 +78,9 @@
// on the web component to make it behave like a noneditable but selectable
// element inside TinyMCE. But we don't want the contenteditable attribute
// to be saved with the content. We therefore need to filter out the attribute
// upon serlialization (which happens on "save", view sourcecode and preview
// upon serialization (which happens on "save", view source code and preview
// among others).
// https://www.tiny.cloud/docs/api/tinymce.dom/tinymce.dom.serializer/#addnodefilter
// https://www.tiny.cloud/docs/tinymce/latest/apis/tinymce.dom.serializer/#addNodeFilter
editor.serializer.addNodeFilter('conditional-block', (nodes) => {
// Iterate through all filtered nodes and remove the contenteditable attribute
// as well as the wrapper <div> we add when creating the custom element
Expand All @@ -81,15 +90,15 @@
node.attr('contenteditable', null);
// Traverse into the first child which would be the <div contenteditable="true">
// and use unwrap to remove the <div> but keep the children.
// https://www.tiny.cloud/docs/api/tinymce.html/tinymce.html.node/#unwrap
// https://www.tiny.cloud/docs/tinymce/latest/apis/tinymce.html.node/#unwrap
node.firstChild.unwrap();
}
});
});
});

// Register a custom toolbar menu button to insert the conditional block
// https://www.tiny.cloud/docs/ui-components/typesoftoolbarbuttons/#menubutton
// https://www.tiny.cloud/docs/tinymce/latest/custom-menu-toolbar-button/
editor.ui.registry.addButton('conditionalblock', {
icon: 'conditional-block',
tooltip: 'Insert conditional block',
Expand All @@ -104,8 +113,8 @@
// In a real world scenario, with much more custom styles for headings
// links, tables, images etc, it's recommended to use the content_css
// option to load a separate CSS file. Makes editing easier too.
// https://www.tiny.cloud/docs/configure/content-appearance/#content_style
// https://www.tiny.cloud/docs/configure/content-appearance/#content_css
// https://www.tiny.cloud/docs/tinymce/latest/add-css-options/#content_style
// https://www.tiny.cloud/docs/tinymce/latest/add-css-options/#content_css
content_style: `
/* We remove the default selected outline because it doesn't follow the
* border radius and reintroduce it as a box-shadow.
Expand Down Expand Up @@ -307,8 +316,7 @@
const dialogManager = (conditionalBlock, editor) => {
// Open a TinyMCE modal where the user can set the badge's
// background and text color.
// https://www.tiny.cloud/docs/ui-components/dialog/
// https://www.tiny.cloud/docs/ui-components/dialogcomponents/
// https://www.tiny.cloud/docs/tinymce/latest/dialog/
editor.windowManager.open({
title: 'Insert/edit Conditional block',
body: {
Expand Down Expand Up @@ -368,13 +376,13 @@
// Check if a block is edited or a new block is to be inserted
if (!conditionalBlock) {
// Insert content at the location of the cursor.
// https://www.tiny.cloud/docs/api/tinymce/tinymce.editor/#insertcontent
// https://www.tiny.cloud/docs/tinymce/latest/apis/tinymce.editor/#insertContent
editor.insertContent(`<conditional-block data-property="${data.property}" data-operator="${data.operator}" data-value="${data.value}"><p>Write conditional text here</p></conditional-block>`);
}
else {
// Working directly with the DOM often requires manually adding
// the actions to the undo stack.
// https://www.tiny.cloud/docs/api/tinymce/tinymce.undomanager/
// https://www.tiny.cloud/docs/tinymce/latest/apis/tinymce.undomanager/
editor.undoManager.transact(() => {
// Update the data-attributes on the conditional-block element
conditionalBlock.dataset.property = data.property;
Expand All @@ -383,7 +391,7 @@
});

// Tell TinyMCE that the ui has been updated.
// https://www.tiny.cloud/docs/api/tinymce/tinymce.editor/#nodechanged
// https://www.tiny.cloud/docs/tinymce/latest/apis/tinymce.editor/#nodeChanged
editor.nodeChanged();
}

Expand Down
44 changes: 23 additions & 21 deletions cool-demos/expand-editor-and-show-toolbar.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!--
This demo showcases a minimalist editor that expands on focus
This demo showcases a minimalist editor that expands on focus.
It uses the TinyMCE inline mode to allow for greater control
over the toolbar position and behavior.
over the toolbar position and behavior.
-->

<!doctype html>
Expand All @@ -10,40 +10,39 @@
<meta charset="utf-8">
<title>Expand and show toolbar demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.tiny.cloud/1/qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc/tinymce/5-dev/tinymce.min.js" referrerpolicy="origin"></script>
<script src="https://cdn.tiny.cloud/1/qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc/tinymce/8/tinymce.min.js" referrerpolicy="origin"></script>

<script>
tinymce.init({
selector: "#editor-content",
plugins: "emoticons hr image link lists charmap table",
toolbar: "formatgroup paragraphgroup insertgroup",
plugins: "emoticons image link lists charmap table",
placeholder: "Ask a question or post an update...",
menubar: false,
skin: 'naked',
icons: 'thin',

// Enable inline mode
// https://www.tiny.cloud/docs/configure/editor-appearance/#inline
// https://www.tiny.cloud/docs/tinymce/latest/use-tinymce-inline/
inline: true,

// Render the toolbar in this container.
// https://www.tiny.cloud/docs/configure/editor-appearance/#fixed_toolbar_container
// https://www.tiny.cloud/docs/tinymce/latest/menus-configuration-options/#fixed_toolbar_container
fixed_toolbar_container: '#editor-toolbar',

// Makes menus move upwards
// https://www.tiny.cloud/docs/configure/editor-appearance/#toolbar_location
// https://www.tiny.cloud/docs/tinymce/latest/toolbar-configuration-options/#toolbar_location
toolbar_location: 'bottom',

// Remove the manual image resizing as we're using percentage widths
// https://www.tiny.cloud/docs/configure/advanced-editing-behavior/#object_resizing
// https://www.tiny.cloud/docs/tinymce/latest/content-behavior-options/#object_resizing
object_resizing: false,

// Hide the right click context menus
// https://www.tiny.cloud/docs/configure/editor-appearance/#contextmenu
// https://www.tiny.cloud/docs/tinymce/latest/menus-configuration-options/#contextmenu
contextmenu: false,

// Create three custom toolbar groups
// https://www.tiny.cloud/docs/configure/editor-appearance/#toolbar_groups
// https://www.tiny.cloud/docs/tinymce/latest/toolbar-configuration-options/#toolbar_groups
toolbar_groups: {
formatgroup: {
icon: 'format',
Expand All @@ -61,31 +60,34 @@
items: 'link image emoticons charmap hr'
}
},

// Show the three toolbar groups
toolbar: "formatgroup paragraphgroup insertgroup",

// On mobile, toolbar_mode is sliding by default which is not compatible
// with toolbar_groups. Therefore we explicitly set toolbar_mode to floating
// on mobile and touch devices.
// https://www.tiny.cloud/docs/configure/editor-appearance/#toolbar_mode
// https://www.tiny.cloud/docs/configure/editor-appearance/#mobile
// https://www.tiny.cloud/docs/tinymce/latest/toolbar-configuration-options/#toolbar_mode
// https://www.tiny.cloud/docs/tinymce/latest/tinymce-for-mobile/
mobile: {
toolbar_mode: 'floating'
},

setup: (editor) => {
// Apply a custom class to the wrapper element when the editor gets focus
// https://www.tiny.cloud/docs/advanced/events/
// https://www.tiny.cloud/docs/tinymce/latest/events/
editor.on('focus', () => {
document.getElementById('editor-wrap').classList.add('focused');
});

// Remove the custom class when the editor loses focus
// https://www.tiny.cloud/docs/advanced/events/
// https://www.tiny.cloud/docs/tinymce/latest/events/
editor.on('blur', () => {
document.getElementById('editor-wrap').classList.remove('focused');
});

// Register a custom context toolbar for images
// https://www.tiny.cloud/docs/ui-components/contexttoolbar/#registeringacontexttoolbar
// https://www.tiny.cloud/docs/tinymce/latest/contexttoolbar/#registeringacontexttoolbar
editor.ui.registry.addContextToolbar('editimage', {
predicate: (node) => {
return node.nodeName.toLowerCase() === 'img'
Expand All @@ -96,24 +98,24 @@
});

// Register a custom edit image button
// https://www.tiny.cloud/docs/ui-components/toolbarbuttons/
// https://www.tiny.cloud/docs/tinymce/latest/custom-toolbarbuttons/
editor.ui.registry.addButton('editimage', {
icon: 'edit-block',
onAction: () => {
// Display the image dialog
// https://www.tiny.cloud/docs/plugins/image/#commands
// https://www.tiny.cloud/docs/tinymce/latest/image/#commands
editor.execCommand('mceImage');
}
});

// Register a custom remove image button
// https://www.tiny.cloud/docs/ui-components/toolbarbuttons/
// https://www.tiny.cloud/docs/tinymce/latest/custom-toolbarbuttons/
editor.ui.registry.addButton('removeimage', {
icon: 'remove',
onAction: () => {
// Get the currently selected content (called "node") and delete it.
// https://www.tiny.cloud/docs/api/tinymce.dom/tinymce.dom.selection/
// https://www.tiny.cloud/docs/api/tinymce.html/tinymce.html.node/
// https://www.tiny.cloud/docs/tinymce/latest/apis/tinymce.dom.selection/
// https://www.tiny.cloud/docs/tinymce/latest/apis/tinymce.html.node/
const node = tinymce.activeEditor.selection.getNode();
node.remove();
}
Expand Down
Loading
Loading