Goal: Create RTE (Rich Text Editor) fontstyle & fontcolor plugin for Classic UI. A Similar Touch UI RTE Extension is available here
Note: Please see RTE – Custom Styles Plugin for understanding of Custom Styles plugin requirement.
Download: Source Code | Package Install
Preview
Solution
- Login to CRXDE Lite (http://localhost:4502/crx/de) and create folder /apps/rte/plugins/classic-ui-styles
- Create node /apps/rte/plugins/classic-ui-styles/clientlib of type cq:ClientLibraryFolder and add a String property categories with value cq.widgets
- Create file (nt:file) /apps/rte/plugins/classic-ui-styles/clientlib/js.txt and add following files
#base=./js commands/SCStyle.js toolbar/SCStylesSelectorImpl.js toolbar/SCToolbarBuilder.js fontstyles.js fontcolor.js
- Create file (nt:file) /apps/rte/plugins/classic-ui-styles/clientlib/commands/SCStyle.js and add the following code to create styles command.
CQ.Ext.ns("SC.rte.commands"); /************************************************************************* * RTE Plugins * ___________________ * Styles Command manager for following plugins: * 1. fontstyles * 2. fontcolor * * @author Mohit K. Bansal **************************************************************************/ SC.rte.commands.SCStyle = new Class({ toString: "SCStyle", extend: CUI.rte.commands.Command, addStyle: function(execDef) { var sel = CUI.rte.Selection; var com = CUI.rte.Common; var styleName = execDef.value.val; var styleList = execDef.value.styles; var selection = execDef.selection; var context = execDef.editContext; // handle DOM elements var selectedDom = sel.getSelectedDom(context, selection); var styleableObjects = CUI.rte.plugins.StylesPlugin.STYLEABLE_OBJECTS; if (selectedDom && com.isTag(selectedDom, styleableObjects)) { com.removeAllClasses(selectedDom); com.addClass(selectedDom, styleName); return; } // handle text fragments var nodeList = execDef.nodeList; if (nodeList) { if(selection.startNode.parentNode.tagName == "SPAN") { var newStyles = []; var existingStyles = selection.startNode.parentNode.className.split(" "); for(var i=0; i<existingStyles.length;i++) { var status = true; for(var j=0; j list of span tags? return false; } }); // register command CUI.rte.commands.CommandRegistry.register("_scstyle", SC.rte.commands.SCStyle);
Download: Source Code | Package Install
- Create file (nt:file) /apps/rte/plugins/classic-ui-styles/clientlib/commands/SCStylesSelectorImpl.js and add the following code to create Styles Selector.
CQ.Ext.ns("SC.rte.plugins"); /************************************************************************* * RTE Plugins * ___________________ * Create ACT Style toolbar renderer for following plugins: * 1. fontstyles * 2. fontcolor * * @author Mohit K. Bansal **************************************************************************/ SC.rte.plugins.SCStylesSelectorImpl = new Class({ toString: "SCStyleSelectorImpl", extend: CUI.rte.ui.TbStyleSelector, // Interface implementation ------------------------------------------------------------ addToToolbar: function(toolbar) { var com = CUI.rte.Common; this.toolbar = toolbar; if (com.ua.isIE) { // the regular way doesn't work for IE anymore with Ext 3.1.1, hence working // around var helperDom = document.createElement("span"); helperDom.innerHTML = "<select class=\"x-font-select\">" + this.createStyleOptions() + "</span>"; this.styleSelector = CQ.Ext.get(helperDom.childNodes[0]); } else { this.styleSelector = CQ.Ext.get(CQ.Ext.DomHelper.createDom({ tag: "select", cls: "x-font-select", html: this.createStyleOptions() })); } this.initializeSelector(); var title = this.id.replace("font", ""); toolbar.add( CQ.I18n.getMessage(title.charAt(0).toUpperCase() + title.slice(1)), " ", this.styleSelector.dom); }, createToolbarDef: function() { return [ { "xtype": "panel", "itemId": this.id, "html": "<select class=\"x-font-select\">" + this.createStyleOptions() + "</span>", "listeners": { "afterrender": function() { var item = this.toolbar.items.get(this.id); if (item && item.body) { this.styleSelector = CQ.Ext.get(item.body.dom.childNodes[0]); this.initializeSelector(); } }, "scope": this } }]; }, initializeSelector: function() { this.styleSelector.on('change', function() { var style = this.styleSelector.dom.value; if (style.length > 0) { } this.plugin.execute(this.id); }, this); this.styleSelector.on('focus', function() { this.plugin.editorKernel.isTemporaryBlur = true; }, this); // fix for a Firefox problem that adjusts the combobox' height to the height // of the largest entry this.styleSelector.setHeight(19); }, getSelectorDom: function() { return this.styleSelector.dom; }, getSelectedStyle: function() { var style = this.styleSelector.dom.value; if (style.length > 0) { return style; } return null; }, selectStyles: function(styles, selDef) { var indexToSelect; var styleableObject = selDef.selectedDom; var selectorDom = this.getSelectorDom(); if (styles.length == 0) { indexToSelect = 0; } else if (styles.length > 1) { indexToSelect = -1; } else { if (selDef.isContinuousStyle || styleableObject) { var styleToSelect = styles[0]; var options = selectorDom.options; for (var optIndex = 0; optIndex < options.length; optIndex++) { var optionToCheck = options[optIndex]; if (optionToCheck.value == styleToSelect) { indexToSelect = optIndex; break; } } } else { indexToSelect = -1; } } selectorDom.selectedIndex = indexToSelect; if (styleableObject != null) { selectorDom.disabled = false; } else if (selDef.isSelection) { selectorDom.disabled = false; } else { selectorDom.disabled = true; } } });
Download: Source Code | Package Install
- Create file (nt:file) /apps/rte/plugins/classic-ui-styles/clientlib/commands/SCToolbarBuilder.js and add the following code to invoke custom toolbar.
/************************************************************************* * RTE Plugins * ___________________ * Extend toolbar builder to register different commands * * @author Mohit K. Bansal **************************************************************************/ (function() { CQ.Ext.override(CUI.rte.ui.ext.ExtToolbarBuilder, { createSCStyleSelector: function(id, plugin, tooltip, styles) { return new SC.rte.plugins.SCStylesSelectorImpl(id, plugin, false, tooltip, false, undefined, styles); } }); }());
Download: Source Code | Package Install
- Create file (nt:file) /apps/rte/plugins/classic-ui-styles/clientlib/fontstyles.js and add the following code to create Font styles plugin.
CQ.Ext.ns("SC.rte.plugins"); /************************************************************************* * RTE Plugins * ___________________ * Font Style Plugin * * @author Mohit K. Bansal **************************************************************************/ SC.rte.plugins.Fontstyles = new Class({ toString: "Fontstyles", extend: CUI.rte.plugins.Plugin, /** * @private */ cachedStyles: null, /** * @private */ stylesUI: null, getFeatures: function() { return [ "fontstyles" ]; }, getStyles: function() { var com = CUI.rte.Common; if (!this.cachedStyles) { this.cachedStyles = this.config.styles; if (this.cachedStyles) { // take styles from config com.removeJcrData(this.cachedStyles); this.cachedStyles = com.toArray(this.cachedStyles, "cssName", "text"); } else { this.cachedStyles = [ ]; } } return this.cachedStyles; }, setStyles: function(styles) { this.cachedStyles = styles; }, hasStylesConfigured: function() { return !!this.config.styles; }, initializeUI: function(tbGenerator) { var plg = CUI.rte.plugins; var ui = CUI.rte.ui; if (this.isFeatureEnabled("fontstyles")) { this.stylesUI = tbGenerator.createSCStyleSelector("fontstyles", this, null, this.getStyles()); tbGenerator.addElement("fontstyles", plg.Plugin.SORT_PARAFORMAT, this.stylesUI, 500); } }, notifyPluginConfig: function(pluginConfig) { pluginConfig = pluginConfig || { }; CUI.rte.Utils.applyDefaults(pluginConfig, { }); this.config = pluginConfig; }, execute: function(cmdId, styleDef) { if (!this.stylesUI) { return; } var cmd = null; var value = null; switch (cmdId.toLowerCase()) { case "fontstyles": cmd = "applyscstyle"; value = (styleDef != null ? styleDef : this.stylesUI.getSelectedStyle()); break; } if (cmd) { var confValue = { val: value, styles: this.cachedStyles }; this.editorKernel.relayCmd(cmd, confValue); } }, updateState: function(selDef) { if (!this.stylesUI) { return; } var com = CUI.rte.Common; var styles = selDef.styles; var actualStyles = [ ]; var s; var styleableObject = selDef.selectedDom; if (styleableObject) { if (!CUI.rte.Common.isTag(selDef.selectedDom, CUI.rte.plugins.StylesPlugin.STYLEABLE_OBJECTS)) { styleableObject = null; } } var stylesDef = this.getStyles(); var styleCnt = stylesDef.length; if (styleableObject) { for (s = 0; s < styleCnt; s++) { var styleName = stylesDef[s].cssName; if (com.hasCSS(styleableObject, styleName)) { actualStyles.push({ "className": styleName }); } } } else { var checkCnt = styles.length; for (var c = 0; c < checkCnt; c++) { var styleToProcess = styles[c]; var currentStyles = styleToProcess.className.split(" "); for(var j=0; j<currentStyles.length; j++) { for (s = 0; s < styleCnt; s++) { if (stylesDef[s].cssName == currentStyles[j]) { actualStyles.push(currentStyles[j]); break; } } } } } this.stylesUI.selectStyles(actualStyles, selDef); } }); // register plugin CUI.rte.plugins.PluginRegistry.register("fontstyles", SC.rte.plugins.Fontstyles);
Download: Source Code | Package Install
- Create file (nt:file) /apps/rte/plugins/classic-ui-styles/clientlib/fontcolor.js and add the following code to create Font color plugin.
CQ.Ext.ns("SC.rte.plugins"); /************************************************************************* * * RTE Plugins * ___________________ * * Font Color Plugin * * @author Mohit K. Bansal * * **************************************************************************/ SC.rte.plugins.Fontcolor = new Class({ toString: "Fontcolor", extend: CUI.rte.plugins.Plugin, /** * @private */ cachedStyles: null, /** * @private */ stylesUI: null, getFeatures: function() { return [ "fontcolor" ]; }, getStyles: function() { var com = CUI.rte.Common; if (!this.cachedStyles) { this.cachedStyles = this.config.styles; if (this.cachedStyles) { // take styles from config com.removeJcrData(this.cachedStyles); this.cachedStyles = com.toArray(this.cachedStyles, "cssName", "text"); } else { this.cachedStyles = [ ]; } } return this.cachedStyles; }, setStyles: function(styles) { this.cachedStyles = styles; }, hasStylesConfigured: function() { return !!this.config.styles; }, initializeUI: function(tbGenerator) { var plg = CUI.rte.plugins; var ui = CUI.rte.ui; if (this.isFeatureEnabled("fontcolor")) { this.stylesUI = tbGenerator.createSCStyleSelector("fontcolor", this, null, this.getStyles()); tbGenerator.addElement("fontcolor", plg.Plugin.SORT_PARAFORMAT, this.stylesUI, 800); } }, notifyPluginConfig: function(pluginConfig) { pluginConfig = pluginConfig || { }; CUI.rte.Utils.applyDefaults(pluginConfig, { }); this.config = pluginConfig; }, execute: function(cmdId, styleDef) { if (!this.stylesUI) { return; } var cmd = null; var value = null; switch (cmdId.toLowerCase()) { case "fontcolor": cmd = "applyscstyle"; value = (styleDef != null ? styleDef : this.stylesUI.getSelectedStyle()); break; } if (cmd) { var confValue = { val: value, styles: this.cachedStyles }; this.editorKernel.relayCmd(cmd, confValue); } }, updateState: function(selDef) { if (!this.stylesUI) { return; } var com = CUI.rte.Common; var styles = selDef.styles; var actualStyles = [ ]; var s; var styleableObject = selDef.selectedDom; if (styleableObject) { if (!CUI.rte.Common.isTag(selDef.selectedDom, CUI.rte.plugins.StylesPlugin.STYLEABLE_OBJECTS)) { styleableObject = null; } } var stylesDef = this.getStyles(); var styleCnt = stylesDef.length; if (styleableObject) { for (s = 0; s < styleCnt; s++) { var styleName = stylesDef[s].cssName; if (com.hasCSS(styleableObject, styleName)) { actualStyles.push({ "className": styleName }); } } } else { var checkCnt = styles.length; for (var c = 0; c < checkCnt; c++) { var styleToProcess = styles[c]; var currentStyles = styleToProcess.className.split(" "); for(var j=0; j<currentStyles.length; j++) { for (s = 0; s < styleCnt; s++) { if (stylesDef[s].cssName == currentStyles[j]) { actualStyles.push(currentStyles[j]); break; } } } } } this.stylesUI.selectStyles(actualStyles, selDef); } }); // register plugin CUI.rte.plugins.PluginRegistry.register("fontcolor", SC.rte.plugins.Fontcolor);
Download: Source Code | Package Install
Mohit, that was a spectacular work from your side. You saved a lot of time. Kindly keep posting such posts. I haven’t checked the packages posted here, but in the “SCStyle.js” you have missed some lines of code i guess. Kindly update it so that it might be helpful for all. I’ve corrected it myself by using your touch UI blog.
Thank you Rajesh. I will check code once again.
This is great work..
Can somebody please tell me how to use this plugin in the OOTB text component ?
You can use this plugin in rich text xtype only