Anyone who has spent time in Microsoft Word knows the magic of the Format Painter: a feature that lets you copy formatting from one piece of text and apply it to another with a single click. Although Format Painter functionality exists in common web editors, developers creating custom document applications require more sophisticated formatting controls. The TX Text Control rich text editor enables developers to implement custom formatting programmatically. This article demonstrates how to build a Format Painter feature using the TX Text Control Document Editor, implementing format detection, copy and paste operations, and custom style handling through the JavaScript API. Understanding Uniform Formatting Detection Building a reliable Format Painter feature starts with solving one key challenge: how do you know if the selected text has consistent formatting? When users select text with mixed fonts, colors, or styles, copying that formatting creates inconsistent results. TX Text Control's isCommonSelectionValueSelected Method solves this by checking if formatting is uniform across any selection. It returns true only when all selected text shares the same formatting attributes, preventing formatting errors before they happen. Getting Started Learn how to create the TX Text Control rich text editor with ASP.NET Core using this guide: Getting Started: Document Editor with ASP.NET Core The ASP.NET Core application with TX Text Control provides rich text editing with comprehensive functionality. The JavaScript API enables further customization and integration with specialized features, such as the Format Painter. For demonstration purposes, this implementation utilizes dedicated buttons to showcase the Format Painter functionality. The complete source code for this implementation is available on the TX Text Control GitHub repository. The project includes all the code examples, along with the complete ASP.NET Core setup and JavaScript integration. Implementing Asynchronous Format Detection Since TX Text Control uses callback-based APIs for asynchronous operations, the implementation converts these to Promise wrappers for cleaner async/await syntax. The isCommonValueSelectedAsync function specifically handles format validation using the isCommonSelectionValueSelected Method. The implementation works as follows: // Global variables let copiedFormat = null; let styleCounter = 1; let customStyles = {}; // Promise wrappers for TX Text Control API const get = (method) => new Promise((resolve, reject) => TXTextControl.selection[method](v => resolve(v), e => reject(e)) ); const set = (method, val) => new Promise((resolve, reject) => TXTextControl.selection[method](val, () => resolve(), e => reject(e)) ); const getLength = () => new Promise((resolve, reject) => TXTextControl.selection.getLength(v => resolve(v), e => reject(e)) ); const selectWord = () => new Promise((resolve, reject) => TXTextControl.selectWord(() => resolve(), e => reject(e)) ); // Utility function to check if selected text has uniform formatting function isCommonValueSelectedAsync(selection, attr) { return new Promise((resolve, reject) => { selection.isCommonSelectionValueSelected( attr, (result) => { resolve(result); // true/false }, reject ); }); } Copying Formatting From Text Selection The event handler shown below validates the text selection and captures its formatting attributes only if the text selection has uniform formatting: // Main event handler - runs when TX Text Control is fully loaded TXTextControl.addEventListener("textControlLoaded", () => { // Get references to all UI elements const copyFormatButton = document.getElementById("copyFormatButton"); const pasteFormatButton = document.getElementById("pasteFormatButton"); const createStyleButton = document.getElementById("createStyleButton"); const customStylesDropdown = document.getElementById("customStylesDropdown"); const applyStyleButton = document.getElementById("applyStyleButton"); // Copy formatting from selected text copyFormatButton.addEventListener("click", async () => { // Validate that selection has uniform formatting const isUniform = await isCommonValueSelectedAsync( TXTextControl.selection, TXTextControl.Selection.Attribute.All ); if (isUniform) { // Capture all formatting attributes from current selection copiedFormat = { baseline: await get("getBaseline"), bold: await get("getBold"), fontName: await get("getFontName"), fontSize: await get("getFontSize"), foreColor: await get("getForeColor"), italic: await get("getItalic"), strikeout: await get("getStrikeout"), textBackColor: await get("getTextBackColor"), underline: await get("getUnderline") }; pasteFormatButton.disabled = false; console.log("Format copied successfully."); } else { alert("Please select text with uniform formatting to copy the format."); } }); Applying Formatting to Text Selections The paste handler applies the previously copied formatting to the target selection with all the captured attributes, as shown in this code: // Apply previously copied formatting to current selection pasteFormatButton.addEventListener("click", async () => { if (!copiedFormat) { pasteFormatButton.disabled = true; return; } try { // Apply all captured formatting attributes to current selection await set("setBaseline", copiedFormat.baseline); await set("setBold", copiedFormat.bold); await set("setFontName", copiedFormat.fontName); await set("setFontSize", copiedFormat.fontSize); await set("setForeColor", copiedFormat.foreColor); await set("setItalic", copiedFormat.italic); await set("setStrikeout", copiedFormat.strikeout); await set("setTextBackColor", copiedFormat.textBackColor); await set("setUnderline", copiedFormat.underline); console.log("Format pasted successfully."); } catch (err) { alert("Paste failed: " + err.message); console.error(err); } }); Creating Custom Styles and Adding Them to TX Text Control's Style Collection This section shows how to create reusable styles that become part of TX Text Control's style collection. Unlike the copy and paste formatting covered earlier, creating custom styles defines inline or paragraph formatting rules that can be reapplied across the document or in future editing sessions. The created custom styles are added to the Document Editor's "Styles" dropdown in the ribbon. TX Text Control supports both inline and paragraph styles, which serve different formatting purposes: Paragraph styles apply formatting to entire paragraphs. Inline styles apply character-level formatting to selected text portions within paragraphs. This implementation uses inline styles because the format painter feature captures character-level formatting properties. Formatting is applied to selected text portions rather than entire paragraphs. The following code shows how to create styles and add them to TX Text Control's style collection: // Create a reusable style from selected text formatting createStyleButton.addEventListener("click", async () => { try { // Validate uniform formatting before creating style const isUniform = await isCommonValueSelectedAsync( TXTextControl.selection, TXTextControl.Selection.Attribute.All ); if (!isUniform) { alert("Please select text with uniform formatting to create a style."); return; } // Capture current selection's formatting const currentFormat = { baseline: await get("getBaseline"), bold: await get("getBold"), fontName: await get("getFontName"), fontSize: await get("getFontSize"), foreColor: await get("getForeColor"), italic: await get("getItalic"), strikeout: await get("getStrikeout"), textBackColor: await get("getTextBackColor"), underline: await get("getUnderline") }; // Generate unique style name and create the style const styleName = "CustomStyle" + styleCounter++; // Add the created style in TX Text Control's inline styles collection const addedStyle = await addStyle(styleName, currentFormat, "inline"); if (addedStyle) { // Store for dropdown usage and add to UI customStyles[styleName] = { ...currentFormat }; addStyleToDropdown(styleName); } alert(`Custom style '${styleName}' created successfully!`); } catch (err) { alert("Style creation failed: " + err.message); console.error(err); } }); Note: TX Text Control's FormattingStyle.setFontSize Method requires font sizes in twips (1/20th of a point). The ptToTwips helper function converts point values to twips, ensuring programmatically created styles display at the correct font size. // Convert font size from points to twips (required by TX Text Control) function ptToTwips(pt) { return pt * 20; } // Function to create a new inline style in TX Text Control's style collection function addStyle(styleName, format) { return new Promise((resolve, reject) => { TXTextControl.inlineStyles.add( styleName, (style) => { // Apply formatting values to the new style style.setFontName(format.fontName); style.setFontSize(ptToTwips(format.fontSize)); // Convert to twips style.setForeColor(format.foreColor); style.setBold(format.bold); style.setItalic(format.italic); style.setUnderline(format.underline); style.setStrikeout(format.strikeout); style.setBaseline(format.baseline); style.setTextBackColor(format.textBackColor); resolve(style); }, (error) => reject(error) ); }); } Conclusion This article demonstrates how to build a professional Format Painter feature for ASP.NET applications using TX Text Control's JavaScript API. The implementation uses the isCommonSelectionValueSelected Method to ensure uniform formatting detection. It also includes complete functionality for copying and pasting formats, creating custom styles, and adding them to the TX Text Control style collection using inline styles. This approach provides developers with a practical foundation for implementing sophisticated text formatting in web-based applications.