Goal
Add a Color Picker to Rich Text Editor of Classic UI. A Touch UI RTE plugin is available here
Demo | Package Install | [ No color field - Demo | Package Install ]
Demo shows dialog of foundation text component (/libs/foundation/components/text/dialog/items/tab1/items/text/rtePlugins) modified to add the color picker config. This is just for demonstration only (on Geometrixx pages), ideally the foundation components should never be altered...
Please leave a comment if you find bug / fix
Bug Fixes
Color palette shows up cropped on Firefox (bug screenshot, fix screenshot), reapplying color on single "p" block throws error - Tested on AEM 61 - Package Install
Picker with Default Colors
Configuration
Button
Picker
Custom Colors
Configuration
Picker
Solution
1) Login to CRXDE Lite, create folder (nt:folder) /apps/rte-color-picker
2) Create clientlib (type cq:ClientLibraryFolder) /apps/rte-color-picker/clientlib and set a property categories of String type to cq.widgets
3) Create file ( type nt:file ) /apps/rte-color-picker/clientlib/js.txt, add the following
color-picker.js
4) Create file (type nt:file) /apps/rte-color-picker/clientlib/color-picker.js, add the following code
CQ.Ext.ns("ExperienceAEM"); ExperienceAEM.ColorPicker = { ADD_COLOR_CMD : "addcolor" }; ExperienceAEM.ColorPicker.Plugin = new Class({ toString: "ColorPickerPlugin", extend: CUI.rte.plugins.Plugin, P: ExperienceAEM.ColorPicker, addPickerUI: null, getFeatures: function() { return [ this.P.ADD_COLOR_CMD ]; }, initializeUI: function(tbGenerator) { var plg = CUI.rte.plugins; if (this.isFeatureEnabled(this.P.ADD_COLOR_CMD)) { this.addPickerUI = tbGenerator.createElement(this.P.ADD_COLOR_CMD, this, true, "Add Color"); tbGenerator.addElement("format", plg.Plugin.SORT_FORMAT,this.addPickerUI,1000); } }, execute: function(cmd, value, env) { if (cmd == this.P.ADD_COLOR_CMD) { this.showDialog(env.editContext); } }, showDialog: function(context) { var editorKernel = this.editorKernel, dm = editorKernel.getDialogManager(); var config = this.config; var colorField = new CQ.form.ColorField({ fieldLabel: "Hex Value", showHexValue: true }); var colorPalette = { fieldLabel: "Select", labelStyle: "padding-top:15px", style: "padding-top:15px", xtype: "colorpalette", listeners: { select: function(t, sColor){ colorField.setValue(sColor); } } }; if(config){ if(config.defaultColor){ colorPalette.value = config.defaultColor; } if(config.colors && config.colors.length > 0){ colorPalette.colors = config.colors; } } var dialogConfig = { "jcr:primaryType": "cq:Dialog", title: "Color Picker", modal: true, width: 400, height: 250, items: [ { xtype: "panel", layout: "form", padding: "20px 0 0 10px", items: [ colorField, colorPalette ] }], ok: function() { this.close(); var sColor = colorField.getValue(); if(sColor){ editorKernel.relayCmd(ExperienceAEM.ColorPicker.ADD_COLOR_CMD, sColor ); } } }; var removeBtn = new CQ.Ext.Button( { text: "Remove Applied Color", width: 150, tooltip: 'Remove applied color and close dialog', handler: function(){ this.close(); editorKernel.relayCmd(ExperienceAEM.ColorPicker.ADD_COLOR_CMD); } }); dialogConfig.buttons = [ removeBtn, CQ.Dialog.OK, CQ.Dialog.CANCEL ]; dm.show(CQ.WCM.getDialog(dialogConfig)); }, notifyPluginConfig: function(pluginConfig) { pluginConfig = pluginConfig || { }; CUI.rte.Utils.applyDefaults(pluginConfig, { "tooltips": { "addcolor": { "title": "Add Color", "text": "Add Color" } } }); this.config = pluginConfig; }, updateState: function(selDef) { if(this.addPickerUI){ this.addPickerUI.setSelected(false); } } }); CUI.rte.plugins.PluginRegistry.register("colorpicker", ExperienceAEM.ColorPicker.Plugin); ExperienceAEM.ColorPicker.Cmd = new Class({ toString: "ColorPicker", extend: CUI.rte.commands.Command, P: ExperienceAEM.ColorPicker, isCommand: function(cmdStr) { return (cmdStr == this.P.ADD_COLOR_CMD); }, getProcessingOptions: function() { var cmd = CUI.rte.commands.Command; return cmd.PO_SELECTION | cmd.PO_NODELIST; }, addColor: function(execDef){ var nodeList = execDef.nodeList, selection = execDef.selection; if(!nodeList || !selection){ return; } try{ nodeList.removeNodesByTag(execDef.editContext, "span", undefined, true); if(!execDef.value){ return; } nodeList.surround(execDef.editContext, "span", { style: "color:#" + execDef.value } ); }catch(err){ console.log("Error applying or removing color - " + err); } }, execute: function(execDef) { if(execDef.command == this.P.ADD_COLOR_CMD){ this.addColor(execDef); } } }); CUI.rte.commands.CommandRegistry.register("colorpicker", ExperienceAEM.ColorPicker.Cmd);
5) Add necessary CSS. Create folder (nt:folder) /apps/rte-color-picker/clientlib/themes
6) Create clientlib (type cq:ClientLibraryFolder) /apps/rte-color-picker/clientlib/themes/default and set a property categories of String type to cq.widgets
7) Create file (nt:file) /apps/rte-color-picker/clientlib/themes/default/css.txt, add the following
css/color-picker.css
8) Create folder (nt:folder) /apps/rte-color-picker/clientlib/themes/default/css and add the icon addcolor.png
9) Create file (nt:file) /apps/rte-color-picker/clientlib/themes/default/css/color-picker.css, add the following code. RTE looks for css classes x-edit-addcolor (for the plugin toolbar button addcolor)
#CQ .x-html-editor-tb .x-edit-addcolor { background: url(addcolor.png) center no-repeat; }
10) Add any text component with RichText editor and in the rtePlugins path of dialog add colorpicker node to enable color picker plugin
I want to create custom video plugin. Here you are using xtype as colorpalette. What xtype needs to be used if we want develop video plugin? Could you please guide me to create video plugin in RTE?
ReplyDeletehello ezhil, not aware of video plugins xtypes. 'guess you can develop one that simply outputs html5 video tag, so in a dialog you select video and play it using the tag...
DeleteHello.. I'm wondering if you could look at this related SO question.... http://stackoverflow.com/questions/28866912/color-picker-for-aem-component Thanks again for your awesome blog- tremendous resource!
ReplyDeleteHi ,
ReplyDeleteDo we have a rich text plugin or xtype for font size and family.Please share references.
Hello,
ReplyDeleteTo make it work I need to add the following statement:
nodeList.commonAncestor = nodeList.nodes[0].dom.parentElement;
after the line 154 above.
This is because commonAncestor reference in nodeList is not updates correctly in function removeNodesByTag
causing exception in line 160.
Do you have the same issue?
Thanks in advance.
Regards,
Ana.
Ana, i think you are hitting the issue "reapplying color on single p block" - check package install the bugfixes section above
DeleteThank you for the answer.
DeleteI didn't see the pacakge bugfixes.
Hello,
ReplyDeleteThank you for sharing your code!
I had a task to wrap selected text along with its parent tag (no matter how many tags there) with some div. It was easier for me to use jQuery so if anyone interested, sharing my code here:
addColor: function(execDef) {
var nodeList = execDef.nodeList,
selection = execDef.selection,
nodes = nodeList.nodes, // selected tags
wrapperEl = "here goes your HTML with class what you want",
selectedTags = [],
$ = jQuery;
if (!nodeList || !selection) {
return;
}
try {
for (var i = 0; i < nodes.length; i++) {
if (nodes.length > 1) {
selectedTags.push(nodes[i].dom); // prepare array to wrap merged items into one div with background
} else {
selectedTags.push(nodes[i].dom.parentElement); // correct array if only 1 tag selected
}
};
if(!execDef.value){
$(selectedTags).unwrap(); // removing wrapper with background (deletes it from dom)
return;
}
$(selectedTags).wrapAll(wrapperEl).parent().css({"background-color": "#" + execDef.value });
} catch(err) {
console.log("Error applying or removing color - " + err);
}
},
Hope it helps somebody :)
Regards,
Natalie
Hello,
ReplyDeleteI had try to color picker to AEM 6.1.
But I found some issue with IE.
Can not changed the color. And source is different like below.
//IE
<P>Test<span style="color: rgb(255, 0, 0);"></span></P>
//Chrome
<P><span style="color: #FF0000;">Test</span></P>
Do you have the same issue?
And Do you have the solution?
Thanks
This comment has been removed by the author.
ReplyDeleteHi Sreekanth,
ReplyDeleteThanks for the plugin its working great...:)
The hex value is not retained in the color picker though the changed color is displayed correctly with the component (e.g. if you change the text color from #ffffff to #fed141, hit ok and then open the color picker again, the hex value displays #ffffff even though the color displayed is #fed141)
ReplyDeleteHow i can fix it?
This comment has been removed by the author.
ReplyDelete