const onButtonClick = (name) => {
DevExpress.ui.notify(`The "${name}" button has been clicked`);
};
const onSelectionChanged = (name) => {
DevExpress.ui.notify(`The "${name}" value has been changed`);
};
const onFontFamilyClick = () => {
DevExpress.ui.notify('The "Font Family" value has been changed');
};
const onHeadingClick = () => {
DevExpress.ui.notify('The "Heading" value has been changed');
};
const toolbarSeparator = {
locateInMenu: 'auto',
location: 'before',
template(itemData, itemIndex, element) {
$('<div>')
.addClass('toolbar-separator')
.appendTo(element);
},
menuItemTemplate(itemData, itemIndex, element) {
$('<div>')
.addClass('toolbar-menu-separator')
.appendTo(element);
},
};
const toolbarItems = [
{
location: 'before',
widget: 'dxButton',
options: {
icon: 'undo',
onClick() {
onButtonClick('Undo');
},
},
},
{
location: 'before',
widget: 'dxButton',
options: {
icon: 'redo',
onClick() {
onButtonClick('Redo');
},
},
},
toolbarSeparator,
{
location: 'before',
locateInMenu: 'auto',
widget: 'dxDropDownButton',
options: {
width: '100%',
displayExpr: 'text',
keyExpr: 'size',
useSelectMode: true,
items: fontSizes,
selectedItemKey: 14,
itemTemplate(itemData) {
return $('<div>')
.text(itemData.text)
.css('font-size', `${itemData.size}px`);
},
onSelectionChanged() {
onSelectionChanged('Font Size');
},
},
},
{
location: 'before',
locateInMenu: 'auto',
widget: 'dxDropDownButton',
options: {
width: '100%',
icon: 'indent',
displayExpr: 'text',
keyExpr: 'lineHeight',
useSelectMode: true,
items: lineHeights,
selectedItemKey: 1.35,
onSelectionChanged() {
onSelectionChanged('Line Height');
},
},
},
{
locateInMenu: 'auto',
location: 'before',
widget: 'dxSelectBox',
options: {
placeholder: 'Font',
displayExpr: 'text',
dataSource: fontFamilies,
inputAttr: { 'aria-label': 'Font' },
onItemClick() {
onFontFamilyClick();
},
},
},
toolbarSeparator,
{
location: 'before',
widget: 'dxButtonGroup',
options: {
displayExpr: 'text',
items: fontStyles,
keyExpr: 'icon',
stylingMode: 'outlined',
selectionMode: 'multiple',
onItemClick(e) {
onButtonClick(e.itemData.hint);
},
},
},
{
location: 'before',
template(itemData, itemIndex, element) {
$(element).addClass('toolbar-separator');
},
},
{
locateInMenu: 'auto',
location: 'before',
widget: 'dxButtonGroup',
template(itemData, itemIndex, element) {
const $buttonGroup = $('<div>').dxButtonGroup({
items: textAlignItems,
keyExpr: 'alignment',
stylingMode: 'outlined',
selectedItemKeys: ['left'],
onItemClick(e) {
onButtonClick(e.itemData.hint);
},
});
$buttonGroup.appendTo(element);
},
menuItemTemplate(itemData, itemIndex, element) {
const $buttonGroup = $('<div>').dxButtonGroup({
displayExpr: 'text',
items: textAlignItemsExtended,
keyExpr: 'alignment',
stylingMode: 'outlined',
selectedItemKeys: ['left'],
onItemClick(e) {
onButtonClick(e.itemData.hint);
},
});
$buttonGroup.appendTo(element);
},
},
{
location: 'before',
widget: 'dxButtonGroup',
options: {
items: listTypes,
keyExpr: 'alignment',
stylingMode: 'outlined',
onItemClick(e) {
onButtonClick(e.itemData.hint);
},
},
},
toolbarSeparator,
{
locateInMenu: 'auto',
location: 'before',
widget: 'dxSelectBox',
options: {
displayExpr: 'text',
valueExpr: 'text',
value: headings[0].text,
dataSource: headings,
inputAttr: { 'aria-label': 'Text Style' },
onItemClick() {
onHeadingClick();
},
},
},
toolbarSeparator,
{
location: 'before',
locateInMenu: 'auto',
widget: 'dxButton',
showText: 'inMenu',
options: {
icon: 'link',
text: 'Link',
onClick() {
onButtonClick('Link');
},
},
},
{
location: 'before',
locateInMenu: 'auto',
widget: 'dxButton',
showText: 'inMenu',
options: {
icon: 'image',
text: 'Add image',
onClick() {
onButtonClick('Add Image');
},
},
},
toolbarSeparator,
{
location: 'before',
locateInMenu: 'auto',
widget: 'dxButton',
showText: 'inMenu',
options: {
icon: 'clearformat',
text: 'Clear formating',
onClick() {
onButtonClick('Clear Formating');
},
},
},
{
location: 'before',
locateInMenu: 'auto',
widget: 'dxButton',
showText: 'inMenu',
options: {
icon: 'codeblock',
text: 'Code block',
onClick() {
onButtonClick('Code Block');
},
},
},
{
location: 'before',
locateInMenu: 'auto',
widget: 'dxButton',
showText: 'inMenu',
options: {
icon: 'blockquote',
text: 'Blockquote',
onClick() {
onButtonClick('Blockquote');
},
},
},
toolbarSeparator,
{
location: 'after',
widget: 'dxButton',
showText: 'inMenu',
options: {
icon: 'attach',
text: 'Attach',
onClick() {
onButtonClick('Attach');
},
},
},
{
locateInMenu: 'always',
widget: 'dxButton',
showText: 'inMenu',
options: {
icon: 'help',
text: 'About',
onClick() {
onButtonClick('About');
},
},
},
];
$(() => {
$('#resizable-container').dxResizable({
minWidth: 500,
minHeight: 150,
maxHeight: 370,
handles: 'right',
area: '.widget-container',
});
const toolbar = $('#toolbar').dxToolbar({
dataSource: toolbarItems,
multiline: true,
}).dxToolbar('instance');
$('#toolbar-mode').dxCheckBox({
value: true,
text: 'Multiline mode',
onValueChanged(e) {
toolbar.option('multiline', e.value);
},
});
});
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title>DevExtreme Demo</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>window.jQuery || document.write(decodeURIComponent('%3Cscript src="js/jquery.min.js"%3E%3C/script%3E'))</script>
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/24.2.3/css/dx.light.css" />
<script src="js/dx.all.js"></script>
<script src="data.js"></script>
<link rel="stylesheet" type="text/css" href="styles.css" />
<script src="index.js"></script>
</head>
<body class="dx-viewport">
<div class="demo-container">
<div class="widget-container">
<div id="resizable-container" class="resizable-container">
<div id="toolbar"></div>
</div>
</div>
<div class="options-container">
<div class="caption">Options</div>
<div id="toolbar-mode"></div>
</div>
</div>
</body>
</html>
.dx-resizable-handle::after {
content: "";
position: absolute;
width: 9px;
height: 36px;
border: none;
border-radius: 50px;
background-color: #fff;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.24);
}
.dx-resizable-handle-right::after {
top: 50%;
right: -5px;
transform: translateY(-50%);
}
.dx-toolbar.dx-toolbar-multiline .dx-toolbar-item {
margin-bottom: 5px;
}
.widget-container {
margin-right: 10px;
}
.resizable-container {
padding: 10px;
height: 300px;
border: 1px dotted #999;
border-radius: 4px;
box-sizing: border-box;
}
.options-container {
margin-top: 20px;
padding: 20px;
background-color: rgba(191, 191, 191, 0.15);
position: relative;
}
.caption {
font-size: 18px;
font-weight: 500;
margin-bottom: 10px;
}
.toolbar-separator {
height: 36px;
margin: 0 5px;
border-left: 1px solid #ddd;
}
.toolbar-menu-separator {
height: 1px;
border-bottom: 1px solid #ddd;
}
const fontSizes = [
{ size: 10, text: '10px' },
{ size: 12, text: '12px' },
{ size: 14, text: '14px' },
{ size: 16, text: '16px' },
{ size: 18, text: '18px' },
];
const lineHeights = [
{ lineHeight: 1, text: '1' },
{ lineHeight: 1.35, text: '1.35' },
{ lineHeight: 1.5, text: '1.5' },
{ lineHeight: 2, text: '2' },
];
const fontFamilies = [
{ text: 'Arial' },
{ text: 'Courier New' },
{ text: 'Georgia' },
{ text: 'Impact' },
{ text: 'Lucida Console' },
{ text: 'Tahoma' },
{ text: 'Times New Roman' },
];
const headings = [
{ text: 'Normal text' },
{ text: 'Heading 1' },
{ text: 'Heading 2' },
{ text: 'Heading 3' },
{ text: 'Heading 4' },
{ text: 'Heading 5' },
];
const fontStyles = [
{
icon: 'bold',
hint: 'Bold',
},
{
icon: 'italic',
hint: 'Italic',
},
{
icon: 'underline',
hint: 'Underlined',
},
{
icon: 'strike',
hint: 'Strikethrough',
},
];
const textAlignItemsExtended = [
{
icon: 'alignleft',
alignment: 'left',
hint: 'Align Left',
text: 'Align left',
},
{
icon: 'aligncenter',
alignment: 'center',
hint: 'Center',
text: 'Center',
},
{
icon: 'alignright',
alignment: 'right',
hint: 'Align Right',
text: 'Align right',
},
{
icon: 'alignjustify',
alignment: 'justify',
hint: 'Justify',
text: 'Justify',
},
];
const textAlignItems = textAlignItemsExtended.map((item) => {
const { icon, alignment, hint } = item;
return {
icon,
alignment,
hint,
};
});
const listTypes = [
{
icon: 'orderedlist',
alignment: 'orderedlist',
hint: 'Ordered',
},
{
icon: 'bulletlist',
alignment: 'bulletlist',
hint: 'Bullet',
},
];