Quantcast
Channel: Experiencing Adobe Experience Manager (AEM, CQ)
Viewing all articles
Browse latest Browse all 525

AEM 63 - Touch UI RTE (Rich Text Editor) Color Picker Plugin for InPlace and Dialog Editing

$
0
0

Goal


Touch UI Color Picker Plugin for RTE (Rich Text Editor) InPlace and Dialog Edit  /libs/cq/gui/components/authoring/dialog/richtext

For a similar extension on 62 check this post, 61 check this post; to add General group components on We.Retail pages check this post

For demo purposes, dialog of foundation text component was modified to add the color picker configuration - /libs/foundation/components/text/cq:dialog/content/items/text/items/column/items/text/rtePlugins

Demo | Package Install | Github


Plugin Configuration - InPlace Editing




Plugin Configuration - Dialog









Picker with Free Style Palette - InPlace Editing Maximized




Picker with Free Style Palette - Inline Dialog




Picker with Free Style Palette - Full Screen Dialog



Color Applied






Solution


1) Login to CRXDE Lite, add nt:folder /apps/eaem-touchui-dialog-rte-color-picker

2) To show the color picker in a dialog create /apps/eaem-touchui-dialog-rte-color-picker/color-picker-popover of type sling:Folder and /apps/eaem-touchui-dialog-rte-color-picker/color-picker-popover/cq:dialog of type nt:unstructured




                             
3) Create clientlib (cq:ClientLibraryFolder) /apps/eaem-touchui-dialog-rte-color-picker/clientlib set property categories to cq.authoring.dialog.all and dependencies to [underscore]

4) Create file (nt:file) /apps/eaem-touchui-dialog-rte-color-picker/clientlib/js.txt, add the following content

                   color-picker.js

5) Create file (nt:file) /apps/eaem-touchui-dialog-rte-color-picker/clientlib/color-picker.js, add the following code

(function($, CUI){
var GROUP = "experience-aem",
COLOR_PICKER_FEATURE = "colorPicker",
TCP_DIALOG = "eaemTouchUIColorPickerDialog",
PICKER_NAME_IN_POPOVER = "color",
REQUESTER = "requester",
PICKER_URL = "/apps/eaem-touchui-dialog-rte-color-picker/color-picker-popover/cq:dialog.html";

addPluginToDefaultUISettings();

addDialogTemplate();

var EAEMColorPickerDialog = new Class({
extend: CUI.rte.ui.cui.AbstractDialog,

toString: "EAEMColorPickerDialog",

initialize: function(config) {
this.exec = config.execute;
},

getDataType: function() {
return TCP_DIALOG;
}
});

var TouchUIColorPickerPlugin = new Class({
toString: "TouchUIColorPickerPlugin",

extend: CUI.rte.plugins.Plugin,

pickerUI: null,

getFeatures: function() {
return [ COLOR_PICKER_FEATURE ];
},

initializeUI: function(tbGenerator) {
var plg = CUI.rte.plugins;

if (!this.isFeatureEnabled(COLOR_PICKER_FEATURE)) {
return;
}

this.pickerUI = tbGenerator.createElement(COLOR_PICKER_FEATURE, this, false, { title: "Color Picker" });
tbGenerator.addElement(GROUP, plg.Plugin.SORT_FORMAT, this.pickerUI, 10);

var groupFeature = GROUP + "#" + COLOR_PICKER_FEATURE;
tbGenerator.registerIcon(groupFeature, "textColor");
},

execute: function (id, value, envOptions) {
if(!isValidSelection()){
return;
}

var context = envOptions.editContext,
selection = CUI.rte.Selection.createProcessingSelection(context),
ek = this.editorKernel,
startNode = selection.startNode;

if ( (selection.startOffset === startNode.length) && (startNode != selection.endNode)) {
startNode = startNode.nextSibling;
}

var tag = CUI.rte.Common.getTagInPath(context, startNode, "span"), plugin = this, dialog,
color = $(tag).css("color"),
dm = ek.getDialogManager(),
$container = CUI.rte.UIUtils.getUIContainer($(context.root)),
propConfig = {
'parameters': {
'command': this.pluginId + '#' + COLOR_PICKER_FEATURE
}
};

if(this.eaemColorPickerDialog){
dialog = this.eaemColorPickerDialog;
}else{
dialog = new EAEMColorPickerDialog();

dialog.attach(propConfig, $container, this.editorKernel);

dialog.$dialog.css("-webkit-transform", "scale(0.8)").css("-webkit-transform-origin", "0 0")
.css("-moz-transform", "scale(0.8)").css("-moz-transform-origin", "0px 0px");

dialog.$dialog.find("iframe").attr("src", getPickerIFrameUrl(color));

this.eaemColorPickerDialog = dialog;
}

dm.show(dialog);

registerReceiveDataListener(receiveMessage);

function isValidSelection(){
var winSel = window.getSelection();
return winSel && winSel.rangeCount == 1 && winSel.getRangeAt(0).toString().length > 0;
}

function getPickerIFrameUrl(color){
var url = PICKER_URL + "?" + REQUESTER + "=" + GROUP;

if(!_.isEmpty(color)){
url = url + "&" + PICKER_NAME_IN_POPOVER + "=" + color;
}

return url;
}

function removeReceiveDataListener(handler) {
if (window.removeEventListener) {
window.removeEventListener("message", handler);
} else if (window.detachEvent) {
window.detachEvent("onmessage", handler);
}
}

function registerReceiveDataListener(handler) {
if (window.addEventListener) {
window.addEventListener("message", handler, false);
} else if (window.attachEvent) {
window.attachEvent("onmessage", handler);
}
}

function receiveMessage(event) {
if (_.isEmpty(event.data)) {
return;
}

var message = JSON.parse(event.data),
action;

if (!message || message.sender !== GROUP) {
return;
}

action = message.action;

if (action === "submit") {
if (!_.isEmpty(message.data)) {
ek.relayCmd(id, message.data);
}
}else if(action === "remove"){
ek.relayCmd(id);
}else if(action === "cancel"){
plugin.eaemColorPickerDialog = null;
}

dialog.hide();

removeReceiveDataListener(receiveMessage);
}
},

//to mark the icon selected/deselected
updateState: function(selDef) {
var hasUC = this.editorKernel.queryState(COLOR_PICKER_FEATURE, selDef);

if (this.pickerUI != null) {
this.pickerUI.setSelected(hasUC);
}
}
});

CUI.rte.plugins.PluginRegistry.register(GROUP,TouchUIColorPickerPlugin);

var TouchUIColorPickerCmd = new Class({
toString: "TouchUIColorPickerCmd",

extend: CUI.rte.commands.Command,

isCommand: function(cmdStr) {
return (cmdStr.toLowerCase() == COLOR_PICKER_FEATURE);
},

getProcessingOptions: function() {
var cmd = CUI.rte.commands.Command;
return cmd.PO_SELECTION | cmd.PO_BOOKMARK | cmd.PO_NODELIST;
},

_getTagObject: function(color) {
return {
"tag": "span",
"attributes": {
"style" : "color: " + color
}
};
},

execute: function (execDef) {
var color = execDef.value ? execDef.value[PICKER_NAME_IN_POPOVER] : undefined,
selection = execDef.selection,
nodeList = execDef.nodeList;

if (!selection || !nodeList) {
return;
}

var common = CUI.rte.Common,
context = execDef.editContext,
tagObj = this._getTagObject(color);

//if no color value passed, assume delete and remove color
if(_.isEmpty(color)){
nodeList.removeNodesByTag(execDef.editContext, tagObj.tag, undefined, true);
return;
}

var tags = common.getTagInPath(context, selection.startNode, tagObj.tag);

//remove existing color before adding new color
if (tags != null) {
nodeList.removeNodesByTag(execDef.editContext, tagObj.tag, undefined, true);
}

nodeList.surround(execDef.editContext, tagObj.tag, tagObj.attributes);
}
});

CUI.rte.commands.CommandRegistry.register(COLOR_PICKER_FEATURE, TouchUIColorPickerCmd);

function addPluginToDefaultUISettings(){
var toolbar = CUI.rte.ui.cui.DEFAULT_UI_SETTINGS.inline.toolbar;
toolbar.splice(3, 0, GROUP + "#" + COLOR_PICKER_FEATURE);

toolbar = CUI.rte.ui.cui.DEFAULT_UI_SETTINGS.fullscreen.toolbar;
toolbar.splice(3, 0, GROUP + "#" + COLOR_PICKER_FEATURE);
}

function addDialogTemplate(){
var url = PICKER_URL + "?" + REQUESTER + "=" + GROUP;

var html = "<iframe width='410px' height='450px' frameBorder='0' src='" + url + "'></iframe>";

if(_.isUndefined(CUI.rte.Templates)){
CUI.rte.Templates = {};
}

if(_.isUndefined(CUI.rte.templates)){
CUI.rte.templates = {};
}

CUI.rte.templates['dlg-' + TCP_DIALOG] = CUI.rte.Templates['dlg-' + TCP_DIALOG] = Handlebars.compile(html);

//Coral.templates.RichTextEditor['dlg_' + TCP_DIALOG] = Handlebars.compile(html);
}
}(jQuery, window.CUI,jQuery(document)));

(function($, $document){
var SENDER = "experience-aem",
REQUESTER = "requester",
COLOR = "color",
ADD_COLOR_BUT = "#EAEM_CP_ADD_COLOR",
REMOVE_COLOR_BUT = "#EAEM_CP_REMOVE_COLOR";

if(queryParameters()[REQUESTER] !== SENDER ){
return;
}

$(function(){
_.defer(stylePopoverIframe);
});

function queryParameters() {
var result = {}, param,
params = document.location.search.split(/\?|\&/);

params.forEach( function(it) {
if (_.isEmpty(it)) {
return;
}

param = it.split("=");
result[param[0]] = param[1];
});

return result;
}

function stylePopoverIframe(){
var queryParams = queryParameters(),
$dialog = $(".coral-Dialog");

if(_.isEmpty($dialog)){
return;
}

$dialog.css("overflow", "hidden");

$dialog[0].open = true;

var $addColor = $dialog.find(ADD_COLOR_BUT),
$removeColor = $dialog.find(REMOVE_COLOR_BUT),
$colorPicker = $document.find(".coral-ColorPicker"),
pickerInstance = $colorPicker.data("colorpicker");

if(!_.isEmpty(queryParameters()[COLOR])){
pickerInstance._setColor(decodeURIComponent(queryParams[COLOR]));
}

adjustHeader($dialog);

$dialog.find(".coral-Dialog-wrapper").css("margin","0").find(".coral-Dialog-content").css("padding","0");

$colorPicker.closest(".coral-Form-fieldwrapper").css("margin-bottom", "285px");

$(ADD_COLOR_BUT).css("margin-left", "150px");

$addColor.click(sendDataMessage);

$removeColor.click(sendRemoveMessage);
}

function adjustHeader($dialog){
var $header = $dialog.css("background-color", "#fff").find(".coral-Dialog-header");

$header.find(".cq-dialog-submit").remove();

$header.find(".cq-dialog-cancel").click(function(event){
event.preventDefault();

$dialog.remove();

sendCancelMessage();
});
}

function sendCancelMessage(){
var message = {
sender: SENDER,
action: "cancel"
};

parent.postMessage(JSON.stringify(message), "*");
}

function sendRemoveMessage(){
var message = {
sender: SENDER,
action: "remove"
};

parent.postMessage(JSON.stringify(message), "*");
}

function sendDataMessage(){
var message = {
sender: SENDER,
action: "submit",
data: {}
}, $dialog, color;

$dialog = $(".cq-dialog");

color = $dialog.find("[name='./" + COLOR + "']").val();

if(color && color.indexOf("rgb") >= 0){
color = CUI.util.color.RGBAToHex(color);
}

message.data[COLOR] = color;

parent.postMessage(JSON.stringify(message), "*");
}
})(jQuery, jQuery(document));

Viewing all articles
Browse latest Browse all 525

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>