Show / Hide Table of Contents

Web Label Editor

The ThermalLabel Web Editor Add-on is a first-class barcode label designer component for ASP.NET websites (Legacy MVC & WebForms and ASP.NET CORE). It gives your web apps an end-user visual label editor. The component leverages and requires the ThermalLabel SDK and is built on jQuery and HTML5 Canvas (Fabric.js 1.x). It runs on Windows, Linux, Mac & Android clients with modern browsers.

Web Label Editor

The editor (highlighted inside the red rectangle) provides visual aids for creating text, barcodes, pictures, tables, RFID tags and shapes; Z-ordering; zooming; in-place text editing; grouping and multi-selection; duplex (two-sided) design; undo/redo; clipboard support; and much more. It is also highly customizable, so you can skin it to match the UI of the app that hosts it.

With the Web Editor, your end users can create, load, edit and save ThermalLabel objects as XML or JSON template definitions.

Note

This document is a feature guide. Every property, method and event is described in detail in the API reference (apiref.md). Here the features are grouped by topic, with short examples.

System Requirements

Server-side

  • Windows Server, or Linux if using ASP.NET CORE
  • Legacy ASP.NET 4.6.1+ or ASP.NET CORE 2.0+
  • ThermalLabel Web Editor Server Component 16.0 (Neodynamic.Web.ThermalLabelEditor.dll)
  • ThermalLabel SDK 16.0 (Neodynamic.SDK.ThermalLabel.dll)
  • ThermalLabel SDK 16.0 Web Printing (Neodynamic.SDK.ThermalLabel.WebPrinting.dll)
  • SkiaSharp 1.68.3+
  • System.Text.Encoding.CodePages 4.4.0+

Client-side (web page)

  • ThermalLabel Web Editor JavaScript Component 16.0 (ThermalLabelWebEditor-16.0.xx.xxxx.js). It already bundles the fabric.CanvasEx extension (fabric.canvasex.js, MIT), so you do not need to reference it separately.
  • ThermalLabel Web Editor CSS 16.0 (ThermalLabelWebEditor-16.0.css)
  • jQuery 1.7+
  • Fabric.js 1.5+ (1.x line only; Fabric 2.x/3.x/4.x/5.x are not supported)

Client OS & browser

  • OS: Windows, Linux, Mac & Android. Printing is only available on Windows clients and requires .NET Framework 4.6.1+.
  • Browser: Edge, Chrome, Firefox and Safari (latest versions); Internet Explorer 10+ is supported for the basic features.
  • TLClientPrint 16.0 (printing from Windows clients only)

Sample Application Projects

The ThermalLabel SDK repo at GitHub provides ASP.NET WebForms, MVC & ASP.NET CORE sample projects that use the ThermalLabelWebEditor component. Open them with Visual Studio to learn how the component works and how to interact with it.

Important

These sample projects are very simple and do NOT demo all the ThermalLabel SDK and Editor features. They may contain errors, bugs or bad practices, so do not treat them as a model for how to structure your own app. They only demonstrate how to interact with the ThermalLabelWebEditor component.

Architecture Overview

The editor is split in two parts that work together:

  • Client (browser): a TypeScript/JavaScript component on top of Fabric.js 1.x. It manages the design surface, selection, handlers, zoom, undo/redo, clipboard and so on. It holds a client-side object model (ThermalLabel and item classes such as TextItem, BarcodeItem, ImageItem, etc.) under the Neodynamic.SDK.Printing namespace.
  • Server (your ASP.NET app): an HTTP Handler (WebForms) or Controller (MVC / ASP.NET CORE) that you code, using the server-side Neodynamic.Web.ThermalLabelEditor component.

Every time a TextItem, BarcodeItem, ImageItem or TableShapeItem changes or is resized/zoomed, the editor sends an asynchronous request to your handler/controller and displays the returned image. Shapes (rectangle, ellipse, line), repeaters, RFID tags and literals are drawn locally and do not need a round trip for rendering.

All requests are POST calls to the URL given by thermalLabelWebEditorControllerName and carry an Action field:

Action Purpose
Render Renders a Text, Barcode, Image or Table item to PNG
Validate Validates whether a barcode can be printed as a resident (native printer) element
GetLabelTemplate Converts the label model to an XML or JSON template
GetLabelPreview / GetLabelThumbnail Preview and thumbnail generation
GetLabelAsPdf / GetLabelAsImage PDF and image export
GetPrinterCommands Printer commands (ZPL, EPL, etc.) generation
Save Downloads the template as a file
Print Registers a print job for TLClientPrint
Expressions Returns the list of supported expressions
GetI18NResourceKey Returns localized UI strings used by the editor
Tip

If the server fails to render an item, the editor shows a "missing image" placeholder on the design surface and raises the onError event with the server message.

Quick Start

1. Reference the resources and add a host element

<link rel="stylesheet" href="ThermalLabelWebEditor-16.0.css" />
<script src="jquery.min.js"></script>
<script src="fabric.min.js"></script>
<script src="ThermalLabelWebEditor-16.0.xx.xxxx.js"></script>

<div id="editorHost" style="width:100%; height:600px"></div>

2. Create, enable and load the editor

var Printing = Neodynamic.SDK.Printing;
var TLE = Neodynamic.Web.Editor.ThermalLabelEditor;

// Required: URL of your MVC Controller action / HTTP Handler
TLE.thermalLabelWebEditorControllerName = "ThermalLabelWebEditorHandler/ProcessRequest";
// Optional: only if the editor is hosted at a different root than the page
// TLE.websiteRootAbsoluteUrl = "https://myserver.com/myapp";

// The container is a jQuery SELECTOR string
var editor = new TLE("#editorHost");
editor.enableEditor();               // builds the editor infrastructure

var label = new Printing.ThermalLabel();
label.unit_type = Printing.UnitType.Inch;   // set the unit BEFORE sizes
label.width = 4;
label.height = 3;

editor.loadThermalLabel(label);

3. Add items by code

var txt = new Printing.TextItem();
txt.text = "Hello World";
txt.x = 0.25;
txt.y = 0.25;
txt.width = 2;
txt.height = 0.5;
editor.addItem(txt);

4. …or let the user draw them with the mouse

editor.active_tool_item = new Printing.BarcodeItem();
editor.active_tool = Neodynamic.Web.Editor.EditorTool.Barcode;
// The user now drags on the surface. When done, the tool returns to Pointer
// and the newItemCreated event is raised.

Available tools: Pointer, Rectangle, Ellipse, Line, Text, Barcode, Image, Literal, RFIDTag, Table and Repeater.

Working with Labels and Items

Loading templates

You can load a label from a template or build it from scratch:

var tl1 = Printing.ThermalLabel.createFromXmlTemplate(xmlString);
var tl2 = Printing.ThermalLabel.createFromJsonTemplate(jsonStringOrObject);
editor.loadThermalLabel(tl1);

loadThermalLabel(tl, options) accepts:

  • resetUndoHistory (default true): clears the undo/redo history.
  • resetActivePage (default true): returns to page 0 and resets the view rotation.

Use resetUndoHistory: false, resetActivePage: false if you only want to refresh the editor from the same label (this is what the editor itself does internally when label properties such as size or unit change).

Item types

Class Rendering Notes
TextItem Server Native printer fonts, TrueType and custom fonts; in-place editing
BarcodeItem Server 180+ symbologies (BarcodeSymbology enum), including 2D and postal codes
ImageItem Server Monochrome conversion settings, flip, lock aspect ratio
TableShapeItem Server Rows and columns with individual fill colors
RectangleShapeItem Client Individual corner radius, stroke styles (solid, dash, dot)
EllipseShapeItem Client Stroke styles
LineShapeItem Client Horizontal, vertical and diagonal lines; stroke styles
RepeaterItem Client Design-time placeholder with repeat count
RFIDTagItem Client Displayed in the tray
LiteralItem Client Raw printer commands; displayed in the tray

Units

Every label and item has a unit_type (Inch, Mm, Cm, DotsPerInch, Point, Pica, Mils, Twip). Internally the editor works at 96 DPI pixels, and all property getters/setters convert from/to the item unit. When you change label.unit_type, all items are converted automatically and the rulers and grid are updated. num_of_fractional_digits (default 4) controls the precision of the width/height values shown on the selection handlers.

Programmatic changes

Changing a property on an item object does not repaint it by itself. After you change properties, refresh it and (if you want it in the undo history) save the state:

var item = editor.current_selection;
item.text = "New text";
editor.updateSelectionItemsProperties();   // refreshes (re-renders) the selected item
editor.saveCurrentLabelCanvasState();      // registers an undo step

Selection, Multi-Selection and Grouping

Single selection

Click an item to select it. The editor displays handles for move, resize and rotate, plus the item's width and height. editor.current_selection returns the selected item (or null).

Marquee (rubber-band) multi-selection

Click on an empty area of the design surface and drag to draw a selection rectangle (marquee). When the mouse is released:

  • Items fully contained in the rectangle are selected.
  • Items that belong to a group are selected only if all the group's members are inside the rectangle.
  • Only items on the active page are considered (see Duplex). Tray items are never marquee-selected.
  • If more than one item is selected, the editor creates a temporary group so they move, resize, rotate, lock, delete and z-order together. A single hit simply selects that item.
  • Clicking on an empty area (or on an item outside the temporary group) dissolves the temporary group.

To keep the temporary group as a permanent one, call createGroup().

Note

Marquee selection is enabled for mouse and pen input only. On touch devices use the click-to-group workflow below.

Click-to-group workflow

editor.startGroup();     // each item the user clicks is added to the group
// ...user clicks items...
editor.createGroup();    // commits the group (assigns a common group_name)
editor.cancelGroup();    // cancels instead
editor.unGroup();        // dissolves the group of the current selection

group_started and items_in_started_group help you enable/disable your UI buttons. getItemsInGroup(groupName) returns the items of a group.

Group members behave as a single unit: moving, resizing, rotating, locking, deleting, copying and z-ordering the selected item applies to all members that are editable, visible and (for transforms) not locked.

Programmatic selection

All of these return the number of items selected and switch to the right page automatically on duplex labels:

editor.selectAll();
editor.selectItemByIndex(0);
editor.selectItemByName("txtTitle");
editor.selectItemsByNames(["txtTitle", "bcSku"]);
editor.selectItemsByTag("price");
editor.selectItemsByType("BarcodeItem");
editor.selectItemsByIndexes([0, 2, 5]);

When more than one item is selected programmatically, a temporary group is created, exactly like a marquee selection.

Layout Tools

var LayoutAlignment = Neodynamic.Web.Editor.LayoutAlignment;

editor.alignItems(LayoutAlignment.Left);               // align to the selected item (pivot)
editor.alignItems(LayoutAlignment.CenterHorizontal);
editor.alignItems(LayoutAlignment.DistributeVertical); // needs 3+ items

editor.setSelectedItemsToSameSize(true, false);        // same width
editor.moveSelectedItems(0.1, 0);                      // nudge, in label units

editor.bringToFront();
editor.sendBackward();
editor.lockSelectedItems();
editor.unlockSelectedItems();
editor.deleteSelectedItems();
editor.deleteAll();

Alignment options: Left, Right, Top, Bottom, CenterHorizontal, CenterVertical, DistributeHorizontal, DistributeVertical.

  • By default the items to align are the current selection (or its group). You can also pass your own list of items and a pivot item.
  • Z-order methods (bringForward, bringToFront, sendBackward, sendToBack) also reorder label.items, which is the order used when printing.
  • deleteAll() clears the whole label, or only the active page on duplex labels.

Zooming, Rulers, Grid and Snapping

Zoom

editor.zoom = 150;     // percent; valid range 10 - 1000
var current = editor.zoom;

All items are rescaled and server-rendered items are re-rendered at the new resolution so they stay sharp. The editor remains centered when the host container is resized; call centerEditor() manually if your layout changes in ways that are not observable.

Rulers

Horizontal and vertical rulers are displayed using the label's unit (inches, mm, points, etc.), scale with the zoom level and highlight the extent of the current selection. Toggle them with editor.show_ruler = true/false.

Grid and Snap to Grid

editor.grid_size = 0.25;                                   // in label units
editor.grid_type = Neodynamic.Web.Editor.GridType.Dots;    // Lines | Dots
editor.show_grid = true;
editor.snap_to_grid = true;                                // position & size snap to the grid

Snap to grid applies when drawing a new item and after moving or resizing an existing one.

Snap to Items (smart guides)

editor.snap_to_items = true;

While dragging an item, dashed guide lines appear when its edges or center align with another item's edges or center, and the item snaps to them on release. Items on the other page of a duplex label are ignored. The guide color is themable (--guidelines-color).

Angle snap

editor.angle_snap (default 5) rounds the rotation to multiples of that many degrees. Use 0 to disable it. Native printer fonts, barcodes, tables and repeaters are always restricted to 90° steps because the printer cannot rotate them otherwise.

View Rotation

The design surface can be rotated in 90° steps without changing the label you will save or print. This is useful to design labels that are fed landscape but easier to read as portrait.

var Rotate = Neodynamic.Web.Editor.Rotate;   // None, Degree90, Degree180, Degree270
editor.rotateView(Rotate.Degree90);
var current = editor.view_rotation;
  • The label dimensions are swapped, and every item is repositioned and rotated accordingly (lines change orientation).
  • Everything that leaves the editor (save, templates, preview, print, PDF, image, clipboard) is normalized back to the original orientation automatically.
  • The undo history stores the view rotation too, so undo/redo restores it.
  • Override viewRotationChanged() to update your UI.
  • Duplex labels rotate page by page and keep the relative gaps.

Duplex (Two-Sided) Design

Duplex labels have a front and a back side. The editor shows one side at a time and offers an animated page flip.

label.is_duplex_design = true;     // front/back pages are created automatically
editor.loadThermalLabel(label);

editor.flipPage();                 // animated 3D flip to the other side
editor.active_page_index = 1;      // jump to a side without animation (0 = front, 1 = back)

What you get:

  • A Front/Back legend above the label and a flip button at its right (both localized and themable).
  • A 3D "card flip" animation (rotateY) when flipping.
  • Items on the inactive side are hidden and cannot be selected or marquee-selected.
  • Selecting an item by code (selectItemByName, etc.) jumps to the side where the item lives.
  • Pasting on the other side maps the items into that side. See Clipboard.
  • Changing the label size keeps both pages in sync.
  • When exporting, the label width is normalized to the combined width of both pages (as the SDK expects).
  • deleteAll() only clears the active side.

When the user (or your code) turns is_duplex_design off, items that live outside page 0 would be lost. Override beforeDuplexDesignDisabled(itemsToRemove) to confirm; return false to cancel the change:

editor.beforeDuplexDesignDisabled = function (itemsToRemove) {
    return confirm(itemsToRemove.length + " item(s) on the back side will be removed. Continue?");
};

Label Shape, Margins and Background

  • Shape: label.shape = Printing.LabelShape.Ellipse renders the label frame as an ellipse (round labels). Items partially outside the ellipse are flagged as out-of-label.
  • Margins: if label.margin is set, the editor draws the margin area in a different color (--label-document-margin-color) and the work area inside it.
  • Design background image: set label.design_background_image (base64 PNG) to display a picture behind the design as a visual guide (for example, a scanned pre-printed label). It is design-time only and is not printed. You can also set a default through the --label-document-frame-background-image CSS variable.
  • Out-of-label adorner: items that are (even partially) outside the label are framed with a dashed colored border. Disable it with editor.adorner_out_of_label_visible = false.

RFID and Literal Items (Tray)

RFIDTagItem and LiteralItem have no visual representation on the printed label. The editor shows them as icons in a tray below the label instead of placing them on the design surface:

editor.rfid_tag_image_file_name = "images/rfid.png";
editor.literal_image_file_name = "images/literal.png";

Tray items can be selected, edited, deleted and copied, but not moved. They keep x = 0, y = 0 in the exported template. Icon size, spacing and colors are themable (--tray-* variables).

In-Place Text Editing

Double-click a TextItem to edit its text directly on the design surface. The editor takes the following into account:

  • input_mask_pattern / input_mask_prompt_char: a masked input is shown instead of a free text area.
  • max_length: the text area limits the number of characters.
  • validation_regex / validation_error_message: used when setting text by code (an Error is thrown if it does not match).
  • Items with editable = false or read_only = true cannot be edited in place.
  • The text is committed when the editor loses focus or when the user presses Esc, and the item is re-rendered by the server.

From code, use textItem.enterInEditMode() and check textItem.is_in_edit_mode.

Undo / Redo

if (editor.can_undo) editor.undo();
if (editor.can_redo) editor.redo();
  • The editor stores a full snapshot of the label on every change made through the UI (move, resize, rotate, create, delete, group, lock, z-order, align, paste, view rotation…).
  • Snapshots also store the view rotation and the duplex page structure.
  • For changes you make by code, call saveCurrentLabelCanvasState() to register a step.
  • Override undoStateChanged() to update the enabled state of your Undo/Redo buttons.
  • loadThermalLabel clears the history by default (see the resetUndoHistory option).

Clipboard

Copy, cut, paste and duplicate are supported, including groups and duplex labels.

editor.clipboardCopy();
editor.clipboardCut();
editor.clipboardPaste();
editor.duplicateSelectedItems();   // copy + paste in a single step, leaves the clipboard untouched

Clipboard modes

var Mode = Neodynamic.Web.Editor.EditorClipboardMode;
editor.clipboard_mode = Mode.Internal;  // default
editor.clipboard_mode = Mode.System;
Mode Behavior
Internal Items are kept in memory inside the editor instance. Fast and works without permissions, but cannot be shared with other editors or tabs.
System Items are written to the operating system clipboard as a JSON envelope, so you can paste between different editor instances, browser tabs and even browsers.

In System mode:

  • On paste, the envelope is converted back to items by the server (GetLabelTemplate), so the content must come from a compatible editor version (the envelope carries a signature and a version).
  • Units are converted automatically if the source and target labels use different units, and the view rotation of the target is honored.
  • If the user pastes the editor's clipboard content into a regular <input> or <textarea>, only the text of the items (text/barcode data) is inserted instead of the raw JSON.

Paste behavior

  • Pasted items are offset a few pixels at each paste so they do not overlap.
  • Group names are renamed on paste so pasted groups are independent of the originals.
  • On duplex labels, pasting on the other side keeps the original relative position.
  • After Cut, the first paste moves the original items (they are not cloned).

Keyboard Shortcuts

Built in

The editor registers these shortcuts automatically (document level) for the editor the user clicked last:

Shortcut Action
Ctrl/Cmd + C or Ctrl + Insert Copy
Ctrl/Cmd + X or Shift + Delete Cut
Ctrl/Cmd + V or Shift + Insert Paste
Double-click on a TextItem In-place text editing
Esc while editing text Commit the text and leave edit mode

Clipboard shortcuts are ignored when the focus is in an <input>, <textarea>, <select> or editable element, when the user has selected text on the page, when a TextItem is being edited in place, or when Alt is pressed. This lets your own forms keep their normal copy/paste behavior.

Recommended (wire them in your app)

The editor does not bind other shortcuts, so your app decides which keys do what. This is a typical setup:

$(document).on("keydown", function (e) {
    var tag = (e.target.tagName || "").toLowerCase();
    if (tag === "input" || tag === "textarea" || tag === "select") return;

    var sel = editor.current_selection;
    if (sel && sel.is_in_edit_mode) return;          // typing in place

    var mod = e.ctrlKey || e.metaKey;
    var step = e.shiftKey ? 0.1 : 0.01;              // label units

    if (mod && e.key === "z") { editor.undo(); e.preventDefault(); }
    else if (mod && e.key === "y") { editor.redo(); e.preventDefault(); }
    else if (mod && e.key === "a") { editor.selectAll(); e.preventDefault(); }
    else if (mod && e.key === "d") { editor.duplicateSelectedItems(); e.preventDefault(); }
    else if (e.key === "Delete" && sel) { editor.deleteSelectedItems(); }
    else if (sel && e.key === "ArrowLeft")  { editor.moveSelectedItems(-step, 0); e.preventDefault(); }
    else if (sel && e.key === "ArrowRight") { editor.moveSelectedItems(step, 0);  e.preventDefault(); }
    else if (sel && e.key === "ArrowUp")    { editor.moveSelectedItems(0, -step); e.preventDefault(); }
    else if (sel && e.key === "ArrowDown")  { editor.moveSelectedItems(0, step);  e.preventDefault(); }
});

Item Flags and Design-Time Adorners

Every item exposes flags that control how the user can interact with it and that the editor reflects visually:

Flag Effect Adorner icon
locked Cannot be moved, resized or rotated Yes
editable When false the item cannot be selected Yes
visible When false the item is not printed (it is still shown at design time) Yes
resizable Disables resize handles when false Handles are drawn in the frame color
read_only Content (text, code, image source) cannot be changed –
data_field Bound to a data source field Yes
expression Has an expression Yes
comments Has designer comments Yes
print_as_resident_element (barcodes) Printed with the printer's native barcode engine Yes (OK / error variants after server validation)
group_name Member of a group Group frame highlighting

Other visual aids on the design surface:

  • A tooltip on hover with the item's name, type, barcode symbology and index in label.items.
  • A design-time border around text, barcode, image and table items, since they can be invisible on an empty label.
  • Width/height labels on the selection frame.
  • Repeater arrows that show the repeat direction and count.
  • A dashed frame for items outside the label.
Tip

BarcodeItemUtils.getRelatedProperties(symbology) returns the list of properties that apply to a given symbology. Use it to build dynamic property panels that only show the relevant barcode options.

Visual Customization (Theming)

The look of the editor is driven by CSS custom properties (variables), read from the element that the editor creates inside your container (#thermalLabelWebEditor). Because custom properties are inherited, you can define them on your container, body or :root, and you can support light/dark themes with regular CSS.

#editorHost {
    --workspace-background-color: #1e1e1e;
    --label-document-frame-background-color: #ffffff;
    --adorner-handler-background-color: #00aaff;
    --adorner-frame-border-color: #00aaff;
    --grid-color: #3a3a3a;
    --rulers-background-color: #2b2b2b;
    --rulers-text-color: #cccccc;
}
Area Variables
Workspace --workspace-background-color, --workspace-safe-margin (padding around the label, default 100)
Rulers --rulers-background-color, --rulers-corner-background-color, --rulers-selection-background-color, --rulers-text-color
Grid & guides --grid-color, --guidelines-color
Label frame --label-document-frame-border-color, --label-document-frame-corner-radius, --label-document-frame-background-color, --label-document-frame-background-image, --label-document-margin-color
Selection handlers (adorners) --adorner-handler-background-color, --adorner-handler-border-color, --adorner-frame-border-color, --adorner-out-of-label-border-color, --item-design-time-border-color
Marquee --marquee-background-color, --marquee-border-color, --marquee-border-dash-array (e.g. 4,3)
Tooltip --item-tooltip-background-color, --item-tooltip-color, --item-tooltip-border-color, --item-tooltip-index-color
Repeater --repeater-item-color
Duplex --duplex-legends-color, --duplex-flip-color, --duplex-flip-hover-color
Tray (RFID/Literal) --tray-icon-size, --tray-frame-gap, --tray-background-color, --tray-border-color

Notes:

  • The selection handler colors are captured when enableEditor() runs, so define the variables before calling it. Other variables are read each time the surface is redrawn, so changing them and then reloading the label (loadThermalLabel(editor.get_thermal_label, { resetUndoHistory: false, resetActivePage: false })) or changing the zoom applies the new theme.
  • Handlers use a different fill when an item is locked or not resizable, so users can tell them apart.
  • Programmatic switches: show_ruler, show_grid, grid_type, adorner_out_of_label_visible, rfid_tag_image_file_name, literal_image_file_name, label.design_background_image.
  • UI strings used by the editor (such as the duplex legends) are retrieved from the server through GetI18NResourceKey, so you can localize them in your handler/controller.

Events and Hooks

The editor exposes notifications as overridable functions. Assign your own function to the editor instance:

Hook Raised when Notes
newItemCreated() The user finishes drawing an item or an item is pasted
selectionChanged() The selection changes or is cleared Read editor.current_selection
selectionItemPropertyChanged() A property of the selected item changes through its setters this is the item
currentSelectionBeforeDelete() Before deleting the selection Return false to cancel
currentSelectionAfterDelete() After the deletion
undoStateChanged() History changed Update Undo/Redo buttons
viewRotationChanged() The view rotation changes
beforeDuplexDesignDisabled(items) Duplex turned off with items on the back side Return false to cancel
onError(errMsg, className) A server call fails or an item cannot load className identifies the source
editor.selectionChanged = function () {
    var item = editor.current_selection;
    if (item) {
        showPropertiesPanel(item);               // your UI
    } else {
        hidePropertiesPanel();
    }
};

editor.newItemCreated = function () {
    console.log("New item:", editor.current_selection.name);
};

editor.currentSelectionBeforeDelete = function () {
    return confirm("Delete the selected item(s)?");   // false cancels
};

editor.undoStateChanged = function () {
    $("#btnUndo").prop("disabled", !editor.can_undo);
    $("#btnRedo").prop("disabled", !editor.can_redo);
};

editor.onError = function (msg, source) {
    console.error("[" + source + "] " + msg);
};

Saving, Previewing, Exporting and Printing

All of these work on the current label (normalized to the original orientation) unless you pass your own XML template. The methods that return data work synchronously if you do not give a callback, or asynchronously if you do. Prefer callbacks, as synchronous AJAX blocks the browser.

Method Output
save(fileName, url, format) Downloads the template as a file (xml or json)
getXmlTemplate(url, callback) / getJsonTemplate(url, callback) The template as text
getLabelPreview(xml, url, outFormat, dsFormat, ds, callback) Preview in the requested format
getLabelAsHtml(...) HTML preview
getLabelThumbnail(size, xml, url, callback) Thumbnail
getLabelAsImage(xml, url, imageSettings, dpi, dsFormat, ds, callback) PNG/JPEG/SVG/PCX using ImageSettings
getLabelAsPdf(xml, url, pdfMetadata, dpi, dsFormat, ds, callback) PDF using PdfMetadata
getPrinterCommands(xml, url, language, orientation, copies, replicates, dpi, dsFormat, ds, callback) ZPL, EPL, Fingerprint, ESC/POS, PCL or Direct Protocol
getSupportedExpressions(url, callback) Expressions list
print(url, dsFormat, ds) Sends the label to the client printer via TLClientPrint (Windows)
editor.getLabelAsImage(null, null, new Printing.ImageSettings(Printing.ImageFormat.Png), 203, null, null,
    function (base64) {
        $("#preview").attr("src", "data:image/png;base64," + base64);
    });

You can pass a data source (dsFormat: "xml" or "json", ds: the data as text) to bind DataField items.

Touch Devices

The editor is usable on touch screens (tablets and phones):

  • Tap to select; drag to move; handles are enlarged on Android.
  • Double-tap on a TextItem opens the in-place editor.
  • Marquee selection is mouse/pen-only; on touch use the click-to-group workflow.
  • The fabric.CanvasEx layer adds the events mouse:dblclick, touch:doubletap, touch:taphold and touch:longtapend, as well as right-click support, which you can use on the underlying canvas.

Lifecycle and Limitations

  • One editor per page. Theme variables, rulers and the in-place text editor are located by element id (#thermalLabelWebEditor, #tlweCanvas). Creating two editors on the same page is not supported.
  • Dispose it in SPAs. Call editor.dispose() (alias of destroy()) when you remove the editor from the DOM. It removes the document-level clipboard/keyboard listeners, the resize observer, the rulers and the canvases.
  • Server round trips. Text, barcode, image and table items are re-rendered on the server when properties, size or zoom change. A fast, close server gives a smoother experience.
  • Undo memory. Each undo step is a full clone of the label (including embedded base64 images), so very large images increase memory use.
  • Secure context for System clipboard. Asynchronous clipboard access requires HTTPS or localhost; the editor falls back to execCommand otherwise.

Migrating to ThermalLabelWebEditor v16

If you are using an older version of ThermalLabelWebEditor (4.0 to 7.0), follow these steps to migrate to Version 16.0:

  • v16 requires .NET Framework 4.6.1+ (older .NET versions are no longer supported).
  • v16 requires your project to reference these external NuGet packages:
    • SkiaSharp 1.60+
    • System.Text.Encoding.CodePages 4.4.0+
  • The ThermalLabelWebEditor.axd HTTP Handler used in older versions is deprecated. In legacy ASP.NET WebForms you must code a custom HTTP Handler, and in MVC / ASP.NET CORE a custom Controller. Sample code is available in the demo projects shipped with the ThermalLabel SDK installer.
  • In the JavaScript file where you create an instance of Neodynamic.Web.Editor.ThermalLabelEditor, you must set the new thermalLabelWebEditorControllerName property to the URL of the MVC Controller or HTTP Handler mentioned above. For example, for an MVC Controller called ThermalLabelWebEditorHandler with an Action called ProcessRequest:
Neodynamic.Web.Editor.ThermalLabelEditor.thermalLabelWebEditorControllerName = "ThermalLabelWebEditorHandler/ProcessRequest";
  • Any ASP.NET project using the new Web Editor must add a reference to the new Neodynamic.SDK.ThermalLabel.WebPrinting.dll assembly and to the new Neodynamic.SDK.ThermalLabel.dll assembly.
Back to top Copyright © 2003- Neodynamic SRL
http://www.neodynamic.com