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

AEM 6420 - Content Fragment Editor add Font size, Color, Background color RTE Plugin

$
0
0

Goal


Add an RTE plugin eaemTextFont to apply size, color, background color to the text in content fragment editor

Demo | Package Install | Github


Minimized



Toolbar Plugin



Maximized



Saved in CRX



Solution


1) Login to CRXDE Lite, create folder (nt:folder) /apps/eaem-touchui-cfm-font-size-plugin

2) Create a Font selector cq:Page /apps/eaem-touchui-cfm-font-size-plugin/font-selector with the following code

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0"
xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="cq:Page">
<jcr:content
jcr:mixinTypes="[sling:VanityPath]"
jcr:primaryType="nt:unstructured"
jcr:title="EAEM Font Selector"
sling:resourceType="granite/ui/components/coral/foundation/page">
<head jcr:primaryType="nt:unstructured">
<favicon
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/page/favicon"/>
<viewport
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/admin/page/viewport"/>
<clientlibs
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/includeclientlibs"
categories="[coralui3,granite.ui.coral.foundation,granite.ui.shell,dam.gui.admin.coral, eaem-cfm.rte.plugin]"/>
</head>
<body
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/page/body">
<items jcr:primaryType="nt:unstructured">
<form
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form"
class="foundation-form content-container"
maximized="{Boolean}true"
style="vertical">
<items jcr:primaryType="nt:unstructured">
<wizard
jcr:primaryType="nt:unstructured"
jcr:title="Select Text Font Color..."
sling:resourceType="granite/ui/components/coral/foundation/wizard">
<items jcr:primaryType="nt:unstructured">
<text
jcr:primaryType="nt:unstructured"
jcr:title="Select Text Font Color..."
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<fixedColumns
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
margin="{Boolean}true">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<fontSize
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/select"
fieldDescription="Select text size"
fieldLabel="Size"
name="./size">
<items jcr:primaryType="nt:unstructured">
<def
jcr:primaryType="nt:unstructured"
text="Select Size"
value=""/>
<small
jcr:primaryType="nt:unstructured"
text="Small (15px)"
value="15px"/>
<medium
jcr:primaryType="nt:unstructured"
text="Medium (30px)"
value="30px"/>
<large
jcr:primaryType="nt:unstructured"
text="Large (40px)"
value="40px"/>
</items>
</fontSize>
<color
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/colorfield"
fieldDescription="Select text color"
fieldLabel="Text Color"
name="./color"
showProperties="{Boolean}true"/>
<bgColor
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/colorfield"
fieldDescription="Select background color"
fieldLabel="Background Color"
name="./bgColor"
showProperties="{Boolean}true"/>
</items>
</column>
</items>
</fixedColumns>
</items>
<parentConfig jcr:primaryType="nt:unstructured">
<prev
granite:class="foundation-wizard-control"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/anchorbutton"
text="Cancel">
<granite:data
jcr:primaryType="nt:unstructured"
foundation-wizard-control-action="cancel"/>
</prev>
<next
granite:class="foundation-wizard-control"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/button"
disabled="{Boolean}true"
text="Apply"
type="submit"
variant="primary">
<granite:data
jcr:primaryType="nt:unstructured"
foundation-wizard-control-action="next"/>
</next>
</parentConfig>
</text>
</items>
</wizard>
</items>
</form>
</items>
</body>
</jcr:content>
</jcr:root>

3) Create clientlib (type cq:ClientLibraryFolder) /apps/eaem-touchui-cfm-font-size-plugin/clientlib and set property categories of String[] type to [dam.cfm.authoring.contenteditor.v2, eaem-cfm.rte.plugin] and dependencies String[] to [lodash]

4) Create file ( type nt:file ) /apps/eaem-touchui-cfm-font-size-plugin/clientlib/css.txt, add the following

  cfm-rte-font-size-plugin.css

5) Create file (type nt:file) /apps/eaem-touchui-cfm-font-size-plugin/clientlib/cfm-rte-font-size-plugin.css, add the following code

.eaem-cfm-font-size {
width: 50%;
margin-left: -50%;
height: 53%;
margin-top: -50%;
box-sizing: content-box;
z-index: 10100;
}

.eaem-cfm-font-size > iframe {
width: 100%;
height: 100%;
border: 1px solid #888;
}

6) Create file ( type nt:file ) /apps/eaem-touchui-cfm-font-size-plugin/clientlib/js.txt, add the following

  cfm-rte-font-size-plugin.js

7) Create file (type nt:file) /apps/eaem-touchui-cfm-font-size-plugin/clientlib/cfm-rte-font-size-plugin.js, add the following code

(function ($, $document) {
var EAEM_PLUGIN_ID = "eaemfont",
EAEM_TEXT_FONT_FEATURE = "eaemTextFont",
EAEM_TEXT_FONT_ICON = EAEM_PLUGIN_ID + "#" + EAEM_TEXT_FONT_FEATURE,
CANCEL_CSS = "[data-foundation-wizard-control-action='cancel']",
FONT_SELECTOR_URL = "/apps/eaem-touchui-cfm-font-size-plugin/font-selector.html",
SENDER = "experience-aem", REQUESTER = "requester", $eaemFontPicker,
url = document.location.pathname;

if( url.indexOf("/editor.html") == 0 ){
extendStyledTextEditor();
registerPlugin();
}else if(url.indexOf(FONT_SELECTOR_URL) == 0){
handlePicker();
}

function handlePicker(){
$document.on("foundation-contentloaded", fillDefaultValues);

$document.on("click", CANCEL_CSS, sendCancelMessage);

$document.submit(sentTextAttributes);
}

function setWidgetValue(form, selector, value){
Coral.commons.ready(form.querySelector(selector), function (field) {
field.value = _.isEmpty(value) ? "" : decodeURIComponent(value);
});
}

function rgbToHex(color){
if(_.isEmpty(color)){
return color;
}

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

return color;
}

function fillDefaultValues(){
var queryParams = queryParameters(),
form = $("form")[0];

setWidgetValue(form, "[name='./color']", queryParams.color);

setWidgetValue(form, "[name='./size']", queryParams.size);

setWidgetValue(form, "[name='./bgColor']", queryParams.bgColor);
}

function sentTextAttributes(){
var message = {
sender: SENDER,
action: "submit",
data: {}
}, $form = $("form"), $field;

_.each($form.find("[name^='./']"), function(field){
$field = $(field);
message.data[$field.attr("name").substr(2)] = $field.val();
});

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

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 sendCancelMessage(){
var message = {
sender: SENDER,
action: "cancel"
};

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

function getParent() {
if (window.opener) {
return window.opener;
}

return parent;
}

function closePicker(event){
event = event.originalEvent || {};

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

var message, action;

try{
message = JSON.parse(event.data);
}catch(err){
return;
}

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

action = message.action;

if(action === "submit"){
$eaemFontPicker.eaemFontPlugin.editorKernel.execCmd(EAEM_TEXT_FONT_FEATURE, message.data);
}

var modal = $eaemFontPicker.data('modal');
modal.hide();
modal.$element.remove();
}

function extendStyledTextEditor(){
var origFn = Dam.CFM.StyledTextEditor.prototype._start;

Dam.CFM.StyledTextEditor.prototype._start = function(){
addTextFontPluginSettings(this);
origFn.call(this);
}
}

function addTextFontPluginSettings(editor){
var config = editor.$editable.data("config");

config.rtePlugins[EAEM_PLUGIN_ID] = {
features: "*"
};

config.uiSettings.cui.multieditorFullscreen.toolbar.push(EAEM_TEXT_FONT_ICON);
}

function registerPlugin(){
var EAEM_CFM_TEXT_FONT_PLUGIN = new Class({
toString: "eaemCFMTextFontPlugin",

extend: CUI.rte.plugins.Plugin,

textFontUI: null,

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

notifyPluginConfig: function (pluginConfig) {
var defaults = {
tooltips: {}
};

defaults.tooltips[EAEM_TEXT_FONT_FEATURE] = {
title: "Set text font size, color, background color..."
};

CUI.rte.Utils.applyDefaults(pluginConfig, defaults);

this.config = pluginConfig;
},

initializeUI: function (tbGenerator) {
if (!this.isFeatureEnabled(EAEM_TEXT_FONT_FEATURE)) {
return;
}

this.textFontUI = new tbGenerator.createElement(EAEM_TEXT_FONT_FEATURE, this, false,
this.config.tooltips[EAEM_TEXT_FONT_FEATURE]);

tbGenerator.addElement(EAEM_TEXT_FONT_FEATURE, 999, this.textFontUI, 999);

if (tbGenerator.registerIcon) {
tbGenerator.registerIcon(EAEM_TEXT_FONT_ICON, "textColor");
}

$(window).off('message', closePicker).on('message', closePicker);
},

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

execute: function (pluginCommand, value, envOptions) {
var context = envOptions.editContext;

if (pluginCommand != EAEM_TEXT_FONT_FEATURE) {
return;
}

if(!this.isValidSelection()){
return;
}

var 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")),
color, size = $tag.css("font-size");

color = this.getColorAttributes($tag);

this.showFontModal(this.getPickerIFrameUrl(size, color.color, color.bgColor));
},

getColorAttributes: function($tag){
var key, color = { color: "", bgColor : ""};

if(!$tag.attr("style")){
return color;
}

//donot use .css("color"), it returns default font color, if color is not set
var parts = $tag.attr("style").split(";");

_.each(parts, function(value){
value = value.split(":");

key = value[0] ? value[0].trim() : "";
value = value[1] ? value[1].trim() : "";

if(key == "color"){
color.color = rgbToHex(value);
}else if(key == "background-color"){
color.bgColor = rgbToHex(value);
}
});

return color;
},

showFontModal: function(url){
var self = this, $iframe = $('<iframe>'),
$modal = $('<div>').addClass('eaem-cfm-font-size coral-Modal');

$iframe.attr('src', url).appendTo($modal);

$modal.appendTo('body').modal({
type: 'default',
buttons: [],
visible: true
});

$eaemFontPicker = $modal;

$eaemFontPicker.eaemFontPlugin = self;

$modal.nextAll(".coral-Modal-backdrop").addClass("cfm-coral2-backdrop");
},

getPickerIFrameUrl: function(size, color, bgColor){
var url = Granite.HTTP.externalize(FONT_SELECTOR_URL) + "?" + REQUESTER + "=" + SENDER;

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

if(!_.isEmpty(bgColor)){
url = url + "&bgColor=" + encodeURIComponent(bgColor);
}

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

return url;
}
});

var EAEM_CFM_TEXT_FONT_CMD = new Class({
toString: "eaemCFMTextFontCmd",

extend: CUI.rte.commands.Command,

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

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

getTagObject: function(textData) {
var style = "";

if(!_.isEmpty(textData.color)){
style = "color: " + textData.color + ";";
}

if(!_.isEmpty(textData.size)){
style = style + "font-size: " + textData.size + ";";
}

if(!_.isEmpty(textData.bgColor)){
style = style + "background-color: " + textData.bgColor;
}

return {
"tag": "span",
"attributes": {
"style" : style
}
};
},

execute: function (execDef) {
var textData = execDef.value, selection = execDef.selection,
nodeList = execDef.nodeList;

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

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

if(_.isEmpty(textData.size) && _.isEmpty(textData.color) && _.isEmpty(textData.bgColor)){
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, tags.attributes ? tags.attributes : undefined, true);
}

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

queryState: function(selectionDef, cmd) {
return false;
}
});

CUI.rte.plugins.PluginRegistry.register(EAEM_PLUGIN_ID, EAEM_CFM_TEXT_FONT_PLUGIN);

CUI.rte.commands.CommandRegistry.register(EAEM_TEXT_FONT_FEATURE, EAEM_CFM_TEXT_FONT_CMD);
}
}(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>