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

AEM 6540 - Core Components 280 - Touch UI RTE (Rich Text Editor) Dialog Emojis Plugin

$
0
0

Touch UI Emoji Picker Plugin for RTE (Rich Text Editor) Dialog - /libs/cq/gui/components/authoring/dialog/richtext

In Core Components 2.8.0uiSettings/cui/dialogFullScreen was removed and the plugin settings were moved to Template (Component) Policies, this post is for core components >= 2.8.0 

Uses Open Emoji API https://emoji-api.com/

For demo purposes, design dialog of core text component v2 was modified to add the emoji picker configuration - /apps/core/wcm/components/text/v2/text/cq:design_dialog/content/items/tabs/items/plugins/items/experience-aem-fonts



Emoji Plugin



Plugin Configuration in Design





Enable Plugin in Component Policy



Let's Do It

1) Login to CRXDE Lite, add nt:folder /apps/eaem-emojis-rte-plugin

2) To show the Emoji Picker in a dialog create cq:Page /apps/eaem-emojis-rte-plugin/emoji-selector and add  eaem.rte.emojis.plugincategories in /apps/eaem-emojis-rte-plugin/emoji-selector/jcr:content/head/clientlibs

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/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 Emoji 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.rte.emojis.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">
<emoji
jcr:primaryType="nt:unstructured"
jcr:title="Click on the Emoji select.."
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">
<emojiPicker
jcr:primaryType="nt:unstructured"
sling:resourceType="/apps/eaem-emojis-rte-plugin/emoji-widget"
fieldDescription="Select Emoji..."
fieldLabel="Select Emoji..."
name="./eaemEmoji"/>
</items>
</column>
</items>
</fixedColumns>
</items>
</emoji>
</items>
</form>
</items>
</body>
</jcr:content>
</jcr:root>

3) Create widget /apps/eaem-emojis-rte-plugin/emoji-widget/emoji-widget.jsp to add a div container, search code for the emojis...

<%@ include file="/libs/granite/ui/global.jsp" %>

<ui:includeClientLib categories="lodash" />

<%
String defaultKeyword = "face";
%>

<div class="coral-Form-fieldwrapper">
<label class="coral-Form-fieldlabel">Search</label>
<input is="coral-textfield" class="coral-Form-field" placeholder="<%= defaultKeyword %>"
id="eaem-emoji-input"
value="<%= defaultKeyword %>">
</div>

<div class="coral-Form-fieldwrapper" id="eaem-emojis">
</div>

<script>
(function($){
var URL = "https://emoji-api.com/emojis?access_key=bcbd6980f7392ceda8914932404927e9b198486e&search=";

function showEmojis(keyword) {
$.ajax(URL + keyword).done(handler);

function handler(data) {
var $emojis = $("#eaem-emojis"), html = "";

_.each(data, function (emoji) {
html = html + getEmojiHtml(emoji["character"]);
});

$emojis.html(html);
}

function getEmojiHtml(character) {
return "<span style='cursor:pointer'>" + character + "</span>";
}
}

function addListener(){
$("form").on("submit", function(){
showEmojis($("#eaem-emoji-input").val());
return false;
});
}

showEmojis("<%=defaultKeyword%>");

addListener();
}(jQuery));
</script>

4) Create clientlib (cq:ClientLibraryFolder) /apps/eaem-emojis-rte-plugin/clientlib set property categories to [cq.authoring.dialog.all, eaem.rte.emojis.plugin] and dependencies to [lodash]

5) Create file (nt:file) /apps/eaem-emojis-rte-plugin/clientlib/js.txt, add the following content

                                    eaem-emojis.js

6) Create file (nt:file) /apps/eaem-emojis-rte-plugin/clientlib/eaem-emojis.js, add the following code

(function($, CUI, $document){
var GROUP = "experience-aem-emojis",
INSERT_EMOJI_FEATURE = "insertEmoji",
EAEM_INSERT_EMOJI_DIALOG = "eaemTouchUIInsertEmojiDialog",
SENDER = "experience-aem", REQUESTER = "requester",
FONT_SELECTOR_URL = "/apps/eaem-emojis-rte-plugin/emoji-selector.html",
url = document.location.pathname;

if( url.indexOf(FONT_SELECTOR_URL) == 0 ){
handlePicker();
return;
}

function handlePicker(){
$document.on("click", "#eaem-emojis span", addEmojiSelectListener);
}

function addEmojiSelectListener(){
var message = {
sender: SENDER,
action: "submit",
data: {
emoji: $(this).html()
}
};

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

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

return parent;
}

addPlugin();

addPluginToDefaultUISettings();

addDialogTemplate();

function addDialogTemplate(){
var url = Granite.HTTP.externalize(FONT_SELECTOR_URL) + "?" + REQUESTER + "=" + SENDER;

var html = "<iframe width='700px' height='300px' 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-' + EAEM_INSERT_EMOJI_DIALOG] = CUI.rte.Templates['dlg-' + EAEM_INSERT_EMOJI_DIALOG] = Handlebars.compile(html);
}

function addPluginToDefaultUISettings(){
var groupFeature = GROUP + "#" + INSERT_EMOJI_FEATURE,
toolbar = CUI.rte.ui.cui.DEFAULT_UI_SETTINGS.dialogFullScreen.toolbar;

if(toolbar.includes(groupFeature)){
return;
}

toolbar.splice(3, 0, groupFeature);
}

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

toString: "EAEMInsertEmojiDialog",

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

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

function addPlugin(){
var EAEMTouchUIInsertEmojiPlugin = new Class({
toString: "EAEMTouchUIInsertEmojiPlugin",

extend: CUI.rte.plugins.Plugin,

pickerUI: null,

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

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

addPluginToDefaultUISettings();

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

this.pickerUI = tbGenerator.createElement(INSERT_EMOJI_FEATURE, this, false, { title: "Select Emoji..." });
tbGenerator.addElement(GROUP, plg.Plugin.SORT_FORMAT, this.pickerUI, 10);

var groupFeature = GROUP + "#" + INSERT_EMOJI_FEATURE;
tbGenerator.registerIcon(groupFeature, "heart");
},

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

if (pluginCommand != INSERT_EMOJI_FEATURE) {
return;
}

var dialog,dm = ek.getDialogManager(),
$container = CUI.rte.UIUtils.getUIContainer($(context.root)),
propConfig = {
'parameters': {
'command': this.pluginId + '#' + INSERT_EMOJI_FEATURE
}
};

if(this.eaemInsertEmojiDialog){
dialog = this.eaemInsertEmojiDialog;

dialog.$dialog.find("iframe").attr("src", this.getPickerIFrameUrl());
}else{
dialog = new EAEMInsertEmojiDialog();

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

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

this.eaemInsertEmojiDialog = dialog;

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

dm.show(dialog);

function receiveMessage(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"){
ek.relayCmd(pluginCommand, message.data);
}

dialog.hide();
}
},

getPickerIFrameUrl: function(){
return Granite.HTTP.externalize(FONT_SELECTOR_URL) + "?" + REQUESTER + "=" + SENDER;
},

updateState: function(selDef) {
var hasUC = this.editorKernel.queryState(INSERT_EMOJI_FEATURE, selDef);

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

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

extend: CUI.rte.commands.Command,

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

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

execute: function (execDef) {
var emoji = execDef.value.emoji, context = execDef.editContext,
emojiSpan = context.doc.createElement("span");

emojiSpan.innerHTML = emoji;

var range = CUI.rte.Common.ua.isIE ? CUI.rte.Selection.saveNativeSelection(context)
: CUI.rte.Selection.getLeadRange(context);

range.insertNode(emojiSpan);
},

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

CUI.rte.commands.CommandRegistry.register(INSERT_EMOJI_FEATURE, EAEMTouchUIEmojiCmd);

CUI.rte.plugins.PluginRegistry.register(GROUP,EAEMTouchUIInsertEmojiPlugin);
}
}(jQuery, window.CUI,jQuery(document)));



Viewing all articles
Browse latest Browse all 526


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