Toolbar integration in EJ2 TypeScript Signature control

15 May 202324 minutes to read

The Signature control integrates with the toolbar and the interaction performed using the change event of the toolbar. In that, canUndo, canRedo and isEmpty methods were used to enable/disable undo, redo, and clear buttons.

import { Toolbar, ClickEventArgs } from '@syncfusion/ej2-navigations';
import { CheckBox, ChangeEventArgs } from '@syncfusion/ej2-buttons';
import { SplitButton, ItemModel, MenuEventArgs } from '@syncfusion/ej2-splitbuttons';
import { Button } from '@syncfusion/ej2-buttons';
import { Signature, ColorPicker, ColorPickerEventArgs, PaletteTileEventArgs, SignatureFileType } from '@syncfusion/ej2-inputs';
import { addClass, createElement, getComponent, enableRipple } from '@syncfusion/ej2-base';
import { DropDownList } from '@syncfusion/ej2-dropdowns';

enableRipple(true);

let signature: Signature = new Signature({
    maxStrokeWidth: 2,
    change: function() {
        if (!signature.isEmpty()) {
            var saveBtn: SplitButton = getComponent(document.getElementById("save-option"), 'split-btn');
            clearButton();
            saveBtn.disabled = false;
        }
        updateUndoRedo();
    }
});
signature.appendTo('#signature');

let items: ItemModel[] = [
    {
        text: 'Png'
    },
    {
        text: 'Jpeg'
    },
    {
        text: 'Svg'
}];

let toolbarObj: Toolbar = new Toolbar({
    width: '100%',
    items: [
        { text: 'Undo', prefixIcon: 'e-icons e-undo', tooltipText: 'Undo (Ctrl + Z)' },
        { text: 'Redo', prefixIcon: 'e-icons e-redo', tooltipText: 'Redo (Ctrl + Y)' },
        { type: 'Separator' },
        { tooltipText: 'Save (Ctrl + S)', type: 'Button', template: '<button id="save-option"></button>' },
        { type: 'Separator' },
        { tooltipText: 'Stroke Color', type: 'Input', template: '<input id="stroke-color" type="color"/>' },
        { type: 'Separator' },
        { tooltipText: 'Background Color', type: 'Input', template: '<input id="bg-color" type="color"/>' },
        { type: 'Separator' },
        { tooltipText: 'Stroke Width', type: 'Input', template: '<input id="stroke-width" type="text"/>' },
        { type: 'Separator' },
        { text: 'Clear', prefixIcon: 'e-sign-icons e-clear', tooltipText: 'Clear' },
        { tooltipText: 'Disabled', type: 'Input', template: new CheckBox({ label: 'Disabled', checked: false, change: disabledChange}), align: 'Right' }
    ],
    created: () => {
        let ddl: DropDownList = new DropDownList({
            dataSource:  [1, 2, 3, 4, 5],
            width: '60',
            value: 2,
            change: function(args) {
                signature.maxStrokeWidth = args.value;
            }
        });
        ddl.appendTo('#stroke-width');
        new SplitButton({ iconCss: 'e-sign-icons e-save', content: 'Save', items: items, select: onSelect, disabled: true  }, '#save-option');
        let strokeColor: ColorPicker = new ColorPicker({
            modeSwitcher: false,
            columns: 4,
            presetColors: {
                'custom': ['#000000', '#000000', '#e91e63', '#9c27b0', '#673ab7', '#2196f3', '#03a9f4', '#00bcd4',
                '#009688', '#8bc34a', '#cddc39', '#ffeb3b']
            },
            beforeTileRender: (args: PaletteTileEventArgs) => {
                args.element.classList.add('e-circle-palette');
                args.element.appendChild(createElement('span', { className: 'e-circle-selection' }));
            },
            showButtons: false, mode: 'Palette', cssClass: 'e-stroke-color', change: strokeColorChanged});
        strokeColor.appendTo('#stroke-color');
        let bgColor: ColorPicker = new ColorPicker({
            modeSwitcher: false,
            columns: 4,
            presetColors: {
                'custom': ['#ffffff', '#f44336', '#e91e63', '#9c27b0', '#673ab7', '#2196f3', '#03a9f4', '#00bcd4',
                '#009688', '#8bc34a', '#cddc39', '#ffeb3b']
            },
            beforeTileRender: (args: PaletteTileEventArgs) => {
                args.element.classList.add('e-circle-palette');
                args.element.appendChild(createElement('span', { className: 'e-circle-selection' }));
            },
            showButtons: false, mode: 'Palette', cssClass: 'e-bg-color', noColor: true, change: bgColorChanged});
        bgColor.appendTo('#bg-color');
        addClass([strokeColor.element.nextElementSibling.querySelector('.e-selected-color')], 'e-sign-icons');
        addClass([bgColor.element.nextElementSibling.querySelector('.e-selected-color')], 'e-sign-icons');
        clearButton();
        let toolbarlItems: NodeListOf<Element> = document.querySelectorAll('.e-toolbar .e-toolbar-items .e-toolbar-item .e-tbar-btn.e-tbtn-txt');
        for (var i = 0; i < toolbarlItems.length; i++) {
            if (toolbarlItems[i].children[0].classList.contains('e-undo')) {
                let undoButton: Button = getComponent(toolbarlItems[i] as HTMLElement, 'btn');
                undoButton.disabled = true;
            }
            if (toolbarlItems[i].children[0].classList.contains('e-redo')) {
                let redoButton: Button = getComponent(toolbarlItems[i] as HTMLElement, 'btn');
                redoButton.disabled = true;
            }
        }
    },
    clicked: (args: ClickEventArgs) => {
        let saveBtn: SplitButton = getComponent(document.getElementById("save-option"), 'split-btn');
        if (signature.disabled && args.item.tooltipText != 'Disabled') {
            return;
        }
        switch (args.item.tooltipText) {
            case 'Undo (Ctrl + Z)':
                if (signature.canUndo()) {
                    signature.undo();
                    updateUndoRedo();
                    updateSaveBtn();
                }
                break;
            case 'Redo (Ctrl + Y)':
                if (signature.canRedo()) {
                    signature.redo();
                    updateUndoRedo();
                    updateSaveBtn();
                }
                break;
            case 'Clear':
                signature.clear();
                if (signature.isEmpty()) {
                    clearButton();
                    saveBtn.disabled = true;
                }
                break;
        }
    }
});
toolbarObj.appendTo('#toolbar');

function disabledChange(args: ChangeEventArgs): void {
    signature.disabled = args.checked;
}

function updateSaveBtn() {
    let saveBtn: SplitButton = getComponent(document.getElementById("save-option"), 'split-btn');
    if (signature.isEmpty()) {
        saveBtn.disabled = true;
    }
}

function onSelect(args: MenuEventArgs): void {
    signature.save(args.item.text as SignatureFileType, 'Signature');
}

document.getElementById('save-option').onclick = function () {
    signature.save();
};

function strokeColorChanged(args: ColorPickerEventArgs): void {
    if (signature.disabled) {
        return;
    }
    let selElem: HTMLElement = this.element.nextElementSibling.querySelector('.e-selected-color') as HTMLElement;
    selElem.style.borderBottomColor = args.currentValue.rgba;
    signature.strokeColor = args.currentValue.rgba;
}

function bgColorChanged(args: ColorPickerEventArgs): void {
    if (signature.disabled) {
        return;
    }
    let selElem: HTMLElement = this.element.nextElementSibling.querySelector('.e-selected-color') as HTMLElement;
    signature.backgroundColor = args.currentValue.rgba;
    selElem.style.borderBottomColor = args.currentValue.rgba;
}

function clearButton() {
    let tlItems: NodeListOf<Element> = document.querySelectorAll('.e-toolbar .e-toolbar-items .e-toolbar-item .e-tbar-btn.e-tbtn-txt');
    for (var i = 0; i < tlItems.length; i++) {
        if (tlItems[i].children[0].classList.contains('e-clear')) {
            let clrBtn: Button = getComponent(tlItems[i] as HTMLElement, 'btn');
            if (signature.isEmpty()) {
                clrBtn.disabled = true;
            } else {
                clrBtn.disabled = false;
            }
        }
    }
}

function updateUndoRedo() {
    let undoButton: Button; let redoButton: Button
    let tlItems: NodeListOf<Element> = document.querySelectorAll('.e-toolbar .e-toolbar-items .e-toolbar-item .e-tbar-btn.e-tbtn-txt');
    for (var i = 0; i < tlItems.length; i++) {
        if (tlItems[i].children[0].classList.contains('e-undo')) {
            undoButton = getComponent(tlItems[i] as HTMLElement, 'btn');
        }
        if (tlItems[i].children[0].classList.contains('e-redo')) {
            redoButton = getComponent(tlItems[i] as HTMLElement, 'btn');
        }
    }
    if (signature.canUndo()) {
        undoButton.disabled = false;
    } else {
        undoButton.disabled = true;
    }
    if (signature.canRedo()) {
        redoButton.disabled = false;
    } else {
        redoButton.disabled = true;
    }
}
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Signature</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="TypeScript Signature Component" />
    <meta name="author" content="Syncfusion" />
    <link href="styles.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/25.1.35/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/25.1.35/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/25.1.35/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/25.1.35/ej2-navigations/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/25.1.35/ej2-dropdowns/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/25.1.35/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/25.1.35/ej2-popups/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div id="signature-toolbar-control">
            <div id="toolbar" style="width: 100%;"></div>
            <div id="signature-control">
                <canvas id="signature" style="height: 100%; width: 100%;"></canvas>
            </div>
        </div>
    </div>
</body>
</html>
#container {
    visibility: hidden;
}

#loader {
  color: #008cff;
  font-family: 'Helvetica Neue','calibiri';
  font-size: 14px;
  height: 40px;
  left: 45%;
  position: absolute;
  top: 45%;
  width: 30%;
}

@font-face {
  font-family: 'font-icons';
  src:
  url(data:application/x-font-ttf;charset=utf-8;base64,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) format('truetype');
  font-weight: normal;
  font-style: normal;
}

.e-sign-icons {
  font-family: 'font-icons' !important;
  font-size: 55px;
  font-style: normal;
  font-weight: normal;
  font-variant: normal;
  text-transform: none;
  line-height: 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

#toolbar-control {
  border: 1px solid lightgray;
}

#toolbar {
  border: none;
  border-bottom: 1px solid lightgray;
  box-sizing: border-box;
}

#toolbar-control .e-btn:disabled {
  opacity: 0.5 !important;
  pointer-events: none;
}

#signature-control {
  height: 300px;
  width: 100%;
  margin: 0;
}

#signature {
  border: 1px solid lightgray;
}

.e-colorpicker-wrapper.e-bg-color #bg-color+.e-split-btn-wrapper .e-split-btn .e-selected-color {
  background: none;
  border-bottom-style: solid;
  border-bottom-width: 3px;
  width: 14px;
  margin: 0px 2px;
  border-bottom-color: #ffffff;
}
.e-colorpicker-wrapper.e-stroke-color #stroke-color+.e-split-btn-wrapper .e-split-btn .e-selected-color {
  background: none;
  border-bottom-style: solid;
  border-bottom-width: 3px;
  width: 14px;
  margin: 0px 2px;
  border-bottom-color: #000000;
}

.e-colorpicker-wrapper.e-bg-color #bg-color+.e-split-btn-wrapper .e-split-btn .e-selected-color .e-split-preview,
.e-colorpicker-wrapper.e-stroke-color #stroke-color+.e-split-btn-wrapper .e-split-btn .e-selected-color .e-split-preview {
  display: none;
}

.e-colorpicker-wrapper.e-bg-color #bg-color+.e-split-btn-wrapper .e-split-btn .e-selected-color::before {
  content: '\e707';
}

.e-colorpicker-wrapper.e-stroke-color #stroke-color+.e-split-btn-wrapper .e-split-btn .e-selected-color::before {
  content: '\e704';
}

.e-clear::before {
  content: '\e706';
}

.e-save::before {
  content: '\e701';
}
.e-container .e-palette .e-circle-palette {
  border: 0;
  height: 32px;
  width: 32px;
  border-radius: 20px;
  margin: 4px;
}
.e-container .e-palette .e-circle-palette:hover {
  box-shadow: none;
  transform: scale(1.2);
  transition: transform .2s ease-out;
}
.e-circle-palette .e-circle-selection {
  height: 32px;
  width: 32px;
  border-radius: 20px;
  display: inline-block;
  transform: scale(0);
  transition: transform 1.2s ease-in;
}
.e-circle-palette.e-selected .e-circle-selection {
  transform: scale(0.8);
  background-color: #fff;
  transition: transform .2s ease-out;
}
#circle-palette+.e-container,
#scroll-palette+.e-container {
  background-color: transparent;
  border-color: transparent;
  box-shadow: none;
}